pax_global_header00006660000000000000000000000064140465371050014517gustar00rootroot0000000000000052 comment=50d821efe99cae82c05be0a4ab3b4035ef0d3883 distcc-3.4/000077500000000000000000000000001404653710500126365ustar00rootroot00000000000000distcc-3.4/.gitignore000066400000000000000000000005311404653710500146250ustar00rootroot00000000000000*.o *.d *.out *.err # binaries /*.exe distcc distccd distccmon-text lsdistcc pump update-distcc-symlinks # files generated by build tools Makefile _include_server/ aclocal.m4 autom4te.cache/ config.log config.status configure lzo/.stamp-conf popt/.stamp-conf src/config.h src/config.h.in src/config.h.stamp man/*.gz _testtmp/ __pycache__/ /h_* distcc-3.4/.travis.yml000066400000000000000000000012241404653710500147460ustar00rootroot00000000000000notifications: email: recipients: - shawn@git.icu on_success: change # default: change on_failure: always # default: always language: c cache: ccache addons: apt: packages: - python3-dev - libiberty-dev - clang - libavahi-client-dev script: - ./autogen.sh - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./configure; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./configure --without-libiberty; fi - make - make check matrix: include: - os: linux compiler: gcc dist: trusty - os: linux compiler: clang dist: trusty - os: osx osx_image: xcode11.3 compiler: clang distcc-3.4/AUTHORS000066400000000000000000000004061404653710500137060ustar00rootroot00000000000000Author and maintainer emeritus of distcc: Martin Pool Authors of "pump" functionality, and maintainers of distcc: Nils Klarlund Fergus Henderson Craig Silverstein Manos Renieris See NEWS for credits of other contributors. distcc-3.4/COPYING000066400000000000000000000431101404653710500136700ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. distcc-3.4/ChangeLog000066400000000000000000030435351404653710500144250ustar00rootroot000000000000002011-10-26 02:49 Fergus Henderson * Makefile.in: After my change to gzip the man pages before installing them, I had to make a couple more changes to get "make distcheck" to pass. Reviewed by Craig Silverstein. 2011-10-25 01:49 Fergus Henderson * Makefile.in, man: Gzip the man pages before installing them. This is required by the Debian policy manual and is also assumed by our packaging/RedHat/rpm.spec file which we use for building both RPM and Debian packages. Also some whitespaces changes; only the first of the four segments in this patch has non-whitespace changes. 2011-10-25 00:42 Fergus Henderson * ChangeLog, NEWS, configure.ac: Update the NEWS and ChangeLog files, and set the version number to 3.2rc1, in preparation for releasing distcc version 3.2. Reviewed by Craig Silverstein. 2011-10-24 23:26 Fergus Henderson * doc/web/man/distcc_1.html, doc/web/man/distccd_1.html, doc/web/man/distccmon_text_1.html, doc/web/man/include_server_1.html, doc/web/man/pump_1.html, man/distcc.1, man/include_server.1: Regenerate the checked-in HTML for the man pages. The HTML files were generated automatically using sudo apt-get install troffcvt make man-html But I have also changed the man source files to ensure that the generated output still looks nice. The changes were mainly replacing blank lines with ".PP", but there were a few other tweaks needed too. Tested by viewing the output on both Chrome and Safari, and using "man" and (equivalently) "nroff -man" and examining the changes. Reviewed by Craig Silverstein. 2011-10-24 00:57 Fergus Henderson * man/distccd.1: Apply a suggestion from Craig Silverstein: update the documentation for the --whitelist option to make it clear that distcc will accept connections *only* from users on the list. 2011-10-21 01:26 Fergus Henderson * popt/popthelp.c, src/dotd.c: Fix a couple of compiler warnings. Reviewed by Craig Silverstein. 2011-06-28 20:13 Fergus Henderson * test/testdistcc.py: Apply patch from Ihor Kaharlichenko to fix issue 81 : SyntaxError_Case was failing with recent versions of gcc, due to the error message format having changed to now include the column number. Also remove an old "XXX" comment that no longer applies. 2011-04-06 14:49 Fergus Henderson * test/testdistcc.py: Fix a syntax error in my last change. 2011-04-06 14:36 Fergus Henderson * Makefile.in: Update Makefile.in for compatibility with autoconf >= 2.60. This avoids the following warning config.status: WARNING: 'Makefile.in' seems to ignore the --datarootdir setting and ensures that our configure script supports that --datarootdir flag. Reviewed by Craig Silverstein. 2011-04-06 14:35 Fergus Henderson * src/clinet.c, src/dotd.c, src/emaillog.c, src/hosts.c, src/mon.c, src/netutil.c, src/serve.c, src/snprintf.c, src/snprintf.h, src/srvnet.c, src/srvrpc.c, src/stats.c, src/trace.c, src/util.c: Fix warnings about unused return values. This includes some code changes to do a better job of error checking. 2011-04-06 14:11 Fergus Henderson * test/testdistcc.py: Fix some issues that caused the gdb-related tests to fail: 1. Recent gcc versions want us to use -Wl,--build-id rather than --build-id. 2. We had missed one of the places where we need to be passing that flag in. 3. With recent gcc/gdb versions, "break main; run" will sometimes stop at the first statement inside of main rather than on the function declaration. So "break main; run; step" may end up inside the code to puts() rather than in the code for main(). My fix was to use "break main; run; next" instead. It is inderminate (varies based on whether you use "-O", for example) whether we end up at the call to puts() or after the call to puts(), but either way the call to puts() should be in the gdb output log. Reviewed by Craig Silverstein. 2011-04-06 14:09 Fergus Henderson * configure.ac: Support Python 2.6. Reviewed by Craig Silverstein. 2011-04-05 18:57 Fergus Henderson * src/hosts.c: Fix indentation (layout changes only, no code changes). 2010-11-16 19:05 Fergus Henderson * test/testdistcc.py: Fix for "Gdb tests fail in pumped mode on Ubuntu 9.10 amd64": pass --build-id to gcc versions that support it. (See for a description of the --build-id switch.) Reviewed by Craig Silverstein. 2010-11-16 18:51 Fergus Henderson * man/include_server.1: Fix error in manual: to disable fallback, set DISTCC_FALLBACK to 0 not 1. Resolves . 2010-10-08 19:33 Fergus Henderson * src/access.c: Apply patch from Ian Kumlien , to fix . This patch fixes a compile error on Gentoo Linux due to "s6_addr" being #defined by a system header file and thus not available for use as a local variable name. 2010-10-08 18:29 Fergus Henderson * src/clirpc.c, src/compile.c, src/remote.c, src/state.c, src/state.h, src/where.c: Apply patch from Jeremy Murphy , tested and reviewed by cheepero@gmail.com, to address "distcc-mon-gnome displays multiple rows for same host/slot". 2010-09-10 22:09 Fergus Henderson * test/testdistcc.py: Fix failures of the Gdb_* test cases: 1. These tests were failing if you have anything in your ~/.gdbinit file that causes gdb to issue an error message. The fix here is to create an empty .gdbinit in the test directory; gdb will read that one in preference to the one in $HOME. 2. These tests were failing due to a new spurious warning from gdb. 3. There were a bug in the code for the Gdb_Case test which previously caused part of the test to be executed only in pump mode. When invoking gcc to check whether preprocessing preserves the pwd info, the command line had not been updated to reflect the fact that this command is run in a subdirectory; as a consequence, gcc_preprocessing_preserves_pwd was always set to false. Reviewed by Craig Silverstein. 2010-08-19 22:51 Fergus Henderson * src/access.c: Some minor stylistic improvements: use array indexing rather than pointer arithmetic; simplify for loops; change a parameter name to match comment describing it; eliminate trailing whitespace. Reviewed by Bob Ham 2010-08-19 20:07 Fergus Henderson * src/daemon.c, src/daemon.h, src/serve.c: Change directory back to the original server working directory after each distcc-pump compilation. This fixes a bug where distcc-pump was changing to a directory and then deleting that directory and not changing back to the original directory. That caused problems when you used a server first in distcc-pump mode and then in distcc mode, and the compiler invoked a shell script. The compilation would succeed, but the shell would report a confusing warning ("shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory"). 2010-08-19 19:23 Fergus Henderson * include_server/compiler_defaults.py, include_server/parse_command.py, include_server/parse_command_test.py: Apply --sysroot patch from Simon Baldwin : 2010-08-18 Simon Baldwin * include_server/compiler_defaults.py (_SystemSearchdirsGCC): Add a 'sysroot' parameter. Add --sysroot, if needed, to the gcc invocation that identifies search directories and default paths. Add debugging output. (SetSystemDirsDefaults): Add 'sysroot' parameter. Add another dictionary level to system_dirs_default for sysroot values. Add debugging output. * include_server/parse_command.py (ParseCommandArgs): Identify and handle arguments of the form '--opt=value'. Pass any --sysroot value to compiler_defaults.SetSystemDirsDefaults, use it in compiler_defaults.system_dirs_default lookups. (CPP_OPTIONS_APPEARING_AS_ASSIGNMENTS): New. * include_server/parse_command_test.py (Mock_SetSystemDirsDefaults): Add sysroot parameter, verify it on function calls. (ParseCommandUnitTest): Add --sysroot to mock gcc invocations. 2010-06-29 15:51 Fergus Henderson * src/fix_debug_info.c: Trivial fix for slight mistake in distccd debug message. Reviewed by Craig Silverstein. 2010-05-04 20:09 Fergus Henderson * src/serve.c, src/stats.c, src/stats.h, src/util.c, src/util.h: Apply patch from Ryan Burns : add 1, 3, 5 minute averages of the number of children used on a server to the statistics collected by the stats server. 2010-05-04 19:52 Fergus Henderson * man/distcc.1, src/compile.c: Apply patch from Ryan Burns : add an environment variable DISTCC_SKIP_LOCAL_RETRY for skipping the local retry in case of a remote compilation failure. 2010-03-02 08:24 Fergus Henderson * test/testdistcc.py: Apply slightly cleaned up version of patch from perezdiez@gmail.com to fix failure of PreprocessAsm_Case on ARM. 2010-03-02 08:13 Fergus Henderson * src/emaillog.c: Apply patch from Akim Demaille : * src/emaillog.c (dcc_maybe_send_email): Pacify GCC's warnings about format strings by getting rid of a useless temporary string. 2010-03-02 08:10 Fergus Henderson * ChangeLog, src/hosts.c: Apply patch from Akim Demaille : * src/hosts.c (strndup): Use the standard signature (without static), so that we don't conflict with GCC's builtin signature. Now that it is not static, declare it, to avoid warnings. 2010-02-18 23:40 Fergus Henderson * test/testdistcc.py: Apply patch from madkinder: use #include rather than #import in C++ test case. This fixes a test case failure with gcc 4.4.1, which warns about use of #import. (The use of #import was an accidental cut-and-paste error resulting from copying the C++ test case from the Objective-C/C++ test case.) 2010-02-18 23:33 Fergus Henderson * test/testdistcc.py: Change the PreprocessAsm_Case so that it reports NOTRUN rather than PASS for systems where it is not run. 2010-02-10 03:31 Lei Zhang * man/distcc.1, src/daemon.c, src/distcc.h, src/io.c, src/pump.c, src/sendfile.c: Add support for $DISTCC_IO_TIMEOUT. Reviewed by Fergus Henderson. 2009-12-30 04:25 Fergus Henderson * packaging/RedHat/init.d/distcc: Apply patch from Tal : In packaging/RedHat/init.d/distcc the executable is once refereed to using the variable EXEC, and once as with the explicit expected name. Change it to always use the EXEC variable. 2009-12-01 04:46 Fergus Henderson * Makefile.in: Apply patch from : This is a simple patch that adds the standard TAGS target for Emacs users. 2009-08-03 23:33 Lei Zhang * man/distcc.1, man/pump.1, pump.in, src/compile.c: Make max_discrepancies_before_demotion configurable via DISTCC_MAX_DISCREPANCY environment variable. 2009-07-24 17:30 Fergus Henderson * test/testdistcc.py: Pass "-c" to gcc for the Dotd_Case tests. This fixes a problem where this test was failing on some systems due to link errors when compiling C++ source files with "gcc foo.cpp". To link C++ code, you now need to use "g++ foo.cpp" or "gcc foo.cpp -lstdc++", even if the C++ code in question doesn't use any C++ library features. Rather than changing the code to use "g++" or "-lstdc++", I though it was better to avoid the link step entirely, since it is not needed for the things this test is testing, and removing it will speed up the test. Reviewed by Craig Silverstein. 2009-07-24 16:59 Fergus Henderson * man/distccd.1, src/auth.h, src/auth_common.c, src/auth_distcc.c, src/auth_distccd.c, src/daemon.c, src/dopt.c, src/dopt.h, src/dparent.c, src/dsignal.c: Apply patch from Ian.Baker@cern.ch: Optional Black/Whitelist Functionality. This patch is used to implement optional server-side access control through a specified black or whitelist file. This option is specified through a command line option. Revised by me (Fergus Henderson): fixed spelling error, added a comment. 2009-07-24 16:31 Fergus Henderson * Makefile.in, configure.ac, src/h_getline.c[ADD], src/util.c, src/util.h, test/testdistcc.py: Define a GNU-compatible getline() implementation, in case we don't have getline() available. Reviewed by Craig Silverstein. 2009-07-24 01:32 Fergus Henderson * src/h_parsemask.c: Fix compile errors for "make check" caused by distcc-v6-acl-2.patch. 2009-07-23 02:16 Fergus Henderson * Makefile.in, configure.ac, man/distcc.1, man/distccd.1, src/auth.h[ADD], src/auth_common.c[ADD], src/auth_distcc.c[ADD], src/auth_distccd.c[ADD], src/clirpc.c, src/daemon.c, src/distcc.c, src/dopt.c, src/dopt.h, src/dparent.c, src/dsignal.c, src/exitcode.h, src/help.c, src/hosts.c, src/hosts.h, src/lock.c, src/remote.c, src/serve.c: Apply patch from Ian.Baker@cern.ch: Optional GSS-API Functionality. This patch implements mutual authentication, out of sequence and replay detection using the GSS-API. The changes implemented are optional and are turned off by default. This option is specified to the client through an environment variable as is the name of the server principal to authenticate. Currently the server principal can be left unspecified and a default based on the host keytab will be used. This option is specified to the daemon through a command line option, with the name of the principal whose credentials the daemon should use specified as an environment variable. A simple handshake is exchanged between the client and server in order to prevent unecessary delays and protocol derailments when mixing authenticating and non-authenticating clients and servers. Revised based on review comments. GSS-API authentication is now implemented as a per host option. Revised further by me (Fergus Henderson) to fix a spelling error and to rename the per host option from ",gssapi" to ",auth". 2009-07-23 02:15 Fergus Henderson * doc/protocol-gssapi.txt[ADD]: Apply patch from Ian.Baker@cern.ch: Protocol Documentation for GSSAPI extension. 2009-07-22 21:39 Fergus Henderson * Makefile.in: Add Makefile target "man-html" for rebuilding the (checked-in) HTML versions of the man pages. This allows you to view the changes with "svn diff" before running "make upload-man" which commits them. Reviewed by Craig Silverstein. 2009-07-22 17:29 Fergus Henderson * src/access.c, src/access.h, src/srvnet.c, src/zeroconf-reg.c: Apply distcc-v6-acl-2.patch from Bob Ham : - Implements IPv6 support for access control. - Restrict zeroconf advertisements to IPv4 if RFC2553 support isn't enabled. - Modifies the non-RFC2553 code to use inet_aton() instead of the RFC2553-specific inet_pton(). 2009-07-22 17:22 Fergus Henderson * man/include_server.1: Improve some slightly misleading documentation. 2009-06-30 21:37 Fergus Henderson * gnome/distccmon-gnome.desktop: Swedish translation, from Nille . 2009-04-18 00:03 Fergus Henderson * Makefile.in: Apply patch from Assar : If any of the files in the source directory are not writable, running "make dist" will prompt you if you want to remove those files in the temporary distribution directory (distcc-3.1). The following tiny patch fixes that. 2009-04-14 03:10 benizi * src/zeroconf.c: Remove duplicate hosts from the zeroconf list. Fixes issue 43 . As mentioned in issue 34 , hosts with both IPv4 and IPv6 addresses showed up twice if avahi is IPv6-enabled. So, filter out duplicates using the service name. 2009-04-10 20:26 Fergus Henderson * src/exec.c: (1) Layout/whitespace changes; the layout of this file seems to have gotten mixed up when we changed from using tabs to using spaces. (2) Fix spacing in a log message. Reviewers: Craig Silverstein 2009-04-10 19:26 Fergus Henderson * test/testdistcc.py: Fix a distcc test that was failing on modern kernels: ignore a spurious warning from gdb. According to Paul Pluzhnikov, the warning is gone from current GDB, fixed by the following patch: 2008-04-21 Pedro Alves * symfile.c (syms_from_objfile): Don't warn if lowest loadable section is not a code section. But since there are going to be some versions of gdb in the wild that don't have that patch, we still need to work around it in the distcc tests. Reviewed by Craig Silverstein. 2009-04-10 17:37 Fergus Henderson * test/testdistcc.py: A fix for distcc issue 44 "Failed tests on make check (gentoo gcc-4.3.3)" . We were using an invalid signature for main(), and newer versions of gcc are stricter about checking this. Reviewed by Craig Silverstein. 2009-03-06 13:55 IanRichardBaker * src/include_server_if.c: Fixed a portability issue that causes compilation to fail on 64 bit boxes. 2009-02-17 23:10 Fergus Henderson * src/dotd.c, src/emaillog.c, src/include_server_if.c, src/lsdistcc.c, src/rslave.c, src/stringmap.c, src/timeval.c: Ensure that all ".c" files start with "#include ". This will hopefully fix issue 39 . Some header files were using #if statements that depended on macros defined in config.h without #including config.h first. The result was a compilation error, because "#if !HAVE_DECL_SNPRINTF" was evaluating to true because config.h hadn't been included, causing us to declare snprintf() when we shouldn't, leading to a conflict with the declaration in the standard header files. (The alternative solution would have been to add "#include " to every header file that uses '#if'. I decided not to do that, just for consistency with the existing code.) 2009-02-17 23:10 Fergus Henderson * packaging/rpm.sh: Fix a non-portability in rpm.sh: use "trap ... HUP" rather than "trap ... SIGHUP". The Posix.1 standard says: The condition can be EXIT, 0 (equivalent to EXIT), or a signal specified using a symbolic name, without the SIG prefix, as listed in the tables of signal names in the header [...]; for example, HUP, INT, QUIT, TERM. Implementations may permit names with the SIG prefix or ignore case in signal names as an extension. Previously, the code was relying on this optional extension. 2009-01-30 17:27 Fergus Henderson * include_server/macro_eval.py, include_server/parse_file.py, test/testdistcc.py: Fix issue 35 . This was a bug where the include server was crashing in certain cases (when the argument to a macro ended in a backslash) due to an escaping problem in the use of Python's re.sub() function. The fix was to replace all occurrences of backslash in the replacement string with double-backslash, which re.sub() will then translate back to a single backslash. (I also changed the code to not bother using re.compile() since we only use the regexp once.) Also, fix a bug where we were not allowing backslashes in filenames. I added regression tests for both of these bugs (and I verified that they were true regression tests). Reviewed by Craig Silverstein. 2009-01-26 23:50 Fergus Henderson * pump.in: Handle failure of "mktemp" more gracefully in the pump script. It was printing an error message, but then it would continue on even if mktemp had failed (it called "exit 1", but only in a subshell). It would then go on and try to start the include server, which would end up hanging. The fix is to make sure that we call "exit 1" from the main shell whenever MakeTmpFile fails. Reviewed by Craig Silverstein. 2009-01-22 05:33 adshea * man/distcc.1, src/hosts.c, src/zeroconf.c: IPv6 patch for Zeroconf and and IPv6 literals in hosts file. * Still needs configure flag masking for IPv6 literals * Needs some fix for zeroconf hosts that have both and IPv6 and IPv4 address 2009-01-20 22:22 Fergus Henderson * doc/web/index.html, doc/web/man/index.html[ADD]: - Add pointer to the INSTALL file to the main page. - Create an index.html in doc/web/man to make the presentation of that page prettier. Previously it was a rather ugly directory listing of file names like "distcc_1.html", "distccd_1.html", etc. - Add links to the INSTALL file and README* files from that doc/web/man/index.html page. Reviewed by Craig Silverstein. 2009-01-09 17:46 Fergus Henderson * doc/web/index.html: Fix broken link to distccWebView. 2009-01-09 08:54 akim.demaille * src/distcc.c: "distcc --scan-includes" dumps core. * src/distcc.c (main): Don't dump --help on the user on command line error, rather, return the `Try --help' message on stderr. Check that --scan-includes is given arguments. 2009-01-05 22:48 Fergus Henderson * src/distcc.c: Document the --scan-includes option in the output of "distcc --help". 2009-01-05 20:29 Fergus Henderson * Makefile.in, pump.in: Avoid using "echo -n", because it's not portable. 2009-01-05 20:18 Fergus Henderson * test/testdistcc.py: Portability fix: the CPlusPlus_SystemIncludeDirectories_Case was assuming that /usr/include/sys/types.h exists, but was not checking this assumption. 2008-12-22 22:21 Fergus Henderson * include_server/compiler_defaults.py: Fix a bug where the SystemIncludeDirectories_Case test was failing on systems where /tmp was a symlink. This failure indicated a real bug: on such systems, distcc was not correctly handling -I where is a subdirectory of a system include directory, e.g. -I/usr/include/foo. The code was calling _RealPrefix(client_root + system_dir) but was implicitly assuming that the answer would always start with client_root. That is, it was implicitly assuming that client_root did not contain any symlinks. I changed the code to use _RealPrefixWithinClientRoot(client_root, system_dir) so that it would find the appropriate prefix of system_dir rather than looking at the prefixes of client_root. 2008-12-22 21:56 Fergus Henderson * include_server/compiler_defaults.py: When computing the compiler's default search path by parsing the output from "gcc -v", ignore Apple-modified MacOS gcc's "framework" directories. 2008-12-10 20:22 Fergus Henderson * INSTALL: Clarify installation instructions; in particular, if you have python installed, you need to also have Python.h installed before building distcc. Reviewer: Craig Silverstein 2008-12-03 00:54 Fergus Henderson * include_server/setup.py: Avoid a spurious message 'setup.py: PYTHON_CFLAGS must be defined.' The top-level Makefile sets CFLAGS="$(CFLAGS) $(PYTHON_CFLAGS)" before invoking setup.py, so there's no need for it to set PYTHON_CFLAGS. 2008-12-02 21:49 Fergus Henderson * ChangeLog: Update ChangeLog with some more changes for distcc 3.1. 2008-12-02 21:44 Fergus Henderson * Makefile.in, NEWS, configure.ac, include_server/setup.py: 1. Fix some compilation errors arising from the use of -Wwrite-strings when compiling the python extension module, due to lack of const correctness in the Python 2.2 "Python.h" header file. This problem was introduced by the fix for distcc issue 26 . The solution was to explicitly disable these warnings with -Wno-write-strings. 2. Centralize the use of gcc-specific compilation options in conditional code in configure.ac that is only executed if we're using gcc. Previously include_server/setup.py was hard-coding gcc-specific options, regardless of whether we're using gcc. 3. Don't use -Wuninitialized if CFLAGS doesn't contain "-O*", because -Wuninitialized only works if optimization is enabled. This avoids a gcc warning (and hence an error with -Werror) about -Wuninitialized not having any effect when distcc is configured with "CFLAGS=-g ./configure". 4. Add a new configure option "--disable-Werror". For the 3.0 release of distcc, some people porting distcc resorted to patching distcc to remove the -Werror option. -Werror is useful, so I want to keep it enabled by default, but I'd prefer that people are able to port distcc easily, hence the configure option. This addresses distcc issue 20 . Reviewers: Craig Silverstein 2008-12-01 23:44 Fergus Henderson * ChangeLog, NEWS, configure.ac: Bump version number to 3.1, and update the NEWS file and ChangeLog. Reviewed by Craig Silverstein. 2008-10-27 22:11 Fergus Henderson * Makefile.in: Apply matsuu's patch to fix issue 26 "missing CFLAGS for include-server" . 2008-10-27 14:38 Fergus Henderson * include_server/c_extensions/distcc_pump_c_extensions_module.c: Applied matsuu's patch for issue 27 "failed to make distcc" , which was a build problem on "Gentoo, x86-64, gcc-4.1.2, glibc-2.6.1, python-2.5.2". 2008-10-27 14:17 Fergus Henderson * Makefile.in: Include the "m4" directory in the source distribution tarball, so that users of the source distribution can (re)run "autogen.sh". Reviewers: Craig Silverstein 2008-10-05 16:43 Fergus Henderson * src/arg.c: Fix a silly mistake (missing "== 0" after strcmp() call) that broke the parsing of "-Wp,-MMD,..." options. This fixes . 2008-09-27 01:57 Fergus Henderson * include_server/test_data/gws-main.o.cmd[DEL]: Delete an unused test data file; it became dead after my previous change which deleted the test that used it. 2008-09-27 01:55 Fergus Henderson * include_server/parse_command_test.py: Delete an unused test case: the test was hard-coded to always pass anyway, so it wasn't testing anything useful. 2008-09-13 17:23 Fergus Henderson * doc/web/man/distcc_1.html, man/distcc.1, src/exitcode.h: Incorporate 01_distcc_man.dpatch from debian distribution. This patch adds documentation of all of the exit codes to the man page. Also add comment to exitcode.h reminding maintainers to update the man page. Also update the HTML versions of the man pages. 2008-09-11 18:48 Fergus Henderson * NEWS, include_server/include_analyzer.py, man/distcc.1, src/clirpc.c, src/compile.c, src/compile.h, src/distcc.c, src/distcc.h, src/include_server_if.c, src/include_server_if.h, src/util.c, test/testdistcc.py: Provides a simple shell API to the include server: add a new "--scan-includes" option to distcc which shows which headers distcc would send to the remote machine in pump mode, without actually compiling anything. 2008-09-10 02:39 Fergus Henderson * pump.in: Fix : the pump script was hard-coding /etc/distcc/hosts rather than using the prefix specified to configure. Reviewed by Craig Silverstein. 2008-09-08 17:51 Fergus Henderson * Makefile.in, src/hosts.c: Report a better error message if a host specification contains ",cpp" but not ",lzo". Previously, setting ",cpp" without ",lzo" would quietly set the protocol version to -1, which the server would then quietly reject (logging as "REJ_BAD_REQ"), and then the client would guess (poorly) at why the server had dropped the connection. Reviewed by Craig Silverstein. 2008-08-07 22:58 Fergus Henderson * doc/web/man/distcc_1.html, doc/web/man/pump_1.html: Update the HTML versions of the man pages. 2008-08-07 22:50 Fergus Henderson * doc/web/index.html: Delete a duplicate link in the side-bar. 2008-08-06 20:37 Fergus Henderson * ChangeLog, NEWS, configure.ac: Change version number to "3.0", and update NEWS file and ChangeLog. 2008-08-06 15:37 Fergus Henderson * man/distcc.1, man/pump.1: Some final documentation updates before 3.0. In the distcc man page: - remove description of a bug that's been fixed now (distcc issue 7) - make it a little clearer that in pump mode we don't ship the header files from the default system header directories to the server - add a new section header "RESTRICTIONS OF PUMP MODE" - some typographical corrections. In the pump man page: - add a prominent pointer to the distcc man page, in particular to the "RESTRICTIONS OF PUMP MODE" section. Reviewers: Craig Silverstein ## distcc 3.0rc4. 2008-08-02 19:54 Fergus Henderson * ChangeLog, NEWS, configure.ac: Time for another release candidate. 2008-08-02 19:49 Fergus Henderson * test/testdistcc.py: Add C++ version of the SystemIncludeDirectories test. Also, reduce code duplication a little by adding a compileOpts() function to the CompilationCase class, and overriding that, rather than compileCmd(), in various derived classes. 2008-08-02 17:50 Fergus Henderson * include_server/compiler_defaults.py: Fix a TODO in compiler_defaults.py that was responsible for a bug that broke pump mode when one of the default system include directories was a subdirectory of another, as turns out to be the case for GNU C++. The CPlusPlus_SystemIncludeDirectories_Case, which was failing before this change, now passes. (TODO: re-enable it.) Reviewers: Craig Silverstein 2008-08-02 01:30 Fergus Henderson * bench/benchmark.py: Make the benchmarking script's stdout and stderr line buffered. Reviewers: Craig Silverstein 2008-08-02 01:27 Fergus Henderson * test/testdistcc.py: Add a test of C++ compilation, and refactor the tests of Objective-C and Objective-C++ to share the common code. Also, fix some bugs in the tests of Objective-C and Objective-C++. These tests were never being activated, even when the right compiler is installed, because in the test compilation (not using distcc) it was compiling with "-o /dev/null" and then testing that testtmp.o exists, which it never did. There was also a missing "std::" in the Objective-C++ test. I still haven't run the Objective-C++ test, because I still haven't figured out how to install Objective-C++, but it's pretty similar to the C++ and Objective-C tests, and both of those now run and pass. Reviewers: Craig Silverstein 2008-08-01 20:59 Fergus Henderson * bench/ProjectDefs.py: Update a stale URL. ## distcc 3.0rc3. 2008-08-01 03:42 Fergus Henderson * include_server/basics.py: Increase MAX_COMPONENTS_IN_SERVER_ROOT from 10 to 20. It turns out that our own test infrastructure (test/testdistcc.py) sets TMPDIR before invoking distccd, so this needs to be reasonably high, otherwise 'make distcheck' will fail. 2008-08-01 03:11 Fergus Henderson * Makefile.in: List va_copy.h in HEADERS, so that it gets included in the source distribution. 2008-07-31 19:19 Fergus Henderson * ChangeLog, NEWS, configure.ac: Bump version number to 3.0rc3, and update NEWS file and ChangeLog. Reviewed by Craig Silverstein. 2008-07-31 05:40 Fergus Henderson * src/distcc.h, src/filename.c: Fix issue 10 : add a work-around for a spurious gcc warning. Also, add a missing check for strdup() returning NULL. 2008-07-30 22:56 Fergus Henderson * src/dotd.c, src/serve.c, src/strip.c, test/testdistcc.py: Add a test case to test "-MT" and "-MF" without spaces after them. Some more bug fixes to make the test case pass. Also, make the DashWpMD_Case test a bit more strict: disable fallbacks, so that it tests that we can distribute such jobs. 2008-07-30 02:28 Fergus Henderson * src/fix_debug_info.c, src/netutil.c, src/snprintf.c, src/srvnet.c: Fix some warnings with -Wcast-align that show up only on machines that don't support unaligned accesses. Fix some const correctness warnings that show up only on machines that don't have vsnprintf(). Reviewers: Craig Silverstein 2008-07-30 02:27 Fergus Henderson * src/arg.c: Fix issue 13 : allow distcc to distribute commands that use "-MF" rather than "-MF ", and likewise for -MT and -MQ. 2008-07-30 01:13 Fergus Henderson * src/clirpc.c, src/tempfile.c: Apply patch from e...@jessies.org in : use S_ISLNK and S_ISDIR macros, to make the code more readable. 2008-07-29 23:04 Fergus Henderson * Makefile.in: In the Makefile, add a target for running a single test in pump mode. 2008-07-29 22:19 Fergus Henderson * include_server/basics.py, include_server/cache_basics.py, include_server/compiler_defaults.py, include_server/include_analyzer.py, include_server/macro_eval_test.py, include_server/mirror_path.py, include_server/mirror_path_test.py, include_server/parse_command_test.py, src/srvrpc.c, src/tempfile.c, test/testdistcc.py: This is based on klarlund's original version of this patch (klarlund/d3b3): gvn --project https://distcc.googlecode.com/svn/trunk review klarlund/d3b3 Fix Issue 7: Compiling with -I/usr/include/FOO or ... in pump mode Problem: Default system include directories are the directories on the default include search path, such as /usr/include, that is determined by the compiler. Distcc will not send default system include directories to the distcc compilation servers. Nevertheless, distcc on the server blindly rewrites -I options such as -I/usr/include/foo to -I/tmp/distccNNN/usr/include/foo. This doesn't work, since the files in /usr/include/foo are not sent to the distccd server. Solution: The present solution keeps the rewriting on the server, because we would like to not manage starting the compiler, parsing its output, and storing the default system paths on the server Instead, we use the existing mechanism for defining relative symbolic links under the server root. We escape from the root by using a sufficient number of '../'s. All this is tremendously complicated by: -- The possibility that other links encountered may point into the system default dirs in which case the usual mirroring of the reachable places should not take place, because the routing of such links will go through the link created for the system directory. -- The fact that determination of default-system-dirness is lazy: a deeply-seated link in a default system dir may become obsolete if it is later determined that a higher directory than the parent directory of the link is in fact also a default system dir. In that case, a new symlink, sitting in a place higher than the previous one will need to be created. Tests: make check benchmarks: samba (still 3X faster than with distcc), linux 2.6 kernel, and a couple of others TODO: better testing TODO: > In compiler_defaults.py, _MakeLinkFromMirrorToRealLocation: > Maybe comment each of the 'if' cases with an example of how this case > might be triggered. eg the real_prefix == rooted_system_dir is > triggered when we see /usr/include/foo, and the later see > /usr/include. 2008-07-29 22:17 Fergus Henderson * configure.ac, src/snprintf.c, src/trace.c, src/va_copy.h: Fix a bug that caused "make check" to fail: MissingCompiler_Case was reporting an unexpected exit status: 139 instead of 110. This was caused by a seg fault in distccd, deep in the bowels of vsnprintf(), which appears to be due to calling vsnprintf() twice on the same va_list. The fix is to use va_copy() in src/trace.c. Of course it's never quite as easy as that. va_copy() exists only in C99, not in C89. Some implementations have __va_copy() but not va_copy(). So we need to autoconf it. There was already an autoconf test for this, but only for __va_copy. I've moved the code which defined VA_COPY from snprintf.c to a new header file va_copy.h, and added a VA_COPY_END macro. Also, fix another bug that I noticed at the same time: snprintf.c was using va_copy(), but was not matching each call to va_copy with a corresponding call to va_end(), as required by the C99 standard. 2008-07-17 21:59 Lei Zhang * configure.ac: This adds an option for disabling avahi and friends. This is useful for building distcc targeted to machines without libavahi on a machine with libavahi. Reviewed by Fergus Henderson. 2008-07-02 00:34 Fergus Henderson * Makefile.in: Fix a bug reported by Aaron P. Perez where "make install" was failing on Cygwin. The problem was due to the install.log file generated by Python's distutils being generated in DOS text mode format rather than Unix text mode format. The fix is to use 'sed' to convert DOS text format to Unix text format when generating install.log. Note: this fix is slightly different than the original patch that I posted to the distcc mailing list. This patch is better because it fixes the install.log file, rather than just the grep command; this is important because the install.log file is also used for "make uninstall". Reviewers: Craig Silverstein 2008-06-30 17:10 Nils Klarlund * include_server/include_analyzer.py, include_server/include_analyzer_memoizing_node.py, include_server/include_analyzer_memoizing_node_test.py, include_server/include_analyzer_test.py, include_server/parse_command.py, include_server/parse_command_test.py: Revert r393. This change is mostly reverted -- some variable renamings are not changed back. A subsequent CL proposes a less arbitrary way to solve the problem of -I, which involves sending no system default header files at all. Tests: make pump-check and make include-server-check 2008-06-27 21:59 Fergus Henderson * NEWS: Delete a duplicate entry from the NEWS file. Reviewers: Craig Silverstein 2008-06-24 22:06 Fergus Henderson * packaging/googlecode_upload.py: Fix wrong description for uploaded distcc-.tar{.gz,.bz2} files. Reviewers: Craig Silverstein ## distcc 3.0rc2. 2008-06-20 15:17 Fergus Henderson * ChangeLog, NEWS: Update NEWS file and ChangeLog for distcc 3.0rc2. Also mention new website, repository and maintainer in NEWS file. 2008-06-20 02:54 Fergus Henderson * configure.ac: Bump version number to 3.0rc2. 2008-06-19 22:25 Fergus Henderson * src/gcc-id.c, src/zeroconf-reg.c, src/zeroconf.c: Add "Copyright (C) 2007 Lennart Poettering" to zeroconf.c, zeroconf-reg.c, and gcc-id.c. Remove Google copyright notice from src/gcc-id.c, since the Google changes to that file were very minor. 2008-06-19 20:55 Fergus Henderson * Makefile.in, packaging/deb.sh, packaging/rpm.sh: Change the deb.sh and rpm.sh scripts to remove old .deb or .rpm files (for the same package and version) before generating the new ones. Similarly change "make install-deb" and "make upload-dist" so that they are more selective in which files they install. This fixes a bug where "make install-deb" tried to install the wrong .deb files, because it just did "rpm -i *.deb", and there can be old .deb files lying around. It also fixes a similar problem in "make upload-dist". Also, add a "tags" target to the Makefile. Reviewers: Craig Silverstein 2008-06-18 03:30 Fergus Henderson * include_server/compiler_defaults.py: Fix bug where the include server would crash if the PATH environment variable wasn't set. 2008-06-18 02:23 Fergus Henderson * packaging/RedHat/conf/clients.allow: Fix a missing word in a comment. 2008-06-17 20:26 Fergus Henderson * src/compile.c, src/lock.c, src/remote.c, src/where.c, src/where.h: Fix for a deadlock bug that I observed (once!) when compiling the Linux kernel in pump mode: - Ensure that locks are acquired in the reverse order that they will be released: acquire remote lock before local lock. - Ensure that locks are released on all fallback paths. - Rename dcc_pick_host_from_list() as dcc_pick_host_from_list_and_lock_it(), so that its locking effect is clearer. - Document the lock ordering invariants. - Document the unlocking behaviour of dcc_compile_remote(). Reviewers: Craig Silverstein, Nils Klarlund 2008-06-17 18:32 Fergus Henderson * man/distcc.1: Document the limitations of pump mode w.r.t. debugging on systems with non-ELF object files. Reviewers: Craig Silverstein, Nils Klarlund 2008-06-11 16:10 Fergus Henderson * src/arg.c: Apply patch from Maks Verver which fixes a bug where distcc was not doing the right thing when invoked with "-march=native" or "mtune=native". This fixes . 2008-06-10 21:21 Fergus Henderson * doc/web/faq.html: Document the use of ssh connection sharing. 2008-06-10 05:51 Craig Silverstein * pump.in: When I moved the envvar declarations to inside the 'eval', I had to quote them to protect them from the extra level of evaluation, but I had failed to do this. This change makes it so I do. Tested by running 'make pump-maintainer-check on linux (ubuntu). Detected and reviewed by fergus ## distcc 3.0rc1. ## The following changes were made internally to Google, and not integrated ## into the main distcc distribution until 2008. The dates here are ## the dates they were applied to the internal-Google branch, and ## interleave with the changes to the main branch, below. 2008-06-10 02:20 Nils Klarlund * doc/web/benchmark.html: Improve wording and accuracy of claims. Just various relatively minor suggestions. I didn't understand the remarks about the importance of having 'beefier' remote machines (their raw CPU power are not different although RAM and number of CPUs per machine differ), so I took them out. Instead, a made a separate point about what would have happened if we'd used multiple-CPU clients. I put in a reference to our gws:gws benchmark, which drove our work. Also, -- Add side point about possible configurations issues and link to man pages. -- The number 'four' (for # of hello compilations) was obtained by inspection of the distcc log. Review: csilvers and fergus (at Google). 2008-06-10 00:52 Craig Silverstein * pump.in: Apparently, for freebsd's sh at least, "eval FOO=a bar" lets bar see FOO=a, while "FOO=a eval bar" does not. So change from the latter formulation to the former. Tested by running 'make pump-maintainer-check' on freebsd and on linux (ubuntu). Reviewed by klarlund 2008-06-10 00:09 Craig Silverstein * test/testdistcc.py: While testdistcc.py tries to use port 42000 to communicate, if it fails it tries 42001, etc. When checking output, make sure we match the port we actually ended up binding on. Tested by running 'make check' on a wide variety or architectures, including a FreeBSD machine where make check failed before this change. Reviewed by fergus 2008-06-09 23:12 Craig Silverstein * man/distcc.1, man/distccd.1, man/include_server.1, man/pump.1: Update date to june 9 instead of june 2. 2008-06-09 23:08 Craig Silverstein * configure.ac: I had talked Fergus into changing the version number from 3.0rc1 to 3.0-rc1. But now rpm is complaining that - is illegal in a version string, so I'm changing it back to 3.0rc1. Sorry Fergus... 2008-06-09 23:07 Craig Silverstein * ChangeLog: I had talked Fergus into changing the version number from 3.0rc1 to 3.0-rc1. But now rpm is complaining that - is illegal in a version string, so I'm changing it back to 3.0rc1. Sorry Fergus... 2008-06-09 22:02 Fergus Henderson * configure.ac: Change version number to 3.0rc1 (for "release candidate 1"). Reviewers: Craig Silverstein 2008-06-09 21:22 Craig Silverstein * Makefile.in, doc/web/man/distcc_1.html, doc/web/man/include_server_1.html, packaging/RedHat/rpm.spec: Update the html version of the man pages, based on the .1 updates. Add include_server, which is a new man page. Update the Makefile to know about the new man page, include it in the distribution, etc. Also update the rpm spec to include it too. 2008-06-09 20:31 Fergus Henderson * TODO: Some updates to the TODO list to mark as done issues which are addressed in distcc 3.0. Reviewers: Craig Silverstein 2008-06-09 20:28 Fergus Henderson * pump.in: Rename "Critique" function as "ReportDiscrepancies", to make it clearer what the function does. Reviewers: Craig Silverstein, Nils Klarlund 2008-06-09 19:59 Nils Klarlund * include_server/include_server.py, man/distcc.1, man/include_server.1, pump.in: The missing include_server(1) man page and additional material about the basic assumptions of distcc-pump added to man/distcc.1 as well. The BUGS section of distcc.1 has been updated. A spelling error correction is made to man/distcc.1. The pump.in script is changed so that it does not introduce other certain defaults than those mentioned in the manual (which are those of the of include server). Finally, I changed the order of the options in the include server source code to be alphabetical in accordance with include_server(1) man page. Reviewers: fergus, csilvers. 2008-06-09 19:53 Nils Klarlund * find_c_extension.sh: Correct obscure bug (that quoting a variable eliminates the conversion of newlines to spaces). Reviewers: fergus and csilvers (at Google). 2008-06-09 16:38 Lei Zhang * src/lsdistcc.c, test/testdistcc.py: lsdistcc should print non-default port numbers. Reviewed by fergus 2008-06-09 15:04 Fergus Henderson * pump.in: Fix typo in Nils' previous change. 2008-06-09 14:14 Nils Klarlund * pump.in, src/compile.c: Add necessary message to pump script with warning that compilations were forced from distcc-pump mode into plain mode. I had resisted doing this at first, because of the max_discrepancies_before_demotion constant in src/compile.c, which actually controls whether there were sufficiently many discrepancies to force a demotion. The problem is that the constant is not known to the pump script. It should be made configurable, through gosh, another env var. But that'll be for later. This constant is currently 1 and it shouldn't be changed. Reviewers: fergus and csilvers. 2008-06-07 01:21 Craig Silverstein * doc/web/benchmark.html, doc/web/compared.html, doc/web/compilers.html, doc/web/faq.html, doc/web/index.html, doc/web/results.html, doc/web/scenarios.html, doc/web/security.html: Add a link to the man pages from the side-bar. Also, fixed up the side-bar from a few non-top-level pages to be consistent with the top-level-pages bars: compilers.html and compared.html. 2008-06-07 01:16 Craig Silverstein * Makefile.in: When uploading the package, we try to update the website as well. Since the website contents are checked into svn, that's just a matter of checking in any auto-generated html-ized pages (eg the man pages). 2008-06-07 01:13 Craig Silverstein * doc/web/benchmark.html, doc/web/man/distcc_1.html, doc/web/man/distccd_1.html, doc/web/man/distccmon_text_1.html, doc/web/man/pump_1.html: Oops, the attribute is called svn:mime-type, not svn:content-type. 2008-06-07 01:10 Craig Silverstein * doc/web/man/distcc_1.html: Update from the empty file. 2008-06-07 01:08 Craig Silverstein * doc/web/man, doc/web/man/distcc_1.html, doc/web/man/distccd_1.html, doc/web/man/distccmon_text_1.html, doc/web/man/pump_1.html: Html version of the man pages, auto-generated. 2008-06-04 07:06 Craig Silverstein * Makefile.in: The avahi files (zeroconf.c, etc), were being left out of the distribution tarball. Add them in. Tested by running 'make distcheck' on a machine with avahi libs installed. Reviewed by fergus 2008-06-04 06:04 Craig Silverstein * pump.in: Get rid of setting is_in_installation; that variable isn't used anywhere anymore, so no reason to set it. Tested by running 'make pump-maintainer-check'. Reviewed by klarlund 2008-06-04 05:17 Craig Silverstein * Makefile.in: It turns out setup.py has a bug(?) in its --record output: in theory, the paths of the --record fields should start with --prefix, but sometimes the paths remove the leading / from --prefix: % env CPPFLAGS='-Isrc -Ilzo -Ipopt' SRCDIR=`pwd` include_server/setup.py install --prefix=/tmp/distcc-bar --record=/dev/stdout --root=/var/ tmp/distcc-bar/lib/python2.4/site-packages/include_server/parse_file_test.pyc [...] % env CPPFLAGS='-Isrc -Ilzo -Ipopt' SRCDIR=`pwd` include_server/setup.py install --prefix=/tmp/distcc-bar --record=/dev/stdout --root=/var /tmp/distcc-bar/lib/python2.4/site-packages/include_server/parse_file_test.pyc [...] It's hard to predict how, when and why it does this (--root=/ and --root="" are particularly confusing cases), but luckily we know we always want the leading slash: configure dies if --prefix isn't an absolute path. So with this change, we just let setup.py write whatever it wants to, and then add a leading slash before each line of the --record output if it's missing. Tested by running ./configure --prefix=/tmp/distcc rm -rf /tmp/distcc; make install rm -rf /var/tmp/tmp/distcc; make install DESTDIR=/var/tmp rm -rf /var/tmp/tmp/distcc; make install DESTDIR=/var/tmp/ and verified that files ended up where expected, and the pump script looked like expected (with pump's sibling files living in /tmp/distcc/...). Reviewed by fergus 2008-06-03 23:06 Craig Silverstein * Makefile.in, configure.ac: Fix up the list of zeroconf files needed to actually compile distcc and distccd. Tested by installing avahi and running 'make' plus 'make check'. Reviewed by klarlund 2008-06-03 21:00 Craig Silverstein * src/zeroconf.h: Fix up the top-of-file comments to look the same as for all the other files. 2008-06-03 20:58 Craig Silverstein * src/zeroconf-reg.c, src/zeroconf.c: Fix some extra comment specifiers that shouldn't have been there. 2008-06-03 12:30 Nils Klarlund * man/distcc.1, man/distccd.1, man/pump.1: Various edits: -- refer to pump(1) credits (and remove distcc(1) credits from pump(1) credentials) -- detail fundamental include server assumption -- clean up incl server discussion -- refer to include_server(1) for hairy stuff (this man page is to follow shortly in separate CL) -- discuss shell scripts instead of symlinks -- change date to June 2 2008 -- other minor edits 2008-06-03 05:43 Craig Silverstein * NEWS: Update the release date. 2008-06-03 05:32 Craig Silverstein * bench/ProjectDefs.py: Add some new benchmark routines (including C++ projects like yate and ACE), and normalize syntax for existing ones. I've tested that we can at least build all of these projects locally, as long as all neccesary dependent packages are installed. Reviewed by fergus 2008-06-03 03:45 Fergus Henderson * bench/Build.py, pump.in: Fix a bug in the pump script where it wasn't waiting for the include server to terminate before exiting. Reviewers: Nils Klarlund, Craig Silverstein 2008-06-03 00:32 Craig Silverstein * doc/web/faq.html, doc/web/index.html, doc/web/results.html, doc/web/scenarios.html, doc/web/security.html: Revamp the toc sidebar to organize the categories a bit better. Also added a benchmark line. 2008-06-03 00:32 Craig Silverstein * doc/web/benchmark.html: Add benchmark results, and a discussion of same. Reviewed by klarlund 2008-06-02 22:38 Fergus Henderson * src/clirpc.c: Fix spelling error and punctuation in warning message. Reviewers: Craig Silverstein 2008-06-02 19:35 Nils Klarlund * include_server/basics.py, include_server/cache_basics.py, include_server/include_server.py, pump.in: Fix option real_path_warning_re not working. I renamed the option to path_observation_re. Now by prefixing INCLUDE_SERVER_ARGS='-d1 --path_observation_re="/usr/.*"' to say make include-server-maintainer-check, one gets a message each time the include server finds a path whose realpath name matches the regular expression. That results in messages like: WARNING include server: For translation unit 'src/testtmp.c', lookup of file 'bits/stdio_lim.h' resolved to '/usr/include/bits/stdio_lim.h' whose realpath is '/usr/include/bits/stdio_lim.h'. To make the interpretation of quoted arguments within INCLUDE_SERVER_ARGS correct, I added 'eval' to the command that cranks up the include server. I remembered to put extra quoted quotes inside the parameters that should be considered a token after the double interpretation that eval implies. 2008-05-31 00:38 Nils Klarlund * test/comfychair.py, test/testdistcc.py: Tidy-up testing framework to overcome recently introduced bug. Testing on cygwine revealed that as tests were being issued the temporary testing directory would suffer from longer and longer prefixes until a 'filename too long' error would stop the party. This is result of an earlier attempt to avoid too much printing to stdout during tests, spefically during recursive test invocations. The problem is that the teardown mechanism of the comfychair enviroment is not expressed -- by any name at all (it could be 'teardown' for example). So, I added a name --- but because there's no expectation that the TestCase class defined there has its teardown method called from derived classes --- I chose the name CleanUps, which corresponds to the private variable. I also made an abstraction for running a test. This new Comfychair.runtest function can the conveniently by called to carry out a subtest. With this CL, 'make pump-maintainer-check' now works on cygwin. 2008-05-30 22:57 Craig Silverstein * AUTHORS, INSTALL, README, README.pump, configure.ac, doc/example/init, doc/web/compared.html, doc/web/compilers.html, doc/web/faq.html, doc/web/favicon.ico, doc/web/index.html, doc/web/results.html, doc/web/scenarios.html, doc/web/security.html, man/distcc.1, man/distccd.1, man/distccmon-text.1, man/pump.1: Documentation fixes: 1) Replace http://distcc.samba.org with the new google code location 2) Add favicon.ico from the distcc.samba.org site 3) Use distcc@lists.samba.org as the only distcc mailing list (there were at least three mailing lists scattered around the docs, some of which don't even exist anymore!) 4) Update man pages and other docs to not use "distcc-pump" anywhere; it's now "pump mode" or "distcc's pump mode", or "distcc-pump mode". I also add, to the README, some discussion of scaling to hundreds of machines. Reviewed by fergus and klarlund 2008-05-30 07:46 Fergus Henderson * Makefile.in, packaging/RedHat/rpm.spec: Fix a bug where the "pump" man page was not included in the RPM and Debian packages. Also, fix a bug where the Makefile rules for building HTML files were not working when srcdir != builddir. Tested by "make install-deb; man pump". Reviewers: Craig Silverstein 2008-05-29 21:44 Nils Klarlund * bench/Build.py: Add include server option '--unsafe_absolute_includes' to all benchmarks in pump mode. This is harmless I think, and it's easy to forget this option. It is of importance to at least Samba-2.2.7. 2008-05-29 18:51 Nils Klarlund * bench/benchmark.py, bench/compiler.py: Tigthen how compilers are located. This overcomes issues on Cygwin. I also changed default C++ compiler to 'c++' instead of 'cxx'. 'c++' is the more common name I believe. Witht this change, both compilers must exist for benchmark.py to run. REVIEW: Craig Silverstein 2008-05-29 18:51 Nils Klarlund * bench/Build.py, bench/Summary.py, bench/statistics.py: Enhance performance reporting for benchmarking. This CL adds reporting of: - number of processors - total cpu time - cpu utilization - include server cpu time I corrected issues with overly loose specification of compiler locations. (I developed this CL under Cygwin and encountered new problems.) This resulted in evil recursive invocations of distcc. I also: -- removed an unnecessary parameter from Build(..) -- pruned the number of decimals reported from 4 to 1. -- removed the dependency of 'Numeric', which is a non-standard package and rewrote the math do to std deviation -- use shell built-in 'time' instead of Python time functionality -- corrected deficient error reporting: builds would fail with non-zero status and not be reported as failing. REVIEW: Craig Silverstein TESTS: DISTCC_HOSTS="--randomize `/home/klarlund/svn-distcc/distcc/lsdistcc -P1 -k100 -d`" PATH=`pwd`:$PATH bench/benchmark.py --cc='/usr/crosstool/v10/gcc-4.2.1-glibc-2.3.2/x86_64-unknown-linux-gnu/bin/x86_64-unknown-linux-gnu-gcc' -n 1 -c 'pump,h40,j120' -c 'dist,h40,j32' linux-2.6.25 Part of the printout for hello-2.1.1: Local number of CPUs: 4 Linux klarlund-warp.nyc.corp.google.com 2.6.18.5-gg34workstation-mixed64-32 #1 SMP Thu May 8 01:31:23 UTC 2008 x86_64 GNU/Linux project compiler time s.d. CPU time CPU util incl serv hello-2.1.1 pump_h39_j120 0.9s 0.0s 0.5s 13.5% 0.2s hello-2.1.1 dist_h39_j32 0.4s 0.1s 0.3s 18.1% (For this small program, pump is a disadvantage.) 2008-05-29 05:38 Craig Silverstein * bench/Build.py, bench/Project.py, bench/actions.py, bench/benchmark.py, bench/compiler.py: Some changes to the benchmark framework to not redo work unnecessarily. Most prominently, no longer re-run 'tar xf && configure' every benchmark run. Instead, if configure was successfully executed last benchmark run, just do 'make clean'. This is equivalent to what we do now between build runs, when the repeat-count is > 1. This feature is not turned on by default, but must be enabled with the new --force=0 flag. --force=1 keeps the same behavior as before: we always re-run configure in each build-directory. --force=2 adds more repeat-work than before; in --force=2 mode, we always re-download the package from the web, even if we had successfully downloaded it before. Note that the 'tar' command currently warms the file-cache, which makes build times more consistent, so there is so cost to setting --force=0, in terms of the data collected. Reviewed by klarlund 2008-05-29 02:04 Nils Klarlund * bench/Build.py, bench/Project.py, bench/ProjectDefs.py: Add include server args to benchmarking framework. This makes the linux kernel build with pump-mode when the benchmark script is used. Also, include the '-t' option to the include server; that prints out the elapsed and CPU times at the end of the build. REVIEW: Craig Silverstein TESTS: (on quad-cpu workstation) DISTCC_HOSTS="--randomize `/home/klarlund/svn-distcc/distcc/lsdistcc -P1 -k100 -d`" PATH=`pwd`:$PATH bench/benchmark.py --cc='/usr/crosstool/v10/gcc-4.2.1-glibc-2.3.2/x86_64-unknown-linux-gnu/bin/x86_64-unknown-linux-gnu-gcc' --cxx='void' -n 5 -c 'pump,h40,j120' -c 'dist,h40,j32' linux-2.6.25 project compiler time s.d. linux-2.6.25 pump_h39_j120 69.6525s 3.0969s linux-2.6.25 dist_h39_j32 103.8416s 10.8041s 2008-05-29 01:57 Nils Klarlund * pump.in: Add critique of pump-mode when include server shuts down. Print a message like: __________Warning: 1 pump-mode compilation(s) failed on server, but succeeded locally. when compile discrepancies have occurred. Currently, a user may think that all is well because we do not terminate a build when discrepancies occur and the warning messages occurring in the middle of a build may easily be overlooked. REVIEW: Craig Silverstein TESTS: make linux-kernel without stat reset triggers to observe message 2008-05-29 01:46 Craig Silverstein * src/dotd.c, src/dotd.h, src/emaillog.c, src/emaillog.h: Fix some of the written-on dates for some google patches. Pointed out by fergus. 2008-05-28 13:12 Nils Klarlund * pump.in: Fix unproctected invocation of distcc and numeric designation of one with a plural noun. I discovered this bug by deleting /usr/bin/distcc. I did that after I found out that the Linux kernel compilation is suffering from a similar issue (amongst others), because the PATH is apparently rewritten. 2008-05-28 02:32 Nils Klarlund * include_server/cache_basics.py, include_server/parse_command.py: Remove spurious warning messages about absolute filepaths. During compilation of the Linux kernel messages like: absolute filepath blabla.h was IGNORED (correctness of build may be affected) are issued. They are wrong. The problem is that -include or -imacro or even source file names with absolute filepaths trigger a complaint from the caching mechanism usually used for relative file names. We correct this problem. We also substitute fp_map for includepath_map, which is the now preferred term. REVIEWER: Craig Silverstein TESTS: make pump-maintainer-check make include-server-maintainer-check 2008-05-28 02:19 Nils Klarlund * src/compile.c: Fix race condition that may prevent the warning message that pump-mode is no longer used from being displayed. This is the current crop of error messages. A couple of them *really* should be suppressed, but not the last one, which the CL is about. distcc[4333] ERROR: compile arch/x86/kernel/syscall_64.c on distcc4.nyc.corp.google.com,lzo,cpp failed distcc[4333] (dcc_build_somewhere) Warning: remote compilation of 'arch/x86/kernel/syscall_64.c' failed, retrying locally distcc[4333] Warning: failed to distribute arch/x86/kernel/syscall_64.c to distcc4.nyc.corp.google.com,lzo,cpp, running locally instead distcc[4333] (dcc_please_send_email_after_investigation) Warning: remote compilation of 'arch/x86/kernel/syscall_64.c' failed, retried locally and got a different result. distcc[4333] (dcc_please_send_email_after_investigation) Warning: file 'include/asm/asm-offsets.h', a dependency of arch/x86/kernel/syscall_64.c, changed during the build distcc[4333] (dcc_note_discrepancy) Warning: now using plain distcc, possibly due to inconsistent file system changes during build The last message may not occur: the code contains a race condition, because more processes may increment the unary file, after it has reached the size of max_discrepancies_before_demotion, preventing the equality from ever becoming true. 2008-05-27 20:33 Nils Klarlund * include_server/include_analyzer.py, include_server/include_analyzer_memoizing_node.py, include_server/include_analyzer_memoizing_node_test.py, include_server/include_analyzer_test.py, include_server/parse_command.py, include_server/parse_command_test.py: Make the Linux 2.6 kernel build with distcc-pump mode. Add a new piece of command line parse information: send_systemdirs. This boolean is normally false. It is true if there is a -isystem option with a default system directory (one known to the compiler). With send_systemdirs true, the compiler headers of system headers are sent to the servers and mounted under the server root. The isystem option is as usual rewritten to be relative to the root. Without this flag setting, distcc quickly decides that pump mode is not viable because remote compilations fail. Also, fixed the comment: # TODO(klarlund): Make mechanism for handling -U, -undef options, along with # default symbols. (-D options are handled.) --------------- TESTS: make pump-maintainer-check make include-server-maintainer-check make 'linux kernel' in a directory made by the benchmark script (as shown below) DISTCC_EMAILLOG_WHOM_TO_BLAME=Nils Klarlund DISTCC_ENABLE_DISCREPANCY_EMAIL=1 INCLUDE_SERVER_ARGS='-d1 -t --email --unsafe_absolute_includes --send_systemdirs --stat_reset_triggers=include/linux/*' DISTCC_HOSTS="--randomize `/home/klarlund/svn-distcc/distcc/lsdistcc -P3 -k100 -d`" PATH=/home/klarlund/svn-distcc/distcc:$PATH ./masquerade pump make -j120 REVIVIEWER: Craig Silverstein TRIVIA: the about 1000 files in the kernel build involve on average 400 headers. The build time on a quad-cpu machine drops from about 1m40 s to 1m20s. With pump-mode, the machine is underutilized judging from the total sys + user time, which is around only 2m20s. NOTE: this is a successor to 'g6n8', which simply introduced a command line option to force sending of system files. A bug in gvn did not allow me to resuse that change list. 2008-05-23 22:24 Craig Silverstein * bench/Build.py, bench/Project.py, bench/Summary.py, bench/actions.py, bench/benchmark.py, bench/buildutil.py, bench/compiler.py, bench/statistics.py, include_server/basics.py, include_server/basics_test.py, include_server/c_extensions_test.py, include_server/cache_basics.py, include_server/compiler_defaults.py, include_server/compress_files.py, include_server/include_analyzer.py, include_server/include_analyzer_memoizing_node.py, include_server/include_analyzer_memoizing_node_test.py, include_server/include_analyzer_test.py, include_server/include_server.py, include_server/include_server_test.py, include_server/macro_eval.py, include_server/macro_eval_test.py, include_server/mirror_path.py, include_server/mirror_path_test.py, include_server/parse_command.py, include_server/parse_command_test.py, include_server/parse_file.py, include_server/parse_file_test.py, include_server/run.py, include_server/setup.py, include_server/statistics.py, src/access.c, src/access.h, src/arg.c, src/argutil.c, src/backoff.c, src/bulk.c, src/bulk.h, src/cleanup.c, src/climasq.c, src/clinet.c, src/clinet.h, src/clirpc.c, src/compile.c, src/compile.h, src/compress.c, src/cpp.c, src/daemon.c, src/daemon.h, src/distcc.c, src/distcc.h, src/dopt.c, src/dopt.h, src/dotd.c, src/dotd.h, src/dparent.c, src/dsignal.c, src/emaillog.c, src/emaillog.h, src/exec.c, src/exec.h, src/exitcode.h, src/filename.c, src/fix_debug_info.c, src/fix_debug_info.h, src/gcc-id.c, src/h_argvtostr.c, src/h_compile.c, src/h_dotd.c, src/h_exten.c, src/h_hosts.c, src/h_issource.c, src/h_parsemask.c, src/h_sa2str.c, src/h_scanargs.c, src/h_strip.c, src/help.c, src/history.c, src/hostfile.c, src/hosts.c, src/hosts.h, src/implicit.c, src/implicit.h, src/include_server_if.c, src/include_server_if.h, src/io.c, src/loadfile.c, src/lock.c, src/lock.h, src/lsdistcc.c, src/mon-gnome.c, src/mon-notify.c, src/mon-text.c, src/mon.c, src/mon.h, src/ncpus.c, src/netutil.c, src/netutil.h, src/prefork.c, src/pump.c, src/remote.c, src/renderer.c, src/renderer.h, src/rpc.c, src/rpc.h, src/rslave.c, src/rslave.h, src/safeguard.c, src/sendfile.c, src/serve.c, src/setuid.c, src/snprintf.h, src/srvnet.c, src/srvnet.h, src/srvrpc.c, src/ssh.c, src/state.c, src/state.h, src/stats.c, src/stats.h, src/stringmap.c, src/stringmap.h, src/strip.c, src/tempfile.c, src/timefile.c, src/timefile.h, src/timeval.c, src/timeval.h, src/trace.c, src/trace.h, src/traceenv.c, src/types.h, src/util.c, src/util.h, src/where.c, src/where.h, src/zeroconf-reg.c, src/zeroconf.c, src/zeroconf.h, test/comfychair.py, test/testdistcc.py: Normalize the copyright text, to the latest version of the GPLv2 text (typically the only change is in the FSF street address). Add Google copyright line in some places it was missing. Add GPLv2 notice to avahi patches. OKed by fergus 2008-05-23 20:43 Craig Silverstein * packaging/RedHat/rpm.spec: Update install-message wording. Reviewed by fergus 2008-05-23 07:33 Craig Silverstein * configure.ac: Update copyright and GPL notice. 2008-05-23 07:29 Craig Silverstein * pump.in, test/onetest.py: Fix author lines. Also, add gpl text. OKed by fergus and klarlund 2008-05-23 06:30 Fergus Henderson * packaging/RedHat/conf/clients.allow, packaging/RedHat/rpm.spec: Do not include 127.0.0.1 in clients.allow by default, because it is a security risk: it may allow other users on the machine to execute arbitrary code as the distcc user. Instead, leave clients.allow empty by default, and require the system admistrator to edit clients.allow manually, if they want to use distcc in TCP mode. We still install distccd as a service, but distccd will exit immediately unless you've already added some hosts to clients.allow. Reviewers: Craig Silverstein 2008-05-23 03:19 Fergus Henderson * include_server/include_analyzer_memoizing_node.py: Fix a typo in a comment. 2008-05-23 03:18 Fergus Henderson * src/dopt.c: Fix a bug: --wizard is supposed to imply --log-level debug, but this wasn't working, because the code that handles --wizard wasn't setting opt_log_level_num. Reviewers: Craig Silverstein 2008-05-23 03:12 Nils Klarlund * include_server/include_analyzer.py, include_server/mirror_path.py: Fix unsoundess of directory replication. Testing of distcc-pump mode on the Linux kernel showed that the computed include closure was sometimes wrong: header files were missing. Further testing showed that sometimes apparently not even the compilation unit made it across to the server or rather, the c-file in its real location would come across, but the path designating it would not. Take as an example: compilation unit is designated by the path ../bar/baz.c and the current directory is /foo but no files in /foo are in actuality referenced during include processing. Then the compilation server will get /PREFIX/bar/baz.h -- the image of the real file -- but /PREFIX/foo, the image of the current directory, will not even be created! So, this CL corrects an oversight in the way that the include processor explores files: although it does take into account the chasing of symbolic links, no provisions are in place to properly model '..' for climbing up directories. Specifically, to climb up a directory, it must exist! Usually, the directory in fact would exist on the server, because it would be replicated thanks to the header files it contains. But there is no guarentee. We solve this problem by forcing the creation of dummy .c files the first time a path is explored. Because paths are being investigated backwards (from the end), forcing results in extra files only at the "deep" levels. Since files are usually clustered together in directories, the addition of a dummy file per deep directory should be inconsequential for performance. TBD: integration level tests that this really work. I will either include that later or in a separate CL. Tested: make pump-maintainer-check build the Linux 2.6 kernel in true pump-mode (with extra patch, to be described separately that sends compiler system files to the server) [all files but a few towards the end suffer from absolute includes are preprocessed and compiled on the compile servers!] The command I used is: DISTCC_EMAILLOG_WHOM_TO_BLAME=Nils Klarlund DISTCC_ENABLE_DISCREPANCY_EMAIL=1 INCLUDE_SERVER_ARGS='-d1 -t --email --stat_reset_triggers=include/linux/compile.h' DISTCC_HOSTS="--randomize `/home/klarlund/svn-distcc/distcc/lsdistcc -P3 -k100 -d`" PATH=/home/klarlund/svn-distcc/distcc:$PATH ./masquerade pump make -j120 I had to delete /usr/bin/distcc for this work, because of the PATH acrobatics that the kernel makefiles apparently exercise. Otherwise, /usr/bin/distcc would sometimes get called. Reviewed: Fergus Henderson , Craig Silverstein 2008-05-23 03:03 Fergus Henderson * INSTALL: Some trivial style changes. 2008-05-23 02:35 Nils Klarlund * bench/Build.py, bench/benchmark.py, bench/compiler.py: Set-up masquerading for benchmarks. Follow the advice of the distcc man page for executing the benchmarks to not rely on CC and CXX variables by also routing naked calls of 'cc', 'gcc', etc to a 'farm' of tiny shell scripts. Also, provide a little wrapper script that does this for people who have to debug a benchmark build. This change is convenient for running the benchmark on the linux kernel, because building the kernel uses naked 'gcc' calls. Testing: Building the linux kernel. 2008-05-23 01:41 Fergus Henderson * Makefile.in: Fix a bug which broke the Debian and RPM distributions: the generated pump script was referring to DESTDIR. Files should be installed into DESTDIR, but they should never refer to DESTDIR, because it is only a temporary location used for constructing the RPM file; when the package is actually installed, the files will get put in e.g. /usr rather than DESTDIR/usr. Tested with "make install-deb && make daemon-installcheck". Reviewers: Nils Klarlund 2008-05-23 01:11 Manos Renieris * NEWS, README.pump, doc/protocol-3-impl.txt, doc/protocol-3.txt, man/distcc.1, man/pump.1: Minor documentation changes. 2008-05-22 19:06 Fergus Henderson * src/dotd.h, src/include_server_if.h: Remove "svn:executable" property (the "+x" permission bit) from header files. Reviewers: Manos Renieris 2008-05-22 05:36 Fergus Henderson * survey.txt: Direct survey response to distcc-survey@google.com rather than to Martin Pool. Reviewers: Craig Silverstein 2008-05-22 05:35 Fergus Henderson * INSTALL: A major overhaul of the INSTALL file. Describe pump mode better, and explain the effects of installing via RPM or Debian package. Also a bunch of other minor edits. Reviewers: Craig Silverstein 2008-05-22 04:51 Fergus Henderson * configure.ac: Bump version number to 3.0-prerelease3. Reviewers: Craig Silverstein 2008-05-22 04:49 Fergus Henderson * include_server/include_analyzer_test.py: Fix a test case that was failing on MacOS X. The test was implicitly assuming that /tmp == realpath(/tmp). But in MacOS X, /tmp is a symbolic link to /private/tmp. Reviewers: Craig Silverstein, Nils Klarlund 2008-05-22 04:40 Fergus Henderson * doc/web/index.html: Update the "60 second instructions" to use pump mode. I considered mentioning both regular mode and pump mode in the 60 second instructions, but 60 seconds doesn't really give you much time to describe the difference between the two, so I thought it was simpler to just go with pump mode. Reviewers: Craig Silverstein 2008-05-21 22:42 Fergus Henderson * test/testdistcc.py: Disable the Gdb_Case test in non-pump mode when using gcc versions that don't preserve the source directory in the preprocessed output. Reviewers: Nils Karlund, Craig Silverstein 2008-05-21 20:28 Nils Klarlund * src/clirpc.c: Make an obscure and common error message more informative. Currently, our users get the following error message when their workstation is not in the allowed domains as specified in the server configuration: distcc[20742] (dcc_readx) ERROR: unexpected eof on fd5 distcc[20742] (dcc_r_token_int) ERROR: read failed while waiting for token "DONE" With this change, a message explains some likely causes of the problem. 2008-05-21 16:37 Fergus Henderson * test/testdistcc.py: Disable some tests that were failing if you don't have a C++ compiler installed. Also, tidy up the output from the DotD_Case test: instead of DotD_Case TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK OK you now get just DotD_Case OK Also, fix a problem where ObjectiveCPlusPlus_Case test was on some systems being run even though the system didn't have Objective C++ installed. Reviewers: Nils Klarlund 2008-05-21 16:26 Nils Klarlund * include_server/basics.py, include_server/cache_basics.py, include_server/include_analyzer_test.py, include_server/include_server.py: Add '--unsafe_absolute_includes' option so that more can be compiled in pump-mode. An occurrence of say #include "/usr/include/acl.h" will normally force the include processor to abort (even when this include is platform-specific and #ifdef'ed away), because there are no guarantees that the file /usr/include/acl.h exists on the host. With this option, these includes will be ignored. A message like: WARNING include server: absolute filepath '/usr/include/acl.h' was IGNORED (correctness of build may be affected) will be printed. The normal message raised when this option is off, the default, has been modified. It now mentions the option. An include server manual page is to follow, which explains the consequences in detail of using this option. Testing: this makes the samba-2.2.7 benchmark build without hiccups using distcc pump. Without the change many compilations fail because the include server bails out and because another unrelated bug in the include server makes it later dish up with include closures that are too small. Revievers: Craig Silverstein , Fergus Henderson 2008-05-21 09:04 Fergus Henderson * Makefile.in, pump.in, src/include_server_if.c: Some usability improvements, in particular better diagnostics for common setup errors. In pump script: - If DISTCC_HOSTS is set, print out a message saying how many hosts there are (similar to the one that we already print if you instead set DISTCC_POTENTIAL_HOSTS) and how many of them have pump enabled. - Report an error if you run pump using a host list containing no hosts with ',cpp'. (Should this be a warning instead?) - Report an error if you run pump using an empty host list. (Should this be a warning instead?) In distcc client: - Improve the warning messages that you get if you run distcc using hosts with ",cpp" without running pump. 2008-05-21 06:13 Craig Silverstein * bench/Project.py, bench/ProjectDefs.py: Document the options that the Package constructor takes. Get rid of source_name, which isn't used anywhere. Also, add a few more benchmark projects. These are big(ish) and written in C++, to test distcc on C++ code. Reviewed by Nils Klarlund 2008-05-20 21:49 Craig Silverstein * bench/Build.py, bench/benchmark.py: In the benchmark code, make sure a directory exists before cd-ing into it. This is to handle projects like ACE, which require you to build from an entirely new directory. Also fix up an obsolete help-text sentence. Reviewed by Fergus Henderson 2008-05-20 20:23 Fergus Henderson * include_server/basics.py, include_server/compiler_defaults.py, include_server/parse_command.py, include_server/parse_command_test.py, test/testdistcc.py: Re-enable Objective C and Objective C++ support. This required the following changes: - Compute the default search paths for each language lazily, when the language is first encountered, rather than computing it for 'c' and 'c++'. - Make the tests of Objective C and Objective C++ conditional on the relevant compiler being installed. Tested by "make check" on two systems: - One with Objective C installed, but not Objective C++. - One with neither installed. I didn't test on a system with Objective C++ installed, because I didn't have one easily available. Reviewers: Craig Silverstein, Nils Klarlund. 2008-05-20 20:19 Fergus Henderson * test/testdistcc.py: Disable part of the DashWpMD_Case test, because it doesn't pass :-( Tested with "make check"; fails before this CL, passes afterwards. Reviewers: Nils Klarlund, Craig Silverstein. 2008-05-20 18:16 Craig Silverstein * src/access.c, src/access.h, src/arg.c, src/backoff.c, src/bulk.c, src/bulk.h, src/cleanup.c, src/climasq.c, src/clinet.c, src/clinet.h, src/clirpc.c, src/compile.c, src/compile.h, src/compress.c, src/cpp.c, src/daemon.c, src/daemon.h, src/distcc.c, src/distcc.h, src/dopt.c, src/dopt.h, src/dotd.c, src/dotd.h, src/dparent.c, src/dsignal.c, src/emaillog.c, src/emaillog.h, src/exec.c, src/exec.h, src/exitcode.h, src/fix_debug_info.c, src/fix_debug_info.h, src/gcc-id.c, src/h_hosts.c, src/h_parsemask.c, src/help.c, src/history.c, src/hostfile.c, src/hosts.c, src/hosts.h, src/implicit.c, src/implicit.h, src/include_server_if.c, src/include_server_if.h, src/io.c, src/loadfile.c, src/lock.c, src/lock.h, src/lsdistcc.c, src/mon-gnome.c, src/mon-notify.c, src/mon-text.c, src/mon.c, src/mon.h, src/ncpus.c, src/netutil.c, src/netutil.h, src/prefork.c, src/pump.c, src/remote.c, src/renderer.c, src/renderer.h, src/rpc.c, src/rpc.h, src/rslave.c, src/rslave.h, src/safeguard.c, src/sendfile.c, src/serve.c, src/setuid.c, src/snprintf.c, src/snprintf.h, src/srvnet.c, src/srvnet.h, src/srvrpc.c, src/ssh.c, src/state.c, src/state.h, src/stats.c, src/stats.h, src/stringmap.c, src/stringmap.h, src/strip.c, src/tempfile.c, src/timefile.c, src/timefile.h, src/timeval.c, src/timeval.h, src/trace.c, src/trace.h, src/traceenv.c, src/types.h, src/util.c, src/util.h, src/where.c, src/where.h, src/zeroconf-reg.c, src/zeroconf.c, src/zeroconf.h: Change C++-style // comments to /**/. Also, fix the emacs var-setting line: it was missing a semicolon before, which means the entire line was being ignored. No contentful change. Reviewed by Fergus Henderson 2008-05-20 06:13 Craig Silverstein * src/access.c, src/access.h, src/arg.c, src/argutil.c, src/backoff.c, src/bulk.c, src/bulk.h, src/climasq.c, src/clinet.c, src/clinet.h, src/clirpc.c, src/compile.c, src/compile.h, src/compress.c, src/cpp.c, src/daemon.c, src/daemon.h, src/distcc.c, src/distcc.h, src/dopt.c, src/dopt.h, src/dotd.c, src/dotd.h, src/dparent.c, src/dsignal.c, src/emaillog.c, src/emaillog.h, src/exec.c, src/exec.h, src/exitcode.h, src/filename.c, src/fix_debug_info.c, src/fix_debug_info.h, src/gcc-id.c, src/h_argvtostr.c, src/h_compile.c, src/h_dotd.c, src/h_exten.c, src/h_hosts.c, src/h_issource.c, src/h_parsemask.c, src/h_sa2str.c, src/h_scanargs.c, src/h_strip.c, src/help.c, src/history.c, src/hostfile.c, src/hosts.c, src/hosts.h, src/implicit.c, src/implicit.h, src/include_server_if.c, src/include_server_if.h, src/io.c, src/loadfile.c, src/lock.c, src/lock.h, src/lsdistcc.c, src/mon-gnome.c, src/mon-notify.c, src/mon-text.c, src/mon.c, src/mon.h, src/ncpus.c, src/netutil.c, src/netutil.h, src/prefork.c, src/pump.c, src/remote.c, src/renderer.c, src/renderer.h, src/rpc.c, src/rpc.h, src/rslave.c, src/rslave.h, src/safeguard.c, src/sendfile.c, src/serve.c, src/setuid.c, src/snprintf.c, src/snprintf.h, src/srvnet.c, src/srvnet.h, src/srvrpc.c, src/ssh.c, src/state.c, src/state.h, src/stats.c, src/stats.h, src/stringmap.c, src/stringmap.h, src/strip.c, src/tempfile.c, src/timefile.c, src/timefile.h, src/timeval.c, src/timeval.h, src/trace.c, src/trace.h, src/traceenv.c, src/types.h, src/util.c, src/util.h, src/where.c, src/where.h, src/zeroconf-reg.c, src/zeroconf.c, src/zeroconf.h: Turned all tabs into 4 spaces. Got rid of whitespace at the end of lines. Fixed up resulting mis-indented code I noticed (mostly in files that used 8 space indents, or used 4-space and 8-space indents in the same file (!)). Added the emacs tab-var setting for all files, not just some of them. I also added in copyright notices for files I noticed that didn't have them. We'll want to do another pass-through to fix these up properly, though. I used the following perl snippet to check for mis-indented code after converting tabs to whitespace: $ for i in *.{c,h}; do echo $i; perl -nle 'if ($indent > 0) {$sp=" " x $indent; /^$sp[^ ]/ && print "$.: $_"; $indent=0;}; if (/^( *).*{/ ) {$indent=length($1);} else {$indent=0;}' $i; done | less It had false positives, but hopefully didn't miss anything. Reviewed by Nils Klarlund 2008-05-20 05:58 Craig Silverstein * bench/benchmark.py: Add --output to benchmark.py, to print the final timing summary to a file in addition to stdout. Also made sure we don't try to access opt_cc and opt_cxx until after all flags are read, so flag order doesn't matter. Finally, fixed indentation so we only print the default actions when --help is specified (as intended). Tested by running make benchmark. Reviewed by Nils Klarlund 2008-05-20 03:32 Nils Klarlund * src/emaillog.c: Fix polarity of condition. Reviewers: Fergus Henderson Tests: manual (both with and without DISTCC_EMAILLOG_WHOM_TO_BLAME set). 2008-05-20 03:31 Nils Klarlund * bench/benchmark.py: Corrent option name. The option is said to be 'distcc', but it's actually implemented as 'dist'. The latter is fine with me: we have 'dist' and 'pump', with 'pump' being a more advanced 'dist'. 2008-05-20 03:31 Nils Klarlund * test/testdistcc.py: Improve assert message. Revievers: Fergus Henderson 2008-05-19 10:00 Fergus Henderson * bench/compiler.py, test/testdistcc.py: Add 'DashWpMD_Case' to the list of test cases that actually get run. Also, an unrelated change to the benchmarking scripts: fix a cut-and-paste error in an error message. Reviewers: Craig Silverstein 2008-05-19 09:58 Fergus Henderson * src/arg.c: Whitespace change: make indentation more consistent. 2008-05-18 06:06 Fergus Henderson * src/arg.c, src/argutil.c, src/compile.c, src/distcc.c, src/dotd.c, src/implicit.c, src/strip.c: Fix bugs in my previous change to handle "-Wp," options: arguments to str_startswith() were in the wrong order, and in one place I had wrongly passed 'argv' instead of 'new_argv'. Move the call to dcc_expand_preprocessor_options() from dcc_get_dotd_info() to gcc_build_somewhere(), so that it is pretty much the first thing done to argv. Not sure if this is really needed, but it seems like a good idea. Fix various memory management problems, including some introduced by moving the call to dcc_expand_preprocessor_options(). One problem was that dcc_find_compiler() was producing a result that was sometimes allocated with malloc() and sometimes not, so the caller couldn't safely deallocate it. I changed dcc_find_compiler to always return a dynamically allocated result. Fix some places where return values were being ignored. Also fix one place where distcc was inconsistenly calling exit() rather than returning a return code. Like my previous change, this one is necessary, but perhaps not sufficient, for building the Linux kernel with distcc-pump. Tested by "make valgrind-check", and by building and installing the debian package and the building Linux 2.6.25 in pump mode using the benchmark.py script. Reviewers 2008-05-18 06:03 Fergus Henderson * packaging/RedHat/init.d/distcc: Fix a bug where "/etc/init.d/distcc stop" was not working when you had installed a new distcc. It wasn't working properly because the call to "start-stop-daemon --stop" used the "--exec /usr/bin/distccd" option, and (perhaps due to a bug in start-stop-daemon?) that option checks /proc//exe against /usr/bin/distccd by comparing inode numbers. Comparing inode numbers doesn't work, because when we install a new distccd, we create a fresh file with a new inode number, so the inode number used by running processes won't match the inode number of /usr/bin/distccd on disk after you've installed a new version. The fix was to remove the "--exec /usr/bin/distccd" option from the call to start-stop-daemon. We're already passing "--name distccd", which is sufficient to indentify the running distccd processes. Reviewers: Craig Silverstein 2008-05-17 16:24 Fergus Henderson * src/compile.c, src/compile.h, src/h_compile.c, test/testdistcc.py: Fix a typo: s/ddc_/dcc_/ Reviewers: Craig Silverstein 2008-05-17 15:18 Nils Klarlund * include_server/basics.py, include_server/include_server.py: Tune gc for 25% speed-up of include processor. Set first parameter of gc.set_threshold to 10000 instead of default 700. See comments in program text. Notes ----- I used a little script to find the include server timings as a function of this parameter. This script executes: "DISTCC_PUMP_INSTALLATION=/tmp/distcc3.0 INCLUDE_SERVER_ARGS='-t --gc_threshold=700' \ /usr/bin/time -p make-dbg -j120 -r -experimental-ld -g0 gws:gws" with various values of gc_threshold. The measurement were done on a four processor system (dual Opterons), loaded with an nxserver process. Files were served through Fuse. gc include server user + sys time setting 700 155.1s 154.0s 164.7s 186.1s 154.3s Mean: 162.8 10000 123.8s 125.4s 120.6s 120.4s 121.0s Mean: 122.2 100000 123.4s 123.3s 122.2s 123.3s 116.5s Mean: 121.7 700 166.5s 156.4s 150.8s 153.4s 155.4s Mean: 156.5 10000 120.7s 142.1s 118.3s 117.7s 119.2s Mean: 123.6 100000 140.3s 117.1s 149.7s 116.7s 141.6s Mean: 123.6 The corresponding elapsed times: 371.0s 363.3s 361.9s 370.8s 369.0s Mean: 367.2 341.8s 346.1s 336.3s 338.3s 340.5s Mean: 340.6 345.9s 338.5s 342.9s 374.4s 340.0s Mean: 348.3 377.4s 379.9s 387.1s 377.4s 373.2s Mean: 379.0 332.1s 337.7s 336.5s 332.2s 314.7s Mean: 330.6 341.1s 334.6s 357.8s 338.5s 352.4s Mean: 344.9 Note that the saving in include server time is around 35s, but the savings in elapsed time is around 44s. These numbers are uncertain. Even so, they strongly indicate that the include server is a signifcant bottleneck. BTW, for comparison with plain distcc: 821.4s 822.0s 842.4s 821.5s 852.0s Mean: 831.9 878.7s 857.2s 860.3s 880.1s 856.0s Mean: 866.5 Thus, pump-mode 2.5X is faster than plain distcc (with the set_threshold = 10000 of this CL). Revievers: Fergus Henderson , Craig Silverstein 2008-05-16 23:12 Craig Silverstein * src/exec.c: There's cygwin-specific code in exec.c, but it seems to assume that when running under cygwin, we'll be using a native windows app to compile. But sometimes we're using a cygwin app (eg /bin/gcc). Trying to use native-windows forking routines with cygwin apps causes a segfault (and takes a while to do it); we need to use unix forking routines there. With this change, when we're asked to spawn a sub-process, we try to guess whether the sup-process app is windows or cygwin, based on its path location (this benefits from using absolute paths): /bin/gcc vs C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\cl.exe or even C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/bin/cl.exe If we decide it's a windows app but are wrong, then the windows-forking code should eventually fail with "file not found"; in that case, we fall through to the normal unix-fork case, to give cygwin a chance to find the binary. I also took the opportunity to clean up some of the code (handles should be initialized to ILLEGAL_HANDLE values, not NULL). I also replaced the crazy permissions the code was asking for before, with normal GENERIC_READ/GENERIC_WRITE. This allows the code to work when the tmpdir is c:\windows, which was failing before. Tested on cygwin using /bin/gcc as the compiler, like so: ./distcc /bin/gcc -c testtmp.c -o testtmp.o where testtmp.c is a simple "hello world" program. I also tested by running 'make check'. With this change, 'make check' passes on cygwin! (Using gcc to do compilations.) Reviewed by Fergus Henderson 2008-05-16 22:00 Fergus Henderson * Makefile.in, src/compile.c: Two bug fixes: - Fix a bug where 'valgrind-check' was invoking 'pump-check', but 'pump-check' was disabling valgrind. - Fix an off-by-one error caught by valgrind. Tested by "make check" and "make valgrind-check". Reviewers: Craig Silverstein 2008-05-16 21:54 Fergus Henderson * src/arg.c, src/distcc.h, src/dotd.c, test/testdistcc.py: Handle '-Wp,-MD,' option. This is needed to build the Linux kernel. Reviewers: Craig Silverstein 2008-05-16 20:46 Fergus Henderson * bench/ProjectDefs.py: In the list of projects to benchmark: - comment out Linux 2.5.51, because it doesn't compile - add Linux 2.6.25. Reviewers: Nils Klarlund, Craig Silverstein 2008-05-16 20:44 Fergus Henderson * bench/actions.py: In the benchmarking script, don't remove the build directories by default, because the log files get stored in the build directories, and it's useful to have the log files around afterwards. Reviewers: Craig Silverstein 2008-05-16 18:08 Craig Silverstein * src/dotd.c: Comment the need to handle gcc's -Wp flag. Reviewed by Fergus Henderson 2008-05-16 01:15 Nils Klarlund * include_server/include_analyzer_test.py: Fix freak name collision on OSs that do not distinguish upper and lowercase in file names. The symbol 'TESTING' is potentially unevaluated according to the overapproximation semantics of the include server. So if this symbol is used in a file name and if 'TESTING' really means 'testing' according to the OS and if in fact 'testing' does exist as file, then there is trouble. Revievewers: Craig Silverstein Testing: make include-server-maintainer-check (on Linux) 2008-05-16 01:10 Nils Klarlund * pump.in: Fix: speed-up the include processor a few times by exporting PYTHONOPTIMIZE. This took a little while: fortunately, the tracing information is dependent on the PYTHONOPTIMIZE setting, so after a diff on the outputs of the gws example before and after, it finally dawned upon me what was wrong. Tested: manually on the gws example with 600 include directories. 2008-05-16 00:59 Nils Klarlund * Makefile.in: Fix removal of 'pump'. Review: Craig Silverstein 2008-05-16 00:52 Nils Klarlund * Makefile.in, pump.in: Fix variable that denotes the source location. (1) It was not documented. I rewrote the documentation for a couple of associated variables. (2) There was no default value. Now, the variable does not need to be set from 'make', so I've removed it from Makefile.in. And, I've made it into a standard shell lowercase variable. Reviewers: Fergus Henderson, Craig Silverstein Tests: (1) make distcheck (2) Running the pump script out of the build directory. 2008-05-15 21:45 Craig Silverstein * find_c_extension.sh, test/testdistcc.py: Modifications to the pump and test framework for cygwin. 1) find_c_extension looks for .dll files in addition to .so files. 2) Likewise, testdistcc.py has to check whether binary names might end in .exe. Usually that doesn't matter, but sometimes (eg when running cp on them), it does. 3) testdistcc.py adds a routine to detect PE binaries. These, like dwarf binaries, do not always give reproducible output on the same input, so take that into account in the gdb tests. 4) In the lsdistcc test, we assumed that when the ping failed, 127.0.0.2 isn't available. But it's also possible ping is just broken (or different) on that machine. So in the failed-ping case, we no longer make any assumption about 127.0.0.2, one way or the other. Tested by running 'make check' on cygwin. Most every test passes! Reviewed by Fergus Henderson 2008-05-15 20:11 Nils Klarlund * Makefile.in: Add 'pump' to 'all' target. Add 'rm pump' to 'clean' target. - 'pump' is a dependency of 'install'. - 'include_server' is a dependency of 'all. So I propose that 'pump' should be a dependency of 'all'. Reviewers: Fergus Henderson Test: make distcheck 2008-05-15 19:39 Craig Silverstein * Makefile.in, configure.ac, pump.in: Instead of a hack to figure out if pump is installed or not -- one that fails on macs with python 2.5 (at least) because of weirdnesses with distutils installation on that platform -- just rewrite pump at install-time to indicate it's installed. We take the opportunity to tell pump where the installed include_server.py is, because it needs to know, and we know that during 'make install'. Tested by running 'make distcheck' on linux (ubuntu) with python 2.4, and mac 10.5 with python 2.5. I also tested by running, on the linux machine, ./configure --prefix=/tmp/distcc.install && make install && make DISTCC_INSTALLATION=/tmp/distcc.install/bin installcheck Furthermore, I manually inspected the installed pump file after that to make sure it looked correct. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-15 02:53 Craig Silverstein * include_server/compiler_defaults.py: Add a comment. From Nils Klarlund : "Assume that: (1) 'gcc' is a link to 'distcc' earlier on PATH than the real gcc. (2) gcc is invoked; in fact that invokes distcc, which will rewrite the PATH in src/climasq.c before invoking 'gcc' again. That will make calls by distcc such as 'gcc -E' for preprocessing work OK, but the include processor will in fact be calling the 'distcc' as 'gcc' again! But because the input argument is an I/O redirection, distcc will then correctly call 'gcc'. In args.c it fails to recognize an input file." 2008-05-15 02:40 Craig Silverstein * src/access.c, src/access.h, src/arg.c, src/backoff.c, src/bulk.c, src/bulk.h, src/cleanup.c, src/climasq.c, src/clinet.c, src/clinet.h, src/clirpc.c, src/compile.h, src/compress.c, src/cpp.c, src/daemon.c, src/daemon.h, src/distcc.c, src/distcc.h, src/dopt.c, src/dopt.h, src/dparent.c, src/dsignal.c, src/exec.h, src/exitcode.h, src/h_hosts.c, src/h_parsemask.c, src/help.c, src/history.c, src/hostfile.c, src/hosts.c, src/hosts.h, src/implicit.c, src/implicit.h, src/io.c, src/loadfile.c, src/lock.c, src/lock.h, src/mon-gnome.c, src/mon-notify.c, src/mon-text.c, src/mon.c, src/mon.h, src/ncpus.c, src/netutil.c, src/netutil.h, src/prefork.c, src/pump.c, src/remote.c, src/renderer.c, src/renderer.h, src/rpc.c, src/rpc.h, src/safeguard.c, src/sendfile.c, src/serve.c, src/setuid.c, src/srvnet.c, src/srvnet.h, src/srvrpc.c, src/ssh.c, src/state.c, src/state.h, src/stats.c, src/stats.h, src/strip.c, src/tempfile.c, src/timefile.c, src/timefile.h, src/traceenv.c, src/types.h, src/util.c, src/util.h, src/where.c, src/where.h: Add a consistent emacs-variable header to all source files. This affects the way emacs users will see these files, when visiting them in emacs. In particular, tabs will show up as 4 spaces, which is (clearly) the setting the original distcc author used when writing the code. We also set an emacs variable to never insert new tabs, but use spaces instead. This will help stop the problem we have now with mixed tabs and spaces. In a future cleanup, we may replace all tabs with 4 spaces, and make other whitespace improvements. The final new variable set, is to set line-wrapping at 78 chars. Personally, I would have made it more like 72, but some existing files already had the 78 limit, so I just do that everywhere, to be consistent. Reviewed by Fergus Henderson 2008-05-15 01:58 Craig Silverstein * test/testdistcc.py: The gdb tests was making two assumptions that the input was ELF, which was failing on OS X (Which uses Mach-O). One is that two identical link commands always produce the same output, which is not true for mach-o. The other is just a test of ELF-specific code, without an "iself" check. Now I check the object-file type and run the appropriate test, based on the type, in each case. Tested by running 'make check' on linux (ubuntu 6) and OS X (10.5). Reviewed by Fergus Henderson 2008-05-15 01:36 Craig Silverstein * include_server/compiler_defaults.py: When running gcc -v, we were clearing the environment too aggressively: in particular, we were clearing $PATH, which is needed to find gcc when it's in an unusual location. Now we clear everything but $PATH. Tested by running 'make include-server-maintainer-check' on solaris x86, which has gcc outside the standard path, and on linux (ubuntu), which does not. Reviewed by Fergus Henderson 2008-05-15 01:15 Craig Silverstein * src/tempfile.c: The tmpdir-creation routine has an (undocumented) invariant that the tmpdir should not end in a slash -- at least, inside distcc, you see code like this: snprintf("%s/%s", tmpdir, filename) On the other hand, windows's routine to create a tempdir guarantees it will end with a slash. I'm not sure it really matters, but get rid of the slash in that case. That way we don't have to worry about how filenames are interpreted (since // does have a special meaning for filenames in windows, though probably not in a way this code could generate before; still, no harm in normalizing to one slash). Tested by running 'make check' on cygwin. Reviewed by Fergus Henderson 2008-05-14 21:01 Craig Silverstein * test/comfychair.py: Replace an os.system calls ('rm -rf') with python (shutil.rmtree). This should improve portability. It seems to help on cygwin, for instance. I also got rid of anotehr os.system call that was redundant: it did a "mkdir -p foo" after the previous line had done a "mkdir -p foo/bar". Tested by running 'make check on linux (ubuntu) and cygwin. Reviewed by Fergus Henderson 2008-05-14 19:48 Craig Silverstein * Makefile.in: 1) Fix up a PATH= assignment that would fail if builddir had spaces in it (because the output of `cd "$builddir" && pwd` was not being quoted). As a bonus, make the PATH= fit on one line, which makes some shells happier. 2) Fixed up some install targets. On some systems, tar without -f reads from stdin, but that's non-standard (it should read from some tape-drive device in /dev in that case). Add -f- to $(TAR) in that case, which should work everywhere. 3) cp -a isn't supported on all systems. I checked what automake does, and it emits cp -pR, so that's what I do too. We don't have any internal symlinks that I need to worry about -P or anything like that. Tested by running 'make installcheck' on a freebsd 6.0 system. Reviewed by Fergus Henderson 2008-05-14 19:22 Craig Silverstein * include_server/include_server_test.py: Show more data when an assert fails, to help in debugging. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-14 18:59 Craig Silverstein * m4/acx_pthread.m4: Update acx_pthread to the latest version we use internally. This is like the one on the cryp.to autoconf repository website, but with the avahi patches added in to deal with some compiler quirks. However, these patches have been rewritten internally within google to make them more robust. In particular, the new code now works with cygwin, which it previously didn't (resulting in the spurious error: "Unable to determine how to use pthreads with shared libraries"). Tested by running configure on cygwin. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-14 14:26 Nils Klarlund * configure.ac, include_server/include_server_test.py: Make distcc 3.0 compatible with Python 2.5. Tests: I made PATH=$PATH:/usr/python/bin (where python2.5 resides on my machine). I ran autogen and reconfigured. Then I did: make include-server-maintainer-check make pump-maintainer-check and I made sure that -Is now are set according to Python2.5. 2008-05-14 08:03 Craig Silverstein * pump.in: Ick. On some systems test is in /bin, and in others /usr/bin. Now figure out where it is before running it, and fall back on the shell test if no binary can be found. Tested by running 'make check' on a FreeBSD machine (/bin/test) and linux (/usr/bin/test). Reviewed by Fergus Henderson 2008-05-14 07:28 Craig Silverstein * src/compile.c: getc returns an int, not a char. We're checking whether a char == EOF, which isn't kosher, and on systems where -funsigned-char is true, dangerous. Change the type of the var to an int. Tested by running on linux (ubuntu) and on linux ppc (debian), the latter of which complained at compile time. Reviewed by Fergus Henderson 2008-05-14 07:15 Fergus Henderson * packaging/RedHat/init.d/distcc: Fix problems where distcc's init script was using the wrong exit status and giving misleading messages as a result. Reviewers: Craig Silverstein 2008-05-14 07:14 Fergus Henderson * packaging/RedHat/conf/commands.allow.sh: Increase the set of commands allowed by default: allow cc, c++, c89, c99, and g++, in addition to gcc. Reviewers: Craig Silverstein 2008-05-14 02:27 Craig Silverstein * pump.in: Fix a test to work on solaris sh. Tested by running 'make check' on linux (ubuntu) and solaris 10 x86. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-14 01:00 Nils Klarlund * include_server/basics.py, include_server/basics_test.py, include_server/include_server.py: Finish refactoring and add tests. Move _CleanOutClientRoot and _CleanOutOthers to the ClientRootKeeper package in basics. Replace _RemoveDirectoryTree with shutil function. Add tests to see that directories are created and deleted. Add a couple of title headers to basics.py. Remove a couple of now irrelevant comments. Tests: make pump-maintainer-check make include-server-maintainer-check Reviewer: Craig Silverstein 2008-05-14 00:42 Craig Silverstein * include_server/setup.py: Include snprintf.c in the source-list for the python extension. This is needed on systems that don't define asprintf/etc on their own. Tested by running 'make check' on a linux ubuntu machine and on a solaris machine. Reviewed by Fergus Henderson 2008-05-14 00:31 Craig Silverstein * Makefile.in, find_c_extension.sh, pump.in: A few more cleanups: 1) No ! outside of a 'test' (sh-compatibility). 2) grep >/dev/null instead of grep -q (solaris portability). 3) Improved the quote hygenie a little. 4) prepend to PYTHONPATH instead of overriding it. Tested by running on a solaris machine, and on a machine where PYTHONPATH is needed to locate the python distribution (which is not in the standard location). Reviewed by Fergus Henderson 2008-05-13 23:53 Craig Silverstein * test/testdistcc.py: On some systems (FreeBSD), it looks like connect() can return EINVAL. This isn't documented, but there's some talk about it on the web, eg http://mail-index.netbsd.org/netbsd-bugs/2003/08/18/0002.html It looks like the cause is that the first connect fails for whatever reason, and then subsequent ones fail with EINVAL. I've detected that in the NoDetachDaemon_Case, both on FreeBSD and OS X machines. The symptom is that sock.connect_ex(('127.0.0.1', self.server_port) continually returns EINVAL, and no amount of time will fix things. I'm not exactly sure why, but I figure one possible problem is the connect is happening before distccd has started listening, and that causes problems. So I put in a bit of a delay to give distccd time to start up. I figure it can't hurt, and may well help. Tested by running 'make check' on a ubuntu machine (not subject to this problem) and a freebsd machine (which sometimes is). It certainly didn't hurt, though I can't tell if it solved the problem for good. Reviewed by Fergus Henderson 2008-05-13 23:36 Craig Silverstein * include_server/setup.py: I found a machine whose python was compiled with _FORTIFY_SOURCE, which -- on linux FC5 at least -- gives warnings (which we turn into errors via -Werror) on distcc code for libc functions where we ignore the return value. Unfortunately, setup.py always uses the same flags that python was compiled with on the local machine, so _FORTIFY_SOURCE is always set when compiling distcc extensions via setup.py, and that compilation fails. Without getting into a philosophical debate about the merits of the warn-unused warnings, we'd rather the code compile, so I turn off _FORTIFY_SOURCE when it exists. Tested by running 'make check' on a goobuntu machine (no _FORTIFY_SOURCE) and an FC5 machine (with _FORTIFY_SOURCE). Reviewed by Fergus Henderson 2008-05-13 20:33 Nils Klarlund * src/compile.c: Fix buglet: insert (void) in call of strcpy to avoid gcc 4.1.1. making trouble. gcc 4.1.1 with glibc 2.2.2. insists that the return value must be used. That appears to be a bug in gcc. Reviewers: Fergus Henderson, Craig Silverstein. 2008-05-13 18:59 Craig Silverstein * test/testdistcc.py: Two changes to robustify the unittests: 1) Don't try to run the gdb tests on machines that don't have gdb installed. Likewise, don't try to run the implicit-cc test on a machine that doesn't have cc installed (it happens! Sometimes there's only gcc.) 2) Raise the file-descriptor limit if we can. Mac OS X likes to keep the limit at 256, but some of these tests need more. Tested by running 'make check' on linux and mac os x 10.5. On linux, I ran on both a machine with gdb installed, and one without. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-13 18:40 Craig Silverstein * src/exec.c: We were logging a char* that could be NULL. With glibc, the printf would just print "(null)", but on solaris libc it would segfault. Explicitly test that case now. Tested by running 'make check' on linux and solaris x86. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-13 17:49 Nils Klarlund * include_server/basics.py, include_server/basics_test.py, include_server/compress_files.py, include_server/include_analyzer.py, include_server/include_analyzer_memoizing_node.py, include_server/include_analyzer_memoizing_node_test.py, include_server/include_analyzer_test.py, include_server/include_server.py, include_server/include_server_test.py, include_server/parse_file_test.py: Clean-up the handling of directories for storing compressed files. The code was lacked encapsulation and proper object-orientation. (I wrote it -- it had started out much simpler.) For example, key parameteres were communicated through file name patterns expressed in file names on disk. These patterns were then inferred from reading file names. Now the patterns are properly abstracted away in a class. There should be no semantic changes. Testing: make include-server-maintainer-check make pump-maintainer-check DISTCC_CLIENT_TMP='/tmp' make pump-maintainer-check The latter test exercices the padding gymnastics. 2008-05-13 07:02 Craig Silverstein * pump.in: Rewrite 'pump' to remove bash-isms. This should now work with standard sh. This involved the following changes: 1) `cmd` instead of $(cmd). 2) [ -n "$VAR" ] instead of [ "$VAR" ] 3) "Here document" (< * test/testdistcc.py: printenv doesn't exist on all systems. 'env' does, and does the same thing as printenv when no arguments are given, so just use env instead of printenv. Tested by running 'make check' on a linux machine (which has both env and printenv). To be reviewed by Fergus Henderson 2008-05-13 05:28 Craig Silverstein * include_server/include_server.py: Be more informative on an assert. Reviewed by Fergus Henderson and Nils Klarlund 2008-05-13 01:49 Craig Silverstein * Makefile.in, configure.ac: In the non-included popt case, POPT_INCLUDES was the empty string, leading to a compile command that had -I"" in it. Who knows what that means? Now the -I is part of POPT_INCLUDES, so when it's absent we don't add anything to CPPFLAGS. Tested on a machine where POPT_INCLUDES is not empty and one where it is. Reviewed by Nils Klarlund 2008-05-12 23:53 Fergus Henderson * bench/benchmark.py: Fix a typo in my previous change: s/parse_opt_compiler/parse_compiler_opt/ 2008-05-12 23:07 Fergus Henderson * include_server/parse_command.py, test/testdistcc.py: Handle gcc's "-MF" option in the include server. This option only affects the name of the ".d" file, not the include closure, so the include server doesn't need to do anything for this option; the actual handling of this option in distcc is done by the distcc client, which already handles it correctly. This change just stops the include server from throwing an exception whenever '-MF' is encountered. Reviewers: Nils Klarlund 2008-05-12 23:02 Fergus Henderson * bench/benchmark.py, bench/compiler.py: Add new options '--cc' and '--cxx' for specifying the paths to use for the C and C++ compilers. Also, update the help message to document the new format for the --compiler option. Reviewers: Craig Silverstein 2008-05-12 20:18 Nils Klarlund * include_server/c_extensions/distcc_pump_c_extensions_module.c: Fix call of 'realpath' to work on FreeBSD. Also fix memory leak. Reviewer: Craig Silverstein, Fergus Henderson. Tests: make pump-maintainer-check make include-server-maintainer-check 2008-05-12 19:11 Fergus Henderson * bench/Build.py, bench/ProjectDefs.py, bench/Summary.py, bench/buildutil.py, bench/compiler.py, bench/statistics.py: Add support for pump mode to the benchmarking scripts. Also add support for setting the number of hosts to use. Fix division by zero error that occurred when running benchmark script with the "-a" option. Fix broken URL for GNU hello package. Reviewers: Craig Silverstein, Nils Klarlund 2008-05-12 18:32 Nils Klarlund * pump.in: Fix 'ps' invocation to be more FreeBSD friendly. Reviewers: Fergus Henderson, Craig Silverstein Tests: make pump-maintainer-check 2008-05-12 16:19 Nils Klarlund * include_server/include_analyzer_test.py: Fix include server test so that it passes on system w/o /dev/shm. Reviewers: Craig Silverstein, Fergus Henderson Tests: make include-server-maintainer-check 2008-05-12 16:15 Nils Klarlund * pump.in: Get rid of 'readlink -f', which is a Gnuism. The purpose of the readlink -f was to give the absolute path of the installation; that happens to reveal the installation date given the way we set up distcc-pump at Google. But this does not work under FreeBSD. The installation information can be communicated in different ways (for example by explicit actions of the build system). Reviewers: Fergus Henderson, Craig Silverstein 2008-05-11 19:06 Craig Silverstein * test/testdistcc.py: Annoyingly, different versions of gcc are inconsistent in how they treat a non-existent #include file when invoked with "-MMD": some versions treat it as an error (rc 1), some as a warning (rc 0). When distcc is responsible for preprocessing (_server_options includes 'cpp'), we need to figure out which our gcc does, in order to verify distcc is doing the same thing. Before this change, we just hard-coded in one sort of gcc behavior (that it always warns). This change actually tries gcc out to see which it does, to make sure distcc does the same. Tested by running 'make pump-maintainer-check' on both Linux gcc 4.0.3 (which warns) and FreeBSD gcc 3.4.4 (which errors). Reviewed by Fergus Henderson 2008-05-10 06:54 Craig Silverstein * src/sendfile.c: No matter what the reason, if we can't use sendfile() but it's still safe to fall back on readwrite(), do that. Before we only did this for certain errors, but we might as well do it for any error we don't expect to be able to recover from. Tested by running on mac os x 10.4, which has a problem with sendfile failing sometimes. The relevant test succeeds after this patch. Reviewed by Fergus Henderson 2008-05-10 00:58 Nils Klarlund * Makefile.in: Double-quote unprotected directory reference. Reviewers: csilvers Tests: make distcheck 2008-05-10 00:56 Nils Klarlund * Makefile.in: Cosmetic clean-up of Makefile.in. -- Put a @ in front of a comment shell command (it shouldn't be printed). It is the only comment in the action part of a build rule in the whole Makefile. In Emacs, this comment is flagged as a syntax issue. -- Group all .PHONYs at beginning of section. Tests: make distcheck Reviewers: fergus, csilvers 2008-05-09 23:19 Nils Klarlund * configure.ac, pump.in: Make the identification of Python 'binaries' more robust. Use the distutil function that generates the library name for locating the Python stuff in an installation. Reviewers: Fergus Henderson, Craig Silverstein Test: make distcheck 2008-05-09 23:17 Nils Klarlund * test/testdistcc.py: Speed-up integration/systems tests. 2008-05-09 21:02 Fergus Henderson * Makefile.in: Add "daemon-installcheck" target. This tests that the distcc daemon is running, and that it and distcc and the pump script have been installed correctly, by compiling a simple hello world program with distcc and distcc-pump. 2008-05-09 20:36 Craig Silverstein * src/lsdistcc.c: A whitespace-only change. Got rid of spaces at the end of lines, and also of tabs. Went through to normalize indents and so forth (some functions were using 4-space indents, and others were using 8-space indents, which were probably actually originally written as tabs on a system with 4-space tabs). diff -w shows no diffs; this is really whitespace-only. Tested by making sure the file still compiles. 2008-05-09 20:33 Craig Silverstein * src/lsdistcc.c: Modify lsdistcc to reduce the number of concurrent fd's it tries to open, when the system doesn't support a lot of concurrent fd's (which we see by default in freebsd). It uses getrlimit and setrlimit to get as many fd's as it can, and then stick to that number. I modified the main search loop to work in stages, where each stage uses at most maxfd's fd's. In the common -- almost universal -- case there will only need to be one stage, and the code will behave the same as before. In some limited environments, you might see multiple stages. You can reproduce this artificially via code like this: $ ulimit -SH -n 32 # in sh-like shells $ ./lsdistcc Tested by running manually on a configuration that gives 141 hosts. Tested both with many fd's available, and arbitrarily limited to 32 (via the ulimit command above). Reviewed by Nils Klarlund 2008-05-09 19:45 Fergus Henderson * packaging/RedHat/init.d/distcc: Fix a bug in my changes to add 'commands.allow.sh' that broke the Debian distribution. There was a spurious assignment to CMDLIST. CMDLIST used for the output of /etc/distcc/commands.allow.sh; it is supposed to be set to /var/state/distcc/commands.allow. But due to the spurious assignment, CMDLIST was being set to /etc/distcc/commands.allow.sh, causing the script to overwrite itself. Reviewers: Craig Silverstein 2008-05-09 19:24 Nils Klarlund * packaging/RedHat/rpm.spec: Fix so that include server record can be found. 2008-05-09 19:23 Fergus Henderson * src/stringmap.c: Fix what appears to be a bug in the handling of DISTCC_CMDLIST. The documentation is not very clear, but distccd was documented as matching against the last DISTCC_CMDLIST_NUMWORDS words of the command, where I think by words they meant directory components. For example, if the file refered to by DISTCC_CMDLIST contains the line "/usr/bin/i686-blah-blah/gcc", and DISTCC_CMDLIST_NUMWORDS=2, only commands which end in "/i686-blah-blah/gcc" would be matched. The bug is that a command "i686-blah-blah/gcc" should be considered to match. Likewise, if DISTCC_CMDLIST contains the line "/usr/bin/gcc", and DISTCC_CMDLIST_NUMWORDS is 1 (or not set), then plain "gcc" should be allowed to match. Reviewers: Dan Kegel, Craig Silverstein 2008-05-09 18:15 Nils Klarlund * Makefile.in, configure.ac, popt/system.h, src/access.c, src/arg.c, src/argutil.c, src/backoff.c, src/bulk.c, src/cleanup.c, src/climasq.c, src/clinet.c, src/clirpc.c, src/compile.c, src/compress.c, src/cpp.c, src/daemon.c, src/distcc.c, src/dopt.c, src/dparent.c, src/dsignal.c, src/exec.c, src/filename.c, src/fix_debug_info.c, src/gcc-id.c, src/h_argvtostr.c, src/h_compile.c, src/h_dotd.c, src/h_exten.c, src/h_hosts.c, src/h_issource.c, src/h_parsemask.c, src/h_sa2str.c, src/h_scanargs.c, src/h_strip.c, src/help.c, src/history.c, src/hostfile.c, src/hosts.c, src/implicit.c, src/io.c, src/loadfile.c, src/lock.c, src/mon-gnome.c, src/mon-notify.c, src/mon-text.c, src/mon.c, src/ncpus.c, src/netutil.c, src/prefork.c, src/pump.c, src/remote.c, src/renderer.c, src/rpc.c, src/safeguard.c, src/sendfile.c, src/serve.c, src/setuid.c, src/snprintf.c, src/srvnet.c, src/srvrpc.c, src/ssh.c, src/state.c, src/stats.c, src/strip.c, src/tempfile.c, src/timefile.c, src/trace.c, src/traceenv.c, src/util.c, src/where.c, src/zeroconf-reg.c, src/zeroconf.c: Make handling of config.h sound. (1) Correct order of -Is in Makefile. (2) remove unnessary PATH modification in configure.ac (this is fergus's suggestion -- hopefully this will do, this replaces a circumvention mechanism I had originally concocted. (3) Fix place of the include of popt in CPPFLAGS. (4) Convert quoted includes of config.h to angle bracket includes so that the build version, not the source version, of this file is picked up. The order of -Is in the build system is wrong: it contradicts the VPATH mechanism. This means that builds in a build directory different from that of the source (distribution) directory will find wrong files even after the hapless developer has issued only a 'configure' command in the source directory (but not actually 'made' any thing there). For in that case, the src/config.h will be generated in the source directory and this will be the file picked in the build directory even if that directory has it's own src/config.h. This can lead to wrong builds and it can be hard to diagnose the problem. Currently, this what CPPFLAGS end up being (as found in the generated Makefile): CPPFLAGS = -DHAVE_CONFIG_H -D_GNU_SOURCE \ -I../distcc/popt -I../distcc/src \ ${DIR_DEFS} \ -Isrc -Ilzo \ -I"$(srcdir)/src" -I"$(srcdir)/lzo" \ Here my source dir was ../distcc. The presence of '-I../distcc/popt' in front of -Isrc is the exact opposite of the semantics of VPATH mechanism, which looks for files in the build directory, then in the source directory. Also, note the remarks in: http://www.gnu.org/software/autoconf/manual/autoconf.html#Configuration-Headers (they do not quite correctly discuss the search path, btw). TESTING: I verified that with a corrupted config.h file in the source directory, building now succeeds. Also: make distcheck (it fails the same place as before: this is corrected in another change of mine --- I'll verify that with that change in place, this change makes 'make distcheck' succeed.) REVIEWERS: Fergus Henderson, Craig Silverstein 2008-05-09 18:00 Nils Klarlund * Makefile.in, find_c_extension.sh, include_server/setup.py, pump.in: Rewrite setup.py and associated logic to fix multiple build problems. The recent distcheck revealed that paths were set incorrectly for the setup.py script. Also, as I dug deeper, it turned out that built files were placed in the src directory (thanks to os.path.join I found in the distutil's source code, that trips up the location if relative paths contains too many '..'s.). [The distccheck revealed this!] I didn't like either that setup was run in the source directory and not from the build directory (that's asking for trouble). I did't like either that the search path, the list of includes, in setup.py was handcoded and not simply that of CPPFLAGS. Finally, I was confused by _builddir being another build directory under $(buildir). I renamed the former _include_server to better explain its role. So, I rewrote most of setup.py (correcting some of the documentation strings along the way). Also, I partly removed the 'jumping through the hoops' gymnastics from the Makefile. TESTING: 'make distcheck' REVIEWERS: csilvers, fergus 2008-05-08 23:18 Fergus Henderson * doc/web/compared.html, doc/web/compilers.html, doc/web/faq.html, doc/web/security.html: Update web pages to correct statements that are no longer accurate for distcc 3.0. Reviewers: Craig Silverstein 2008-05-08 19:41 Fergus Henderson * doc/example/README, doc/example/default, doc/example/hosts.allow, doc/example/logrotate, doc/example/services, doc/example/xinetd, packaging/RedHat/logrotate.d/distcc, packaging/RedHat/rpm.spec: Revise the doc/example directory: - Add README file to the doc/example directory. - Add files in doc/example for every system configuration file installed or modified by the RPM installation script (rpm.spec). - Update some comments in rpm.spec. - Some whitespace changes to doc/example/logrotate and packaging/RedHat/logrotate.d/distcc to make those two files match. - Copy warning from packaging/RedHat/xinetd.d/distcc to doc/examples/xinetd. Reviewers: Craig Silverstein 2008-05-08 16:33 Nils Klarlund * include_server/basics.py: Make this file mostly conformant with gpylint. There should be no semantic consequences. TESTS: make distcheck REVIEWER: Fergus Henderson 2008-05-07 23:50 Craig Silverstein * NEWS, doc/web/compared.html, doc/web/compilers.html, doc/web/faq.html, doc/web/index.html, doc/web/results.html, doc/web/scenarios.html, doc/web/security.html: Change NEWS links to point to the actual NEWS file, rather than the svn history-log for the NEWS file. Also changed the NEWS file itself to use ^L instead of a ^ + L, for the top instance. 2008-05-07 23:03 Fergus Henderson * man/pump.1: Add a man page for the "pump" script. The contents are similar to the output of "pump --help", but with a bit more mark-up, and with additional sections "INVOKING LSDISTCC", "BUGS", "AUTHORS", "LICENSE", and "SEE ALSO". Reviewers: Craig Silverstein, Nils Klarlund. 2008-05-07 18:54 Craig Silverstein * test/testdistcc.py: The DaemonBadPort test case was not passing in --allow, which is a new flag required by distcc 3 (all other tests had been modified to add it). We never noticed until now because the distccd command is *expected* to fail with a "bad arguments" error code -- though the bad argument is supposed to be --port, not --allow. So this change gets this test actually testing what it's supposed to, again. Reviewed by Fergus Henderson 2008-05-07 18:21 Fergus Henderson * include_server/include_server.py: Insert "Usage: " at the start of the usage message for the include server. 2008-05-07 18:01 Craig Silverstein * doc/web, doc/web/compared.html, doc/web/compilers.html, doc/web/distcc-green.css, doc/web/distcc-lca-2004.html, doc/web/distcc-lca-2004.pdf, doc/web/distcc-lca2003.ps.gz, doc/web/distccmon-gnome-2003-09-23-01.png, doc/web/faq.html, doc/web/index.html, doc/web/results.html, doc/web/scenarios.html, doc/web/security.html: Add the documentation files, as downloaded from distcc.samba.org. I then modified the files slightly, mostly by deleting content that referred to files on the samba.org server and replacing them by files (or, usually, links) to Google Code. For instance, the 'source' link now points to the Google Code svn page for distcc, rather than a page holding tarball information. Likewise, the News page now just points to the svn trunk's NEWS file. For the record, here's email from Martin Pool OK-ing this move/copy: --- From: Martin Pool Date: Sun, May 4, 2008 at 9:31 PM Subject: Re: sources for distcc web site To: Fergus Henderson > Hi, The sources are at You are welcome to either work from these or scrape the web site. You can make any reasonable use of the text in making a new web site. -- Martin > --- Reviewed by Fergus Henderson 2008-05-05 15:31 Fergus Henderson * man/distcc.1, man/distccd.1: Document Zeroconf support: the "--zeroconf" option to distccd and the "+zeroconf" entry in the distcc hosts list. Reviewers: Craig Silverstein, Nils Klarlund. 2008-05-05 15:26 Fergus Henderson * man/distcc.1: Document the -j and --show-hosts options in the man page. Also mention that pump mode requires release 3.0 or later, and a few other minor corrections. 2008-05-02 23:07 Fergus Henderson * test/testdistcc.py: Change Lsdistcc_Case to work on hosts for which 127.0.0.2 is not a loopback address. Tested by "(g)make TESTNAME=Lsdistcc_Case single-test" on both Linux and FreeBSD. Reviewers: Craig Silverstein, Nils Klarlund. 2008-05-02 21:11 Fergus Henderson * test/testdistcc.py: Fix EmptySource_Case test so that it passes with gcc 3.4.x. Tested by "(g)make SINGLETEST=EmptySource_Case single-test" on both FreeBSD (gcc 3.4.4) and Linux (gcc 4.0.3). Reviewers: Craig Silverstein 2008-05-02 19:54 Nils Klarlund * configure.ac, lzo/.stamp-conf.in, popt/.stamp-conf.in: Explain stamp files and remove unneeded @src_dir@ (which was misspelled?). TESTED: make distcheck REVIEWED: Craig Silverstein, Fergus Henderson 2008-05-02 19:09 Craig Silverstein * Makefile.in, configure.ac: For machines without python installed, before this change we'd check for that case, but still give an error rc in that case, so the make would fail. Now I make sure we don't fail just because we don't have python installed. Also, some machines (solaris 10) don't have a grep with -q, so just use >/dev/null insteasd. Third, we had left out a file to add to the tarball: ontest.py. Fourth, 'make distcheck' fails a bit on the pump-installcheck. I've addressed some of the problems, but others remain. Finally -- and this is the bulk of the change, line-count wise, I added quotes around all variables, so we do the right thing when variables have spaces or other shell-meaningful characters in them, as indeed they often do on windows machines. Tested by running 'make check' on various architectures, including solaris 10 x86 and cygwin. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-02 18:49 Fergus Henderson * src/sendfile.c: Treat ENOTSOCK errors from sendfile() the same way that we treat ENONSYS and EINVAL errors: fall back to using read() and write(). This fixes the failure of SyntaxError_Case and MissingCompiler_Case on FreeBSD. Tested by "make check". Reviewers: Craig Silverstein 2008-05-02 18:17 Nils Klarlund * test/testdistcc.py: Remove .d test case for which gcc stumbles on Mac OS. 2008-05-02 18:11 Craig Silverstein * src/distcc.h: This adds an #two that's technically needed to compile. Cygwin happened to notice this was missing. Tested by compiling (via 'make') on cygwin and ubuntu. Reviewed by Fergus Henderson 2008-05-02 18:10 Craig Silverstein * test/testdistcc.py: Four improvements to the test framework: 1) While pump-mode requires python 2.4, the test framework is designed to work with python 2.2 and later. A few non-2.2 features have snuck in though. I replaced them with 2.2-compatible code. 2) The test system used the --ex flag to gdb, which is only supported in more recent gdb's. I've changed the code to use --command instead, which is supported in old gdb's as well. I also added a workaround for a buggy error-message that gdb sometimes emits. See http://www.archlinux.org/pipermail/arch/2007-January/013366.html 3) I fixed a regexp for the gcc-options case, to handle correctly systems that don't name gcc "gcc" (for instance, they might name it powerpc-apple-darwin8-gcc-4.0.1). 4) Use shell quoting, when appropriate, to deal with paths that have spaces (eg on windows) or other weird characters in them. Tested by running 'make maintainer-check' on a variety of architectures, including os x and cygwin. The tests successfully run on all of them (though not all tests successfully pass yet...) Reviewed by Fergus Henderson and Nils Klarlund 2008-05-02 00:10 Craig Silverstein * Makefile.in: Small wording change, suggested by Nils Klarlund 2008-05-01 23:52 Craig Silverstein * configure.ac: This test was broken before: I needed to escape [ and ] from m4. Tested by running configure on a machine with python 2.2 installed. Reviewed by Fergus Henderson 2008-05-01 23:51 Craig Silverstein * Makefile.in: Previously, 'make check' was a noop because we do not require python to be installed for distcc, but the tests require python. Therefore, to run the tests you had to run 'make maintainer-check' instead (since maintainers of distcc *do* have to have python installed). Now, I have 'make check' check if python is installed. If so, it runs the tests. Otherwise, it prints a message and exits. Tested by running 'make check' and 'make installcheck' manually, on systems with the various pythons installed as well as a few without. Code reviewed by Fergus Henderson 2008-05-01 23:02 Craig Silverstein * Makefile.in, configure.ac: Include-server requires python 2.4 or higher, but the test framework only requires python 2.2. Check for both, so for folks with python 2.2 or python 2.3, they can at least run the tests, even if they can't install the include-server. 2008-05-01 00:58 Nils Klarlund * include_server/c_extensions_test.py: Clean up Python code. -- Do TODOs. -- Heed most pylint warnings. 2008-04-30 22:46 Nils Klarlund * Makefile.in, find_c_extension.sh, include_server/c_extensions_test.py, pump.in: Make install-checks work and a lot of clean-up in regards to the 'checking' targets. - Remove temporary installation for include server tests. The current scheme doesn't make too much sense: when testing a real installation, the include server is tested in the separate temporary installation. Instead, we propose to make the installation tests run only the regression tests in the 'test' directory, unpumped and pumped. The include server is now tested as part of maintainer-check only, but run out of the source directory, except for the C extension module. - The maintainer-check and the maintainer-install-check now run the integration test (test/testdistcc.py) also in pump mode. - A new script, find_c_extension.sh, is added; it finds the location of the shared library. It is used for both running the include server tests and the regression tests out of the built (not installed) version of the software. It was cut of the 'pump' script, which now has been simplified. - Reorganize the order of affected targets. Introduce '###############...' as separator between sections of Makefile in a more consistent way. Make each section consistently declare all the phony targets at the beginning of the section. - Introduce DISTCC_INSTALLATION variable to account for the precise location of the tested binaries in an installation. - Add verify-binaries-installcheck target to ensure that binaries are in this location. - Also, this target reports the location to users: Make sure all paths below are where you expect them to be: ********************************************************** /home/klarlund/svn-distcc/mybin/installation/bin/distcc /home/klarlund/svn-distcc/mybin/installation/bin/distccd /home/klarlund/svn-distcc/mybin/installation/bin/distccmon-text /home/klarlund/svn-distcc/mybin/installation/bin/lsdistcc ********************************************************** - Absolutize a couple of relative directory references before they are passed to scripts, because otherwise things won't work with the disciplined approach to DISTCC_INSTALLATION. - Change a randomly generated filename so that it resides in /tmp (in c_extensions_test.py) and not inside the build directory tree. Fix up logic for filenaming to be more secure. This makes 'make distcheck' pass w/o permission problems. Also, delete the temporary file and directory when test passes. - Make include-server-maintainer-check remove the .out file when test passes. This makes 'make distcheck' pass the final test of the clean-out. - Remove the 'Filtering' of the c_extensions_test output. This filtering was necessary in a previous version that printed all output to stdout to reduce user confusion. But now the test results go to intermediate files. This change was forced by the removal of the .out files (above). REVIEWED: fergus, csilvers. TESTS: make distcheck make maintainer-installcheck make include-server-maintainer-check make maintainer-check 2008-04-28 21:52 Craig Silverstein * src/sendfile.c: OS X added sendfile support in 10.5, so add this case to sendfile.c. Looking at the man pages, it looks like os x sendfile is pretty much the same as BSD's, so I copied much of the code from the existing BSD case. Tested by ensuring the code compiles and links on os x 10.5. No attempt to see if it runs correctly, though. Reviewed by Fergus Henderson 2008-04-28 19:23 Craig Silverstein * Makefile.in, configure.ac, include_server/setup.py, src/compile.c, src/distcc.h, src/dotd.c, src/emaillog.c, src/exec.c, src/fix_debug_info.c, src/io.c, src/lsdistcc.c, src/netutil.c, src/snprintf.c, src/srvrpc.c, src/tempfile.c, src/trace.c, src/util.c: These changes are enough to get code to compile, and at least some of the unittests to pass, on FreeBSD 6.0, Solaris 10 x86, and OS X Leopard. You have to use gmake instead of standard bsd make, though, because neither bsd nor solari make understand 'include */*.d' and 'CFLAGS += $(POPT_FLAGS).' These may be fixable later. Most changes fall into four categories: 1) #include differences 2) New errors due to some #ifdef paths being taken differently 3) Undefined functions (see, eg, the new HAVE_STRSEP) 4) Type differences (eg tv_usec is an int on os x, not a long int) As one concrete example, snprintf.c is an empty file on linux, where all the functionality is part of glibc. But on Solaris, some of its functionality is useful. This turned up a bug where if you have vsnprintf on your system but not vasnprintf, then dopr() was not being used but was being defined, leading to an "unused static function" warning in gcc. As another, solaris would complain about "index" being used as a variable, since it's also a function name. The var was renamed idx. Tested by compiling on FreeBSD, Solaris 10, and OS X leopard (x86). I also compiled and ran unittests under Linux Ubuntu, to make sure this change didn't break anything there. Reviewed by Fergus Henderson 2008-04-25 06:29 Craig Silverstein * include_server/include_analyzer_test.py, include_server/test_data/symlink_farm/foo, include_server/test_data/symlink_farm/sub_farm/link_to_dd_dd_dfoo_include_dotdot_foo[CPY], include_server/test_data/symlink_farm/sub_farm/link_to_dotdot_dotdot_dfoo_include_dotdot_foo[DEL]: Some older versions of tar have problems with filenames > 100 characters. To maximize compatibility, I renamed the only file we have that is close to that limitation, to be shorter. 2008-04-24 06:40 Craig Silverstein * configure.ac: Neglected to commit this with the Makefile.am changes from last time, though it's needed to define UNINSTALL_GNOME. Reviewed by Fergus Henderson 2008-04-24 05:39 Craig Silverstein * Makefile.in: Add uninstall targets, to undo the effects of 'make install'. I try to be semi-smart about deleting empty directories. Unfortunately, python's setup.py does not have an --uninstall mode, so I can only uninstall the include-server if a python-record-file was preserved during make install. This record-file must be passed in for make uninstall as well. Tested by running 'make install' followed by 'make uninstall' on my local machine. Reviewed by Fergus Henderson 2008-04-23 00:40 Craig Silverstein * TODO: Update the TODO file to add an entry on better non-ELF support. Also get rid of the TODO for Latte, since we're not going to be using any doc-template system on Google Code. While in the area, normalize a little bit the number of blank lines between entries (I try to make it 2). 2008-04-19 23:40 Craig Silverstein * Makefile.in, configure.ac, packaging/googlecode_upload.py: Fix some bugs in the googlecode-upload script, and modify the upload target in the Makefile to call it. Also added googlecode_upload.py to the dist tarball. Also update the version number to prerelease2. As part of testing this change, I actually uploaded the tarballs and rpm files to code.google.com. Reviewed by Fergus Henderson 2008-04-18 19:19 Nils Klarlund * Makefile.in, test/comfychair.py: Rename directory testtmp to _testtmp in line with our current practice for generated directories. 2008-04-18 18:51 Craig Silverstein * .: Another auto-generated file I had forgotten last time. 2008-04-18 18:32 Fergus Henderson * Makefile.in, packaging/RedHat/conf, packaging/RedHat/conf/clients.allow, packaging/RedHat/conf/commands.allow.sh, packaging/RedHat/conf/hosts, packaging/RedHat/default, packaging/RedHat/default/distcc, packaging/RedHat/init.d/distcc, packaging/RedHat/rpm.spec: A bunch of changes to the configuration files and installation: (1) Remove the Google crosstool-specific stuff from packaging/RedHat/init.d/distcc; instead, make it source a new configuration file "commands.allow.sh". (2) Install default versions of all the configuration files in $(sysconfdir), i.e. /etc: distcc/hosts, distcc/clients.allow, commands.allow.sh, and defaults/distcc. (3) Fix a bug in Makefile.in: "make install" didn't work when you configured with srcdir != builddir. Added "$(srcdir)/" in various places to make it work. (There's similar problems with "make dist", but I gave up on those for now.) (4) Add "install-deb" rule, to install the ".deb" files. (5) Don't run install-for-include-server-tests as part of "make install". That target is part of "make check", not "make install". (6) Add missing dependency on "include-server" to "pump-check" rule. (7) Remove some bash-isms from the "init.d/distcc" script. Tested by running "make install-deb" followed by "distcc /usr/bin/gcc -c foo.c" - this now works "out-of-the-box"! :-> Also ran "make maintainer-check" and "make pump-check". 2008-04-18 16:01 Fergus Henderson * autogen.sh: Address review comments on an earlier change: - autogen.sh now uses "#!/bin/sh -e" rather than "|| exit 1" everywhere. - autogen.sh now determines srcdir automatically from $0 - autogen.sh no longer tells you to run "./configure --srcdir=.". 2008-04-18 15:13 Nils Klarlund * test/testdistcc.py: Fix-up test in regard to angle bracket includes of non-existent files in order to explicitly accommodate the rather strange difference between running gcc locally and running it remotely in pump mode. In the former case, gcc fails with an error message; in the latter it succeeds and the error has been demoted to a warning. TESTING: make maintainer-check make pump-check 2008-04-18 08:59 Fergus Henderson * man/distccd.1: The --allow option to distccd is no longer optional. Update the distccd man page to better reflect that. 2008-04-18 06:53 Craig Silverstein * ., lzo, packaging, popt, src, test: Update the svn:ignore property on these directories, so 'svn status' doesn't show the auto-generated files that can show up, such as distcc.d or config.h.in. 2008-04-18 06:37 Craig Silverstein * packaging/googlecode_upload.py: Add distcc-specific code to googlecode_upload. This allows us to upload all the package files we create in one fell swoop (they must be specified on the commandline). We figure out the summary to give to each file and the label to apply, and then upload each in turn. I've also turned off the feature to figure out the name and password directly from the local svn repository, because that feature is broken (alas), with the current python-subversion bindings. Instead, I prompt for them, but at least it's only once per upload as opposed to once per file! Not yet tested (will do so when I add to the Makefile to actually use it). Reviewed by Fergus Henderson 2008-04-18 01:12 Nils Klarlund * Makefile.in: Add missing dependency on pump for target pump-check and pump-installcheck. To do so, introduce new phony intermediate target. Add TODO about the `pwd` in maintainer-installcheck target. 2008-04-18 01:08 Fergus Henderson * Makefile.in: Fix missing line continuation in a Makefile rule. Also, use "@" to avoid printing out a line with disturbing contents ("ERROR") during normal successful test execution. 2008-04-18 01:05 Fergus Henderson * autogen.sh: Support running autogen.sh in the build directory, rather than the source directory. Now the source directory should be completely untouched, so we should be able to autogen, configure, and build even if the source directory is read-only. 2008-04-18 01:03 Craig Silverstein * Makefile.in: Quick fix to my previous commit: I have to make sure every Make line ends in success, when it in fact succeeds. Thus you need to use || sometimes instead of &&. 2008-04-18 01:00 Craig Silverstein * Makefile.in: Augment 'make distcheck' to ensure that 'make', 'make check', 'make install', etc. only write into builddir and instdir, not srcdir. In the process, fixed up a typo -- introduced when I merged all the Makefile.in's -- that affected us in the (common) case DISTDIR is the empty string. Tested by running 'make distcheck'. Reviewed by Fergus Henderson 2008-04-18 00:07 Craig Silverstein * packaging/googlecode_upload.py: Add googlecode_upload.py, a script to help upload tarballs and package files to the Google Code location of distcc. This is the version as downloaded from the web, at http://support.googlecode.com/svn-history/r57/trunk/scripts/googlecode_upload.py After this pristine version is checked in, we'll hack on it to add some distcc-specific features (multiple uploads, etc). We'll also add it to the Makefile at that time, both to use ('make upload') and as part of the distribution (hey, why not). 2008-04-17 22:27 Craig Silverstein * Makefile.in, build-distcc.sh[DEL], distcc.spec[DEL], packaging/RedHat/rpm.spec[CPY], packaging/deb.sh, packaging/rpm.sh[CPY]: Add 'make rpm' to make the rpm files for this project (much like 'make dist' makes a tar.gz file), and 'make deb' to make the deb files. 'make alldist' will make all three (well, four): .tar.gz, .tar.bz2, .rpm, and .deb. The rpm.spec file that's used is based on the old distcc.spec file, which is now deleted. However, it's reordered to look a bit more like other spec files for Google projects, removes the obsolete 'include-server' package (that's now part of the distcc package proper), and takes out all the ChangeLog entries that don't relate to the spec file in particular. I also added a script, rpm.sh, to build the rpm file, which is a combination of the rpm.sh script used to build other google projects, and the existing build-distcc.sh, which is now deleted. Mostly it just calls rpmbuild with the right flags. deb.sh could have re-done all the work that rpm.spec and rpm.sh does, but instead we just use "alien" to convert the rpm to a deb file. Tested by installing the deb files (both client and server) on my home machine and then running 'make maintainer-installcheck'. Reviewed by Fergus Henderson 2008-04-17 05:42 Fergus Henderson * README.pump: Avoid referring to "the distcc-pump". Reviewed by Nils Klarlund. 2008-04-17 02:45 Craig Silverstein * INSTALL, Makefile.in, configure.ac, include_server/setup.py: Resolve some TODO's in the Makefile (and, to a lesser extent, in configure.ac): 1) Create a .gz tarfile as well as a .bz2 tarfile, with "make dist". I've also added a few more dist rules: "make rpm", "make deb", and "make alldist", though currently they're commented out since the scripts they call have yet to be written. 2) setup.py looks at os.environ("BUILDDIR"), so make sure that environment variable is always set properly. 3) setup.py was hard-coding the version number. Instead, have it get it from the environment ("DISTCC_VERSION"), and set that envvar before calling setup.py in the Makefile. (The alternate solution, of making a setup.py.in and having configure set the version number in setup.py, did not work well because the Makefile really wants setup.py to be in $srcdir, that the configure option puts it in builddir.) 4) Clean up distcheck to have three separate directories: src, build, and install. Before src and build were the same. This pulled up several places that were using srcdir instead of builddir, which I fixed. 5) Clean up distcheck to make sure that 'make distclean' cleans all the build files created during the build. At first it didn't quite, so I fixed that up as well. 6) Added some new files to 'make dist': particularly, the files used to build rpm and deb files. 7) Have maintainer-check and maintainer-installcheck both call the same routine (via recursive make) rather than copy all that code. This simplifies things surprisingly, especially since the main check logic no longer has be inside a big "if $(PYTHON)". 8) (Various rules:) replace $^, which is not very portable, with a repetition of the dependency line. 9) Rename GZIP to GZIP_BIN, since GZIP as an envvar is read by gzip and parsed as gzip options. 10) In include_server/setup.py, we weren't setting builddir/src as an include dir, and it needs to be (as 'make distcheck' shows). I'm not sure builddir/../../src really needs to be anymore, but I guess it can't hurt, so I've left it in. 11) Updated INSTALL to refer to autogen.sh, which will create configure if it's not already there. 2008-04-15 02:23 Nils Klarlund * pump.in: Clean logic and error messaging in pump script. - There were missing error messages. - Some of them did not go to stderr. - Global variable include_server_started_successfully was ugly. Changed to a status variable. - Also, joined some lines that were joinable. - Fixed a spurious parameter to a function ExportDISTCC_HOSTS. Added a parameter to same function. Tests ----- Can run 'pump-check'. Also, when I forced more than one C extension, I get the following tirade. __________Using distcc-pump from /home/klarlund/svn-distcc/distcc __________Shared libraries for multiple architectures discovered. __________Cannot determine which one to use among: ./_builddir/lib.blah/include_server/distcc_pump_c_extensions.so ./_builddir/lib.linux-x86_64-2.4/include_server/distcc_pump_c_extensions.so __________Could not start distcc-pump include server 2008-04-14 23:17 Craig Silverstein * ChangeLog: Added some Google-branch changes to the ChangeLog file, now that we've integrated them back into the main branch in preparation for distcc 3.0. These messages were taken from the rpm.spec ChangeLog, where they had been living before. I can't say that it's a complete list of google-branch patches, but it's a good started. Reviewed by Fergus Henderson 2008-04-14 17:11 Nils Klarlund * pump.in: Fix up pump.in: - Rename DISTCC_PUMP_LOCATION because there is now no distinct such entity. - Comment 'return 0'. - Fix logic in Main so that script aborts when include server not started. - Add missing line: include_server_started_successfully=0. 2008-04-12 00:58 Craig Silverstein * Makefile.in, autogen.sh, bench/Build.py, bench/Project.py, bench/ProjectDefs.py, bench/Summary.py, bench/actions.py, bench/benchmark.py, bench/buildutil.py, bench/compiler.py, bench/statistics.py, configure.ac, distcc[DEL], include_server/basics.py, include_server/setup.py, pump.in: The second part of my change to hoist everything in the distcc/ directory up to the top level: delete the distcc directory (I already copied it all to the top level in my last commit). This requires changing all files that refer to distcc/FOO to refer directly to FOO instead. Mostly this is Makefile.in and setup.py, but there are a few other changes in scripts that have to hard-code paths, like configure.ac and pump.in. Also, several files changed their comments to refer to the new location, which isn't strictly necessary but I did anyway. The only other change I made was to get rid of the hack I had put in before, which renamed distcc to distcc-bin. I had needed to do that before, temporarily, because "distcc" was already the name of a directory, and couldn't also be the name of a binary. Now that the distcc directory is going away, I can rename the target back to distcc. Tested by running './autogen; ./configure; make maintainer-check'. I also ran 'make pump-check' and 'make distcheck'. To be reviewed (post-facto) by Nils Klarlund and Fergus Henderson 2008-04-11 22:36 Craig Silverstein * bench[CPY], contrib[CPY], doc[CPY], gnome[CPY], lzo[CPY], m4[CPY], m4/pkg.m4[CPY], man[CPY], packaging[CPY], popt[CPY], src[CPY], survey.txt[CPY], test[CPY]: The first step of moving everything in the distcc directory to the top level. I'm doing this in two stages, because I don't understand svn enough to be confident to do it in one. This first stage just copies all the files from distcc/FOO to FOO. Now there are two copies of each file under distcc; the Makefile/etc uses the one in distcc and ignores the one at the top level. The next commit will delete everything under distcc, and rewrite the Makefile/etc to use the top-level versions instead. 2008-04-11 22:20 Craig Silverstein * INSTALL, Makefile.in[CPY], autogen.sh[CPY], build-distcc.sh, config.guess[CPY], config.sub[CPY], configure.ac[CPY], distcc/Makefile.in[DEL], distcc/autogen.sh[DEL], distcc/config.guess[DEL], distcc/config.sub[DEL], distcc/configure.ac[DEL], distcc/install-sh[DEL], distcc/m4/pkg.m4, distcc/mkinstalldirs[DEL], include_server/Makefile.in[DEL], include_server/configure.ac[DEL], include_server/setup.py, install-sh[CPY], mkinstalldirs[CPY], pump.in, run_all_autoconf.sh[DEL], version.sh[DEL]: Merge configure.ac, distcc/configure.ac, and include_server/configure.ac into a single, top-level configure.ac script. Likewise with the three Makefile.in scripts. Now one config file at the top level controls everything. I had to rewrite quite a bit of code to account for the new level-up. In particular, I had to add "distcc/" in front of many things in order to refer to the same files I used to refer to when the configure.ac/Makefile.in text lived in the distcc/ directory rather than the top-level directory. Likewise (though to a lesser extent) for include_server. I also had to do a bit of merge work. Typically I'd leave the originally-distcc-directory content as close to the original as possible, and then try to put in the include_server directory stuff. Most of the top-level configure.ac and Makefile.in could go away, since they were glue before. I also could get rid of other top-level helper scripts that were used for the glue, such as version.sh. I also fixed a number of typos and other bugs: Makefile.in: 1) Removed obsolete CVS comment (we're 3 source-control systems past that now!) 2) distcc/Makefile.in was using top_builddir without importing it from the configure script. 3) Add zeroconf.h to HEADERS, which is needed for 'make dist'. I also added all the include_server files to 'make dist'. 4) "make dist" was passing 'h' ("no symlinks") to tar. This does not work with the include_server test-suite, which includes symlinks. I verified no other part of the distribution uses symlinks. Removed the h. 5) "make dist" was missing a lot of stuff (including almost all the include-server files). Updated it to get it all now. Likewise, updated "make clean" and its cousins to be more precise. Also made "make distcheck" more careful in checking that kind of thing. 6) Declared more phony targets .PHONY. 7) The include-server build commands do a lot of 'cd'-ing (since setup.py requires it), and then using make variables that might store relative directory paths. I now go through some hoops to make those directory paths absolute before the cd. 8) "make pump-check" was not setting the path, so it was using the installed distcc instead of the local one in the client. Fixed that, and added a new target, "make pump-installcheck", to use the installed distcc instead (parallel to the maintainer-check and maintainer-installcheck targets). configure.ac: 1) popt test was using $srcdir rather than required ${srcdir}, and thus was always getting the empty string. (Luckily, srcdir is usually ".", and the empty string is usually equivalent.) Likewise when setting CPPFLAGS, which again didn't matter because it turns out the relevant code was redundant with what autoconf already does automatically. 2) A merge error: apparently the avahi check was added twice. Get rid of the second one. 3) Was using obsolete AC_OUTPUT format. Use AC_CONFIG_FILES instead. 4) Added pkg.m4 to the m4/ directory. Before it only lived in autoconf.m4. But my system, at least, doesn't have it. 5) include-server requires python2.4, so remove checks for earlier pythons. autogen.sh: 1) Added aclocal call. I think it was a bug that it was left out before. pump.in: 1) Fixed it to notice when it can't find the .so file it needs. I also modified INSTALL to point to the new file locations, and the new instructions to run them (eg no more run_all_autoconf.sh). Despite all these bugfixes, I made the minimal changes possible to get things to work. I marked with "TODO" further improvements I'd like to make later. One particular TODO is that I had to rename the "distcc" target -- the main executable -- because it conflicts with the existing distcc directory. This is a temporary breakage which will be fixed in the next submit after this one, where I move the subdirs under distcc to the top level, getting rid of the artificial extra directory introduced. Tested by running 'make maintainer-check', 'make distcheck', and 'make pump-check' on my local machine, which passed. I've not tested all the various configurations and options (including using avahi, using the library popt library, building without python, etc). I've also not tried 'make benchmark'. Reviewed by Nils Klarlund and Fergus Henderson 2008-04-11 20:40 Fergus Henderson * README.pump: Update README.pump to better describe performance on small clusters. 2008-04-11 18:45 Fergus Henderson * distcc/Makefile.in: In the rule for 'make pump-check', set DISTCC_HOSTS, so that 'pump' won't complain that it isn't set. 2008-04-10 00:27 Craig Silverstein * distcc/README[DEL]: I meant to delete this as part of my last commit, but apparently neglected to... 2008-04-09 23:19 Craig Silverstein * AUTHORS[CPY], ChangeLog[CPY], INSTALL, NEWS[CPY], README, README.packaging[CPY], README.pump[CPY], TODO[CPY], distcc/AUTHORS[DEL], distcc/COPYING[DEL], distcc/ChangeLog[DEL], distcc/ChangeLog.old[DEL], distcc/INSTALL[DEL], distcc/NEWS[DEL], distcc/README.packaging[DEL], distcc/TODO[DEL]: Take these human-readable files and normalize their content and location: README Our blurp, tooting our horn INSTALL The run_all_autoconf and friends incantations COPYING GPL 2.0 license distcc/README Martin's blurp distcc/INSTALL Also: more on masquerading, host lists, distcc/COPYING GPL 2.0 license distcc/NEWS Recently updated distcc/AUTHORS Martin Pool distcc/README.packaging Various advice (version numbering etc) distcc/TODO A very long list (not updated) distcc/ChangeLog All changes under arch and under bzr distcc/ChangeLog.old All changes from before arch. Now all live in the top-level directory. This is the first step towards our eventual goal of getting rid of the second-level distcc and include_server directories, and just having everything under one top-level directory. We're all part of the same project now! Here's how I merged and updated content: . README became README.pump. It was slightly edited for clarity. (I also redid all the line-wrapping, which makes diff-ing difficult. :-( ) distcc/README became README, with a small amount of text added to describe 'pump' mode, and point to README.pump. . distcc/NEWS became NEWS. pump functionality was added (a new "distcc-3.0" entry). I also added all new features and bug-fixes since we moved from arch to bzr. It looks like NEWS was well-maintained before the move to bzr, so this might be pretty complete. There may be some more pump-developed bugfixes we need to add, though. . I got rid of distcc/COPYING. Now COPYING is the only license in this directory. This file was not changed. It remains the GPL 2.0 license. . distcc/AUTHORS became AUTHORS. I changed Martin to maintainer emeritus. I added the Google authors as authors of the "pump" functionality, and current maintainers. I set the Google email address to be distcc@googlegroups.com, which is a new group I've set up to be the clearinghouse for distcc discussions. . distcc/README.packaging became README.packaging. It was not otherwise changed. . distcc/TODO became TODO. It was not otherwise changed, except I added that folks should look for FIXMEs in source files, not just TODOs. . I merged INSTALL and distcc/INSTALL (in that order). I rearranged the text a little bit to remove redundancy (both talked about running 'configure'), but did not make any contentful changes. . I merged distcc/ChangeLog and distcc/ChangeLog.old to have a single changelog again going all the way to 2002. Comments now separate the various version control systems used. (svn is #4!) The single ChangeLog file now lives in the top-level directory. 2008-04-09 23:11 Craig Silverstein * distcc/ChangeLog, distcc/Makefile.in, distcc/configure.ac, distcc/m4, distcc/m4/acx_pthread.m4, distcc/src/distcc.c, distcc/src/distcc.h, distcc/src/dopt.c, distcc/src/dopt.h, distcc/src/dparent.c, distcc/src/gcc-id.c, distcc/src/help.c, distcc/src/hostfile.c, distcc/src/hosts.c, distcc/src/io.c, distcc/src/tempfile.c, distcc/src/zeroconf-reg.c, distcc/src/zeroconf.c, distcc/src/zeroconf.h: Integrate the following post-bzr (post 2.18.3) patch from the mainline distcc sources (http://bazaar.launchpad.net/%7Embp/distcc/trunk/): % bzr log -r3 message: merge avahi patch from Lennart Poettering (This patch comes from http://0pointer.de/public/distcc-avahi.patch, which is the version of the patch I applied, since the one in the bzr repository was missing the new files from the avahi patch.) I've also manually updated ChangeLog, which is not automatically updated by bzr the same way it is by arch. I've also added a new m4 directory, including non-standard autoconf macros that we use. For now, it only includes ACX_PTHREAD (added by the avahi patch) which I got from 0pointer.de. See the notes at the top of m4/acx_pthread.m4 for more details. I removed the change to Makefile.in that added in distccmon-gnome.1. This file is not actually added in as part of this patch (it seems to be part of a separate patch, at http://patches.ubuntu.com/d/distcc/extracted/02_distccmongnome_man.dpatch), and may have gotten in here by accident. Tested by running 'make maintainer-check'. However, I did not test with avahi installed, so I don't know how well that works. Reviewed by Fergus Henderson and Nils Klarlund 2008-04-09 16:21 Fergus Henderson * version.sh: Change the version number from "distcc 2.18.3-17gg1.pump20" (ugh!) to "distcc 3.0-prerelease1". 2008-04-09 00:38 Craig Silverstein * distcc/ChangeLog, distcc/NEWS, distcc/src/lock.c: Integrate the following post-bzr (post 2.18.3) patches -- all of them, so far -- from the mainline distcc sources (http://bazaar.launchpad.net/%7Embp/distcc/trunk/): % bzr log -r2 message: Add more ignored files % bzr log -r4 message: Locks taken through F_SETLK or lockf() must be explicitly released, because closing the file does not do so. (Sascha Demetrio) r2 is a noop for us, since it just updates a .bzr config file (which we may want to update in svn-land too, one day, but not for now). r3, not part of this CL, is the "avahi" patch (http://0pointer.de/public/distcc-avahi.patch). It was imperfectly applied: the new files that are part of this patch were not added to the bzr repository. We're following up with the patch-applier to see if these files can be taken verbatim from the patch in the 0pointer website. We'll also have to audit this patch to make sure it works with distcc-pump without needing any changes. For those reasons, we'll apply that patch in a separate change. I've also manually updated ChangeLog, which is not automatically updated by bzr the same way it is by arch. Tested by running 'make maintainer-check'. Reviewed by Nils Klarlund 2008-03-31 04:38 Craig Silverstein * distcc/ChangeLog, distcc/Makefile.in, distcc/NEWS, distcc/man/distcc.1, distcc/src/clinet.c: Integrate the following post-2.18.3 patches from the mainline distcc sources (distcc--devel--2/mbp@sourcefrog.net--2004): % tla cat-log patch-179: Summary: More details on error 110 % tla cat-log patch-180: Summary: draft patch for substituting compiler command name % tla cat-log patch-181: Summary: fix error check in dcc_connect_by_add % tla cat-log patch-182: Summary: build fix for --as-needed % tla cat-log patch-183: Summary: ignore tags file Note only one of these (patch-181) affects code in the src/ directory. Tested by running 'make maintainer-check'. Reviewed by Fergus Henderson 2008-03-29 19:19 Craig Silverstein * distcc/ChangeLog, distcc/NEWS, distcc/autogen.sh, distcc/bench/ProjectDefs.py, distcc/configure.ac, distcc/src/exec.c, distcc/src/exitcode.h, distcc/src/io.c, distcc/src/tempfile.c, distcc/test/comfychair.py, distcc/test/testdistcc.py: Integrate the following post-2.18.3 patches from the mainline distcc sources (distcc--devel--2/mbp@sourcefrog.net--2004): % tla cat-log patch-167: Summary: - better autogen message % tla cat-log patch-168: Summary: use python2.4 if available % tla cat-log patch-169: Summary: bump version number % tla cat-log patch-170: Summary: return error on timeout in dcc_select_for_write % tla cat-log patch-171: Summary: doc % tla cat-log patch-172: Summary: doc % tla cat-log patch-173: Summary: [patch] cygwin improvements from Alex Besogonov % tla cat-log patch-174: Summary: update patch to fix up gdb line numbers % tla cat-log patch-175: Summary: [patch] update stale benchmark source URLS (Dongmin Zhang) % tla cat-log patch-176: Summary: update benchmark project urls and md5s % tla cat-log patch-177: Summary: Update more benchmark project definitions % tla cat-log patch-178: Summary: set locale when running make maintainer-check Note only two of these (patch-170 and patch-173) affect non-comment code in the src/ directory. patch-173 introduced an "unused variable" warning in tempfile.c when run in non-cygwin mode, which I fixed up separate to the above patches. Tested by running 'make maintainer-check'. Reviewed by Fergus Henderson 2008-03-29 04:40 Craig Silverstein * run_all_autoconf.sh: Replace the sanity-check in run_all_autoconf.sh with a more accurate one. Reviewed by Nils Klarlund 2008-03-28 22:38 Craig Silverstein * distcc/ChangeLog, distcc/NEWS, distcc/TODO, distcc/man/distcc.1, distcc/src/arg.c, distcc/src/clinet.c, distcc/test/testdistcc.py: Integrate the following post-2.18.3 patches from the mainline distcc sources (distcc--devel--2/mbp@sourcefrog.net--2004): % tla cat-log patch-160: Summary: note on .incbin from asm() % tla cat-log patch-161: Summary: args: -d must be local % tla cat-log patch-162: Summary: manpage correction from Frerich % tla cat-log patch-163: Summary: todo % tla cat-log patch-164: Summary: add note that the mDNS patch cannot be legally merged % tla cat-log patch-165: Summary: add hosts-from-dnsdomain patch from dan % tla cat-log patch-166: Summary: [patch] better checking for errors on connect() Note only two of these (patch-161 and patch-166) affect the src/ or test/ directories. Tested via 'make maintainer-check'. 2008-03-28 17:39 Fergus Henderson * distcc/Makefile.in: Fix typo. 2008-03-28 17:38 Fergus Henderson * distcc/src/fix_debug_info.c: Work around spurious gcc warning that was causing trouble with -Werror. 2008-03-28 17:30 Fergus Henderson * distcc/src/lsdistcc.c: Fix a portability issue: compile error on 64-bit platform. ## This is the point at which the code was moved to the svn repository. ## The changes below this were made in an internal Google repository. 2008/03/03 11:35:34 Fergus Henderson Add extra "-I" option that seems to be needed when building distcc-pump with Blaze: we need _two_ ".."'s to get from $BUILDDIR/include_server/build to $BUILDDIR/distcc/src/config.h. Without this change, building distcc fails with a compilation error about "config.h" not found when run in a fresh workspace. R=klarlund DELTA=2 (2 added, 0 deleted, 0 changed) * include_server/setup.py: edit 2007/12/14 19:17:16 Fergus Henderson Fix a bug which showed up if the include server was run from a different directory than the distcc clients: in that case, it was at some times wrongly interpreting relative paths in the --stat_reset_trigger option as relative to the distcc client's cwd, rather than the include server's cwd. TODO(fergus): add a regression test. R=klarlund CC=distcc-pump APPROVED=klarlund DELTA=20 (18 added, 2 deleted, 0 changed) * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node_test.py: edit 2007/12/14 10:26:29 Nils Klarlund Fix location of stamp file that record autoconf execution. The location was incorrect: the stamp file that pertains to autoconf must necessarily be in the source code directory because autoconf'ing is the process of generating the configure script. Only the result of configuring is to be carried out in the object directory. R=fergus DELTA=1 (0 added, 0 deleted, 1 changed) * Makefile.in: edit 2007/12/13 21:52:59 Nils Klarlund Fix typos in Makefile.in. R=fergus DELTA=2 (0 added, 0 deleted, 2 changed) * include_server/Makefile.in: edit 2007/12/07 16:19:16 Nils Klarlund This file is generated by run_all_autoconf.sh and should not be checked in. (Because that leads to Perforce complaints about 'clobbering'.) R=fergus DELTA=262 (0 added, 262 deleted, 0 changed) * distcc/src/config.h.in: delete 2007/12/07 12:57:55 Nils Klarlund Fix bug caused by non-idempotency of 'ln' and ensuing falsely positive test result. So, it turns out that 'ln -sf' is not idempotent. If C/D and E are directories, then ln -sf $(readlink -f C/D) E/D creates a link E/D -> realpath(C/D) and subsequent ln -sf $(readlink -f C/D) E/D creates a link C/D/D -> realpath(C/D), a self-reference of sorts. This is nasty because the second link created is in C/D, which was supposed to be just a target directory, not something to be modified! This bug enabled a faulty test to pass: the directory structure created by the non-potency bug is not cleaned on make clean. And the existence of the inserted extra directory made resolution of a certain include path possible when it should not have. R=fergus CC=manos DELTA=11 (9 added, 0 deleted, 2 changed) * include_server/Makefile.in: edit * include_server/include_analyzer_test.py: edit 2007/12/03 18:37:17 Nils Klarlund This version is to incorporate: ' Fix bug that leads to concurre' Change 2007/12/03 by Nils Klarlund R=fergus DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/12/03 16:36:06 Nils Klarlund Fix bug that leads to concurrent build interference: one distcc-pump build will severely affect another. The logic for naming the root directory was flawed: it used the pid of the parent, not the child, which is where the include server resides. Also fix less severe bug that allowed the cleaning up to end prematurely. The code is refactored at the same time -- for better readability and to address the parent/child pid confusion. The fix also includes the introduction of an additional communication mechanism, a semaphor: the child is now starting the include server and it must tell the parent that it has done so before the parent is allowed to exit. Testing: - 'make check' - Made several concurrent runs and verified that interference no longer takes place. R=fergus DELTA=65 (45 added, 1 deleted, 19 changed) * include_server/include_server.py: edit 2007/11/29 12:30:45 Nils Klarlund Add more meta-dependencies (those that involve autoconf) to the Makefile.in files and add sanity check to run_all_autoconf.sh. These dependencies should help prevent builds that do not reflect the configuration changes such as to version.sh or configure.ac. Dependencies are added, so this should be a conservative CL: making this build system less fragile. Tests: patched this CL into a clean client and rebuilt software: ./run_all_autoconf.sh ./configure --prefix=$(pwd)/installation make make install R=fergus DELTA=73 (62 added, 0 deleted, 11 changed) * Makefile.in: edit * distcc/Makefile.in: edit * include_server/Makefile.in: edit * run_all_autoconf.sh: edit 2007/11/06 15:58:38 Nils Klarlund Prepare 'pump19'. It contains: 'Add basics_test rule to include' Change 2007/11/06 12:43:59 by Nils Klarlund ' Fix typo and missing condition' Change 2007/11/06 11:51:01 by Nils Klarlund 'Fix an infinite loop in the inc' Change 2007/11/05 14:11:47 by Nils Klarlund ' Bump up length of interval tha' Change 2007/11/05 07:25:13 by Nils Klarlund ' Make the _CleanOutOthers routi' Change 2007/11/02 12:36:27 by Nils Klarlund ' Increase include server timeou' Change 2007/11/01 14:46:44 by Nils Klarlund 'Fix buglet: when the contents o' Change 2007/11/01 14:28:22 by Nils Klarlund R=fergus DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/11/06 15:43:59 Nils Klarlund Add basics_test rule to include_server/Makefile.in. This enables 'make check' to run all tests. Test: ./run_all_autoconf.sh; ./configure --prefix=$(pwd)/installation make basics_test make -C include_server basics_test make check R=fergus DELTA=4 (4 added, 0 deleted, 0 changed) * include_server/Makefile.in: edit 2007/11/06 14:51:01 Nils Klarlund Fix typo and missing conditional of a previous change, which "broke" the build. Tests: - make -C include_server check R=fergus DELTA=3 (1 added, 0 deleted, 2 changed) * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/11/05 17:11:47 Nils Klarlund Fix an infinite loop in the include server. FindNode would call itself ad infinitum prompted by unusual link structures and includes. This change is non-trivial. In particular, it relates to a previous bug fix which is rolled-back as part of the present change -- and then the problem reported in the bug report is solved instead by properly mending the code that was removed in that change. The fix consists of making the memoization removed in that change cognizant of the file directory or rather the absolute path of the file directory, see extensive new comments in class IncludeAnalyzerMemoizingNode. Small stuff: we change 'filepath' to 'fp' in all identifiers in FindNode. That's because the identifiers were otherwise getting too long in the new code. And, we used that abbreviation already. Testing: a test_DotdotInInclude test case specifically exercices the situation in the bug. [Plus additional Google-specific correctness and performance tests.] Additionally, we're now doing the test_IncludeAnalyzer in two ways: directly and through a symlink farm. This helps us test regression against subtle bugs that may occur with symbolic links. R=fergus DELTA=327 (194 added, 12 deleted, 121 changed) * include_server/cache_basics.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_analyzer_test.py: edit * include_server/test_data/dfoo/include_dotdot_foo: add * include_server/test_data/symlink_farm/abc_post.c: add * include_server/test_data/symlink_farm/abc_pre.c: add * include_server/test_data/symlink_farm/computed_includes.c: add * include_server/test_data/symlink_farm/dbar: add * include_server/test_data/symlink_farm/dfoo: add * include_server/test_data/symlink_farm/foo: add * include_server/test_data/symlink_farm/p1.h: add * include_server/test_data/symlink_farm/parse.c: add * include_server/test_data/symlink_farm/sub_farm/link_to_dotdot_dotdot_dfoo_include_dotdot_foo: add * include_server/test_data/symlink_farm/test_directory_probing.c: add * include_server/test_data/symlink_farm/test_include_next: add 2007/11/05 10:25:13 Nils Klarlund Bump up length of interval that determines when SIGALRM is raised. Testing showed that with srcfs -- which increases user time -- I/O between distcc and include server (in the C extension part) would be tripped up by SIGALRM when it is raised every 2s. This results in a Python exception such as IOError, which is wrong and even harmful, because it terminates the include server. The interval in the currently released version is 3s, so 4s is better. This is to be followed up by CL that makes the algorithmic code "protected" by SIGALRM free of I/O. R=fergus DELTA=5 (4 added, 0 deleted, 1 changed) * include_server/basics.py: edit 2007/11/02 15:36:27 Nils Klarlund Make the _CleanOutOthers routine be called. Before this CL, this routine was not called at all, because a variable describing the tmp directory has not been initialized. We split the InitializeTmpDirectories function into two parts to distinguish between creation of the temporary directory and the creation of client root under it. Also, fixed bug in the glob expression. Also, don't write out warning when cleaning -- that's just bound to confuse users. Demote message to TRACE level. Also, fix basics_test.py and make sure it's called as part of 'make check'. R=fergus DELTA=97 (52 added, 17 deleted, 28 changed) * include_server/Makefile.in: edit * include_server/basics.py: edit * include_server/basics_test.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node_test.py: edit * include_server/include_analyzer_test.py: edit * include_server/include_server.py: edit * include_server/include_server_test.py: edit * include_server/parse_file_test.py: edit 2007/11/01 17:46:44 Nils Klarlund Increase include server timeout to 3.8s. We are still getting emails about the include server running out of time for gws files and many others. R=fergus DELTA=2 (0 added, 0 deleted, 2 changed) * include_server/basics.py: edit 2007/11/01 17:28:22 Nils Klarlund Fix buglet: when the contents of the file descriptor would contain percent signs the call to DEBUG would fail. R=fergus DELTA=1 (0 added, 0 deleted, 1 changed) * include_server/include_server.py: edit 2007/10/23 17:56:23 Nils Klarlund Prepare new release, pump18, changing a timing constant in include server. R=fergus CC=distcc-pump DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/10/23 17:53:40 Nils Klarlund Increase time quota introduced in a previous change for handling a request. We released pump17 10/22. One day later, it turns out that there are a cases where the include server spends more than 2s processsing a compilation unit. Here we increase the 2s to 3s. R=fergus DELTA=9 (4 added, 0 deleted, 5 changed) * include_server/basics.py: edit 2007/10/22 13:43:09 Nils Klarlund Limit the time that the includer analyzer is allowed to spend servicing a request. We use the rudimentary SIGALRM mechanism, because generally Python does not allow one thread to raise an exception in another. Experiments show that SIGALRM interferes with the use of Popen. When determining the default compiler, the include server uses Popen to invoke gcc. If the SIGALRM is raised, then it be caught in the 'select', which then aborts. Therefore, we stop the timer while the include server determines default compilers. The timeout exception is raised according to utime passed, not real time. That prevents the include server from going bananas, restarting again and again, because of NFS delays. The risk with this CL is that something else breaks in unexpected ways, perhaps a file operation, with the signaling. However, we've put the first signal to occur 2s after the start of the request. That should be more than ample time. In practice, we have not seen the include server using more than 2s per request (but this is based on limited measurements). We have also tested this change with a 1s timer. That showed the SIGALRM problem with Popen. After, we fixed that this CL seems to work fine. R=manos CC=distcc-pump DELTA=110 (89 added, 1 deleted, 20 changed) * include_server/basics.py: edit * include_server/compiler_defaults.py: edit * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/10/22 12:46:42 Nils Klarlund Make version 'pump17'. R=fergus CC=distcc-pump DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/10/22 12:39:29 Nils Klarlund Fix name of stamp file. Remove initial '.'. R=manos CC=fergus DELTA=1 (0 added, 0 deleted, 1 changed) * run_all_autoconf.sh: edit 2007/10/22 11:06:40 Fergus Henderson Partial rollback of a previous change. In particular, comment out the code to support the Objective-C file extensions and the Objective-C test case. Currently Objective-C support breaks things if you don't have an Objective-C compiler installed, even if distcc is used only to compile C/C++ code; we try to compute the default include paths for all languages at startup, and barf it if fails. Leave in place the support for "#import". It turns out that "#import" can be used in GNU C/C++ code, as a GNU extension, and some Google code makes use of this. *** Original change description *** Add support for Objective-C to distcc-pump. In particular, recognize the Objective-C file extensions (".m", ".mi") and the "#import" declaration. (#import is like #include, but never includes the same file twice. So for the distcc-pump include server, processing of #import is exactly the same as processing of #include.) Tested with "make maintainer-check" (all tests pass) and "make pump-check" (no regressions). Also added a test of Objective-C compilation. R=klarlund CC=distcc-pump APPROVED=klarlund DELTA=21 (11 added, 0 deleted, 10 changed) * distcc/test/testdistcc.py: edit * include_server/basics.py: edit 2007/10/19 16:52:44 Nils Klarlund Loosen assumption about the syntax -D options. A user had written something the include server couldn't understand. It provoked a rare internal error. The compilation did not succeed locally either. The include server must remain unfazed when confronted with weird syntax. Also, corrected comment for ParseCommandArgs. R=fergus CC=distcc-pump * include_server/include_analyzer_memoizing_node.py: edit * include_server/parse_command.py: edit * include_server/parse_command_test.py: edit 2007/10/19 16:28:57 Nils Klarlund When storing warning messages in temporary file, we are using 'print >>', which appends a newline. Then, when presenting the errors to the user, we'd also use 'print', which appends another newline. With this fix, the newline is not append the first time around (we append ','). The other use of the contents of the temporary file, in the mail sending routines, should not be affected by one less newline. R=manos CC=fergus DELTA=3 (0 added, 0 deleted, 3 changed) * include_server/include_server.py: edit 2007/10/19 10:57:39 Nils Klarlund Fix so that 'make' fails when version.sh is out of date. We remade the dependency checking in the makefile so that the need to autoreconf is expressed as a depedency on something certainly produced by autoreconf when run through our script, namely a time stamp file. R=fergus DELTA=27 (4 added, 12 deleted, 11 changed) * Makefile.in: edit * run_all_autoconf.sh: edit 2007/10/19 10:15:14 Nils Klarlund Don't send email when a file that exists cannot be read. Also, slight correction to error message. R=fergus DELTA=5 (4 added, 0 deleted, 1 changed) * include_server/parse_file.py: edit 2007/10/18 15:56:20 Fergus Henderson Fix a missing word in a comment. R=klarlund DELTA=5 (0 added, 2 deleted, 3 changed) * distcc/src/compile.c: edit 2007/10/18 11:41:46 Fergus Henderson Add support for Objective-C to distcc-pump. In particular, recognize the Objective-C file extensions (".m", ".mi") and the "#import" declaration. (#import is like #include, but never includes the same file twice. So for the distcc-pump include server, processing of #import is exactly the same as processing of #include.) Tested with "make maintainer-check" (all tests pass) and "make pump-check" (no regressions). Also added a test of Objective-C compilation. R=klarlund CC=distcc-pump APPROVED=klarlund DELTA=136 (100 added, 8 deleted, 28 changed) * distcc/test/testdistcc.py: edit * include_server/basics.py: edit * include_server/parse_command.py: edit * include_server/parse_file.py: edit 2007/10/12 14:10:36 Nils Klarlund This corrects description of the previous change. Prepare a new release, pump16. Deploy in NYC only. To be installed under 2007.10.12 in buildstatic. This release includes: 'Rather than just replacing the ' Change 2007/10/11 by Fergus Henderson 'Prevent distcc-pump from revert' Change 2007/10/11 by Nils Klarlund R=fergus CC=manos DELTA=2 (2 added, 0 deleted, 0 changed) * version.sh: edit 2007/10/12 11:30:45 Nils Klarlund Prepare a new release, pump16, to include the change "Prevent distcc-pump from reverting to local compilations". Deploy in NYC only. To be installed under 2007.10.11 in buildstatic. R=fergus CC=manos DELTA=2 (0 added, 0 deleted, 2 changed) * version.sh: edit 2007/10/11 22:06:33 Fergus Henderson Rather than just replacing the server's current working directory with the clients' current working directory, we need to replace the server's root directory with the client's root directory. This is needed because the problems with gdb arise not only from the "current working directory" field (DW_AT_comp_dir), but also with the file names (DW_AT_file_name). These file names can be absolute paths to files that are outside of the current working directory. This change is basically just a one-line fix in serve.c, but for clarity I've also changed some variable names and comments in fix_debug_info.c. R=klarlund CC=distcc-pump DELTA=36 (13 added, 0 deleted, 23 changed) * distcc/src/fix_debug_info.c: edit * distcc/src/serve.c: edit 2007/10/11 16:20:33 Nils Klarlund Prevent distcc-pump from reverting to local compilations hundreds or thousands of times. Such a situation should never occur but if it occurs, we want to fall back to distcc behavior. For example, this is desirable if the include server for reason picks up files that don't exist any more or symbolic links that changed surreptiously during the build. A typical output is shown below (where we have tampered with the include server to produce too few files). Note that ERRORs still occur in the output (from the remote server). distcc[7791] ERROR: compile third_party/pcre/pcre-7.3/pcre_globals.c on 192.168.1.137,lzo,cpp failed distcc[7791] (dcc_build_somewhere) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_globals.c' failed, retrying locally distcc[7791] Warning: failed to distribute third_party/pcre/pcre-7.3/pcre_globals.c to 192.168.1.137,lzo,cpp, running locally instead distcc[7708] (dcc_please_send_email_note_discrepancy_except_fresh_dependency) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_chartables.c' failed, retried locally and got a different result. distcc[7708] (dcc_note_discrepancy) Warning: now using plain distcc, possibly due to inconsistent file system changes during build distcc[7708] Warning: Will send an email to distcc-pump-errors@google.com distcc[7780] ERROR: compile third_party/pcre/pcre-7.3/pcre_get.c on 192.168.1.135,lzo,cpp failed distcc[7780] (dcc_build_somewhere) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_get.c' failed, retrying locally distcc[7780] Warning: failed to distribute third_party/pcre/pcre-7.3/pcre_get.c to 192.168.1.135,lzo,cpp, running locally instead distcc[7869] ERROR: compile third_party/pcre/pcre-7.3/pcre_ord2utf8.c on 192.168.1.124,lzo,cpp failed distcc[7869] (dcc_build_somewhere) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_ord2utf8.c' failed, retrying locally distcc[7869] Warning: failed to distribute third_party/pcre/pcre-7.3/pcre_ord2utf8.c to 192.168.1.124,lzo,cpp, running locally instead __________Compiling obj/gcc-4.2.1-glibc-2.2.2-piii-linux-dbg/bin/third_party/pcre/pcre-7.3/pcre_ucp_searchfuncs.c.o distcc[7780] (dcc_please_send_email_note_discrepancy_except_fresh_dependency) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_get.c' failed, retried locally and got a different result. distcc[7780] Warning: Will send an email to distcc-pump-errors@google.com distcc[7791] (dcc_please_send_email_note_discrepancy_except_fresh_dependency) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_globals.c' failed, retried locally and got a different result. distcc[7791] Warning: Will send an email to distcc-pump-errors@google.com __________Compiling obj/gcc-4.2.1-glibc-2.2.2-piii-linux-dbg/bin/third_party/pcre/pcre-7.3/pcre_valid_utf8.c.o distcc[7723] (dcc_please_send_email_note_discrepancy_except_fresh_dependency) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_compile.c' failed, retried locally and got a different result. distcc[7723] Warning: Will send an email to distcc-pump-errors@google.com R=fergus,manos DELTA=211 (174 added, 8 deleted, 29 changed) * distcc/src/compile.c: edit * distcc/src/compile.h: edit * distcc/src/h_compile.c: edit * distcc/test/testdistcc.py: edit 2007/10/09 12:40:31 Nils Klarlund The obvious radical approach to clearing all caches. With this CL, we run all the initialization code of the major include analyzer object. This changes passes all usual tests and some third_party tests. All to be run before release. R=fergus,manos DELTA=52 (17 added, 32 deleted, 3 changed) * include_server/cache_basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/mirror_path.py: edit 2007/10/09 12:38:53 Nils Klarlund Introduce a time analysis of source files in order to improve S/N ratio of automatically generated error emails. Currently, we send an email in situations where: -- the remote compilation fails because a file contains something bad, -- the file is changed to not contain bad stuff, and consequently the -- the local compilation succeeds. This makes it sometimes impossible for us to determine accurately from the email whether some error really occurred or whether the user changed source files during the build. We can carry out the analysis only if there is a .d file. We check each dependency descriped there. If anyone changed after the build started, then we really don't want to hear about distcc-pump errors, because dependencies shouldn't change. The generated files are exceptions. To disregard these, the distcc user may specify a glob pattern in environment variable DISTCC_EXCLUDE_FRESH_FILES defined when invoking distcc. R=fergus APPROVED=fergus,sunq DELTA=378 (362 added, 4 deleted, 12 changed) * distcc/Makefile.in: edit * distcc/configure.ac: edit * distcc/src/compile.c: edit * distcc/src/compile.h: edit * distcc/src/emaillog.c: edit * distcc/src/h_compile.c: add * distcc/test/testdistcc.py: edit * pump.in: edit 2007/10/09 12:08:14 Nils Klarlund Release pump15 to buildstatic under name 2007.10.09. To include: Fix a bug with the check to see whether /usr/lib/rpm/... The obvious radical approach to... Ensure that the build process reruns... Introduce a time analysis of source files... R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/10/08 22:56:48 Fergus Henderson Fix a bug with the check to see whether /usr/lib/rpm/find-requires has been patched to special-case the linux-gate.so dependency. The sense of the check was inverted. On my system, find-requires had been properly patched already, but build-distcc.sh was incorrectly telling me that I needed to patch it. R=klarlund CC=distcc-pump DELTA=1 (0 added, 0 deleted, 1 changed) * build-distcc.sh: edit 2007/10/08 22:49:19 Fergus Henderson Ensure that the build process reruns autoconf and autoheader. This is needed in case configure.ac has been changed since the last build. R=klarlund CC=distcc-pump DELTA=1 (1 added, 0 deleted, 0 changed) * distcc.spec: edit 2007/10/08 10:35:13 Nils Klarlund Start a new snaphost of the file system when caches are cleared as part of the stat trigger mechanism. The stat reset is supposed to mean: ``don't trust anything about previous analyses of includes.'' So files, directories, and symbolic links, as known to the include server, are all invalid. In particular, all information gathered in the client root directory is stale. (This is where we compress source file and mirror the directory and link structure of the part of the file system explored for include analysis.) With this CL, we make the client root concept generational, as indicated by a new suffix, a generation number, added to the automatically generated root name. A trigger event bumps the generation number by one. R=manos,fergus DELTA=86 (60 added, 4 deleted, 22 changed) * include_server/basics.py: edit * include_server/compress_files.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_test.py: edit * include_server/include_server.py: edit * include_server/mirror_path.py: edit 2007/10/04 18:18:18 Manos Renieris Update the init script. Major difference is the understanding of comments. R=klarlund CC=ahyun,distcc-pump DELTA=248 (25 added, 62 deleted, 161 changed) * distcc/packaging/RedHat/init.d/distcc: edit 2007/10/04 15:05:43 Fergus Henderson Tidy up the output from c_extensions_test. Also change the test so that it will die if some unreachable code is reached, rather than quietly ignoring the error condition, and avoid using the message "internal error 3" for two different errors. R=manos CC=distcc-pump APPROVED=klarlund DELTA=8 (5 added, 0 deleted, 3 changed) * include_server/Makefile.in: edit * include_server/c_extensions_test.py: edit 2007/10/04 13:25:56 Nils Klarlund Warning message clean-up. 1) Change all information printed by Debug to go to stderr. 2) When an exception is raised it should generally be reported as a new warning (as defined by Debug called with DEBUG_WARNING, so that this output is controllable), not just printed to stderr. In particular, this change makes situations not covered by the include processor (such as absolute filepaths in #include's) be reported as warnings. 3) We removed an unnecessary try/except block for totally unexpected siutations. Those are to be handled by the general except clause of the 'handler'. Fatal issues and timing information (not normally used) is still reported to stderr through print statements. R=fergus,manos DELTA=18 (0 added, 4 deleted, 14 changed) * include_server/basics.py: edit * include_server/include_server.py: edit 2007/10/04 13:06:01 Fergus Henderson Include h_fix_debug_info in the list of check_programs, so that it gets removed by "make clean". R=klarlund DELTA=1 (1 added, 0 deleted, 0 changed) * distcc/Makefile.in: edit 2007/10/04 11:37:39 Nils Klarlund If Ctrl-c is issued while the include server is running in 'handle', then an unfortunate double error message would sometimes occur, along with a stack trace. Fixed here by propagating exception to outer handler in 'Main'. [While we're at it, we change 'main' to 'Main'. There's no reason to lowercase it.] Also, we fix the situations where the exception raised in 'handle' is an internal error or the one corresponding to SIGTERM. Both situations are uncommon. And, in both cases, we raise SIGTERM for Main to catch, so that include server can be terminated without stack traces to be printed out. R=fergus,manos DELTA=6 (0 added, 0 deleted, 6 changed) * include_server/include_server.py: edit 2007/10/04 10:13:58 Fergus Henderson Set VPATH. This is needed to make things work if you run configure in a different directory than the source directory. R=klarlund CC=distcc-pump DELTA=1 (1 added, 0 deleted, 0 changed) * Makefile.in: edit 2007/10/04 01:10:42 Fergus Henderson Add the header file for a source file I added in a previous change. I had accidentally omitted this file from that CL. R=iant CC=distcc-pump APPROVED=iant DELTA=10 (10 added, 0 deleted, 0 changed) * distcc/src/fix_debug_info.h: add 2007/10/03 20:41:00 Nils Klarlund Version 14 will contain: - a server update (for .o rewriting), to be installed 10/4 in NYC - fix for include server failure to update symbolic links when clearing caches - minor changes to messages in exception circumstances - possibly, change that analyzes .d files before sending emails about discrepancies between server and client R=fergus,manos * version.sh: edit 2007/10/03 15:03:24 Nils Klarlund Add clarifying comment. R=fergus,manos APPROVED=manos DELTA=1 (1 added, 0 deleted, 0 changed) * include_server/test_data/dfoo/foo2.h: edit 2007/10/03 12:04:55 Fergus Henderson Change distcc so that it generates the correct value for the "current directory" field in the debug info. I do this by mmapping the ".o" file into memory, parsing the ELF headers to find the ".debug_info" section, and then doing a blind string search and replace in that section. This should be quite safe: although there is a remote possibility of false hits, they will only affect the debug_info section. R=iant,klarlund CC=distcc-pump APPROVED=klarlund DELTA=628 (594 added, 5 deleted, 29 changed) * distcc/Makefile.in: edit * distcc/configure.ac: edit * distcc/src/config.h.in: edit * distcc/src/fix_debug_info.c: add * distcc/src/serve.c: edit * distcc/test/testdistcc.py: edit 2007/09/28 17:52:51 Nils Klarlund Fix .d target error. This error was unfortunately introduced with a previous change, which corrected other errors and attempted to put this logic into a unit test straightjacket. R=fergus,manos DELTA=2 (0 added, 1 deleted, 1 changed) * distcc/src/dotd.c: edit * distcc/test/testdistcc.py: edit 2007/09/28 17:13:53 Nils Klarlund Prepare release of pump13 to overcome bug in yesterday's release. R=fergus,manos * version.sh: edit 2007/09/27 14:18:09 Nils Klarlund Prepare new release. R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/09/26 22:31:54 Nils Klarlund Allow globs in trigger path expressions. R=fergus,manos DELTA=101 (85 added, 0 deleted, 16 changed) * include_server/include_analyzer.py: edit * include_server/include_analyzer_test.py: edit * include_server/include_server.py: edit * pump.in: edit 2007/09/26 22:01:05 Nils Klarlund Fix parsing of -D options to allow for function-like macros. R=fergus,manos DELTA=88 (55 added, 28 deleted, 5 changed) * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_analyzer_test.py: edit * include_server/parse_file.py: edit * include_server/test_data/func_macro.c: add 2007/09/26 21:51:45 Nils Klarlund The interpretation of the # operator of CPP was incorrect because whitespace after # was not ignored. For example, # a must expand to "a" not "" a We fix this problem here. R=fergus,manos DELTA=3 (2 added, 0 deleted, 1 changed) * include_server/macro_eval.py: edit * include_server/macro_eval_test.py: edit 2007/09/21 22:57:17 Fergus Henderson Fix two compiler warnings, one of them serious: - The type of the "len" argument in a call to PyArg_ParseType("#s", &string, &len) must be "int", not "size_t". This could cause serious problems for a 64-bit architecture. - Include "distcc.h" before the other header file, so that we get the definition of 'enum dcc_protover' before it is used. R=klarlund CC=distcc-pump DELTA=4 (1 added, 2 deleted, 1 changed) * include_server/c_extensions/distcc_pump_c_extensions_module.c: edit 2007/09/21 22:56:33 Fergus Henderson When compiling the distcc code and the extension module, enable C compiler warnings ("-Wall -Wextra"), and enforce them ("-Werror"). Also make sure that we compile with "-D_GNU_SOURCE", since distcc uses that, and we need that to avoid some compiler warnings. R=klarlund CC=distcc-pump DELTA=3 (0 added, 0 deleted, 3 changed) * include_server/setup.py: edit 2007/09/21 22:56:08 Fergus Henderson Pass the "-v" (verbose) option to "autoreconf". R=klarlund DELTA=1 (0 added, 0 deleted, 1 changed) * run_all_autoconf.sh: edit 2007/09/21 13:41:36 Nils Klarlund Fix bugs in dcc_get_dotd_info that give rise to erroneous .d file names or erroneous target names in .d files. - If derived from the file name given by -o, then the suffix must be stripped before .d is appended. - If the file name ends in '.', then only "d" is appended. - If an -o name is given and the name ends in '.', then this name, not the input filename, is still to be used for the name of the .d file. - If a target is provided in DEPENDENCIES_OUTPUT, then this target must be returned -- otherwise the .d file computed on the server will be incorrect if the target happens not to be the object file. Extra: a test for the length of the string in variable extension was unnecessary. Tests: We made a unit test that exercices the function in a number of ways. Heuristics about the names of .d files, expressed as globs, are used to pinpoint the actual naming conventions used by gcc. R=manos,fergus DELTA=255 (217 added, 20 deleted, 18 changed) * distcc/Makefile.in: edit * distcc/src/dotd.c: edit * distcc/src/h_dotd.c: add * distcc/test/testdistcc.py: edit 2007/09/20 11:36:58 Nils Klarlund Fix sending of emails by include server. Avoid sending emails when translation unit could not be found or if command line is malformed. Also, fix buglet that made the previous translation unit name appear in the case of malformed command line. R=fergus,manos DELTA=6 (2 added, 0 deleted, 4 changed) * include_server/include_analyzer.py: edit * include_server/include_server_test.py: edit * include_server/parse_command.py: edit 2007/09/20 11:33:48 Nils Klarlund Prepare new release to include "Reset caches more aggressively". R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/09/20 07:54:03 Nils Klarlund Reset caches more aggressively. According to a bug report, there are uncommon build situations where distcc-pump fails. We address this by: -- Making sure to reset the cache use by the link-gathering mechanism of mirror_path in the include server. This is a real bug although probably not the culprit. -- Also monitoring 'includes/third_party/stl/third_party/stl', which is the symbolic link changed (with path-doubling) by the set symlink mechanism of the third_party/stl/BUILD file. R=fergus,manos DELTA=6 (5 added, 0 deleted, 1 changed) * include_server/include_analyzer.py: edit * include_server/mirror_path.py: edit * pump.in: edit 2007/09/18 13:03:49 Nils Klarlund Prepare 'pump10' release. This release is to correct minor issues such as interaction with ccache and the handling of command line -D options. R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/09/18 12:59:45 Nils Klarlund Correct two mistakes in the handling of filepaths: -- an elementary one in basics.py: the rstrip() function of string is functional -- a more tricky one: in an include of the form "#include ./foo.h", we must normalize the file name to 'foo.h', otherwise an infinite regression would occur if foo.h includes ./foo.h. R=fergus,manos DELTA=13 (10 added, 1 deleted, 2 changed) * include_server/basics.py: edit * include_server/cache_basics.py: edit 2007/09/17 14:51:56 Nils Klarlund Fix client to change protocol version from 3 (pump) to 2 (plain) in situations involving already preprocessed code, such as arising from ccache use, or involving certain insidious environment variables. Test: make -C distcc valgrind-check R=fergus,manos DELTA=41 (40 added, 1 deleted, 0 changed) * distcc/src/compile.c: edit 2007/09/17 13:56:56 Nils Klarlund When announcing pump installation, show the real location -- unmasked by symbolic links. R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * pump.in: edit 2007/09/17 13:26:48 Fergus Henderson Fix a bug in "pump --startup": don't print out a setting for DISTCC_HOSTS if we didn't set DISTCC_HOSTS. (Note: this is not an urgent fix, because I've made Blaze work around the bug. But worth fixing nevertheless.) R=klarlund CC=distcc-pump DELTA=3 (2 added, 0 deleted, 1 changed) * pump.in: edit 2007/09/17 12:33:21 Nils Klarlund Make 'pump' executable. R=fergus,manos DELTA=2 (1 added, 0 deleted, 1 changed) * configure.ac: edit 2007/09/17 09:48:08 Nils Klarlund Propagate symbols defined through -D options to include analyzer. This makes computed includes operable wtih values provided on the command line. Tests: 1. New tests exercise that when reissuing an analysis for the same file and with same search directories, but with a symbol definition affecting a previously computed include, the include graph is recalculated, not reused, and the new value of the symbol is used for resolving the computed include. 2. The new code was also verified to solve the problem reported in a bug report (I used a workstation in ZRH to build the actual code that cause the issue). 3. I did 'make maintainer-check'. R=fergus,manos DELTA=66 (56 added, 0 deleted, 10 changed) * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_analyzer_memoizing_node_test.py: edit * include_server/include_analyzer_test.py: edit * include_server/parse_command.py: edit * include_server/parse_command_test.py: edit 2007/09/15 21:47:49 Nils Klarlund Update a comment as per Fergus's review comment for a previous change. R=fergus,manos DELTA=3 (1 added, 0 deleted, 2 changed) * include_server/compiler_defaults.py: edit 2007/09/13 23:40:04 Nils Klarlund Introduces mechanism for monitoring the real paths that are resolved during include analysis. Invoke as --realpath_warning_re=RE. For more, see include_server.py, Usage() in this CL. This allows a user to find out which source files are actually picked out by the include analysis during the build. Such information can useful if it is suspected that include directories are wrong. TESTING: this CL passes make check and make maintainer-check. It was tested earlier on Google software as part of the discussion of this feature now found on the distcc-pump wiki. From the wiki: INCLUDE_SERVER_ARGS='--realpath_warning_re=RE' make-dbg .... makes the include server write a warning to stderr whenever a filename is resolved to a realpath (a canonicalized absolute pathname - see 'man realpath') that is matched by RE, which is a regular expression in Python syntax. For example, to find out which C/C++ files from /home/build/buildonly are used during a build of gws:gws, do: INCLUDE_SERVER_ARGS='--realpath_warning_re=/auto/buildonly' make-dbg -distcc_pump -g0 gws:gws Then, you will see messages like: WARNING include server: For translation unit 'foo/bar.cc' while processing 'foo/bar.cc' lookup of file 'baz.h' resolved to '../whatever/baz.h' whose realpath is '/auto/whatever/blah/blah/baz.h'. (Here we have formatted the message from it's one-liner original.) Note that the include server currently does not identify the header file containing the #include for which the realpath matched, but only the translation unit. Also, because of caching in the include server, a message for a particular resolution appears usually only once. Thus this analysis cannot be used to find out which files a particular compilation unit uses. R=fergus,manos DELTA=42 (40 added, 0 deleted, 2 changed) * include_server/basics.py: edit * include_server/cache_basics.py: edit * include_server/include_server.py: edit 2007/09/13 23:15:37 Nils Klarlund Introduce flag for NotCoveredError exceptions that specify whether email is to be sent or not. We use this parameter to suppress warnings that related to #include "/foo/bar.h" and similar uses. Also, clean up of some error messages (add '.'). We fix a few typos and unneeded variables (e.g.: opt_build_stat_verify), while we're looking at these files. Additionally, improve NotCovered messages by adding the file name (in most cases). Finally, introduce option --no-email to negate the default of --email in the pump script if so desired through INCLUDE_SERVER_ARGS. TESTING: This change passes 'make check' and 'make maintainer-check'. We also ran system tests and verified that occurences of #include "/foo/bar.h" now does not result in mail being generated. These tests are not part of this changelist, but contained in another change. R=manos,fergus DELTA=186 (93 added, 49 deleted, 44 changed) * include_server/basics.py: edit * include_server/cache_basics.py: edit * include_server/include_server.py: edit * include_server/include_server_test.py: edit * include_server/parse_file.py: edit 2007/09/13 18:18:25 Nils Klarlund Reorganize and extend tests: - move existing tests in include_server.py to new include_server_test.py - test the main 'handler' in include_server, including how exceptions, such as internal error, affect automated email generation R=fergus,manos DELTA=613 (374 added, 198 deleted, 41 changed) * include_server/Makefile.in: edit * include_server/include_analyzer_test.py: add * include_server/include_server_test.py: edit * include_server/test_data/contains_abs_include.c: add 2007/09/13 14:54:43 Nils Klarlund Prepare for release; bump to version 'pump9'. R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/09/13 14:41:34 Nils Klarlund Remove Google crosstool specification (which made the build fail anyway). R=manos,fergus DELTA=1 (0 added, 0 deleted, 1 changed) * build-distcc.sh: edit 2007/09/13 14:38:24 Nils Klarlund Correct flawed configuration scripts and introduce configuration sanity checks. autoconfig assumes that if an .ac script has not changed then the resulting configure scripts do not need to change. This assumption is untrue because we use a shell escape. (This escape has been rewritten according to Fergus's suggestion.) Moreover, m4 caches processed files. This royally messes up things beyond and in addition to just the aforementioned problem. We fix this by using autoreconf (suggested by Fergus). It seems to address these issues. We have verified that: ./run_all_autoconf.sh; ./configure; make clean; make all works and embeds a changed version number (in version.sh) in the right places. With further CLs "Remove Google crosstool specification" and "Introduce needed cast.", it is possible to use ./build-distcc.sh to make RPM and .deb packages. R=fergus,manos DELTA=76 (36 added, 20 deleted, 20 changed) * Makefile.in: edit * configure.ac: edit * distcc/configure.ac: edit * include_server/configure.ac: edit * run_all_autoconf.sh: edit * version.sh: edit 2007/09/13 14:21:11 Nils Klarlund Introduce needed cast. This problem was detected with gcc version 4.0.3 (Ubuntu 4.0.3-1ubuntu5). R=fergus,manos DELTA=3 (2 added, 0 deleted, 1 changed) * distcc/src/stats.c: edit 2007/09/13 14:18:44 Nils Klarlund Not deleting .d files breaks the build sometimes. R=fergus,manos DELTA=4 (1 added, 0 deleted, 3 changed) * distcc/Makefile.in: edit 2007/09/12 21:08:29 Fergus Henderson Use the standard autoconf substitution process to create pump from pump.in, rather than a hand-crafted Makefile rule. R=klarlund CC=distcc-pump DELTA=16 (4 added, 6 deleted, 6 changed) * Makefile.in: edit * configure.ac: edit * pump.in: edit 2007/09/12 20:49:57 Fergus Henderson Fix a Posix conformance bug: we were passing the same fd set to select() for both the writeable fd set and the error fd set, but according to Posix (specifically The Open Group Base Specifications Issue 6, available at ), the arguments to select() are declared with the "restrict" attribute, which means they must not be aliased. Also, issue a trace message in the case when select() returns due to an error condition on the fd rather than because the fd has become writable. R=manos CC=distcc-pump DELTA=23 (18 added, 0 deleted, 5 changed) * distcc/src/io.c: edit 2007/09/12 18:57:03 Fergus Henderson Fix manual memory management bugs, and simplify the memory management a bit. dcc_set_output() was inconsistent about whether it copied its input argument or aliased it, about whether it freed the previous value in that slot. I changed the function so that it always copies the input argument, and always frees the previous value in the argv array slot that it is about to overwrite. I likewise changed dcc_set_input to copy its argument. dcc_set_output() was also inconsistent about whether or not it logged the change to the argument; I fixed that too, by always logging it. In serve.c I simplified the code and comments a little - there is no longer any aliasing going on, so the deallocation logic is simpler. R=manos CC=distcc-pump DELTA=35 (9 added, 12 deleted, 14 changed) * distcc/src/arg.c: edit * distcc/src/serve.c: edit 2007/09/12 18:51:05 Fergus Henderson Add support for running a single test case at a time, rather than running all of them. This is useful for debugging. R=manos CC=distcc-pump APPROVED=klarlund DELTA=46 (46 added, 0 deleted, 0 changed) * distcc/Makefile.in: edit * distcc/test/onetest.py: add 2007/09/12 18:48:53 Fergus Henderson Fix a timing dependence in the distcc test suite that caused the 'NoDetachDaemon_Case' test case to sometimes fail when run under valgrind. Specifically, when running the server in --no-detach mode, wait until the server starts accepting connections before running the test, rather than just waiting 0.5 seconds, which under valgrind is not always long enough. R=klarlund CC=distcc-pump DELTA=6 (3 added, 0 deleted, 3 changed) * distcc/test/testdistcc.py: edit 2007/09/12 18:47:34 Fergus Henderson Add "--startup" and "--shutdown" options to the pump script, for use by Blaze. Blaze can't use the ordinary mode of the pump script, because the Blaze server's lifetime is greater than the lifetime of the include server. R=klarlund CC=distcc-pump DELTA=181 (119 added, 12 deleted, 50 changed) * pump.in: edit 2007/09/11 13:59:25 Nils Klarlund Annul enviroment when probing for built-in include path. Fixes subtle problem reported in a bug report. R=fergus,manos DELTA=6 (3 added, 0 deleted, 3 changed) * include_server/compiler_defaults.py: edit 2007/09/11 12:37:56 Nils Klarlund Fix leftover comment from earlier fix: delete it. R=manos DELTA=3 (0 added, 3 deleted, 0 changed) * include_server/include_analyzer_memoizing_node.py: edit 2007/09/06 16:02:39 Nils Klarlund Improve mechanishm for overcoming unsoundness in build system. Change the semantics of stat_reset_triggers so that the changing of a symbolic link during the build triggers a reset of all include server caches. R=fergus,manos DELTA=57 (28 added, 1 deleted, 28 changed) * include_server/basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_server.py: edit * include_server/include_server_test.py: edit 2007/09/05 15:50:58 Fergus Henderson Make distcc warning-free: - Remove "-Wconversion" from CFLAGS; this warning was useful for writing code that had to be compatible with pre-C89 C compilers that didn't support prototypes, but that isn't needed anymore, and it causes too many spurious warnings for perfectly legitimate code. - Add "-Wno-unused" to cflags for popt/*.c; those files have a bunch of unused parameters. - Eliminate all the remaining compiler warnings. - Add "-Werror" to CFLAGS so we won't get any regressions! TESTED = make maintainer-check valgrind-check R=manos CC=distcc-pump APPROVED=manos DELTA=56 (27 added, 6 deleted, 23 changed) * distcc/Makefile.in: edit * distcc/configure.ac: edit * distcc/popt/popt.c: edit * distcc/popt/popt.h: edit * distcc/popt/popthelp.c: edit * distcc/src/bulk.c: edit * distcc/src/emaillog.c: edit * distcc/src/exec.c: edit * distcc/src/hosts.c: edit * distcc/src/include_server_if.c: edit * distcc/src/lsdistcc.c: edit * distcc/src/prefork.c: edit * distcc/src/srvnet.c: edit * distcc/src/stats.c: edit 2007/08/30 14:01:37 Manos Renieris When receiving a string, print it out. R=klarlund,fergus DELTA=2 (2 added, 0 deleted, 0 changed) * distcc/src/rpc.c: edit 2007/08/30 13:58:45 Nils Klarlund Make tracing for client print out strings that are sent, not just their lengths. R=manos DELTA=1 (0 added, 0 deleted, 1 changed) * distcc/src/rpc.c: edit 2007/08/29 21:44:15 Nils Klarlund Fix bug in include server that gives rise to the include server being unable to find the translation unit. Also, delete some unneeded variables and make the remaining ones lowercased. R=manos,fergus DELTA=86 (73 added, 0 deleted, 13 changed) * include_server/basics.py: edit * include_server/basics_test.py: add * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/08/29 21:35:45 Nils Klarlund Prepare new release. R=manos,fergus DELTA=3 (2 added, 0 deleted, 1 changed) * version.sh: edit 2007/08/28 17:56:22 Nils Klarlund Fix typos incidentally introduced in a previous change -- and fix a function that scrubs file names in a test; it didn't work with links. R=manos DELTA=10 (1 added, 0 deleted, 9 changed) * include_server/include_server.py: edit * include_server/include_server_test.py: edit 2007/08/28 17:50:46 Nils Klarlund Add test files, missing from a previous change. R=manos,fergus APPROVED=manos DELTA=1 (1 added, 0 deleted, 0 changed) * include_server/test_data/dfoo/stat_triggers.h: add * include_server/test_data/stat_triggers.c: add * include_server/test_data/stat_triggers.h: add 2007/08/28 17:47:06 Manos Renieris Observe the HAVE_SENDFILE config variable. R=klarlund DELTA=7 (6 added, 0 deleted, 1 changed) * distcc/src/bulk.c: edit 2007/08/28 16:23:43 Nils Klarlund Make a central place for defining versions. Remove various generated files from source control. R=manos,fergus DELTA=13450 (41 added, 13401 deleted, 8 changed) * INSTALL: edit * build-distcc.sh: edit * configure: delete * configure.ac: edit * distcc/configure: delete * distcc/configure.ac: edit * include_server/configure: delete * include_server/configure.ac: edit * run_all_autoconf.sh: add * version.sh: add 2007/08/28 12:41:59 Nils Klarlund New option --stat_reset_triggers. The --stat_reset_triggers argument is a list of path names. If any such path changes from non-existing to existing during the build, then all stat-related caches are cleared. A test in include_server_test.py checks that the include analysis of a file is done from scratch after a trigger path went from non-existing to existing. R=manos,fergus DELTA=229 (174 added, 44 deleted, 11 changed) * include_server/basics.py: edit * include_server/cache_basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_server.py: edit * include_server/include_server_test.py: edit * pump.in: edit 2007/08/27 14:05:26 Manos Renieris Part of a change from Nils, with a test added. This once fixes the #include"foobar" case. R=klarlund,fergus APPROVED=klarlund DELTA=5 (4 added, 0 deleted, 1 changed) * include_server/parse_file.py: edit * include_server/parse_file_test.py: edit 2007/08/27 13:56:47 Manos Renieris Part of a change from Nils. This one adds support for the -include flag. I've moved the test data and added a test for parse_command.py. R=klarlund,fergus APPROVED=klarlund DELTA=1545 (1498 added, 9 deleted, 38 changed) * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node_test.py: edit * include_server/parse_command_test.py: edit * include_server/test_data/distcc/README: add * include_server/test_data/distcc/src/bulk.h: add * include_server/test_data/distcc/src/compile.h: add * include_server/test_data/distcc/src/config.h: add * include_server/test_data/distcc/src/distcc.c: add * include_server/test_data/distcc/src/distcc.h: add * include_server/test_data/distcc/src/emaillog.h: add * include_server/test_data/distcc/src/exitcode.h: add * include_server/test_data/distcc/src/hosts.h: add * include_server/test_data/distcc/src/implicit.h: add * include_server/test_data/distcc/src/include_me.h: add * include_server/test_data/distcc/src/state.h: add * include_server/test_data/distcc/src/trace.h: add * include_server/test_data/distcc/src/util.h: add 2007/08/27 13:05:08 Manos Renieris Report the client ip if we refuse a connection. R=dkegel,klarlund,fergus CC=ahyun DELTA=14 (7 added, 1 deleted, 6 changed) * distcc/src/srvnet.c: edit 2007/08/20 13:21:57 Manos Renieris Add include_analyzer_memoizing_node_test to the list of tests. R=klarlund,fergus DELTA=2 (1 added, 0 deleted, 1 changed) * include_server/Makefile.in: edit 2007/08/20 12:00:47 Manos Renieris Minimize the output during tests; it obscures the test results. R=klarlund,fergus APPROVED=klarlund DELTA=22 (1 added, 1 deleted, 20 changed) * include_server/c_extensions_test.py: edit * include_server/include_server_test.py: edit * include_server/macro_eval_test.py: edit 2007/08/10 11:21:02 Nils Klarlund Fix a bug: memoization in the central FindNode algorithm was too optimistic. R=fergus,manos DELTA=20 (0 added, 20 deleted, 0 changed) * include_server/include_analyzer_memoizing_node.py: edit 2007/08/08 17:42:57 Nils Klarlund Make include server not write a stack trace when the exception is NotCovered. Such a situation is not bad. Also, remove a couple of unnecessary imports. R=manos,fergus DELTA=19 (5 added, 4 deleted, 10 changed) * include_server/include_server.py: edit 2007/08/08 15:22:54 Nils Klarlund More missing test files. This time for computed includes. R=fergus,manos APPROVED=manos DELTA=21 (21 added, 0 deleted, 0 changed) * include_server/test_data/test_computed_includes/helper.c: add * include_server/test_data/test_computed_includes/incl.h: add * include_server/test_data/test_computed_includes/inclA.h: add * include_server/test_data/test_computed_includes/src.c: add * include_server/test_data/test_computed_includes/srcA.c: add 2007/08/08 00:58:27 Nils Klarlund Fix the problem that stat's in the main 'Resolve' routine of cache_basics were based on os.path.exists, not on os.path.isfile. Write new test to verify that the behavior is now correct. Fix little problem in compress_files.py R=fergus,manos APPROVED=fergus,manos DELTA=88 (66 added, 0 deleted, 22 changed) * include_server/c_extensions/distcc_pump_c_extensions_module.c: edit * include_server/c_extensions_test.py: edit * include_server/cache_basics.py: edit * include_server/compress_files.py: edit * include_server/include_server_test.py: edit * include_server/test_data/dfoo/i_am_perhaps_a_directory.h: add * include_server/test_data/i_am_perhaps_a_directory.h/empty_file: add * include_server/test_data/test_directory_probing.c: add 2007/08/07 23:06:24 Nils Klarlund 'make test' was failing --- this CL fixes that. R=fergus,manos DELTA=1 (1 added, 0 deleted, 0 changed) * include_server/setup.py: edit 2007/08/07 23:06:00 Nils Klarlund Make release subversion = pump6. R=fergus,manos DELTA=31 (0 added, 0 deleted, 31 changed) * build-distcc.sh: edit * configure: edit * configure.ac: edit * distcc/configure: edit * distcc/configure.ac: edit * include_server/configure: edit * include_server/configure.ac: edit 2007/08/07 16:26:27 Manos Renieris a) Include the server side error messages in the maintainer email b) Don't output them on the screen. R=fergus,klarlund DELTA=116 (107 added, 1 deleted, 8 changed) * distcc/src/bulk.c: edit * distcc/src/bulk.h: edit * distcc/src/clirpc.c: edit * distcc/src/compile.c: edit * distcc/src/compile.h: edit * distcc/src/distcc.h: edit * distcc/src/emaillog.c: edit * distcc/src/emaillog.h: edit * distcc/src/remote.c: edit 2007/08/07 16:20:57 Manos Renieris For testing purposes, add a way to stub out the include server. R=fergus,klarlund DELTA=73 (72 added, 1 deleted, 0 changed) * distcc/src/include_server_if.c: edit * distcc/src/util.c: edit * distcc/src/util.h: edit 2007/08/06 23:07:25 Nils Klarlund Reintroduced 'introspection' so that an installed package can be moved from say buildstaticrw to buildstatic with all references to executables moving along. Added overide mechanism as well. Also, introduced a necessary check when running off source directory so see whether there's more than on .so file. Finally, changed messages so that we're printing a message that the include server has started instead of one indicating that is starting. R=fergus,manos DELTA=74 (52 added, 9 deleted, 13 changed) * Makefile.in: edit * pump.in: edit 2007/08/06 21:56:31 Nils Klarlund Various minor changes in response to comment by Fergus for a previous change. R=fergus DELTA=12 (3 added, 0 deleted, 9 changed) * include_server/include_server.py: edit 2007/08/06 14:29:44 Nils Klarlund Check that /dev/shm is actually writable and executable. Also, correct two very, very minor mistakes. R=fergus,manos DELTA=14 (4 added, 1 deleted, 9 changed) * include_server/basics.py: edit * include_server/compress_files.py: edit * include_server/include_server.py: edit 2007/08/02 16:15:06 Nils Klarlund Add email notifications from include server. Delete email notifications from distcc client when caused by include server providing an error indication. Features: - new command line flags for enabling emails for exception conditions - a limit on the number of emails sent due to NotCovered exception - stack trace is included Testing: - tested new commnand line arguments - tested for each of the three exception handlers where email is sent that email is indeed being sent - 'make test' for include_server R=fergus,manos DELTA=106 (86 added, 2 deleted, 18 changed) * distcc/src/compile.c: edit * include_server/basics.py: edit * include_server/include_server.py: edit * pump.in: edit 2007/08/02 14:40:27 Nils Klarlund Add option -t or --time for total time spent in include server to be printed on stderr. Example: Include server timing. Elapsed: 18.2s User: 0.1s System: 0.0s Total: 0.1s R=fergus,manos DELTA=47 (32 added, 0 deleted, 15 changed) * include_server/basics.py: edit * include_server/include_server.py: edit 2007/08/01 17:33:50 Nils Klarlund Make the handling of computed includes sound. Upto now, the include server failed to reprocess a file F with the property: - F transitively includes a file G - G contains a computed include and the support of its expression contains a symbol X - X is defined or redefined after G is processed the first time We hope to compile OpenOffice with this fix. Little things: - Fixed include_analyzer_memoizing_node_test.py to allow regression test for distcc itself to pass. - Removed dead code EvalExprDirs in include_analyzer.py. Correctness testing: - In include_server: 'make test' works. - Function test_AdvancedComputedIncludes is added in 'include_server/include_server_test.py'. It contains the basic scenario we are correcting for. - We ran multiple tests 'make-dbg -r -j80 third_party/lzo'; every test succeeded. These did not succeed with existing version. - We built gws:gws and localsearch/mustang Performance testing: For make-dbg gws:gws -g0, the best time before the change: make-dbg real 7m44.230s user 7m0.494s sys 2m25.385s Include server Elapsed: 463.9s User: 72.5s System: 37.3s Total: 109.9s The best time after: make-dbg real 7m44.772s user 6m46.249s sys 2m2.944s Include server Elapsed: 464.6s User: 87.4s System: 36.9s User + System: 124.3s Thus, it seems that we've added 15s or about 8% to the include server time. (These times are on a hyperthreaded machine and therefore hard to interpret.) Remarks: the central algorithm still is in the need of refactoring. That 8% running time was added because of the current change adds to my impression that the refactoring must be done with care. R=fergus,manos DELTA=316 (237 added, 25 deleted, 54 changed) * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_analyzer_memoizing_node_test.py: edit * include_server/include_server_test.py: edit * include_server/macro_eval.py: edit * include_server/macro_eval_test.py: edit * include_server/parse_file.py: edit 2007/07/30 17:10:04 Manos Renieris Bump up the release number. R=klarlund,fergus DELTA=1 (0 added, 0 deleted, 1 changed) * build-distcc.sh: edit 2007/07/27 20:23:30 Manos Renieris Push declaration to the top of block so that it's more portable. TBR=klarlund,fergus DELTA=4 (2 added, 2 deleted, 0 changed) * distcc/src/compile.c: edit * distcc/src/serve.c: edit 2007/07/27 19:40:59 Manos Renieris Respect the second part of the DEPENDENCIES_OUTPUT env variable. R=fergus,klarlund DELTA=79 (65 added, 5 deleted, 9 changed) * distcc/src/compile.c: edit * distcc/src/distcc.h: edit * distcc/src/dotd.c: edit * distcc/src/dotd.h: edit * distcc/src/serve.c: edit 2007/07/27 09:09:53 Nils Klarlund This file went MIA. This CL will make 'make -C include_server test' pass. R=fergus,manos DELTA=14 (14 added, 0 deleted, 0 changed) * include_server/test_data/more_macros.c: add 2007/07/26 21:25:25 Manos Renieris Print the protocol description even if opt_numeric is true. R=fergus,klarlund DELTA=4 (1 added, 0 deleted, 3 changed) * distcc/src/lsdistcc.c: edit 2007/07/26 15:39:00 Manos Renieris Explicitly rewrite the .d file dependency on the server; -MT does not work quite as advertised (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12448): gcc adds the argument of -MT to the list of object files in the dependencies, rather than replacing the default object file name with the argument of -MT; dotd does not tolerate two object files in the .d file. R=fergus,klarlund DELTA=71 (59 added, 5 deleted, 7 changed) * distcc/src/compile.c: edit * distcc/src/dotd.c: edit * distcc/src/dotd.h: edit * distcc/src/serve.c: edit 2007/07/26 15:07:34 Fergus Henderson Add -Wuninitialized to CFLAGS. TESTED= Ran "autoconf && configure && make clean && make" and verified that no new warnings were generated. R=manos CC=distcc-pump DELTA=2 (2 added, 0 deleted, 0 changed) * distcc/configure: edit * distcc/configure.ac: edit 2007/07/25 11:28:33 Manos Renieris Don't output the statistics for the doti file if there is no doti file. R=fergus,klarlund DELTA=1 (0 added, 0 deleted, 1 changed) * distcc/src/remote.c: edit 2007/07/25 11:26:03 Manos Renieris Fix a (serious) bug. sets_dotd was not initialized, and we were not rewritting the dependency in the .d file. R=fergus,klarlund DELTA=2 (1 added, 0 deleted, 1 changed) * distcc/src/compile.c: edit * distcc/src/dotd.c: edit 2007/07/24 17:33:23 Manos Renieris Always close the file descriptors after communicating with the server, regardless of how soon we bail out. R=fergus,klarlund DELTA=19 (9 added, 9 deleted, 1 changed) * distcc/src/remote.c: edit 2007/07/18 19:49:54 Manos Renieris Don't try to send the preprocessed file to the server if the local preprocessing failed. Otherwise, either the file sent to the server is wrong, or it does not exist at all. In the first case, the result of the compilation is wrong. In the second, trying to send an existing file is considered a communication or remote error, and we end up thinking that the remote host is down or in some other way unresponsive. Under the current fallback mode, this ends up printing the erro messages from local preprocessing twice, once while its trying to preprocess the file to send it to the server, and once while trying to compile locally. I think that's ok. R=fergus,klarlund DELTA=3 (3 added, 0 deleted, 0 changed) * distcc/src/remote.c: edit 2007/07/18 16:21:35 Manos Renieris Added some notes on the implementation of protocol version 3. R=fergus,klarlund DELTA=61 (61 added, 0 deleted, 0 changed) * distcc/doc/protocol-3-impl.txt: add 2007/07/13 14:22:13 Manos Renieris Tiny change to use the phony feature directly for the pump target. R=klarlund,fergus DELTA=5 (1 added, 3 deleted, 1 changed) * Makefile.in: edit 2007/07/12 15:17:54 Nils Klarlund Addressing Fergus's comments for a previous change + more changes. R=fergus,manos DELTA=45 (27 added, 6 deleted, 12 changed) * README: edit 2007/07/10 17:18:31 Manos Renieris Added a description for protocol version 3. R=klarlund,fergus DELTA=82 (82 added, 0 deleted, 0 changed) * distcc/doc/protocol-3.txt: add 2007/07/09 16:01:36 Nils Klarlund New subversion number for packages. R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * build-distcc.sh: edit 2007/07/09 13:50:11 Nils Klarlund When using --verbose, the variable denoting the option level is not touched. So, --verbose is not equivalent to setting the option level to 'debug' as the manual says. This is fixed. R=fergus,manos DELTA=1 (1 added, 0 deleted, 0 changed) * distcc/src/dopt.c: edit 2007/07/09 13:41:11 Nils Klarlund Simplify memory allocation strategy in dcc_run_job. Tests: 'make valgrind-check'. R=fergus,manos DELTA=22 (9 added, 3 deleted, 10 changed) * distcc/src/serve.c: edit 2007/07/05 14:38:09 Nils Klarlund Fix server and include server to allow absolute translation unit. I refactored a bit to cut down the length of dcc_run_job (which is still too long). TESTING: I have verified that regexp-options.cc now compiles on pump server. I have compiled several hundred other files. Also, I verified that 'make valgrind-check' passes. Note: a problem occurred in an lsdistcc test. The output from lsdistcc was not in the expected order. I changed the test to sort the output before the comparison. R=fergus,manos DELTA=241 (145 added, 76 deleted, 20 changed) * distcc/src/serve.c: edit * distcc/test/testdistcc.py: edit * include_server/include_analyzer.py: edit 2007/06/29 15:19:42 Nils Klarlund Fix email address in comments and code by introducing an abstraction. R=fergus,manos DELTA=7 (1 added, 0 deleted, 6 changed) * distcc/src/compile.c: edit * distcc/src/emaillog.c: edit * distcc/src/emaillog.h: edit 2007/06/29 15:15:39 Nils Klarlund Fix problem that a stack trace was produced for Ctrl-C. In particular, we discovered that printing out args[0] of the instance object is not wise, because an index error may ensue. R=fergus,manos DELTA=20 (9 added, 5 deleted, 6 changed) * include_server/include_server.py: edit 2007/06/28 18:30:54 Nils Klarlund Remove offensive code. I'm now handling configuring of pump in an auxiliary script, also called 'pump'. R=fergus,manos DELTA=11 (0 added, 8 deleted, 3 changed) * Makefile.in: edit * pump.in: edit 2007/06/28 15:51:09 Manos Renieris Change the address we send errors to. R=fergus,klarlund DELTA=1 (0 added, 0 deleted, 1 changed) * distcc/src/emaillog.c: edit 2007/06/26 22:03:23 Manos Renieris Added -Pprotocol option, which will print out only the servers that support (at least) the given protocol. lsdistcc wll now print the protocol type out with the host i.e. host.domain.com,lzo. R=fergus,klarlund CC=distcc-pump DELTA=134 (116 added, 9 deleted, 9 changed) * distcc/Makefile.in: edit * distcc/src/lsdistcc.c: edit 2007/06/21 17:45:39 Manos Renieris Tell the user why they are seeing error messages twice. R=fergus,klarlund DELTA=3 (2 added, 0 deleted, 1 changed) * distcc/src/compile.c: edit 2007/06/21 16:40:25 Manos Renieris Forgot emaillog.h. Oops! R=fergus,klarlund DELTA=8 (8 added, 0 deleted, 0 changed) * distcc/src/emaillog.h: add 2007/06/21 13:04:17 Manos Renieris Add email logging. R=klarlund,fergus DELTA=170 (137 added, 15 deleted, 18 changed) * distcc/Makefile.in: edit * distcc/src/compile.c: edit * distcc/src/distcc.c: edit * distcc/src/emaillog.c: add * distcc/src/trace.c: edit * distcc/src/traceenv.c: edit 2007/06/20 16:10:59 Nils Klarlund Fix spelling error in Makefile.in, bump-up subversion number. R=fergus,manos DELTA=2 (0 added, 0 deleted, 2 changed) * build-distcc.sh: edit * include_server/Makefile.in: edit 2007/06/20 15:36:43 Nils Klarlund Further enviroment variables for controlling behavior of include server when invoked through pump. Also, we fixed the problem that for the common situation that configure is run in the top level directory of the source tree it was impossible to run 'pump'. The solution is to regard the script alteration by the Makefile rule for 'pump' something that regards mainly the installed version. The source tree version of pump finds its Python files in the source directory and its .so file under the 'build/lib.xxx/include_server' subdirectory of th scr directory. Finally, we took out the hardcoding for values of the potential distcc servers. When the make rule for 'pump' is run, the environment variable DISTCC_POTENTIAL_HOSTS with its current value is copied into 'pump' -- if it is set. So, now I prepare distribution by doing: DISTCC_POTENTIAL_HOSTS="test-distcc1.ame test-distcc2.ame test-distcc3.ame test-distcc4.ame test-distcc5.ame pump1.ame pump2.ame pump3.ame pump4.ame pump5.ame pump6.ame pump7.ame pump8.ame pump9.ame distcc1" make pump This also of course makes the 'pump' script work in the source directory, where it'll now pick up the servers I specified for the ad hoc and regression tests I run. With this machinery, I was again able to easily test the other pending changelists for the include server. * Makefile.in: edit * pump.in: edit 2007/06/20 01:38:51 Fergus Henderson When aborting, make sure we exit with a non-zero exit status. TBR=klarlund * include_server/include_server.py: edit 2007/06/19 23:44:15 Nils Klarlund Fix the problem that source was nuked by 'make clean'. R=manos,fergus DELTA=6 (0 added, 1 deleted, 5 changed) * include_server/Makefile.in: edit 2007/06/19 23:41:55 Nils Klarlund Reapplying after rollback. Make --verify mode work with the include server and improve error reporting. An internal error would now look like: WARNING: Preprocessing locally. Include server internal error: 'exceptions.TypeError: expected string or buffer' for translation unit 'maps/frontend/geocode_api_renderer.cc' We also fix a bug regarding TERM signal that would not properly terminate an include server. R=fergus,manos DELTA=58 (38 added, 2 deleted, 18 changed) * include_server/cache_basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/06/19 23:39:46 Nils Klarlund We fix several bugs in the include server. - The macro evaluator has been completely rewritten. In particular, it can now be used to parse files in maps/frontend that involve computed includes like: #include MAPS_TEMPLATE_VARNAMES(map_kml_results) - We also now parse macro calls on arguments that contain macro calls. - We implement the 'disabled' semantics of macro invocation (for infinite recursion prevention). - We now apply # and ## only as part of expanding function-like macros. - We added several new tests, in part taken from the CPP Internals document. - A test for ResolveExpr with pedagodical value has been added (and another file for this test to work). - The macro evaluator has been thouroughly commented. - The parser has been updated so that it no longer thinks that '//' within a filepath is a C++ comment. - The parser's handling of macro calls (and definitions) was improved. Note that we now only use the parser's understanding of macros for function-like defines, not for macro invocations, which are treated in a new routine in macro_eval. R=fergus,manos DELTA=531 (373 added, 68 deleted, 90 changed) * include_server/macro_eval.py: edit * include_server/macro_eval_test.py: edit * include_server/parse_file.py: edit * include_server/parse_file_test.py: edit * include_server/test_data/maps/foo.tpl.varnames.h: add * include_server/test_data/parse.c: edit 2007/06/19 13:27:49 Manos Renieris Update the rpm prefix to be /usr, because that's where the init.d scripts expect it. R=klarlund,fergus DELTA=4 (0 added, 0 deleted, 4 changed) * distcc.spec: edit 2007/06/18 23:10:26 Fergus Henderson Give better error messages in cases where we can't determine the compiler's default search path(s). Also don't try to terminate the include server in those cases (it wasn't actually terminating anyway, since the sys.exit() exception was being caught by the SocketServer class, I think). R=karlund CC=distcc-pump DELTA=17 (9 added, 0 deleted, 8 changed) * include_server/compiler_defaults.py: edit 2007/06/15 15:07:45 Fergus Henderson Another change towards getting "make check" working again. TBR=manos * include_server/Makefile.in: edit 2007/06/15 14:58:27 Fergus Henderson Make the "pump" target depend on the "Makefile" target, so that it gets rebuilt if you configure with a different prefix. This is in response to manos' verbal post-submit review comments on a previous change. TBR=manos * Makefile.in: edit 2007/06/15 14:52:08 Nils Klarlund This CL was submitted too early. Automated g4 rollback of a previous change: Make --verify mode work with the include server and improve error reporting. An internal error would now look like: WARNING: Preprocessing locally. Include server internal error: 'exceptions.TypeError: expected string or buffer' for translation unit 'maps/frontend/geocode_api_renderer.cc' We fix a bug regarding TERM signal that would not properly terminate an include server. * include_server/cache_basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/06/15 14:35:39 Fergus Henderson Fix bugs with the generation of the "pump" script from "pump.in": - $ was not properly escaped and was being interpreted by Make rather than the shell - the pump.in script that is being copied could be read-only and we did not (a) remove the old read-only copy nor (b) make the new copy writable. - pump should be a real target, not a phony target - we need a dependency "all: pump" P.S. After syncing this change, you need to run "autoconf" (or sync Manos' change which updated the configure script), "configure", and then "make". TBR=manos CC=distcc-pump DELTA=5 (1 added, 0 deleted, 4 changed) * Makefile.in: edit 2007/06/15 14:33:52 Fergus Henderson Temporary work-around for problem where "make clean" nukes the source tree. TBR=manos,klarlund * include_server/Makefile.in: edit 2007/06/15 14:26:45 Fergus Henderson Add support for running tests in lzo mode or in pump mode. R=manos CC=distcc-pump DELTA=38 (27 added, 2 deleted, 9 changed) * distcc/Makefile.in: edit * distcc/test/testdistcc.py: edit 2007/06/15 13:34:48 Manos Renieris Update the configure script. Remove pump, which is now generated by make. R=klarlund,fergus DELTA=272 (52 added, 219 deleted, 1 changed) * configure: edit * pump: delete 2007/06/15 07:13:52 Nils Klarlund Fix file permission to +x. R=manos * build-distcc.sh: edit 2007/06/14 22:51:35 Nils Klarlund Make --verify mode work with the include server and improve error reporting. An internal error would now look like: WARNING: Preprocessing locally. Include server internal error: 'exceptions.TypeError: expected string or buffer' for translation unit 'maps/frontend/geocode_api_renderer.cc' We fix a bug regarding TERM signal that would not properly terminate an include server. R=fergus,manos * include_server/cache_basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/06/14 17:21:22 Manos Renieris Script and spec file for building rpm. R=fergus,klarlund DELTA=490 (490 added, 0 deleted, 0 changed) * build-distcc.sh: add * distcc.spec: add 2007/06/14 16:10:47 Manos Renieris Add DESTDIR so that rpm building can find the pump script. R=fergus,klarlund DELTA=6 (3 added, 0 deleted, 3 changed) * Makefile.in: edit 2007/06/14 14:06:05 Manos Renieris Revamp the configure/make/make install process: - the python building and installation is done by setup.py. - include_server is now a python package. - include_server/c_extensions is not buildable by itself anymore. - include_server tests are build into their own directory. - the pump script is "finished" at make time, before install. - run.py is not needed anymore R=fergus,klarlund DELTA=633 (456 added, 147 deleted, 30 changed) * Makefile.in: edit * configure.ac: edit * distcc/configure: edit * distcc/configure.ac: edit * include_server/Makefile.in: edit * include_server/__init__.py: add * include_server/c_extensions/Makefile.in: delete * include_server/c_extensions/setup.py: delete * include_server/c_extensions_test.py: edit * include_server/configure: edit * include_server/configure.ac: edit * include_server/setup.py: add * pump.in: add 2007/06/11 16:30:54 Nils Klarlund Improving start-up time. It turns out that the include server is not the bottleneck -- it's about 200ms to start it. But lsdistcc is. So with change I'm just trying to save that amount of time by starting the include server while doing lsdistcc. R=fergus,manos DELTA=106 (70 added, 2 deleted, 34 changed) * pump: edit 2007/06/11 16:22:37 Nils Klarlund Fix "ERROR: failed to connect to UNIX-DOMAIN /dev/shm/include-server: Resource temporarily unavailable". The former assignment to server.request_queue_size was ineffectual because this parameter is used by the constructor for a server. The parameter is passed to socket.listen. R=manos,fergus DELTA=22 (17 added, 2 deleted, 3 changed) * include_server/include_server.py: edit 2007/06/08 18:15:16 Fergus Henderson Some minor fixes to avoid warnings from gcc. Also a small bug fix: when cleanup_tempfiles is invoked from a signal handler, we should not call free(), because it is unsafe to call free() from an asynchronous signal handler that could be executed in the middle of another call to malloc() or free(). Also fix the use of volatile in cleanup_tempfiles. R=manos CC=distcc-pump DELTA=87 (42 added, 16 deleted, 29 changed) * distcc/src/cleanup.c: edit * distcc/src/distcc.c: edit * distcc/src/distcc.h: edit * distcc/src/dsignal.c: edit * distcc/src/trace.c: edit * distcc/src/util.c: edit 2007/06/08 17:52:40 Fergus Henderson Allow ".i" and ".ii" file names as inputs to the include server. Also some improvements to the messages produced by the include server. R=klarlund CC=distcc-pump DELTA=26 (11 added, 7 deleted, 8 changed) * include_server/basics.py: edit * include_server/include_server.py: edit * include_server/parse_command.py: edit * include_server/parse_file.py: edit * include_server/run.py: edit 2007/06/08 16:40:16 Nils Klarlund Improve warning messages regarding include server failures. R=fergus,manos DELTA=3 (2 added, 0 deleted, 1 changed) * distcc/src/compile.c: edit * distcc/src/include_server_if.c: edit 2007/06/07 21:41:25 Manos Renieris Put all declarations before executable code, for compatibility with older C compilers. R=fergus,klarlund DELTA=15 (6 added, 7 deleted, 2 changed) * distcc/src/clirpc.c: edit * distcc/src/include_server_if.c: edit * distcc/src/srvrpc.c: edit * include_server/c_extensions/distcc_pump_c_extensions_module.c: edit 2007/06/07 15:47:57 Nils Klarlund Check that execution of gcc to find defaults succeeds and warns appropriately if not. R=fergus,manos DELTA=17 (11 added, 5 deleted, 1 changed) * include_server/compiler_defaults.py: edit 2007/06/07 15:41:55 Nils Klarlund Fixed bugs from the autoconf conversions. Now, the include server extension builds. R=fergus,manos DELTA=8 (0 added, 3 deleted, 5 changed) * distcc/Makefile.in: edit * include_server/c_extensions/setup.py: edit 2007/06/05 14:50:22 Nils Klarlund Fixes: so that we can find the include server, also in installation. Note that we erase previous value of PYTHONPATH for performance reasons. R=fergus DELTA=137 (91 added, 23 deleted, 23 changed) * include_server/run.py: edit * pump: edit 2007/06/04 17:46:36 Nils Klarlund This is to repair a previous change, which I submitted by mistake. This CL together with the previous CL fix bugs: - check that include_server_pid exists before killing it - don't strip \n before stuffing hosts into temporary variable Also fixes a couple of minor syntax issues in comments. R=manos,fergus DELTA=4 (1 added, 0 deleted, 3 changed) * pump: edit 2007/06/04 16:04:51 Fergus Henderson Fix a bug where we were attempting to use memory that had already been freed. (I detected this by running the tests under valgrind.) R=manos CC=distcc-pump DELTA=19 (13 added, 0 deleted, 6 changed) * distcc/src/serve.c: edit 2007/06/04 14:53:03 Nils Klarlund Fixed bug: 'opts' were appended to only last host. Fixed very minor syntax issues in comments. * pump: edit 2007/06/04 14:32:33 Fergus Henderson 1. Use srcdir rather than top_srcdir to locate the mkinstalldirs script; now that distcc_pump has its own autoconf-generated configure script, top_srcdir is now "distcc_pump" rather than "distcc". 2. Add USE_VALGRIND variable, and use it in the maintainer-check rule, so that you can do 'make USE_VALGRIND=--valgrind" maintainer-check' to run the tests under valgrind. R=manos CC=distcc-pump DELTA=7 (5 added, 0 deleted, 2 changed) * distcc/Makefile.in: edit 2007/06/04 13:43:00 Manos Renieris Make lsdistcc 80 columns wide. R=klarlund,fergus DELTA=199 (113 added, 5 deleted, 81 changed) * distcc/src/lsdistcc.c: edit 2007/06/04 11:40:08 Fergus Henderson Add support for running tests under valgrind. R=manos CC=distcc-pump DELTA=108 (59 added, 3 deleted, 46 changed) * distcc/test/testdistcc.py: edit 2007/06/04 11:31:24 Fergus Henderson Add "install" targets to the makefiles. Use autoconf-generated configure scripts, in order to support the standard configure options such as '--prefix', etc. R=klarlund CC=distcc-pump DELTA=4959 (4816 added, 110 deleted, 33 changed) * Makefile: delete * Makefile.in: add * configure: edit * configure.ac: add * include_server/Makefile: delete * include_server/Makefile.in: add * include_server/c_extensions/Makefile: delete * include_server/c_extensions/Makefile.in: add * include_server/configure: add * include_server/configure.ac: add 2007/06/04 11:20:11 Fergus Henderson Rewrite the pump script using functions. Use lowercase names for shell variables that are local to this process. Document the DISTCC_PUMP_LOCATION environment variable in the usage message. Ensure error messages go to stderr rather than stdout. Fix some problems with the cleanup: the order of cleanup was wrong. It was doing "rmdir $SOCKET_DIR" before "rm $SOCKET", which meant the rmdir could fail since the directory isn't empty yet. Check for "lsdistcc" in the same directory as "pump", if it isn't found in the "distcc" subdirectory. R=klarlund CC=manos,distcc-pump DELTA=197 (119 added, 51 deleted, 27 changed) * pump: edit 2007/06/04 00:27:53 Fergus Henderson Use gcc's automatic dependency generation. Without this change, the Makefile was missing dependencies on all the header files, so editing say src/distcc.h and then running "make" would not cause a recompile. R=manos CC=distcc-pump DELTA=5 (3 added, 0 deleted, 2 changed) * distcc/Makefile.in: edit * distcc/configure: edit * distcc/configure.ac: edit 2007/06/01 19:24:28 Nils Klarlund Handshake mechanism for starting include server. Introduce os.fork() in include server, so that the parent returns right after starting the child. The child becomes the real include server. Change options so as to allow the parent to write the child pid to a file. That will allow an invoking script to send SIGTERM to the include server later. Fix missing deletion of temp file in include_server. Also, fixed bug: the initialization of the temp directory was done twice, from two different modules. R=fergus,manos DELTA=168 (85 added, 8 deleted, 75 changed) * include_server/basics.py: edit * include_server/include_server.py: edit * pump: edit 2007/06/01 19:06:50 Nils Klarlund Change file permission to +x. * distcc/contrib/distccd-on-servers: edit 2007/06/01 19:04:28 Nils Klarlund New tests for include analyzer; corrections to DirNameCache. DirnameCache was hardcoded to return absolute directories -- that was wrong. Also, define helper function RetrieveDirectoriesExceptSys in cache_basic for test purposes. Make _CalculateIncludeClosureExceptSystem call Fillcache so as to avoid prerequisite condition. Fix missing deletion of temp file in include_server. Fix another couple of minor bugs. R=fergus,manos DELTA=331 (266 added, 21 deleted, 44 changed) * include_server/Makefile: edit * include_server/cache_basics.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_analyzer_memoizing_node_test.py: add * include_server/include_server_test.py: edit * include_server/parse_command_test.py: edit * include_server/run.py: edit 2007/06/01 15:48:51 Nils Klarlund Fixes bug so that 'status' works as intended. Also fixes bugs that meant that the return command was given a non-integer argument. R=fergus,manos DELTA=17 (3 added, 0 deleted, 14 changed) * distcc/contrib/distccd-on-servers: edit 2007/06/01 13:22:00 Manos Renieris Plug memory leaks in the server. R=klarlund,fergus CC=distcc-pump DELTA=111 (54 added, 26 deleted, 31 changed) * distcc/src/arg.c: edit * distcc/src/serve.c: edit * distcc/src/srvrpc.c: edit 2007/05/31 20:26:35 Nils Klarlund Initial submission: script for handling distccd on servers. R=fergus,manos DELTA=142 (142 added, 0 deleted, 0 changed) * distcc/contrib/distccd-on-servers: add 2007/05/31 19:14:53 Fergus Henderson Change the distcc_pump Makefile and configure script to support building with the build directory being different than the source directory, e.g. mkdir obj cd obj ../configure make R=klarlund CC=distcc-pump DELTA=144 (91 added, 14 deleted, 39 changed) * INSTALL: edit * Makefile: edit * configure: edit * distcc/Makefile.in: edit * include_server/Makefile: edit * include_server/c_extensions/Makefile: edit * include_server/c_extensions/setup.py: edit * include_server/run.py: edit 2007/05/31 15:32:41 Manos Renieris Retry connecting if we get EAGAIN. R=klarlund,fergus DELTA=5 (4 added, 0 deleted, 1 changed) * distcc/src/clinet.c: edit 2007/05/30 20:13:37 Nils Klarlund Continuing "Continuing cleanup of the code...", we fix various tiny buglets and wipe unnecessary variables from mirror-path. TESTED=(cd include_closure; make test) R=fergus CC=csilvers DELTA=24 (0 added, 17 deleted, 7 changed) * include_server/compiler_defaults.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/macro_eval.py: edit * include_server/mirror_path.py: edit * include_server/mirror_path_test.py: edit 2007/05/30 16:59:02 Craig Silverstein Continuing cleanup of the code, mostly to get varnames to be consistent. But also some functionality changes: 1) Separated out the realpath_map into two data structures, one that canonicalizes the paths, and the other that keeps the systemdir-prefix information. Both are now part of the mondo-cache object. There's still a bit more work to be done to get the systemdir-prefix cache working intuitively. 2) Added RelpathMapToIndex, which requires that its keys not start with a /. Use this new class for includepaths, so we get better error checking; we'll now correctly fail when we see code like #include , which we can't handle properly. 3) [smaller] We now fall back on the python equivalents if we don't have the C-speedups for realpath and stat(). 4) [smaller] Modified the convenience functions to be per data-type rather than per varialbe: we have SearchdirIndex and CurrdirIndex rather than just DirectoryIndex. (Since this function is never used, it doesn't really matter, but...) These were more syntactic cleanup: 1) Use currdir everywhere to mean the current directory, to match cache_basics.py. 2) I started some comment changes to be more consistent. For instance, every time we had a realpath_map argument, I try to say what a realpath_map is (in one line!) rather than just say its type -- which is, admittedly, better than nothing. Only small work done here; still lots more. 3) Some places are still using fp instead of includepath. I've fixed up most, but for some I'm not sure that the fp is an includepath exactly, so I'm waiting to clean those up. 4) Several places would pass a list in to a routine by reference, so the procedure would fill the passed-in list rather than returning a new list. This can be more efficient, but is harder to follow, especially in python where pass-by-value is expected. Change to a more natural control-flow in situations where efficiency isn't critical. I also corrected the following deviations from the style guide: 1) (Almost) no "naked" exceptions. Before there was lots of "try: os-operation except: die". Now we actually check that it's an IOError or an OSError. We also now print out the 'why' status as part of the error message. 2) Got rid of unused imports. 3) Made sure there was at least two spaces between code and end-of-line comments. Still more places to fix this one... 4) Nixed trailing whitespace (at the end of each line). R=klarlund DELTA=719 (297 added, 193 deleted, 229 changed) * include_server/basics.py: edit * include_server/cache_basics.py: edit * include_server/compiler_defaults.py: edit * include_server/compress_files.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_server.py: edit * include_server/include_server_test.py: edit * include_server/macro_eval.py: edit * include_server/macro_eval_test.py: edit * include_server/mirror_path.py: edit * include_server/mirror_path_test.py: edit * include_server/parse_command_test.py: edit * include_server/parse_file.py: edit * include_server/parse_file_test.py: edit 2007/05/25 18:35:29 Nils Klarlund The sed -i command I ran to perform renaming according to cache_basics.py tricked me; these files were not added to my CL that took care of several little changes. I have verified that make -C include_server test now works. R=fergus,csilvers DELTA=8 (0 added, 0 deleted, 8 changed) * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_server_test.py: edit * include_server/mirror_path_test.py: edit 2007/05/25 17:53:45 Nils Klarlund Installation and use improvements. Now the 'pump' wrapper is generic; no-hardcoded hosts, but a an environment variable must be set. Also, it uses lsdistcc to discover which potential hosts are actually ready. The INSTALL instructions are still rudimentary, but improved. The 'configure' script simply calls 'configure' in distcc subdir. R=fergus,csilvers DELTA=82 (47 added, 33 deleted, 2 changed) * INSTALL: edit * configure: add * pump: edit 2007/05/25 16:05:37 Nils Klarlund Add test targets. R=fergus DELTA=26 (26 added, 0 deleted, 0 changed) * include_server/Makefile: edit 2007/05/25 15:49:30 Nils Klarlund It turns out that the gcc system path discovery command creates a temporary file. Make tempdir to overcome this problem. R=fergus,manos DELTA=14 (4 added, 0 deleted, 10 changed) * include_server/compiler_defaults.py: edit 2007/05/25 15:48:56 Nils Klarlund Make safer tempdir mechanism. R=fergus DELTA=4 (1 added, 0 deleted, 3 changed) * include_server/basics.py: edit 2007/05/25 15:47:27 Nils Klarlund Lots of little changes for final integration. One theme: names changes. R=fergus,manos DELTA=145 (51 added, 26 deleted, 68 changed) * include_server/include_analyzer.py: edit * include_server/include_server.py: edit * include_server/macro_eval_test.py: edit * include_server/mirror_path.py: edit * include_server/parse_command_test.py: edit * include_server/parse_file.py: edit * include_server/parse_file_test.py: edit * include_server/statistics.py: edit * include_server/test_data/gws-main.o.cmd: edit 2007/05/25 15:17:51 Nils Klarlund This CL should have accompanied "This CL is in response to csilvers's questions.." * include_server/parse_command.py: edit 2007/05/25 15:15:43 Nils Klarlund Initial submission: "Compress files in an include closure." * include_server/compress_files.py: add 2007/05/25 13:47:00 Nils Klarlund A unittest for module mirror_path, featuring dependency injection. This version is working. It replaces something that didn't. R=fergus,manos DELTA=121 (87 added, 3 deleted, 31 changed) * include_server/mirror_path_test.py: edit 2007/05/25 11:38:56 Nils Klarlund Initial submit of module to compute approximation of include dependencies for C/C++. Also, some accompanying changes to basics.py * include_server/basics.py: edit * include_server/include_server.py: add * include_server/include_server_test.py: add 2007/05/25 11:29:51 Nils Klarlund Wrapper script for distcc-pump test users. R=fergus,manos DELTA=80 (80 added, 0 deleted, 0 changed) * pump: add 2007/05/24 21:49:42 Fergus Henderson Add -r option to lsdistcc to specify which port to connect to. ("-p", "-o", and "-t" were already taken.) Fix a bug where "lsdistcc distcc%d" was only returning the first host. Add some unit tests for lsdistcc. Also tidy up the usage message a little. R=manos CC=distcc-pump,dkegel,aaw DELTA=57 (47 added, 0 deleted, 10 changed) * distcc/src/lsdistcc.c: edit * distcc/test/testdistcc.py: edit 2007/05/24 18:12:30 Fergus Henderson Fix a bug that broke "cd distcc; configure; make": move definition of the "echo_common_obj" target to the end of the file, so that it doesn't become the default target (Make treats the first rule in the file as the default target). R=klarlund CC=distcc-pump DELTA=10 (5 added, 5 deleted, 0 changed) * distcc/Makefile.in: edit 2007/05/24 14:17:43 Nils Klarlund Fix "Usage" logic and printing error. Improve error reporting when path to execute is not found. R=fergus,manos DELTA=12 (7 added, 0 deleted, 5 changed) * include_server/run.py: edit 2007/05/24 09:14:17 Nils Klarlund Tests for distcc_pump_c_extensions. Writes out doc strings and calls some distcc rpc functions. Also, times the speed-up of using libc versions of os.path.realpath and os.path.exists. R=fergus,manos DELTA=115 (115 added, 0 deleted, 0 changed) * include_server/c_extensions_test.py: add 2007/05/24 09:11:50 Nils Klarlund A file used for testing parse_command.py. Should not be part of open source release. * include_server/test_data/gws-main.o.cmd: add 2007/05/24 09:03:57 Nils Klarlund Wrapper for running include server and tests. Initial submission. R=fergus,manos DELTA=49 (49 added, 0 deleted, 0 changed) * include_server/run.py: add 2007/05/23 23:48:11 Nils Klarlund directory and link structure." R=fergus,manos DELTA=159 (159 added, 0 deleted, 0 changed) * include_server/mirror_path.py: add * include_server/mirror_path_test.py: add 2007/05/23 23:12:36 Nils Klarlund Initial submission: CPP macro evaluation. This admittedly needs a little more work as explained. But there are some tests. R=manos,fergus DELTA=338 (338 added, 0 deleted, 0 changed) * include_server/macro_eval.py: add * include_server/macro_eval_test.py: add 2007/05/23 22:31:52 Nils Klarlund Initial submission. include_analyzer: "The skeleton, including caches, of an include analyzer." include_analyzer_memoizing_node: "An graph-based algorithm for memoizing include closure calculations. R=fergus,csilvers DELTA=545 (545 added, 0 deleted, 0 changed) * include_server/include_analyzer.py: add * include_server/include_analyzer_memoizing_node.py: add 2007/05/23 19:01:57 Craig Silverstein Augment comments and normalize variable names. In addition, clean up the code a bit, mostly by removing redundant code. That said, with the variable-name changing, almost every line in this file is affected by this CL. The file now is at a point where it makes sense to me!, though I am perhaps too close to the algorithm these days to be a good 'outside observer' judge. I think it's more consistent in its naming, in any case. That said, I left in many TODOs where I still need some clarification of functionality, or have cleanups to do later (I tried not to change the functionality too much). Some outside-visible function/variable names may have changed as a result of this CL, so other changes may be needed to get the system working again after this. R=klarlund DELTA=411 (108 added, 35 deleted, 268 changed) * include_server/cache_basics.py: edit 2007/05/22 15:25:09 Nils Klarlund This bunch of files is used for various tests of the include server. I submit them as a bundle for further perusal with the various *_test.py code. R=fergus,manos DELTA=52 (52 added, 0 deleted, 0 changed) * include_server/test_data/abc_post.c: add * include_server/test_data/abc_pre.c: add * include_server/test_data/computed_includes.c: add * include_server/test_data/dbar/dbar1/bar.h: add * include_server/test_data/dbar/foo.h: add * include_server/test_data/dfoo/foo.h: add * include_server/test_data/dfoo/foo2.h: add * include_server/test_data/dfoo/include_next_foo.h: add * include_server/test_data/include_include_next_foo.h: add * include_server/test_data/p1.h: add * include_server/test_data/parse.c: add * include_server/test_data/test_include_next/bar/x.h: add * include_server/test_data/test_include_next/bar/y.h: add * include_server/test_data/test_include_next/baz/start_x.c: add * include_server/test_data/test_include_next/baz/start_y.c: add * include_server/test_data/test_include_next/baz/x.h: add * include_server/test_data/test_include_next/baz/y.h: add * include_server/test_data/test_include_next/biz/x.h: add * include_server/test_data/test_include_next/foo/x.h: add * include_server/test_data/test_include_next/foo/y.h: add 2007/05/21 18:37:57 Manos Renieris Change the test regexp to match the version text. R=fergus,klarlund DELTA=4 (2 added, 0 deleted, 2 changed) * distcc/test/testdistcc.py: edit 2007/05/21 18:29:41 Nils Klarlund Initial submission. "How to find system path defaults for gcc." R=fergus,manos APPROVED=fergus DELTA=136 (136 added, 0 deleted, 0 changed) * include_server/compiler_defaults.py: add 2007/05/21 17:01:16 Nils Klarlund Initial submissin. Statistics gathering for the distcc-pump include server. R=fergus,manos DELTA=110 (110 added, 0 deleted, 0 changed) * include_server/statistics.py: add 2007/05/21 12:09:10 Nils Klarlund This CL is in response to csilvers's questions about the use of indices and caches in the include server. I've tried to make the terminology coherent and to make the distinction between indexed and string representation clearer. Also, I moved the actual use of the classes into function SetUpCaches that constructs the intended hierarchy for memoization. Now: also includes parse_command. R=fergus,csilvers CC=manos DELTA=410 (184 added, 40 deleted, 186 changed) * include_server/cache_basics.py: edit 2007/05/21 11:59:41 Manos Renieris Initialize needs_dotd. R=klarlund,fergus DELTA=1 (0 added, 0 deleted, 1 changed) * distcc/src/compile.c: edit 2007/05/21 11:59:13 Manos Renieris Fix the cleanup function. R=klarlund,fergus DELTA=3 (0 added, 0 deleted, 3 changed) * distcc/src/cleanup.c: edit 2007/05/18 17:22:48 Manos Renieris Added the new files and one missing file to the Makefile. R=klarlund,fergus DELTA=8 (3 added, 0 deleted, 5 changed) * distcc/Makefile.in: edit 2007/05/18 11:37:55 Manos Renieris Undo the local_cpu lock if we are using the include server. R=fergus,klarlund DELTA=6 (5 added, 0 deleted, 1 changed) * distcc/src/compile.c: edit 2007/05/17 18:21:26 Nils Klarlund Initial check-in of directives-only C/C++ parser. R=manos,fergus DELTA=395 (395 added, 0 deleted, 0 changed) * include_server/parse_file.py: add * include_server/parse_file_test.py: add 2007/05/17 17:27:24 Nils Klarlund This change accompanies a previous change. It allows the extension module to extract the needed .o files from the distcc Makefile. R=fergus,manos DELTA=5 (5 added, 0 deleted, 0 changed) * distcc/Makefile.in: edit 2007/05/17 16:15:36 Nils Klarlund This CL enables us to compile distcc and to install the Python extension module that provides access to some distcc rpc functions as well as lzo. It no longer uses the Python interface that is part of the lzo distribution. The CL also include some initial attempts a Makefile's. R=fergus,manos DELTA=467 (467 added, 0 deleted, 0 changed) * INSTALL: add * Makefile: add * include_server/Makefile: add * include_server/c_extensions/Makefile: add * include_server/c_extensions/distcc_pump_c_extensions_module.c: add * include_server/c_extensions/setup.py: add 2007/05/17 11:09:39 Nils Klarlund Include server for distcc-pump. The basic stuff. Initial submit. The basic caching mechanisms for distcc-pump. Initial submit. R=manos,fergus DELTA=596 (596 added, 0 deleted, 0 changed) * include_server/basics.py: add * include_server/cache_basics.py: add 2007/05/16 17:03:03 Fergus Henderson Update the output from "distcc --version". 1. src/help.c: mention that it supports version 3 of the protocol, i.e. distcc_pump 2. configure.ac: change version to "distcc 2.18.3-13gg-pump1" rather than "distcc 2.18.3", i.e. include both a. "-13gg" to show it has all the existing Google patches, and b. "-pump1" for the distcc_pump extensions that support preprocessing on the server. 3. configure: regenerate based on the new configure.ac. This resulted in some slight differences due to different autoconf versions, but they appear innocuous. TESTED=Ran make and manually verified the output of "distcc --version" and "distccd --version". Tried running "make maintainer-check"; that failed, but I think the failures are unrelated to my change (probably they're due to problems with the merge of distcc-pump with the Google distcc patches). R=manos CC=distcc-pump DELTA=135 (24 added, 86 deleted, 25 changed) * distcc/configure: edit * distcc/configure.ac: edit * distcc/src/help.c: edit 2007/05/16 15:04:29 Manos Renieris Change the name of the temp directories to reflect that they are server-side. R=fergus,klarlund DELTA=1 (0 added, 0 deleted, 1 changed) * distcc/src/tempfile.c: edit 2007/05/14 17:16:41 Craig Silverstein Rewrite the argument-parser to be more efficient: this code now runs about 50% faster than it used to (tested by time_ParseCommandArguments.py). I can't totally vouch for the fact the output is the same now as before, since there's not a complete test for this code yet, but it seems to be on the one example I tried. Also, a few TODOs remain to deal with some obscure cases I didn't understand (how does "-iquote=foo" differ from "-iquote foo"?). But the basics should be right on. R=klarlund,fergus DELTA=295 (153 added, 76 deleted, 66 changed) * include_server/parse_command.py: edit * include_server/parse_command_test.py: edit 2007/05/14 17:05:15 Manos Renieris Improve the robustness of cleanup. R=klarlund,fergus DELTA=33 (18 added, 1 deleted, 14 changed) * distcc/src/cleanup.c: edit * distcc/src/srvrpc.c: edit * distcc/src/tempfile.c: edit 2007/05/14 11:37:26 Manos Renieris Mark the top tmp directory for deletion. R=fergus,klarlund DELTA=3 (3 added, 0 deleted, 0 changed) * distcc/src/tempfile.c: edit 2007/05/14 11:22:04 Manos Renieris Close the file descriptors after being done talking to the include server. R=klarlund,fergus DELTA=14 (11 added, 1 deleted, 2 changed) * distcc/src/include_server_if.c: edit 2007/05/10 10:04:32 Nils Klarlund The routines for interpreting a gcc command, along with tests. Two issues still to be resolved: - This code is too slow. - For computed includes, we need to parse -D etc. R=fergus,manos DELTA=518 (518 added, 0 deleted, 0 changed) * include_server/parse_command.py: add * include_server/parse_command_test.py: add 2007/05/09 23:13:18 Fergus Henderson Update Makefile.in to fix some bugs introduced in CL a previous change (which just applied the Google and LSB-specific patches). Some object files had been moved into $(common_obj), but were still listed in h_*_obj, resulting in duplicate symbol errors when running "make maintainer-check". R=manos CC=dkegel,klarlund DELTA=3 (0 added, 1 deleted, 2 changed) * distcc/Makefile.in: edit 2007/05/09 19:12:09 Manos Renieris A bit more const-correctness. R=fergus DELTA=6 (2 added, 0 deleted, 4 changed) * distcc/src/serve.c: edit 2007/05/09 18:41:10 Manos Renieris Distcc-pump first implementation. Various little changes, making functions from static into global, all around the code; a bug fix in argutil.c. Important changes are: - On the protocol, which is extended as "version 3", that supports compression and also cpp on the server. - distcc.h: Added the enum for where to do the cpp. - hosts.c: Map a set of features (currently a subset of where to do cpp and whether to do compression) onto a protocol number. - rpc.c: The client sometimes sends either a file, or a link to the server. The server needs to be able to accept either, so dcc_r_sometoken_int allows some alternation to the protocol. - Talking to the include server: - compile.c: dcc_build_somewhere tries to talk to the include server, and pushes the information about the dotd file to dcc_compile_remote. This is where the fallback-to-the-original-protocol code lives. - include_server_if.c: Talk to the include server. - The communication from client to server. The client needs to send multiple files, and perhaps links, to the server; the client also needs to sent its current working directory, - remote.c: Entry points for sending multiple files to the server. - rpc.c: The server needs to handle not only files, but also links (directories are handled implicitly). - clirpc.c: Added a function to send the current working directory. Added a function, dcc_x_many_files. It sends multiple files to the server. In addition, it changes the filenames to chop off the additions of the include server. - serve.c: Added a function to receive the current working directory. - On the server side, the server receives multiple files, and the working directory, builds a directory structure (which it keeps of, to clean it up at the end) - srvrpc.c: Added a function, dcc_r_many_files, to receive multiple files. In addition, it changes the filenames to put all the files under a "fake root" directory. - serve.c: lots of work to set up "fake root" directories, chdir to the right place, produce a .d file, and absolutize include directives. - tempfile.c: Creation of whole temp directories, not just files. - cleanup.c: Since we are receiving multiple files, we need to keep a dynamic list of what temporary files we create. It can now handle directories. - ".d" files: the client needs to find out where the dotd file should go; the server needs to produce it, remove all references to the local filesystem (gcc can't do that from the outside) and send it back to the client. - dotd.c: Most of the code that handles the dotd: figuring out if we need it, and where it should go; also, cleaning it up after it gets created on the server. - clirpc.c Changed dcc_retrieve_results to retrieve the dotd file. R=klarlund,fergus DELTA=1208 (1058 added, 36 deleted, 114 changed) * distcc/Makefile.in: edit * distcc/README.google: add * distcc/src/arg.c: edit * distcc/src/argutil.c: edit * distcc/src/bulk.c: edit * distcc/src/bulk.h: edit * distcc/src/cleanup.c: edit * distcc/src/clinet.c: edit * distcc/src/clinet.h: edit * distcc/src/clirpc.c: edit * distcc/src/compile.c: edit * distcc/src/compile.h: edit * distcc/src/compress.c: edit * distcc/src/distcc.h: edit * distcc/src/dotd.c: add * distcc/src/dotd.h: add * distcc/src/filename.c: edit * distcc/src/hosts.c: edit * distcc/src/hosts.h: edit * distcc/src/include_server_if.c: add * distcc/src/include_server_if.h: add * distcc/src/lock.c: edit * distcc/src/remote.c: edit * distcc/src/rpc.c: edit * distcc/src/rpc.h: edit * distcc/src/serve.c: edit * distcc/src/srvrpc.c: edit * distcc/src/tempfile.c: edit 2007/05/08 17:53:54 Manos Renieris A few "\n\" were missing. R=fergus,klarlund DELTA=4 (0 added, 0 deleted, 4 changed) * distcc/src/lsdistcc.c: edit ## More changes that were made internally to Google, and not integrated ## into the main distcc distribution until 2008. These log messages ## are from the RPM spec file's changlog. * Thu Jun 14 2007 Manos Renieris - Added all the distcc-pump related parts to distcc.spec. - Changed the way the package is built. - Remove source package generation. - Man pages are now unzipped. * Mon Feb 8 2007 Dongmin Zhang - Added hosts list option to lsdistcc, such that lsdistcc can check only the hosts listed on the given list. The host list is given in command line. * Wed Jan 31 2007 Dongmin Zhang - Added _libdir definition in rpms.epc. - Changed Name, Version, and Release to the ones passed by --define. - Updated the server init script to give different path of ACL files for grhat and goobuntu as suggested by Arthur Hyun . * Mon Jan 22 2007 Dongmin Zhang - Fixed a bug in timeout patch. Added sigaction to catch SIGCHLD such that the select() in dcc_collect_child() could break out when the file is finished to compile. * Fri Dec 1 2006 Ollie Wild - Removed the 01-distcc-gdb-20051210.patch patch. The parser in this was too naive to deal with output generate with the -directives-only flag. Also, it should no longer be needed with recent versions of gcc. - Removed the 10-distcc-before-cpp_locking-sub-gdb.patch and 12-distcc-after-cpp_locking-add-gdb.patch patches. These were just modifying the former patch. * Fri Sep 8 2006 Michael Moss - Update install and init scripts to work on Debian and Red Hat (allowing the .rpm to be converted to .deb with alien, and then installed on Debian). Some noteworthy changes: - Deb - Remove unused defaults file /etc/default/distcc. - Deb - No longer uses debconf. - RH - useradd is run in post- rather than pre- install. - RH - distcc server is automatically started. - Added enable/disable commands to init scripts so the daemon can be "permanently" disabled on misbehaving hosts. - Added patches to allow building LSB-compliant binaries. - Reorganized some existing patches to better partition functionality. * Tue Feb 28 2006 Dan Kegel - removed cache again * Mon Feb 20 2006 Dan Kegel - added cache * Mon Feb 6 2006 Dan Kegel - use Josh's randomize patch instead of Michael's, since Josh's seems to perform better in our tests - added disk space statistic on http interface - lsdistcc now has -x option to output info even on down hosts (will be useful for server side caching) * Tue Jan 2 2006 Dan Kegel - removed load shedding patch (we have swap turned on, so overload isn't as bad) - added stats for timeout * Wed Dec 8 2005 Dan Kegel - lsdistcc now has -l option, better -v output - distccd now has nicer logging, --limit-load option, bugfixes in load shedding * Tue Nov 22 2005 Dan Kegel - rejects jobs if load too high - serves up stats via http on port 3633 - lsdistcc now has new -p and -c0 options * Wed Nov 2 2005 Dan Kegel - updated lsdistcc to use the longer of the two of HOST and HOSTNAME to handle shells that set HOST to the nonqualified hostname, but HOSTNAME to the FQDN * Thu Oct 13 2005 Dan Kegel - updated lsdistcc patch - removed gcc as a dependency, since we want to use it with a wide range of other compilers (and in our case, not the standard gcc), and it's impractical to list them all as dependencies * Fri Sep 16 2005 Dan Kegel - now reads /etc/distcc/hosts instead of /usr/etc/distcc/hosts - replaced distcc-2.18.3-rhl.patch with distcc-2.18.3-stringmap.patch The stringmap patch updates the rhl init.d script to know about all installed crosstool toolchains, and enables fuzzy path matching This is useful if the toolchains are not installed at the same prefix on all systems - removed distcc-domain.patch - added distcc-2.18.3-lsdistcc.patch * Sat Sep 3 2005 Dan Kegel - now reads /etc/distcc/hosts instead of /usr/etc/distcc/hosts - applied distcc-domain-2.patch * Thu Jun 15 2005 Dan Kegel - Updated to 2.18.3 - applied --randomize patch and cpp_locking patch - redhat init.d script reads /etc/distccd.allow to construct --allow arguments - added scriptlets from dag's package, but don't start service on install, and call it distcc rather than distccd (to match the current packaging's old practice) ## These changes are from when development was done under bzr. ## bzr branch: http://bazaar.launchpad.net/%7Embp/distcc/trunk/ 2008-03-14 13:31:23 +1100 Martin Pool revno: 4 message: Locks taken through F_SETLK or lockf() must be explicitly released, because closing the file does not do so. (Sascha Demetrio) 2007-09-22 21:32:03 +1000 Martin Pool revno: 3 message: merge avahi patch from Lennart Poettering (http://0pointer.de/public/distcc-avahi.patch) 2007-09-22 21:32:03 +1000 Martin Pool revno: 2 message: Add more ignored files ## These changes are from when development was done under arch. ## arch-tag: automatic-ChangeLog--mbp@sourcefrog.net--2004/distcc--devel--2 2006-04-05 23:35:36 GMT Martin Pool patch-183 Summary: ignore tags file Revision: distcc--devel--2--patch-183 modified files: ChangeLog {arch}/=tagging-method 2006-04-03 17:56:54 GMT Martin Pool patch-182 Summary: build fix for --as-needed Revision: distcc--devel--2--patch-182 modified files: ChangeLog Makefile.in NEWS 2006-03-03 00:10:56 GMT Martin Pool patch-181 Summary: fix error check in dcc_connect_by_add Revision: distcc--devel--2--patch-181 Found in code review from recent list thread -- error check was done incorrectly for nonblocking commits. modified files: ChangeLog src/clinet.c 2006-02-21 05:38:41 GMT Martin Pool patch-180 Summary: draft patch for substituting compiler command name Revision: distcc--devel--2--patch-180 new files: patches/.arch-ids/distcc-substitute-command.diff.id patches/distcc-substitute-command.diff modified files: ChangeLog 2006-01-20 23:40:53 GMT Martin Pool patch-179 Summary: More details on error 110 Revision: distcc--devel--2--patch-179 modified files: ChangeLog man/distcc.1 2006-01-11 04:03:16 GMT Martin Pool patch-178 Summary: set locale when running make maintainer-check Revision: distcc--devel--2--patch-178 modified files: ChangeLog NEWS test/comfychair.py 2006-01-11 03:58:36 GMT Martin Pool patch-177 Summary: Update more benchmark project definitions Revision: distcc--devel--2--patch-177 modified files: ChangeLog bench/ProjectDefs.py test/testdistcc.py 2006-01-05 00:20:52 GMT Martin Pool patch-176 Summary: update benchmark project urls and md5s Revision: distcc--devel--2--patch-176 modified files: ChangeLog bench/ProjectDefs.py 2006-01-05 00:12:56 GMT Martin Pool patch-175 Summary: [patch] update stale benchmark source URLS (Dongmin Zhang) Revision: distcc--devel--2--patch-175 modified files: ChangeLog bench/ProjectDefs.py 2005-12-12 05:47:20 GMT Martin Pool patch-174 Summary: update patch to fix up gdb line numbers Revision: distcc--devel--2--patch-174 Updated patch from Dan Kegel to workaround wrong source file names in debug symbols for older versions of gcc. new files: patches/.arch-ids/fix-line-numbers.diff.id patches/fix-line-numbers.diff removed files: patches/.arch-ids/distcc-line3.diff.id patches/.arch-ids/timj-line1.diff.id patches/distcc-line3.diff patches/timj-line1.diff modified files: ChangeLog 2005-11-28 03:00:58 GMT Martin Pool patch-173 Summary: [patch] cygwin improvements from Alex Besogonov Revision: distcc--devel--2--patch-173 modified files: ChangeLog NEWS src/exec.c src/tempfile.c 2005-11-28 02:50:23 GMT Martin Pool patch-172 Summary: doc Revision: distcc--devel--2--patch-172 modified files: ChangeLog src/exitcode.h 2005-11-28 02:49:19 GMT Martin Pool patch-171 Summary: doc Revision: distcc--devel--2--patch-171 modified files: ChangeLog src/exitcode.h 2005-10-05 00:44:49 GMT Martin Pool patch-170 Summary: return error on timeout in dcc_select_for_write Revision: distcc--devel--2--patch-170 modified files: ChangeLog src/io.c 2005-10-05 00:14:16 GMT Martin Pool patch-169 Summary: bump version number Revision: distcc--devel--2--patch-169 modified files: ChangeLog configure.ac 2005-10-05 00:07:50 GMT Martin Pool patch-168 Summary: use python2.4 if available Revision: distcc--devel--2--patch-168 modified files: ChangeLog NEWS configure.ac 2005-10-05 00:05:20 GMT Martin Pool patch-167 Summary: - better autogen message Revision: distcc--devel--2--patch-167 modified files: ChangeLog autogen.sh 2005-10-05 00:04:18 GMT Martin Pool patch-166 Summary: [patch] better checking for errors on connect() Revision: distcc--devel--2--patch-166 modified files: ChangeLog NEWS src/clinet.c 2005-09-05 01:36:22 GMT Martin Pool patch-165 Summary: add hosts-from-dnsdomain patch from dan Revision: distcc--devel--2--patch-165 new files: patches/.arch-ids/kegel-distcc-domain.patch.id patches/kegel-distcc-domain.patch modified files: ChangeLog 2005-08-16 01:39:54 GMT Martin Pool patch-164 Summary: add note that the mDNS patch cannot be legally merged Revision: distcc--devel--2--patch-164 modified files: ChangeLog patches/howl-mdns.diff 2005-06-10 09:58:57 GMT Martin Pool patch-163 Summary: todo Revision: distcc--devel--2--patch-163 modified files: ChangeLog TODO 2005-01-19 03:17:27 GMT Martin Pool patch-162 Summary: manpage correction from Frerich Revision: distcc--devel--2--patch-162 modified files: ChangeLog man/distcc.1 2004-12-21 02:11:57 GMT Martin Pool patch-161 Summary: args: -d must be local Revision: distcc--devel--2--patch-161 modified files: ChangeLog NEWS src/arg.c test/testdistcc.py 2004-12-20 12:40:10 GMT Martin Pool patch-160 Summary: note on .incbin from asm() Revision: distcc--devel--2--patch-160 new files: doc/todo/.arch-ids/unhandled-cases.txt.id doc/todo/unhandled-cases.txt modified files: ChangeLog 2004-12-15 00:11:05 GMT Martin Pool patch-159 Summary: remove obsolete web targets from makefile Revision: distcc--devel--2--patch-159 modified files: ChangeLog Makefile.in 2004-12-14 07:07:01 GMT Martin Pool patch-158 Summary: add pending Howl mDNS patch from Lennart Poettering Revision: distcc--devel--2--patch-158 new files: patches/.arch-ids/howl-mdns.diff.id patches/howl-mdns.diff modified files: ChangeLog 2004-11-30 19:05:36 GMT Martin Pool patch-157 Summary: Add freshmeat submission data Revision: distcc--devel--2--patch-157 new files: freshmeat/.arch-ids/2.18.3.id freshmeat/.arch-ids/=id freshmeat/2.18.3 modified files: ChangeLog new directories: freshmeat freshmeat/.arch-ids 2004-11-30 12:25:10 GMT Martin Pool patch-156 Summary: Fix for -x and -specs bug Revision: distcc--devel--2--patch-156 modified files: ChangeLog NEWS src/arg.c 2004-11-30 12:11:30 GMT Martin Pool patch-155 Summary: Better text for -x and -specs Revision: distcc--devel--2--patch-155 modified files: ChangeLog NEWS TODO configure.ac test/testdistcc.py 2004-11-12 03:33:34 GMT Martin Pool patch-154 Summary: Prepare for 2.18.2 release Revision: distcc--devel--2--patch-154 modified files: ChangeLog NEWS configure.ac 2004-11-12 03:32:54 GMT Martin Pool patch-153 Summary: Notes on performance influence of mmap Revision: distcc--devel--2--patch-153 new files: doc/.arch-ids/mmap-influence.txt.id doc/mmap-influence.txt modified files: ChangeLog 2004-11-12 03:31:51 GMT Martin Pool patch-152 Summary: fix size_t/unsigned mismatch Revision: distcc--devel--2--patch-152 modified files: ChangeLog NEWS src/distcc.h 2004-11-12 03:23:15 GMT Martin Pool patch-151 Summary: fix for checking uninitialized errno Revision: distcc--devel--2--patch-151 modified files: ChangeLog NEWS src/clinet.c 2004-11-03 02:20:56 GMT Martin Pool patch-150 Summary: gcc -specs must also be run locally Revision: distcc--devel--2--patch-150 modified files: ChangeLog NEWS src/arg.c test/testdistcc.py 2004-11-02 07:12:57 GMT Martin Pool patch-149 Summary: mon-gnome: fix tree_model warning Revision: distcc--devel--2--patch-149 modified files: ChangeLog NEWS src/mon-gnome.c 2004-10-23 08:42:53 GMT Martin Pool patch-148 Summary: fold io.h into distcc.h Revision: distcc--devel--2--patch-148 removed files: src/.arch-ids/io.h.id src/io.h modified files: ChangeLog Makefile.in src/arg.c src/argutil.c src/backoff.c src/bulk.c src/clinet.c src/clirpc.c src/compress.c src/daemon.c src/distcc.h src/dopt.c src/dparent.c src/exec.c src/h_exten.c src/h_issource.c src/h_scanargs.c src/h_strip.c src/hostfile.c src/io.c src/loadfile.c src/lock.c src/mon-gnome.c src/mon-notify.c src/mon-text.c src/mon.c src/prefork.c src/pump.c src/remote.c src/renderer.c src/rpc.c src/safeguard.c src/sendfile.c src/serve.c src/srvnet.c src/srvrpc.c src/ssh.c src/state.c src/strip.c src/timefile.c src/util.c 2004-10-23 08:23:22 GMT Martin Pool patch-147 Summary: fix some signedness/type warnings Revision: distcc--devel--2--patch-147 modified files: ChangeLog src/bulk.c src/climasq.c src/clirpc.c src/distcc.h src/hosts.c src/io.h src/mon-gnome.c src/netutil.c src/netutil.h src/rpc.c src/trace.c src/util.c src/where.c 2004-10-23 08:11:25 GMT Martin Pool patch-146 Summary: Turn off -Wunreachable-code Revision: distcc--devel--2--patch-146 modified files: ChangeLog configure.ac 2004-10-23 08:00:12 GMT Martin Pool patch-145 Summary: turn on more warnings Revision: distcc--devel--2--patch-145 modified files: ChangeLog configure.ac 2004-10-21 23:06:54 GMT Martin Pool patch-144 Summary: Allow for host files containing \r Revision: distcc--devel--2--patch-144 modified files: ChangeLog NEWS src/hosts.c test/testdistcc.py 2004-10-13 02:37:50 GMT Martin Pool patch-143 Summary: Return errors, rather than aborting. Revision: distcc--devel--2--patch-143 Don't call rs_fatal; instead return an error. It was giving warnings on non-gcc compilers because it wasn't seen as noreturn, and anyhow aborting is a bit untidy. modified files: ChangeLog src/arg.c src/bulk.c src/cleanup.c src/cpp.c src/dopt.c src/h_ccvers.c src/history.c src/hosts.c src/io.c src/lock.c src/mon.c src/pump.c src/remote.c src/rpc.c src/serve.c src/ssh.c src/trace.h src/util.c 2004-10-13 02:23:11 GMT Martin Pool patch-142 Summary: fix header problem for Solaris Revision: distcc--devel--2--patch-142 * src/distcc.h: Need sys/types.h for pid_t. modified files: ChangeLog NEWS bench/Build.py bench/Project.py bench/ProjectDefs.py src/distcc.h 2004-10-12 06:28:10 GMT Martin Pool patch-141 Summary: Add samba 3.0.7 as benchmark project Revision: distcc--devel--2--patch-141 modified files: ChangeLog bench/ProjectDefs.py 2004-10-12 05:41:38 GMT Martin Pool patch-140 Summary: benchmark: scrub results on completion by default Revision: distcc--devel--2--patch-140 modified files: ChangeLog bench/actions.py 2004-10-12 05:37:21 GMT Martin Pool patch-139 Summary: advance version to 2.19pre Revision: distcc--devel--2--patch-139 modified files: ChangeLog configure.ac 2004-10-12 05:13:54 GMT Martin Pool patch-138 Summary: Prepare for release Revision: distcc--devel--2--patch-138 modified files: ChangeLog NEWS configure.ac 2004-10-12 05:10:31 GMT Martin Pool patch-137 Summary: Always build conftest.c locally Revision: distcc--devel--2--patch-137 Problem: configure tests are typically very quick to build; also configure can be very sensitive to stderr warnings or other small variations between machines. Fix: To make things faster and safer, build conftest.* locally; also tmp.conftest.* used by ccache. * src/filename.c (dcc_source_needs_local): New function. * src/arg.c (dcc_scan_args): Check. * cases/conftest.c: Manual test case. new files: cases/conftest.c modified files: ChangeLog NEWS TODO src/arg.c src/distcc.h src/filename.c 2004-10-12 04:50:41 GMT Martin Pool patch-136 Summary: Reset PATH when running maintainer-check Revision: distcc--devel--2--patch-136 Problem: Installed copies of distcc and/or ccache were getting invoked from inside the test suite in a confusing way. Fix: Force the path to just /bin:/usr/bin:`pwd` modified files: ChangeLog Makefile.in 2004-10-12 04:43:39 GMT Martin Pool patch-135 Summary: Remove mmap when receiving uncompressed data Revision: distcc--devel--2--patch-135 Problem: Calling msync seems likely to force disk IO, but not calling it is unsafe. Fix: In fact, we can probably do fine by just using plain IO to receive data. This is already done for compressed data. * src/pump.c (dcc_r_bulk_plain): Remove. * src/pump.c (dcc_r_bulk): Just pump bytes through when receiving data; don't worry about mmap. Doc. * src/bulk.c (dcc_r_file): Output files can be WRONLY if we're not using mmap. * src/io.c (dcc_want_mmap): Remove. * man/distcc.1, man/distccd.1: No more mmap! modified files: ChangeLog NEWS man/distcc.1 man/distccd.1 src/bulk.c src/io.c src/pump.c src/sendfile.c 2004-10-12 04:38:27 GMT Martin Pool patch-134 Summary: fix headers Revision: distcc--devel--2--patch-134 modified files: ChangeLog src/history.c 2004-10-12 04:27:45 GMT Martin Pool patch-133 Summary: todo: conftest.c Revision: distcc--devel--2--patch-133 modified files: ChangeLog TODO 2004-10-12 04:20:05 GMT Martin Pool patch-132 Summary: doc Revision: distcc--devel--2--patch-132 modified files: ChangeLog src/pump.c 2004-10-12 04:10:49 GMT Martin Pool patch-131 Summary: Select-based non-blocking connect() Revision: distcc--devel--2--patch-131 * src/clinet.c (dcc_connect_by_addr): Make socket non-blocking at connect time and impose a timeout on connection attempts; currently hardcoded to 5s. modified files: ChangeLog NEWS src/clinet.c src/io.c 2004-10-12 03:10:31 GMT Martin Pool patch-130 Summary: ssh: doc Revision: distcc--devel--2--patch-130 modified files: ChangeLog src/ssh.c 2004-10-12 03:02:18 GMT Martin Pool patch-129 Summary: Ignore HTML manpages Revision: distcc--devel--2--patch-129 new files: man/.arch-inventory modified files: ChangeLog 2004-10-12 02:59:16 GMT Martin Pool patch-128 Summary: ssh: doc Revision: distcc--devel--2--patch-128 modified files: ChangeLog src/ssh.c 2004-10-12 02:15:39 GMT Martin Pool patch-127 Summary: remove signal-based timeouts Revision: distcc--devel--2--patch-127 Problem: Using alarms to enforce timeouts is inherently unsafe, because it might leave e.g. the resolver or C library in an inconsistent state. Fix: Don't use signals. We can do something simpler and safer using select() in a future commit. We no longer have a timeout on name resolution; the best fix for this is to set an appropriate timeout in resolv.conf. removed files: src/.arch-ids/timeout.c.id src/timeout.c modified files: ChangeLog Makefile.in man/distcc.1 src/distcc.h src/remote.c src/serve.c 2004-10-11 09:09:47 GMT Martin Pool patch-126 Summary: distcc(1): mention timeouts Revision: distcc--devel--2--patch-126 modified files: ChangeLog man/distcc.1 2004-10-11 08:15:05 GMT Martin Pool patch-125 Summary: no timeout on cpp Revision: distcc--devel--2--patch-125 Refactor code that waits for cpp to finish, and disarm the timeout during this phase. modified files: ChangeLog NEWS src/remote.c 2004-10-11 07:28:00 GMT Martin Pool patch-124 Summary: Adjust timeouts Revision: distcc--devel--2--patch-124 Short 5s CONNECT timeout covers only name resolution and TCP connection. SEND phase and timeout should include sending the header, and waiting for cpp to complete. 60s to send. Allow up to 20mins for compilation. modified files: ChangeLog src/remote.c src/serve.c 2004-10-11 07:17:31 GMT Martin Pool patch-123 Summary: fix timeout crash bug Revision: distcc--devel--2--patch-123 Problem: Was using longjmp() from the SIGALRM handler to return an error. This is not safe. Fix: Use siglongjmp() instead. That may not be completely safe either, but it might fix the problem. modified files: ChangeLog NEWS src/timeout.c 2004-10-11 06:24:35 GMT Martin Pool patch-122 Summary: Add test case for siglongjmp Revision: distcc--devel--2--patch-122 new files: cases/.arch-ids/.arch-inventory.id cases/.arch-ids/tryjump.c.id cases/.arch-inventory cases/tryjump.c modified files: ChangeLog NEWS 2004-10-11 06:21:43 GMT Martin Pool patch-121 Summary: todo: problems with state file sharing Revision: distcc--devel--2--patch-121 modified files: ChangeLog TODO 2004-10-09 13:26:15 GMT Martin Pool patch-120 Summary: distccmon-text(1): Clarify client requirements Revision: distcc--devel--2--patch-120 modified files: ChangeLog man/distccmon-text.1 2004-09-25 10:01:05 GMT Martin Pool patch-119 Summary: doc Revision: distcc--devel--2--patch-119 modified files: ChangeLog TODO 2004-09-25 09:57:52 GMT Martin Pool patch-118 Summary: distcc.1: make it clearer this is a client-side monitor Revision: distcc--devel--2--patch-118 modified files: ChangeLog man/distccmon-text.1 2004-09-17 00:41:14 GMT Martin Pool patch-117 Summary: --allow is now mandatory Revision: distcc--devel--2--patch-117 modified files: ChangeLog NEWS src/daemon.c src/dopt.c 2004-09-16 05:58:09 GMT Martin Pool patch-116 Summary: sa_family_t Tru64 portability cleanup -- just remove test Revision: distcc--devel--2--patch-116 modified files: ChangeLog NEWS configure.ac src/distcc.h 2004-09-16 05:20:08 GMT Martin Pool patch-115 Summary: include state.h from within distcc.h Revision: distcc--devel--2--patch-115 modified files: ChangeLog src/compile.c src/distcc.c src/distcc.h src/history.c src/mon-gnome.c src/mon-notify.c src/mon-text.c src/mon.c src/remote.c src/renderer.c src/serve.c src/state.c src/timeout.c src/where.c 2004-09-16 05:12:42 GMT Martin Pool patch-114 Summary: doc Revision: distcc--devel--2--patch-114 modified files: ChangeLog src/distcc.h 2004-09-16 05:08:07 GMT Martin Pool patch-113 Summary: Improved check for gcc>=3.4 for warn_unused_result Revision: distcc--devel--2--patch-113 modified files: ChangeLog src/distcc.h 2004-09-16 04:55:26 GMT Martin Pool patch-112 Summary: fix enum type warning from Dmitri Revision: distcc--devel--2--patch-112 modified files: ChangeLog src/distcc.h src/timeout.c 2004-09-16 04:46:42 GMT Martin Pool patch-111 Summary: fix unused var warning Revision: distcc--devel--2--patch-111 modified files: ChangeLog src/state.c 2004-09-16 04:46:26 GMT Martin Pool patch-110 Summary: bump version Revision: distcc--devel--2--patch-110 modified files: ChangeLog configure.ac 2004-08-24 12:12:50 GMT Martin Pool patch-109 Summary: Prepare for 2.17.1 release Revision: distcc--devel--2--patch-109 modified files: ChangeLog NEWS 2004-08-24 12:10:43 GMT Martin Pool patch-108 Summary: Update version to 2.17.1 Revision: distcc--devel--2--patch-108 modified files: ChangeLog configure.ac 2004-08-24 12:07:55 GMT Martin Pool patch-107 Summary: Don't use warn_unused_result on old gcc Revision: distcc--devel--2--patch-107 modified files: ChangeLog src/distcc.h 2004-08-13 22:06:05 GMT Martin Pool patch-106 Summary: distcc.1: better explanation of using distcc with ccache Revision: distcc--devel--2--patch-106 modified files: ChangeLog Makefile.in man/distcc.1 2004-08-06 00:34:21 GMT Martin Pool patch-105 Summary: doc Revision: distcc--devel--2--patch-105 modified files: ChangeLog src/compile.c 2004-08-05 23:29:15 GMT Martin Pool patch-104 Summary: Fix dcc_trace bug Revision: distcc--devel--2--patch-104 modified files: ChangeLog NEWS src/clinet.c 2004-08-02 18:41:07 GMT Martin Pool patch-103 Summary: doc Revision: distcc--devel--2--patch-103 modified files: ChangeLog src/distcc.h 2004-08-01 05:52:01 GMT Martin Pool patch-102 Summary: fix usage of dcc_timeout_arm Revision: distcc--devel--2--patch-102 modified files: ChangeLog src/serve.c 2004-08-01 05:50:45 GMT Martin Pool patch-101 Summary: prepare for 2.17 release Revision: distcc--devel--2--patch-101 modified files: ChangeLog 2004-08-01 05:49:42 GMT Martin Pool patch-100 Summary: add server-side timeouts Revision: distcc--devel--2--patch-100 modified files: ChangeLog Makefile.in NEWS src/serve.c 2004-08-01 05:45:46 GMT Martin Pool patch-99 Summary: fix usage of dcc_timeout_arm Revision: distcc--devel--2--patch-99 modified files: ChangeLog src/remote.c 2004-08-01 05:43:10 GMT Martin Pool patch-98 Summary: merge from happy Revision: distcc--devel--2--patch-98 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--patch-26 dcc_timeout_arm: add WARN_UNUSED * mbp@sourcefrog.net--happy/distcc--devel--2--patch-27 merge to devel * mbp@sourcefrog.net--happy/distcc--devel--2--patch-28 add WARN_UNUSED to some functions modified files: ChangeLog src/distcc.h new patches: mbp@sourcefrog.net--happy/distcc--devel--2--patch-26 mbp@sourcefrog.net--happy/distcc--devel--2--patch-27 mbp@sourcefrog.net--happy/distcc--devel--2--patch-28 2004-08-01 05:39:19 GMT Martin Pool patch-97 Summary: add WARN_UNUSED to some functions Revision: distcc--devel--2--patch-97 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--patch-26 dcc_timeout_arm: add WARN_UNUSED * mbp@sourcefrog.net--happy/distcc--devel--2--patch-27 merge to devel modified files: ChangeLog src/distcc.h 2004-07-29 21:38:23 GMT Martin Pool patch-96 Summary: cleanups Revision: distcc--devel--2--patch-96 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--patch-23 check return codes from dcc_timeout_arm * mbp@sourcefrog.net--happy/distcc--devel--2--patch-24 ifdef __attribute__ on GNUC * mbp@sourcefrog.net--happy/distcc--devel--2--patch-25 dcc_build_somewhere: cleanup modified files: ChangeLog src/compile.c src/distcc.h new patches: mbp@sourcefrog.net--happy/distcc--devel--2--patch-23 mbp@sourcefrog.net--happy/distcc--devel--2--patch-24 mbp@sourcefrog.net--happy/distcc--devel--2--patch-25 2004-07-29 21:32:11 GMT Martin Pool patch-95 Summary: doc Revision: distcc--devel--2--patch-95 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--patch-16 update todo items * mbp@sourcefrog.net--happy/distcc--devel--2--patch-17 merged to devel * mbp@sourcefrog.net--happy/distcc--devel--2--patch-18 doc * mbp@sourcefrog.net--happy/distcc--devel--2--patch-19 notes on timeouts * mbp@sourcefrog.net--happy/distcc--devel--2--patch-20 timeouts are done * mbp@sourcefrog.net--happy/distcc--devel--2--patch-21 correct version number * mbp@sourcefrog.net--happy/distcc--devel--2--patch-22 treat emacs temporary files as backups modified files: ChangeLog NEWS TODO configure.ac doc/roadmap.txt src/remote.c {arch}/=tagging-method new patches: mbp@sourcefrog.net--happy/distcc--devel--2--patch-16 mbp@sourcefrog.net--happy/distcc--devel--2--patch-17 mbp@sourcefrog.net--happy/distcc--devel--2--patch-18 mbp@sourcefrog.net--happy/distcc--devel--2--patch-19 mbp@sourcefrog.net--happy/distcc--devel--2--patch-20 mbp@sourcefrog.net--happy/distcc--devel--2--patch-21 mbp@sourcefrog.net--happy/distcc--devel--2--patch-22 2004-07-29 19:35:33 GMT Martin Pool patch-94 Summary: more timeouts and cleanups Revision: distcc--devel--2--patch-94 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--patch-11 portability fix for WCOREDUMP * mbp@sourcefrog.net--happy/distcc--devel--2--patch-12 remove obsolete patch * mbp@sourcefrog.net--happy/distcc--devel--2--patch-13 dcc_compile_remote: add more client-side timeouts * mbp@sourcefrog.net--happy/distcc--devel--2--patch-14 dcc_connect_by_addr: handle EINTR from connect() * mbp@sourcefrog.net--happy/distcc--devel--2--patch-15 bump version number removed files: patches/.arch-ids/resolver-timeout.diff.id patches/resolver-timeout.diff modified files: ChangeLog NEWS configure.ac src/clinet.c src/distcc.h src/exec.c src/remote.c new patches: mbp@sourcefrog.net--happy/distcc--devel--2--patch-11 mbp@sourcefrog.net--happy/distcc--devel--2--patch-12 mbp@sourcefrog.net--happy/distcc--devel--2--patch-13 mbp@sourcefrog.net--happy/distcc--devel--2--patch-14 mbp@sourcefrog.net--happy/distcc--devel--2--patch-15 2004-07-29 19:12:49 GMT Martin Pool patch-93 Summary: alarm-based connection timeout Revision: distcc--devel--2--patch-93 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--base-0 import from ozlabs * mbp@sourcefrog.net--happy/distcc--devel--2--patch-1 tweak version output more * mbp@sourcefrog.net--happy/distcc--devel--2--patch-2 Add EXIT_TIMEOUT * mbp@sourcefrog.net--happy/distcc--devel--2--patch-3 Add overall connection timeout * mbp@sourcefrog.net--happy/distcc--devel--2--patch-4 remove docs for deleted DISTCC_CONNECT_TIMEOUT * mbp@sourcefrog.net--happy/distcc--devel--2--patch-5 fold in backoff.h * mbp@sourcefrog.net--happy/distcc--devel--2--patch-6 remove select-based timeout in client connect * mbp@sourcefrog.net--happy/distcc--devel--2--patch-7 dcc_connect_by_addr: remove host and port params * mbp@sourcefrog.net--happy/distcc--devel--2--patch-8 dcc_connect_by_addr: cleanup trace * mbp@sourcefrog.net--happy/distcc--devel--2--patch-9 dcc_build_somewhere: better message on fallback * mbp@sourcefrog.net--happy/distcc--devel--2--patch-10 dcc_timeout_arm: doc new files: src/.arch-ids/timeout.c.id src/timeout.c removed files: src/.arch-ids/backoff.h.id src/backoff.h modified files: ChangeLog Makefile.in NEWS man/distcc.1 src/backoff.c src/clinet.c src/compile.c src/distcc.h src/exitcode.h src/help.c src/remote.c src/ssh.c src/util.c src/util.h src/where.c new patches: mbp@sourcefrog.net--happy/distcc--devel--2--base-0 mbp@sourcefrog.net--happy/distcc--devel--2--patch-1 mbp@sourcefrog.net--happy/distcc--devel--2--patch-2 mbp@sourcefrog.net--happy/distcc--devel--2--patch-3 mbp@sourcefrog.net--happy/distcc--devel--2--patch-4 mbp@sourcefrog.net--happy/distcc--devel--2--patch-5 mbp@sourcefrog.net--happy/distcc--devel--2--patch-6 mbp@sourcefrog.net--happy/distcc--devel--2--patch-7 mbp@sourcefrog.net--happy/distcc--devel--2--patch-8 mbp@sourcefrog.net--happy/distcc--devel--2--patch-9 mbp@sourcefrog.net--happy/distcc--devel--2--patch-10 2004-07-28 18:38:20 GMT Martin Pool patch-92 Summary: mention miniLZO in --version Revision: distcc--devel--2--patch-92 modified files: ChangeLog src/help.c 2004-07-23 13:47:05 GMT Martin Pool patch-91 Summary: Manpage fix from Jean Delvare. Revision: distcc--devel--2--patch-91 modified files: ChangeLog NEWS man/distcc.1 2004-07-15 08:27:57 GMT Martin Pool patch-90 Summary: Add CVE number for netmask problem Revision: distcc--devel--2--patch-90 modified files: ChangeLog NEWS 2004-07-14 05:32:41 GMT Martin Pool patch-89 Summary: notes on mod_backhand load balancing Revision: distcc--devel--2--patch-89 new files: doc/todo/.arch-ids/backhand.txt.id doc/todo/backhand.txt modified files: ChangeLog 2004-07-14 05:32:16 GMT Martin Pool patch-88 Summary: dcc_set_row_idle: reduce unnecessary tree model updates Revision: distcc--devel--2--patch-88 modified files: ChangeLog src/mon-gnome.c 2004-07-14 05:27:54 GMT Martin Pool patch-87 Summary: dcc_build_somewhere: don't retry if remote compiler crashed Revision: distcc--devel--2--patch-87 modified files: ChangeLog NEWS src/compile.c 2004-07-12 07:39:35 GMT Martin Pool patch-86 Summary: Cleanup Revision: distcc--devel--2--patch-86 modified files: ChangeLog src/mon-gnome.c 2004-07-12 07:23:46 GMT Martin Pool patch-85 Summary: make sure idle periods get drawn in history Revision: distcc--devel--2--patch-85 modified files: ChangeLog src/renderer.c 2004-07-12 07:21:41 GMT Martin Pool patch-84 Summary: mon-gnome: Use circular array not GQueue for history Revision: distcc--devel--2--patch-84 Using a doubly-linked list to hold integers uses a lot of time and memory. Instead we use just a simple circular array. history.c: New file holding this. new files: src/.arch-ids/history.c.id src/history.c modified files: ChangeLog Makefile.in NEWS src/mon-gnome.c src/mon.h src/renderer.c 2004-07-12 06:53:56 GMT Martin Pool patch-83 Summary: s/dcc_history/dcc_task_state/ Revision: distcc--devel--2--patch-83 modified files: ChangeLog src/mon-fake.c src/mon-gnome.c src/mon-text.c src/mon.c src/mon.h src/state.c src/state.h 2004-07-12 06:49:54 GMT Martin Pool patch-82 Summary: s/dcc_state/dcc_phase/ Revision: distcc--devel--2--patch-82 modified files: ChangeLog src/mon-fake.c src/mon-gnome.c src/mon-text.c src/mon.c src/mon.h src/renderer.c src/renderer.h src/state.c src/state.h 2004-07-12 06:46:16 GMT Martin Pool patch-81 Summary: Rename DCC_STATE_* to DCC_PHASE_* Revision: distcc--devel--2--patch-81 modified files: ChangeLog src/clirpc.c src/compile.c src/mon-fake.c src/mon-gnome.c src/mon-text.c src/mon.c src/remote.c src/renderer.c src/renderer.h src/state.c src/state.h src/where.c 2004-07-12 06:45:29 GMT Martin Pool patch-80 Summary: Fix warning Revision: distcc--devel--2--patch-80 modified files: ChangeLog src/daemon.h 2004-07-12 06:39:40 GMT Martin Pool patch-79 Summary: Doc Revision: distcc--devel--2--patch-79 modified files: ChangeLog src/mon-gnome.c 2004-07-12 06:20:10 GMT Martin Pool patch-78 Summary: dcc_draw_state_stripe: inline into the only caller Revision: distcc--devel--2--patch-78 modified files: ChangeLog src/renderer.c 2004-07-12 05:24:32 GMT Martin Pool patch-77 Summary: Doc Revision: distcc--devel--2--patch-77 modified files: ChangeLog src/renderer.c 2004-07-09 05:16:20 GMT Martin Pool patch-76 Summary: todo: monitor ideas Revision: distcc--devel--2--patch-76 new files: doc/todo/.arch-ids/monitor-clear.txt.id doc/todo/.arch-ids/monitor-count.txt.id doc/todo/monitor-clear.txt doc/todo/monitor-count.txt modified files: ChangeLog 2004-07-09 04:56:11 GMT Martin Pool patch-75 Summary: benchmark: notes on building glibc Revision: distcc--devel--2--patch-75 modified files: ChangeLog bench/ProjectDefs.py 2004-07-08 07:40:50 GMT Martin Pool patch-74 Summary: fix warnings about sockaddr Revision: distcc--devel--2--patch-74 modified files: ChangeLog src/netutil.h 2004-07-08 07:39:35 GMT Martin Pool patch-73 Summary: setuid.h: remove Revision: distcc--devel--2--patch-73 removed files: src/.arch-ids/setuid.h.id src/setuid.h modified files: ChangeLog Makefile.in src/daemon.c src/daemon.h src/dopt.c src/setuid.c 2004-07-08 07:36:08 GMT Martin Pool patch-72 Summary: filename.h: remove Revision: distcc--devel--2--patch-72 removed files: src/.arch-ids/filename.h.id src/filename.h modified files: ChangeLog Makefile.in src/arg.c src/argutil.c src/cpp.c src/distcc.c src/distcc.h src/filename.c src/h_exten.c src/h_issource.c src/implicit.c src/mon-notify.c src/mon-text.c src/mon.c src/serve.c src/srvrpc.c src/state.c 2004-07-08 07:32:43 GMT Martin Pool patch-71 Summary: cpp.h: removed Revision: distcc--devel--2--patch-71 removed files: src/.arch-ids/cpp.h.id src/cpp.h modified files: ChangeLog Makefile.in src/compile.c src/cpp.c src/distcc.h 2004-07-08 07:31:15 GMT Martin Pool patch-70 Summary: strip.h: removed Revision: distcc--devel--2--patch-70 removed files: src/.arch-ids/strip.h.id src/strip.h modified files: ChangeLog doc/roadmap.txt src/compile.c src/cpp.c src/distcc.h src/h_strip.c src/strip.c 2004-07-08 06:02:34 GMT Martin Pool patch-69 Summary: doc Revision: distcc--devel--2--patch-69 modified files: ChangeLog src/mon-text.c 2004-07-08 05:57:05 GMT Martin Pool patch-68 Summary: note leak fixes Revision: distcc--devel--2--patch-68 modified files: ChangeLog 2004-07-08 05:56:54 GMT Martin Pool patch-67 Summary: distccmon-text: fix memory leak Revision: distcc--devel--2--patch-67 modified files: ChangeLog src/mon-text.c 2004-07-08 05:52:06 GMT Martin Pool patch-66 Summary: dcc_history_free: Fix memory leak Revision: distcc--devel--2--patch-66 modified files: ChangeLog src/mon.c 2004-07-08 05:48:31 GMT Martin Pool patch-65 Summary: mon-gnome: fix leak in setting title; don't set title twice Revision: distcc--devel--2--patch-65 modified files: ChangeLog src/mon-gnome.c 2004-07-08 05:10:10 GMT Martin Pool patch-64 Summary: dcc_mon_load_state: fix leak on error path Revision: distcc--devel--2--patch-64 modified files: ChangeLog NEWS src/mon.c 2004-07-08 04:56:58 GMT Martin Pool patch-63 Summary: Prepare for 2.16 release Revision: distcc--devel--2--patch-63 modified files: ChangeLog NEWS configure.ac 2004-07-08 04:52:43 GMT Martin Pool patch-62 Summary: distccmon-gnome: use a GNOME status bar with a grab handle Revision: distcc--devel--2--patch-62 Patch from Nathan Fredrickson. modified files: ChangeLog NEWS src/mon-gnome.c 2004-07-08 04:32:35 GMT Martin Pool patch-61 Summary: testdistcc.py: update to work on ia64 linux Revision: distcc--devel--2--patch-61 modified files: ChangeLog NEWS test/testdistcc.py 2004-07-08 04:31:44 GMT Martin Pool patch-60 Summary: Rephrase news Revision: distcc--devel--2--patch-60 modified files: ChangeLog NEWS 2004-07-07 05:49:15 GMT Martin Pool patch-59 Summary: testdistcc: allow for --version output to have more than two lines Revision: distcc--devel--2--patch-59 modified files: ChangeLog test/testdistcc.py 2004-07-07 05:44:23 GMT Martin Pool patch-58 Summary: dcc_parse_mask: fix 64-bit bugs Revision: distcc--devel--2--patch-58 modified files: ChangeLog NEWS src/access.c 2004-07-07 05:21:02 GMT Martin Pool patch-57 Summary: h_parsemask: stub for trace Revision: distcc--devel--2--patch-57 modified files: ChangeLog src/h_parsemask.c 2004-07-07 04:47:00 GMT Martin Pool patch-56 Summary: dcc_show_version: Include copyright and licence Revision: distcc--devel--2--patch-56 modified files: ChangeLog NEWS src/distcc.c src/distcc.h src/dopt.c src/help.c 2004-07-07 04:38:53 GMT Martin Pool patch-55 Summary: configure: if using system popt, need to use -lpopt Revision: distcc--devel--2--patch-55 modified files: ChangeLog configure.ac 2004-07-07 02:14:54 GMT Martin Pool patch-54 Summary: dcc_log_child_exited: Fix bizarre syntax bug, remove #ifdef Revision: distcc--devel--2--patch-54 modified files: ChangeLog NEWS src/dparent.c 2004-07-07 02:07:47 GMT Martin Pool patch-53 Summary: draft patch for faster polling when blocked Revision: distcc--devel--2--patch-53 new files: patches/.arch-ids/shorter-boredom-poll.diff.id patches/shorter-boredom-poll.diff modified files: ChangeLog 2004-07-07 02:06:53 GMT Martin Pool patch-52 Summary: doc: note popt fix Revision: distcc--devel--2--patch-52 modified files: ChangeLog NEWS 2004-07-07 01:59:58 GMT Martin Pool patch-51 Summary: doc: benchmarks Revision: distcc--devel--2--patch-51 modified files: ChangeLog doc/results.txt 2004-07-07 01:59:39 GMT Martin Pool patch-50 Summary: configure.ac: fix problem detecting popt.h Revision: distcc--devel--2--patch-50 Problem: Some people might have libpopt, but no popt.h, in which case we tried to use the system copy and failed. Fix: Check for popt.h. If not present, use ./popt. modified files: ChangeLog configure.ac 2004-07-06 13:05:12 GMT Martin Pool patch-49 Summary: Prepare for 2.15 release Revision: distcc--devel--2--patch-49 modified files: ChangeLog NEWS configure.ac 2004-07-06 13:00:16 GMT Martin Pool patch-48 Summary: Notes on version checking Revision: distcc--devel--2--patch-48 modified files: ChangeLog doc/todo/version-check.txt 2004-07-06 12:47:38 GMT Martin Pool patch-47 Summary: Doc Revision: distcc--devel--2--patch-47 new files: doc/todo/.arch-ids/monitor-legend.txt.id doc/todo/monitor-legend.txt modified files: ChangeLog 2004-07-06 09:03:44 GMT Martin Pool patch-46 Summary: compress: assume a larger decompression buffer by default so less likely to retry Revision: distcc--devel--2--patch-46 modified files: ChangeLog src/compress.c 2004-07-06 08:50:24 GMT Martin Pool patch-45 Summary: remove mmap/lzo support Revision: distcc--devel--2--patch-45 modified files: ChangeLog NEWS doc/results.txt src/compress.c 2004-07-06 08:27:44 GMT Martin Pool patch-44 Summary: dcc_r_bulk_lzo1x: fix nasty bug in mmap recv lzo Revision: distcc--devel--2--patch-44 When reading in compressed data, our initial buffer might not be large enough for the actual compressed data, so we need to free it and make a larger one. When freeing the mmapped buffer, we need to pass both address and length of the mapping. The bug was that we increased the length before unmapping and therefore randomly unmapped some block of memory, causing a crash later on. Fix: don't increase the length until we're done with the old value. This code is really too complex to be safe. modified files: ChangeLog src/compress.c 2004-07-06 08:09:27 GMT Martin Pool patch-43 Summary: fix warning Revision: distcc--devel--2--patch-43 modified files: ChangeLog src/daemon.c 2004-07-06 08:09:03 GMT Martin Pool patch-42 Summary: tempfile.h: remove Revision: distcc--devel--2--patch-42 removed files: src/.arch-ids/tempfile.h.id src/tempfile.h modified files: ChangeLog Makefile.in src/backoff.c src/cleanup.c src/cpp.c src/daemon.c src/distcc.c src/distcc.h src/dparent.c src/dsignal.c src/hosts.c src/lock.c src/mon-notify.c src/mon-text.c src/mon.c src/prefork.c src/remote.c src/serve.c src/state.c src/tempfile.c src/timefile.c src/where.c 2004-07-06 08:06:57 GMT Martin Pool patch-41 Summary: distccd: chdir to $TMPDIR not / at startup Revision: distcc--devel--2--patch-41 modified files: ChangeLog NEWS src/daemon.c 2004-07-06 08:05:30 GMT Martin Pool patch-40 Summary: dcc_get_tmp_top: make public Revision: distcc--devel--2--patch-40 modified files: ChangeLog src/tempfile.c src/tempfile.h 2004-07-06 08:00:29 GMT Martin Pool patch-39 Summary: dcc_log_child_exited: indicate if core was produced Revision: distcc--devel--2--patch-39 modified files: ChangeLog src/dparent.c 2004-07-06 05:10:05 GMT Martin Pool patch-38 Summary: Revision: distcc--devel--2--patch-38 modified files: ChangeLog src/arg.c src/argutil.c src/distcc.c src/distcc.h src/implicit.c 2004-07-06 05:03:25 GMT Martin Pool patch-37 Summary: argutil.c: Doc Revision: distcc--devel--2--patch-37 modified files: ChangeLog src/argutil.c 2004-07-06 05:00:57 GMT Martin Pool patch-36 Summary: arg.h: fold into distcc.h Revision: distcc--devel--2--patch-36 removed files: src/.arch-ids/arg.h.id src/arg.h modified files: ChangeLog Makefile.in src/arg.c src/argutil.c src/clirpc.c src/compile.c src/cpp.c src/distcc.c src/distcc.h src/exec.c src/h_argvtostr.c src/h_ccvers.c src/h_scanargs.c src/h_strip.c src/implicit.c src/serve.c src/srvrpc.c src/ssh.c src/strip.c 2004-07-06 04:54:15 GMT Martin Pool patch-35 Summary: dcc_free_argv: new function Revision: distcc--devel--2--patch-35 modified files: ChangeLog src/arg.h src/argutil.c 2004-07-06 04:47:46 GMT Martin Pool patch-34 Summary: Remove redundant temporary file cleanup in non-forking mode. Revision: distcc--devel--2--patch-34 modified files: ChangeLog NEWS src/dparent.c src/serve.c 2004-06-18 23:47:56 GMT Martin Pool patch-33 Summary: roadmap update Revision: distcc--devel--2--patch-33 modified files: ChangeLog doc/roadmap.txt 2004-06-17 04:15:48 GMT Martin Pool patch-32 Summary: Doc Revision: distcc--devel--2--patch-32 modified files: ChangeLog src/lock.c 2004-06-12 08:47:59 GMT Martin Pool patch-31 Summary: dcc_service_job: Doc Revision: distcc--devel--2--patch-31 modified files: ChangeLog src/serve.c 2004-06-11 08:31:22 GMT Martin Pool patch-30 Summary: protocol-3: I think there's no need for hash after all Revision: distcc--devel--2--patch-30 modified files: ChangeLog doc/protocol-3.txt 2004-06-11 08:19:20 GMT Martin Pool patch-29 Summary: protocol-3: describe request format; propose adding CRC Revision: distcc--devel--2--patch-29 modified files: ChangeLog doc/protocol-3.txt 2004-06-10 04:55:25 GMT Martin Pool patch-28 Summary: protocol-3 design development Revision: distcc--devel--2--patch-28 modified files: ChangeLog doc/protocol-3.txt 2004-06-10 03:18:55 GMT Martin Pool patch-27 Summary: todo: notes on file permissions Revision: distcc--devel--2--patch-27 new files: doc/todo/.arch-ids/permissions.txt.id doc/todo/permissions.txt modified files: ChangeLog TODO 2004-06-10 02:47:13 GMT Martin Pool patch-26 Summary: cases/hello.c: Include more headers to trigger compression Revision: distcc--devel--2--patch-26 modified files: ChangeLog cases/hello.c 2004-06-01 06:52:14 GMT Martin Pool patch-25 Summary: distccmon-text(1) typo fix from Lisa Revision: distcc--devel--2--patch-25 modified files: ChangeLog man/distccmon-text.1 2004-05-30 05:54:37 GMT Martin Pool patch-24 Summary: Add fixme comments for places where memory is probably leaked Revision: distcc--devel--2--patch-24 modified files: ChangeLog src/arg.c src/compile.c src/cpp.c src/where.c 2004-05-30 05:48:09 GMT Martin Pool patch-23 Summary: Doc Revision: distcc--devel--2--patch-23 new files: doc/todo/.arch-ids/gnome-leak.txt.id doc/todo/gnome-leak.txt modified files: ChangeLog 2004-05-29 05:10:27 GMT Martin Pool patch-22 Summary: More TODO notes on scheduling Revision: distcc--devel--2--patch-22 new files: doc/todo/.arch-ids/host-selection.txt.id doc/todo/.arch-ids/randomize-order.txt.id doc/todo/host-selection.txt doc/todo/randomize-order.txt modified files: ChangeLog 2004-05-28 23:42:32 GMT Martin Pool patch-21 Summary: patch from joshh to randomize host list Revision: distcc--devel--2--patch-21 In http://lists.samba.org/archive/distcc/2004q2/002250.html, Dan proposed randomizing the hosts list. Here's a patch to add that feature, controlled by a special --randomize option in the hosts list. On a large shared build cluster, this helps spread the load without requiring separate hosts lists for each user. Martin, what do you think? new files: patches/.arch-ids/joshh-random.diff.id patches/joshh-random.diff modified files: ChangeLog 2004-05-08 12:16:47 GMT Martin Pool patch-20 Summary: Update plans Revision: distcc--devel--2--patch-20 new files: doc/todo/.arch-ids/window-geometry.txt.id doc/todo/window-geometry.txt modified files: ChangeLog doc/roadmap.txt 2004-05-06 03:20:08 GMT Martin Pool patch-19 Summary: 'make uninstall' note Revision: distcc--devel--2--patch-19 new files: doc/todo/.arch-ids/make-uninstall.txt.id doc/todo/make-uninstall.txt modified files: ChangeLog 2004-05-05 06:34:07 GMT Martin Pool patch-18 Summary: Doc Revision: distcc--devel--2--patch-18 modified files: ChangeLog NEWS src/remote.c 2004-05-03 00:41:02 GMT Martin Pool patch-17 Summary: Red Hat fix from Colin Revision: distcc--devel--2--patch-17 Patches applied: * walters@verbum.org--2003/distcc--devel--2.14--patch-5 merge from mbp * walters@verbum.org--2003/distcc--devel--2.14--patch-6 actually expand variables modified files: ChangeLog contrib/redhat/init contrib/redhat/logrotate contrib/redhat/xinetd new patches: walters@verbum.org--2003/distcc--devel--2.14--patch-5 walters@verbum.org--2003/distcc--devel--2.14--patch-6 2004-05-02 10:42:57 GMT Martin Pool patch-16 Summary: Note rate calculation Revision: distcc--devel--2--patch-16 modified files: ChangeLog NEWS 2004-05-02 10:40:35 GMT Martin Pool patch-15 Summary: Client calculates overall compilation rate for remote jobs Revision: distcc--devel--2--patch-15 modified files: ChangeLog src/bulk.c src/distcc.h src/remote.c 2004-05-02 10:30:00 GMT Martin Pool patch-14 Summary: Collect SSH child even when it fails Revision: distcc--devel--2--patch-14 modified files: ChangeLog src/remote.c 2004-05-02 10:22:22 GMT Martin Pool patch-13 Summary: Remove unnecessary check that cpp produced output Revision: distcc--devel--2--patch-13 modified files: ChangeLog src/remote.c 2004-05-02 10:20:01 GMT Martin Pool patch-12 Summary: Pass back size of transmitted files Revision: distcc--devel--2--patch-12 Also fix printf formats for file sizes. Remove old prototype for dcc_x_file_timed. modified files: ChangeLog src/bulk.c src/bulk.h src/remote.c src/serve.c 2004-05-02 10:06:11 GMT Martin Pool patch-11 Summary: Ignore gtags temporaries Revision: distcc--devel--2--patch-11 modified files: ChangeLog src/.arch-inventory 2004-05-02 10:05:11 GMT Martin Pool patch-10 Summary: Remove dcc_send_job_corked wrapper Revision: distcc--devel--2--patch-10 Just insert/remove corks at the right places. modified files: ChangeLog src/remote.c 2004-05-02 10:00:52 GMT Martin Pool patch-9 Summary: Split out code to wait for cpp Revision: distcc--devel--2--patch-9 modified files: ChangeLog src/remote.c 2004-05-02 09:58:22 GMT Martin Pool patch-8 Summary: Refactor code to send requests into remote.c Revision: distcc--devel--2--patch-8 modified files: ChangeLog src/clirpc.c src/distcc.h src/remote.c 2004-05-02 09:49:23 GMT Martin Pool patch-7 Summary: Plan for calculating rate Revision: distcc--devel--2--patch-7 new files: doc/todo/.arch-ids/show-rate.txt.id doc/todo/show-rate.txt modified files: ChangeLog 2004-05-02 09:38:40 GMT Martin Pool patch-6 Summary: Remove relic zip.c Revision: distcc--devel--2--patch-6 removed files: src/.arch-ids/zip.c.id src/zip.c modified files: ChangeLog Makefile.in 2004-05-02 09:35:26 GMT Martin Pool patch-5 Summary: Remove old prototypes Revision: distcc--devel--2--patch-5 modified files: ChangeLog src/daemon.h src/dparent.c 2004-05-02 08:46:14 GMT Martin Pool patch-4 Summary: Remove non-prefork mode Revision: distcc--devel--2--patch-4 Only choices now are preforking, or not forking at all. modified files: ChangeLog NEWS src/dopt.c src/dparent.c 2004-05-02 08:35:51 GMT Martin Pool patch-3 Summary: Set version to 2.15pre Revision: distcc--devel--2--patch-3 modified files: ChangeLog NEWS configure.ac 2004-05-02 08:34:49 GMT Martin Pool patch-2 Summary: Plans for upcoming releases Revision: distcc--devel--2--patch-2 modified files: ChangeLog doc/roadmap.txt 2004-05-02 08:25:17 GMT Martin Pool patch-1 Summary: New ChangeLog for new revision Revision: distcc--devel--2--patch-1 new files: ChangeLog renamed files: ChangeLog ==> ChangeLog-2.14 2004-05-02 05:07:46 GMT Martin Pool base-0 Summary: tag of mbp@sourcefrog.net--2004/distcc--devel--2.14--version-0 Revision: distcc--devel--2--base-0 (automatically generated log message) new patches: mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--base-0 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-1 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-2 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-3 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-4 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-5 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-6 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-7 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-8 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-9 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-10 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-11 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-12 mbp@sourcefrog.net--2004/distcc--cvs--0--base-0 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-1 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-2 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-3 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-4 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-5 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-6 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-7 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-8 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-9 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-10 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-11 mbp@sourcefrog.net--2004/distcc--devel--2.14--base-0 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-1 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-2 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-3 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-4 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-5 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-6 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-7 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-8 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-9 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-10 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-11 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-12 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-13 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-14 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-15 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-16 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-17 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-18 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-19 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-20 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-21 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-22 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-23 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-24 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-25 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-26 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-27 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-28 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-29 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-30 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-31 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-32 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-33 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-34 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-35 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-36 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-37 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-38 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-39 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-40 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-41 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-42 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-43 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-44 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-45 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-46 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-47 mbp@sourcefrog.net--2004/distcc--devel--2.14--version-0 mbp@sourcefrog.net--2004/distcc--release--2.13--base-0 walters@verbum.org--2003/distcc--devel--2.14--base-0 walters@verbum.org--2003/distcc--devel--2.14--patch-1 walters@verbum.org--2003/distcc--devel--2.14--patch-2 walters@verbum.org--2003/distcc--devel--2.14--patch-3 walters@verbum.org--2003/distcc--devel--2.14--patch-4 ## These changes are from before development was done under arch. 2004-04-10 Martin Pool * src/mon-gnome.c (dcc_gnome_make_mainwin): Check gtk version and don't use gtk_window_set_icon_from_file before 2.2.0. Reported by Dag Wieers. 2004-03-21 Martin Pool * src/exec.c (dcc_critique_status): Log input filename. * src/clirpc.c (dcc_send_job): Log input filename, * src/remote.c (dcc_compile_remote): Log input filename. * src/serve.c (dcc_run_job): Log input filename. * src/compile.c (dcc_compile_local): Log input filename. 2004-03-03 Martin Pool * src/mon-gnome.c: Quieten g_messages. * src/distcc.c (dcc_show_usage): Describe DISTCC_DIR and other things. * man/distcc.1: Document DISTCC_DIR and fix some spelling errors. Patch from Thomas Schwinge. * src/hosts.c (dcc_get_hostlist): Get hosts from $DISTCC_DIR/hosts, rather than hardcoding to ~/.distcc. * src/tempfile.c (dcc_get_top_dir): Make this public. Just log a warning if $HOME is not set. 2004-03-02 Martin Pool * src/srvnet.c (dcc_listen_by_addr): Don't create the socket, just listen() on it. (dcc_check_client): Do access control checks on ipv4-mapped or ipv4-compat IPv6 addresses. * src/srvnet.c (dcc_socket_listen) [ENABLE_RFC2553]: Try creating sockets in every returned address family until we get one that works. Fix leak of addrinfo list. * src/srvnet.c (dcc_socket_listen) [!ENABLE_RFC2553]: Create socket here. 2004-03-01 Martin Pool * src/cleanup.c (dcc_cleanup_tempfiles): If DISTCC_SAVE_TEMPS is set, then we still need to remove temp files from the list or it will overflow. * src/mon-gnome.c, src/mon.c: Don't include netutil. * src/dparent.c (dcc_standalone_server): Set defer-accept bit. * man/distccd.1: Document DISTCC_TCP_DEFER_ACCEPT. * src/netutil.c (dcc_defer_accept): New function. 2004-02-29 Martin Pool * test/testdistcc.py (ScanArgs_Case): Test -Wa,-xarch=v8. * src/arg.c (dcc_scan_args): Allow "-Wa,-xarch=v8" to be remote. Reported by Ben Scarlet. * test/testdistcc.py (ScanArgs_Case): Add test cases for -x handling. * src/arg.c (dcc_scan_args): Handle invocations like "-xcpp" with no space after -x. Suggested by Ben Scarlet. * test/testdistcc.py (CompressedCompile_Case): Add a test of compression. * src/mon-gnome.c: Include sys/loadavg.h if available. * configure.ac: Check for sys/loadavg.h. Suggested by Dimitri Papadopoulos. * man/distcc.1: Document comments in host files. * test/testdistcc.py (ParseHostSpec_Case): Add test for "localhostbutnotreally". * src/hosts.c (dcc_parse_hosts): Fix matching of hosts with names like "localhost2". 2004-02-20 Martin Pool * src/compress.c (dcc_r_bulk_lzo1x): ftruncate the file after munmapping, rather than before. Might be better on HP-UX which has problems with IO on mapped files. * README.packaging: Update description of why packagers should change version numbers. 2004-02-19 Martin Pool * src/netutil.c (dcc_sockaddr_to_string): Handle null sockaddr. * src/srvnet.c (dcc_check_client): Handle null sockaddr. * src/daemon.c (dcc_inetd_server): If there is no sockaddr, pass it as NULL. * src/netutil.c (dcc_sockaddr_to_string) [ENABLE_RFC2553]: Failure to convert the address to a string should be just a warning, not an error. Add special cases for unix-domain sockets and unknown address families. Possibly fixes SSH connections with ENABLE_RFC2553. * src/daemon.c (dcc_inetd_server): Downgrade warning on getpeername failure to just a notice message. 2004-02-19 Albert China * test/testdistcc.py: Get test suite working on most of the platforms we support: 1. Not much use in testing with the native compiler so we *force* the test suite to use gcc. 2. Rather than picking up gcc from $PATH, we pass the full path to GCC. This avoids problems when distccd is running. 3. I've added known failures on some platforms. For example, the assembler test should only run on Linux x86. Where we know the test will fail, we print: DashONoSpace_Case NOTRUN, GCC mips-tfile wants space after -o ... RemoteAssemble_Case NOTRUN, Linux x86 only PreprocessAsm_Case NOTRUN, Linux x86 only ... The tests pass on: HP-UX 10.20, 11.00, 11i; IRIX 6.5; Redhat Linux 7.1, 9; Solaris 7, 8, 9; Tru64 UNIX 4.0d, 5.1 2004-02-18 Albert China These patches were tested on: AIX 4.3.2, 5.1; HP-UX 10.20, 11.00, 11i; IRIX 6.5; Redhat Linux 7.1, 9; Solaris 2.5.1, 2.6, 7, 8, 9; Tru64 UNIX 4.0D, 5.1: * src/exitcode.h: IBM C compiler doesn't like trailing commas after last enum constant. * src/clinet.c: Define h_errno for HP-UX 10.20. * src/distcc.h: Forward declaration of 'struct sockaddr' gives problems with IBM C compiler. And, it's not needed. * src/serve.c: Forgot to include Needed on HP-UX 10.20, 11.00, 11i. * src/types.h: Remove definition of socklen_t if unavailable. We not declare it correctly via autoconf. * configure.ac: a) Better detection for socklen_t. This code is taken from curl but we submitted it so we own the copyright. Feel free to use as you please. b) Existence of mmap() doesn't imply MAP_FAILED exists. So, test and define it if unavailable. c) Replace the AC_CHECK_FUNCS(connect) mess. 2004-01-30 Martin Pool * src/hosts.c (dcc_parse_hosts): Fix problem where we accidentally detected localhost at end of string. * src/h_hosts.c (main): Fix up verbose mode. * test/testdistcc.py (ParseHostSpec_Case.runtest): Test parsing of comments in host specifications. * src/hosts.c (dcc_parse_hosts): Skip over hash comments in host specifications. 2004-01-11 Martin Pool * src/srvnet.c (dcc_check_client): Take list of allowed addresses as a new parameter so that this file doesn't depend on opt.c. * src/h_sa2str.c: New test harness. * Makefile.in (h_sa2str): new test. 2004-01-09 Martin Pool * configure.ac: Make --without-gnome, --without-gtk, --disable-profile all turn the relevant options off rather than on. * Makefile.in: Add man/distccmon-text.1, and clean up manpage handling. * man/distccmon-text.1: Fix some typos. * src/dopt.c (distccd_parse_options): Option arguments should be held in (const char *). * src/setuid.c (dcc_discard_root): Must setuid after setgid, not before. Fix from Wayne Davison. * src/mon.c (dcc_mon_check_orphans): When checking if a process exists, accept EPERM as indicating it exists but isn't ours. This allows watching the directory of a different user. Reported by Ernst Bachmann. 2003-12-21 Shri Shrikumar * man/distccmon-text.1: New manpage. 2003-12-15 Martin Pool * man/distccd.1: Mention TMPDIR. * man/distcc.1: We don't use a subdirectory of TMPDIR anymore. 2003-11-28 Harold L Hunt II * configure.ac, Makefile.in: Add --with-docdir=PATH option to set install location for documents. The default is the same as previously: ${datadir}/doc/distcc. 2003-11-28 Martin Pool * src/distcc.h (dcc_sockaddr_storage): Different method for choosing the type for dcc_sockaddr_storage. We now use a plain sockaddr unless RFC2553 was requested, in which case we use sockaddr_storage. HAVE_SOCKADDR_STORAGE is only used as a check that the RFC2553 implementation is reasonable. * src/distcc.h (dcc_sockaddr_storage): Use a new type name for our replacement of sockaddr_storage, rather than calling it sockaddr_storage, to make it more clear that it's determined by autoconf. * src/prefork.c (dcc_preforked_child): Use dcc_sockaddr_storage. * src/dparent.c (dcc_forking_parent): Likewise. * src/daemon.c (dcc_inetd_server): Likewise. 2003-11-23 Martin Pool * src/netutil.c (dcc_sockaddr_to_string) [ENABLE_RFC2553]: Include the port number in the returned string, as for !ENABLE_RFC2553. This looks a bit wierd for IPv6 but is legible and unambiguous at least for output. Increase static buffer size. * src/clinet.c (dcc_connect_timed): Check SO_ERROR to see if the connection failed so that we can trap it at this point rather than waiting until we start doing IO. * src/distcc.h [ENABLE_RFC2553]: sockaddr_storage is required for RFC2553. * src/dparent.c (dcc_nofork_parent, dcc_forking_parent): Socket addresses should be stored on the stack in sockaddr_storage so that IPv6 addresses will fit. We always have this type, or can simulate it. * src/prefork.c (dcc_preforked_child): Likewise. * src/srvnet.c (dcc_socket_listen) [ENABLE_RFC2553]: Don't prefer to listen on IPv4 addresses, just use whatever the operating system thinks is best. * INSTALL: Suggest using --with-gnome and --enable-rfc2553. * man/distccd.1: Add description of --log-level. * src/dopt.c: New --log-level option to accomodate people who only want to log errors. * src/trace.c, src/trace.h (rs_loglevel_from_name): New function. * configure.ac, Makefile.in: Check pkg-config information for GNOME/GTK+ at configure time, not build time. This is a bit quicker than running the script for every file we build, and means that PKG_CONFIG_PATH only needs to be set for configure. * src/lock.c: Doc. 2003-11-17 Lionel Sausin * man/fr/distcc.1, man/fr/distccd.1: French translations of the manual pages. 2003-11-17 Martin Pool * distcc.h: MAXPATHLEN is not defined on GNU/Hurd, so supply a reasonable default value of 4096. Reported by Santiago Vila. 2003-11-17 Martin Pool * sendfile.c: Documentation updates. 2003-11-17 Allan Saddi * sendfile.c (sys_sendfile): BSD implementation of this function needs to return -1 when transmission fails with EAGAIN and no bytes were sent. 2003-11-17 Martin Pool * setuid.c (dcc_discard_root): Wayne suggests calling setgid()/setuid() before doing setgroups(). setgroups() on Mac OS X Jaguar can't seem to handle setting to 0 groups, so just set it to the same as the regular group. 2003-10-30 19:02 Martin Pool * doc/release-names.txt: [no log message] 2003-10-28 11:38 Martin Pool * configure.ac: Bump version. 2003-10-23 13:36 Martin Pool * autogen.sh: Remove check on autoconf version because it breaks on non-numeric versions like "2.57a". 2003-10-23 10:50 Martin Pool * man/distccd.1: Add some description of search paths. 2003-10-23 10:44 Martin Pool * man/distcc.1: Add some description of search paths. 2003-10-23 10:14 Martin Pool * TODO: More tasks to do. 2003-10-23 09:56 Martin Pool * NEWS, configure.ac: Prepare for 2.11.2 release 2003-10-14 14:23 Martin Pool * gnome/distccmon-gnome.desktop, NEWS: Desktop file corrections from Dag Wieers. 2003-10-13 23:57 Martin Pool * TODO: Notes on current bugs. 2003-10-13 20:05 Martin Pool * src/distcc.c: Don't trim the path at all when our invocation name is "distcc". 2003-10-13 19:52 Martin Pool * src/util.c: dcc_trim_path: Trace the compiler name. 2003-10-13 19:51 Martin Pool * src/util.c: dcc_trim_path: Doc. 2003-10-13 19:39 Martin Pool * src/distcc.c: Doc. 2003-10-13 19:24 Martin Pool * src/climasq.c: Doc. 2003-10-13 19:03 Martin Pool * NEWS, src/distcc.c, src/dsignal.c: Fatal signal handlers for client and daemon should reset the signal vector before doing anything else, to protect against an (unlikely) spin if the signal is re-sent. 2003-10-13 19:00 Martin Pool * src/distcc.c: Doc typo 2003-10-13 18:39 Martin Pool * src/: distcc.c, dsignal.c: Use AC_TYPE_SIGNAL to set signal handler return type for portability. 2003-10-13 18:38 Martin Pool * doc/example/xinetd, NEWS: Add type = UNLISTED to cope without an /etc/services entry. 2003-10-13 18:34 Martin Pool * configure.ac: Doc * Add check for signal return type. 2003-10-13 17:56 Martin Pool * man/distcc.1: Bump date. 2003-10-13 17:56 Martin Pool * man/distcc.1, NEWS: Clear up meaning of UNCACHED_ERR_FD. 2003-10-13 17:37 Martin Pool * README.packaging: Suggest adding to /etc/services. 2003-10-13 17:06 Martin Pool * man/distccd.1: Clarifications/corrections to --allow description. 2003-10-13 16:52 Martin Pool * NEWS: IRIX fixes. 2003-10-13 16:42 Martin Pool * src/serve.c: dcc_check_compiler_masq: Remove dead variable. 2003-10-13 16:40 Martin Pool * src/dparent.c: dcc_log_child_exited: Use appropriate log severity to match the signal severity, even on machines that don't have strsignal(). 2003-10-13 16:37 Martin Pool * TODO: Notes on better scheduling. 2003-10-13 16:26 Martin Pool * NEWS: Remove dependency on libglade. * Fix --without-gnome. 2003-10-13 16:24 Martin Pool * gnome/: distccmon-gnome.glade, distccmon-gnome.gladep: Remove Glade packages. 2003-10-13 16:20 Martin Pool * src/mon-gnome.c: Set icon on monitor window from png file. 2003-10-13 16:15 Martin Pool * src/mon-gnome.c: Remove dependency on Glade by rolling back to by-hand construction of window components, based on the code in 2.10. 2003-10-13 16:10 Martin Pool * Makefile.in: Don't require libglade. 2003-10-13 16:09 Martin Pool * configure.ac: Correct the handling of --without-gnome, etc. Previously this was treated the same as --with-gnome. * Don't require libglade. 2003-10-13 15:31 Martin Pool * configure.ac: Bump version 2003-10-08 15:47 Martin Pool * NEWS, configure.ac: Prepare for 2.11.1 release. 2003-10-08 15:45 Martin Pool * NEWS, src/arg.c, test/testdistcc.py: C++ compilation with -frepo must be local, because it emits .rpo files. 2003-10-07 16:12 Martin Pool * src/bulk.c: dcc_x_file_lzo1x should return any errors that occur. 2003-10-07 16:07 Martin Pool * src/exec.c: dcc_inside_child should be void and should never return. 2003-10-07 16:01 Martin Pool * src/: util.c, util.h: dcc_exit can be void. 2003-10-07 15:52 Martin Pool * man/distcc.1: Typo fix from Lionel Sausin. 2003-10-01 13:56 Martin Pool * src/mon.h, NEWS: Description from Frerich of how to write monitor programs, with some edits by me. 2003-09-30 12:54 Martin Pool * NEWS: Put Gnome data files into PKGDATADIR, e.g. /usr/local/share/distcc/, rather than the top-level datadir. 2003-09-30 12:49 Martin Pool * Makefile.in, src/mon-gnome.c: Put Gnome data files into PKGDATADIR, e.g. /usr/local/share/distcc/, rather than the top-level datadir. 2003-09-30 12:42 Martin Pool * configure.ac, Makefile.in: New @INSTALL_GNOME@ substitution so that Gnome/GTK data files are only installed when necessary. 2003-09-30 12:40 Martin Pool * INSTALL: Give dependencies for --with-gtk. 2003-09-30 09:54 Martin Pool * src/state.h: Remove stdint.h. We don't use it, and it does not exist on FreeBSD 4-STABLE, according to Frerich Raabe. 2003-09-29 22:23 Martin Pool * man/distcc.1: Set datestamp. 2003-09-29 22:21 Martin Pool * NEWS: Fix for state.h 2003-09-29 22:19 Martin Pool * man/distcc.1: Documentation corrections from Lionel Sausin. 2003-09-29 16:57 Martin Pool * src/tempfile.c, NEWS: Check that we have permission to write to the specified TMPDIR, or otherwise fail. 2003-09-29 16:46 Martin Pool * src/mon.h: Doc rename to dcc_history. 2003-09-29 16:44 Martin Pool * src/mon.h: Explain why dnotify is cut out. 2003-09-29 16:33 Martin Pool * NEWS: stdint.h is not on iricks or sloaris either. 2003-09-29 16:30 Martin Pool * src/access.c, src/h_parsemask.c, src/mon-text.c, src/state.c, configure.ac: Remove stdint.h. We don't use it, and it does not exist on FreeBSD 4-STABLE, according to Frerich Raabe. 2003-09-29 16:16 Martin Pool * configure.ac: Make it just --with-gtk. 2003-09-29 16:15 Martin Pool * configure.ac: Fix help string for --with-gtk+. 2003-09-29 16:13 Martin Pool * NEWS, configure.ac: Add support for building with either GNOME or plain GTK+. 2003-09-29 16:08 Martin Pool * src/mon-gnome.c: Remove unnecessary inclusion of headers for pango. * Allow compilation with either GNOME or plain GTK+, depending on WITH_GNOME and WITH_GTK. 2003-09-29 16:06 Martin Pool * src/renderer.c: Remove unnecessary inclusion of headers for gnome, pango and glade, and use of gettext macro. 2003-09-27 23:13 Martin Pool * src/state.h: Fix state.h for use with C++. Patch from Frerich Raabe. 2003-09-27 19:42 Martin Pool * configure.ac: Bump version. 2003-09-25 13:39 Martin Pool * src/mon-gnome.c: Include GTK as well. 2003-09-24 15:33 Martin Pool * Makefile.in: Change for new log archiving method. 2003-09-23 16:12 Martin Pool * NEWS: Prepare for release. 2003-09-23 15:58 Martin Pool * configure.ac: Run tests for GNOME packages when --with-gnome is set. 2003-09-23 15:51 Martin Pool * configure.ac: Bump to version 2.11. 2003-09-23 15:43 Martin Pool * NEWS, src/distcc.c: Client catches SIGINT, SIGHUP and SIGTERM and cleans up temporary files before terminating. 2003-09-23 15:26 Martin Pool * NEWS: Make directories and state files with weak mode bits, to try to avoid conflicts in shared distcc_dirs. 2003-09-23 15:24 Martin Pool * src/tempfile.c: dcc_mkdir: Make directory with weak mode bits, to try to avoid conflicts in shared distcc_dirs. 2003-09-23 15:22 Martin Pool * src/lock.c: dcc_open_lockfile: Open lockfile with weak mode bits, to try to avoid conflicts in shared distcc_dirs. 2003-09-23 15:18 Martin Pool * gnome/: .cvsignore, distccmon-gnome-icon.png, distccmon-gnome.desktop, distccmon-gnome.glade, distccmon-gnome.gladep: Merge from branch-pretty. Update desktop file to include the right name. 2003-09-23 15:12 Martin Pool * Makefile.in: Distribute and install GNOME data files. 2003-09-23 15:00 Martin Pool * NEWS: Change to --with-gnome for consistency with other packages. 2003-09-23 14:57 Martin Pool * test/testdistcc.py: The access mask 1.2.3.4/0 should match anything. 2003-09-23 14:53 Martin Pool * src/distcc.c: Fix bad bug in main() that caused us to exit through the wrong path. 2003-09-23 14:38 Martin Pool * configure.ac, INSTALL: Change to --with-gnome for consistency with other packages. 2003-09-23 14:28 Martin Pool * configure.ac: LINUXDOC is no longer a special variable. 2003-09-23 14:23 Martin Pool * INSTALL, Makefile.in, NEWS, TODO, configure.ac, doc/release-names.txt, src/clirpc.c, src/compile.c, src/distcc.c, src/distcc.h, src/mon-fake.c, src/mon-gnome.c, src/mon-text.c, src/mon.c, src/mon.h, src/remote.c, src/renderer.c, src/renderer.h, src/state.c, src/state.h, src/util.c, src/util.h, src/where.c: Merge the new GNOME monitor back from 'branch-pretty': * GNOME monitor now uses a custom GtkCellRenderer subclass (renderer.c, renderer.h) to draw a scarf-style history of the states for the slot. * Now uses binary state files that are quicker to write out and read in. Not compatible with monitors from the previous version. * Structure renamed from dcc_mon_list to dcc_history. Text fields are held directly in the structure to allow it to be directly written out. * State files are written and rewritten in place, rather than always being renamed into place. We cope reasonably gracefully when reading back files that are truncated. * New strlcpy() utility. * Clean up cruft in dcc_lock_one() from when we had transmission lock files. * Better handling of EXEEXT to allow tab completion to work in Makefiles. * GNOME monitor is now constructed using libglade-2, rather than the hard way. * New --enable-profile option for gprof. * Depends on libglade, pango, libgnome, libgnomeui, at least if you want the graphical monitor. * Change UNUSED() macro to make sure the variable is not accidentally used. * Rename state tags to consistent DCC_STATE_* 2003-09-23 14:02 Martin Pool * Makefile.in: Doc. 2003-09-23 14:00 Martin Pool * src/mon-gnome.c: Change colors to a set selected from the GNOME palette that are easier to distinguish. 2003-09-23 13:44 Martin Pool * gnome/distccmon-gnome.glade, src/mon-gnome.c: Remove About and Key windows, which don't do anything very useful at the moment. 2003-09-22 17:33 Martin Pool * src/mon.c: Check structure size when loading binary state files. 2003-09-22 17:32 Martin Pool * src/: state.c, state.h, where.c: Don't make the client's state structure global. * Don't need dcc_timeval_to_microseconds anymore. 2003-09-22 17:29 Martin Pool * TODO: Remove done items. 2003-09-22 17:24 Martin Pool * src/state.h: Add a size field to the state struct. 2003-09-22 17:22 Martin Pool * src/mon.h: Don't need dcc_timeval_to_double 2003-09-22 17:13 Martin Pool * src/mon-gnome.c: Don't need sys/time.h 2003-09-22 17:12 Martin Pool * src/lock.c: Don't need state.h anymore. 2003-09-22 17:10 Martin Pool * src/: compile.c, distcc.c: Don't use STARTUP state anymore. 2003-09-22 16:50 Martin Pool * INSTALL: Note gnome dependencies. 2003-09-22 15:53 Martin Pool * src/mon-gnome.c: Lower the priority of scanning for changes, so that we're more likely to keep the UI responsive. 2003-09-22 14:53 Martin Pool * src/mon-gnome.c: Doc 2003-09-22 14:51 Martin Pool * src/remote.c: Store hostname in state file, not the host definition string. 2003-09-20 19:36 Martin Pool * NEWS: Try safe lzo decompressor, to try to catch cases where the compressed data is corrupt or our output buffer is too small. 2003-09-20 16:42 Martin Pool * src/compress.c: Try safe lzo decompressor, to try to catch cases where the compressed data is corrupt or our output buffer is too small. 2003-09-19 17:23 Martin Pool * gnome/: distccmon-gnome-icon.png, distccmon-gnome.glade, distccmon-gnome.gladep: Move icons. * Add menu item to show color key. * Set size through allocation of scroll area, not through the window default_size. 2003-09-19 17:21 Martin Pool * src/mon-gnome.c: Add menu option to show chart key. 2003-09-19 17:21 Martin Pool * src/: renderer.c, renderer.h: Set bar width so that the whole history cell is filled. 2003-09-19 16:53 Martin Pool * gnome/.cvsignore: Rename icon PNG 2003-09-19 16:51 Martin Pool * gnome/distccmon-gnome.glade: Rename icon png. 2003-09-19 16:35 Martin Pool * gnome/distccmon-gnome.desktop: Add draft FreeDesktop .desktop definition. 2003-09-19 16:02 Martin Pool * src/renderer.c: Choose bar width such that the complete history roughly fills the cell. 2003-09-19 15:40 Martin Pool * src/mon.c: Quieten warnings when polling state files. 2003-09-19 15:39 Martin Pool * src/state.c: Change state name to "Preprocess". 2003-09-19 15:15 Martin Pool * src/renderer.c: Doc. 2003-09-19 14:57 Martin Pool * src/: mon-gnome.c, renderer.c, renderer.h: Create graphics contexts for drawing state strips just once at startup, rather than every time we draw a rectangle. Ought to be much more efficient. 2003-09-19 14:43 Martin Pool * configure.ac: Add --enable-profile option. * Cleanup CPPFLAGS generation. 2003-09-19 14:29 Martin Pool * src/dparent.c, NEWS: In non-forking mode, make sure to close the accepted fd after processing a request. 2003-09-19 14:01 Martin Pool * NEWS: Allow access masks like 0.0.0.0/0, meaning allow access from anywhere. Some adjustments required to allow for behaviour of C bitshift operators. 2003-09-19 13:58 Martin Pool * src/access.c: Allow access masks like 0.0.0.0/0, meaning allow access from anywhere. Some adjustments required to allow for behaviour of C bitshift operators. 2003-09-19 13:07 Martin Pool * Makefile.in: Use an autoconf substitution for EXEEXT, rather than a Make variable, so that bash's tab completion doesn't get confused by the targets. 2003-09-19 12:45 Martin Pool * NEWS: Manpage updates. 2003-09-19 12:44 Martin Pool * man/distcc.1: Suggest using SCons. 2003-09-19 12:41 Martin Pool * man/distcc.1: [no log message] 2003-09-19 12:35 Martin Pool * man/distcc.1: More explanation of Make and compiler errors. 2003-09-19 12:30 Martin Pool * man/distcc.1: More discussion of where to place localhost in the list. 2003-09-19 12:21 Martin Pool * src/tempfile.c: [no log message] 2003-09-19 12:06 Martin Pool * NEWS: [no log message] 2003-09-19 12:03 Martin Pool * patches/: backlog-sample.c, colorgcc, compression.patch, connect-timeout-02.diff, daemon-address-binding.diff, distcc-ethereal.diff, distcc-hostlist.diff, distcc-hostopt.patch, distccd-clean-path.diff, prefork-sample.c, state-in-home.diff, trylzo.c: Remove obsolete patches. 2003-09-19 11:47 Martin Pool * NEWS: [no log message] 2003-09-18 19:53 Martin Pool * src/mon-gnome.c: Retain history of 100 states. 2003-09-18 18:58 Martin Pool * src/renderer.c: Draw "DONE" states as empty. 2003-09-18 18:32 Martin Pool * src/renderer.c: Render the slot history as a set of state stripes. This looks great! 2003-09-18 18:18 Martin Pool * src/renderer.c: Kill dead code. 2003-09-18 18:01 Martin Pool * src/mon-gnome.c: Trim the history queue length every time we add to it. 2003-09-18 17:58 Martin Pool * src/renderer.c: Cope with the "history" property being a GQueue of state values, rather than a list of dcc_history structures. * Just the first state is drawn through the whole cell at the moment. 2003-09-18 17:57 Martin Pool * src/mon-gnome.c: Fix pointer error in prepending to an existing history queue. 2003-09-18 17:55 Martin Pool * src/mon-gnome.c: Fix up code to insert at end. 2003-09-18 17:48 Martin Pool * src/mon-gnome.c: Actually go ahead and store the state history in a queue in all rows. Create this queue when the row is first inserted. * Change appended rows to go through dcc_insert_row_from_task() so that we can set up the queue. 2003-09-18 17:25 Martin Pool * src/mon-gnome.c: Doc * Store a GQueue of state values in the table row, so that the cell renderer can easily read back all of them and draw them. * Split out code to insert a row into dcc_insert_row_from_task(), because it needs to construct a new GQueue. * rename dcc_clear_row -> dcc_set_row_idle() 2003-09-18 17:05 Martin Pool * src/mon-gnome.c: Fix number of columns. 2003-09-18 17:04 Martin Pool * src/mon-gnome.c: Add textual State column. 2003-09-18 17:00 Martin Pool * src/mon.c: Don't sort localhost specially. I think this was buggy. 2003-09-18 16:28 Martin Pool * src/mon-gnome.c: After we finish the task list, clear any rows remaining in the table. 2003-09-18 16:21 Martin Pool * src/mon-gnome.c: dcc_update_store_from_tasks: Fix bug that caused it to lock up when it hit a host with no name or file or in DONE state. 2003-09-18 16:13 Martin Pool * src/renderer.c: Silently ignore NULL "history" properties. 2003-09-18 16:12 Martin Pool * src/mon-gnome.c: Add a "Slot" column, visible in the list. * First cut at a method for updating the tree model in place, rather than deleting it and creating a new one. Takes advantage of the tree model and the task list being in the same order to detect changed, added or deleted rows. Partially working. 2003-09-18 15:40 Martin Pool * src/mon-gnome.c: Typo 2003-09-18 15:38 Martin Pool * src/mon-gnome.c: Split code for merging task list into list store into new function dcc_update_store_From_tasks(), in preparation for doing an update-in-place rather than clearing it and reloading. * COLUMN_HISTORY is currently set to NULL. It will become a pointer to a list of state values. * task_list is no longer global. It is held in memory only during the update. 2003-09-18 15:22 Martin Pool * gnome/distccmon-gnome.glade: Vertical scrollbar auto; horizontal scrollbar never. 2003-09-18 15:20 Martin Pool * src/mon-gnome.c: Doc. * Move gtk_list_store_new() to near the column number declarations to help keep them in step. * Drop unused dcc_timeval_to_double(). 2003-09-18 15:06 Martin Pool * src/renderer.c: Render the state cell solidly filled with the color for the current state. 2003-09-18 15:02 Martin Pool * src/renderer.c: Remove dead code. 2003-09-18 14:59 Martin Pool * src/mon-gnome.c: Show file name in the table too. 2003-09-18 14:54 Martin Pool * Makefile.in, gnome/distccmon-gnome.glade, src/mon-gnome.c, src/renderer.c: Roll back to using a table and cellrenderer. I think the immediately previous approach of having the monitor keep track of state history and draw an unlabelled striped bar is probably pretty good. However, I'd like to also rely on the regular table widget to give us space to draw it. This code builds and gives an empty table. The renderer is here but disabled. 2003-09-18 14:14 Martin Pool * src/compress.c: Fix up types for printing size_ts and for interfacing with minilzo. Detected when building on ia64 for Debian. 2003-09-18 10:48 Martin Pool * autogen.sh: "sed 1q" is more portable than using head to chop the version out of autoconf. Reported by Alexandre Oliva. 2003-09-18 10:39 Martin Pool * AUTHORS: [no log message] 2003-09-18 10:20 Martin Pool * NEWS: Note portability fixes. 2003-09-18 10:17 Martin Pool * src/ncpus.c, NEWS: In all cases, if we failed to determine the number of CPUs using sysconf, then assume 1. 2003-09-18 10:15 Martin Pool * src/ncpus.c: If we failed to determine the number of CPUs using sysconf, then assume 1. 2003-09-18 10:14 Martin Pool * src/ncpus.c: bsdi can use the BSD method of finding NCPUs as well. Reported by Nick Amato. 2003-09-17 17:24 Martin Pool * src/mon-gnome.c: Accumulate all task lists in a GSList (currently never truncated) and draw striped bars showing past tasks. Currently they are not placed on the right row, so the stripes are all pushed up towards the top. 2003-09-17 16:10 Martin Pool * src/: mon-gnome.c, state.c, state.h: Rework monitor yet again: :-/ * State files no longer hold a history of that process's state, just its current information, and they are removed when the process exits. This means that we cannot get very fine-grained plots of transitions between states, but it seemed to be hard to get that information displayed smoothly without burning a lot of CPU. In addition, we were getting hundreds of leftover state files, which slow down traversing the directory and are not really necessary. I'll try instead putting the burden of remembering and painting history onto the monitor, since it's the only program that really needs that information. 2003-09-17 15:44 Martin Pool * src/mon.c: Files only 60s old are now considered too old. 2003-09-17 15:41 Martin Pool * NEWS, autogen.sh: Fix autogen.sh for recent versions of GNU coreutils. Reported by Lisa Seelye. 2003-09-17 15:36 Martin Pool * src/: state.c, distcc.c: Move back towards removing state files when the client process that they belong to exits. 2003-09-17 12:27 Martin Pool * src/mon-gnome.c: Skip tasks on no host * Draw labels again * Refresh every 300ms 2003-09-17 12:24 Martin Pool * src/renderer.c: GtkCellRenderer is no longer needed 2003-09-17 12:21 Martin Pool * COPYING.FDL: The GNU FDL need not be included, because the SGML manual is gone. All the documentation is in the manpages, which are GPL'd. 2003-09-17 12:16 Martin Pool * man/distcc.1: Set date. 2003-09-17 12:14 Martin Pool * man/: distccd.1, distcc.1: Add no-warranty statement. 2003-09-17 12:11 Martin Pool * Makefile.in: COPYING.FDL is no longer included, because the manpages are GPL'd. 2003-09-16 19:27 Martin Pool * src/mon-gnome.c: Only draw rectangles of >=1 width. 2003-09-16 19:17 Martin Pool * src/: mon-gnome.c, mon.c, state.c, state.h: Handle times as microseconds-since-epoch rather than doubles. * Rework task drawing routine to correctly handle tasks that have already completed. Currently working but a bit slow. 2003-09-16 19:06 Martin Pool * patches/lisa--recursive-mkdir-uid-distccdir.patch: Patch from Lisa. 2003-09-16 19:00 Martin Pool * src/mon-gnome.c: Better attempt at drawing current and previous tasks. 2003-09-16 18:38 Martin Pool * src/distcc.c: Make a better attempt at always recording DONE when we are. 2003-09-16 18:13 Martin Pool * src/mon-gnome.c: Center text labels in bars. * Set bar height to 1.5x text height. * Draw host name once per row. 2003-09-16 18:03 Martin Pool * src/: mon-gnome.c, state.h: Much simpler fix for identifying multiple tasks in the same slot: now that things are sorted properly, we can just find neighbouring history reports and check if they're the same. That should make drawing past tasks easy... 2003-09-16 15:57 Martin Pool * src/state.h: Add a pointer to the next on this slot. 2003-09-16 15:55 Martin Pool * src/mon-gnome.c: Update every 200ms * Allocate rows for each host slot, so that we can draw multiple tasks onto each line. 2003-09-16 15:08 Martin Pool * src/mon.c: Sort localhost to the front of the list of tasks. 2003-09-16 15:04 Martin Pool * src/mon.c: Return list of running tasks sorted by hostname and slot to make monitor displays more likely to keep tasks in a stable position. 2003-09-16 14:36 Martin Pool * src/mon.c: Don't need signal.c 2003-09-16 14:23 Martin Pool * NEWS: Note that we should now work on BSD/OS. 2003-09-16 14:20 Martin Pool * NEWS: Call getpgrp() rather than getpgid(), because it's the POSIX.1 standard function. Suggestion from Nick Amato. 2003-09-16 14:19 Martin Pool * src/exec.c: Call getpgrp() rather than getpgid(), because it's the POSIX.1 standard function. 2003-09-16 13:56 Martin Pool * src/mon-gnome.c: Don't draw border. * Do get proper alignment between host names and task bars. * Include slot number in the name. 2003-09-16 13:28 Martin Pool * src/mon-gnome.c: Draw host names on left. (Not very well. :-) 2003-09-16 13:24 Martin Pool * src/mon-gnome.c: Leave space on the left to draw hostnames, and draw a splitter bar at that point. * Draw a border around the drawingarea. 2003-09-16 13:10 Martin Pool * Makefile.in: Roll back to using a GtkDrawingArea rather than a table. renderer.c is no longer needed. 2003-09-16 13:08 Martin Pool * src/mon-gnome.c: Fix up rollback. 2003-09-16 13:07 Martin Pool * src/mon-gnome.c: Roll back to 1.43.2.37, using a GtkDrawingArea rather than a table. 2003-09-16 12:42 Martin Pool * gnome/distccmon-gnome.glade: Merge back to DrawingArea in 1.1.2.14. No other changes. 2003-09-15 17:57 Martin Pool * src/mon-gnome.c: Redraw the chart more frequently than we reload the task list, so that scrolling seems smoother. 2003-09-15 17:32 Martin Pool * src/renderer.c: Fix horizontal gaps between stripes. 2003-09-15 17:30 Martin Pool * src/mon-gnome.c: Update every 200ms 2003-09-15 17:23 Martin Pool * src/renderer.c: Draw tasks as multiple strips for each state. 2003-09-15 17:18 Martin Pool * src/: mon-gnome.c, mon.h: Remove old GCs * Make dcc_timeval_to_double global 2003-09-15 17:14 Martin Pool * src/mon-fake.c: Split out code for fake monitor data; currently not used. 2003-09-15 17:02 Martin Pool * src/renderer.c: Partially merge some code from the old GtkDrawingArea implementation, so that we have better-factored code for drawing state strips. 2003-09-15 16:50 Martin Pool * src/renderer.c: Fix unused params. 2003-09-15 16:36 Martin Pool * src/distcc.h: UNUSED macro should mangle the variable name to make sure that parameters marked UNUSED are not accidentally used. 2003-09-15 16:34 Martin Pool * src/renderer.c: Draw state color and filename from the history record. 2003-09-15 16:29 Martin Pool * src/mon-gnome.c: Go back to a "history" property, being a pointer to a list of tasks. 2003-09-15 16:21 Martin Pool * src/: renderer.c, mon-gnome.c: Go back to a "history" property, being a pointer to a list of tasks. 2003-09-15 16:04 Martin Pool * src/where.c: Only enter BLOCKED state when we need to sleep waiting for a slot. 2003-09-15 16:03 Martin Pool * src/where.c: Sleep only 1s when bored. 2003-09-15 16:02 Martin Pool * src/state.h: Expose client state. 2003-09-15 16:01 Martin Pool * src/where.c: Fix code that caused us not to record the right slot number for local builds. Remove old code left over from transmission locks. 2003-09-15 15:53 Martin Pool * src/: lock.c, mon-gnome.c, renderer.c, state.c, state.h, where.c: * Store slot number as an integer in the state file. 2003-09-15 15:51 Martin Pool * src/mon-text.c: Show slot number in text display. 2003-09-15 15:33 Martin Pool * src/: mon-gnome.c, renderer.c, state.h: Change to storing slot name in the state file so that we can easily work out which tasks to draw on which line. Use a global variable to publish that information to the cell renderer. 2003-09-15 14:54 Martin Pool * src/renderer.c: Make the colored region fill the whole strip. 2003-09-15 14:46 Martin Pool * src/renderer.c: Draw text for jobs vertically centered within their rectangle. 2003-09-15 00:41 Martin Pool * src/renderer.c: Draw text into the task blocks. 2003-09-14 20:17 Martin Pool * src/renderer.c: Draw a border around the state rectangle, and try to take the padding into account when drawing. 2003-09-14 19:48 Martin Pool * Makefile.in: Cosmetic 2003-09-14 19:24 Martin Pool * src/: mon-gnome.c, renderer.c: Renderer now draws process states in something like the right color. 2003-09-14 17:43 Martin Pool * src/renderer.c: Add get/set code for history property. 2003-09-14 17:40 Martin Pool * src/: renderer.c, renderer.h: The implementation structures for the cell renderer can be more private. 2003-09-14 17:38 Martin Pool * src/renderer.c: Add a "task-history" property to the CellRenderer, currently storing only an integer that will be the current task's state. We don't handle sets/gets on it yet. 2003-09-14 17:33 Martin Pool * src/mon-gnome.c: Allow sorting by host name. * Make the tasks column in the list model store an integer, so that we can give it the current task's state. Bind this cell to the "task-history" property of the renderer. 2003-09-14 17:18 Martin Pool * src/: mon-gnome.c, mon-text.c, mon.c, mon.h, state.c, state.h: Rename dcc_client_history to just dcc_history. 2003-09-14 17:17 Martin Pool * NEWS: Add release header. 2003-09-14 17:09 Martin Pool * src/renderer.c: Doc 2003-09-12 17:23 Martin Pool * src/renderer.h: Add state field to _DccCellRendererChart 2003-09-12 17:16 Martin Pool * src/renderer.c: Implement dcc_cell_renderer_chart_get_size 2003-09-12 17:08 Martin Pool * src/renderer.c: Add a simpleminded implementation of dcc_cell_renderer_chart_render() that can draw the chart cells as black rectangles. 2003-09-12 15:58 Martin Pool * src/renderer.c: Implement the get_property and set_property methods. 2003-09-12 15:49 Martin Pool * src/renderer.c: Fix call to g_type_register_static, which needs a reference to the parent type. 2003-09-12 15:46 Martin Pool * src/: renderer.c, renderer.h: Add GTK Type boilerplate to create a new GtkCellRenderer. 2003-09-12 13:08 Martin Pool * Makefile.in, src/mon-gnome.c, src/renderer.c, src/renderer.h: Put renderer interface into renderer.h 2003-09-12 13:05 Martin Pool * Makefile.in, src/mon-gnome.c, src/renderer.c: Split out draft GtkCellRenderer into its own file. 2003-09-11 19:07 Martin Pool * src/mon-gnome.c: Start adding a custom renderer. Doesn't do anything yet. 2003-09-11 18:57 Martin Pool * src/mon-gnome.c: As an experiment, draw pixbufs into the task cells using a GtkCellRendererPixmap, rather than text. This seems to be working OK. 2003-09-11 18:47 Martin Pool * src/mon-gnome.c: Put hostname and state into the tree model as they're updated. 2003-09-11 18:47 Martin Pool * gnome/distccmon-gnome.glade: Turn off rules_hint on table. 2003-09-11 18:23 Martin Pool * src/mon-gnome.c: Add a task column. 2003-09-11 18:17 Martin Pool * gnome/distccmon-gnome.glade, src/mon-gnome.c: Move back towards using a table, but now with space for our own GtkCellRenderer to draw a chart for each host slot. At the moment nothing is in the table, just a column for host names. 2003-09-11 17:44 Martin Pool * src/mon-gnome.c: Cut out trace messages. 2003-09-11 17:31 Martin Pool * src/mon-gnome.c: Use real task information. * Avoid coloring in areas that will be hidden by the border. * Make the border the correct width. 2003-09-11 17:15 Martin Pool * src/mon-gnome.c: Draw text labels in black. * Add a second file to the fake information. * Set the start time on fake files. * Draw all states for a file, using the old code but adapted to drawing on the DrawingArea not a canvas. 2003-09-11 15:19 Martin Pool * src/mon-gnome.c: Draw tasks from a faked up list, rather than just drawing arbitrary rectangles. * Redraw window using gtk_widget_queue_draw rather than Gdk. This seems to fix a problem with redraw. Perhaps we were passing the wrong rectangle. 2003-09-11 15:02 Martin Pool * src/mon-gnome.c: Set bar height from font height. Now when you change the GNOME system font, all the bars redraw to the right height. That is so cool. :-) 2003-09-10 22:51 Martin Pool * src/mon-gnome.c: Cut out expose trace events. 2003-09-10 22:48 Martin Pool * src/mon-gnome.c: Stub out display of tasks so that we do get something correctly drawn again. 2003-09-10 18:27 Martin Pool * Makefile.in, configure.ac: We need Pango as well for GNOME. 2003-09-10 18:27 Martin Pool * src/mon-gnome.c: Start adding support for fake monitor data for testing. 2003-09-10 17:03 Martin Pool * src/mon-gnome.c: Draw tasks from the task list. 2003-09-10 16:25 Martin Pool * src/mon-gnome.c: Draw tasks by creating a new PangoLayout each time using the GTK+ helper. 2003-09-10 16:13 Martin Pool * src/mon-gnome.c: Draw labels onto file rectangles using Pango. How cool! 2003-09-10 15:27 Martin Pool * gnome/distccmon-gnome.glade: Put the chart drawing into a GtkAlignment so that we can get a 6px border around it. It was looking a bit cramped against the window border. 2003-09-10 15:17 Martin Pool * src/mon-gnome.c: Allocate GCs for all states. * Draw nice gray outlines around all task rectangles. 2003-09-10 15:05 Martin Pool * src/mon-gnome.c: Invalidate/repaint the chart widget every time we update the list. 2003-09-10 15:00 Martin Pool * src/mon-gnome.c: Factor out code for drawing state rectangles (back) into dcc_draw_state_rect(). * Draw a whole array of dummy tasks. 2003-09-10 14:55 Martin Pool * src/mon-gnome.c: Allocate a graphics context in the appropriate color and use it to draw our dummy tasks. 2003-09-10 14:32 Martin Pool * src/mon-gnome.c: Stub for on_chart_drawing_expose(). 2003-09-10 14:19 Martin Pool * gnome/distccmon-gnome.glade, src/mon-gnome.c: Rework again: * Start adding a 'key' window showing all the state colors. * Go back to a DrawingArea for showing the chart (just experimental). * Delete table view from monitor. 2003-09-09 18:17 Martin Pool * src/state.h: States must be listed in the order in which they're run. 2003-09-09 18:15 Martin Pool * src/mon-gnome.c: Update every 150ms. * Don't update the table. * Don't include DONE tasks. * Left-align filename. * Don't outline tasks. * Reorder color list for new state enum. * Make sure all states are drawn properly. This is leaking memory badly! 2003-09-09 17:54 Martin Pool * src/compile.c: Record input filename as soon as it is known. 2003-09-09 17:53 Martin Pool * src/state.c: Don't update state times that are already recorded. 2003-09-09 17:52 Martin Pool * src/where.c: Go into BLOCKED state at the start of the locking phase, so that we don't need to update repeatedly. 2003-09-09 17:29 Martin Pool * src/mon-gnome.c: Draw compilation tasks as striated rectangles. Handling of DONE tasks is not OK yet. 2003-09-09 17:14 Martin Pool * src/: compile.c, distcc.c: Go into STARTUP state earlier in the client process. 2003-09-09 17:09 Martin Pool * src/state.c: Make sure the time is recorded even for state 0. In fact, always update the time whenever dcc_note_state() is called. 2003-09-09 16:57 Martin Pool * src/compile.c: Please do use DCC_STATE_STARTUP so that we know when we started. 2003-09-09 16:43 Martin Pool * src/mon-gnome.c: Factor out code to create canvas items for the task 2003-09-09 16:21 Martin Pool * src/mon-gnome.c: Color task bars according to current state. 2003-09-08 21:12 Martin Pool * src/mon-gnome.c: Check for glade definition file in ., ./gnome, and DATADIR. 2003-09-08 21:10 Martin Pool * Makefile.in: Fix Make syntax 2003-09-08 21:09 Martin Pool * Makefile.in: Pass in DATADIR (e.g. /usr/local/share) when installing. 2003-09-08 18:11 Martin Pool * src/mon-gnome.c: More experiments in drawing. 2003-09-08 18:10 Martin Pool * gnome/distccmon-gnome.glade: Try a Canvas in a GtkAlignment 2003-09-08 17:47 Martin Pool * src/mon-gnome.c: More progress on canvas display * Skip done tasks * Show a nice vertical stack of running tasks, with the file name in each, and drawn with reasonable colors. 2003-09-08 17:33 Martin Pool * src/mon-gnome.c: More progress on canvas display * Put all bars into an overall group, so that they can all be removed every time we redraw. * Create all process bars in one group each time. 2003-09-08 16:39 Martin Pool * src/mon-gnome.c: More fixups for new state mechanism * Convert state to a string before putting it into the table. * Skip done tasks. 2003-09-08 16:26 Martin Pool * src/mon-gnome.c: Fix up (mostly renames) for new monitor interface. 2003-09-08 16:21 Martin Pool * src/mon-text.c: Skip display of Done tasks. 2003-09-08 16:20 Martin Pool * src/state.c: Add missing state names. 2003-09-08 16:19 Martin Pool * src/state.c: Make sure to actually record our state! 2003-09-08 16:12 Martin Pool * src/: state.c, state.h, mon-text.c: Put state names into a new function dcc_get_state_name, rather than into constants. 2003-09-08 16:08 Martin Pool * src/mon.c: Processes that have exited can still be returned. 2003-09-08 16:01 Martin Pool * src/mon.c: Now that we're storing client history, it's OK to return information about processes that have already exited. We just need to make sure that their state gets set to DCC_STATE_DONE. 2003-09-08 15:59 Martin Pool * src/state.c: Put the client pid into the state file. 2003-09-08 15:57 Martin Pool * src/: mon.c, state.c, state.h: Store a magic number in the binary state file as a little protection. * Align magic and pid fields to unsigned longs. 2003-09-08 15:51 Martin Pool * src/state.c: Store history of state transitions in the state file. 2003-09-08 15:48 Martin Pool * NEWS, src/clirpc.c, src/compile.c, src/distcc.c, src/mon-text.c, src/mon.c, src/mon.h, src/remote.c, src/state.c, src/state.h, src/where.c: Many changes to the representation of the client state to make it easier to draw a history. * State is now stored as a natively encoded struct in a disk file, rather than using our network protocol. This is slightly faster, makes it easier to store multiple fields, and avoids tangling up the state file handling (which ought to ignore errors) with network IO. * States can now be written and read with one atomic IO, and we don't use temporary files. * States are represented by integers not strings. * There is space in the state file for a history of times that it entered particular states. 2003-09-08 15:29 Martin Pool * src/: util.h, util.c: Add strlcpy() if missing. 2003-09-08 15:29 Martin Pool * configure.ac: Add check for strlcpy(). 2003-09-08 13:17 Martin Pool * src/mon-gnome.c: Draw rectangles onto the canvas for each job that's currently running. 2003-09-08 13:11 Martin Pool * src/mon-gnome.c: Set canvas scroll region at startup. 2003-09-08 13:04 Martin Pool * src/mon-gnome.c: Draw little rectangles into the chart from the timer callback to prove that we can. 2003-09-08 12:51 Martin Pool * src/mon-gnome.c: Prepare to update both table and chart from one timer callback. Refactor into a part that gets the process list and a new function that updates the table model. * Add some prototypes for functions called by glade to silence compiler warnings. 2003-09-08 12:45 Martin Pool * src/mon-gnome.c: Rename setup_proc_view -> setup_table_view. * Doc. 2003-09-08 12:44 Martin Pool * src/mon-gnome.c: Document design of chart view. 2003-09-07 22:54 Martin Pool * src/mon-gnome.c: Draw a rectangle onto the chart to see it working. 2003-09-07 19:09 Martin Pool * gnome/distccmon-gnome.glade: Swich from a DrawingArea to a Canvas for the chart view. 2003-09-07 19:04 Martin Pool * src/mon-gnome.c: Swich from a DrawingArea to a Canvas for the chart view. 2003-09-07 19:03 Martin Pool * Makefile.in: Move mon-gnome.c back to src/ * Pull out common list of packages to be passed to pkg-config. * Compile mon-gnome.c separate from linking. 2003-09-07 18:53 Martin Pool * gnome/mon-gnome.c, src/mon-gnome.c: Move mon-gnome.c back to src/ 2003-09-05 17:01 Martin Pool * gnome/mon-gnome.c: Abort if we can't find the glade XML file. 2003-09-04 15:20 Martin Pool * man/distcc.1: Clear up explanation of --allow option. * Note that "gcc hello.c" is not split. 2003-09-03 12:41 Martin Pool * src/where.c, NEWS: Sleep only one second when blocked, to try to reduce idle time when recovering from an overloaded period. 2003-09-01 23:20 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Draw big black ellipse in the chart area. 2003-09-01 23:15 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Try to make View menu items toggle each other. Not working yet. 2003-09-01 23:09 Martin Pool * gnome/distccmon-gnome.glade: Put tabs on the notebook just for the time being. 2003-09-01 23:02 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Flip between view notebook pages when view menu items are chosen. 2003-09-01 22:47 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Add a cute monkey icon. * Add an About box and hook it up appropriately. 2003-09-01 22:23 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Hook up process table to Glade. The existing processs monitoring functions are now working again. 2003-09-01 22:09 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Get load bar hooked up for Gnome monitor. 2003-09-01 22:04 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: More merges of monitor code into Glade interface. * Set size of Glade window at startup and tweak scrollbars. 2003-09-01 21:39 Martin Pool * gnome/mon-gnome.c: Merge in all the GNOME monitor code from HEAD. 2003-09-01 21:23 Martin Pool * configure.ac: Check for other necessary libraries when --enable-gnome is given. * Bump version. 2003-09-01 13:33 Martin Pool * TODO: Idea of using gkrellm 2003-09-01 11:30 Martin Pool * man/distccd.1: Add a little more explanation of --allow. 2003-08-28 15:05 Martin Pool * TODO: Update for done tasks. 2003-08-28 15:02 Martin Pool * man/distccd.1: Note that ccache can't be called from distccd. 2003-08-28 14:33 Martin Pool * NEWS, man/distcc.1: Note about problems with no_subtree_check. 2003-08-28 14:31 Martin Pool * TODO: DEPENDENCIES_OUTPUT is not directly a problem for distcc. 2003-08-28 12:48 Martin Pool * cases/mmaptest.c: Bug has been isolated; no longer need this test case. 2003-08-28 12:45 Martin Pool * cases/mmaptest.c: More tests for NFS bug. 2003-08-26 15:56 Martin Pool * cases/mmaptest.c: Do the mmapped IO in a child process, to be more similar to ccache/distcc. 2003-08-26 12:01 Martin Pool * cases/: .cvsignore, mmaptest.c: Add test for mmap-on-NFS problems 2003-08-25 16:06 Martin Pool * src/pump.c: Doc 2003-08-25 12:48 Martin Pool * src/: arg.c, compile.c, compress.c, serve.c: Patch from Wayne Davison to fix Solaris warnings 2003-08-25 11:55 Martin Pool * src/: compress.c, io.c, io.h, pump.c: Add DISTCC_MMAP option, defaults to on. May be useful in working around bugs with mmap on NFS. 2003-08-25 11:13 Martin Pool * man/distcc.1, man/distccd.1, NEWS: Document DISTCC_MMAP. 2003-08-15 14:17 Martin Pool * Makefile.in, gnome/distccmon-gnome.glade, gnome/distccmon-gnome.gladep, gnome/mon-gnome.c: Initial stub version of the monitor. 2003-08-15 14:16 Martin Pool * src/mon-gnome.c: Move gnome monitor into its own directory. 2003-08-14 18:12 Martin Pool * TODO, gnome/distccmon-gnome.glade, gnome/distccmon-gnome.gladep, gnome/mon-gnome.c: Start doing a better GNOME monitor. 2003-08-13 13:05 Martin Pool * TODO: Note problem with DEPENDENCIES_OUTPUT. 2003-08-13 12:57 Martin Pool * configure.ac: Bump version. 2003-08-12 13:34 Martin Pool * man/distcc.1: Update manpage date. 2003-08-12 13:27 Martin Pool * test/testdistcc.py: Set DISTCC_DIR when running tests to give better isolation between tests and anything else that might be happening on the machine. 2003-08-12 13:18 Martin Pool * Makefile.in: make distcheck ought to run maintainer-check and also check that the directory can be cleaned. 2003-08-12 13:10 Martin Pool * NEWS: Note "make clean" problem is fixed. 2003-08-12 13:09 Martin Pool * configure.ac: Bump version to 2.10.1 2003-08-12 11:42 Martin Pool * Makefile.in: Fix "make clean" problem in lzo. Reported by Lisa Marie Seelye. 2003-08-11 16:09 Martin Pool * cases/hello.c: Make hello actually say hello 2003-08-11 16:07 Martin Pool * distcc-check: Allow the compiler to be changed. 2003-08-11 16:05 Martin Pool * NEWS, configure.ac: Prepare for release. 2003-08-11 15:51 Martin Pool * TODO: Suggestions from Lisa on the monitor. 2003-08-11 15:46 Martin Pool * src/tempfile.c: Fix from wayned for crash when DISTCC_DIR is set. 2003-08-11 15:43 Martin Pool * src/tempfile.c: Doc. 2003-08-11 15:40 Martin Pool * test/testdistcc.py: [no log message] 2003-08-11 15:33 Martin Pool * NEWS: [no log message] 2003-08-11 15:32 Martin Pool * man/distcc.1: Corrections from Frerich Raabe. 2003-08-11 15:18 Martin Pool * src/exec.c, NEWS: For simple compile failures, don't say "with exit code 1". 2003-08-11 15:15 Martin Pool * src/exec.c: Doc. 2003-08-07 15:42 Martin Pool * TODO: [no log message] 2003-08-05 12:09 Martin Pool * src/exitcode.h: Add include guard. 2003-08-05 11:56 Martin Pool * Makefile.in: Remove roadmap page, because it's now largely complete. 2003-08-05 11:53 Martin Pool * Makefile.in: Make sure examples get installed into doc/example. 2003-08-05 11:48 Martin Pool * doc/example-init, doc/example/init, doc/example/init-suse, doc/example/logrotate, doc/example/xinetd, Makefile.in, doc/example.xinetd: Move all example files into doc/example. 2003-07-25 17:34 Martin Pool * doc/results.txt: [no log message] 2003-07-25 17:25 Martin Pool * bench/Summary.py: Show summary table properly. 2003-07-25 15:50 Martin Pool * src/state.c, NEWS: Roll back to writing state into temporary files. 2003-07-25 15:36 Martin Pool * test/testdistcc.py: Doc 2003-07-25 15:35 Martin Pool * test/testdistcc.py: If the daemon fails to bind to the desired port, keep trying other ones. 2003-07-25 15:21 Martin Pool * NEWS: Store state files by writing and rewriting them directly, rather than renaming every time. That was starting to take a fair fraction of our syscalls. 2003-07-25 15:15 Martin Pool * src/state.c: Fix state file names. 2003-07-25 15:14 Martin Pool * src/state.c: Store state files by writing and rewriting them directly, rather than renaming every time. That was starting to take a fair fraction of our syscalls. 2003-07-25 14:56 Martin Pool * NEWS: [no log message] 2003-07-25 14:53 Martin Pool * src/tempfile.c: Make temp filenames more random. 2003-07-25 14:51 Martin Pool * src/tempfile.c: Check return code when closing the temporary file after creating it. 2003-07-25 14:47 Martin Pool * src/tempfile.c: O_NOFOLLOW is not needed with O_EXCL and O_CREAT, because they never follow symlinks. * Doc. 2003-07-25 14:39 Martin Pool * src/tempfile.c: dcc_make_tmpnam: Fix the case where the chosen name already exists. 2003-07-25 14:34 Martin Pool * src/tempfile.c: Create temporary files in a loop, with O_EXCL and O_NOFOLLOW to try to guard against collision with existing files or links. 2003-07-25 14:15 Martin Pool * src/: cpp.c, serve.c: Better template names for temporary files. 2003-07-25 14:08 Martin Pool * configure.ac: Check for gettimeofday 2003-07-25 13:52 Martin Pool * src/: tempfile.c, tempfile.h: dcc_get_top_dir can be static, and does not need to return a newly-allocated string. 2003-07-25 13:32 Martin Pool * src/: lock.c, mon.c, state.c, tempfile.c, tempfile.h: Make sure lock dir and state dir are only created the first time we use them. 2003-07-25 13:22 Martin Pool * NEWS, src/lock.c, src/mon.c, src/state.c, src/tempfile.c, src/tempfile.h: Temporary directory is now gone. Working files are created directly under $TMPDIR, as they are for gcc. Lock files and state files are stored under DISTCC_DIR. 2003-07-25 13:18 Martin Pool * src/distcc.c: Temporary directory is no longer used. 2003-07-25 12:35 Martin Pool * Makefile.in: cleanup.c is also needed by monitors. 2003-07-25 11:53 Martin Pool * src/tempfile.c: Daemon runs from root directory, not the temporary directory. * Doc. 2003-07-25 11:51 Martin Pool * src/daemon.c, src/tempfile.h, NEWS: Daemon runs from root directory, not the temporary directory. 2003-07-24 18:58 Martin Pool * src/tempfile.c: Doc 2003-07-24 18:46 Martin Pool * src/tempfile.c: Remove dead fifo code. 2003-07-24 18:45 Martin Pool * Makefile.in, src/cleanup.c, src/tempfile.c, src/tempfile.h: Factor out tempfile cleanup into a new file cleanup.c 2003-07-24 18:43 Martin Pool * patches/ccache-uncached-err.diff: Patch to ccache to avoid caching network errors. 2003-07-24 18:20 Martin Pool * NEWS: Note about tmpdir fixes. 2003-07-24 18:17 Martin Pool * src/tempfile.c: dcc_get_tempdir: Make sure that if we fail the first time we don't pass back a bogus directory on future attempts. 2003-07-24 18:12 Martin Pool * src/distcc.c: Check up front in the client that the working directory can be created, otherwise we get a whole pile of errors when it fails. 2003-07-24 17:58 Martin Pool * src/: cpp.c, lock.c, lock.h, serve.c, state.c, tempfile.c, tempfile.h, timefile.c: Change temporary filename handling to consistently use error returns and check them. 2003-07-23 17:19 Martin Pool * src/: state.c, tempfile.c, tempfile.h: dcc_make_dir: Rename to dcc_safe_mkdir. Check the ownership of the directory after it is created to help guard against an attacker creating the directory. 2003-07-23 17:18 Martin Pool * TODO: [no log message] 2003-07-23 16:56 Martin Pool * src/tempfile.c: Doc. 2003-07-23 16:11 Martin Pool * src/tempfile.c: Don't check that TMPDIR starts with '/'. * dcc_setup_tempdir can be static. 2003-07-23 16:11 Martin Pool * src/tempfile.h: dcc_setup_tempdir can be static. 2003-07-23 16:09 Martin Pool * NEWS: Don't check that TMPDIR starts with '/'. 2003-07-22 18:02 Martin Pool * src/pump.c: Doc. 2003-07-22 17:36 Martin Pool * src/lock.c: Be strict about enums. 2003-07-22 17:35 Martin Pool * src/: clirpc.c, rpc.c, rpc.h: waitstatus is not unsigned. 2003-07-22 17:34 Martin Pool * src/filename.c: dcc_output_from_source: Remove dead variable. 2003-07-22 17:33 Martin Pool * configure.ac: Remove doubled CFLAG. 2003-07-22 17:30 Martin Pool * src/exec.c: waitstatus is not unsigned. 2003-07-22 17:25 Martin Pool * src/: exec.h, distcc.h: waitstatus is not unsigned. 2003-07-22 17:24 Martin Pool * src/compile.c: Signedness warning correction; reported by Dimitri Papadopoulos. 2003-07-22 17:21 Martin Pool * src/remote.c: timeval.h is not needed. 2003-07-22 17:19 Martin Pool * src/tempfile.c: Snip out dcc_mkfifo 2003-07-22 16:58 Martin Pool * NEWS: [no log message] 2003-07-22 16:57 Martin Pool * man/distcc.1: Document UNCACHED_ERR_FD. 2003-07-22 16:55 Martin Pool * man/distcc.1: Note that ccache doesn't handle compilation from .i files. 2003-07-22 16:47 Martin Pool * src/daemon.c: Factor out code for setting the daemon's path. * Show path for daemon at startup. 2003-07-22 16:43 Martin Pool * src/daemon.c: daemon/main: The daemon no longer trims its path, because it will emit warnings if a masqueraded directory is detected. 2003-07-22 16:42 Martin Pool * src/util.c: dcc_trim_path: This is no longer called by the server, only by the client. So remove support for detecting ccache, and require the compiler name to always be specified. 2003-07-22 16:38 Martin Pool * TODO: [no log message] 2003-07-22 16:35 Martin Pool * src/distcc.c: Remove duplicated dcc_find_basename(). 2003-07-22 14:16 Martin Pool * distcc-check: Doc 2003-07-22 14:13 Martin Pool * NEWS: Default niceness is 5. 2003-07-22 14:11 Martin Pool * src/: daemon.c, dopt.c, dopt.h, util.c: Increment niceness by 5 by default. 2003-07-22 14:08 Martin Pool * man/distccd.1: Clarify that niceness is an increment not an absolute value. * Default niceness is 5. 2003-07-22 13:58 Martin Pool * NEWS: Nasty note about SCO. 2003-07-22 13:53 Martin Pool * doc/results.txt: SSH results. 2003-07-22 12:43 Martin Pool * README.packaging: More suggestions about cross compiling from Dag Wieers. 2003-07-21 17:37 Martin Pool * src/serve.c: dcc_run_job: Before executing the compiler, check the server's path and emit a warning if it looks like a symlink to distcc. 2003-07-21 17:36 Martin Pool * NEWS: Note about finding the right compiler on the volunteer. 2003-07-21 17:14 Martin Pool * src/distcc.c: Doc. 2003-07-21 16:35 Martin Pool * src/: distcc.c: Doc. 2003-07-21 16:31 Martin Pool * src/distcc.c: distcc/main: Rename variable. 2003-07-21 16:25 Martin Pool * src/distcc.c: dcc_get_my_basename: Rename to dcc_find_basename, which is a better name, and just make it work on a string, rather than looking in an argv. This function is really no longer distcc-specific. 2003-07-21 16:06 Martin Pool * configure.ac: Bump version. 2003-07-21 15:50 Martin Pool * man/distcc.1: Remove PP 2003-07-21 15:24 Martin Pool * configure.ac, NEWS: 2.9 release. 2003-07-21 15:14 Martin Pool * configure.ac: Make sure GNOME_BIN actually gets set. 2003-07-21 15:10 Martin Pool * Makefile.in: lzoconf.h needs to be distributed. 2003-07-21 15:07 Martin Pool * doc/results.txt: [no log message] 2003-07-21 14:59 Martin Pool * src/util.c, NEWS: When trimming the path to avoid recursive invocations, stop as soon as we find one non-symlink compiler. This should help avoid the path getting trimmed down far too much on the server. Patch from Wayne Davison. 2003-07-21 14:49 Martin Pool * man/distccd.1: Suggest inetd limit be raised to 6000 2003-07-21 14:42 Martin Pool * NEWS: [no log message] 2003-07-21 14:40 Martin Pool * src/compress.c: dcc_compress_lzo1x_alloc can be static. 2003-07-21 14:20 Martin Pool * src/distcc.h: dcc_compress_lzo1x_alloc can be static. 2003-07-21 12:45 Martin Pool * NEWS: Note about documentation. 2003-07-21 12:35 Martin Pool * src/compress.c: Trace message for use of mmap. 2003-07-21 12:31 Martin Pool * src/pump.c: Trace message for receipt using mmap. 2003-07-21 12:23 Martin Pool * src/daemon.c: Tweak daemon startup message. 2003-07-21 12:21 Martin Pool * src/daemon.c: Show gnu-host in daemon startup message. 2003-07-21 12:13 Martin Pool * src/: daemon.c, daemon.h, dparent.c: Factor out code to show daemon startup message, and include the daemon mode in it. 2003-07-21 12:08 Martin Pool * TODO: [no log message] 2003-07-21 12:02 Martin Pool * src/hosts.c: Update host grammar from manpage. 2003-07-21 12:01 Martin Pool * man/distcc.1: Grammar fixes: * Be consistent about quoting. * Add LOCAL_HOST. * Make USER option in SSH production. 2003-07-21 11:59 Martin Pool * man/distcc.1: Add ccache URL * Cleanup 2003-07-21 11:56 Martin Pool * man/distccd.1: Some cleanups from Tim and myself. 2003-07-21 11:42 Martin Pool * man/distcc.1: Many suggestions from Tim: * Add quickstart section. * Consistent capitalization of "make" * Grammar/readability fixes. * Move up section about ccache with distcc * Clear up host grammar section. * What to do about broken makefiles. 2003-07-21 11:21 Martin Pool * NEWS: Note mmap support. * Delete trailing whitespace. 2003-07-21 11:17 Martin Pool * man/distcc.1: Add information about compression. 2003-07-18 16:50 Martin Pool * src/pump.c: dcc_r_bulk_plain: For uncompressed data coming in, we know the exact right length and so we only need to truncate the file once. 2003-07-18 16:48 Martin Pool * src/pump.c: Receive bulk data by writing into an mmaped file, or otherwise reading in and writing out one big buffer. 2003-07-18 16:41 Martin Pool * doc/results.txt: [no log message] 2003-07-18 16:39 Martin Pool * src/pump.c: Start implementing dcc_r_bulk_plain 2003-07-18 16:32 Martin Pool * src/: bulk.c, clirpc.c, io.c, io.h, pump.c: Rename dcc_pump_in for consistency. * Doc. 2003-07-18 16:21 Martin Pool * src/: bulk.c, compress.c, compress.h, distcc.h, pump.c: Make compression function naming consistent. * Remove compress.h 2003-07-18 16:00 Martin Pool * test/testdistcc.py: Fix silly error in ParseHostSpec_Case. 2003-07-18 15:59 Martin Pool * test/testdistcc.py: Fix VersionOption_Case for new version string that mentions two protocols. 2003-07-18 15:58 Martin Pool * test/testdistcc.py: Add partial test for parsing host specifications with the LZO option. 2003-07-18 15:57 Martin Pool * src/hosts.c: ',' should also terminate TCP hostnames. 2003-07-18 15:48 Martin Pool * NEWS: More about compression. 2003-07-18 15:45 Martin Pool * NEWS: Add support for ",lzo" option at the end of host specifications. 2003-07-18 15:43 Martin Pool * src/hosts.c: ',' should also terminate SSH hostnames. 2003-07-18 15:42 Martin Pool * src/hosts.c: Add support for ",lzo" option at the end of host specifications. 2003-07-18 15:02 Martin Pool * doc/results.txt: Results from 3.4 snapshot. 2003-07-18 13:16 Martin Pool * src/: rpc.h, rpc.c: Remove obsolete dcc_compr_for_proto() 2003-07-18 13:15 Martin Pool * src/: clirpc.c, distcc.h, hosts.c, hosts.h, lock.c, remote.c: Store both protocol and compression method in the host definition. Simpler than converting between them all the way through. 2003-07-18 12:21 Martin Pool * src/distcc.h: Reorder enums to top. 2003-07-18 12:18 Martin Pool * src/distcc.h: Make dcc_compress values not be 0-based. 2003-07-18 12:01 Martin Pool * Makefile.in, src/clirpc.c, src/clirpc.h, src/distcc.h, src/remote.c: Remove clirpc.h. 2003-07-18 11:35 Martin Pool * src/: clirpc.c, distcc.h, help.c, hosts.h, lock.c, mon-gnome.c, mon-text.c, mon.c, remote.c, rpc.c, rpc.h, serve.c, srvrpc.c, state.c: Start adding support for talking either protocol 1 or 2. Store protocol in host specification and propagate it through relevant functions. 2003-07-17 22:09 Martin Pool * src/hosts.c: Document upcoming compression option for host specifications. 2003-07-17 22:01 Martin Pool * doc/protocol-2.txt: [no log message] 2003-07-17 22:00 Martin Pool * Makefile.in: Include description of protocol version 2. 2003-07-17 21:59 Martin Pool * doc/protocol-2.txt: Description of protocol version 2. 2003-07-17 17:18 Martin Pool * src/bulk.c: Doc. 2003-07-17 17:16 Martin Pool * src/: compile.c, compile.h, remote.c: Pass source filename to dcc_compile_remote and set the state file from there so that we can get the filename in the first status message. 2003-07-17 17:11 Martin Pool * src/compress.c: Doc. * Only use mmap for buffers larger than 64k. 2003-07-17 17:04 Martin Pool * TODO: [no log message] 2003-07-17 17:03 Martin Pool * man/distcc.1: Add hostspec grammar * Some formatting changes. 2003-07-17 17:00 Martin Pool * src/hosts.c: Fix grammar nit. 2003-07-17 16:39 Martin Pool * man/distccd.1, src/dopt.c: Document --wizard. 2003-07-17 16:35 Martin Pool * NEWS, man/distccd.1: Change to starting 2+NCPUS jobs by default. 2003-07-17 16:31 Martin Pool * src/dparent.c: Change to starting 2+NCPUS jobs by default. 2003-07-17 16:24 Martin Pool * Makefile.in: Clean lzo/ directory. Patch from Wayne Davison. 2003-07-17 15:52 Martin Pool * distcc-check: Doc 2003-07-17 10:37 Martin Pool * man/distccd.1: There was some confusion about the meaning of "proportional to" in the description of -j. Now make it clearer that the number of jobs is higher than the number of CPUs. 2003-07-16 12:33 Martin Pool * Makefile.in: Remove the "tested" page. 2003-07-15 19:00 Martin Pool * src/mapfile.c: Remove mapfile; mmap is now called directly. 2003-07-15 18:51 Martin Pool * src/compress.c: Quieten warning. 2003-07-15 18:50 Martin Pool * src/compress.c: Doc * dcc_receive_lzo1x: Pass the right value to munmap(). 2003-07-15 18:47 Martin Pool * src/bulk.c: dcc_r_file: We need to open the file read/write, not just wronly, to be able to mmap it. 2003-07-15 18:45 Martin Pool * src/compress.c: dcc_compress_lzo1x_file: Make sure to return an error if the munmap failed, because we might not have managed to write everything out. * dcc_receive_lzo1x: First cut at decompressing into a writable mmap'd buffer. 2003-07-15 18:23 Martin Pool * src/compile.c: Disable "startup" state. 2003-07-15 18:21 Martin Pool * src/compress.c: dcc_compress_lzo1x_file: Try to use mmap() to read the input file if mmap() is available. If not, fall back to using malloc and read(). 2003-07-15 18:20 Martin Pool * doc/results.txt: Results from compilation on 10Mbps network. 2003-07-15 18:18 Martin Pool * Makefile.in: mapfile is no longer needed -- we just mmap as necessary. 2003-07-15 18:10 Martin Pool * configure.ac, NEWS: Don't check for GTK+ unless --enable-gnome is requested, because it's a needless portability risk on platforms that don't have it. 2003-07-15 18:04 Martin Pool * configure.ac: Check for mmap() 2003-07-15 18:02 Martin Pool * src/: bulk.c, compress.c, compress.h: Factor out code to compress from a file. 2003-07-15 17:57 Martin Pool * src/bulk.c: dcc_calc_rate: Guard against division by zero (which never seems to happen). * Doc. 2003-07-15 17:51 Martin Pool * NEWS: Note compression. 2003-07-15 17:40 Martin Pool * src/: distcc.h, dopt.h, srvnet.c: Clean up dopt headers. 2003-07-15 17:38 Martin Pool * doc/results.txt: Notes on testing compression. 2003-07-15 17:23 Martin Pool * src/distcc.h: Change protocol version to 2 so that incompatibilities with old servers are trapped. Eventually we need to switch intelligently. 2003-07-15 17:12 Martin Pool * src/mon-gnome.c: Make columns in the GNOME monitor resizable, as well as auto-resizing. 2003-07-15 11:32 Martin Pool * src/bulk.c: dcc_r_file: Doc. Fix uninitialized variable for 0-length files. 2003-07-14 22:02 Martin Pool * src/compress.c: Show decompression ratio as small:large. 2003-07-14 21:51 Martin Pool * src/pump.c: dcc_pump_in: Handle 0-byte optimization too. 2003-07-14 21:45 Martin Pool * src/bulk.c: Add optimization of not doing any compression for 0-byte files. 2003-07-14 21:39 Martin Pool * src/pump.c: dcc_pump_out: No longer needed because dcc_x_file now switches based on compression. * Fix parameter ordering bug for dcc_pump_in 2003-07-14 21:38 Martin Pool * src/io.h: compress.h: New header. 2003-07-14 21:38 Martin Pool * src/dopt.c: Fix --wizard. 2003-07-14 21:38 Martin Pool * src/: compress.c, compress.h: dcc_compress_lzo1x_alloc: New function to just compress in memory without doing IO. * compress.h: New header. 2003-07-14 21:36 Martin Pool * src/bulk.c: New dcc_x_file_lzo1x: Read in the file, compress it, and then write out that buffer. This has to be done in a single level because the token has to include the compressed length. * dcc_x_file: Handle compression. 2003-07-14 21:24 Martin Pool * src/dopt.c: Rename to --wizard. 2003-07-14 21:22 Martin Pool * src/dopt.c: Add -X, --maintainer option that adds all settings for running under gdb. 2003-07-14 18:10 Martin Pool * src/: bulk.c, bulk.h, clirpc.c, serve.c: dcc_x_file doesn't need to return the file size anymore. 2003-07-14 18:07 Martin Pool * src/: bulk.c, bulk.h, remote.c, serve.c: Set default compression to LZO1X -- which is not working now, and breaks compatibility * Start factoring out code for receiving a token and file into dcc_r_token_file 2003-07-14 17:55 Martin Pool * src/: bulk.c, bulk.h, clirpc.c, clirpc.h, remote.c, serve.c: Propagate compression setting through all routines. 2003-07-14 17:49 Martin Pool * src/: bulk.c, bulk.h, clirpc.c, compress.c, distcc.h, io.h, pump.c: Start moving bulk data receipt through dcc_pump_in, which does decompression if needed. Remove null dcc_r_file_body. 2003-07-14 17:43 Martin Pool * src/: compress.c, io.h, pump.c: Rename compression functions to lzo_1x, the generic name for the algorithm family we're using. 2003-07-14 17:38 Martin Pool * src/compress.c: Doc 2003-07-14 17:35 Martin Pool * doc/results.txt: [no log message] 2003-07-14 17:35 Martin Pool * man/.cvsignore: Ignore built HTML files. 2003-07-14 16:56 Martin Pool * man/distccd.1: [no log message] 2003-07-14 16:52 Martin Pool * Makefile.in: Don't install README.packaging or SuSE example init script. 2003-07-14 16:49 Martin Pool * Makefile.in: Strip out linuxdoc, because all the information there has been merged into the manpages. 2003-07-14 16:47 Martin Pool * Makefile.in: Add upload-man target to make the manual available on the web page. * There's no need to install README.popt. * Fix targets to build html from troff. 2003-07-14 16:44 Martin Pool * man/: distccd.1, distcc.1: Credit other people. 2003-07-14 16:35 Martin Pool * man/distccd.1: Document DISTCC_SAVE_TEMPS 2003-07-14 16:34 Martin Pool * man/distccd.1: Merge option descriptions and other things. 2003-07-14 16:15 Martin Pool * man/distcc.1: Merge more information. 2003-07-14 15:50 Martin Pool * man/distccd.1: Merge more information. 2003-07-14 15:44 Martin Pool * man/distcc.1: Merge more information. 2003-07-14 15:16 Martin Pool * man/distcc.1: Merge more information. 2003-07-14 14:54 Martin Pool * Makefile.in: Add targets to build HTML from manpages. 2003-07-14 14:47 Martin Pool * man/distccd.1: Start adding more details about the server. 2003-07-14 14:46 Martin Pool * man/distcc.1: Merge stuff about cross-compiling. * More about security. 2003-07-14 14:41 Martin Pool * INSTALL: More about how to install distccd. 2003-07-14 14:33 Martin Pool * man/distcc.1: More manpage documentation. 2003-07-14 13:45 Martin Pool * man/distcc.1: Put a lot more useful information into the manual page. 2003-07-14 12:42 Martin Pool * linuxdoc/distcc.sgml: Information on reporting bugs has been merged into a separate file. 2003-07-14 12:35 Martin Pool * doc/reporting-bugs.txt: Merge more information on reporting problems from the SGML manual. 2003-07-14 12:32 Martin Pool * Makefile.in: Include information on how to report bugs effectively. 2003-07-14 12:31 Martin Pool * doc/reporting-bugs.txt: Information on how to report bugs effectively. 2003-07-14 12:20 Martin Pool * Makefile.in: Include example-init in package. 2003-07-14 12:14 Martin Pool * src/mon.c: Increase allowable age of state files to 300s. 2003-07-14 12:09 Martin Pool * Makefile.in: mon-notify.o is not currently used by the monitors. 2003-07-14 11:53 Martin Pool * bench/compiler.py: Don't put commas in path names because they can cause trouble with some linker command. 2003-07-14 10:51 Martin Pool * src/: mon-gnome.c, mon-notify.c, mon.c: Fix header ordering. 2003-07-14 10:47 Martin Pool * configure.ac: Remove standard GTK test macros because we don't use them. 2003-07-13 18:40 Martin Pool * Makefile.in: Clean up files which were duplicated in dist_files and pkgdoc_DOCS. 2003-07-13 18:09 Martin Pool * patches/.cvsignore: Add built program. 2003-07-13 18:08 Martin Pool * src/: distcc.h, h_argvtostr.c, h_exten.c, h_issource.c, h_scanargs.c, h_strip.c, io.h, mon-text.c, state.c: Clean up header inclusions. 2003-07-13 18:07 Martin Pool * src/arg.c: Doc 2003-07-13 17:57 Martin Pool * TODO: [no log message] 2003-07-13 17:55 Martin Pool * DEPENDENCIES, Makefile.in: Remove DEPENDENCIES file, which is being merged into INSTALL. 2003-07-13 17:30 Martin Pool * INSTALL: Rewrite installation instructions to be specific to distcc and to cover all the main steps. 2003-07-13 12:44 Martin Pool * configure.ac, NEWS: Autodetect the right behaviour for --enable-gnome: If explicitly enabled, insist that the GTK+ libraries be present. If explicitly disabled, don't even look for them. Otherwise, build the GTK+ monitor if possible. 2003-07-12 22:57 Martin Pool * man/distcc.1: Correction for duplicated word by Tobias Stoeckmann. 2003-07-12 17:04 Martin Pool * test/testdistcc.py: Doc. 2003-07-12 16:57 Martin Pool * test/testdistcc.py: Fix up checks for remote assembly listings: we *can* distribute these, unless a filename is specified. 2003-07-12 16:52 Martin Pool * src/arg.c, NEWS: Add checks for -Wa options that produce an assembler listing file. 2003-07-12 11:45 Martin Pool * test/testdistcc.py: Add tests for new -o and -Wa,-al handling. 2003-07-12 01:31 Martin Pool * src/compress.c: Add implementation of LZO decompression. 2003-07-12 01:30 Martin Pool * TODO: [no log message] 2003-07-12 00:58 Martin Pool * src/arg.c: Doc. 2003-07-11 18:21 Martin Pool * bench/Build.py: Make sure full paths are generated for log files. * Add support for programs that use C++. 2003-07-11 18:20 Martin Pool * bench/compiler.py: Make default compiler setups consistent with ones specified by -c * Add support for programs that use C++ 2003-07-11 18:19 Martin Pool * bench/ProjectDefs.py: Add other definitions needed for building firebird. 2003-07-11 18:18 Martin Pool * cases/simple.c: Simple test with no header files. 2003-07-11 17:27 Martin Pool * bench/compiler.py: New/better naming of build directories: now just 'dist,2'. 2003-07-11 17:26 Martin Pool * bench/ProjectDefs.py: Comment out Mozilla, which is having trouble on Debian. * Add MozillaFirebird. 2003-07-11 17:25 Martin Pool * bench/Build.py: Put build logs in the build directory so they're easier to find and use. 2003-07-11 15:19 Martin Pool * bench/ProjectDefs.py: Fix unpacked_subdir for Mozilla 2003-07-11 15:15 Martin Pool * distcc-check: Make sure we do move into the right scratch directory * Remove with -f on completion so that we don't fail if the files were never created. 2003-07-11 15:14 Martin Pool * bench/Project.py: We need wget --continue to get the intended behaviour. 2003-07-11 15:10 Martin Pool * bench/Summary.py: Don't give an error when trying to print a summary table of no compilations. 2003-07-11 15:06 Martin Pool * doc/results.txt: More benchmark stuff. 2003-07-11 14:50 Martin Pool * bench/Summary.py: Fix uname usage. 2003-07-11 14:50 Martin Pool * bench/Project.py: Use wget not snarf, because its progress bar works better with tty and non-tty setups. 2003-07-11 14:47 Martin Pool * bench/benchmark.py: Show -a in help. 2003-07-11 14:47 Martin Pool * bench/ProjectDefs.py: Fix apache 2.0.43 link, which has moved. * Add Mozilla 1.4 (not tested yet) 2003-07-11 14:28 Martin Pool * NEWS: When run as "distcc foo.o -o foo", work out that foo.o is an object file not a compiler name. This can happen with Mozilla. 2003-07-11 14:28 Martin Pool * src/implicit.c: When run as "distcc foo.o -o foo", work out that foo.o is an object file not a compiler name. This can happen with Mozilla. * Many documentation updates to reflect the way that masquerade invocation now works -- a lot of the comments in this file were written before it was added. 2003-07-11 14:20 Martin Pool * src/: filename.h, distcc.h, implicit.c: Move declarations for filename.c into filename.h. 2003-07-11 14:18 Martin Pool * src/filename.h: dcc_is_object: New function. 2003-07-11 14:17 Martin Pool * src/filename.c: dcc_is_object: New function. * filename.c: Doesn't need sys/stat.h. * Doc. 2003-07-11 14:13 Martin Pool * Doxyfile: Don't produce LaTeX 2003-07-11 14:10 Martin Pool * src/filename.c: Doc 2003-07-11 14:09 Martin Pool * patches/.cvsignore: Ignore built programs. 2003-07-11 13:34 Martin Pool * src/: exec.c, exec.h: dcc_execvp() can be static 2003-07-09 18:30 Martin Pool * src/compress.c, TODO: Start a decompressor. 2003-07-09 18:06 Martin Pool * src/compress.c: First cut at implementation of dcc_send_lzo1x1. 2003-07-09 18:05 Martin Pool * src/mapfile.c: Finish implementing dcc_map_input_file. 2003-07-09 17:52 Martin Pool * src/mapfile.c, Makefile.in, src/io.h: Add simple mmap routine for reading input files. 2003-07-09 17:42 Martin Pool * configure.ac: Check for sys/mman.h 2003-07-09 17:39 Martin Pool * src/pump.c: Call dcc_send_lzo1x1 for compressed mode. 2003-07-09 17:38 Martin Pool * src/: hostfile.c, io.h, loadfile.c: Rename dcc_load_file to dcc_load_file_string to be more clear. 2003-07-09 17:17 Martin Pool * patches/trylzo.c: Simple test harness to measure lzo1x1 compression. 2003-07-09 16:49 Martin Pool * src/compress.c: Stub file for doing bulk compression. 2003-07-09 16:28 Martin Pool * Makefile.in, src/bulk.c, src/bulk.h, src/clirpc.c, src/clirpc.h, src/io.c, src/io.h, src/pump.c, src/remote.c, src/serve.c: Refactor bulk-IO code, and start adding support for compression. Nothing is actually compressed yet. 2003-07-09 16:25 Martin Pool * src/timebuild: Remove 'timebuild' script because it's replaced by a better benchmark script. 2003-07-09 15:54 Martin Pool * src/sendfile.c: Handle EINTR from sendfile(). 2003-07-09 15:44 Martin Pool * configure.ac: Remove check for poptGetContext that made us get an unnecessary second -lpopt option. 2003-07-09 15:39 Martin Pool * Makefile.in: Doc 2003-07-09 15:38 Martin Pool * Makefile.in: Start including lzo support: include it on the include path and in the distribution and build minilzo.o. 2003-07-09 15:37 Martin Pool * configure.ac: Bump version. 2003-07-09 14:31 Martin Pool * TODO: Notes on distcc-check and globally visible state. 2003-07-09 14:17 Martin Pool * TODO: Update for current progress. 2003-07-09 13:41 Martin Pool * TODO: 0-length output files are now handled OK. 2003-07-09 13:13 Martin Pool * NEWS: Correction to NEWS: in fact the GNOME monitor is not smart about making updates only when visible. 2003-07-09 13:04 Martin Pool * NEWS: Credit Marcelo Matus. 2003-07-09 12:46 Martin Pool * NEWS: Bump version to 2.8 2003-07-09 12:01 Martin Pool * configure.ac: Bump version to 2.8 2003-07-08 17:02 Martin Pool * doc/results.txt: More results from SSH 2003-07-08 16:58 Martin Pool * src/md.c, Makefile.in: Remove md.c because we can't do anything very useful here. 2003-07-08 16:49 Martin Pool * src/arg.c: Doc. 2003-07-08 16:49 Martin Pool * Makefile.in, src/cpp.h: Remove md.c 2003-07-08 16:45 Martin Pool * Makefile.in: Add security page. 2003-07-08 16:11 Martin Pool * NEWS: [no log message] 2003-07-08 15:59 Martin Pool * src/cpp.c: Doc. 2003-07-08 15:45 Martin Pool * src/: arg.c, arg.h, argutil.c, clirpc.c, compile.c, cpp.c, distcc.c, distcc.h, exec.c, implicit.c, md.c, serve.c, srvrpc.c, ssh.c, strip.c: Move argument-handing prototypes to arg.h 2003-07-08 15:41 Martin Pool * src/arg.h, Makefile.in: arg.h: new file. 2003-07-08 15:17 Martin Pool * src/arg.c: Doc. 2003-07-08 15:11 Martin Pool * src/md.c: Doc 2003-07-08 15:05 Martin Pool * src/cpp.c: dcc_cpp_maybe: Call dcc_fudge_md. 2003-07-08 15:03 Martin Pool * src/: md.c, cpp.h: md.c: new file for dependency generation. 2003-07-08 14:59 Martin Pool * Makefile.in: md.c: new file. 2003-07-08 14:53 Martin Pool * src/strip.c: Doc. 2003-07-08 14:49 Martin Pool * src/cpp.c: Doc. 2003-07-08 14:44 Martin Pool * src/arg.c: Doc. 2003-07-08 14:36 Martin Pool * src/: arg.c, argutil.c: Move functions that are to do with handling argv[] arrays but not really distcc-specific intelligence from arg.c to argutil.c. * Delete dcc_deepcopy_argv which is no longer used. 2003-07-08 14:34 Martin Pool * Makefile.in: argutil.c: New file containing argv[] utilities. * Clean up harness object lists to use $(common_obj) 2003-07-08 14:31 Martin Pool * src/argutil.c: New file containing argv[] utilities. 2003-07-08 14:24 Martin Pool * test/testdistcc.py: Add test for distcc cc -otesttmp.o 2003-07-08 14:01 Martin Pool * NEWS: dcc_set_output: Add support for -ofoo.o. Based on a patch from Tsutomu Yasuda. 2003-07-08 13:57 Martin Pool * src/arg.c: dcc_set_output: Add support for -ofoo.o. Based on a patch from Tsutomu Yasuda. 2003-07-08 13:46 Martin Pool * distcc-check: Simple sanity-check script. 2003-07-08 13:23 Martin Pool * doc/example-init: Example Red Hat init file from Andrew Morton. 2003-07-08 13:20 Martin Pool * NEWS: Example xinetd configuration from akpm. 2003-07-08 13:19 Martin Pool * doc/example.xinetd: Doc 2003-07-08 13:16 Martin Pool * doc/example.xinetd, Makefile.in: Example xinetd configuration from akpm. 2003-07-08 13:06 Martin Pool * src/remote.c: Doc. 2003-07-08 12:42 Martin Pool * src/: clinet.c, io.c, io.h, sendfile.c: dcc_select_for_write, dcc_select_for_read: Both now take a timeout parameter, which is set by default to 15 for opening connections, and 300s for IO during a transfer. This should reduce problems with timeouts during an SSH connection. 2003-07-08 12:39 Martin Pool * NEWS: [no log message] 2003-07-08 12:18 Martin Pool * src/clinet.c: dcc_connect_timed: When connecting, we need to select() until the new socket is writeable, not readable. This bug was previously masked by the inverted call in dcc_select_for_read(). 2003-07-08 12:14 Martin Pool * src/remote.c: dcc_remote_connect: Factor out code to open a connection from dcc_compile_remote. 2003-07-07 23:57 Martin Pool * NEWS: dcc_run_job: Use separate input and output file descriptors, to support sshds that use pipes to run programs rather than local sockets. Suggestion from Felix Lee. 2003-07-07 23:53 Martin Pool * src/io.c: Handle EINTR from read and write. 2003-07-07 23:44 Martin Pool * src/io.c: dcc_select_for_write: Handle EINTR. * Doc. 2003-07-07 23:37 Martin Pool * src/io.c, NEWS: dcc_select_for_read: Fix silly parameter ordering mistake. 2003-07-07 23:31 Martin Pool * src/io.c: dcc_select_for_read: Fix warning. 2003-07-07 23:27 Martin Pool * src/io.c: dcc_select_for_read: Better trace messages. 2003-07-07 23:17 Martin Pool * src/: daemon.c, daemon.h, dparent.c, prefork.c, serve.c: dcc_run_job: Use separate input and output file descriptors, to support sshds that use pipes to run programs rather than local sockets. Suggestion from Felix Lee. 2003-07-07 23:15 Martin Pool * configure.ac: Don't give a warning about linuxdoc, because we do it during installation. 2003-07-07 23:03 Martin Pool * src/: serve.c: Doc. 2003-07-07 22:57 Martin Pool * NEWS: If Linuxdoc was not detected, just give a small warning and not an error while installing. 2003-07-07 22:25 Martin Pool * Makefile.in: If Linuxdoc was not detected, just give a small warning and not an error while installing. 2003-07-07 18:35 Martin Pool * doc/protocol-1.txt: Document the changes to support 0-byte output. 2003-07-07 18:34 Martin Pool * TODO: [no log message] 2003-07-07 18:33 Martin Pool * test/badcc: Add mode to generate empty output. 2003-07-07 18:08 Martin Pool * src/clirpc.c: Retrieval of the output file is now determined by the remote compiler status, not the DOTO length. This allows us to correctly get back a 0-length output file from a successful compile. 2003-07-07 18:03 Martin Pool * src/remote.c: Doc. 2003-07-07 17:59 Martin Pool * src/serve.c: Doc. 2003-07-07 17:48 Martin Pool * src/: bulk.h, bulk.c: Be more careful about treating token parameters as unsigned. 2003-07-07 17:28 Martin Pool * configure.ac, NEWS: Better test for vararg macro support that correctly identifies apple gcc brokenness. From Matt Watson . 2003-07-07 16:44 Martin Pool * NEWS: distccmon-text: Output should always be line-buffered, even if not writing to a terminal. 2003-07-07 15:27 Martin Pool * src/mon-text.c: distccmon-text: Output should always be line-buffered, even if not writing to a terminal. 2003-07-07 15:23 Martin Pool * src/mon-gnome.c: Doc. 2003-07-07 13:50 Martin Pool * src/state.c: dcc_note_state: Quote strings in trace message. 2003-07-07 12:55 Martin Pool * src/mon.h, NEWS: Protect against repeated inclusion. Suggestion from Fr'ed'eric Forjan. 2003-07-07 12:53 Martin Pool * src/mon.h: mon.h now uses "extern C" so that it can be included from C++ programs. Suggestion from Fr'ed'eric Forjan. 2003-06-25 17:50 Martin Pool * src/mon-gnome.c: Doc. 2003-06-25 17:48 Martin Pool * src/mon-gnome.c: Always update load, even if not onscreen, so that we don't show a dummy message at startup. 2003-06-25 17:46 Martin Pool * src/mon-gnome.c: Increase niceness at startup. 2003-06-25 17:43 Martin Pool * src/mon-gnome.c, NEWS: distccmon-gnome: Prevent selection of rows in the treeview. Emphasize horizontal rows ("rules-hint"). 2003-06-25 17:28 Martin Pool * NEWS: distccmon-gnome: Check whether the window is iconified or withdrawn, and if so then don't update. This slightly reduces the load in those cases. 2003-06-25 17:12 Martin Pool * src/mon-gnome.c: Expose a reference to the GtkTreeView widget and use that in the update callback. * Check whether the window is iconified or withdrawn, and if so then don't update. This slightly reduces the load in those cases. 2003-06-25 11:31 Martin Pool * NEWS: Prepare for 2.7.1 2003-06-25 11:28 Martin Pool * patches/state-in-home.diff: Store rolled-back ~/.distcc/state patch. 2003-06-25 11:27 Martin Pool * Makefile.in: Fix EXEEXT on gnome binaries. 2003-06-25 11:26 Martin Pool * configure.ac: Prepare for 2.7.1 * Fix EXEEXT on gnome binaries. 2003-06-25 10:59 Martin Pool * src/state.c, NEWS: Roll back: put the state in the temporary directory, because storing it in home does not seem to fix ebuild. 2003-06-24 13:40 Martin Pool * patches/hosts-from-file-raabe.diff: hosts-from-file-raabe.diff Has been merged 2003-06-21 14:21 Martin Pool * DEPENDENCIES: Note that libgnome is no longer required. 2003-06-21 13:45 Martin Pool * TODO: Updates based on work done recently. 2003-06-21 13:42 Martin Pool * NEWS, src/state.c: State files now in ~/.distcc/state 2003-06-21 13:13 Martin Pool * src/arg.c: Fix constness. 2003-06-20 17:32 Martin Pool * src/mon-gnome.c: Doc. 2003-06-20 17:29 Martin Pool * configure.ac: Add autoconf test for GTK+-2.0 (but don't call it yet.) * Change --enable-gnome to just check for GTK+. 2003-06-20 17:25 Martin Pool * src/mon-gnome.c: stdint.h is not needed. 2003-06-20 17:23 Martin Pool * Makefile.in, NEWS: distccmon-gnome now depends only on gtk+-2.0 2003-06-20 17:18 Martin Pool * src/mon-gnome.c: Follow the advice in the GTK+ 2.2 API: * Don't call gtk_widget_set_usize and gtk_window_set_policy, but instead just gtk_window_set_default_size. This gives us the same default size and allows the user to shrink the window, but doesn't let them shrink it right down to zero. 2003-06-20 17:15 Martin Pool * src/mon-gnome.c: Add some other necessary headers. 2003-06-20 17:14 Martin Pool * src/mon-gnome.c: Update to use just the GTK+ 2.0 API, and nothing from libgnomeui. 2003-06-16 18:40 Martin Pool * Makefile.in: Remove stupid autom4te.cache from distclean 2003-06-16 18:36 Martin Pool * src/arg.c: Remove TODO about -MD because the information is in TODO and I think I know how to fix it now. 2003-06-16 18:33 Martin Pool * src/cpp.c: Doc 2003-06-16 18:30 Martin Pool * configure.ac: Bump version 2003-06-16 17:51 Martin Pool * configure.ac, NEWS: Release 2.7. 2003-06-16 17:50 Martin Pool * src/arg.c: Doc 2003-06-16 17:39 Martin Pool * TODO: [no log message] 2003-06-16 17:06 Martin Pool * TODO: Notes on dnotify. 2003-06-16 16:59 Martin Pool * NEWS: [no log message] 2003-06-16 16:50 Martin Pool * Makefile.in: Need to link LIBS in to get functions like inet_ntoa on Solaris, etc. 2003-06-16 16:31 Martin Pool * src/mon-gnome.c: Make the tree sortable. 2003-06-16 14:39 Martin Pool * src/mon-gnome.c: Doc. 2003-06-16 14:38 Martin Pool * src/mon-gnome.c: Put commas in load average line. 2003-06-16 14:37 Martin Pool * src/mon-gnome.c: Load bar now actually shows the system load as we go. * Load bar is initialized at startup. 2003-06-16 14:31 Martin Pool * src/mon-gnome.c: Add a callback to update the load indicator. 2003-06-16 14:26 Martin Pool * src/mon-gnome.c: Fix up load indicator. 2003-06-16 14:17 Martin Pool * src/mon-gnome.c: Start adding a load indicator at the bottom of the window. 2003-06-16 13:48 Martin Pool * src/mon-notify.c, Makefile.in, src/mon.c: mon-notify.c: New file to keep the dnotify stuff out of mon.c 2003-06-16 13:41 Martin Pool * src/mon-gnome.c: Remove dnotify support, because the signals seem to cause trouble with GNOME, and too-frequent updates are bad for our CPU usage. 2003-06-16 13:15 Martin Pool * src/tempfile.c: Doc 2003-06-16 13:07 Martin Pool * NEWS: Check for sys/select.h, which is not present on HP-UX. 2003-06-16 13:03 Martin Pool * configure.ac, src/io.c: Check for sys/select.h, which is not present on HP-UX. 2003-06-16 12:48 Martin Pool * src/mon-gnome.c: Doc. 2003-06-16 12:43 Martin Pool * src/mon.c: Doc. 2003-06-16 12:33 Martin Pool * src/: clirpc.c, clirpc.h, compile.c, exec.c, exec.h, mon.c, rpc.c, rpc.h, serve.c, srvrpc.c: Store all token parameter values, including lengths and waitstatuses to unsigned throughout the program. Fixes some warnings on Sun and probably a bit safer. 2003-06-16 12:25 Martin Pool * src/arg.c: dcc_note_compiled: Fix constness. 2003-06-16 12:25 Martin Pool * src/util.c: snprintf.h is needed. 2003-06-16 12:24 Martin Pool * src/distcc.h: Change dcc_trace_argv macro to try to quieten warnings on Sun. 2003-06-16 12:21 Martin Pool * src/trace.h: Add RS_STMT_START macros from glib, to quieten warnings on Sun. 2003-06-16 12:19 Martin Pool * src/hosts.c: snprintf.h is needed. 2003-06-16 12:17 Martin Pool * src/: mon-gnome.c, mon.c, mon.h: Rename dcc_gnome_setup_dnotify to dcc_gnome_setup_notify to be less Linux-specific. * Add documentation on the mon interface to help people writing new monitors. 2003-06-16 12:08 Martin Pool * src/tempfile.c: Doc 2003-06-16 12:05 Martin Pool * configure.ac: Fix configure messages. 2003-06-16 12:04 Martin Pool * configure.ac: Only check for libgnomeui-2.0 if --enable-gnome was specified. 2003-06-16 11:27 Martin Pool * doc/results.txt: Notes on performance of monitor with dnotify. 2003-06-14 20:09 Martin Pool * TODO: IPv6 is now done. 2003-06-14 20:08 Martin Pool * TODO: Notes on nicely handling gcc -MD. 2003-06-13 17:30 Martin Pool * src/clinet.c: Doc. 2003-06-13 14:57 Martin Pool * src/mon-gnome.c: Change default size * Print out a star when we reread the directory. 2003-06-13 14:39 Martin Pool * src/mon-gnome.c: Even if we can use dnotify, still poll every 10s to clean up dead files. 2003-06-13 14:33 Martin Pool * src/mon.c: Also listen for deletion notifications to make sure that we notice when the last compiler quits. 2003-06-13 14:31 Martin Pool * src/mon-gnome.c: Attach to dnotify prompts from mon.c and drain them as they arrive. 2003-06-13 14:28 Martin Pool * src/mon.c: dcc_mon_setup_dnotify: Check that the fcntl to set F_NOTIFY suceeded -- this can fail on linux systems that don't have dnotify in the kernel. 2003-06-13 12:55 Martin Pool * NEWS: Fix spelling mistake. 2003-06-13 12:18 Martin Pool * src/mon.c: Dnotify stuff now actually writes to the dummy pipe when the state changes. 2003-06-13 12:14 Martin Pool * src/: mon.c, state.c: Doc. 2003-06-12 22:02 Martin Pool * src/mon.c: Doc 2003-06-12 21:58 Martin Pool * src/mon.c: Fix up half-committed code. 2003-06-12 21:55 Martin Pool * configure.ac, src/mon-gnome.c: Fix up half-committed code. 2003-06-12 18:13 Martin Pool * TODO, src/mon-gnome.c, src/mon.c, src/mon.h: Start adding dnotify support for monitor rather than polling. 2003-06-12 18:02 Martin Pool * Makefile.in: Fix distccmon-gnome 2003-06-12 18:00 Martin Pool * Makefile.in: Make sure to use the right cpp flags when building distccmon-gnome 2003-06-12 17:56 Martin Pool * Makefile.in: distccmon-gnome needs nonblocking routines from netutil.o 2003-06-12 17:50 Martin Pool * src/mon-gnome.c: Refactor 2003-06-12 17:37 Martin Pool * src/mon-gnome.c: Doc. 2003-06-12 17:27 Martin Pool * src/mon-gnome.c: GTK 2.0 manual says that gtk_timeout_add is deprecated in favour of g_timeout_add. 2003-06-12 17:26 Martin Pool * src/mon-gnome.c: Show USER@HOST in monitor title bar, because it's possible people will run this remotely. 2003-06-12 16:57 Martin Pool * NEWS: If --enable-gnome was specified, then check that libgnomeui is actually present. 2003-06-12 16:52 Martin Pool * configure.ac: Bump version * If --enable-gnome was specified, then check that libgnomeui is actually present. 2003-06-12 16:38 Martin Pool * src/mon-gnome.c: Doc 2003-06-12 16:27 Martin Pool * DEPENDENCIES: Describe dependencies for GNOME. 2003-06-12 16:25 Martin Pool * src/mon-gnome.c: The GTK tree model is now updated on each new monitor state. It seems to be working correctly. 2003-06-12 16:09 Martin Pool * src/mon-gnome.c: Reindent only. 2003-06-12 16:06 Martin Pool * src/mon-gnome.c: Add a callback every 0.5s. At the moment it does nothing. 2003-06-12 15:56 Martin Pool * TODO: More small updates. 2003-06-12 15:51 Martin Pool * TODO: Remove many done TODO items, and add notes on some continuing ones. 2003-06-12 15:40 Martin Pool * src/clirpc.c: Doc 2003-06-12 13:47 Martin Pool * src/compile.c: dcc_build_somewhere: input_fname must be initialized to NULL so that in the case of a very early fallback to local compilation we don't read an invalid pointer and crash. 2003-06-12 13:44 Martin Pool * src/: clirpc.c, remote.c, state.c: Remove infrequently-hit states. 2003-06-12 13:42 Martin Pool * src/compile.c: Remove "Startup" state because it's very unlikely to be hit. 2003-06-12 12:53 Martin Pool * configure.ac: Prepare for 2.6 release. 2003-06-12 12:41 Martin Pool * src/prefork.c: dcc_preforking_parent: Put in another 1s sleep between collecting dead children and starting new ones. 2003-06-12 12:35 Martin Pool * NEWS: Reorder sections. Patch from Sean MacLennan: * dcc_ncpus for Linux: make sure that we don't return 0 cpus. 2003-06-12 12:34 Martin Pool * src/ncpus.c: Patch from Sean MacLennan: * dcc_ncpus for Linux: make sure that we don't return 0 cpus. 2003-06-12 12:14 Martin Pool * NEWS: Get ready for 2.66 release. 2003-06-12 12:04 Martin Pool * Makefile.in: Include doc/status-1.txt in distribution. 2003-06-12 12:00 Martin Pool * doc/status-1.txt: Update to describe the implemented monitor design. 2003-06-12 09:53 Martin Pool * NEWS: Reorder items 2003-06-12 09:30 Martin Pool * NEWS: Note changed tmpdir name. 2003-06-12 00:34 Martin Pool * src/mon.c: Skip state files for which the process no longer exists. 2003-06-12 00:29 Martin Pool * src/state.c: Call the blocked state "starved". 2003-06-12 00:28 Martin Pool * src/state.c: Call the blocked state "bored" 2003-06-12 00:26 Martin Pool * src/mon.c: Doc. 2003-06-12 00:17 Martin Pool * src/clirpc.c: Doc. 2003-06-12 00:15 Martin Pool * src/clirpc.c: Add more states: distinguish more states: waiting for preprocessor, sending source, and receiving object. 2003-06-12 00:12 Martin Pool * src/: state.h, state.c: Add more states. 2003-06-12 00:09 Martin Pool * src/mon-text.c: Clip columns to appropriate widths. 2003-06-12 00:04 Martin Pool * src/: compile.c: Note input filename as soon as it has been determined. 2003-06-12 00:03 Martin Pool * src/: compile.c, compile.h, remote.c, where.c, where.h: Roll back the rest of the xmit lock code. * Rely on state code to keep track of what source file we're compiling. 2003-06-11 22:41 Martin Pool * src/: compile.c, state.c, state.h: Show another state during startup. 2003-06-11 22:38 Martin Pool * src/state.c: Doc 2003-06-11 22:37 Martin Pool * src/clirpc.c: dcc_retrieve_results: Try to keep the right file name when updating state. 2003-06-11 22:36 Martin Pool * TODO: Thoughts on -MD support. 2003-06-11 22:36 Martin Pool * NEWS: [no log message] 2003-06-11 22:34 Martin Pool * src/remote.c: Doc 2003-06-11 22:31 Martin Pool * src/remote.c: dcc_compile_remote: Try to keep the right file name when updating state. 2003-06-11 22:30 Martin Pool * src/where.c: dcc_lock_pause: Set state notification when blocked. 2003-06-11 22:29 Martin Pool * src/: state.c, state.h: dcc_note_state: constness 2003-06-11 22:29 Martin Pool * src/: filename.h, filename.c: dcc_find_basename: constness 2003-06-11 22:26 Martin Pool * src/state.c: dcc_note_state: Remember the previously-set filename and host, so that we can just change state without needing to always know the filename. 2003-06-11 22:22 Martin Pool * src/: state.c, state.h: Add STATE_BLOCKED. 2003-06-11 22:21 Martin Pool * src/state.h: Delete garbage comment. 2003-06-11 17:22 Martin Pool * src/mon.c: Doc. 2003-06-11 17:20 Martin Pool * Makefile.in: Remove done todo 2003-06-11 17:19 Martin Pool * doc/results.txt: Measurements with state notes turned on. 2003-06-11 17:18 Martin Pool * src/: compile.c, compile.h, remote.c: dcc_compile_remote: Input filename is passed in for use in state notes. 2003-06-11 17:17 Martin Pool * src/remote.c: dcc_compile_remote: xmit_lock_fd is unused for now. 2003-06-11 17:14 Martin Pool * src/remote.c: Doc. 2003-06-11 17:07 Martin Pool * src/mon-text.c: Doc. 2003-06-11 17:02 Martin Pool * NEWS: [no log message] 2003-06-11 16:59 Martin Pool * src/mon-text.c: Take one optional parameter, which sets a time to wait between refreshes. Currently done using usleep(), which may not be portable. 2003-06-11 16:58 Martin Pool * src/mon.c: dcc_mon_poll: Fix memory scribble. 2003-06-11 16:53 Martin Pool * src/state.c: Doc. 2003-06-11 16:46 Martin Pool * NEWS: [no log message] 2003-06-11 16:29 Martin Pool * src/state.c: Only unlink file before replacing on cygwin. 2003-06-11 16:24 Martin Pool * src/state.c: Write state out into temporary files and rename into place, to try to avoid monitors ever seeing half-full files. 2003-06-11 15:19 Martin Pool * src/mon.c: Reduce max age to 30s. 2003-06-11 15:06 Martin Pool * src/tempfile.c: Include hostname in tempdir name, to avoid problems when /tmp is shared. 2003-06-11 15:03 Martin Pool * NEWS: Note distccmon-text. 2003-06-11 15:00 Martin Pool * src/tempfile.c: dcc_make_tmpnam: Just use asprintf() now we have it, rather than doing the equivalent by hand. Use the plain pid in temporary filenames rather than zero-filling it. 2003-06-11 14:55 Martin Pool * src/mon-text.c: Dump out the monitor list in a simple text table form. 2003-06-11 14:50 Martin Pool * src/mon.c: Doc * dcc_mon_kill_old: Always close fd on failure. * Build up a list of dcc_mon_list structures as the files are read in. * dcc_mon_list_free: Walk down the list, freeing each link. 2003-06-11 14:24 Martin Pool * src/mon.c: Read host and file variabels from state. 2003-06-11 14:22 Martin Pool * src/mon.c: Put in constant for the time to allow statefiles to live, and reduce to 60s. * Read state string. 2003-06-11 14:19 Martin Pool * src/mon.c: Check for and kill old state files. * Read in the start of the state file. 2003-06-11 14:15 Martin Pool * src/: rpc.c, rpc.h, srvrpc.c: dcc_r_token_string: New function factored out. 2003-06-11 14:06 Martin Pool * src/exitcode.h: Add EXIT_GONE 2003-06-11 12:41 Martin Pool * src/mon-text.c: distccmon-gnome: Emit blank at end. 2003-06-11 12:41 Martin Pool * src/mon.c: dcc_mon_do_file: Open each state file and handle missing ones. * dcc_mon_poll: Fix reference to freed memory. 2003-06-11 12:35 Martin Pool * src/: state.c, state.h: dcc_state_prefix: Export identifying prefix for state files. 2003-06-11 12:35 Martin Pool * src/mon.c: dcc_mon_do_file: New function. Skip everything but state files. 2003-06-11 12:31 Martin Pool * src/mon.c: dcc_mon_poll: Partial implementation that just traverses the directory. 2003-06-11 12:30 Martin Pool * src/mon-text.c: Set trace level from environment. 2003-06-11 12:30 Martin Pool * src/distcc.c, src/distcc.h, src/traceenv.c, Makefile.in: dcc_set_trace_from_env: Split out into new file src/traceenv.c, so that this can also be used from monitor programs. 2003-06-11 12:29 Martin Pool * .cvsignore: Ignore distccmon-text binary. 2003-06-11 12:24 Martin Pool * src/trace.c: Default trace should get all messages allowed by log level. 2003-06-11 12:22 Martin Pool * Makefile.in: Build and install distccmon-text 2003-06-11 12:19 Martin Pool * src/trace.c: Typo 2003-06-11 12:18 Martin Pool * src/trace.c: If no logger has been initialized when the first message goes out, then write to stderr. 2003-06-11 12:13 Martin Pool * src/mon.h: Declare part of the monitor API 2003-06-11 12:13 Martin Pool * src/mon-text.c: Hook in to trace code. 2003-06-11 12:11 Martin Pool * Makefile.in: More routines are needed for monitors 2003-06-11 12:06 Martin Pool * src/mon-text.c: Hook in to trace code. * Doc. 2003-06-11 12:04 Martin Pool * src/: exec.c, util.c: dcc_remove_if_exists: Move to util.c 2003-06-11 12:04 Martin Pool * Makefile.in: Add mon_obj variable for building monitor programs. 2003-06-11 11:58 Martin Pool * src/mon-text.c: src/mon-text.c: New file. 2003-06-11 11:57 Martin Pool * Makefile.in: Include src/mon-gnome.c in distribution * src/mon-text.c: New file. 2003-06-11 11:51 Martin Pool * src/state.c: dcc_note_state: Put client pid in state. 2003-06-11 11:50 Martin Pool * Makefile.in, src/mon.c, src/mon.h: src/mon.c, src/mon.h: New files. 2003-06-11 11:48 Martin Pool * src/: clirpc.c, remote.c: Add more calls to publish state. 2003-06-11 11:43 Martin Pool * src/state.c: dcc_note_state: Handle null file or host names. 2003-06-11 11:39 Martin Pool * src/: distcc.c, state.c, state.h: Call dcc_remove_state_file from atexit in client. 2003-06-11 11:37 Martin Pool * src/state.c: dcc_remove_state_file: Implement. 2003-06-11 11:35 Martin Pool * src/state.c: dcc_open_state_file: Release memory after use. 2003-06-11 11:32 Martin Pool * src/: rpc.c, rpc.h: dcc_x_token_string: Make buffer const. 2003-06-11 11:31 Martin Pool * src/state.c: dcc_note_state: Include file and host too. 2003-06-11 11:28 Martin Pool * src/state.c: dcc_note_state: Include state string as well. 2003-06-11 11:26 Martin Pool * src/clirpc.c: dcc_x_argv: Call dcc_x_token_string rather than doing it inline. 2003-06-11 11:22 Martin Pool * src/: rpc.h, rpc.c: dcc_x_token_string: New function factored out. 2003-06-11 11:06 Martin Pool * Makefile.in: Subst in LINUXDOC. 2003-06-11 11:02 Martin Pool * configure.ac: AC_ARG_VAR LINUXDOC 2003-06-11 11:00 Martin Pool * configure.ac: Add a check for existence of linuxdoc. 2003-06-11 10:47 Martin Pool * src/snprintf.h: snprintf.h needs to include stdarg.h to get va_list. Possibly fixes IRIX. 2003-06-10 18:23 Martin Pool * NEWS: Patch from Paul Russell: * If the compiler is not found on the server and is a fully-qualified name, then strip off the full name and just look for it on the path. 2003-06-10 18:16 Martin Pool * src/exec.c: Doc. 2003-06-10 18:15 Martin Pool * src/exec.c: Patch from Paul Russell: * If the compiler is not found on the server and is a fully-qualified name, then strip off the full name and just look for it on the path. 2003-06-10 18:00 Martin Pool * doc/release-names.txt: [no log message] 2003-06-10 18:00 Martin Pool * NEWS: Note new state files. 2003-06-10 17:57 Martin Pool * src/stat.c, src/stat.h, src/state.c, src/state.h, Makefile.in, src/compile.c: Rename stat.* to state.* 2003-06-10 17:57 Martin Pool * src/stat.h: dcc_remove_state_file: New function. 2003-06-10 17:56 Martin Pool * src/stat.c: dcc_get_state_file: New function to return the name of the state file for this process. * dcc_note_state: Start writing into state file. 2003-06-10 17:43 Martin Pool * src/compile.c: Update state directory when compiling locally. 2003-06-10 17:42 Martin Pool * src/arg.c: Factor out "compile from %s to %s" message into its own function, and log only the basename. Should prevent page-widening in server logs. 2003-06-10 17:41 Martin Pool * src/: stat.c, stat.h: dcc_note_state only logs the basename of the file. 2003-06-10 17:39 Martin Pool * src/stat.c: dcc_note_state: Trim filename down to basename. 2003-06-10 17:37 Martin Pool * NEWS: Try to fix UTF-8 coding, which seemed to be mangled by CVS. 2003-06-10 17:31 Martin Pool * NEWS: In compilation log message, just show the basename of the file to make it more compact. 2003-06-10 17:23 Martin Pool * src/: stat.h, stat.c: Add compile state constants. 2003-06-10 17:16 Martin Pool * src/: filename.h, filename.c: dcc_find_basename: New function. 2003-06-10 16:57 Martin Pool * src/compile.c: Remove unneeded header. 2003-06-10 16:55 Martin Pool * src/: stat.c, stat.h: dcc_note_state: New function to record what the client's up to. 2003-06-10 16:54 Martin Pool * src/: bulk.c, distcc.h: Move O_BINARY ifdef to distcc.h 2003-06-10 15:56 Martin Pool * Makefile.in: New file stat.h 2003-06-10 15:55 Martin Pool * src/: stat.c, stat.h: New file stat.h * Add routine to open a state file. 2003-06-10 15:55 Martin Pool * .cvsignore: Ignore distccmon-gnome. 2003-06-10 15:49 Martin Pool * src/stat.c: Doc * Add function to create/return state directory. 2003-06-10 15:47 Martin Pool * src/tempfile.h: Split code for idempotent directory creation out into a new function dcc_make_dir, so that it can be used by state file code. 2003-06-10 15:33 Martin Pool * src/tempfile.c: Split code for idempotent directory creation out into a new function dcc_make_dir, so that it can be used by state file code. 2003-06-10 15:23 Martin Pool * src/mon-gnome.c: Add columns for file and host * Add more sample data * Refactor code to create table view. 2003-06-10 15:14 Martin Pool * src/mon-gnome.c: Set a more reasonable default size. 2003-06-10 15:09 Martin Pool * src/mon-gnome.c: Refactor into smaller functions * Remove horizontal scrollbar; vertical only as needed. * Remove dummy text entry 2003-06-10 15:00 Martin Pool * NEWS: Start adding a GNOME-based monitor. 2003-06-10 14:58 Martin Pool * Makefile.in: make clean: Remove distccmon-gnome, even if it's currently not configured on. 2003-06-10 14:57 Martin Pool * Makefile.in, configure.ac: Add --enable-gnome configure option. When set, build and install distccmon-gnome. 2003-06-09 23:09 Martin Pool * src/mon-gnome.c: Add more sample data. 2003-06-09 23:07 Martin Pool * Makefile.in: Add hardcoded rule for distccmon-gnome. 2003-06-09 23:05 Martin Pool * doc/status-1.txt: Update status indicator notes. 2003-06-09 23:03 Martin Pool * src/stat.c: Stub for status indicator. 2003-06-09 19:23 Martin Pool * src/mon-gnome.c: Start of a monitor implementation in GTK+-2.2. Displays a window with a list containing only "42". 2003-06-09 18:37 Martin Pool * src/: mon-gnome.c, mon-gtk.c: Stub implementation of GNOME monitor. 2003-06-09 18:35 Martin Pool * src/: netutil.c, netutil.h: Add implementation of hstrerror() for systems that don't have it. 2003-06-09 18:28 Martin Pool * Makefile.in: src/stat.c: New file. 2003-06-09 15:23 Martin Pool * src/mon-gtk.c: Add a stub GTK+ monitor interface -- compiles and shows an empty window but does nothing. 2003-06-09 14:26 Martin Pool * NEWS: Note that hstrerror() is now supplied. 2003-06-09 12:47 Martin Pool * src/remote.c: Remove more unneeded headers. 2003-06-09 12:43 Martin Pool * src/: distcc.c, compile.c: Remove more unneeded headers. 2003-06-09 12:36 Martin Pool * src/distcc.c: Remove more unneeded headers. 2003-06-09 12:33 Martin Pool * src/distcc.c: Remove unneeded headers. 2003-06-08 20:05 Martin Pool * test/testdistcc.py, NEWS: Fix silly typo that made maintainer-check fail in ParseHostSpec_Case. 2003-06-08 19:52 Martin Pool * Makefile.in, src/compile.c, src/compile.h, src/distcc.c: Split other client-side compile functionality into src/compile.c. src/distcc.c now only has the top-level client code. * src/compile.c: New file. 2003-06-08 19:43 Martin Pool * Makefile.in, src/compile.h, src/distcc.c, src/remote.c: Split dcc_compile_remote into src/remote.c, and make it public. * compile.h, remote.c: New files. 2003-06-08 19:36 Martin Pool * TODO: Multiple updates to TODO file. 2003-06-08 19:19 Martin Pool * src/distcc.c, NEWS: Look for UNCACHED_ERR_FD environment variable, to allow distcc networking errors to avoid being cached by ccache. 2003-06-06 13:07 Martin Pool * TODO: OpenMOSIX autodiscovery 2003-06-05 17:44 Martin Pool * TODO: Rearrange comments on DNS A and SRV records. * Move question about --enable-final to web. 2003-06-05 17:34 Martin Pool * TODO: 2.5 bug is fixed. 2003-06-05 17:26 Martin Pool * Makefile.in: Include doc/protocol-1.txt in distribution. 2003-06-05 17:21 Martin Pool * configure.ac: Bump version back to 2.6cvs 2003-06-05 17:03 Martin Pool * NEWS: Note connection timeout added in 2.5.1. 2003-06-05 16:53 Martin Pool * NEWS, configure.ac: Prepare for 2.5.1 release. 2003-06-05 16:48 Martin Pool * src/io.c, NEWS: sys/time.h might be needed for select on SuSE 7.1 (spe158). 2003-06-05 16:45 Martin Pool * src/hosts.c, NEWS: dcc_parse_multiplier must advance over the multiplier to be able to read things like "angry/30:3000" correctly. Patch from Wayne Davison. 2003-06-05 16:43 Martin Pool * linuxdoc/distcc.sgml: Get out these fixes in 2.5.1. 2003-06-05 16:42 Martin Pool * test/testdistcc.py, NEWS: Add check for support of old multiplier format. (angry/44:300) 2003-06-05 16:41 Martin Pool * test/testdistcc.py: Doc 2003-06-05 16:39 Martin Pool * configure.ac: Get out these fixes in 2.5.1. 2003-06-05 16:36 Martin Pool * NEWS: Get out these fixes in 2.5.1. 2003-06-05 16:17 Martin Pool * src/: clinet.c, netutil.c, netutil.h, srvnet.c: Rename everything called 'sa_len' because this is #defined on IRIX. (Yuk) 2003-06-05 16:12 Martin Pool * NEWS: Fix IRIX. 2003-06-05 16:09 Martin Pool * NEWS: Recode as UTF-8. 2003-06-05 16:08 Martin Pool * NEWS: Solaris fixes from Tomas. 2003-06-05 16:08 Martin Pool * src/daemon.h: dcc_master_pid is really a pid_t. 2003-06-05 16:07 Martin Pool * src/netutil.c: Can't use "sun" as an identifier on gcc Solaris 8. 2003-06-05 16:03 Martin Pool * doc/release-names.txt: [no log message] 2003-06-04 23:19 Martin Pool * src/dparent.c: Doc. 2003-06-04 11:22 Martin Pool * doc/status-1.txt: Notes on design possibilities. 2003-06-03 08:37 Martin Pool * doc/noent.txt: Transient bug while compiling. 2003-06-03 08:23 Martin Pool * doc/status-1.txt: Notes on status reporting 2003-06-02 15:48 Martin Pool * src/netutil.c: This file needs snprintf.h * AF_LOCAL might be missing on Solaris. 2003-06-02 15:45 Martin Pool * TODO: [no log message] 2003-06-02 14:46 Martin Pool * doc/release-names.txt: [no log message] 2003-06-02 13:20 Martin Pool * src/dparent.c: Clarify "%d CPUs online" message. http://groups.google.com/groups?q=distcc&hl=en&lr=&ie=UTF-8&oe=UTF-8&scoring=d&selm=1054494726.347698%40auth2.dns.griffin.net.uk&rnum=1 2003-06-02 13:13 Martin Pool * survey.txt: Clarify privacy clause for survey. 2003-06-02 13:11 Martin Pool * NEWS: [no log message] 2003-05-31 00:29 Martin Pool * doc/protocol-1.txt: Start handling empty output files. 2003-05-31 00:29 Martin Pool * TODO: [no log message] 2003-05-30 23:49 Martin Pool * src/: bulk.c, distcc.h: dcc_open_read can be static. 2003-05-30 23:47 Martin Pool * src/bulk.c: Remove dead code. 2003-05-30 12:58 Martin Pool * linuxdoc/distcc.sgml: Add section about Mailing lists. 2003-05-30 12:45 Martin Pool * src/dsignal.c: Doc. 2003-05-29 09:00 Martin Pool * src/access.c: Doc 2003-05-28 17:34 Martin Pool * src/: clinet.c, io.c: Increase timeout to 15s. * Move select() check into dcc_select_for_read 2003-05-28 17:28 Martin Pool * src/clinet.c: dcc_connect_timed: Add trace. 2003-05-28 17:16 Martin Pool * src/clinet.c: Doc 2003-05-28 17:13 Martin Pool * TODO, doc/results.txt: [no log message] 2003-05-28 17:01 Martin Pool * src/clinet.c: Impose 5s timeout on opening TCP connections. Change to using nonblocking sockets (just while opening). 2003-05-28 16:16 Martin Pool * Makefile.in: Move check functionality to maintainer-check, because I don't want it to run by default on the build farm. 2003-05-28 16:13 Martin Pool * NEWS: [no log message] 2003-05-28 16:11 Martin Pool * src/distcc.c: Include hostdef string in "failed to distribute" warning. 2003-05-28 16:03 Martin Pool * src/: netutil.h, ssh.c, netutil.c: dcc_set_nonblocking, dcc_set_blocking: Move to netutil.h 2003-05-28 15:57 Martin Pool * TODO: The server in fact already generates the right extension name for temporary files. But this might be a problem for the proposed new protocol. 2003-05-28 15:50 Martin Pool * src/serve.c: dcc_run_job: Split some code out into dcc_input_tmpnam. 2003-05-28 15:50 Martin Pool * doc/results.txt: [no log message] 2003-05-28 15:46 Martin Pool * TODO: Preforking is now done. 2003-05-28 15:45 Martin Pool * TODO: Thoughts on boredom and temporary file extensions. 2003-05-28 15:29 Martin Pool * linuxdoc/distcc.sgml, NEWS: Document use from inetd. * Document -j option. 2003-05-28 15:08 Martin Pool * linuxdoc/distcc.sgml: Notes on running daemon from init and standalone. 2003-05-28 14:51 Martin Pool * NEWS: dcc_setpgid: Rename to dcc_new_pgrp. * dcc_new_pgrp: Don't call setpgid() if we're already a process group leader, because this fails with EPERM if we happen to also be a session group leader. 2003-05-28 14:42 Martin Pool * src/: dparent.c, exec.c, exec.h: dcc_setpgid: Rename to dcc_new_pgrp. * dcc_new_pgrp: Don't call setpgid() if we're already a process group leader, because this fails with EPERM if we happen to also be a session group leader. 2003-05-28 14:31 Martin Pool * configure.ac: Bump version 2003-05-28 14:13 Martin Pool * NEWS: Need types.h 2003-05-28 14:03 Martin Pool * src/daemon.c: Need types.h 2003-05-27 19:18 Martin Pool * src/serve.c: Tweak trace message. 2003-05-27 19:17 Martin Pool * src/bulk.c: Disable dcc_x_file_timed, which is no longer called. 2003-05-27 19:12 Martin Pool * configure.ac, NEWS, doc/release-names.txt: Prepare for 2.5 release. 2003-05-27 19:11 Martin Pool * src/daemon.c: Doc. * If getpeername() fails on a socket then continue anyhow. 2003-05-27 19:08 Martin Pool * TODO: SSH child is now collected by the client. 2003-05-27 18:55 Martin Pool * NEWS: [no log message] 2003-05-27 18:54 Martin Pool * src/distcc.c: Only collect SSH child if we actually started one. (How embarrassing.) 2003-05-27 18:48 Martin Pool * src/distcc.c: Log elapsed time for whole compilation. 2003-05-27 18:42 Martin Pool * src/: serve.c, clirpc.c: Don't time transmission of a file: because a large fraction of it can be stuck in network buffers it is not a very accurate measure. 2003-05-27 18:39 Martin Pool * TODO: [no log message] 2003-05-27 18:35 Martin Pool * TODO: Note on handling SIGCHLD from cpp. 2003-05-27 18:17 Martin Pool * src/: distcc.c: Doc. 2003-05-27 18:16 Martin Pool * src/: clirpc.c, distcc.c, exec.c, exec.h, serve.c: dcc_report_rusage: Merge into dcc_collect_child because they're coupled. * dcc_collect_child: Don't pass back rusage. Do take a descriptive name for the child. * dcc_compile_remote: Collect the SSH child after the connection is closed. 2003-05-27 18:06 Martin Pool * src/distcc.c: Add pointer to manual in usage message. 2003-05-27 17:54 Martin Pool * src/netutil.c: dcc_sockaddr_to_string: Remove "INET" from IP address. 2003-05-27 17:54 Martin Pool * src/clinet.c: dcc_connect_by_addr: Print sockaddr in raw form. 2003-05-27 15:11 Martin Pool * test/testdistcc.py: ParseMask_Case: Better error message. 2003-05-27 14:58 Martin Pool * doc/results.txt: Notes on prefork mode. 2003-05-27 14:43 Martin Pool * src/daemon.h: Fix decl. 2003-05-27 14:42 Martin Pool * src/hosts.c: Fix C syntax. 2003-05-27 14:41 Martin Pool * TODO: Update notes on fsh/ssh. 2003-05-27 12:26 Martin Pool * src/serve.c: Tweak log messages. 2003-05-27 11:44 Martin Pool * linuxdoc/distcc.sgml: Recommend using log files. 2003-05-27 11:41 Martin Pool * src/prefork.c: dcc_preforked_child can be static. 2003-05-27 11:07 Martin Pool * src/exec.c: dcc_critique_status: Tweak log output. 2003-05-27 11:05 Martin Pool * src/exec.c: dcc_critique_status: Better message for termination by signal. 2003-05-27 11:00 Martin Pool * src/lock.c: Show lock fd in trace messages. 2003-05-27 10:59 Martin Pool * src/srvnet.c: dcc_sockaddr_to_ip now indicates which AF it is. 2003-05-27 10:58 Martin Pool * src/netutil.c: Better description of AF_UNIX sockets. 2003-05-27 10:54 Martin Pool * src/netutil.c: dcc_sockaddr_to_string: Handle AF_LOCAL and unknown AF addresses. Return "INET 1.2.1.2:323" to distinguish AFs. 2003-05-27 10:49 Martin Pool * src/: netutil.c, netutil.h, srvnet.c: dcc_sockaddr_to_ip: Rename to dcc_sockaddr_to_string. 2003-05-27 10:46 Martin Pool * src/bulk.c: Doc 2003-05-27 10:43 Martin Pool * src/bulk.c: Tweak trace message. 2003-05-27 10:42 Martin Pool * src/sendfile.c: Doc. 2003-05-27 10:28 Martin Pool * src/: distcc.c, where.c: Disable XMIT locks for the moment. 2003-05-26 18:43 Martin Pool * doc/results.txt: More testing. 2003-05-26 18:39 Martin Pool * doc/results.txt: More testing. 2003-05-26 18:09 Martin Pool * NEWS: Client no longer considers NCPUs. 2003-05-26 18:08 Martin Pool * src/bulk.c: Tweak trace message. 2003-05-26 17:53 Martin Pool * TODO: [no log message] 2003-05-26 17:45 Martin Pool * src/hosts.c: Fix warning. 2003-05-26 17:44 Martin Pool * src/hosts.c, Makefile.in: Don't look at the number of CPUs on the client; it's too expensive. 2003-05-26 17:39 Martin Pool * src/srvnet.c, src/dparent.c, NEWS: Log full passive sockaddr in listen message. 2003-05-26 17:36 Martin Pool * src/dparent.c: Shuffle startup messages. 2003-05-26 17:34 Martin Pool * src/dsignal.c, NEWS: Make sure to remove handler before re-raising signal, or Valgrind gets its kickers in a knot. 2003-05-26 17:30 Martin Pool * src/serve.c: dcc_service_job: Split off code for checking access control. 2003-05-26 17:13 Martin Pool * src/: daemon.c, daemon.h, distcc.h, dparent.c, prefork.c, serve.c, srvnet.c, srvnet.h: Use the sockaddr passed in by accept() when a connection is accepted, rather than doing an extra getpeername() call. * dcc_accept_job: Rename to dcc_service_job, since accept() is no longer called from here. 2003-05-26 17:00 Martin Pool * NEWS: dcc_listen_by_addr: Show sockaddr if bind fails. 2003-05-26 16:58 Martin Pool * src/netutil.c: dcc_sockaddr_to_ip: sin_port is in network byte order. 2003-05-26 16:57 Martin Pool * src/srvnet.c: Fix silly typo. 2003-05-26 16:56 Martin Pool * src/srvnet.c: dcc_listen_by_addr: Show sockaddr if bind fails. 2003-05-26 16:53 Martin Pool * src/netutil.c: dcc_sockaddr_to_ip: Show port number as well as IP address. 2003-05-26 16:46 Martin Pool * src/srvnet.c: Split out "address family" part from "connection from" message. 2003-05-26 16:35 Martin Pool * src/daemon.c: Fix syntax problem and missing header. 2003-05-26 16:34 Martin Pool * NEWS: Move daemon into temporary directory during startup. 2003-05-26 16:33 Martin Pool * src/daemon.c: Doc. 2003-05-26 16:32 Martin Pool * src/daemon.c: main: Refactor error handling. * Move daemon into temporary directory during startup. 2003-05-26 16:29 Martin Pool * src/: tempfile.c, tempfile.h: dcc_enter_tempdir: New function. 2003-05-26 16:27 Martin Pool * src/tempfile.c, NEWS: Just use decimal userid rather than username in temporary directory. 2003-05-26 16:22 Martin Pool * src/setuid.c: Undo 1.3 2003-05-26 16:21 Martin Pool * src/setuid.c: Move opt_user to somewhere it can be reached by tmpfile. 2003-05-26 16:19 Martin Pool * NEWS: Use username or decimal userid for temporary directory name. 2003-05-26 15:55 Martin Pool * src/serve.c: Doc. 2003-05-26 15:54 Martin Pool * src/serve.c: Fix naming of stdout, stderr temporary files. * Call server object file .o. 2003-05-26 15:51 Martin Pool * src/serve.c: dcc_accept_job: Close down ecolog connection to server error log, so that we don't leak fds in prefork mode. 2003-05-26 15:48 Martin Pool * src/trace.c: rs_remove_logger: New function to allow turning off loggers without shutting everything down. 2003-05-26 15:42 Martin Pool * src/trace.h: rs_remove_logger: New function. 2003-05-26 15:38 Martin Pool * src/prefork.c: Message when child exits. 2003-05-26 15:13 Martin Pool * test/testdistcc.py: Add tests for new host multiplicity specifications. 2003-05-26 15:12 Martin Pool * src/dsignal.c: Remove unneeded headers. 2003-05-26 15:07 Martin Pool * linuxdoc/distcc.sgml: TCP hosts can now be specified in the more logical form of HOST:PORT/MUL. * Explain when and where to list localhost. 2003-05-26 15:02 Martin Pool * src/hosts.c, NEWS: TCP hosts can now be specified in the more logical form of HOST:PORT/MUL. 2003-05-26 14:58 Martin Pool * src/h_hosts.c: Log to stderr. 2003-05-26 14:54 Martin Pool * src/hosts.c: dcc_parse_multiplier: Remove unnecessary string copy. 2003-05-26 14:51 Martin Pool * src/hosts.c: Doc. 2003-05-26 14:48 Martin Pool * src/dsignal.c: dcc_parent_terminate: Rename to dcc_daemon_terminate because it's now done in both parent and children. 2003-05-26 14:47 Martin Pool * test/testdistcc.py: Run tests in prefork mode. 2003-05-26 14:46 Martin Pool * src/: daemon.h, dparent.c, dsignal.c, prefork.c, serve.c: Don't change the signal handler when starting a child, because this is racy and not straightforward. Instead, keep track of the pid of the master daemon, and in the signal handler check if that's who we are when running cleanup. 2003-05-26 14:34 Martin Pool * NEWS: Call server-side output object files .o, not .out. Patch from rishikesh shetty. 2003-05-26 14:28 Martin Pool * src/prefork.c: Doc. 2003-05-26 14:24 Martin Pool * test/testdistcc.py: Assume localhost has one CPU when checking host parsing. 2003-05-26 14:20 Martin Pool * test/testdistcc.py: Wait status for a terminated daemon is now TERM, not 0. * Use --no-prefork for the moment to check nothing was broken. 2003-05-26 14:13 Martin Pool * src/dparent.c: Don't catch signals until we've established our own process group, because we don't want to accidentally kill the caller's process group. * More trace messages. 2003-05-26 14:12 Martin Pool * src/: exec.h, exec.c: dcc_setpgid: Return an error if we fail to create a process group, because we rely on being separated for proper shutdown. 2003-05-26 13:55 Martin Pool * src/exec.c: dcc_setpgid: Return an error if we fail to create a process group, because we rely on being separated for proper shutdown. 2003-05-26 13:34 Martin Pool * src/tempfile.c: Fix warning 2003-05-26 13:14 Martin Pool * src/tempfile.c: tmpfile list must be volatile. 2003-05-26 13:10 Martin Pool * src/dparent.c: dcc_standalone_server: Even in --no-detach mode, create a new process group. 2003-05-26 13:09 Martin Pool * src/prefork.c: dcc_preforking_parent: We don't need to create a new process group because it has already been done at a higher level. 2003-05-26 13:08 Martin Pool * src/exec.c: Doc. 2003-05-26 12:15 Martin Pool * Makefile.in: h_hosts now needs ncpus.c 2003-05-26 12:08 Martin Pool * NEWS: Note prefork support. 2003-05-26 12:06 Martin Pool * src/: srvrpc.c, serve.c: Split server-specific RPC code into its own file. 2003-05-26 12:05 Martin Pool * Makefile.in, src/rpc.h: src/srvrpc.c: New file. 2003-05-26 12:00 Martin Pool * src/daemon.c: Doc. 2003-05-26 11:53 Martin Pool * NEWS: Kill process group on termination signal. 2003-05-26 11:50 Martin Pool * src/: prefork.c, dparent.c: "up to n children" is only a debug message. 2003-05-26 11:49 Martin Pool * src/dparent.c: Split out code for logging terminated children. * Show signal names if appropriate when a child exits. * If a child is terminated, this is just an info log not an error. 2003-05-26 11:49 Martin Pool * src/daemon.c: Doc 2003-05-26 11:44 Martin Pool * src/dsignal.c: dcc_child_terminate: No log message when the child is terminated, the parent can do it. 2003-05-26 11:40 Martin Pool * src/dsignal.c: Termination signal handlers re-raise the signal and therefore should not _exit, because the signal is blocked until we try to return. 2003-05-26 08:38 Martin Pool * src/: daemon.h, dparent.c, dsignal.c, prefork.c: Use a separate signal handler for daemon children, that cleans up temporary files but doesn't kill the group. 2003-05-25 21:10 Martin Pool * src/: daemon.h, dparent.c, dsignal.c, prefork.c, serve.c, util.c: Rework some daemon signal handling designs to better suit a preforking server. * Daemon now runs in a single process group in all modes. * Use signal() rather than sigaction() for simplicity. * Killing the daemon kills all running children. This is more consistent with other daemons like Apache. Any clients ought to fall back to local compilation, as they will have to do anyhow. Daemon is killed by reraising the signal, rather than exiting. * Print a message when terminated by a signal that fits better with the strsignal() output. * When terminated, explicitly run cleanups rather than relying on exit(). * Accepted children are not run in a separate group, because this will not work for preforked jobs. 2003-05-25 17:39 Martin Pool * src/prefork.c: Doc * dcc_preforking_parent: Should wait until a child exits before bothering about starting a new one. 2003-05-25 17:32 Martin Pool * src/prefork.c: Doc 2003-05-25 17:29 Martin Pool * src/: daemon.h, dparent.c, prefork.c: dcc_reap_kids: Flags ought to allow distinguishing between needing to reap at least one child, and just checking for any of them. We don't want to wait until all the children exited. This fixes the problem of the preforked parent waiting until all the children have exited before starting any more. 2003-05-25 16:34 Martin Pool * linuxdoc/distcc.sgml: Note that DISTCC_LOG doesn't change the server. * Add section on how to shut down distccd. 2003-05-25 16:23 Martin Pool * linuxdoc/distcc.sgml: Bump version to 2.5. * Add descriptions of some new error codes. 2003-05-23 19:19 Martin Pool * src/dparent.c: Doc 2003-05-23 19:15 Martin Pool * src/daemon.c, NEWS: Make sure that the right syslog facility is opened. 2003-05-23 19:04 Martin Pool * src/: .cvsignore, daemon.c, daemon.h, distcc.h, dparent.c, dsignal.c, prefork.c: Split prefork stuff into prefork.c. * Split daemon stuff into daemon.h. 2003-05-23 19:03 Martin Pool * Makefile.in: No more recursive Make. 2003-05-23 18:33 Martin Pool * src/: distcc.h, dopt.c, dopt.h, dparent.c: New option --no-prefork * Add simple implementation of preforking: just create max_jobs children and let them all accept connections. They time out after a few requests. 2003-05-23 15:50 Martin Pool * NEWS, src/dopt.c, src/dopt.h, src/dparent.c: Add new --jobs, -j option to server to set limit on incoming jobs. 2003-05-23 15:48 Martin Pool * configure.ac: Bump version to 2.5cvs 2003-05-23 15:48 Martin Pool * README.libiberty: Remove libiberty stuff 2003-05-23 14:54 Martin Pool * src/dparent.c: Remove quote. 2003-05-23 14:51 Martin Pool * src/dparent.c: dcc_reap_kids: Add option to block until a child exits. * dcc_forking_parent: Block waiting for a child to complete before accepting any new connections when we've exceeded the maximum number of connections. 2003-05-23 14:30 Martin Pool * src/dparent.c: Rename /_loop/_parent/ 2003-05-23 14:29 Martin Pool * src/dparent.c: max_kids: New variable to impose a limit on concurrent servers. 2003-05-23 14:21 Martin Pool * src/dparent.c: Fix prototype 2003-05-23 14:20 Martin Pool * src/dparent.c: Refactor daemon parent loop into separate versions for nofork and forking mode, so that we don't need checks for mode at more than one place. 2003-05-23 14:05 Martin Pool * src/hosts.c: Doc 2003-05-23 14:04 Martin Pool * src/hosts.c: Set default local task limit to twice the number of CPUs. 2003-05-23 13:38 Martin Pool * TODO: Remove done items. 2003-05-23 13:02 Martin Pool * NEWS, configure.ac: Prepare for 2.4.2 release 2003-05-23 12:58 Martin Pool * src/serve.c: Doc. 2003-05-23 12:47 Martin Pool * src/netutil.c, NEWS: Fix string allocation bug in dcc_sockaddr_to_ip that could cause a server crash. 2003-05-23 12:17 Martin Pool * NEWS, src/distcc.h, src/hostfile.c, src/hosts.c: Better error messages if DISTCC_HOSTS or host files are empty. Patch from Wayne Davison. 2003-05-22 19:06 Martin Pool * doc/results.txt: [no log message] 2003-05-22 19:05 Martin Pool * TODO: More notes on feeding from a FIFO. 2003-05-22 17:39 Martin Pool * src/sendfile.c: Doc. 2003-05-22 16:40 Martin Pool * Makefile.in: libiberty is no longer used by distcc. 2003-05-22 16:24 Martin Pool * src/bulk.c, NEWS: Open output files in the same way that GNU as does, by only trying to remove them if they're >0 bytes, and ignoring failure to remove. This fixes compilation directed to /dev/null, which is used by some configure scripts. Reported by Hal Duston. 2003-05-22 16:12 Martin Pool * cases/fooey.c: Another developer scratch test. 2003-05-22 16:09 Martin Pool * test/testdistcc.py: Fix /dev/null test. 2003-05-22 15:51 Martin Pool * test/testdistcc.py: Add test case for "-o /dev/null", reported by Hal Duston. Currently fails. 2003-05-22 15:48 Martin Pool * configure.ac: Update to 2.5cvs 2003-05-22 15:24 Martin Pool * configure.ac: Update to 2.4.1 2003-05-22 15:21 Martin Pool * NEWS: Patch from Frerich Raabe: * Add strndup on platforms that don't have it. 2003-05-22 11:25 Martin Pool * src/hosts.c, NEWS: Patch from Frerich Raabe: * Add strndup on platforms that don't have it. 2003-05-22 11:13 Martin Pool * configure.ac: Bump version to 2.4.1cvs * Check for function and declaration of strndup. 2003-05-22 10:03 Martin Pool * man/: distcc.1, distccd.1: Add email addresses. 2003-05-21 16:57 Martin Pool * TODO: Note on waking up bored clients. 2003-05-21 16:47 Martin Pool * configure.ac, NEWS: Get ready for 2.4 release 2003-05-21 16:45 Martin Pool * test/testdistcc.py: NoHosts_Case needs to reset DISTCC_FALLBACK=1 to test the desired behaviour. 2003-05-21 16:41 Martin Pool * src/: clirpc.c, distcc.c, exec.c, exec.h, serve.c: dcc_critique_status: Add butt-ugly verbose parameter, so that diagnostics on command completion are only given high status in cases where the user is likely to want to see them. 2003-05-21 16:39 Martin Pool * doc/results.txt: Notes on backoff. 2003-05-21 16:30 Martin Pool * src/timefile.c: dcc_remove_timefile: Better messages. 2003-05-21 16:26 Martin Pool * src/h_hosts.c: Renamed to dcc_get_hostlist 2003-05-21 16:25 Martin Pool * NEWS: [no log message] 2003-05-21 16:24 Martin Pool * src/clinet.c: Doc. 2003-05-21 16:16 Martin Pool * src/distcc.c: dcc_build_somewhere: Allow for the fallback code to be invoked because of failure to choose a host, e.g. because they're all down or none were defined. 2003-05-21 16:10 Martin Pool * src/where.c: dcc_pick_host_from_list: Return EXIT_NO_HOSTS on failure, not 0. This makes sure that all failures are caught in common code and that DISTCC_FALLBACK is always applied. 2003-05-21 16:09 Martin Pool * src/exitcode.h: New code EXIT_NO_HOSTS 2003-05-21 16:07 Martin Pool * src/: where.h, where.c, distcc.c: dcc_pick_host_from_env: rename to dcc_pick_host_from_list, since hosts can now come from files too. 2003-05-21 16:04 Martin Pool * src/where.c: If removing disliked hosts leaves us with nothing, then use localhost instead. 2003-05-21 15:55 Martin Pool * src/backoff.c: Doc 2003-05-21 15:55 Martin Pool * doc/results.txt: [no log message] 2003-05-21 15:54 Martin Pool * src/: backoff.c, backoff.h, hosts.c, where.c: Backoff from disliked hosts for 60 seconds. 2003-05-21 15:53 Martin Pool * NEWS: Note sleep changes and backoff. 2003-05-21 15:38 Martin Pool * src/: hosts.h, hosts.c: dcc_free_hostdef: New function. 2003-05-21 15:25 Martin Pool * src/: hosts.h, hosts.c, where.c: Rename dcc_preferred_hosts to dcc_get_hostlist. 2003-05-21 15:23 Martin Pool * src/where.c: Sleep for just 2s if a host is not free. 2003-05-21 14:09 Martin Pool * src/where.c, NEWS: dcc_lock_pause: Replace simple 0.1s sleep with a truncated exponential backoff starting at 1s and going up to 8s. 0.1s is very short compared to the period a compile typically takes to complete, and if we hit this code at all then we're probably overloaded. 2003-05-21 14:01 Martin Pool * src/lock.c: Doc. 2003-05-21 14:00 Martin Pool * src/timefile.c: dcc_mark_timefile: Fix error check 2003-05-21 13:57 Martin Pool * src/: backoff.c, distcc.c: backoff.c, backoff.h: New files. 2003-05-21 13:56 Martin Pool * src/distcc.c: dcc_build_somewhere: Remember when a server failed or not. 2003-05-21 13:55 Martin Pool * src/: backoff.h, backoff.c: dcc_enjoyed_host, dcc_disliked_host: New function that remember when a server failed. 2003-05-21 13:51 Martin Pool * Makefile.in: backoff.c, backoff.h: New files. 2003-05-21 13:44 Martin Pool * src/timefile.c: dcc_remove_timefile, dcc_check_timefile: Cope with timestamp files that don't exist. 2003-05-21 13:35 Martin Pool * src/timefile.c: dcc_mark_timefile, dcc_remove_timefile: add trace messages. 2003-05-21 13:34 Martin Pool * src/: timefile.c, timefile.h: dcc_remove_timefile, dcc_check_timefile: New functions. 2003-05-21 13:30 Martin Pool * src/timefile.h, Makefile.in, src/lock.h: timefile.h: New header for timefile.c 2003-05-21 13:22 Martin Pool * doc/release-names.txt: [no log message] 2003-05-21 13:21 Martin Pool * Makefile.in, src/lock.c, src/lock.h, src/timefile.c: timefile.c: New file. * Export some functions from lock.c needed to do timestamps. * dcc_mark_timefile: Very simple implementation of time markers. 2003-05-21 13:19 Martin Pool * src/climasq.c: Doc 2003-05-21 13:14 Martin Pool * test/testdistcc.py: Doc. 2003-05-21 11:49 Martin Pool * doc/release-names.txt: [no log message] 2003-05-20 22:35 Martin Pool * doc/release-names.txt: [no log message] 2003-05-20 12:00 Martin Pool * survey.txt: Add request to send misconfigurations to the list rather than to the survey. 2003-05-19 18:21 Martin Pool * TODO: Describe use of SSH. * Notes about localhost scheduling. 2003-05-19 18:17 Martin Pool * linuxdoc/distcc.sgml: Bump version. 2003-05-19 18:16 Martin Pool * linuxdoc/distcc.sgml, NEWS: Describe use of SSH. 2003-05-19 18:02 Martin Pool * doc/results.txt: Results from SSH. 2003-05-19 17:50 Martin Pool * src/lock.c: dcc_lock_host: Use hostdef_string, not hostname. 2003-05-19 17:47 Martin Pool * TODO, src/hosts.c: Move notes about multi-A-records to TODO, since it probably won't happen. 2003-05-19 17:43 Martin Pool * NEWS: dcc_critique_status now takes a hostdef, not a hostname, so that it can give better error messages. Update all callers. 2003-05-19 17:41 Martin Pool * src/exec.c: dcc_critique_status: Don't print function name in errors. 2003-05-19 17:39 Martin Pool * src/: clirpc.c, distcc.c, exec.c, exec.h, hosts.c, serve.c: dcc_critique_status now takes a hostdef, not a hostname, so that it can give better error messages. Update all callers. 2003-05-19 17:29 Martin Pool * src/: distcc.c, exec.c, exec.h, lock.c: Move towards passing around hostdefs, rather than hostnames, because they provide better explanations now that we have multiple protocols and different ports. At the moment done just for dcc_note_execution. 2003-05-19 17:20 Martin Pool * src/hosts.h: Add verbatim name to hostdef struct. 2003-05-19 17:18 Martin Pool * NEWS: If remote compilation fails, give an error rather than just a notice. People might want to know. 2003-05-19 17:16 Martin Pool * cases/bad.c: Test case for errors. 2003-05-19 17:15 Martin Pool * src/exec.c: If remote compilation fails, give an error rather than just a notice. People might want to know. 2003-05-19 17:10 Martin Pool * src/arg.c: Doc. 2003-05-19 16:58 Martin Pool * src/: filename.c: Doc. 2003-05-19 16:43 Martin Pool * NEWS, src/clinet.c, src/netutil.c, src/srvnet.c: Don't use the RFC2553 getaddrinfo/getnameinfo API by default, because it seems to be slower on OS X and possibly problematic on other systems. It can be enabled with --enable-rfc2553 if you want to use IPv6, multi-homed servers, or want to test the new API. 2003-05-19 16:08 Martin Pool * doc/results.txt: Notes on getaddrinfo vs gethostinfo. 2003-05-19 16:08 Martin Pool * configure.ac: Add --enable-rfc2553 configuration option. 2003-05-19 16:08 Martin Pool * TODO: Notes on name handling and statistics. 2003-05-19 16:07 Martin Pool * NEWS: Patch from Paul Green to start supporting VOS: * Use autoconf EXEEXT in Makefile. Remove sbin_programs. * Add VOS implementation of dcc_ncpus. * Once socklen_t, in_addr_t and in_port_t have been typedef'd, set the feature macros for them. * src/util.c needs netdb.h 2003-05-19 13:08 Martin Pool * src/hosts.c, TODO: Merge comment from Alexandre about keeping the HOSTS syntax such that it can be handled from the shell. 2003-05-19 12:25 Martin Pool * Makefile.in, src/ncpus.c, src/types.h, src/util.c: Patch from Paul Green to start supporting VOS: * Use autoconf EXEEXT in Makefile. Remove sbin_programs. * Add VOS implementation of dcc_ncpus. * Once socklen_t, in_addr_t and in_port_t have been typedef'd, set the feature macros for them. * src/util.c needs netdb.h 2003-05-16 17:52 Martin Pool * src/where.c, NEWS: If an IO error occurs while trying to get a lock, bail out rather than getting stuck. 2003-05-16 17:47 Martin Pool * src/filename.c: Doc. 2003-05-16 17:43 Martin Pool * src/cpp.c: dcc_cpp_maybe: Doc, add trace. 2003-05-16 17:40 Martin Pool * src/cpp.c: dcc_cpp_maybe: Pull out all the preprocessor-extension logic and just call dcc_preproc_exten, which already knows all about C++ and ObjC and ObjC++. 2003-05-16 17:37 Martin Pool * src/cpp.c: Logic cleanup on Dara's patch. * For C++ source files, call the preprocessor output .ii. 2003-05-16 17:24 Martin Pool * Makefile.in: Fix upload-dist. 2003-05-16 17:23 Martin Pool * src/cpp.c, src/filename.c, NEWS: Merge cleaned-up patch from Dara Hazeghi to recognize ObjC extensions. Still not clear. 2003-05-16 17:18 Martin Pool * doc/results.txt: Update from experiments today on kernel. 2003-05-16 17:16 Martin Pool * NEWS: Bump to 2.4cvs. * Merge patch to recognize Objective C files, by Dara Hazeghi. 2003-05-16 17:14 Martin Pool * configure.ac: Bump to 2.4cvs. 2003-05-16 17:10 Martin Pool * cases/hello-objc.m: Add compile-command. 2003-05-16 17:09 Martin Pool * cases/hello-objc.m: Example case for Objective C, from Dara Hazeghi. 2003-05-16 15:15 Martin Pool * src/distcc.c: Fix typo in usage message. 2003-05-16 15:07 Martin Pool * doc/release-names.txt: [no log message] 2003-05-16 14:46 Martin Pool * linuxdoc/distcc.sgml: Prepare for 2.3 release. 2003-05-16 14:09 Martin Pool * NEWS: Prepare for 2.3 release. 2003-05-16 13:43 Martin Pool * configure.ac: Prepare for 2.3 release. 2003-05-15 15:14 Martin Pool * src/util.c: Update trace message. 2003-05-14 10:47 Martin Pool * src/util.c: dcc_trim_path: More trace information. 2003-05-13 15:47 Martin Pool * src/srvnet.c: HAVE_GETADDRINFO version of dcc_socket_listen: check that the port is in range, because getaddrinfo doesn't trap it. 2003-05-13 15:37 Martin Pool * src/: daemon.c, distcc.c, util.c, util.h: Patch from Wayne Davison: * When trimming our path, look for the name we were invoked under rather than "cc". 2003-05-13 15:26 Martin Pool * NEWS: Doc updates. 2003-05-13 11:46 Martin Pool * TODO: [no log message] 2003-05-11 12:31 Martin Pool * src/daemon.c, NEWS: dcc_setup_startup_log: Send startup errors to stderr, unless that is a socket. Perhaps a better heuristic for working out when we can stand to have e.g. bad option warnings go there. 2003-05-11 12:21 Martin Pool * src/daemon.c: dcc_set_lifetime: Remove "set alarm for" message, which tends to leak into syslog when testing. 2003-05-11 12:18 Martin Pool * NEWS: Update status of IPv6. 2003-05-11 12:17 Martin Pool * src/srvnet.c: Coallesce log entries. * Doc. 2003-05-11 12:04 Martin Pool * TODO: [no log message] 2003-05-09 14:05 Martin Pool * linuxdoc/distcc.sgml: Remove chapter on "internals", because this is covered in the protocol documentation file, etc. 2003-05-08 18:02 Martin Pool * linuxdoc/distcc.sgml: Document DISTCC_SSH, host list files, and execution over SSH. 2003-05-08 17:17 Martin Pool * NEWS: Updates to manual. 2003-05-08 17:13 Martin Pool * linuxdoc/distcc.sgml: Better description of how --help and --version work with the client. * Document DISTCC_FALLBACK. 2003-05-08 17:05 Martin Pool * linuxdoc/distcc.sgml: Rename "Invoking" section to "Setting up", because this is what it's really about now. * Add SGML markup. * Rephrase some sections about masquerading. 2003-05-08 17:01 Martin Pool * linuxdoc/distcc.sgml: Update section about security to describe ssh and new options. 2003-05-08 16:52 Martin Pool * src/srvnet.c: Restore access control checking for IPv4 connections. 2003-05-08 16:51 Martin Pool * test/testdistcc.py: AccessDenied_Case depends on falling back to local compilation. 2003-05-08 16:44 Martin Pool * src/h_hosts.c: dcc_parse_hosts_env renamed to dcc_preferred_hosts. 2003-05-08 16:43 Martin Pool * src/clinet.c: non-GETADDRINFO version of dcc_connect_by_name: Pass the right socklen. 2003-05-08 16:42 Martin Pool * test/testdistcc.py: Set DISTCC_FALLBACK=0 for most compilations so that we can be more sure that distribution failures will be visible. 2003-05-08 15:47 Martin Pool * src/clinet.c: Remove unused vars. 2003-05-07 17:27 Martin Pool * src/srvnet.c: dcc_socket_listen, dcc_prefer_ipv4: Try to listen on an IPv4 address if there is an acceptable one, because that's the least disruptive change from the previous code and it avoids ugly "::127.0.0.1" strings. 2003-05-07 17:02 Martin Pool * src/srvnet.c: dcc_check_client: Update to be AF-indepedent. Does not do checks yet. 2003-05-07 16:58 Martin Pool * src/: netutil.c, netutil.h: dcc_sockaddr_to_hostname renamed to dcc_sockaddr_to_ip, which is more accurate. Add a non-getnameinfo() implementation. 2003-05-07 16:48 Martin Pool * Makefile.in, src/netutil.c, src/netutil.h: netutil.c, netutil.h: New files. * dcc_sockaddr_to_hostname: New function that hides inet_ntoa vs getnameinfo. 2003-05-07 16:38 Martin Pool * configure.ac: Check for sockaddr_storage.ss_family, since ss_len doesn't seem to exist in glibc. If we have it, define HAVE_SOCKADDR_STORAGE. 2003-05-07 16:24 Martin Pool * configure.ac: Check for inet_ntop and inet_ntoa 2003-05-07 16:18 Martin Pool * src/srvnet.c, NEWS: dcc_socket_listen: Dual implementations for getaddrinfo and old API. The new implementation specifies AI_PASSIVE if no --listen address is given, so it should be able to accept connections on all ports or protocols. 2003-05-07 16:06 Martin Pool * src/srvnet.c: dcc_listen_by_addr, dcc_socket_listen: Factor out the code that creates and listens on a socket from the code that works out the address to use, so that we can use getaddrinfo when available. Also, remove assumptions about socket addresses always being IPv4. 2003-05-07 16:04 Martin Pool * src/clinet.c: Doc. 2003-05-07 15:57 Martin Pool * doc/dietlibc-distcc.trace: strace using dietlibc, just for interest. 2003-05-07 15:56 Martin Pool * NEWS, src/clinet.c, src/clinet.h, src/distcc.c: Use getaddrinfo() if it's available for opening connections, to better handle multihomed servers and start supporting IPv6. 2003-05-07 15:26 Martin Pool * src/clinet.c: dcc_open_socket_out: Add a second definition of this function to be used on machines with getaddrinfo. 2003-05-07 15:25 Martin Pool * configure.ac: Check for getaddrinfo, getnameinfo, and struct sockaddr_storage. 2003-05-07 15:20 Martin Pool * src/clinet.c: dcc_open_socket_out: Check client name before creating a socket. (Not a big deal for now, but will be needed for AF-independence.) 2003-05-07 12:23 Martin Pool * NEWS: hostlist.c fix * snprintf.c fixes. 2003-05-07 12:21 Martin Pool * configure.ac: Add check from Samba for va_copy, which is needed for building our snprintf. 2003-05-07 12:21 Martin Pool * cases/.cvsignore: Ignore built programs. 2003-05-07 12:20 Martin Pool * TODO: [no log message] 2003-05-07 12:07 Martin Pool * src/snprintf.c: Update ifdefs to make sure that this file compiles to an (almost) empty object file on systems that already have all the functions we need. 2003-05-07 11:53 Martin Pool * src/hosts.c: dcc_parse_hosts_env: Remove obsolete function. 2003-05-07 11:52 Martin Pool * src/hosts.c: Trace messages when reading in host lists. 2003-05-07 11:50 Martin Pool * src/hostfile.c: Remove unnecessary recursion protection. * Trace message when reading a file. 2003-05-07 11:49 Martin Pool * src/loadfile.c: Fix silly pointer error when loading a host file. 2003-05-07 11:15 Martin Pool * src/snprintf.h: Fix all HAVE_DECL_ uses: these are defined to zero rather than left undefined by autoconf if the decl is missing. 2003-05-07 11:14 Martin Pool * src/snprintf.c: Merge from samba HEAD: * Fix floating point handling. * Make snprintf test work better. * If the system's vsnprintf is not C99 compliant, then we need to override both vsnprintf and snprintf to make sure the correct code is always called. Also: * Make sure LDOUBLE, VA_COPY, etc are defined even if the system already has some snprintf routines. * Always include snprintf.h, so that we get declarations for the functions in this file. 2003-05-07 10:27 Martin Pool * README.packaging: Note about using ./configure options to set directories, and DESTDIR. 2003-05-07 10:23 Martin Pool * linuxdoc/distcc.sgml: "for 2.2" 2003-05-07 10:23 Martin Pool * NEWS, linuxdoc/distcc.sgml: Document --listen, plus other cleanups. Patch from Frerich Raabe. 2003-05-07 10:13 Martin Pool * cases/lzotest.c: Hacky test to examine efficiency of minilzo. 2003-05-06 18:21 Martin Pool * TODO: Merge some stuff. 2003-05-06 18:18 Martin Pool * doc/scheduling.txt: Merge into TODO 2003-05-06 18:16 Martin Pool * doc/new-scheduler.txt: Merged into doc/results.txt 2003-05-06 18:16 Martin Pool * doc/results.txt: Move "new-scheduler.txt" results (from February) into the results.txt file. 2003-05-06 17:36 Martin Pool * doc/protocol-3.txt: Only a draft 2003-05-06 17:34 Martin Pool * doc/protocol-3.txt: Rephrase. * Don't compress 0-length data. * Insert COMP packets. * Questions about how to describe temporaries. 2003-05-06 17:11 Martin Pool * doc/protocol-3.txt: Describe input and output files. * Start updating request and response descriptions. 2003-05-06 16:54 Martin Pool * doc/protocol-3.txt: Describe handshaking on reused connections. * Describe compression. 2003-05-06 16:02 Martin Pool * doc/protocol-3.txt: More updates towards version 3 protocol. 2003-05-06 14:55 Martin Pool * TODO: [no log message] 2003-05-06 13:12 Martin Pool * src/dparent.c, src/ncpus.c, NEWS: Two Mac OS X fixes from Benjamin Reed: Use the BSD method to discover the number of CPUs, and include types.h where it is needed. 2003-05-05 22:42 Martin Pool * src/trace.h: Doc 2003-05-05 22:31 Martin Pool * src/HACKING: Just about everything in this file has been implemented! The ideas which are not done yet are now in TODO. We're almost a year old now. 2003-05-05 22:29 Martin Pool * src/rpc.c: Fix printf formatting error. 2003-05-05 18:46 Martin Pool * src/trace.h: Doc 2003-05-05 18:40 Martin Pool * src/distcc.h: Doc 2003-05-05 18:07 Martin Pool * TODO: Remove page marks 2003-05-05 18:01 Martin Pool * TODO: Notes on feeding from fifo. 2003-05-05 17:56 Martin Pool * TODO: Notes on streaming output 2003-05-05 17:49 Martin Pool * doc/protocol-3.txt: Start writing notes about a version 3 protocol. 2003-05-05 17:44 Martin Pool * NEWS: Better description of network error detection. 2003-05-05 17:36 Martin Pool * src/rpc.c: dcc_explain_mismatch: After a protocol problem, show up to 200 bytes of printable context. 2003-05-05 17:26 Martin Pool * NEWS, src/rpc.c: dcc_explain_mismatch: New function, to give more information in the case of a protocol mismatch. Most importantly, if an unexpected response is seen then we give a bit more text from the network in the hope that it will help diagnose the problem. 2003-05-05 16:58 Martin Pool * src/clirpc.c: Doc. 2003-05-05 16:54 Martin Pool * src/: clirpc.c, rpc.c: dcc_r_result_header, dcc_r_cc_status: These are client-specific, so move them to clirpc.c. 2003-05-05 16:53 Martin Pool * configure.ac: Bump version. 2003-05-05 16:28 Martin Pool * NEWS, configure.ac: Prepare for 2.2 release. 2003-05-05 16:27 Martin Pool * src/hosts.h: Remove CVS tag. 2003-05-05 16:23 Martin Pool * TODO: [no log message] 2003-05-05 16:21 Martin Pool * TODO: Add a basic --listen option, based on a patch by Neil Mansilla. 2003-05-05 16:17 Martin Pool * src/dopt.c, src/dopt.h, src/dparent.c, src/srvnet.c, src/srvnet.h, NEWS: Add a basic --listen option, based on a patch by Neil Mansilla. 2003-05-05 16:05 Martin Pool * patches/andresen-gcc-wrapper-r2.tbz2: Remove Gentoo-only patch. 2003-05-05 15:54 Martin Pool * TODO: Update TODO list. 2003-05-05 15:30 Martin Pool * src/distcc.c: (dcc_show_usage): Describe where the host list comes from -- this is important because it is a configurable option. Add documentation for SSH syntax. 2003-05-05 15:16 Martin Pool * test/testdistcc.py, NEWS: Test host file support. 2003-05-05 15:15 Martin Pool * NEWS: Note about support for host files. 2003-05-05 15:14 Martin Pool * Makefile.in: h_hosts: Now needs hostfile.o and io.o 2003-05-05 15:08 Martin Pool * src/: hosts.c, hosts.h, where.c: If DISTCC_HOSTS is not set, look in ~/.distcc/hosts, or otherwise /etc/distcc/hosts. 2003-05-05 15:03 Martin Pool * src/hostfile.c: Doc 2003-05-05 15:01 Martin Pool * cases/empty.s: Empty assembler file for testing. 2003-05-05 15:01 Martin Pool * Makefile.in: SYSCONFDIR must be quoted for C. 2003-05-05 14:37 Martin Pool * src/: hosts.c, hosts.h, util.c, util.h: (dcc_dup_part): Move to util.c. 2003-05-05 14:35 Martin Pool * TODO: Build .debs or .rpms? 2003-05-05 14:24 Martin Pool * TODO: Build .debs or .rpms? 2003-05-05 14:19 Martin Pool * src/hostfile.c: (dcc_parse_hosts_file): New function. 2003-05-05 12:59 Martin Pool * Makefile.in, src/hostfile.c: New file: src/hostfile.c * where.o and hosts.o don't need to be linked into the server, only the client. 2003-05-05 12:56 Martin Pool * Makefile.in: (SRC): Sort. 2003-05-05 12:53 Martin Pool * src/loadfile.c: dcc_load_file: Move everything back into a single function. Actually allocate a buffer and read into it. 2003-05-04 23:17 Martin Pool * src/loadfile.c: dcc_load_file: Split into a second function to ease error checking. * dcc_load_fd: New function. Allocate a memory buffer for the file after discovering its size. 2003-05-04 23:13 Martin Pool * src/loadfile.c: dcc_load_file: Check size of file and complain about those that are too large. 2003-05-04 23:06 Martin Pool * Makefile.in, src/exitcode.h, src/io.h, src/loadfile.c: Start adding code to load a whole file in to memory, so that we can read hosts from a file. 2003-05-04 23:00 Martin Pool * patches/hosts-from-file-raabe.diff: Old patch from Frerich to read hosts from a file. 2003-05-04 22:48 Martin Pool * src/: arg.c, bulk.c, clinet.c, dopt.c, exec.c, filename.c, h_argvtostr.c, h_exten.c, h_hosts.c, h_issource.c, h_scanargs.c, h_strip.c, help.c, hosts.c, lock.c, rpc.c, sendfile.c, serve.c, srvnet.c, tempfile.c, trace.c, util.c, where.c, zip.c: Remove all dependencies on assert.h. Most of them were not used, and the rest are better written using our standard error handling library. 2003-05-04 22:43 Martin Pool * configure.ac: More spacing in output. 2003-05-04 22:42 Martin Pool * Makefile.in: Start adding support for a host list file: define SYSCONFDIR, and show it when displaying paths. 2003-05-04 22:31 Martin Pool * configure.ac: Bump version to 2.2cvs 2003-05-04 22:29 Martin Pool * TODO: Notes about compression and reading hosts from a file. 2003-05-04 21:38 Martin Pool * doc/protocol-1.txt: Suggestions from Brad Hards: * Correction about SOUT. * Explain a bit more about waitstatus. 2003-05-04 17:24 Martin Pool * NEWS, linuxdoc/distcc.sgml: Add documentation for --allow and --user, by Frerich Raabe. 2003-05-04 12:01 Martin Pool * TODO: Update todo list. 2003-05-04 11:21 Martin Pool * NEWS, news.el: Roll over NEWS for new release. * Move news.el into mode variables at the bottom of the NEWS file. 2003-05-03 23:57 Martin Pool * NEWS, configure.ac: Prepare for 2.1 release. 2003-05-03 17:56 Martin Pool * doc/protocol-1.txt: Ask for questions. * Describe all the packets in the request and the response. 2003-05-03 13:39 Martin Pool * TODO: Note about preprocessing remotely. 2003-05-03 12:05 Martin Pool * TODO: Note about never running locally. 2003-04-30 12:17 Martin Pool * TODO: Link to API for async name lookups. 2003-04-27 00:18 Martin Pool * doc/protocol-1.txt: Add some documentation of the protocol in the current version. Pretty good but does not cover the complete sequence yet. 2003-04-19 23:08 Martin Pool * NEWS: Test harnesses may need snprintf.o linked in as well. Reported by Joe Meslovich as broken on Solaris. 2003-04-19 21:55 Martin Pool * Makefile.in: Test harnesses may need snprintf.o linked in as well. Reported by Joe Meslovich as broken on Solaris. 2003-04-17 12:26 Martin Pool * doc/release-names.txt: [no log message] 2003-04-14 13:05 Martin Pool * TODO: [no log message] 2003-04-14 13:02 Martin Pool * TODO: [no log message] 2003-04-13 19:00 Martin Pool * TODO: Notes from UML. 2003-04-13 17:35 Martin Pool * TODO: Note about setting listen address. 2003-04-13 17:18 Martin Pool * TODO: Notes about DISTCC_HOSTS syntax. 2003-04-10 16:42 Martin Pool * src/help.c: Add quote. 2003-04-08 16:23 Martin Pool * TODO: [no log message] 2003-04-08 13:58 Martin Pool * patches/n_cpus.txt: n_cpus.txt Remove merged code 2003-04-04 17:39 Martin Pool * patches/: distcc-path.patch, distccd-path.patch: distcc-path.patch distccd-path.patch Delete merged patches 2003-04-04 17:38 Martin Pool * TODO: [no log message] 2003-04-04 17:32 Martin Pool * TODO: [no log message] 2003-04-04 17:28 Martin Pool * src/io.c: tcp_cork_sock: Don't complain about ENOTSUPP when uncorking. 2003-04-04 17:24 Martin Pool * src/: rpc.c, io.h: dcc_read_int: Remove dead function. 2003-04-04 17:20 Martin Pool * src/: io.c: Doc. 2003-04-04 17:19 Martin Pool * src/io.c: dcc_pump_readwrite: Increase transfer buffer to 256kB, and move it off the stack. 2003-04-04 17:16 Martin Pool * src/io.c: dcc_pump_readwrite: Doc. 2003-04-04 17:12 Martin Pool * src/io.c, NEWS: dcc_pump_readwrite: Should print an error on unexpected end of input, rather than treating it as success. Why did I do that? 2003-04-04 17:11 Martin Pool * NEWS: Note about nonblocking support. 2003-04-04 16:59 Martin Pool * src/io.c: dcc_pump_readwrite: Only select on file descriptors after we get EAGAIN. * dcc_readx, dcc_writex: Clarify. 2003-04-04 15:54 Martin Pool * linuxdoc/distcc.sgml: Patch from Wayne Davison to document DISTCCD_PATH. 2003-04-04 15:51 Martin Pool * cases/hello.m: Example ObjC program from Dara Hazeghi 2003-04-04 12:19 Martin Pool * TODO: [no log message] 2003-04-04 12:06 Martin Pool * src/util.c: dcc_abspath: Memory overflow ought to be fatal. 2003-04-04 12:00 Martin Pool * NEWS, src/climasq.c, src/daemon.c, src/distcc.c, src/util.c, src/util.h: Merged patch from Wayne Davison: Try to prevent distcc from invoking itself recursively either on the server, or as cc -E on the client. * dcc_trim_path: New code to remove from the PATH any directories that contain "cc" as a link to something that looks like ccache or distcc. * climasq.c: Munge path as appropriate. * daemon.c/main: Use DISTCCD_PATH if set, otherwise trim path. * distcc.c/main: Trim path. 2003-04-04 11:45 Martin Pool * src/daemon.c: Factor out code for checking whether to be inetd. 2003-04-04 10:41 Martin Pool * README.packaging: Note about ssh and path to distccd * Note about --allow * Note about distcc user * Prefer --daemon 2003-04-04 10:33 Martin Pool * TODO: [no log message] 2003-04-04 10:32 Martin Pool * NEWS: Change behaviour of distccd for log messages encountered during startup, before options are parsed. These are now written to stderr only if that is a tty, and otherwise to syslog. This is intended to prevent log messages from distccd getting mixed into the network protocol when it is run from inetd. 2003-04-04 10:21 Martin Pool * test/testdistcc.py: NoDetachDaemon_Case: Specify --daemon to suppress diagnostic message. 2003-04-04 10:19 Martin Pool * src/daemon.c: dcc_setup_startup_log: Split out code for sending startup messages to either stderr or syslog. * distccd/main: refactor code for deciding whether to be inetd or standalone. * dcc_setup_real_log: Rename function for setting final log destination. * Doc. 2003-04-04 10:04 Martin Pool * src/daemon.c: Change behaviour of distccd for log messages encountered during startup, before options are parsed. These are now written to stderr only if that is a tty, and otherwise to syslog. This is intended to prevent log messages from distccd getting mixed into the network protocol when it is run from inetd. 2003-04-04 10:01 Martin Pool * src/: distcc.c, distcc.h, help.c: Show version in log at client startup. 2003-04-04 09:43 Martin Pool * patches/distcc-path.patch: Patch from Wayne to clean path of masquerade links. 2003-04-03 16:21 Martin Pool * NEWS: Note rusage format fix. 2003-04-03 14:39 Martin Pool * TODO: [no log message] 2003-04-03 14:37 Martin Pool * test/comfychair.py: Better log message. 2003-04-03 14:29 Martin Pool * src/distcc.c: Factor out code to find basename from argv. 2003-04-03 10:23 Martin Pool * src/: distcc.h, serve.c: Patch from Wayne Davison: * Removed prototype for dcc_trace_argv() (since it's a define now). * Use "else while(0)" instead of "else {}" so that using the dcc_trace_argv() define doesn't result in two C statements. * Return the "ret" value in dcc_r_request_header() when it's non-0. 2003-04-02 17:26 Martin Pool * src/util.c: dcc_exit: Remove silly printf bug that made all rusage messages inaccurate. 2003-04-02 17:16 Martin Pool * patches/: distcc-hostopt.patch, distccd-path.patch, distccd-version.patch: Patches from Wayne 2003-04-02 17:12 Martin Pool * TODO: More protocol wonderings. 2003-04-02 16:43 Martin Pool * test/testdistcc.py: Update todos. 2003-04-02 16:37 Martin Pool * src/: arg.c, distcc.h: dcc_trace_argv: Convert to a macro so that it shows the right function name in trace messages. 2003-04-02 16:33 Martin Pool * src/: io.c: dcc_readx, dcc_writex: Only select() on the fd after we've got EAGAIN. It might not be necessary in many cases. 2003-04-02 16:30 Martin Pool * src/sendfile.c: dcc_pump_sendfile: Check for select() failure. 2003-04-02 16:27 Martin Pool * src/io.c: Doc 2003-04-02 15:25 Martin Pool * src/: climasq.c, distcc.c, distcc.h: Make dcc_support_masquerade() return standard error codes. 2003-04-02 15:16 Martin Pool * src/: util.c, arg.c: Remove incorrect EXIT_FAULURE 2003-04-02 15:10 Martin Pool * Makefile.in, src/climasq.c, src/distcc.c, src/distcc.h: Split masquerade support into climasq.c 2003-04-02 15:10 Martin Pool * src/safeguard.c: Doc 2003-04-02 15:05 Martin Pool * src/distcc.c: Doc 2003-04-02 14:57 Martin Pool * src/serve.c: Remove one more old "-1" error code. Patch from Wayne Davison. 2003-04-02 14:54 Martin Pool * src/distcc.c: Doc 2003-04-02 14:49 Martin Pool * src/: io.c, rpc.c: Move rpc-specific functions from io.c into rpc.c. 2003-04-02 14:46 Martin Pool * src/dopt.c: Make --no-fork undocumented. 2003-04-02 14:43 Martin Pool * src/sendfile.c: dcc_pump_sendfile: Only select() on the output socket after sendfile has failed with EAGAIN. Otherwise we can miss the case where the remote host has closed the connection on us, as can happen if we connect contrary to --allow. 2003-04-02 14:42 Martin Pool * src/io.c: Trace message when select()ing 2003-04-02 14:41 Martin Pool * src/distcc.h, src/exec.c, src/exec.h, src/safeguard.c, Makefile.in: Split safeguard functions out into their own file. 2003-04-02 12:39 Martin Pool * doc/results.txt: SSH results. 2003-04-02 12:27 Martin Pool * NEWS: Note removal of "return -1". 2003-04-02 11:55 Martin Pool * NEWS: Update SSH news. 2003-04-02 11:00 Martin Pool * TODO: Notes on DISTCC_SSH. 2003-04-02 10:58 Martin Pool * src/ssh.c: Doc 2003-04-02 10:46 Martin Pool * TODO: Note about documenting SSH. 2003-04-01 13:59 Martin Pool * Makefile.in: Split binary downloads onto their own page. 2003-03-31 23:16 Martin Pool * src/bulk.c: Show more precision when printing transfer rates. 2003-03-31 18:48 Martin Pool * src/sendfile.c: Check network is ready to write before attempting sendfile. 2003-03-31 18:47 Martin Pool * src/: io.h, io.c: Export select_for_* 2003-03-31 18:46 Martin Pool * src/io.c: Before reading or writing a socket, select() on it to make sure it's available. Makes things work when our network socket is really a nonblocking connection to ssh. 2003-03-31 18:43 Martin Pool * src/ssh.c: Don't send server log to stderr by default. 2003-03-31 18:36 Martin Pool * src/serve.c: Doc. 2003-03-31 18:36 Martin Pool * src/io.c: dcc_readx: Handle reading from nonblocking socketpairs/pipes. 2003-03-31 18:34 Martin Pool * src/ssh.c: Use nonblocking pipes to ssh. * Add --log-stderr when invoking the remote daemon. 2003-03-31 18:30 Martin Pool * src/bulk.c: Doc. 2003-03-31 18:18 Martin Pool * configure.ac: Bump version 2003-03-31 18:17 Martin Pool * src/distcc.c: For ssh support, we need to allow for separate fds writing to and reading from the network, because our connection to the ssh client may be over pipes, which are one-way connections. Therefore split them out into separate fds in the code. 2003-03-31 18:14 Martin Pool * NEWS: Preliminary support for ssh. 2003-03-31 18:08 Martin Pool * src/ssh.c: Make the dcc end of the socketpairs/pipes talking to ssh be blocking, even if ssh needs blocking ones. Does this work? 2003-03-31 18:02 Martin Pool * src/io.c: dcc_readx: Stub handler for EAGAIN. 2003-03-31 18:00 Martin Pool * src/io.c: Reindent only. 2003-03-31 17:55 Martin Pool * test/testdistcc.py: Fix silly Python bug. 2003-03-31 17:49 Martin Pool * test/testdistcc.py: Giving a bogus port number now gives you EXIT_BAD_ARGUMENTS. 2003-03-31 17:48 Martin Pool * src/: dparent.c, srvnet.c, srvnet.h: open_socket_in: Rename to conventional name 'dcc_socket_listen', and return an exit code. 2003-03-31 17:44 Martin Pool * test/testdistcc.py: Allow default daemon lifetime of 60s, and 300s for BigAssFile. 2003-03-31 17:42 Martin Pool * patches/.cvsignore: Ignore built test programs. 2003-03-31 17:42 Martin Pool * src/: arg.c, bulk.c, clirpc.c, distcc.c, dparent.c, exec.c, filename.c, hosts.c, io.c, sendfile.c, serve.c, srvnet.c, tempfile.c, util.c: Get medieval on "return -1" in old code. Everything ought to return a standard error code now. 2003-03-31 17:30 Martin Pool * src/distcc.c: Doc 2003-03-31 17:22 Martin Pool * src/distcc.c, NEWS: Add DISTCC_FALLBACK environment variable. If set to 0, means that failure to distribute will be considered an overall failure. By default, a networking error means that compilation will be retried locally. 2003-03-31 17:11 Martin Pool * src/io.c, NEWS: Better error handling when corks are not supported on a particular system or socket. 2003-03-31 17:08 Martin Pool * test/testdistcc.py: Revert r1.129: sending logs to stderr doesn't work very well. The daemon can get sigpipe while writing them and similar problems. 2003-03-31 17:02 Martin Pool * test/testdistcc.py, NEWS: Test invalid --allow masks. 2003-03-31 17:00 Martin Pool * src/: distcc.h, ssh.c: dcc_ssh_connect: Fix const-ness of strings. 2003-03-31 17:00 Martin Pool * src/distcc.c: First cut of support for distcc-over-ssh. * dcc_compile_remote: For ssh-mode connections, try to open up using dcc_ssh_connect. 2003-03-31 16:59 Martin Pool * src/arg.c: Undo constness of argv[] arguments, it just doesn't work well in gcc. 2003-03-31 16:55 Martin Pool * src/: distcc.h, ssh.c: Undo constness of argv[] arguments, it just doesn't work well in gcc. 2003-03-31 16:54 Martin Pool * TODO: More notes on new scheduler. 2003-03-31 16:54 Martin Pool * doc/release-names.txt: [no log message] 2003-03-31 16:45 Martin Pool * src/distcc.h: dcc_trace_argv: Fix constness of parameter. * dcc_ssh_connect: Export prototype. 2003-03-31 16:44 Martin Pool * src/arg.c: dcc_trace_argv: Fix constness of parameter. 2003-03-31 16:39 Martin Pool * Makefile.in: Include ssh.o in client build. 2003-03-31 16:38 Martin Pool * src/ssh.c: dcc_ssh_connect: If no username is specified, don't pass the -l option. If no machine is specified, abort. If no path is given, just use "distccd". 2003-03-31 16:33 Martin Pool * src/ssh.c: Remove blocking_io support; it shouldn't be needed if we're only using ssh not rsh. * Update to build cleanly in this tree. * dcc_run_piped_cmd: Make sure pipes are always closed because the program will not necessarily abort if we fail to connect and we don't want to leak file descriptors. * dcc_ssh_connect: Build connection command in argv[] not a string, so that we can avoid invoking a shell. 2003-03-31 16:02 Martin Pool * TODO: Many more notes about single-queue multi-server scheduler. 2003-03-31 15:59 Martin Pool * src/serve.c: Remove dead code. 2003-03-31 15:37 Martin Pool * patches/backlog-sample.c: Sample that tries to use TCP connection backlogs to give the client some information about whether the server is busy. Doesn't seem to work very well. 2003-03-31 14:59 Martin Pool * TODO: Update 2003-03-31 14:54 Martin Pool * test/testdistcc.py: Doc. 2003-03-31 14:53 Martin Pool * test/testdistcc.py: Add new case exercising dcc_check_address and h_parsemask. 2003-03-31 14:48 Martin Pool * src/access.c: Doc 2003-03-31 14:34 Martin Pool * test/testdistcc.py: NoDetachDaemon_Case: prevent logs from background process getting into build process's stderr. 2003-03-31 14:28 Martin Pool * src/dsignal.c, NEWS: dcc_parent_terminate: No need to explicitly remove pid file; it will be cleaned up in atexit(). 2003-03-31 14:25 Martin Pool * test/testdistcc.py: Allow log output from the server into stderr so that it can be presented if a test case fails. 2003-03-31 14:22 Martin Pool * NEWS, test/testdistcc.py: Add test that --allow does in fact deny connections as it should. 2003-03-31 14:14 Martin Pool * TODO, doc/ssh-notes.txt, doc/to-test.txt: Move notes on future design options into ./TODO. 2003-03-31 14:14 Martin Pool * doc/lock-deadlock.txt: Remove old bug report. 2003-03-31 14:10 Martin Pool * test/testdistcc.py: Remove done TODOs 2003-03-31 14:09 Martin Pool * patches/prefork-sample.c: Doc 2003-03-29 11:06 Martin Pool * NEWS: Retrospective release name. 2003-03-28 18:57 Martin Pool * TODO: Notes about preforking. 2003-03-28 18:43 Martin Pool * patches/prefork-sample.c: Experimental code to see if we can just have every preforked child accept() on the socket 2003-03-28 18:20 Martin Pool * doc/interceptor.txt: interceptor.txt Remove old file 2003-03-28 18:12 Martin Pool * configure.ac, NEWS: Prepare for 2.0.1 release. 2003-03-28 18:12 Martin Pool * Makefile.in: Dereference symbolic files when producing tarball. 2003-03-28 17:33 Martin Pool * linuxdoc/distcc.sgml: Masquerade came out in 2.0, not 1.3. 2003-03-28 16:47 Martin Pool * doc/release-names.txt: [no log message] 2003-03-28 16:17 Martin Pool * linuxdoc/distcc.sgml: Get ready for 2.0 release. 2003-03-28 16:13 Martin Pool * NEWS, configure.ac: Get ready for 2.0 release. 2003-03-28 16:11 Martin Pool * Makefile.in: Remove old doc/ files from the distribution. 2003-03-28 16:02 Martin Pool * src/distcc.c: Remove "HOST/MAX:PORT" syntax from --help. I don't want to make this fully "public" yet because I'm not sure this is the ideal way to set this value in the future. 2003-03-28 15:58 Martin Pool * NEWS, test/testdistcc.py: Test DISTCC_LOG being set to an unwriteable file. 2003-03-28 15:55 Martin Pool * NEWS: Test suite now works with Python 1.5 or later. 2003-03-28 15:53 Martin Pool * test/comfychair.py: Remove dependency on os.spawnvp, which is not in Python1.5 2003-03-28 15:52 Martin Pool * test/testdistcc.py: NoHosts_Case: Python 1.5 can't delete environment variables, so just set them to empty. 2003-03-28 15:50 Martin Pool * src/distcc.c, NEWS: If the file specified by DISTCC_LOG can't be opened, then show an error and use stderr. Previously all errors were just lost. 2003-03-28 15:45 Martin Pool * src/distcc.c, NEWS: If DISTCC_LOG is an empty string, treat as undefined. 2003-03-28 15:42 Martin Pool * test/testdistcc.py: runcmd_background now takes a string, not a sequence. * Python1.5 doesn't have ''.split. 2003-03-28 15:27 Martin Pool * test/: comfychair.py, testdistcc.py: Remove dependency on popen4, which is not present in Python 1.5. * runcmd and related functions now return stdout and stderr messages separately. Many tests must be updated to allow for this. * Refactor some tests towards a flatter hierarchy. * Assert that the compiler should not normally produce errors or other messages. 2003-03-28 13:58 Martin Pool * test/comfychair.py: Remove list comprehension, which is not available in Python 1.5. 2003-03-28 13:54 Martin Pool * TODO: Note on static linking. 2003-03-28 13:51 Martin Pool * test/testdistcc.py, NEWS: On BSD, 'true' and 'false' are in /usr/bin (?) not /bin. 2003-03-28 13:44 Martin Pool * NEWS: Notes on test improvments. 2003-03-28 13:40 Martin Pool * Makefile.in: Makefile (check, installcheck): If Python is not found then just print "tests skipped" rather than failing. This should make the results on the build farm a bit more clear. 2003-03-28 13:37 Martin Pool * configure.ac: If Python is not found in the path, then just leave $(PYTHON) blank rather than setting it to 'false'. 2003-03-28 11:59 Martin Pool * Makefile.in: Remove redundant setting of $(LIBS): autoconf puts -lpopt in there if it's needed. 2003-03-28 11:57 Martin Pool * configure.ac: (Hopefully) better check for socket() and gethostbyname() that will avoid unnecessarily linking libnsl on Linux. Taken from Samba, which got it from CVS. 2003-03-27 19:16 Martin Pool * TODO: Note on DNS timeouts. 2003-03-27 15:58 Martin Pool * src/rpc.h: dcc_x_token_int: Token parameters are unsigned. 2003-03-27 15:54 Martin Pool * NEWS: [no log message] 2003-03-27 15:45 Martin Pool * src/rpc.c: dcc_x_token_int: Remove call to snprintf to format outgoing packets. It really sticks out in valgrind and this is a reasonably common function. 2003-03-27 15:33 Martin Pool * src/: io.c, io.h: dcc_write_int: Remove dead function. 2003-03-27 15:31 Martin Pool * src/: io.h, io.c: dcc_write_str: Remove dead function. 2003-03-27 15:29 Martin Pool * src/clirpc.c: dcc_x_argv: Avoid redundant strlen() computation. 2003-03-27 15:08 Martin Pool * src/arg.c, src/distcc.h, src/exec.c, src/serve.c, src/ssh.c, src/strip.c, NEWS: Factor out code for tracing argv[] arrays. By avoiding conversion unless it is actually going to be logged we save a few cycles. This also addresses some cases where the printable form was not freed after creation, although that shouldn't ever matter much in such a short-lived program. 2003-03-27 11:39 Martin Pool * Makefile.in: Allow for implementations of 'install' that can only process one file at a time. GNU's 'install-sh' is one such. 2003-03-27 11:08 Martin Pool * NEWS: Don't install linuxdoc-info by default, either from CVS or distributions. 2003-03-27 10:37 Martin Pool * Makefile.in: Don't install linuxdoc-info by default, either from CVS or distributions. 2003-03-27 10:30 Martin Pool * Makefile.in: Remove overall 'upload' target: we don't want to upload the manual when the web site is uploaded. 2003-03-26 23:36 Martin Pool * linuxdoc/distcc.sgml: Manual is for 1.3cvs. 2003-03-23 12:18 Martin Pool * Makefile.in: Don't ship unmerged patches in the tarball. 2003-03-23 12:17 Martin Pool * patches/resolver-timeout.diff: resolver-timeout.diff Resolver timeout draft patch from Jonas Jensen 2003-03-22 09:44 Martin Pool * patches/connect-timeout.diff: Remove old draft patch. 2003-03-21 19:02 Martin Pool * test/testdistcc.py: Get rid of Python 2 ism. 2003-03-21 18:59 Martin Pool * src/ncpus.c: Try looking for the predefined "__hpux" or "__hpux__" not "hpux". 2003-03-21 18:47 Martin Pool * NEWS, test/testdistcc.py: Use randomly chosen TCP port for the server when running tests. 2003-03-21 18:46 Martin Pool * NEWS: Use --allow=127.0.0.1 when starting daemon 2003-03-21 18:41 Martin Pool * test/testdistcc.py: Use --allow=127.0.0.1 when starting daemon * killDaemon: if the daemon has already exited, perhaps because of an alarmclock, and removed it's pid file, then don't worry about killing it. 2003-03-21 18:32 Martin Pool * test/testdistcc.py: SimpleDistCC_Case.__init__: remove redundant code: logging has moved into comfychair.TestCase. * SimpleDistCC_Case: Allow subclasses to change lifetime of daemon or command used to start it. * By default daemon only lives 10s. For ThousandFold_Case and Concurrent_Case it needs to live up to 2 minutes. 2003-03-21 18:24 Martin Pool * test/testdistcc.py: NoDetachDaemon_Case: Shouldn't need --lifetime for this test. 2003-03-21 18:21 Martin Pool * test/testdistcc.py, NEWS: Specify limited lifetime when running daemon, so that if it is not cleaned up by the tests it will go away after a little while anyhow. 2003-03-21 18:18 Martin Pool * NEWS, configure.ac, src/dsignal.c: If we have strsignal(), then log the signal name rather than number when terminating. 2003-03-21 18:12 Martin Pool * src/dsignal.c: Also print a message when terminating on SIGALRM. 2003-03-21 18:11 Martin Pool * Makefile.in, src/distcc.h, src/dparent.c, src/dsignal.c: Split signal-handling code into new file dsignal.c 2003-03-21 17:56 Martin Pool * src/: daemon.c, distcc.h, dparent.c: Make sure lifetime limit applies even when the daemon detaches: after forking to dissociate from the session, reset the alarm clock. 2003-03-21 17:25 Martin Pool * test/testdistcc.py: NoHosts_Case: Cleanup to get it working with the new framework. 2003-03-21 16:27 Martin Pool * test/testdistcc.py: NoHosts_Case: Better log message. 2003-03-21 16:24 Martin Pool * test/testdistcc.py: NoDetachDaemon_Case: Make sure daemon is killed off. 2003-03-21 16:21 Martin Pool * test/comfychair.py: Update from Subversion 2003-03-21 16:21 Martin Pool * test/testdistcc.py: Move code for entering rundir into comfychair. * Change killing of daemon to be a cleanup rather than part of teardown. 2003-03-21 14:00 Martin Pool * src/: daemon.c, dopt.c, dparent.c, serve.c: Rename opt.h to dopt.h, to be consistent with dopt.c. 2003-03-21 13:59 Martin Pool * TODO: CCACHE_ERR_FD 2003-03-21 13:56 Martin Pool * Makefile.in: Remove "=distcheck" directory on successful completion. 2003-03-21 13:55 Martin Pool * Makefile.in: Include types.h in distribution. 2003-03-21 13:54 Martin Pool * Makefile.in, src/dopt.h, src/opt.h: Rename opt.h to dopt.h, to be consistent with dopt.c. 2003-03-21 13:46 Martin Pool * NEWS, src/daemon.c, src/dopt.c, src/opt.h: * Add new undocumented (heh) "--lifetime" option that causes the daemon to expire after a certain period. 2003-03-21 13:44 Martin Pool * test/comfychair.py: Doc. 2003-03-21 12:58 Martin Pool * src/sendfile.c: printf type correctness. 2003-03-21 12:51 Martin Pool * TODO: [no log message] 2003-03-21 12:34 Martin Pool * NEWS: types.h: New file, to give typedefs for missing systems types. Include this in files that need it. Move typedefs from random source files into here. * Add in_addr_t, which is int by default. 2003-03-21 12:34 Martin Pool * src/types.h: in_addr_t should perhaps be ulong by default. 2003-03-21 12:31 Martin Pool * src/: access.c, clinet.c, dopt.c, h_parsemask.c, srvnet.c, types.h: types.h: New file, to give typedefs for missing systems types. Include this in files that need it. Move typedefs from random source files into here. * Add in_addr_t, which is int by default. 2003-03-21 12:21 Martin Pool * configure.ac: Check for existence of sys/socket.h * Check for in_addr_t 2003-03-21 12:20 Martin Pool * src/srvnet.c: If socklen_t is missing, make it a size_t. 2003-03-21 12:14 Martin Pool * src/snprintf.h, NEWS: Fix incorrect config macro names: should be HAVE_DECL_ASPRINTF not HAVE_ASPRINTF_DECL. Fixes declaration warnings on Solaris. 2003-03-21 12:02 Martin Pool * NEWS: Should build on IRIX. 2003-03-21 11:58 Martin Pool * NEWS: Don't include Info file in the distribution. It's a bit redundant to ship the documentation in three forms (SGML, HTML, Info), and people can build it or download it if they want to. * Don't rebuild all Linuxdoc files for distribution, only the ones which need to be included. 2003-03-21 11:54 Martin Pool * Makefile.in: Don't include Info file in the distribution. It's a bit redundant to ship the documentation in three forms (SGML, HTML, Info), and people can build it or download it if they want to. * Don't rebuild all Linuxdoc files for distribution, only the ones which need to be included. 2003-03-19 09:34 Martin Pool * configure.ac: Change check for in_port_t, which exists on Solaris, but which isn't found in just sys/types.h and netinet/in.h. 2003-03-19 09:28 Martin Pool * src/ncpus.c: Try to fix BSD dcc_ncpus(). 2003-03-18 21:18 Martin Pool * src/ssh.c: piped_child: Update to take an argv[] array rather than a simple command so that we can avoid running a shell. 2003-03-18 18:15 Martin Pool * configure.ac: Check whether the C compiler supports inlining, etc. Needed for popt. 2003-03-18 17:47 Martin Pool * src/tempfile.c: Cast to int when calling printf. 2003-03-18 17:46 Martin Pool * src/snprintf.h: Add conditional declaration of vsnprintf. 2003-03-18 17:45 Martin Pool * src/ncpus.c: Add FreeBSD/OpenBSD/NetBSD implementation. 2003-03-18 17:36 Martin Pool * src/ncpus.c: Fix includes. 2003-03-18 17:35 Martin Pool * src/ncpus.c: Add a separate definition of dcc_ncpus for HP-UX (not tested), and URLs describing this. 2003-03-18 17:27 Martin Pool * src/ncpus.c, NEWS: Add credit to Dimitri PAPADOPOULOS-ORFANOS for reporting how to do this on various systems. 2003-03-18 17:25 Martin Pool * src/ncpus.c: Check for definition of _SC_NPROCESSORS_ONLN (linux), and _SC_NPROC_ONLN (Irix), and call the appropriate sysconf. 2003-03-18 17:21 Martin Pool * src/ncpus.c: Include prototypes for this file. 2003-03-18 17:20 Martin Pool * NEWS: Clean up some warnings on IRIX. 2003-03-18 17:20 Martin Pool * src/ncpu.c, src/ncpus.c, Makefile.in: Rename ncpu.c to ncpus.c to be consistent with the function name. 2003-03-18 17:18 Martin Pool * src/tempfile.c: Cast mode_t to int when passing to printf. 2003-03-18 17:17 Martin Pool * src/: rpc.c, tempfile.c: Include snprintf.h for systems that don't have these functions. 2003-03-18 17:15 Martin Pool * src/: exec.c: Cast pid_t to long when passing to printf. 2003-03-18 17:13 Martin Pool * src/trace.c: Update copyright. * Remove done TODOs. * Include snprintf.h to quieten warning on machines that don't have vsnprintf, such as IRIX. 2003-03-18 17:11 Martin Pool * NEWS, src/dparent.c: Print number of online CPUs when daemon starts up. 2003-03-18 17:09 Martin Pool * src/distcc.h: Add prototype for dcc_ncpus. 2003-03-18 17:04 Martin Pool * Makefile.in, src/ncpu.c: Add basic code to detect the number of online processors, at least on Linux. 2003-03-18 16:56 Martin Pool * NEWS: Reorder news items. 2003-03-18 15:21 Martin Pool * TODO: Add note to try out masquerade with make-kpkg. 2003-03-18 14:27 Martin Pool * patches/daemon-address-binding.diff: Patch from Neil Mansilla: * Add --address option to daemon, to make it bind only a particular address. I don't know if this is bloat (should be done through inetd?) or a good idea. Therefore not merged yet. 2003-03-18 14:24 Martin Pool * test/comfychair.py: Decode waitstatus values when a command fails. 2003-03-17 22:25 Martin Pool * doc/release-names.txt: [no log message] 2003-03-14 15:49 Martin Pool * TODO: Update status: * Kernel 2.5 bug * SQMS scheduler * --allow is done * Distributed caching 2003-03-13 17:33 Martin Pool * NEWS: Note that SIGTERM handling race for server is now fixed. 2003-03-13 17:31 Martin Pool * test/comfychair.py: Merge from svn r30 2003-03-13 17:29 Martin Pool * patches/distccd-clean-path.diff: Draft patch from Wayne Davison to try to keep masquerade connections off the server's $PATH. 2003-03-13 17:28 Martin Pool * patches/: compression.patch, swhite-lzo-compress.diff: Updated draft patch from Stephen White to do LZO compression. 2003-03-13 17:27 Martin Pool * patches/distcc-ethereal.diff: Draft patch to Ethereal to decode/dissect distcc connections. 2003-03-12 19:08 Martin Pool * src/dparent.c: Fix small signal handling race that would occasionally cause distccd not to exit when signalled. Pointed out by Vance Lankhaar, solution advice from Andrew Tridgell. The problem was that a signal could arrive after we checked the global indicator, but before entering accept(). So the daemon would need to wait for the accept to complete before it could respond to the signal. Since the daemon only needs to do very simple cleanup, we now simply do it in line in the signal handler and never return. 2003-03-12 18:56 Martin Pool * src/dparent.c: FIXME about bug reported by Vance: the daemon sometimes doesn't exit on receipt of SIGTERM, which makes the test suite hang. 2003-03-12 17:12 Martin Pool * test/testdistcc.py: assert_regexp renamed to assert_re_search 2003-03-12 17:09 Martin Pool * test/testdistcc.py: Fix incorrect regexp assertion 2003-03-12 16:51 Martin Pool * test/testdistcc.py: explainFailure, fail, assertEquals, assertNotEqual, assertReMatch: these are now present in ComfyChair and don't need to be in this file. 2003-03-12 16:40 Martin Pool * test/comfychair.py: Update from Subversion r24: ------------------------------------------------------------------------ rev 24: mbp | 2003-03-12 16:32:53 +1100 (Wed, 12 Mar 2003) | 4 lines * Fix calls to explain_failure() * comfychair.main: If test names are specified, run them. ------------------------------------------------------------------------ rev 23: mbp | 2003-03-12 16:28:29 +1100 (Wed, 12 Mar 2003) | 2 lines * Fix --help message. 2003-03-12 16:37 Martin Pool * NEWS: Many internal updates to ComfyChair framework. 2003-03-12 16:11 Martin Pool * test/testdistcc.py: Change to using new ComfyChair.main() method, rather than implementing it by hand. 2003-03-12 15:43 Martin Pool * test/comfychair.py: Import updated ComfyChair from Subversion: renamed methods, new main() method, etc. 2003-03-12 15:42 Martin Pool * test/testdistcc.py: SimpleDistCC_Case.__init__ needs to call the base constructor method. * Update for renamed methods in latest ComfyChair. 2003-03-11 17:42 Martin Pool * doc/release-names.txt: [no log message] 2003-03-10 15:34 Martin Pool * src/util.c: IRIX might need sys/time.h before sys/resource.h 2003-03-10 15:13 Martin Pool * src/util.c: Check for sys/resource.h 2003-03-10 15:10 Martin Pool * configure.ac: Check for sys/resource.h 2003-03-10 15:08 Martin Pool * configure.ac: Check for getrusage. 2003-03-10 14:12 Martin Pool * NEWS: Give credit for masquerade mode. 2003-03-10 13:46 Martin Pool * configure.ac: Test for getwd and getcwd 2003-03-10 10:58 Martin Pool * Makefile.in: Remove ssh.o from client for the time being. 2003-03-10 10:16 Martin Pool * patches/: distcc-1.2.1-masquerade.patch, masquerade.patch: Remove merged 'masquerade' patch. 2003-03-10 10:07 Martin Pool * src/io.c: sendfile.h no longer needed here. Thanks to Wayne Davison. 2003-03-09 20:28 Martin Pool * linuxdoc/distcc.sgml: Re-add "if your disks are too empty". 2003-03-09 10:43 Martin Pool * configure.ac: Advance version to 1.3cvs. 2003-03-09 10:14 Martin Pool * Makefile.in: Add ssh module to build. 2003-03-08 22:48 Martin Pool * .cvsignore: Ignore =distcheck directory 2003-03-08 21:53 Martin Pool * NEWS: Note about merged masquerade mode. * Reindent stuff. 2003-03-08 21:47 Martin Pool * doc/release-names.txt: [no log message] 2003-03-08 10:43 Martin Pool * src/sendfile.c: Fix cast in call to sprintf for platforms where ssize_t != int. Found on Alpha Linux in the hp Compaq testdrive. 2003-03-08 10:39 Martin Pool * src/implicit.c: Doc 2003-03-08 10:29 Martin Pool * NEWS: Fix cast in call to sprintf for platforms where ssize_t != int. Found on Alpha Linux in the hp Compaq testdrive. 2003-03-05 13:02 Martin Pool * configure.ac, linuxdoc/distcc.sgml, src/distcc.c, src/exec.c, src/exec.h, src/serve.c, src/util.c, src/util.h: masquerade patch from Wayne Davison: * Add 'masquerade' option, where a link to distcc is created in e.g. /usr/lib/distcc/bin/cc so that it can catch calls to 'cc'. * Check for getwd in configure * Update manual to document 'masquerade' * Update manual to say default port is 3632. * Document /MAX syntax in --help. 2003-03-03 12:42 Martin Pool * doc/release-names.txt: [no log message] 2003-03-02 10:31 Martin Pool * configure.ac: Update for release. 2003-03-02 09:52 Martin Pool * NEWS: Update for release. 2003-03-01 23:54 Martin Pool * README.popt: URL for popt. 2003-03-01 23:49 Martin Pool * src/: setuid.c, setuid.h: Fix constness of opt_user. 2003-03-01 09:12 Martin Pool * src/lock.c, NEWS: SUSv3 says that locking functions can return EACCES for contention. HP-UX does this; perhaps Cygwin does too. 2003-02-28 14:18 Martin Pool * configure.ac, NEWS: Check existence of ctype.h. Pointed out by Tom Matelich. 2003-02-28 14:15 Martin Pool * patches/masquerade.patch: Masquerade patch from Wayne Davison 2003-02-28 10:45 Martin Pool * NEWS: Header for 1.2.3 release. * dcc_make_lock_filename: Windoze can't handle ':' in filenames. Pointed out by Heiko Elger. 2003-02-28 10:41 Martin Pool * src/lock.c: dcc_make_lock_filename: Windoze can't handle ':' in filenames. Pointed out by Heiko Elger. 2003-02-28 10:40 Martin Pool * src/lock.c: Doxygen janitor 2003-02-28 08:02 Martin Pool * src/lock.c: Fix unreachable trace message. Thanks to Dimitri Papadopoulos-Orfanos. 2003-02-27 16:07 Martin Pool * Makefile.in: analog-resolve: Tweak jdresolve invocation 2003-02-27 15:58 Martin Pool * Makefile.in: analog-resolve: Tweak jdresolve invocation 2003-02-27 13:23 Martin Pool * patches/n_cpus.txt: n_cpus.txt Notes on determining NCPUs, from Dimitri PAPADOPOULOS 2003-02-27 13:14 Martin Pool * patches/connect-timeout-02.diff: connect-timeout-02.diff Connection timeout patch from Oscar Esteban 2003-02-27 13:09 Martin Pool * patches/connect-timeout.diff: connect-timeout.diff Connection timeout patch from Oscar Esteban 2003-02-27 12:52 Martin Pool * Makefile.in, OLDNEWS: Remove empty/dead OLDNEWS file. 2003-02-27 12:36 Martin Pool * NEWS: Add missing release comments. 2003-02-27 12:32 Martin Pool * NEWS: Add release date. 2003-02-27 12:20 Martin Pool * test/testdistcc.py: Doc 2003-02-27 12:18 Martin Pool * Makefile.in: Be more selective in uploading linuxdoc files. 2003-02-27 11:52 Martin Pool * Makefile.in: Make distcheck should use $MAKE. 2003-02-27 11:50 Martin Pool * Makefile.in: Distribute the uncompressed info file: this makes patch across the source distribution work, and possibly helps bzip2 compress the whole distribution. 2003-02-27 11:38 Martin Pool * src/sendfile.c: Add HP-UX implementation of sys_sendfile, based on a note from Tom Matelich and the manual. Not tested on an HP-UX machine yet. 2003-02-27 11:17 Martin Pool * Makefile.in: clirpc.h: New header 2003-02-27 11:14 Martin Pool * Makefile.in, NEWS: Add a simple distcheck target. 2003-02-27 11:10 Martin Pool * Makefile.in: Remove deleted tests from $(test_SOURCE) 2003-02-27 11:06 Martin Pool * Makefile.in: Fix command to remove dist dir before building. 2003-02-27 10:25 Martin Pool * src/access.c: The FreeBSD manual suggests might be needed here to make in_addr_t work. 2003-02-27 10:20 Martin Pool * configure.ac: Check for stdint.h 2003-02-27 10:18 Martin Pool * doc/release-names.txt: [no log message] 2003-02-27 10:17 Martin Pool * NEWS: Call this release 1.2.2. * Note about updated Makefile. 2003-02-26 16:36 Martin Pool * test/: basecases.py, testdistcc.py: Move basecases back into testdistcc 2003-02-26 12:35 Martin Pool * test/: setuidcases.py, testdistcc.py: Splitting tests across several files seems not to be a good idea at the moment. It doesn't really make it easier to navigate. A new factoring is desirable. * setuidcases.py merged back into testdistcc.py 2003-02-26 12:33 Martin Pool * test/: EmptySource.py, ScanArgs.py, testdistcc.py: Splitting tests across several files seems not to be a good idea at the moment. It doesn't really make it easier to navigate. A new factoring is desirable. * EmptySource.py, ScanArgs.py merged back into testdistcc.py 2003-02-26 12:28 Martin Pool * test/ScanArgs.py: Remove RunCmd_Case, whose functionality has now migrated up into ComfyChair. 2003-02-26 12:27 Martin Pool * test/.cvsignore: Ignore ./testtmp/ if it happens to be here. 2003-02-26 12:27 Martin Pool * test/testdistcc.py: Remove RunCmd_Case, whose functionality has now migrated up into ComfyChair. * Add GPL. 2003-02-26 12:25 Martin Pool * test/basecases.py: Remove RunCmd_Case, whose functionality has now migrated up into ComfyChair. 2003-02-26 12:22 Martin Pool * test/comfychair.py: runCmdNoWait: add missing "import os" 2003-02-26 12:21 Martin Pool * test/comfychair.py: Copy from distcc HEAD * Make sure to print out any errors that happen while running tests, not only the ComfyChair-specific exceptions. 2003-02-26 12:18 Martin Pool * test/comfychair.py: Merge from tpot's comfychair HEAD checkin: * report failure to construct * add skip_on_noexec to runCmdUnchecked 2003-02-26 12:13 Martin Pool * test/comfychair.py: Add GPL. * Add runCmdNoWait to run things in the background. * Don't use '+=' to support Python 1.5. 2003-02-26 11:52 Martin Pool * NEWS: ./configure should not be removed by distclean, only by maintainer-clean. * Make Makefile work with pmake 2003-02-26 11:51 Martin Pool * Makefile.in: Remove '$^' variable, which doesn't work with pmake. 2003-02-26 11:47 Martin Pool * Makefile.in: ./configure should not be removed by distclean, only by maintainer-clean. 2003-02-26 11:44 Martin Pool * Makefile.in: Change to old-style implicit rules, in the hope of getting this to compile on non-GNU Make. 2003-02-25 23:29 Martin Pool * src/ssh.c: More cleanups/merges. Still not working. 2003-02-25 23:14 Martin Pool * src/ssh.c: Merge more code from rsync. Still not working. 2003-02-25 23:10 Martin Pool * configure.ac: Add socketpair test from rsync. 2003-02-25 22:50 Martin Pool * src/ssh.c: ssh.c Check in non-working skeleton ssh code from rsync and cvs 2003-02-25 22:37 Martin Pool * src/clinet.c: Doc 2003-02-25 22:36 Martin Pool * src/trace.h: Don't use __FUNCTION__ if not building on gnuc. 2003-02-25 22:26 Martin Pool * configure.ac, NEWS: Check for inet_aton in libresolv, which might fix Solaris 2.6. 2003-02-25 22:23 Martin Pool * src/distcc.c: Clear up unused vars * Doc 2003-02-25 22:22 Martin Pool * NEWS, src/distcc.c: Avoid repeatedly locking localhost when it's chosen from the host list, because we don't have reentrant locks on Cygwin. 2003-02-25 22:09 Martin Pool * src/distcc.c: Typo 2003-02-25 22:08 Martin Pool * Makefile.in, src/clirpc.c, src/clirpc.h, src/distcc.c: Split client RPC code into its own file to slim distcc.c. 2003-02-25 22:04 Martin Pool * patches/distcc-1.2.1-masquerade.patch: Patch from Wayne Davison to masquerade as cc. 2003-02-25 22:01 Martin Pool * src/distcc.c: Doc 2003-02-25 21:49 Martin Pool * configure.ac: Bump version to 1.3cvs 2003-02-25 21:26 Martin Pool * .cvsignore: Ignore linbot-report. 2003-02-25 21:25 Martin Pool * Makefile.in: Delete directory used to make distribution tarball before starting to build it. 2003-02-25 21:23 Martin Pool * TODO: Notes about asprintf and Linuxdoc. 2003-02-25 16:59 Martin Pool * NEWS: Note about libiberty redaction. 2003-02-25 16:57 Martin Pool * NEWS, configure.ac: Update for 1.2.1 release. 2003-02-25 16:51 Martin Pool * Makefile.in: Fix typo 2003-02-25 16:48 Martin Pool * src/snprintf.c: Quieten compiler warning. 2003-02-25 16:47 Martin Pool * configure.ac: Also check for snprintf 2003-02-25 16:38 Martin Pool * src/arg.c: Fix small memory leak. 2003-02-25 16:33 Martin Pool * src/exec.c: Remove dead function dcc_close_extra_fds. 2003-02-25 16:28 Martin Pool * Makefile.in: Don't use "python -V" because it apparently doesn't work on 1.5. Just look directly in sys.version. 2003-02-25 16:14 Martin Pool * Makefile.in: Print Python version before running tests to help in debugging remote problems. 2003-02-25 16:08 Martin Pool * test/testdistcc.py: Remove unnecessary 'unittest' import 2003-02-25 16:07 Martin Pool * test/testdistcc.py, NEWS: Return code from running the tests now indicates whether they worked or not. 2003-02-25 16:06 Martin Pool * test/comfychair.py: Refactor function * comfychair.runtests now returns a value that can be returned from system.exit 2003-02-25 15:53 Martin Pool * test/testdistcc.py: Remove += operator not supported in old Pythons. 2003-02-25 15:22 Martin Pool * test/testdistcc.py: Don't use fn(*tup) calling convention, because it's not supported in earlier Python versions. Use apply instead. 2003-02-25 15:18 Martin Pool * configure.ac: Don't worry about -Winline, because nothing in distcc is explicitly inlined. 2003-02-25 15:14 Martin Pool * DEPENDENCIES: We need autoconf >=2.53 2003-02-25 15:13 Martin Pool * configure.ac: Check for vsnprintf as well. 2003-02-25 15:06 Martin Pool * Makefile.in: Make sure snprintf.o actually gets linked in. 2003-02-25 11:28 Martin Pool * src/lock.c: Include local declarations for asprintf if necessary. 2003-02-25 11:27 Martin Pool * Makefile.in, NEWS, configure.ac, src/h_hosts.c, src/hosts.c, src/lock.c, src/tempfile.c, src/trace.c, src/where.c: Remove libiberty asprintf. Might fix problems with headers on Solaris and BSD. * Add asprintf etc from Samba HEAD. * Define _GNU_SOURCE in CPPFLAGS so that it is set for autoconf tests. * Add configure test for C99-compliant vsnprintf from Samba HEAD. 2003-02-25 11:07 Martin Pool * src/: snprintf.c, snprintf.h: Add *printf implementation from Samba HEAD. 2003-02-24 16:39 Martin Pool * configure.ac: Remove -Wredundant-decls, because it causes noise with some system headers. 2003-02-24 16:35 Martin Pool * configure.ac: Remove -W options that are implied by -Wall. 2003-02-24 16:29 Martin Pool * Makefile.in: Include %.o target for Makes that have a wierd built-in definition. 2003-02-24 16:24 Martin Pool * NEWS: Add ansidecl.h from libiberty (from gdb-5.3) 2003-02-24 16:20 Martin Pool * Makefile.in: Add ansidecl.h from libiberty (from gdb-5.3) 2003-02-24 16:15 Martin Pool * NEWS: Update NEWS 2003-02-24 16:12 Martin Pool * src/io.c: Remove redundant inclusion of assert.h 2003-02-24 16:10 Martin Pool * configure.ac, Makefile.in: Try to find Python during configuration. 2003-02-24 15:56 Martin Pool * Makefile.in: Allow installation to complete even if the tools to build Linuxdoc are missing. 2003-02-24 15:05 Martin Pool * Makefile.in: installcheck needs to look in the build directory as well as in the installed path to find the harness programs. In the future perhaps there ought to be a subset of tests that skips the harnesses. 2003-02-24 14:58 Martin Pool * Makefile.in: Add "installcheck" target that can be called by the buildfarm. 2003-02-24 14:48 Martin Pool * configure.ac: Check autoconf >= 2.53 * Don't use AC_CONFIG_LIBOBJ_DIR because it's not in ac 2.53 2003-02-24 14:39 Martin Pool * configure.ac: FIXME 2003-02-24 13:59 Martin Pool * autogen.sh: Merge back from the samba/HEAD autogen.sh 1.2, which jerry updated to work on more systems, including RH7.2. 2003-02-24 13:33 Martin Pool * NEWS: foo 2003-02-24 13:19 Martin Pool * NEWS: foo 2003-02-24 13:15 Martin Pool * NEWS: Dummy checkin to test build farm. 2003-02-24 11:54 Martin Pool * NEWS: Dummy checkin to test build farm. 2003-02-24 09:52 Martin Pool * configure.ac: Update version to 1.2.1cvs. 2003-02-22 20:29 Martin Pool * NEWS: Get ready for 1.2 release. 2003-02-22 20:22 Martin Pool * configure.ac: Set bug report address to the list, not me. 2003-02-22 20:21 Martin Pool * configure.ac: Get ready for 1.2 release. 2003-02-22 12:55 Martin Pool * Makefile.in: Remove Docbook from distribution. 2003-02-22 12:53 Martin Pool * Makefile.in: filename.h: New file. 2003-02-22 12:41 Martin Pool * src/: arg.c, cpp.c, distcc.c, distcc.h, exec.c, exec.h, filename.c, filename.h, hosts.c, implicit.c, lock.c, serve.c, strip.c, trace.h: Cleanups to fix various gcc warnings. 2003-02-22 12:20 Martin Pool * src/distcc.h: Remove redundant decls. 2003-02-22 12:19 Martin Pool * configure.ac: Turn on more compiler warnings. 2003-02-22 12:16 Martin Pool * TODO: Turn on more compiler warnings. * Note about statistics. 2003-02-22 12:07 Martin Pool * src/hosts.c: Refactor code into new function dcc_parse_localhost. 2003-02-22 11:58 Martin Pool * src/hosts.c: Fix comments 2003-02-22 11:56 Martin Pool * NEWS: Roll back to Linuxdoc for the manual. 2003-02-22 11:37 Martin Pool * linuxdoc/distcc.sgml: Ask people to report bugs to the mailing list, not to me. 2003-02-22 11:35 Martin Pool * linuxdoc/distcc.sgml: distcc.sgml Resurrect Linuxdoc manual 2003-02-22 11:25 Martin Pool * Makefile.in: Use rsync --delete when uploading manual to delete unneeded files. 2003-02-22 11:12 Martin Pool * Makefile.in: Roll back to Linuxdoc for the manual. Docbook tools seem to be still too unstable. 2003-02-21 11:54 Martin Pool * Makefile.in: Add "links" web page 2003-02-21 10:13 Martin Pool * patches/distcc-line3.diff: Patch from Tim Janik to absolutize #line directives. 2003-02-21 10:08 Martin Pool * doc/lca2003/slides/.cvsignore: Ignore built Postscript 2003-02-21 10:05 Martin Pool * Makefile.in: Include additional Python files in distribution. 2003-02-19 13:09 Martin Pool * test/testdistcc.py: By default only one job is run locally now. 2003-02-18 17:55 Martin Pool * NEWS: Postscript and PDF turned off for now. 2003-02-18 17:44 Martin Pool * Makefile.in: Add target to build "nochunks" (one big page) manual. 2003-02-18 17:22 Martin Pool * Makefile.in: Add upload-usermanual target. 2003-02-18 15:15 Martin Pool * Makefile.in: Put usermanual files correctly into distribution. 2003-02-18 15:14 Martin Pool * Makefile.in: Add targets/rules to build, distribute and install the Docbook-XML manual. 2003-02-18 14:37 Martin Pool * doc/aoss2002/slides/: README.aoss2002, aoss4.mgp, flow.dia, flow.png: Move AOSS2002 slides 2003-02-14 15:40 Martin Pool * TODO: Add note about slow networks. 2003-02-13 18:10 Martin Pool * src/where.c: Don't use XMIT locks for localhost, because there is no transmission phase. 2003-02-13 18:00 Martin Pool * src/distcc.c: Change completion message for remote compile to "compile on FOO" rather than "gcc on FOO". Easier to grep for. 2003-02-13 17:56 Martin Pool * src/hosts.c: /N syntax now *sets* the number of slots, rather than setting a multiplier. * Default for localhost is now 1. 2003-02-13 17:13 Martin Pool * src/hosts.c: Add HOST/NSLOTS syntax to limit number of tasks. Patch from Rusty. 2003-02-13 16:50 Martin Pool * src/where.c: dcc_lock_one: New implementation: The previous code was far too heavily biased towards the first machine, because it tried to find any empty CPU slot there even if other machines were idle. Now, the outer loop is the slot number, and we try all hosts with at least that many slots. We acquire the CPU lock before getting the XMIT lock. 2003-02-13 16:27 Martin Pool * src/where.c: Typo: didn't set CPU slot properly. 2003-02-13 16:19 Martin Pool * src/: distcc.c, lock.c, where.c, where.h: Update new scheduler to use two locks: one controlling access to the remote machine's CPU, and one serializing the network connection to the machine to avoid inadvertent synchronization. 2003-02-13 15:52 Martin Pool * TODO: Add compiler warnings from Daniel Veilard 2003-02-12 18:24 Martin Pool * test/testdistcc.py: Import new setuidcases module. 2003-02-12 18:12 Martin Pool * test/setuidcases.py: New file to check --user option. 2003-02-12 18:08 Martin Pool * test/comfychair.py: require(), require_root(): New functions that causes a test to be skipped unless particular conditions are met. 2003-02-12 17:46 Martin Pool * test/comfychair.py: Merge from comfychair CVS 2003-02-11 11:18 Martin Pool * src/lock.c: Fixme. 2003-02-07 21:17 Martin Pool * src/: distcc.c, where.c, where.h: Rename dcc_pick_buildhost to dcc_pick_host_from_env 2003-02-05 23:11 Martin Pool * TODO: [no log message] 2003-02-05 23:07 Martin Pool * Makefile.in: Don't delete config.status with plain "make clean", because it's really at the same level as the Makefile. 2003-02-05 23:05 Martin Pool * src/bulk.c, NEWS: Add O_BINARY bit needed for Cygwin. Based on a patch from Helind. 2003-02-05 22:43 Martin Pool * DEPENDENCIES: Note about dietlibc. 2003-02-05 22:41 Martin Pool * Makefile.in: Update "*clean" targets: cleaning should remove configure state files; maintainer-clean should remove all autoconf files that can be regenerated. From a patch by Paul Russell. 2003-02-05 21:52 Martin Pool * TODO: Note about manpages. 2003-02-05 19:14 Martin Pool * src/distcc.h: opt_allowed needs to be declared extern. Found by tcc. 2003-02-05 19:11 Martin Pool * TODO: [no log message] 2003-02-05 19:10 Martin Pool * src/io.c: Change assert to trace call to make dietlibc happy 2003-02-05 19:08 Martin Pool * src/clinet.c: fixme 2003-02-04 23:02 Martin Pool * src/where.c: Cleanup comments. 2003-02-04 22:58 Martin Pool * NEWS, src/bulk.c, src/bulk.h, src/distcc.c, src/serve.c: Show timing on transmission of DOTI and DOTO files. 2003-02-04 22:48 Martin Pool * src/bulk.c: Remove dcc_r_fifo, which is no longer called because we no longer support feeding the compiler from a fifo. 2003-02-04 19:58 Martin Pool * Makefile.in, src/bulk.c, src/bulk.h, src/distcc.c, src/serve.c: Show transfer rate for transmitted files. 2003-02-04 19:55 Martin Pool * src/: timeval.c, timeval.h: Add GNU function for calculating the difference between timevals. 2003-02-04 19:29 Martin Pool * doc/release-names.txt: [no log message] 2003-02-04 19:21 Martin Pool * configure.ac: Add ./lib to include path so libiberty.h can be found. 2003-02-03 12:50 Martin Pool * src/rpc.h: Doc 2003-02-03 12:49 Martin Pool * TODO: [no log message] 2003-02-03 01:15 Martin Pool * doc/new-scheduler.txt: Notes on new scheduler 2003-02-03 00:59 Martin Pool * NEWS: Describe new scheduling algorithm. 2003-02-03 00:44 Martin Pool * src/where.c: Better message 2003-02-03 00:43 Martin Pool * src/distcc.c: Fixme 2003-02-03 00:28 Martin Pool * src/where.c: Doc 2003-02-03 00:27 Martin Pool * src/distcc.c: Hold transmit lock only while sending request. 2003-02-03 00:27 Martin Pool * src/where.c: Doc 2003-02-03 00:27 Martin Pool * src/: lock.c, lock.h: (dcc_unlock): New function. 2003-02-03 00:13 Martin Pool * src/: distcc.c, lock.c, lock.h, where.c, where.h: Lock functions pass back their fd so that it can be released later. * (dcc_lock_host): Clean up error handling. 2003-02-03 00:06 Martin Pool * src/lock.h: Add lock_fd parameter to dcc_lock_host and dcc_lock_local functions 2003-02-03 00:04 Martin Pool * src/lock.c: Doc 2003-02-03 00:04 Martin Pool * src/lock.c: Remove redundant dcc_get_tempdir call. 2003-02-03 00:03 Martin Pool * src/lock.c: Split lockfile creation into dcc_open_lockfile 2003-02-03 00:01 Martin Pool * src/: where.c, where.h: Document locking system. * Add a "lockname" parameter to allow for multiple locks in the future. * WORK IN PROGRESS: Start moving towards new transmission-based locking, where we hold the lock only while sending. Not done yet. 2003-02-03 00:00 Martin Pool * src/: lock.c, lock.h: Document locking system. * Add a "lockname" parameter to allow for multiple locks in the future. 2003-02-02 23:44 Martin Pool * Makefile.in: Remove linuxdoc targets from the Makefile to allow for transition to Docbook. Docbook manual is not built yet because of issues with Debian's xsltproc. 2003-02-02 23:34 Martin Pool * TODO: [no log message] 2003-02-02 23:31 Martin Pool * Makefile.in: Add README.libiberty to distributed files. 2003-02-02 23:31 Martin Pool * README.libiberty: Check in some files from libiberty. 2003-02-02 23:30 Martin Pool * src/lock.c: (dcc_lock_host): Add doc. Change "already locked" to less ambiguous "%s is busy". Update to use standard exit codes. 2003-02-02 23:24 Martin Pool * src/exitcode.h: Add EXIT_BUSY. 2003-02-02 22:56 Martin Pool * src/lock.c: Use libiberty for asprintf(). * (dcc_make_lock_filename): Rewrite to use asprintf() rather than a fixed-length buffer. Safer and simpler. Lock filenames now take into account the port as well as the hostname, and it supports ssh schemes. 2003-02-02 22:54 Martin Pool * NEWS: [no log message] 2003-02-02 22:48 Martin Pool * Makefile.in: Include libiberty source in distribution. 2003-02-02 22:48 Martin Pool * configure.ac: Add lib/ directory * Check for asprintf() and vasprintf() and replace them if not present. 2003-02-02 22:06 Martin Pool * TODO: Notes on Docbook. * Notes on a minimal gcc for clients. 2003-02-02 16:30 Martin Pool * linuxdoc/: distcc.sgml, footer.html: Remove Linuxdoc documentation now that it's been converted to Docbook XML 2003-02-02 16:30 Martin Pool * NEWS: Note conversion of user manual. 2003-02-02 16:18 Martin Pool * patches/timj-line1.diff: Patch from Tim Janik to post-process the preprocessor output to absolutify file names. It works and it's nicely written, but I'm not yet convinced that the benefit is justified. 2003-02-02 14:38 Martin Pool * src/.cvsignore: Don't ignore .d and .i files, since they shouldn't be generated anymore. 2003-02-02 14:37 Martin Pool * Makefile.in, contrib/distcc-absolutify, contrib/netpwd, contrib/stage-cc-wrapper.patch: Additional contributed scripts by Alexandre Oliva useful in building gcc using distcc. From his mail of 14 Aug 2002. 2003-01-31 15:03 Martin Pool * src/where.c: Doc 2003-01-31 11:48 Martin Pool * analog/.cvsignore: Ignore generated files. 2003-01-31 11:17 Martin Pool * TODO: Notes on corks, scheduling, and tcp options. 2003-01-31 10:56 Martin Pool * TODO: Notes about scheduling from BBQ 2003-01-31 10:42 Martin Pool * TODO: Note about #pragma implementation 2003-01-29 15:52 Martin Pool * linuxdoc/distcc.sgml: Grammar fixes. 2003-01-29 12:14 Martin Pool * src/dopt.c: (distccd_show_usage): Remove vestigial argument to printf * (distccd_parse_options): Fix return code handling * Doc 2003-01-29 00:52 Martin Pool * Makefile.in: Typo 2003-01-29 00:50 Martin Pool * test/testdistcc.py: TODO 2003-01-29 00:49 Martin Pool * src/: access.h, distcc.h, dopt.c, srvnet.c: Add --allow, -a option to distccd. Build up a list of allowed client addresses. Check against them when a client connects; drop the connection if it's not allowed. 2003-01-29 00:46 Martin Pool * NEWS: Note new --allow option. 2003-01-29 00:19 Martin Pool * src/: access.c, access.h, h_parsemask.c: Add code to actually check whether access ought to be allowed. 2003-01-29 00:08 Martin Pool * src/: access.c, access.h, h_parsemask.c: Start adding IP-based access control. So far, a function to parse matchers like 10.0.0.0/8. 2003-01-29 00:07 Martin Pool * Makefile.in, .cvsignore: Add new h_parsemask test harness. 2003-01-29 00:02 Martin Pool * doc/lca2003/slides/: .cvsignore, distcc-lca2003.mgp, flow.dia, flow.png: Add LCA2003 slides. 2003-01-28 23:14 Martin Pool * Makefile.in: Add access.c and access.h 2003-01-28 19:57 Martin Pool * NEWS, src/exec.c: * Use putenv() rather than setenv() to fit into SUSv2 and work on Solaris 8. Pointed out by Dimitri Papadopoulos. 2003-01-28 19:52 Martin Pool * test/testdistcc.py: TODO 2003-01-28 01:24 Martin Pool * src/access.c: Empty file 2003-01-28 01:21 Martin Pool * src/lock.c: Doc 2003-01-28 01:19 Martin Pool * src/dopt.c: Fix string syntax problem. 2003-01-28 01:18 Martin Pool * configure.ac: Version to 1.2cvs 2003-01-28 01:18 Martin Pool * src/help.c: Please send bugs to the mailing list 2003-01-28 01:17 Martin Pool * src/help.c: Update copyright 2003-01-28 01:06 Martin Pool * Makefile.in: Add missing Python source. 2003-01-28 01:05 Martin Pool * TODO: [no log message] 2003-01-28 01:01 Martin Pool * src/: dparent.c, daemon.c: srvnet.h: new header 2003-01-28 00:56 Martin Pool * NEWS, configure.ac: Update for 1.1 2003-01-28 00:52 Martin Pool * NEWS: Updates to manual 2003-01-28 00:21 Martin Pool * analog/extract_version_downloads.py: Simple script to show the number of downloads of each version. 2003-01-27 23:23 Martin Pool * src/lock.c: Doc 2003-01-27 23:19 Martin Pool * TODO: Note about taking host list from a file. 2003-01-27 23:16 Martin Pool * src/distcc.h: New srvnet.h header 2003-01-27 23:16 Martin Pool * patches/andresen-gcc-wrapper-r2.tbz2: Patch from Eric Andresen for Gentoo bug #13897 to add some kind of wrapper. 2003-01-27 23:13 Martin Pool * src/distcc.c: Doxygen cleanups 2003-01-27 23:11 Martin Pool * src/dparent.c: Just refuse root once at the top level of distccd. We don't support binding reserved ports so there's no need to do it any later as far as I can see. 2003-01-27 23:06 Martin Pool * src/dopt.c: Doc * Add new --user option. Warning is printed if this is used when not started by root. * Sort option table into alphabetical order. 2003-01-27 23:03 Martin Pool * src/: exec.h, exec.c: Doc 2003-01-27 23:01 Martin Pool * src/exitcode.h: Give the exitcode enum a name * Add EXIT_SETUID_FAILED and EXIT_ACCESS_DENIED 2003-01-27 22:59 Martin Pool * src/hosts.h: Fix Doxygen glitch 2003-01-27 22:58 Martin Pool * src/io.c: Split sendfile wrappers out into src/sendfile.c 2003-01-27 22:55 Martin Pool * src/: setuid.c, setuid.h: New code for discarding privileges when run by root. 2003-01-27 22:54 Martin Pool * src/serve.c: src/srvnet.h: New header * Log client name (and in the future, check access) very early in connection handling. * Doc. 2003-01-27 22:53 Martin Pool * src/trace.h: Update Doxygen. 2003-01-27 22:50 Martin Pool * src/util.h: Move srvnet functions to srvnet.h 2003-01-27 22:41 Martin Pool * src/util.c: Message when exiting should always just be level 'info'. * Just show 4 decimal places in time measurements. Higher than that may not be very meaningful. 2003-01-27 22:36 Martin Pool * src/srvnet.c: src/srvnet.h: New header * Doc * Prepare for IP access-control checks 2003-01-27 22:35 Martin Pool * src/srvnet.h: src/srvnet.h: New header 2003-01-27 22:33 Martin Pool * src/sendfile.c: Move sendfile support into sendfile.c * Doc * Better handling of unsupported systems 2003-01-27 22:30 Martin Pool * Makefile.in: src/sendfile.c: Split sendfile into a separate source file * src/setuid.c, src/setuid.h: Add new ability to change persona when started by root * src/srvnet.h: Move server-side network functions to their own file. 2003-01-27 22:28 Martin Pool * src/daemon.c: Update Doxygen tags * Remove unneeded headers * Discard root privileges if we have them. 2003-01-27 22:27 Martin Pool * src/: arg.c, clinet.c: Update Doxygen tags 2003-01-27 22:25 Martin Pool * NEWS: tcpwrappers isn't in after all, because it's poorly documented and I'm not convinced it's a good fit for distccd. For example, it can only normally be configured by root, but we want to make sure that distccd can be installed and run by ordinary users. 2003-01-27 22:24 Martin Pool * bench/: Build.py, Project.py: Better messages while build is in progress. 2003-01-27 22:23 Martin Pool * bench/ProjectDefs.py: Point at glibc 2.3.1 rather than 2.3 in the hope that this will work better. (It doesn't build yet unfortunately.) 2003-01-27 22:21 Martin Pool * doc/release-names.txt: [no log message] 2003-01-27 22:21 Martin Pool * README.packaging: Please use shlibs * Please use proper gcc names 2003-01-27 22:18 Martin Pool * configure.ac: Doc * Fix help string for --with-included-popt * Some cleanups * Look for setgroups() 2003-01-27 22:17 Martin Pool * NEWS, OLDNEWS: Update NEWS for recent commits * Keep all change notes in the NEWS file per GNU standards. OLDNEWS is now empty. 2003-01-27 22:15 Martin Pool * README: Update performance for current project status 2003-01-27 22:12 Martin Pool * TODO: Many TODO updates. 2003-01-27 22:06 Martin Pool * test/testdistcc.py: Doc 2003-01-27 21:49 Martin Pool * .cvsignore, Doxyfile: Add Doxygen configuration. Not called from Makefile. 2003-01-27 21:35 Martin Pool * linuxdoc/distcc.sgml: Just show CVS date, not version. * Update to version 1.1. * Update: distccd now sends error messages back to the client as well as to its local log file. * Remove "author" section left over from man page. * Describe --verbose option. * Add description of new EXIT_RECURSION code * Move "Compatibility" section into a new chapter. * Move "Cross compilation" into a new chapter, because it's not relevant to many users. * Reformat Huxley quote to make it fit better. * Rearrange introduction. * Warning not to use --no-fork. * Document --no-detach. 2003-01-24 20:16 Martin Pool * NEWS, src/srvnet.c: Don't log client hostname, only the IP address. It's not really necessary and can slow us down. 2003-01-24 20:08 Martin Pool * NEWS, src/distcc.c, src/distcc.h, src/exec.c, src/exec.h, src/exitcode.h: Add environment variable to check for inadvertent recursion. 2003-01-24 20:03 Martin Pool * bench/buildutil.py: Better error message for command failures 2003-01-24 19:54 Martin Pool * NEWS: Add check for inadvertent recursion 2003-01-24 19:52 Martin Pool * TODO: Many updates to TODO 2003-01-24 19:51 Martin Pool * bench/compiler.py: Don't explicitly say "gcc-3.2", because it's not available under that name on Red Hat 8.0. 2003-01-20 11:22 Martin Pool * NEWS, configure.ac: Fix configure test for hstrerror(). (Frerich Raabe) 2003-01-19 20:50 Martin Pool * bench/Summary.py: Fix bugs in printing statistics. 2003-01-19 20:29 Martin Pool * bench/buildutil.py: Better formatting time messages. 2003-01-19 20:27 Martin Pool * bench/Summary.py: Better handling of statistics generation or build failures. 2003-01-19 18:45 Martin Pool * src/arg.c: Doc. 2003-01-19 18:43 Martin Pool * test/: ScanArgs.py, basecases.py, testdistcc.py: Split some Python classes out into separate files. 2003-01-19 18:19 Martin Pool * src/arg.c: Doc. 2003-01-19 15:10 Martin Pool * src/dopt.c: Remove ifdef'd code. 2003-01-18 23:57 Martin Pool * configure.ac: TODO about finding Python. 2003-01-18 23:55 Martin Pool * test/testdistcc.py: Roll back change to version number format. 2003-01-18 23:48 Martin Pool * src/: .cvsignore, config.h.in: Build config.h.in, rather than storing in CVS. 2003-01-18 23:46 Martin Pool * src/io.c, NEWS: Flag platforms that have a sendfile() function, but that aren't explicitly supported, because it seems to vary substantially. At the moment only FreeBSD and Linux are known. 2003-01-18 23:43 Martin Pool * configure.ac: Fix text formatting. 2003-01-18 23:41 Martin Pool * test/testdistcc.py, NEWS: Be less strict in checking the output from the plain text preprocessor, because this seems to have changed in gcc 3.2. 2003-01-18 23:36 Martin Pool * test/testdistcc.py: Update copyright * Allow for new --version output * Fix accidental extra newline in C source, when we wanted the escape sequence "\n" * Change way the preprocessor is called -- not working yet. 2003-01-18 22:53 Martin Pool * .cvsignore: Ignore files produced by autoconf. 2003-01-18 22:51 Martin Pool * bench/benchmark.py, NEWS: Projects can now be selected by unambiguous name prefix 2003-01-18 22:39 Martin Pool * configure.ac: Update copyright 2003-01-18 22:38 Martin Pool * config.guess, config.sub: Update from Debian autotools-dev 2003-01-18 22:27 Martin Pool * config.sub: Resurrect 2003-01-18 22:22 Martin Pool * bench/: Build.py, Summary.py, actions.py, benchmark.py, statistics.py: Make std dev and variance methods handle too-short sequences by returning None, rather than failing. * Add -n option to run benchmarks repeatedly. 2003-01-18 22:21 Martin Pool * aclocal.m4, config.guess, config.sub, configure: Stop storing autoconf junk in CVS 2003-01-18 22:19 Martin Pool * TODO: Need to document benchmark. 2003-01-18 22:10 Martin Pool * Makefile.in: Invite people to pass BENCH_ARGS to Make to control the benchmark. 2003-01-18 22:02 Martin Pool * Makefile.in: Include bench/statistics.py in distribution. 2003-01-18 22:00 Martin Pool * bench/Summary.py, bench/statistics.py, NEWS: Start to add support in the Summary class for repeated runs of a benchmark, plus a new "statistics" library containing code to do mean and std dev. 2003-01-18 21:50 Martin Pool * NEWS: Roll over news 2003-01-18 21:49 Martin Pool * OLDNEWS: Put in correct version of old news file. 2003-01-18 21:36 Martin Pool * OLDNEWS: Roll over NEWS. 2003-01-17 12:05 Martin Pool * configure, configure.ac: Bump version to 1.1cvs 2003-01-17 12:00 Martin Pool * src/daemon.c: FIXME about running as root. 2003-01-17 11:37 Martin Pool * src/daemon.c: fixme 2003-01-16 11:36 Martin Pool * configure: Prepare for 1.0 release. 2003-01-16 11:32 Martin Pool * configure.ac: Prepare for 1.0 release. 2003-01-16 11:28 Martin Pool * NEWS, configure.ac: Prepare for 1.0 release. 2003-01-16 11:06 Martin Pool * Makefile.in: Include benchmark source in tarball. * bzip tarball rather than gzipping it, to save a little space. 2003-01-15 22:22 Martin Pool * bench/benchmark.py: Doc 2003-01-14 16:25 Martin Pool * NEWS: Build .bz2 tarball rather than .tgz * Remove PS and PDF from tarball. 2003-01-14 16:03 Martin Pool * NEWS: [no log message] 2003-01-14 15:46 Martin Pool * Makefile.in: Do not include PDF or PS in the tarball, or install them by default. This may save some space in the distribution. They can be built from source using the Linuxdoc tool, or downloaded. 2003-01-14 15:03 Martin Pool * Makefile.in: Resolve logfile lines in order. 2003-01-14 15:01 Martin Pool * bench/.cvsignore: Ignore bench.log 2003-01-14 00:54 Martin Pool * src/io.c: Correct calling of sendfile on BSD 2003-01-13 14:47 Martin Pool * TODO: [no log message] 2003-01-13 12:24 Martin Pool * Makefile.in: Benchmark must be run from bench/ directory. 2003-01-12 23:59 Martin Pool * bench/Summary.py: Show uname in summary. 2003-01-12 23:51 Martin Pool * bench/Summary.py: Show uname in summary. 2003-01-12 23:40 Martin Pool * bench/Project.py: Doc snarf bug. 2003-01-12 23:24 Martin Pool * Makefile.in, NEWS: * Remove Plucker file: nobody seems to be downloading it, and it's easy enough for people to build if they're interested. 2003-01-12 23:09 Martin Pool * bench/Summary.py: Store results into Summary in the order in which they are generated. 2003-01-12 23:05 Martin Pool * bench/: Build.py, actions.py: Add action to "make clean" if desired. Off by default. 2003-01-12 22:58 Martin Pool * bench/: Build.py, CompilerSpec.py, benchmark.py, compiler.py: Add -c option to specify compilers to run. * Remove 'CompilerSpec' module to 'compiler' so that it can more easily have some static methods. 2003-01-12 22:43 Martin Pool * bench/Summary.py: Print a heading on the results, plus the date and the host list. 2003-01-12 22:37 Martin Pool * bench/: actions.py, benchmark.py: Split intelligence about action selection into a new module. * Auto-generation action help table. * Turn 'scrub' off by default. 2003-01-12 22:20 Martin Pool * bench/: Summary.py, buildutil.py: Show all times in %.4f format -- about the right amount of precision. 2003-01-12 22:18 Martin Pool * bench/: Build.py, Project.py, benchmark.py: Put intelligence about running various Actions in order into the Build and Project classes. * More --help documentation for actions. 2003-01-12 22:10 Martin Pool * bench/: Build.py, Project.py, Summary.py, benchmark.py, buildutil.py: Further refactoring: put the combination of a project and a compiler into a new Build object. * Put each Build in a separate directory, rather than using one directory per Project that is overwritten every time. More scope now for retrying or investigating failed builds. 2003-01-12 22:09 Martin Pool * bench/CompilerSpec.py: Don't use commas in directory names because it causes trouble with some Makefiles. 2003-01-12 21:43 Martin Pool * bench/Project.py: Doc 2003-01-12 21:38 Martin Pool * bench/: CompilerSpec.py, benchmark.py: Split CompilerSpec into its own file. 2003-01-12 21:32 Martin Pool * bench/: Project.py, ProjectDefs.py, Summary.py, benchmark.py: Split Project class and project definitions out into two new source files. * Rename Compiler to CompilerSpec and change name format. 2003-01-12 20:50 Martin Pool * bench/: Summary.py, benchmark.py: Split Summary class out into its own file, and print summaries out in a tabular form rather than as Python data definitions. 2003-01-12 20:50 Martin Pool * bench/.cvsignore: Ignore download directory and .pyc files. 2003-01-09 11:06 Martin Pool * bench/benchmark.py: Run snarf quietly * Doc 2003-01-08 18:28 Martin Pool * bench/benchmark.py: Add GNU Hello so that there's something small for testing the benchmark program. * Add --list-projects option. * Allow selection of actions to perform with --actions=ACTIONS. 2003-01-08 18:03 Martin Pool * bench/benchmark.py: Push mainline code into a main() routine. 2003-01-08 18:01 Martin Pool * bench/benchmark.py: Add Project configuration for Wine * Implement the 'unpacked_subdir' Project option, to handle projects like Wine whose unpacked directory is named differently from the tarball. * Doc. 2003-01-06 15:53 Martin Pool * bench/benchmark.py: Doc 2003-01-06 11:24 Martin Pool * doc/release-names.txt: [no log message] 2003-01-06 11:24 Martin Pool * Makefile.in: Split old news items out into a separate page. 2003-01-02 19:52 Martin Pool * NEWS: Doc macrobenchmark. 2003-01-02 16:31 Martin Pool * TODO: Explanation of KDE's --enable-final option, and impact on parallelism. * Half explain "Supermarket scheduler" idea. * Half explain load balancer. 2003-01-02 15:58 Martin Pool * DEPENDENCIES: Add notes about macrobenchmark. 2003-01-01 10:01 Martin Pool * Makefile.in: Add new "benchmark" target to invoke the macrobenchmark suite. The Makefile prints a notice and checks that the hosts are set up before starting the script. 2003-01-01 09:24 Martin Pool * bench/benchmark.py: Use env(1) to find python2.2. (Frerich Raabe) Really the right way is to call through the Makefile to use $(PYTHON). 2003-01-01 09:22 Martin Pool * bench/: benchmark, benchmark.py: Rename bench/benchmark to bench/benchmark.py. 2003-01-01 09:19 Martin Pool * Makefile.in: Use a $(PYTHON) variable so that it can be overridden if the name varies. 2002-12-17 17:17 Martin Pool * news.el, news.emacs: Store settings in elisp rather than as mode variables. 2002-12-17 10:27 Martin Pool * bench/benchmark: If a build fails, then record that but continue. If the overall build is interrupted, just stop. 2002-12-16 21:29 Martin Pool * bench/benchmark: Doc * Better link for kernel 2002-12-16 21:21 Martin Pool * bench/benchmark: Add gdb * Add md5sum and configure command for linux-2.4.20 * Automatically detect and resume interrupted downloads. Do downloads into a temporary directory and move them on completion. 2002-12-16 21:15 Martin Pool * bench/benchmark: b* Project._rm_files: Do this silently and only as necessary. 2002-12-16 21:12 Martin Pool * bench/benchmark: Remove log files at the start of a build. (We use separate logfiles for each case and phase, so this loses no information.) 2002-12-16 21:08 Martin Pool * bench/benchmark: Rename /SourceTree/Project/ 2002-12-16 21:07 Martin Pool * bench/benchmark: Doc. * Just check for download once when we start working on a project. * Scrub the tree just once when finished on a project. 2002-12-16 21:03 Martin Pool * bench/benchmark: Doc. * Add MD5 for GIMP. * When configuring GIMP, turn off Perl support because it seems not to work on Sid and it's not really necessary. 2002-12-16 20:59 Martin Pool * bench/benchmark: Scrub source directories after successful build to save disk space. * Try boring slow gcc build first, to see if it works. 2002-12-16 20:50 Martin Pool * bench/benchmark: Doc 2002-12-16 20:43 Martin Pool * bench/benchmark: SourceTree.build: Accumulate statistics in Summary object on completion of building. Fix syntax error. * Take list of project names from command line. If none are specified, build all known projects. 2002-12-16 20:38 Martin Pool * bench/benchmark: SourceTree.run_cmd: Return status and elapsed time. * SourceTree.build: Remove obsolete make_args argument. * Summary: New class holding overall results of building. 2002-12-16 20:34 Martin Pool * bench/benchmark: Doc. * Try to make shell commands more readable. * Add GIMP URL. 2002-12-16 20:24 Martin Pool * bench/benchmark: Store separate make and distcc logs for configuring and building, in a per-project per-compiler directory. DISTCC_LOG no longer needs to be set beforehand. * Add more MD5sums. * Add correct configuration and build commands for the kernel. 2002-12-16 20:15 Martin Pool * bench/benchmark: Add new Compiler class, encapsulating $(CC) and Make options. * Add URLs for GNU Make and Linux-2.4.20. * Store build logs into a directory identified by both project and compiler. 2002-12-16 19:59 Martin Pool * bench/benchmark: Add support for packages which need to be built from a subdirectory of their unpacked directory. In particular, Samba needs to be built from "samba-2.2.7/source". 2002-12-16 19:54 Martin Pool * bench/benchmark: Add MD5 sums for other packages. * Add Samba tree. (Doesn't work yet, needs a different configure command to handle source being in source/) 2002-12-16 19:49 Martin Pool * bench/.cvsignore: Ignore output files. 2002-12-16 19:48 Martin Pool * bench/benchmark: Send all build log messages to a persistent file in a standard location. * make_dir: New utility function. * Properly check MD5sum for files before unpacking. 2002-12-16 19:41 Martin Pool * bench/benchmark: Store MD5sum of files in the benchmark source and verify them before use. * Allow overriding $(CC) when the program is configured. * Add glib-2.0.7 test. * Test with distcc and plain cc. 2002-12-16 19:24 Martin Pool * bench/benchmark: (SourceTree.configure, SourceTree.build): Redirect configure and build output into log files so that the display is uncluttered. 2002-12-16 19:21 Martin Pool * bench/benchmark: (SourceTree): Cleaner handling of directories. 2002-12-16 19:11 Martin Pool * bench/benchmark: (SourceTree.run_cmd): Show time to execute each command. * (SourceTree): Don't use the time(1) command, but just measure elapsed time. 2002-12-16 19:03 Martin Pool * bench/benchmark: (SourceTree.run_cmd): Show commands as they're executed. * (SourceTree): Time commands as they're run. * (SourceTree.scrub): Remove build trees before starting to build them. * (SourceTree.build): Allow passing options such as -j to make. 2002-12-16 16:49 Martin Pool * bench/benchmark, NEWS: New macro-benchmark and test suite for distcc. This is the start of a script that runs distcc to build various open source programs, as an overall test of correctness, and to measure performance of a distcc installation. It relies on the user to install and configure distcc servers and clients, but handles the work of downloading, preparing, and building packages by itself. * benchmark: New file. 2002-12-16 16:44 Martin Pool * lzo/.cvsignore: Ignore built files for minilzo 2002-12-16 14:43 Martin Pool * lzo/: Makefile, README.LZO, lzoconf.h, minilzo.c, minilzo.h, testmini.c: Import minilzo-1.08 library. Not linked in to main program yet. 2002-12-16 14:42 Martin Pool * doc/release-names.txt: [no log message] 2002-12-16 11:56 Martin Pool * patches/swhite-lzo-compress.diff: Patch from Stephen White * First cut at adding LZO compression, turned on by client-side environment variable and setting a high bit in the protocol number to indicate its use. Uses static copy of lzo. 2002-12-16 11:40 Martin Pool * src/: h_scanargs.c, h_argvtostr.c: Reindent to java / 4-space style. 2002-12-16 11:32 Martin Pool * patches/README.patches: Disclaim warranty on these patches. 2002-12-13 12:06 Martin Pool * linuxdoc/distcc.sgml: Bump version to 0.16cvs. 2002-12-13 12:04 Martin Pool * NEWS, linuxdoc/distcc.sgml: (Cross-Compilation): The recommended convention for gcc names is -gcc-, and GCC 3.3 will install itself under this name. (Alexandre Oliva, Claes Wallin) 2002-12-13 11:06 Martin Pool * configure, configure.ac: Bump version to 0.16cvs. 2002-12-13 09:58 Martin Pool * NEWS, OLDNEWS: Roll over NEWS. 2002-12-12 20:57 Martin Pool * NEWS, configure, configure.ac: Bump version to 0.15. 2002-12-12 20:45 Martin Pool * doc/results.txt: Current linux-2.4.19 benchmark results. 2002-12-12 20:40 Martin Pool * configure: Run autoconf. 2002-12-12 20:17 Martin Pool * linuxdoc/distcc.sgml: Suggest using qualified compiler names rather than -b and -V options, because those options didn't work very well in earlier gcc versions. Based on an explanation from Alexandre Oliva. 2002-12-12 20:06 Martin Pool * Makefile.in, NEWS: Rename TARGET_ROOT variable to the more standard name of DESTDIR. (Alexandre Oliva) 2002-12-12 20:03 Martin Pool * doc/irc/openprojects-distcc-20020807.txt: Random notes about distcc 2002-12-12 19:45 Martin Pool * src/help.c: [Tests are more useful if they're actually run. :-/] * (dcc_show_version): Use intended syntax in --version output. 2002-12-12 19:41 Martin Pool * test/testdistcc.py, src/help.c: (dcc_show_version, VersionOption_Case): --version now shows default port. 2002-12-12 19:38 Martin Pool * doc/flood.txt: flood.txt: Notes on network performance. 2002-12-12 19:38 Martin Pool * src/: distcc.c, distcc.h, dopt.c, hosts.c: Put default port into DISTCC_DEFAULT_PORT preprocessor constant, rather than copying it everywhere. 2002-12-12 19:34 Martin Pool * aclocal.m4: Rerun autoconf. 2002-12-12 19:33 Martin Pool * TODO: TODO: New file. Many random notes about things to do, moved from the user manual. 2002-12-12 19:31 Martin Pool * src/distcc.c, src/dopt.c, src/hosts.c, test/testdistcc.py, NEWS: * Change default port from 4200 to IANA-assigned standard for distcc service "3632". 2002-12-12 19:30 Martin Pool * analog/.cvsignore: Ignore generated files. 2002-12-12 19:29 Martin Pool * analog/: httplog.py, print_referers: httplog.py: New file to parse Apache logs. * print_referers: Change to using httplog.py library. 2002-12-12 19:19 Martin Pool * analog/day.gnuplot: day.gnuplot: New gnuplot file to plot daily traffic. 2002-12-12 18:59 Martin Pool * linuxdoc/distcc.sgml: (Author): Rephrase. 2002-12-12 18:56 Martin Pool * linuxdoc/distcc.sgml: Move "Reporting Bugs" and "Test Suite" sections into the introduction chapter. 2002-12-12 18:43 Martin Pool * linuxdoc/distcc.sgml: Remove empty tag. 2002-12-12 18:41 Martin Pool * NEWS: Only show non-maintainer names in the NEWS file, as in Subversion. 2002-12-12 18:38 Martin Pool * linuxdoc/distcc.sgml, NEWS: Move "Bugs" chapter into TODO. (Martin Pool) 2002-12-12 18:36 Martin Pool * linuxdoc/distcc.sgml: Remove "results" chapter, because this information is more appropriate for the web site. * Start moving bugs/features into TODO. 2002-12-12 18:12 Martin Pool * NEWS: [no log message] 2002-12-12 18:09 Martin Pool * linuxdoc/distcc.sgml: (distcc Compatibility): Remove section about MOC, because we have nothing at the moment to say. Add a new section describing the complex situation for -MD with gcc 2.95 and 3.2. 2002-12-12 17:55 Martin Pool * Makefile.in: (dist_files): Add TODO to distribution. 2002-12-12 17:39 Martin Pool * linuxdoc/distcc.sgml: (Bugs): Need a performance regression suite. * (Bugs): Perhaps need to migrate the manual from Linuxdoc to Docbook Lite. 2002-12-12 16:53 Martin Pool * analog/traffic.py: traffic.py: Add a new first command line parameter, either 'day' or 'week' to set grouping quantum. 2002-12-12 15:47 Martin Pool * src/lock.c: lock.c: Add quotation. 2002-12-06 11:32 Martin Pool * analog/traffic.gnuplot: traffic.gnuplot: Use log y scale. 2002-12-06 11:29 Martin Pool * analog/traffic.py: traffic.py: New utility to produce weekly counts of downloads and accesses. 2002-12-06 11:07 Martin Pool * analog/traffic.gnuplot: Simple plot of traffic 2002-12-06 10:19 Martin Pool * linuxdoc/distcc.sgml, NEWS: Remove "Results" chapter from manual: there are now many more detailed results on the web site, and this information is better suited to storage there, because it will be updated on a different cycle. End-users don't really need to have it in their reference. 2002-12-05 15:22 Martin Pool * doc/release-names.txt: [no log message] 2002-12-05 14:07 Martin Pool * doc/interceptor.txt: Notes on using an external interceptor 2002-12-05 10:02 Martin Pool * src/srvnet.c: srvnet.c: (dcc_log_clientname): Clearer error messages for failure to look up client hostname. 2002-12-05 10:01 Martin Pool * NEWS: [no log message] 2002-11-28 04:48 Martin Pool * linuxdoc/distcc.sgml: We now use ComfyChair not PyUnit 2002-11-28 04:45 Martin Pool * NEWS: Add section on how to report bugs well 2002-11-28 04:40 Martin Pool * linuxdoc/distcc.sgml: Add section on how to report bugs well 2002-11-28 04:20 Martin Pool * src/dopt.c: Say that --no-fork is for debugging ONLY 2002-11-23 04:35 Martin Pool * linuxdoc/distcc.sgml: Add TODO Bump version to 0.14 2002-11-22 19:00 Martin Pool * NEWS: Add note about -MF 2002-11-21 18:53 Martin Pool * src/cpp.c: Doc 2002-11-21 18:50 Martin Pool * src/cpp.c: Doc 2002-11-21 18:46 Martin Pool * NEWS, src/cpp.c, src/strip.c, src/strip.h: Run the preprocessor with output sent to stdout and redirected to a file, rather than by using the -o option. This should fix some compilers that can't handle "-E -o". It may improve gcc behaviour with -MD, but because gcc behaviour has changed over time it may not be a complete fix. 2002-11-21 18:38 Martin Pool * test/testdistcc.py: Doc 2002-11-21 18:24 Martin Pool * Makefile.in, src/cpp.c, src/cpp.h, src/distcc.c: dcc_cpp_maybe: Split code to run preprocessor into its own file. 2002-11-21 18:09 Martin Pool * test/testdistcc.py: DaemonBadPort_Case: avoid polluting system log files. 2002-11-21 18:06 Martin Pool * src/distcc.c: Doc 2002-11-21 18:02 Martin Pool * Makefile.in: Remove obsolete/uncalled dist-python target Move comfychair into test/ 2002-11-21 17:21 Martin Pool * analog/.cvsignore: Ignore generated refererlog 2002-11-21 17:16 Martin Pool * test/: .cvsignore, comfychair.py: Move comfychair into test/ 2002-11-21 17:06 Martin Pool * cases/empty.i: empty .i file 2002-11-21 17:05 Martin Pool * DEPENDENCIES: popt is now included in package 2002-11-21 17:02 Martin Pool * src/serve.c: Doc 2002-11-21 12:04 Martin Pool * doc/to-test.txt: Add list of trees that would be interesting to test 2002-11-20 11:47 Martin Pool * NEWS, configure, configure.ac, src/config.h.in: Fix autoconf detection of resolv.h on Solaris. (Dimitri Papadopoulos) 2002-11-20 11:30 Martin Pool * NEWS: Add badly-behaved compiler drop-in for use in testing. 2002-11-19 14:23 Martin Pool * test/badcc: Add badly-behaved compiler drop-in for use in testing. 2002-11-19 13:11 Martin Pool * NEWS, src/exec.c: * Fix waitpid() takes three options. Required for Irix. (Michael Santy) 2002-11-19 12:49 Martin Pool * Makefile.in: Remove obsolete comment. 2002-11-19 12:42 Martin Pool * Makefile.in: OK, now we use install-sh 2002-11-19 09:09 Martin Pool * analog/print_referers: Better line parser 2002-11-19 08:57 Martin Pool * analog/distcc.analog: Show more search words. 2002-11-19 08:54 Martin Pool * Makefile.in: Copy new EmptySource.py file into distribution 2002-11-19 08:52 Martin Pool * test/.cvsignore: Ignore .pyc files. 2002-11-19 08:48 Martin Pool * Makefile.in, NEWS, configure, configure.ac: Use the correct autoconf macros to detect whether install(1) is available and working, and if not, fall back to using the included install-sh script. This should fix "make install" on Solaris. (Mike Santy, Martin Pool) 2002-11-19 07:45 Martin Pool * test/testdistcc.py: todo 2002-11-18 13:05 Martin Pool * analog/report/.cvsignore: Ignore built files 2002-11-18 13:03 Martin Pool * NEWS, test/EmptySource.py, test/testdistcc.py: Add test case for transmission of a zero-byte file. 2002-11-18 13:01 Martin Pool * configure: autoconf 2002-11-16 12:27 Martin Pool * analog/images/: analogo.png, barc1.png, barc16.png, barc2.png, barc32.png, barc4.png, barc8.png, html2.png: Add analog images 2002-11-16 12:24 Martin Pool * analog/print_referers: Python script to print web referers 2002-11-16 12:22 Martin Pool * analog/distcc.analog: Get ready to include bar images in cvs 2002-11-16 12:19 Martin Pool * configure.ac: Bump version to 0.16cvs 2002-11-16 12:18 Martin Pool * Makefile.in: Include Scenarios page 2002-11-16 11:13 Martin Pool * OLDNEWS, NEWS: roll over news 2002-11-16 09:57 Martin Pool * configure, configure.ac: Bump version to 0.14 2002-11-15 18:10 Martin Pool * contrib/distccd-init: distccd Debian init.d script contributed by Jason Thomas. (Debian #161136) 2002-11-15 18:07 Martin Pool * NEWS: reformat only 2002-11-15 18:07 Martin Pool * NEWS: distccd Debian init.d script contributed by Jason Thomas. (Debian #161136) 2002-11-15 18:06 Martin Pool * Makefile.in: Include contrib files in distribution. 2002-11-15 10:06 Martin Pool * src/trace.h: Doc 2002-11-14 14:09 Martin Pool * NEWS: Make sure PreprocessPlainText_Case runs in the right directory. 2002-11-14 14:09 Martin Pool * test/testdistcc.py: TODO (thanks Oscar) 2002-11-14 14:00 Martin Pool * test/testdistcc.py: Make sure PreprocessPlainText_Case runs in the right directory. 2002-11-14 12:58 Martin Pool * Makefile.in: Make sure that if Latte processing fails, the output file is removed Remove obsolete maintainer-clean dependencies 2002-11-13 08:56 Martin Pool * configure, configure.ac, src/config.h.in, src/exec.c: Handle machines without wait4 by using waitpid instead. 2002-11-13 08:48 Martin Pool * configure.ac, NEWS: Test for wait4 and wait3, which are missing on IRIX (Mike Santy) 2002-11-13 08:46 Martin Pool * src/serve.c: Fix parameter type (suggestion from Dimitri Papadopoulos) 2002-11-13 07:47 Martin Pool * configure: autoconf 2002-11-13 07:44 Martin Pool * Makefile.in, NEWS: Fix silly bug that caused HTML documentation to be missing from the tarball 2002-11-13 07:43 Martin Pool * configure.ac: Bump version to 0.14 2002-11-13 07:14 Martin Pool * NEWS: Bump version to 0.14 2002-11-13 07:11 Martin Pool * src/distcc.c: Take lock on localhost only when compiling locally, not for all compilations. 2002-11-13 07:03 Martin Pool * OLDNEWS, NEWS: Roll over news 2002-11-13 07:01 Martin Pool * src/where.c: Remove dead code. 2002-11-13 06:02 Martin Pool * configure.ac: Bump version to 0.13.1cvs 2002-11-12 18:40 Martin Pool * README: Update README 2002-11-12 18:38 Martin Pool * configure, configure.ac: Prepare for 0.13 release 2002-11-12 18:34 Martin Pool * NEWS: Prepare for release. 2002-11-12 18:25 Martin Pool * test/testdistcc.py: More ComfyChair merges. 2002-11-12 18:24 Martin Pool * configure: autoconf 2002-11-12 18:23 Martin Pool * configure.ac: Remove --with-extra-includes and --with-extra-libs, because they just don't work well with autoconf, since they can only be specified once and repeated appearances will cause only the last to have effect. The official way for autoconf 2.5 is to set CPPFLAGS and LDFLAGS. 2002-11-12 18:21 Martin Pool * configure.ac: Change --with-included-popt if not specified, use if necessary if specified, then always (or never) use it 2002-11-12 18:20 Martin Pool * NEWS: If popt is missing and not specified, get it 2002-11-12 18:14 Martin Pool * configure.ac: If popt is missing and not specified, get it 2002-11-12 18:11 Martin Pool * Makefile.in: doh 2002-11-12 18:10 Martin Pool * Makefile.in: Clean popt, binaries, and testtmp from "clean" target. 2002-11-12 17:53 Martin Pool * NEWS: Merge tpot's comfychair patch 2002-11-12 17:47 Martin Pool * NEWS, configure, configure.ac, src/config.h.in: Add config options for included popt 2002-11-12 17:39 Martin Pool * configure.ac: Add --with-included-popt option 2002-11-12 17:37 Martin Pool * Makefile.in: Make 'all' the default 2002-11-12 17:36 Martin Pool * Makefile.in: Include other necessary files in distribution 2002-11-12 17:33 Martin Pool * Makefile.in: Clean up some Makefile targets Remove GNU makeisms Include popt in tarball 2002-11-12 17:17 Martin Pool * test/testdistcc.py: Make MissingCompiler_Case actually test what it's meant to test. Doc. 2002-11-12 17:11 Martin Pool * NEWS: Update news 2002-11-12 17:08 Martin Pool * linuxdoc/distcc.sgml: Add new exit codes. Bump version to 0.13. 2002-11-12 17:03 Martin Pool * src/: exitcode.h, exec.c: Add EXIT_COMPILER_MISSING 2002-11-12 16:28 Martin Pool * Makefile.in: Doc 2002-11-12 08:16 Martin Pool * aclocal.m4, configure, configure.ac, src/config.h.in, src/srvnet.c: Make inclusion of arpa/nameser.h and resolv.h conditional 2002-11-08 18:51 Martin Pool * src/distcc.c: Fix prototypes 2002-11-08 18:51 Martin Pool * src/exec.c: Doc 2002-11-08 18:50 Martin Pool * src/distcc.c: On the client, we should take locks only when compiling locally. cpp is cheap enough that it doesn't really need to be taken into account. 2002-11-08 18:49 Martin Pool * src/exec.c: Do not take a lock on localhost when spawning commands. This is intended to get rid of a race condition that will sometimes deadlock the client: Two clients, P1 and P2, are both trying to compile on remote machine R. Therefore, they both need to get a lock on localhost to run cpp, and on R. If they acquire the locks in the opposite order, then they will block holding locks, and deadlock. The ordering is indeterminate because the cpp lock is acquired from the separate process forked to run cpp. This was not evident in 0.12 and earlier because there was no limit on the number of locks that could be taken. On the server side, there are better places to regulate process load than here. We should instead hold off on accepting connections until we have space to handle them. On the client, we should take locks only when compiling locally. cpp is cheap enough that it doesn't really need to be taken into account. 2002-11-08 17:39 Martin Pool * cases/: cpp-set-path.c, foo.h, hello.c: Add small files for exploring gcc behaviour 2002-11-05 05:47 Martin Pool * src/exec.c: BSD needs signal.h. Thanks to Ajay Agrawalla. 2002-11-01 19:12 Martin Pool * test/testdistcc.py: MissingCompiler_Case: Fix function name 2002-11-01 19:11 Martin Pool * src/serve.c: dcc_accept_job: Fix little prototype consistency mistake 2002-11-01 19:08 Martin Pool * test/testdistcc.py: Doc 2002-11-01 19:08 Martin Pool * src/serve.c: Drop support for using fifos on the server. Run compilers in their own process group, and kill them if the daemon is killed. Copy server's output into the error log, and try to always send it back to the client even if something goes wrong. 2002-11-01 19:06 Martin Pool * src/: io.c, rpc.c: Use error codes more consistently 2002-11-01 19:06 Martin Pool * src/exitcode.h: Add EXIT_TRUNCATED and EXIT_PROTOCOL_ERROR 2002-11-01 19:05 Martin Pool * src/: exec.c, exec.h: Add new utilities: dcc_reset_signal, and dcc_setpgid Doc 2002-11-01 19:03 Martin Pool * src/dparent.c: Better doc and messages 2002-11-01 19:02 Martin Pool * src/distcc.c: If cpp returns an error, don't bother trying to run the compilation locally. Upgrade notice -> warning on failure to distribute. Only show warning or higher on the client by default. Don't abruptly close the connection if the remote compiler fails. 2002-11-01 18:58 Martin Pool * src/bulk.c: Tidyup 2002-11-01 18:58 Martin Pool * README: Mention DISTCC_LOG and possible future ssh support 2002-11-01 18:57 Martin Pool * NEWS: Temporarily remove limit on number of local tasks, because this can cause a deadlock. Client does not abruptly drop network connection on compiler failure but rather reads the 0-byte object file token. (Martin Pool) Rework logger library to allow multiple logger callbacks to be active at once. This is used for the server, which can write to its own log files and also send a copy of messages to a buffer to be sent to the client. 2002-11-01 18:53 Martin Pool * samples/: bad.c, badcpp.c, hello.c: Add small sample source files 2002-11-01 17:54 Martin Pool * test/testdistcc.py: * Allow distcc's version to be set to something like "0.13cvs-nofifo". * Add test for handling of a compiler missing from the server. 2002-11-01 17:51 Martin Pool * src/distcc.c, src/dparent.c, src/exec.c, src/serve.c, src/where.c, NEWS: * Remove support for feeding the compiler from a fifo. The gain from using fifos does not seem to justify the maintenance burden. (Martin Pool) - This makes the behaviour more consistent, because some platforms (Cygwin) or filesystems (NFS, strangely) can't use fifos. It removes a code path and a slightly complex autodetection. - Using fifos makes some potential scheduling improvements hard: the server can't make good decisions about how many tasks to run, because each one will only use a fraction of the CPU. The client cannot serialize file transmission, which would probably be desirable. - Using fifos makes reliably handling compiler failures slightly harder: the compiler may crash or exit at any time, which will in turn cause the server to hang if it later tries to open or write to the fifo. In previous versions, distcc tried to handle this by catching SIGCHLD when the child terminated, and aborting the operation, but I am not sure that the method is completely reliable. * Use return codes more consistently * Change log levels slightly to try to make sure nothing is emitted for successful compilation or even only compiler errors. * Detached daemon now ignores hangup signal. * Follow Unix convention of returning 128+SIGNAL if the compiler exits with a signal. (Martin Pool) * Write server error messages to a log file and send them back to the client on completion. 2002-11-01 17:25 Martin Pool * src/daemon.c: Doc 2002-10-31 13:40 Martin Pool * NEWS: More news 2002-10-31 13:28 Martin Pool * Makefile.in: Add TARGET_ROOT Makefile variable for installation, when building binary packages. 2002-10-31 13:15 Martin Pool * NEWS, src/daemon.c, src/exec.c, src/serve.c: Log messages on the server of severity "warning" or higher are captured and sent back to the client. Do not use atexit() to clean up temporary files, because this can cause havoc if it's ever called from a child process that forked but failed to exec. 2002-10-31 13:11 Martin Pool * src/tempfile.c: Show trace message when temporary files are deleted 2002-10-31 13:11 Martin Pool * src/: trace.c, trace.h, distcc.c: Change the logger callback system so that multiple loggers may be attached at any time. 2002-10-31 12:35 Martin Pool * src/exec.c: Add trace message for EINTR failure of wait4, because we don't really expect it to happen. Doc. 2002-10-31 12:34 Martin Pool * src/distcc.h: Define true and false for clarity 2002-10-31 12:33 Martin Pool * Makefile.in: Include autogen.sh in dist 2002-10-31 12:32 Martin Pool * configure.ac, src/distcc.c: Doc 2002-10-31 12:32 Martin Pool * news.emacs: No tabs please 2002-10-21 20:33 Martin Pool * analog/distcc.analog: Exclude distcc.samba.org from referrer calculations 2002-10-18 16:45 Martin Pool * DEPENDENCIES: Add URL for popt 2002-10-18 11:58 Martin Pool * NEWS: Note Makefile fixes 2002-10-18 11:57 Martin Pool * configure, configure.ac: Don't use -MD because there seems not to be a portable way to include the results in the Makefile 2002-10-18 11:55 Martin Pool * Makefile.in: Check that programs have been built before trying to install them 2002-10-18 11:53 Martin Pool * Makefile.in: Put back pkgdoc_DOCS, which somehow got lost Distribute pkgdocs as well 2002-10-18 11:46 Martin Pool * aclocal.m4, configure: Run autoconf 2002-10-18 11:45 Martin Pool * popt/: findme.c, findme.h, popt.c, popt.h, poptconfig.c, popthelp.c, poptint.h, poptparse.c, system.h: Import popt-1.7 2002-10-18 11:41 Martin Pool * README.popt: Start adding included popt 2002-10-18 11:38 Martin Pool * README.packaging, Makefile.in: Add note to packagers 2002-10-18 11:29 Martin Pool * Makefile.in, configure.ac: Remove reference to src/Makefile.in 2002-10-18 11:29 Martin Pool * NEWS, src/Makefile.in: Get rid of Makefile recursion; build all source from the toplevel Makefile 2002-10-18 11:22 Martin Pool * Makefile.in, .cvsignore: Get rid of Makefile recursion; build all source from the toplevel Makefile Binaries are now deposited into the top-level directory Drop obsolete pyunit rules 2002-10-18 10:36 Martin Pool * src/distcc.c: Test that the .i file exists before trying to transmit it to the server. Doc. 2002-10-17 18:33 Martin Pool * src/arg.c: Better message for object or output files 2002-10-17 18:32 Martin Pool * NEWS, test/testdistcc.py: Add test case for invocations like "distcc -c test1.c test2.c". 2002-10-17 18:22 Martin Pool * test/testdistcc.py: Doc 2002-10-17 18:21 Martin Pool * NEWS, test/testdistcc.py: Add test case for preprocessing non-C text, as is done by (for example) xrdb. Remove done TODOs 2002-10-17 18:07 Martin Pool * test/testdistcc.py: Add test case for #error directive 2002-10-17 13:40 Martin Pool * NEWS, linuxdoc/distcc.sgml: More Gentoo notes from Ernesto 2002-10-17 13:29 Martin Pool * linuxdoc/distcc.sgml, NEWS: Add Gentoo documentation from Dean Bailey 2002-10-16 11:00 Martin Pool * Makefile.in: Don't use "make -C" because some non-GNU makes don't support -C. Instead, explicitly cd, and do it in a way that better allows parallelism. 2002-10-11 11:45 Martin Pool * NEWS, test/testdistcc.py: Split out tests for implied compiler name into their own class 2002-10-11 11:40 Martin Pool * doc/lock-deadlock.txt: Doc deadlock observed in 0.13cvs 2002-10-10 12:56 Martin Pool * Makefile.in: Include where.h 2002-10-10 12:56 Martin Pool * src/Makefile.in: Cope when there are no .d files 2002-10-10 12:52 Martin Pool * Makefile.in: Clean up the dist targets; include new patches 2002-10-10 12:33 Martin Pool * packaging/SuSE/init.d/distcc, NEWS: SuSE init.d script from Brandon Forehand 2002-10-10 11:47 Martin Pool * patches/: colorgcc, distcc-hostlist.diff: Patches from Charles Samuels to store hosts in a file, and to run distcc through colorcc. 2002-10-10 10:54 Martin Pool * src/distcc.c: Add FIXME 2002-10-10 00:33 Martin Pool * src/: distcc.c, distcc.h, exec.c, exec.h, lock.h, serve.c, where.c, where.h: In lock debug messages, show whether we're running the compiler or the preprocessor. 2002-10-07 23:20 Martin Pool * NEWS: Doc 2002-10-07 23:13 Martin Pool * src/where.c: Add trace 2002-10-07 23:03 Martin Pool * src/lock.c: Fix parameters for fcntl locks 2002-10-07 23:02 Martin Pool * src/where.c: Add trace Use pid+ppid as a seed for randomly choosing a host when we can't find a free one. 2002-10-07 22:54 Martin Pool * src/: Makefile.in, distcc.c, distcc.h, hosts.h, lock.c, lock.h, where.c: Add code to wait for a blocking lock if no host is immediately free. 2002-10-07 22:10 Martin Pool * NEWS, src/dparent.c: When the parent is terminated, don't kill its process group. Allow children to finish in their own time. 2002-10-07 22:08 Martin Pool * src/Makefile.in: Include generated dependencies 2002-10-07 18:17 Martin Pool * test/testdistcc.py: NoDetachDaemon_Case: Fix bug in arguments for starting --no-detach daemon Correctly wait for daemon after signalling Fix log message 2002-10-07 15:07 Martin Pool * test/testdistcc.py: Move code for explaining failures into test case Move setUp/runTest/tearDown structure into framework runCmdNoWait(): take a list Add test case for --no-detach (broken) 2002-10-07 14:37 Martin Pool * NEWS: Nicer handling of ^C while running tests: print "INTERRUPT" and terminate the whole test 2002-10-07 14:36 Martin Pool * test/testdistcc.py: New runCmdNoWait function needs argument as string, not list 2002-10-07 14:28 Martin Pool * test/testdistcc.py: When killing daemon, ping every 200ms to try to notice faster that it's finished. Clean up some function names. Add unused DetachDaemon_Case 2002-10-07 13:57 Martin Pool * NEWS, src/dopt.c, src/dparent.c, src/opt.h: Add --no-detach option 2002-10-07 13:52 Martin Pool * NEWS, src/h_hosts.c, src/hosts.c, src/hosts.h, src/lock.c, src/where.c, test/testdistcc.py: Add per-host limit on number of compile slots to dcc_hostdef structure. Not used yet, and always set to 4. 2002-10-07 13:06 Martin Pool * NEWS, OLDNEWS, configure, configure.ac: Advance version to 0.13cvs 2002-10-07 12:39 Martin Pool * NEWS, aclocal.m4, configure, configure.ac: Bump version to 0.12 2002-10-07 12:34 Martin Pool * src/where.c: Doc 2002-10-07 12:29 Martin Pool * linuxdoc/distcc.sgml: Bump to version 0.12 2002-10-07 12:16 Martin Pool * linuxdoc/distcc.sgml: Note on adaptive scheduling 2002-10-07 11:35 Martin Pool * NEWS, src/clinet.c, src/clinet.h, src/distcc.c, src/exec.c, src/exec.h, src/hosts.c, src/hosts.h, src/lock.c, src/where.c: Roll back multi-A-record patch: seems to break the test suite, and on further consideration I think just SRV records might be cleaner. 2002-10-07 11:19 Martin Pool * test/testdistcc.py: Doc 2002-10-07 11:15 Martin Pool * src/hosts.c: Doc about handling host list. 2002-10-07 11:04 Martin Pool * linuxdoc/distcc.sgml: Add note about performance test suite. 2002-10-06 21:37 Martin Pool * aclocal.m4, configure, configure.ac: Bump version to 0.12cvs 2002-10-04 11:53 Martin Pool * NEWS: foo 2002-10-02 15:03 Martin Pool * src/arg.c: Add fixme 2002-10-02 14:55 Martin Pool * src/distcc.c: Add fixme 2002-10-02 13:03 Martin Pool * linuxdoc/distcc.sgml: Note about starting the daemon 2002-10-02 12:47 Martin Pool * doc/irc/: slashnet-distcc-20020919.txt, slashnet-distcc-20021002.txt: Check in IRC logs 2002-09-30 23:06 Martin Pool * src/h_hosts.c: Fix extra headers to allow for host definitions that now include an IP address. 2002-09-30 23:01 Martin Pool * NEWS, configure, src/clinet.c, src/clinet.h, src/distcc.c, src/exec.c, src/exec.h, src/hosts.c, src/hosts.h, src/lock.c, src/where.c: Handle DNS A records that give multiple IP addresses for a host by distributing work across all the addresses. This should allow you to create "linux.build.squick.net" that resolves to all the relevant machines. Patch from Andreas Granig, but seems to break some tests. 2002-09-30 16:06 Martin Pool * NEWS, src/serve.c: wait4() on Solaris can't handle a pid of -1, which means "any child" on Linux and BSD. Use pid of 0 instead to collect any children from the same process group. (Kevin Bailey) 2002-09-30 15:44 Martin Pool * NEWS, src/arg.c, test/testdistcc.py: Add tests for "gcc -S -o - foo.c" 2002-09-30 14:04 Martin Pool * linuxdoc/distcc.sgml: Update version to 0.11 2002-09-30 14:00 Martin Pool * linuxdoc/distcc.sgml: Remove done TODO 2002-09-30 13:46 Martin Pool * Makefile.in: Add roadmap 2002-09-27 14:50 Martin Pool * NEWS, src/arg.c: Handle "gcc -S foo.c -o -", which ought to write assembly to stdout. 2002-09-27 14:20 Martin Pool * src/where.c: Add fixme 2002-09-27 14:03 Martin Pool * Makefile.in: Add results page 2002-09-27 13:55 Martin Pool * survey.txt: Add qn about distcc version 2002-09-26 16:19 Martin Pool * NEWS, OLDNEWS: Roll over NEWS 2002-09-25 16:36 Martin Pool * src/implicit.c: Doc 2002-09-25 11:54 Martin Pool * NEWS, configure, configure.ac: Bump version to 0.11 2002-09-25 11:43 Martin Pool * Makefile.in, patches/README.patches, patches/granig_distcc_multi-A-record.diff: Add patches/README, and Andrea Granig's multi-A-record patch 2002-09-25 11:39 Martin Pool * Makefile.in: Include patches in distributed tarball 2002-09-25 11:37 Martin Pool * linuxdoc/distcc.sgml: GNU Info can't handle having two sections with the same heading 2002-09-24 18:18 Martin Pool * NEWS, src/strip.c: Fix (non-exploitable) buffer overrun bug. 2002-09-23 22:47 Martin Pool * NEWS: Update news 2002-09-23 22:31 Martin Pool * src/strip.c: List -MD, etc, separately, because we don't know how other -M options will be parsed in the future. 2002-09-23 22:29 Martin Pool * src/strip.c: Strip -MF -MT -MQ options that are followed by a filename 2002-09-23 22:24 Martin Pool * src/arg.c: Add support for gcc-3.2 new -M options (-MG, etc) 2002-09-23 15:25 Martin Pool * linuxdoc/distcc.sgml: Update todo list. Add section discussing ccache and distcc 2002-09-23 15:17 Martin Pool * patches/joerg-proof-build-01.diff: Patch from Joerg to do "proof" by compiling a file on all machines and checking that they're the same. 2002-09-23 14:56 Martin Pool * NEWS, src/daemon.c: Do not object to running as group 0, because on BSD this is "wheel" and many non-privileged users are in it. 2002-09-23 12:46 Martin Pool * doc/scheduling.txt: More notes 2002-09-20 12:37 Martin Pool * src/arg.c: Doc 2002-09-20 11:39 Martin Pool * NEWS, src/strip.c, test/testdistcc.py: Strip more local-only options Add more tests for argument stripping dcc_strip_local_args: trace result on completion 2002-09-20 10:30 Martin Pool * test/testdistcc.py: Doc 2002-09-20 10:14 Martin Pool * src/arg.c: Doc. 2002-09-19 00:33 Martin Pool * src/bulk.c: Mode on received files should be 0666&~umask 2002-09-19 00:06 Martin Pool * src/serve.c: Doc 2002-09-18 22:58 Martin Pool * src/serve.c: Doc 2002-09-18 21:36 Martin Pool * NEWS, src/bulk.c, src/daemon.c, test/testdistcc.py: Make permissions on output files obey umask, etc. Add test case for this. Add option to test case driver to run particular specified tests. 2002-09-18 16:57 Martin Pool * src/distcc.c, src/h_scanargs.c, src/implicit.c, src/implicit.h, test/testdistcc.py: Rename dcc_add_implicit to dcc_find_compiler Remove "distcc hello.o -o hello" case -- too hard at the moment. 2002-09-18 16:47 Martin Pool * src/: distcc.c, h_scanargs.c, implicit.c, implicit.h: Reduce too-long function name 2002-09-18 16:42 Martin Pool * src/implicit.c: Doc. 2002-09-18 16:39 Martin Pool * test/testdistcc.py: Add implicit linker test: "distcc testtmp.o -o testtmp" 2002-09-18 16:36 Martin Pool * test/testdistcc.py: Fix tests for -MD that were giving a false pass Add basic tests for implict compiler names. 2002-09-18 16:33 Martin Pool * NEWS, src/Makefile.in, src/h_scanargs.c, test/testdistcc.py: Add more test cases for implicit compiler name handling. Extend h_scanargs to exercise this. 2002-09-18 16:32 Martin Pool * src/arg.c: Fix doc. 2002-09-18 13:29 Martin Pool * NEWS: Release name 2002-09-18 10:45 Martin Pool * doc/results.txt: Add results on building inside VMWare 2002-09-17 18:49 Martin Pool * src/io.c: Doc. 2002-09-17 13:59 Martin Pool * src/srvnet.c: resolv.h might need sys/types.h on BSD? 2002-09-17 13:58 Martin Pool * src/implicit.c: Might need sys/types.h on BSD? 2002-09-16 18:14 Martin Pool * src/clinet.c: Fix docs 2002-09-16 11:02 Martin Pool * Makefile.in: Upload "tested" page 2002-09-16 11:01 Martin Pool * README: Update readme text 2002-09-14 19:02 Martin Pool * src/srvnet.c: Cope without hstrerror(). Thanks to Richard Zidlicky 2002-09-14 18:59 Martin Pool * configure, configure.ac, src/config.h.in: Check for presence of hstrerror function. Richard Zidlicky reports that it is missing in libc5 2002-09-14 18:54 Martin Pool * src/srvnet.c: Cope without socklen_t. Thanks to Richard Zidlicky 2002-09-14 18:53 Martin Pool * configure, configure.ac, src/config.h.in: Check for socklen_t 2002-09-14 18:46 Martin Pool * src/clinet.c, NEWS: Remove unnecessary sa_family_t cast. (Richard Zidlicky) 2002-09-14 13:35 Martin Pool * NEWS: Doc 2002-09-14 13:20 Martin Pool * NEWS, configure, configure.ac, src/config.h.in: More helpful message explaining that popt is needed if it is missing at build time. 2002-09-14 10:58 Martin Pool * configure.ac: Doc 2002-09-14 10:52 Martin Pool * src/dparent.c: Don't set cloexec() on the accept fd -- this seems to make it close after the first compiler runs. 2002-09-14 10:51 Martin Pool * NEWS, test/testdistcc.py: Create and use a separate TMPDIR for each test case. Also, rename subdirectories of testtmp 2002-09-14 10:46 Martin Pool * src/serve.c: Doc. 2002-09-14 10:38 Martin Pool * src/serve.c: Doc. 2002-09-14 10:11 Martin Pool * src/: dparent.c, exec.c: Don't close all fds when starting the compiler, because this gets a bit confusing with logs and lock files. However, do set CLOEXEC on the network fds, because the compiler should never be writing to them. 2002-09-14 09:52 Martin Pool * src/lock.c, NEWS: Fix leakage of fds when trying to get a lock. 2002-09-14 09:51 Martin Pool * src/util.c: Doc. 2002-09-14 09:50 Martin Pool * src/exec.c: Move lock prototypes to lock.h 2002-09-14 09:48 Martin Pool * src/: lock.h, distcc.h: Rearrange prototypes 2002-09-14 09:47 Martin Pool * Makefile.in, src/Makefile.in, src/exec.c, src/hosts.c, src/lock.c, src/lock.h, src/where.c: Split locking code out into a separate file so that it can be used by the server as well 2002-09-14 09:46 Martin Pool * test/testdistcc.py: Run daemon with --verbose 2002-09-14 09:33 Martin Pool * src/exec.c: dcc_execvp doesn't return 2002-09-14 09:32 Martin Pool * NEWS: Whenever a command by either the client or the server, it counts towards the load on that machine. This covers undistributed commands, cpp, and compilation. 2002-09-14 09:32 Martin Pool * src/distcc.c: dcc_compile_local: Don't need to take a lock as a special case; this is always done now 2002-09-14 09:30 Martin Pool * src/exec.c: dcc_inside_child: Take a lock on localhost for all executed commands 2002-09-14 09:08 Martin Pool * test/testdistcc.py: Doc 2002-09-14 08:42 Martin Pool * src/serve.c: Doc 2002-09-14 08:41 Martin Pool * src/exec.c, NEWS: dcc_inside_child: new function to handle setup and execution of children. Now checks return codes, and makes sure (very important!) that we can never return above the fork() call. 2002-09-14 08:33 Martin Pool * src/exec.c: dcc_redirect_fds: If any redirection fails, return that error. 2002-09-14 08:32 Martin Pool * src/util.c: Needs exitcode.h 2002-09-14 08:31 Martin Pool * src/util.c: dcc_redirect_fd: Return EXIT_IO_ERROR not -1 for error 2002-09-14 08:30 Martin Pool * src/util.c: dcc_redirect_fd: Remove calls to rs_fatal() in favour of returning an error. 2002-09-14 08:28 Martin Pool * src/tempfile.c: Doc 2002-09-14 08:26 Martin Pool * OLDNEWS, NEWS: Roll over NEWS 2002-09-14 08:25 Martin Pool * src/io.c: Failure to write should be an error, but not fatal. We might want to do something to make sure the process unwinds properly. 2002-09-14 08:23 Martin Pool * src/serve.c: Doc 2002-09-13 17:52 Martin Pool * linuxdoc/distcc.sgml: Update libtool situation. 2002-09-13 15:40 Martin Pool * doc/ssh-notes.txt: Back-of-envelope calculations on using SSH. 2002-09-13 13:08 Martin Pool * src/: arg.c: Doc. 2002-09-13 13:02 Martin Pool * src/arg.c: Doc. 2002-09-13 12:58 Martin Pool * src/serve.c: Doc. 2002-09-13 12:55 Martin Pool * src/serve.c: Remove done todo 2002-09-13 12:29 Martin Pool * Makefile.in: Remove done TODO 2002-09-13 12:28 Martin Pool * Makefile.in: Include new header file 2002-09-13 12:27 Martin Pool * configure, configure.ac: Bump version to 0.10.1 2002-09-13 12:24 Martin Pool * src/serve.c: Define W_EXITCODE with standard Unix meaning if it is missing. 2002-09-13 12:22 Martin Pool * src/: distcc.c, distcc.h, exec.c, exec.h, serve.c: Split headers, also fix fact that pid_t is in sys/types.h. 2002-09-13 12:20 Martin Pool * configure, configure.ac: Bump version to 0.10.1cvs 2002-09-12 21:38 Martin Pool * linuxdoc/distcc.sgml, src/distcc.c: Update for new syntax, 'distcc -c hello.c' 2002-09-12 21:28 Martin Pool * configure, configure.ac: Bump version to 0.10. 2002-09-12 21:20 Martin Pool * NEWS: Add release name. 2002-09-12 21:00 Martin Pool * NEWS: Strip emacs stuff. 2002-09-12 20:43 Martin Pool * NEWS, src/filename.c, test/testdistcc.py: It turns out that .s and .S files in fact cannot be assembled remotely, because they might use the gas '.include' pseudo op, which is resolved by the assembler and would end up reading something from the volunteer's disk. Thanks to Richard Zidlicky for pointing this out. 2002-09-12 20:15 Martin Pool * test/testdistcc.py: Doc. 2002-09-12 14:30 Martin Pool * src/: arg.c: Note about difficulties of included files in .s and .S. 2002-09-12 12:14 Martin Pool * test/testdistcc.py: Update regexp to handle new "cannot distribute" message format. 2002-09-12 11:20 Martin Pool * src/strip.c: Remove dumb overoptimization that mangled command lines 2002-09-12 11:17 Martin Pool * src/strip.c, NEWS: Strip -M* from remote command lines as well. 2002-09-12 11:13 Martin Pool * configure.ac: If using gcc, use -MMD for dependency files. 2002-09-12 11:03 Martin Pool * src/distcc.c, NEWS: If distribution fails, show the name of the server that we were trying to use. 2002-09-12 10:58 Martin Pool * src/implicit.c: Document design tradeoffs about implicit compiler names. 2002-09-12 10:34 Martin Pool * src/: distcc.c, distcc.h, hosts.c, implicit.c, implicit.h, where.c: Allow distcc to be directly used with the same syntax as a compiler: "distcc -c hello.c". At the moment, always calls "cc". 2002-09-11 17:19 Martin Pool * Makefile.in, NEWS, src/Makefile.in, src/arg.c, src/distcc.c, test/testdistcc.py: Allow distcc to be directly used with the same syntax as a compiler: "distcc -c hello.c". At the moment, always calls "cc". 2002-09-11 17:02 Martin Pool * src/: distcc.c, arg.c: Remove done todos. 2002-09-11 16:44 Martin Pool * NEWS, src/distcc.c, src/h_strip.c, src/strip.c, src/strip.h: Also strip -L arguments before passing across the network. There's no good reason why they should be on compilation lines, but it does happen in GNOME. 2002-09-11 16:26 Martin Pool * src/distcc.c: Strip -D and -I options before passing the command line across the network, for clarity (and perhaps a tiny performance improvement.) 2002-09-11 16:22 Martin Pool * NEWS: Strip -D and -I options before passing the command line across the network, for clarity (and perhaps a tiny performance improvement.) 2002-09-11 16:20 Martin Pool * NEWS, test/testdistcc.py: Add test case that uses -D on the compiler command line 2002-09-11 16:00 Martin Pool * test/testdistcc.py: Add test cases for scanning -Mfoo 2002-09-11 15:56 Martin Pool * test/testdistcc.py: Add test case for arg stripping 2002-09-11 15:37 Martin Pool * Makefile.in, src/.cvsignore, src/Makefile.in, src/h_strip.c, src/strip.c, src/strip.h, src/util.h: Add code to strip -D and -I from command lines before passing them, and test harness for same. 2002-09-11 13:08 Martin Pool * src/distcc.c: Doc 2002-09-11 12:43 Martin Pool * src/distcc.c: Doc from tpot 2002-09-09 22:44 Martin Pool * test/testdistcc.py, NEWS: Add a test for running 100 compilations simultaneously. 2002-09-09 18:56 Martin Pool * src/serve.c: Doc. 2002-09-09 18:31 Martin Pool * src/dopt.c: Doc. 2002-09-09 16:13 Martin Pool * src/bulk.c: Log info message giving length after receiving files. 2002-09-09 16:09 Martin Pool * src/arg.c: Fix docs. 2002-09-09 13:19 Martin Pool * NEWS, src/arg.c: Allow -MD and -MMD to be distributed, since the compiler will produce a little file locally. 2002-09-09 12:58 Martin Pool * test/testdistcc.py: Add todo 2002-09-09 11:23 Martin Pool * src/distcc.c, NEWS: Try to make sure to uncork client socket before closing if cpp fails, to work around Linux 2.2 bug that causes the socket to jam in FIN_WAIT1. 2002-09-09 10:34 Martin Pool * src/arg.c: Doc 2002-09-08 18:13 Martin Pool * NEWS, test/testdistcc.py: Test many simple compilations, in case there is an infrequent error. 2002-09-08 17:17 Martin Pool * test/testdistcc.py: Actually run CppError_Case 2002-09-08 17:15 Martin Pool * src/exec.c: Remove old doc. dcc_collect_child: Show pid returned from wait4, not input pid. Much better if called with -1. 2002-09-08 17:12 Martin Pool * src/serve.c: Factor out code for trapping child exit into new routine. 2002-09-08 17:08 Martin Pool * NEWS: update news 2002-09-08 17:08 Martin Pool * src/util.h: dcc_remove_if_exists: new function 2002-09-08 17:07 Martin Pool * src/serve.c: Remove pid variable which was causing trouble by not being initialized before the child exited. Instead, just wait(-1) to collect whatever child was started. 2002-09-08 17:03 Martin Pool * src/exec.c: When redirecting an fd in a new process, remove the file if it already exists. 2002-09-08 16:59 Martin Pool * src/tempfile.c: dcc_remove_if_exists: new common function 2002-09-08 16:56 Martin Pool * src/: util.h, exec.c: dcc_redirect_fd: Make name consistent. 2002-09-08 16:56 Martin Pool * src/util.c: dcc_redirect_fd: Make name consistent. Better error messages. 2002-09-08 15:54 Martin Pool * NEWS, src/distcc.c: If .o file is 0 bytes or not created on the server, do not create it on the client either. 2002-09-08 15:53 Martin Pool * NEWS, src/serve.c: Attempt to fix a race where the compiler process could exit without opening its input before we started writing to the FIFO. In that case, the daemon would hang forever waiting for the compiler to arrive. In the new code, SIGCHLD causes a longjmp to break out of trying to feed the compiler. 2002-09-08 15:25 Martin Pool * src/serve.c: Doc. 2002-09-08 15:01 Martin Pool * NEWS, src/serve.c: If the volunteer compiler exits without reading all of its input, return the compiler's own exit code across the network, rather than EXIT_DISTCC_FAILED. 2002-09-08 14:54 Martin Pool * src/serve.c: remove done todo 2002-09-08 14:48 Martin Pool * NEWS, test/testdistcc.py: Test compiler that succeeds without reading input. 2002-09-08 14:29 Martin Pool * NEWS, test/testdistcc.py: Test handling of a file that causes a preprocessor error. 2002-09-08 14:19 Martin Pool * Makefile.in: Don't upload Latte source. 2002-09-06 14:39 Martin Pool * src/distcc.c: Add fixmes. 2002-09-05 17:56 Martin Pool * src/zip.c: Doc. 2002-09-05 11:05 Martin Pool * test/testdistcc.py: todo 2002-09-05 10:07 Martin Pool * src/exec.c: Doc waitstatus requirements. 2002-09-04 16:14 Martin Pool * NEWS: Modified patch from Alexandre Oliva to handle "distcc -c -S testtmp.c". 2002-09-04 16:11 Martin Pool * test/testdistcc.py: Test case for "distcc -c -S testtmp.c", reported by Alexandre Oliva 2002-09-04 16:08 Martin Pool * src/arg.c: Modified patch from Alexandre Oliva to handle "distcc -c -S testtmp.c". 2002-09-04 15:53 Martin Pool * test/testdistcc.py: Test case for "distcc -c -S testtmp.c", reported by Alexandre Oliva 2002-09-04 13:48 Martin Pool * src/serve.c: Doc. 2002-09-04 13:46 Martin Pool * linuxdoc/distcc.sgml: Notes on getloadavg() 2002-09-04 12:59 Martin Pool * doc/lzo-notes.txt: Notes on LZO compression 2002-09-04 12:53 Martin Pool * src/srvnet.c: Use additional headers possibly required on Solaris. 2002-09-04 12:52 Martin Pool * src/config.h.in: Check for -lresolv 2002-09-04 12:51 Martin Pool * NEWS: Solaris portability fixes 2002-09-04 12:49 Martin Pool * configure: Look for -lresolv, needed on Solaris. http://docs.sun.com/?q=hstrerror&p=/doc/816-3322/6m9k32d1v&a=view Suggestion from Dimitri PAPADOPOULOS-ORFANOS. 2002-09-04 12:47 Martin Pool * analog/.cvsignore: Ignore downloaded logs 2002-09-04 12:40 Martin Pool * Makefile.in, src/Makefile.in: Solaris "install -d" can only create a single directory at a time. Suggestion from Dimitri PAPADOPOULOS-ORFANOS. 2002-09-04 12:38 Martin Pool * configure.ac: Look for -lresolv, needed on Solaris. http://docs.sun.com/?q=hstrerror&p=/doc/816-3322/6m9k32d1v&a=view Suggestion from Dimitri PAPADOPOULOS-ORFANOS. 2002-09-04 12:14 Martin Pool * src/distcc.c: Patch from Dimitri PAPADOPOULOS-ORFANOS to fix signedness warning. 2002-09-04 10:06 Martin Pool * linuxdoc/distcc.sgml: Note that server log messages stay on the server. 2002-09-03 18:13 Martin Pool * NEWS, OLDNEWS: Roll over NEWS 2002-09-03 18:12 Martin Pool * man/distccd.1: troff fix 2002-09-03 18:12 Martin Pool * man/distcc.1: Tiny troff fix 2002-09-03 18:09 Martin Pool * configure.ac: Set version to 0.10cvs 2002-09-03 18:02 Martin Pool * src/arg.c: Doc. 2002-09-03 18:00 Martin Pool * analog/distcc.analog: Turn on weekly report. Adjust floors. 2002-09-03 17:49 Martin Pool * Makefile.in: analog-download: Get archived log files 2002-09-03 15:45 Martin Pool * NEWS, configure, configure.ac: Bump version to 0.9 2002-09-03 14:03 Martin Pool * doc/results.txt: More results. 2002-09-03 14:02 Martin Pool * Makefile.in: Fix linuxdoc targets so that .ps and .info files don't get rebuilt if the .gz files are up-to-date. 2002-09-03 13:49 Martin Pool * Makefile.in: Doc. 2002-09-03 13:49 Martin Pool * Makefile.in: Change .gz rule to compress "in-place" 2002-09-03 13:48 Martin Pool * Makefile.in: Add new header files to list of things to distribute! 2002-09-03 13:40 Martin Pool * news.emacs: emacs stub to set up NEWS file. 2002-09-03 10:55 Martin Pool * linuxdoc/distcc.sgml: Split TODOs about load balancing out into their own section. Add nice suggestion from Oscar Esteban about allowing some jobs to be remotely queued. 2002-09-02 10:33 Martin Pool * linuxdoc/distcc.sgml: Add RFC for DNS SRV. 2002-09-02 10:32 Martin Pool * linuxdoc/distcc.sgml: More todo notes. 2002-09-02 09:21 Martin Pool * Makefile.in: Apache logs have moved on new samba.org machine 2002-09-02 09:17 Martin Pool * Makefile.in: Add analog-all target 2002-09-02 07:38 Martin Pool * src/distcc.c: Doc. 2002-09-02 07:16 Martin Pool * src/distcc.c: dcc_retrieve_results: If the remote compiler exited non-zero, but the transfer was successful, return 0, indicating that there is no point trying to re-run the job locally. 2002-09-02 07:12 Martin Pool * src/serve.c: If something went wrong running the compiler, then make sure the overall status is failure. However, only overwrite the status code if it was not already !0. 2002-09-02 07:07 Martin Pool * test/testdistcc.py: Set up a distcc client log file for all tests. 2002-09-02 07:02 Martin Pool * test/testdistcc.py: Add test case that runs /bin/false to simulate a compiler that fails without reading its input. 2002-09-01 15:33 Martin Pool * NEWS: Doc recent changes 2002-09-01 15:30 Martin Pool * src/bulk.c: Better message for the case where the compile command exits without opening the fifo. 2002-09-01 15:27 Martin Pool * src/serve.c: Fix message 2002-09-01 15:26 Martin Pool * src/serve.c: If compilation failed, then still collect the compiler child, and send back a reply, with the waitstatus forced to be failure. 2002-09-01 15:15 Martin Pool * src/distcc.c, NEWS: dcc_compile_remote: If transmission to the server fails, close the socket sooner rather than later so as not to make the server process wait around unnecessarily. 2002-09-01 15:12 Martin Pool * src/distcc.c: dcc_compile_remote: Split into smaller functions. 2002-09-01 15:02 Martin Pool * src/bulk.c: Doc. 2002-09-01 14:28 Martin Pool * NEWS: Add common routine for setting SIGPIPE handling. 2002-09-01 14:27 Martin Pool * src/serve.c: Split server-side compile code into slightly smaller functions If a network error is detected while feeding data to the compiler, then it is sent a SIGHUP. 2002-09-01 14:08 Martin Pool * NEWS, src/exec.c: Set SIGPIPE handler back to default before starting compiler tasks. 2002-09-01 14:06 Martin Pool * src/: clinet.c, serve.c, util.c, util.h: Add common routine for setting SIGPIPE handling. 2002-09-01 14:05 Martin Pool * test/testdistcc.py: Send distccd log to a file while testing -- easier for postmortems. 2002-09-01 13:56 Martin Pool * NEWS, src/dparent.c: Do not try to collect daemon children if --no-fork was specified. Otherwise that routine collects compilers, and gives crazy messages like "-2 children". 2002-09-01 13:43 Martin Pool * src/serve.c: Doc. 2002-09-01 09:18 Martin Pool * src/serve.c: Doc. 2002-09-01 09:09 Martin Pool * src/serve.c: Doc. 2002-09-01 09:07 Martin Pool * src/distcc.c: dcc_compile_remote: Better log message 2002-09-01 09:06 Martin Pool * src/serve.c: dcc_accept_job: Better log message 2002-09-01 09:05 Martin Pool * src/distcc.c: Fix silly parameter order bug. 2002-09-01 08:55 Martin Pool * src/dparent.c: Get rid of cloexec, just close fds by hand. 2002-09-01 08:52 Martin Pool * src/serve.c: Typo 2002-09-01 08:50 Martin Pool * src/exec.c, NEWS: Close extra file descriptors before starting the compiler. 2002-09-01 08:46 Martin Pool * src/dparent.c: Set close-on-exec flags on listen and accepted fds. 2002-09-01 08:43 Martin Pool * src/: util.c, util.h: set_cloexec_flag: new function 2002-09-01 08:39 Martin Pool * src/serve.c: Doc 2002-09-01 08:38 Martin Pool * src/: distcc.c, serve.c: dcc_accept_job: * Use new dcc_mkfifo routine to make sure the fifo is created properly. * Use new dcc_r_file_body, dcc_r_file and dcc_r_fifo routines to make sure each type of temporary file is opened in the right way. 2002-09-01 08:36 Martin Pool * src/daemon.c: tempfile.h: new header 2002-09-01 08:34 Martin Pool * NEWS: Doc mkfifo changes and BigAssFile_Case 2002-09-01 08:31 Martin Pool * src/tempfile.c: dcc_mkfifo: * New routine. * We now unlink before trying to create a fifo, to make sure that if somehow that name is already in use by a file or fifo we won't get confused. 2002-09-01 08:29 Martin Pool * src/: rpc.h, bulk.h: bulk.h: new header 2002-09-01 08:28 Martin Pool * src/io.c: needs exitcode.h 2002-09-01 08:27 Martin Pool * src/: bulk.c, dparent.c, where.c: tempfile.h: new header 2002-09-01 07:52 Martin Pool * src/: tempfile.h, distcc.h: Split out tempfile.c routines into their own header 2002-09-01 07:49 Martin Pool * src/bulk.c: Doc. dcc_r_file: * Unlink the name before starting to receive the file. This may prevent bugs where the name already existed as a fifo. The old code would have opened the fifo rather than replacing it, and therefore would hang. Afterwards, create with O_EXCL. * Check that the file is successfully closed. (Might catch ENOSPC or similar.) dcc_r_fd: Fix return code to be the result of transferring the contents of the file. 2002-09-01 07:40 Martin Pool * src/io.c: dcc_close: make return code consistent (EXIT_IO_ERROR, not errno) 2002-09-01 07:39 Martin Pool * src/exitcode.h: Add EXIT_IO_ERROR 2002-09-01 07:37 Martin Pool * src/io.c: dcc_close: log file descriptor correctly. 2002-08-31 14:50 Martin Pool * src/bulk.c: Doc 2002-08-31 14:45 Martin Pool * test/testdistcc.py, src/clinet.c: Doc 2002-08-31 14:43 Martin Pool * src/clinet.c: Doc. Make variables consistent. 2002-08-31 14:31 Martin Pool * src/distcc.c: Doc. 2002-08-31 14:23 Martin Pool * src/: bulk.c, serve.c: Doc. 2002-08-31 14:13 Martin Pool * src/: bulk.c, io.c, io.h, rpc.c, rpc.h, serve.c: dcc_r_token_int: Add common routine for reading token and parameter value. 2002-08-31 14:01 Martin Pool * src/rpc.c: Doc. 2002-08-31 13:58 Martin Pool * src/: io.c, io.h: dcc_write_token: remove dead function 2002-08-31 13:56 Martin Pool * src/io.c: Cleanup sendfile code somewhat. 2002-08-31 13:48 Martin Pool * NEWS, linuxdoc/distcc.sgml, src/distcc.c, src/io.c, src/tempfile.c, src/util.c, src/util.h: dcc_getenv_bool: Add parameter giving default value so that things can default to either on or off. Add new environment variable for client and server, DISTCC_TCP_CORK. Defaults to on, intended mostly for performance comparison or debugging. 2002-08-31 13:44 Martin Pool * src/rpc.c: Fix prototype Use dcc_x_token_int in one case I missed before 2002-08-31 12:41 Martin Pool * NEWS, src/bulk.c, src/distcc.c, src/rpc.c, src/rpc.h: Write token/parameters using a single write() call. May be very slightly more efficient in CPU and perhaps packets. 2002-08-31 12:13 Martin Pool * src/io.c: Doc. 2002-08-30 10:53 Martin Pool * src/dparent.c: Doc. 2002-08-30 10:51 Martin Pool * src/serve.c: Put cork in correct hole. 2002-08-29 11:43 Martin Pool * src/trace.c: Doc. 2002-08-29 11:18 Martin Pool * NEWS, src/io.c: Handle the case of sendfile() transmitting only part of the supplied data, similarly to a short write on a socket. This doesn't often happen, but can occur if a ptrace debugger attaches while sendfile is running. 2002-08-29 10:35 Martin Pool * NEWS, src/distcc.c: Message for completion of local cpp now gives the correct hostname. 2002-08-29 10:21 Martin Pool * src/Makefile.in: Include $CFLAGS when linking so that profiling works 2002-08-29 10:17 Martin Pool * NEWS: Display test names while they're running so that long tests are easier to follow. 2002-08-29 10:06 Martin Pool * NEWS: Doc 2002-08-29 10:05 Martin Pool * test/testdistcc.py: When trying to kill the daemon, keep pinging it to make sure it actually died. This prevents the cases sometimes tripping over each other. Fix damage to assembly cases from previous commit Doc Remove some dead code 2002-08-29 09:49 Martin Pool * src/dparent.c: Create the pid file from the parent process, so that we can be sure that it exists before the parent exits. 2002-08-29 09:24 Martin Pool * src/dparent.c: Turn on signal handlers in parent. Why were they off? 2002-08-29 08:50 Martin Pool * test/testdistcc.py: Add missing newline 2002-08-29 08:50 Martin Pool * test/testdistcc.py: Add test for compilation of a large file (200,000 lines) 2002-08-29 08:13 Martin Pool * src/serve.c: Uncork sock before exiting. 2002-08-29 06:50 Martin Pool * src/bulk.c: quote 2002-08-28 11:33 Martin Pool * test/testdistcc.py: Doc. 2002-08-28 10:35 Martin Pool * NEWS, src/tempfile.c: Properly support platforms with 32-bit pids, such as Cygwin. Patch from Aaron Lehmann. 2002-08-28 10:18 Martin Pool * src/Makefile.in: Remove 'check' target because it must be run from the parent 2002-08-26 09:37 Martin Pool * linuxdoc/distcc.sgml: Notes about Cygwin and LNX-BBC volunteers into TODO list. 2002-08-26 08:52 Martin Pool * NEWS, configure, configure.ac: On FreeBSD, the sa_family_t type is defined in (Patch from Dennis Taylor) 2002-08-26 08:48 Martin Pool * aclocal.m4, configure, configure.ac, NEWS: Bump version to 0.9cvs 2002-08-26 08:43 Martin Pool * NEWS, OLDNEWS: roll over news 2002-08-15 18:51 Martin Pool * configure: autoconf 2002-08-15 18:41 Martin Pool * configure.ac: Set version 2002-08-15 14:39 Martin Pool * NEWS: Ready for release. 2002-08-15 12:56 Martin Pool * src/distcc.c: Tweak message 2002-08-15 12:45 Martin Pool * test/testdistcc.py: Add assertReMatch utility function When testing invalid server names, look in the log for the warning message. 2002-08-15 12:24 Martin Pool * src/distcc.c: Only emit the "running locally" notice when the job ought to be distributed but is not. So having the host set to be local, or non-distributable arguments just silently works. 2002-08-15 12:10 Martin Pool * src/tempfile.c: Add headers, remove dead variable 2002-08-15 12:03 Martin Pool * src/filename.c: Doc 2002-08-15 11:59 Martin Pool * src/serve.c: dcc_accept_job: patch from Chris Halls to make us more robust against files where we can't work out the preprocessor extension. 2002-08-15 11:57 Martin Pool * NEWS, src/filename.c: Correctly handle compilation of C++ code under ccache, by properly recognizing the .ii extension. Same patch from both Stephen White and Chris Halls. 2002-08-15 11:17 Martin Pool * configure: Run autoconf 2002-08-12 06:36 Martin Pool * configure.ac: Fix quoting. 2002-08-10 15:28 Martin Pool * src/where.c: Doc. Don't truncate lock files, open them with open(). 2002-08-10 15:26 Martin Pool * src/bulk.c: Doc. 2002-08-10 15:19 Martin Pool * src/: distcc.c, exec.c: Doc. 2002-08-10 15:13 Martin Pool * linuxdoc/distcc.sgml: Explain that we don't keep trying if we fail to connect. 2002-08-10 15:11 Martin Pool * src/distcc.c: Doc. 2002-08-10 15:08 Martin Pool * NEWS, src/distcc.c, test/testdistcc.py: If anything goes wrong with remote compilation other than the remote compiler returning an error, then run it locally instead. 2002-08-10 15:07 Martin Pool * src/tempfile.c: dcc_getenv_bool(): new function to make behaviour of DISTCC_VERBOSE etc consistent. 2002-08-10 15:05 Martin Pool * src/: arg.c, dparent.c: Adjust error severity levels. 2002-08-10 15:04 Martin Pool * src/trace.c: rs_format_msg: put the function name before the severity rather than after. I hate to change message formats but this seems more readable. 2002-08-10 15:01 Martin Pool * src/: util.c, util.h: dcc_getenv_bool(): new function to make behaviour of DISTCC_VERBOSE etc consistent. 2002-08-10 14:59 Martin Pool * src/trace.c: Make notice messages have a "Notice: " prefix. 2002-08-10 14:50 Martin Pool * src/clinet.c: Doc 2002-08-10 14:39 Martin Pool * test/testdistcc.py: Put all scratch directories under 'testtmp' to keep things tidy. 2002-08-10 14:19 Martin Pool * configure: Run autoconf 2002-08-09 18:10 Martin Pool * linuxdoc/distcc.sgml: Clearer text about env vars. 2002-08-09 18:08 Martin Pool * linuxdoc/distcc.sgml: Add doc for DISTCC_SAVE_TEMPS 2002-08-09 18:02 Martin Pool * survey.txt: Better text. 2002-08-09 17:59 Martin Pool * survey.txt: Better text. 2002-08-09 17:56 Martin Pool * Makefile.in: Upload survey. 2002-08-09 17:55 Martin Pool * Makefile.in: Install survey.txt into docs 2002-08-09 17:53 Martin Pool * configure, configure.ac, survey.txt, src/survey.txt: Running configure now shows a click-wrapish version of the GPL, plus information on installation directories, and a request to complete the survey. 2002-08-09 17:42 Martin Pool * README: Add survey 2002-08-09 17:33 Martin Pool * src/survey.txt: Add survey 2002-08-09 16:43 Martin Pool * NEWS: Add documentation for --no-fifo and --log-stderr. 2002-08-09 16:29 Martin Pool * linuxdoc/distcc.sgml: Add documentation for --no-fifo and --log-stderr. 2002-08-09 16:15 Martin Pool * NEWS: Show host specification syntax in --help 2002-08-09 16:13 Martin Pool * src/distcc.c: Better --help message 2002-08-09 16:11 Martin Pool * src/distcc.c: Show host specification syntax in --help 2002-08-09 16:02 Martin Pool * NEWS, OLDNEWS: Roll over NEWS 2002-08-09 16:01 Martin Pool * linuxdoc/distcc.sgml: Document that $DISTCC_HOSTS can now specify ports. 2002-08-08 12:27 Martin Pool * contrib/dmake: Example script contributed by Luke Gorrie 2002-08-05 23:33 Martin Pool * Makefile.in: There's always one. 2002-08-05 23:25 Martin Pool * Makefile.in: Add rules to build NEWS and signature files, and to upload everything to the ftp site. 2002-08-05 23:19 Martin Pool * configure, configure.ac: Bump version to 0.7; run autoconf. 2002-08-05 23:19 Martin Pool * README: Note that it probably works on Cygwin now. 2002-08-05 23:07 Martin Pool * DEPENDENCIES: Add --with-extra-includes and --with-extra-libs configure options, as in CVS. This helps people on platforms such as Solaris and BSD where some things install into /usr/local, but that is not on the default path. 2002-08-05 23:01 Martin Pool * configure.ac, src/Makefile.in: Add --with-extra-includes and --with-extra-libs configure options, as in CVS. This helps people on platforms such as Solaris and BSD where some things install into /usr/local, but that is not on the default path. 2002-08-05 19:47 Martin Pool * Makefile.in: Another attempt at packaging and installing the manual, but coping on machines without linuxdoc. 2002-08-05 19:46 Martin Pool * src/serve.c: Doc. 2002-08-05 19:39 Martin Pool * Makefile.in: Make 'all' the default target again. 2002-08-05 19:28 Martin Pool * Makefile.in: Fix packaging of Linuxdoc html. 2002-08-05 19:22 Martin Pool * NEWS: Set version for release. 2002-08-05 15:44 Martin Pool * Makefile.in: Make all latte HTML files depend on style.latte 2002-08-05 15:15 Martin Pool * linuxdoc/distcc.sgml: Add todo 2002-08-03 23:31 Martin Pool * NEWS: Doc 2002-08-03 23:29 Martin Pool * NEWS: Add release name 2002-08-03 23:28 Martin Pool * NEWS: Note that documentation is shipped. 2002-08-03 18:21 Martin Pool * linuxdoc/distcc.sgml: We could strip -D and -I from command lines. 2002-08-02 15:00 Martin Pool * test/testdistcc.py: Remove debugging stub 2002-08-02 14:58 Martin Pool * src/exec.c: Remove old message 2002-08-02 14:56 Martin Pool * test/testdistcc.py: Don't try to link file which is expected not to compile. 2002-08-02 14:43 Martin Pool * test/testdistcc.py: Run daemon on port 42000 for testing. Check that compiling an invalid file produces no output file. Use absolute path for pid file so that it's not confused by changing directories. 2002-08-02 14:28 Martin Pool * NEWS: host:port syntax now supported. 2002-08-02 14:23 Martin Pool * src/: distcc.c, distcc.h, dparent.c, exec.c, hosts.c, hosts.h, serve.c, where.c: Move towards using passing around dcc_hostdef structures, rather than just hostnames, so that we can start supporting nonstandard ports and eventually ssh. 2002-08-02 14:20 Martin Pool * src/filename.c: Use strrchr() rather than rindex(): they ought to be identical, but Valgrind seems to dislike rindex() 2002-08-02 14:19 Martin Pool * src/arg.c: Doc 2002-08-02 11:59 Martin Pool * NEWS: --log-stderr 2002-08-02 11:56 Martin Pool * src/: daemon.c, dopt.c, opt.h: Add --log-stderr option, intended mainly for testing/debugging 2002-08-02 11:39 Martin Pool * .cvsignore: Ignore *.tmp 2002-08-02 11:36 Martin Pool * test/testdistcc.py: Run all test cases within their own scratch directory. 2002-08-01 23:58 Martin Pool * src/serve.c: Add the ability to use either a fifo or a regular temporary file for input to the compiler, controlled by --no-fifo or failure to create the fifo. 2002-08-01 23:39 Martin Pool * src/: daemon.c, dparent.c, serve.c: dcc_accept_job: return standard exit code 2002-08-01 23:34 Martin Pool * src/: daemon.c, dparent.c, io.c, io.h: Explicitly close the socket before exiting, so that we have a better chance of catching network transmission errors. 2002-08-01 23:20 Martin Pool * NEWS, src/dopt.c, src/opt.h: Add --no-fifo option. Doesn't do anything yet. 2002-08-01 23:19 Martin Pool * Makefile.in: Fix cvsplot target. 2002-08-01 23:17 Martin Pool * NEWS: Doc 2002-08-01 23:12 Martin Pool * contrib/distcc.sh: This file, contributed by Dimitri PAPADOPOULOS-ORFANOS may be installed as "cc" somewhere on your $PATH ahead of the real gcc. That allows you to just use regular Makefiles without modifying them to change hardcoded calls to cc. This script will be a bit slow because of the overhead of running things through a shell. In a future release, this function should be supported directly by distcc, which should be a bit faster. 2002-08-01 23:02 Martin Pool * src/dparent.c: Define WAIT_ANY if it is missing, as seems to be the case on Cygwin. 2002-08-01 22:11 Martin Pool * src/exec.c: Doc. 2002-08-01 22:07 Martin Pool * src/serve.c: Cygwin needs not 2002-08-01 21:44 Martin Pool * src/exec.c: Cope without WCOREDUMP, which is missing on Cygwin. 2002-08-01 21:34 Martin Pool * NEWS, configure, configure.ac, src/config.h.in, src/distcc.h: If sa_family_t is missing, try just defining it as int. Might help Cygwin. 2002-08-01 21:16 Martin Pool * src/where.c: Try using fcntl locks in addition to lockf and flock. Perhaps this will fix Cygwin. Thanks to Marco Alanen. 2002-08-01 17:41 Martin Pool * src/: daemon.c, dopt.c, opt.h: Make errors from command-line options go to stderr. 2002-08-01 17:14 Martin Pool * Makefile.in: Always build check programs before running checks, even with -j. Specify complete PATH to binaries when running tests, so that they can change into subdirectories. 2002-07-25 17:14 Martin Pool * Makefile.in: Remove file that's no longer in CVS from distro. 2002-07-25 17:11 Martin Pool * doc/results.txt: Add results file; not much here yet. 2002-07-25 16:58 Martin Pool * Makefile.in: Add a somewhat-hacky "make dist" target to build a tarball. Compared to just "cvs export", this means we get to include built versions of the documents, which is nice for people who can't easily get the Linuxdoc SGML tools to work. It does make the binary bigger because there are so many formats, though. Also, we omit things that end users might not want, such as the Latte web site source. People can get it from CVS (or rsync) if they care. 2002-07-25 16:08 Martin Pool * configure, configure.ac: Bump version 2002-07-24 19:03 Martin Pool * test/testdistcc.py: Clear the environment before running the child -- this avoids any problems with the developer's environment. 2002-07-24 19:02 Martin Pool * src/dparent.c: Change the semantics for detaching a little bit: we now do it once the socket is listening. This is rather more useful for the test suite, because the suite now knows for sure that when the parent exits, it can go ahead and try to connect. 2002-07-24 18:58 Martin Pool * DEPENDENCIES, Makefile.in: Test case now requires python 2.2 for proper unsetenv() semantics 2002-07-24 18:50 Martin Pool * NEWS: foo 2002-07-24 18:49 Martin Pool * src/tempfile.c: Avoid using asprintf() because it's missing on Solaris 2002-07-24 18:49 Martin Pool * src/where.c: dcc_make_lock_filename: new function Avoid using asprintf() because it's missing on Solaris 2002-07-24 18:48 Martin Pool * src/exitcode.h: Doc 2002-07-24 17:57 Martin Pool * src/dparent.c: remove pid file if daemon exits on signal 2002-07-24 17:55 Martin Pool * src/dparent.c, NEWS: Log pid even if running with --no-fork. Remove pid file on exit. 2002-07-24 14:39 Martin Pool * Makefile.in, configure, configure.ac, patches/distc, patches/distc++: Suggestion from Dimitri PAPADOPOULOS-ORFANOS: should check for -lnsl and -lsocket on Solaris. 2002-07-24 14:38 Martin Pool * OLDNEWS, NEWS: Roll over news 2002-07-23 11:36 Martin Pool * Makefile.in: Add the start of an FAQ, and the AOSS4 slides. 2002-07-22 16:45 Martin Pool * Makefile.in: Doc. 2002-07-12 11:46 Martin Pool * configure: Rerun autoconf 2002-07-12 11:44 Martin Pool * Makefile.in: "make install" doesn't imply install-linuxdoc 2002-07-12 11:38 Martin Pool * Makefile.in: "make install" doesn't imply install-linuxdoc 2002-07-12 11:34 Martin Pool * test/testdistcc.py: Start adding to the test framework a way for test cases to provide their own explanation of why they failed. In particular, for ones that run shell commands, dump out all the commands that were run, and their output. 2002-07-12 11:33 Martin Pool * src/distcc.c: Give a proper error message for "distcc --fubar", even when we would have chosen to run the command locally. 2002-07-12 11:32 Martin Pool * src/daemon.c: If stdin is neither a socket nor a tty assume --daemon mode. This is more compatible with previous usage. 2002-07-12 11:19 Martin Pool * src/arg.c: Correct message for "distcc --bad-option" 2002-07-12 10:51 Martin Pool * configure.ac: Set version for release. 2002-07-12 10:45 Martin Pool * NEWS: Update news for release. 2002-07-12 10:39 Martin Pool * DEPENDENCIES: Clarify requirements for libpopt 2002-07-12 10:37 Martin Pool * Makefile.in: Install info files into the right directory 2002-07-10 15:37 Martin Pool * src/arg.c: dcc_set_action_opt: Need to also understand how to transform "gcc -S hello.c" to "gcc -o hello.i -E hello.c" for the client. 2002-07-10 15:11 Martin Pool * NEWS, src/arg.c, src/distcc.h, src/filename.c: distcc will now distribute jobs which use -s to compile but not assemble. Previously they were always run locally, but there's no strong reason why they must be. Unfortunately you need to upgrade both the client and server for this to work, because old servers will refuse to run gcc with -s. 2002-07-10 14:07 Martin Pool * NEWS, src/tempfile.c: dcc_cleanup_tempfiles: If $DISTCC_SAVE_TEMPS is set to "1", then files are not actually deleted -- good for debugging. 2002-07-09 14:38 Martin Pool * Makefile.in: Add page with current problems 2002-07-09 12:06 Martin Pool * Makefile.in: Add target to run Linbot to check for broken links. 2002-07-08 17:20 Martin Pool * configure: autogen 2002-07-08 17:18 Martin Pool * src/: daemon.c, distcc.h: Fix prototypes 2002-07-08 17:17 Martin Pool * src/dopt.c: distccd_show_usage: Document new options 2002-07-08 17:16 Martin Pool * NEWS: dcc_scan_args: -M causes the preprocessor to produce a list of make-style dependencies on header files, either to stdout or to a local file. It implies -E, so only the preprocessor is run, not the compiler. There would be no point trying to distribute it even if we could. 2002-07-08 17:13 Martin Pool * src/daemon.c, linuxdoc/distcc.sgml: Change --inetd and --daemon defaults: - if both are specified, die - if either is specified, do that - if stdin is a socket or tty assume inetd or daemon respectively - otherwise, complain 2002-07-08 17:03 Martin Pool * linuxdoc/distcc.sgml: Document more distccd command-line options 2002-07-08 17:00 Martin Pool * man/distcc.1: Syntax fix 2002-07-08 16:57 Martin Pool * DEPENDENCIES: Clarify dependencies 2002-07-08 16:54 Martin Pool * linuxdoc/distcc.sgml: Clarify that distcc returns the same value as the compiler. 2002-07-08 16:53 Martin Pool * linuxdoc/distcc.sgml: Clarify description how to get environment variables set properly. 2002-07-08 16:50 Martin Pool * linuxdoc/distcc.sgml: Clarify description of jobs which are distributed or local, give an example of a typical command that can be distributed. 2002-07-08 16:46 Martin Pool * src/arg.c: dcc_scan_args: -M causes the preprocessor to produce a list of make-style dependencies on header files, either to stdout or to a local file. It implies -E, so only the preprocessor is run, not the compiler. There would be no point trying to distribute it even if we could. 2002-07-08 16:33 Martin Pool * Makefile.in: Doc. 2002-07-07 22:23 Martin Pool * NEWS: Works on FreeBSD? 2002-07-07 22:12 Martin Pool * src/Makefile.in: Have to respect $LDFLAGS so we can build on BSD. Thanks Lauri! 2002-07-07 22:11 Martin Pool * test/testdistcc.py: SyntaxError_Case: Be less fussy about the exact compiler error message 2002-07-07 21:58 Martin Pool * configure.ac: Doc. 2002-07-07 21:52 Martin Pool * test/testdistcc.py: --version output has changed to include build date and to just say "protocol 1" 2002-07-07 21:46 Martin Pool * src/arg.c: Temporary fix for "distcc -c hello.c" 2002-07-07 21:43 Martin Pool * NEWS: Note about valgrind fix 2002-07-07 21:02 Martin Pool * Makefile.in: We don't build the web pages or manual by default, because many people will not have the tools to do it. Just use all-web or all-linuxdoc if you want them. 2002-07-07 21:01 Martin Pool * DEPENDENCIES, README: Put the documentation of dependencies in a separate file where it can be more easily found by people doing ports. 2002-07-07 20:08 Martin Pool * src/arg.c: dcc_argv_tostr: If out of memory, give an error and exit, rather than aborting. Apparently Valgrind doesn't like using strchr(s, 0) to find the terminating nul. I wonder why? 2002-07-07 19:51 Martin Pool * src/distcc.h: Add missing prototype 2002-07-07 19:40 Martin Pool * src/: .cvsignore, h_argvtostr.c: Start new test case h_argvtostr 2002-07-07 19:38 Martin Pool * src/: Makefile.in, arg.c, filename.c, distcc.h: Split filename manipulation code out into new file filename.c 2002-07-07 19:36 Martin Pool * src/distcc.c: Get ready to handle command lines with implied compiler. 2002-07-06 18:24 Martin Pool * src/arg.c: Doc about the idea of handling "distcc -c hello.c" 2002-07-06 18:11 Martin Pool * src/distcc.c: Remove old docs. 2002-07-06 18:07 Martin Pool * linuxdoc/distcc.sgml: Document --ping option. 2002-07-06 18:00 Martin Pool * linuxdoc/distcc.sgml: The log now shows execution time; remove this from the todo list. 2002-07-06 16:49 Martin Pool * src/: clinet.c, clinet.h, distcc.c, distcc.h: dcc_open_socket_out: use the standard error return mechanism 2002-07-06 16:44 Martin Pool * src/: daemon.c, dparent.c: Include build date/time in daemon startup message 2002-07-06 16:41 Martin Pool * src/help.c: dcc_show_version: Include build date/time 2002-07-06 16:32 Martin Pool * src/clinet.c: dcc_open_socket_out: Return EXIT_CONNECT_FAILED if it did (or indeed for all client socket-opening errors at the moment.) 2002-07-06 16:24 Martin Pool * linuxdoc/distcc.sgml: Notes about distcc with autoconf.Doc. 2002-07-06 16:18 Martin Pool * src/: distcc.c, distcc.h, exec.c, serve.c, util.c, util.h: myhostname: rename to dcc_gethostname for consistency dcc_spawn_child, dcc_redirect_fds: add another parameter specifying redirection for stdin, so that the same routine can be used on the client (with regular stdin) or on the server (with /dev/null) dcc_compile_local: Run the compiler as a child process, not over the top of us. distcc/main: Log exit code. 2002-07-06 16:02 Martin Pool * src/distcc.c: Rename dcc_run_remote and dcc_build_locally to dcc_compile_* to be consistent. 2002-07-06 15:57 Martin Pool * src/exec.c: Doc. 2002-07-06 15:56 Martin Pool * NEWS: dcc_exit: Show self and children's CPU time usage when exiting. 2002-07-06 15:54 Martin Pool * linuxdoc/distcc.sgml, src/where.c: dcc_pick_buildhost: If the host specification is invalid or missing, fall back to building locally with a warning. 2002-07-06 15:51 Martin Pool * src/where.c: dcc_pick_buildhost: bug fix: if we fail to parse the host specification, then return the right error. 2002-07-06 15:50 Martin Pool * linuxdoc/distcc.sgml: More detail on handling of invalid hostspecs. 2002-07-06 15:46 Martin Pool * src/util.c: dcc_exit: Show self and children's CPU time usage when exiting. 2002-07-05 17:12 Martin Pool * linuxdoc/distcc.sgml: Note about libtool. 2002-07-05 16:48 Martin Pool * linuxdoc/distcc.sgml: Add note about Makefiles which don't use $(CC). 2002-07-05 12:48 Martin Pool * NEWS, src/daemon.c, src/dopt.c, src/opt.h: Add --daemon and --inetd options, so that you can properly start a remote daemon with a single-line ssh command. 2002-07-05 12:32 Martin Pool * src/dparent.c: Need sys/ioctl.h 2002-07-05 11:31 Martin Pool * configure, configure.ac: Put docs in $prefix/share/doc 2002-07-05 11:21 Martin Pool * Makefile.in: Add "make showpaths" target to show where "make install" will put things. 2002-07-04 23:42 Martin Pool * NEWS: Show CPU usage of compiler, cpp, etc 2002-07-04 23:39 Martin Pool * .cvsignore, src/daemon.c, src/distcc.c, src/distcc.h, src/exec.c, src/serve.c: Show CPU usage of compiler, cpp, etc 2002-07-04 23:38 Martin Pool * Makefile.in: Fix "make install" 2002-07-04 23:23 Martin Pool * Makefile.in: Shush linuxdoc 2002-07-04 23:10 Martin Pool * src/exec.c: Doc. 2002-07-04 23:06 Martin Pool * src/exec.c: Better trace message. 2002-07-04 23:06 Martin Pool * src/dparent.c: Doc. 2002-07-04 23:05 Martin Pool * src/exec.c: Fix inverted test on waitpid() result. Doc. 2002-07-04 23:01 Martin Pool * src/serve.c: Doc (passing server errors back to client) 2002-07-04 22:56 Martin Pool * linuxdoc/distcc.sgml: Note about tcpwrappers. Note that you can now set the server port number. 2002-07-04 22:46 Martin Pool * src/daemon.c: Doc. 2002-07-04 22:15 Martin Pool * Makefile.in: distclean removes config.log Better maintainer-clean rules 2002-07-04 22:12 Martin Pool * test/testdistcc.py: Doc. 2002-07-04 22:03 Martin Pool * Makefile.in, linuxdoc/.cvsignore, man/.cvsignore: More Makefile fiddling - make "all" the default rule again - add "upload-linuxdoc" - try make SGML stuff build properly 2002-07-04 21:48 Martin Pool * Makefile.in, configure, configure.ac, linuxdoc/Makefile.in: Move linuxdoc stuff into top-level Makefile too 2002-07-04 21:31 Martin Pool * Makefile.in, configure, configure.ac, man/Makefile.in: Move man/ makefile into top level 2002-07-03 23:11 Martin Pool * Makefile.in: New design of the web site, now using Latte. 2002-07-03 20:31 Martin Pool * Makefile.in, analog/Makefile, analog/distcc.analog: Fiddle analog Make rules; use jdresolve to do DNS resolution. 2002-07-03 19:58 Martin Pool * analog/.cvsignore: Ignore more stuff 2002-07-03 16:57 Martin Pool * Makefile.in: Further Makefile fudging 2002-07-03 16:54 Martin Pool * analog/.cvsignore: Ignore built files. 2002-07-03 16:47 Martin Pool * Makefile.in: Move web/latte rules into top-level Makefile. Add more maintainer-clean rules 2002-07-02 17:14 Martin Pool * linuxdoc/distcc.sgml: We now have proper C++ support, so s/C/C or C++/ where appropriate. 2002-07-02 17:11 Martin Pool * man/: distcc.1, distccd.1: Update manpages, and remove information that is redundant with the SGML manual. I think between them, the big manual and --help are more useful than man pages, and they're certainly easier to maintain. 2002-07-02 12:05 Martin Pool * linuxdoc/distcc.sgml: Add bug. 2002-07-01 19:39 Martin Pool * linuxdoc/distcc.sgml: Clearer explanation of multiprocessor scheduling. 2002-07-01 19:36 Martin Pool * linuxdoc/distcc.sgml: Add CVS revision. 2002-07-01 19:35 Martin Pool * linuxdoc/distcc.sgml: Add new error codes 105, 106 2002-07-01 19:32 Martin Pool * linuxdoc/distcc.sgml: Make titles consistent 2002-07-01 19:31 Martin Pool * linuxdoc/distcc.sgml: Remove redundant SMP section 2002-07-01 19:27 Martin Pool * linuxdoc/distcc.sgml: "Leaky buckets" explanation of scheduling algorithm. 2002-07-01 09:38 Martin Pool * src/serve.c: Doc 2002-07-01 09:34 Martin Pool * src/dopt.c: Fix small syntax error 2002-07-01 09:34 Martin Pool * src/dopt.c: Add --verbose option for daemon 2002-07-01 09:23 Martin Pool * NEWS: emacs-fu 2002-07-01 09:22 Martin Pool * NEWS: Reformat 2002-07-01 09:15 Martin Pool * NEWS, src/daemon.c, src/distcc.h, src/dparent.c, src/serve.c: Move check for !getuid() up to a higher level so that the daemon refuses to start at all. 2002-07-01 09:08 Martin Pool * linuxdoc/distcc.sgml: Improved quick-start guide. 2002-06-30 22:01 Martin Pool * linuxdoc/: distcc.sgml: Better URL link. 2002-06-30 21:59 Martin Pool * linuxdoc/distcc.sgml: Add link to ccache. 2002-06-30 21:59 Martin Pool * linuxdoc/distcc.sgml: Clarify bug about compilers which touch local files. 2002-06-30 21:58 Martin Pool * linuxdoc/distcc.sgml: Clarify large-file message. 2002-06-30 21:55 Martin Pool * linuxdoc/distcc.sgml: Substantially improved section on cross-compilation; give more details on how to use -b. 2002-06-30 17:32 Martin Pool * analog/distcc.analog: Show more referers 2002-06-30 17:32 Martin Pool * test/testdistcc.py: Fix regexp for new error message. 2002-06-30 17:31 Martin Pool * src/: .cvsignore, Makefile.in, hosts.c, where.c: Change to new hostspec parser 2002-06-30 00:34 Martin Pool * test/testdistcc.py: All tests now moved across to new framework 2002-06-30 00:26 Martin Pool * test/testdistcc.py: Go back to purely object-based definitions of test cases 2002-06-30 00:02 Martin Pool * test/testdistcc.py: Fiddle with comfychair interface 2002-06-30 00:00 Martin Pool * src/: trace.c, trace.h: Rename rs_trace_stderr to rs_trace_to_file, a more correct name. 2002-06-29 23:59 Martin Pool * src/dopt.c: Add --log-file option 2002-06-29 23:58 Martin Pool * src/: dparent.c, distcc.h: Make dcc_become_daemon private 2002-06-29 23:57 Martin Pool * analog/Makefile: Fix Makefile 2002-06-29 23:28 Martin Pool * test/testdistcc.py: Make comfychair more OO. 2002-06-29 23:14 Martin Pool * src/serve.c: Refuse to run daemon as root. 2002-06-29 23:13 Martin Pool * src/hosts.c: Doc. 2002-06-29 23:00 Martin Pool * doc/scheduling.txt: Notes on scheduling 2002-06-29 16:39 Martin Pool * src/OLDNEWS: Moved 2002-06-29 01:49 Martin Pool * test/testdistcc.py: Add more host parser cases. 2002-06-29 01:44 Martin Pool * src/hosts.c: Correctly handle ssh tokens with command specified. 2002-06-29 01:42 Martin Pool * src/h_hosts.c, src/hosts.c, src/hosts.h, test/testdistcc.py: Add special host type for local compilation. 2002-06-29 01:38 Martin Pool * test/testdistcc.py: Better hosts parser test 2002-06-29 01:37 Martin Pool * src/hosts.c: Fix parser bug in tcp with specified port. 2002-06-29 01:32 Martin Pool * test/testdistcc.py: Doc. 2002-06-29 01:25 Martin Pool * test/testdistcc.py: Add test case for host specification parser. 2002-06-29 01:24 Martin Pool * src/hosts.c: Hosts parser that works better with missing components. 2002-06-29 00:53 Martin Pool * test/testdistcc.py: Move more tests from pyunit to comfychair. It's definitely more comfortable! 2002-06-29 00:39 Martin Pool * test/testdistcc.py: Move more tests from pyunit to comfychair. It's definitely more comfortable! 2002-06-28 23:23 Martin Pool * src/srvnet.c: Also show numeric client address in connection message 2002-06-28 23:19 Martin Pool * linuxdoc/Makefile.in: Fix Makefile a bit more 2002-06-28 23:15 Martin Pool * linuxdoc/Makefile.in: Fix Makefile 2002-06-28 23:14 Martin Pool * linuxdoc/distcc.sgml: Bump version. Note about IPv6 2002-06-28 23:03 Martin Pool * src/dparent.c: Doc. 2002-06-28 23:01 Martin Pool * src/dparent.c: When in no-fork mode, clean up files after each job 2002-06-28 22:59 Martin Pool * src/Makefile.in: Drop sbin install target. 2002-06-28 22:49 Martin Pool * src/tempfile.c: Doc. 2002-06-28 22:14 Martin Pool * src/: dopt.c, dparent.c, opt.h: Add --no-fork option to daemon to help with some debugging stuff. 2002-06-28 21:51 Martin Pool * man/distcc.1: Add newline 2002-06-28 21:50 Martin Pool * man/distccd.1: Make a slightly more useful distccd manpage 2002-06-28 21:41 Martin Pool * analog/Makefile: Create report/ subdir if it doesn't exist. 2002-06-28 21:40 Martin Pool * linuxdoc/Makefile.in: Create html/ subdir if it doesn't exist. 2002-06-28 18:35 Martin Pool * README: Make it clear that we do C++ too! Try to explain relationship to gcc. 2002-06-28 18:20 Martin Pool * test/testdistcc.py: test_option_version: Handle host triples like i386-unknown-freebsd4.4 (Claes Wallin) 2002-06-28 16:57 Martin Pool * src/dparent.c: Doc. 2002-06-28 16:53 Martin Pool * src/: dparent.c, exec.c: The two routines that call waitpid() must handle EINTR, in case a signal arrives while waiting. (Perhaps on BSD if a child exits, you will break out with SIGCHLD and then need to wait again? Not sure.) 2002-06-28 16:49 Martin Pool * Makefile.in: Add target to run old (currently broken) pyunit tests 2002-06-28 16:47 Martin Pool * src/distcc.h: Add prototypes for hosts.c 2002-06-28 16:33 Martin Pool * src/serve.c: Doc. 2002-06-28 16:19 Martin Pool * src/: io.c: Better message. 2002-06-28 16:13 Martin Pool * src/Makefile.in: distccd ought to be in bin/; add rationale. 2002-06-28 16:04 Martin Pool * NEWS, src/io.c: If the system supports sendfile, but the particular filesystem we're on (e.g. tmpfs) doesn't, then fall back to using read/write. 2002-06-28 16:02 Martin Pool * src/Makefile.in: Makefile must properly inherit configured variables 2002-06-28 16:01 Martin Pool * man/Makefile.in: Remove old Makefile target to do with pre-processed manpages 2002-06-28 16:00 Martin Pool * configure: foo 2002-06-28 15:59 Martin Pool * man/Makefile.in: distccd can be run by ordinary users, so arguably belongs in section 1. 2002-06-28 13:20 Martin Pool * NEWS: Foo 2002-06-28 13:18 Martin Pool * README: Update README. 2002-06-28 13:12 Martin Pool * src/Makefile.in: Make directories before installing into them. 2002-06-28 13:08 Martin Pool * OLDNEWS: Merge news from 0.5 and make format consistent. 2002-06-28 13:07 Martin Pool * Makefile.in: Also install top-level documentation (e.g. README) 2002-06-28 13:05 Martin Pool * configure.ac, linuxdoc/Makefile.in, man/Makefile.in, src/Makefile.in: More work on 'make install' 2002-06-28 12:49 Martin Pool * configure.ac, analog/distcc.analog, man/Makefile.in: More automake removal, mostly for man/ 2002-06-28 12:48 Martin Pool * Makefile.in: If any sub-make fails, the top-level one should fail too. 2002-06-28 12:06 Martin Pool * Makefile.in, configure, configure.ac, linuxdoc/.cvsignore, src/Makefile.in: More work on conversion away from automake 2002-06-28 11:56 Martin Pool * linuxdoc/Makefile.in: Cleanup. Only remove documents with maintainer-clean. 2002-06-28 11:50 Martin Pool * linuxdoc/Makefile.in: Remove automake cruft. 2002-06-28 11:42 Martin Pool * src/io.c: Merge fixup 2002-06-28 11:41 Martin Pool * patches/ChangeLog: kill changelogs 2002-06-28 11:40 Martin Pool * missing: remove automake cruft 2002-06-28 11:38 Martin Pool * .cvsignore, linuxdoc/distcc.sgml, src/arg.c, src/distcc.c, src/distcc.h, src/exec.c, src/h_scanargs.c, src/io.c, src/serve.c: Merge changes from freeze_0_5 branch: - avoid argv[] overrun bug - more trace messages - some refactoring/cleanups - FreeBSD sendfile portability fix - better exit codes 2002-06-28 11:23 Martin Pool * analog/: Makefile, distcc.analog: Add analog config. 2002-06-27 22:45 Martin Pool * test/testdistcc.py: Also test hostspec parser. 2002-06-27 22:43 Martin Pool * src/hosts.c: Better messages for EXIT_BAD_HOSTSPEC 2002-06-27 22:41 Martin Pool * src/hosts.c: dcc_parse_hosts() needs to return EXIT_BAD_HOSTSPEC if no hosts are defined. 2002-06-27 22:29 Martin Pool * test/testdistcc.py: Port more tests from PyUnit. 2002-06-27 22:27 Martin Pool * Makefile.in: Run tests against just-built executables. 2002-06-27 22:12 Martin Pool * test/testdistcc.py: Add a slightly nontrivial test that we can call --version on distcc and distccd. 2002-06-27 21:59 Martin Pool * Makefile.in: Don't run pyunit by default any more. 2002-06-27 21:58 Martin Pool * Makefile.in: Call comfy chair and pyunit tests 2002-06-27 21:57 Martin Pool * test/testdistcc.py: Start of conversion of Python tests to use comfy chair 2002-06-27 21:45 Martin Pool * Makefile.in, aclocal.m4: Start getting 'make check' working without automake. 2002-06-27 21:45 Martin Pool * src/Makefile.in: Add non-automake rules to build test harnesses. 2002-06-27 21:34 Martin Pool * src/exitcode.h: Cleanup. 2002-06-27 21:33 Martin Pool * src/: daemon.c, dparent.c: Fixes for removal of automake. 2002-06-27 21:29 Martin Pool * src/distcc.h: Add a new host specification string parser (not called yet except from test case.) 2002-06-27 21:28 Martin Pool * src/io.c: Reindent. Emit trace messages when (un)corking sockets. 2002-06-27 21:25 Martin Pool * src/trace.h: Change rs_log_critical to rs_log_crit to be consistent. 2002-06-27 21:24 Martin Pool * src/srvnet.c: Doc 2002-06-27 21:24 Martin Pool * src/: hosts.c, where.c: Add a new host specification string parser (not called yet except from test case.) 2002-06-27 21:24 Martin Pool * src/h_hosts.c: Print out the results of parsing the host specification. Pass exit code from scanner out. 2002-06-27 21:23 Martin Pool * src/exitcode.h: Add additional exit codes: compiler crashed, out of memory, bad hostspec. Doc. 2002-06-27 21:20 Martin Pool * src/dparent.c: Log an info message when standalone daemon starts, including version. 2002-06-27 21:20 Martin Pool * src/daemon.c: Log an info message when inetd daemon starts. 2002-06-27 20:36 Martin Pool * configure, configure.ac: Bump version to 0.5 2002-06-27 20:32 Martin Pool * NEWS: Add date, etc. 2002-06-27 20:28 Martin Pool * NEWS: Update NEWS 2002-06-27 20:25 Martin Pool * src/io.c: Doc. 2002-06-27 14:34 Martin Pool * configure, configure.ac: Bump version. 2002-06-27 13:46 Martin Pool * src/io.c: Try to handle FreeBSD's different API for sendfile() by introducing a sys_sendfile() portability wrapper. 2002-06-27 13:23 Martin Pool * Makefile.am, Makefile.in, NEWS, aclocal.m4, autogen.sh, configure, configure.ac, linuxdoc/Makefile.am, man/Makefile.am, src/Makefile.am, src/Makefile.in, src/config.h.in, src/help.c: Get rid of automake, just use plain autoconf 2.53. What a mess! Building the basic executables should still work; test cases etc is probably broken at the moment. 2002-06-27 10:39 Martin Pool * ChangeLog, Makefile.in, aclocal.m4, contrib/ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, linuxdoc/Makefile.in, man/ChangeLog, man/Makefile.in, src/ChangeLog, src/Makefile.in: Run autogen Remove dumb ChangeLogs 2002-06-26 21:59 Martin Pool * Makefile.in, aclocal.m4, configure, depcomp, missing, linuxdoc/Makefile.in, man/Makefile.in, src/Makefile.in: Upgrade automake to 1.5. 2002-06-26 21:59 Martin Pool * NEWS: Set version. 2002-06-26 21:58 Martin Pool * autogen.sh, .cvsignore: ChangeLogs no longer stored in CVS. 2002-06-26 21:56 Martin Pool * src/dparent.c: Handle EINTR from waitpid(), which is expected on FreeBSD. 2002-06-26 14:49 Martin Pool * linuxdoc/distcc.sgml: Document EXIT_COMPILER_CRASHED. 2002-06-26 14:44 Martin Pool * src/distcc.c: Doc. Clearer message for remote compiler failure. 2002-06-26 14:35 Martin Pool * ChangeLog, contrib/ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, man/ChangeLog, patches/ChangeLog, src/ChangeLog: Remove ChangeLogs -- I'm not convinced that keeping them in CVS makes much sense. If you want them, autogenerate them. 2002-06-26 14:21 Martin Pool * configure, configure.ac: Set version to 0.5rc1 2002-06-26 14:19 Martin Pool * NEWS, src/arg.c, src/distcc.c, src/distcc.h, src/exec.c, src/exitcode.h, src/h_hosts.c, src/h_scanargs.c, src/serve.c: Fix bug in h_hosts that caused us to write off the end of the real argv[], rather than a copy. Thanks to Julian Seward. Use more specific return codes when the remote compiler fails: EXIT_COMPILER_CRASHED for a signal, or the return code from the compiler if it exited non-0. Refactor client main() to be a bit clearer. 2002-06-22 14:44 Martin Pool * src/: t_exten, t_issource, t_version: Remove unused sh-based tests. 2002-06-22 03:58 Martin Pool * Makefile.in, NEWS, aclocal.m4, configure, configure.ac, linuxdoc/Makefile.in, man/Makefile.in, src/Makefile.in: Bump version to 0.5. 2002-06-22 03:56 Martin Pool * src/trace.h: Doc. 2002-06-21 19:48 Martin Pool * src/: distcc.h, h_hosts.c, hosts.c, where.c: Make everything build again :) 2002-06-21 19:46 Martin Pool * src/hosts.c: Doc. 2002-06-21 19:34 Martin Pool * src/hosts.c: dcc_parse_hosts_env: Better parser that splits things into words and recognizes the two types of host definition. Doesn't do the whole job yet though. 2002-06-21 19:33 Martin Pool * src/h_hosts.c: h_hosts: Actually print out the results of the test. Exit 1 if something went wrong or is inconsistent. 2002-06-21 19:15 Martin Pool * src/: .cvsignore, Makefile.am, Makefile.in, distcc.h, h_hosts.c, hosts.c, hosts.h, where.c: Start splitting out new host parser. Doesn't do anything yet. 2002-06-18 08:50 Martin Pool * linuxdoc/Makefile.in: Keep Makefile.in to allow building without automake. 2002-06-13 15:42 Martin Pool * src/: trace.c, trace.h: Cope without varargs macros. All trace routines are redirected to plain functions. 2002-06-13 15:41 Martin Pool * Makefile.in, configure, src/config.h.in: Run autoconf 2002-06-13 15:22 Martin Pool * src/: h_exten.c, h_issource.c, h_scanargs.c: - cope without varargs macros or __attribute__ 2002-06-13 15:14 Martin Pool * NEWS, configure.ac, src/arg.c, src/bulk.c, src/distcc.c, src/distcc.h, src/dopt.c, src/dparent.c, src/exec.c, src/io.c, src/rpc.c, src/tempfile.c, src/trace.c, src/trace.h, src/util.c, src/util.h, src/where.c: Modified patch from Petter Reinholdtsen to try to build on Solaris with Forte cc. Specifically: - cope without varargs macros or __attribute__ - use lockf rather than flock if missing - fix bashism - put config.h in all files 2002-06-13 15:02 Martin Pool * Makefile.in, man/Makefile.in: run automake 2002-06-13 15:01 Martin Pool * README: Remove old performance numbers Add supported platforms 2002-06-13 15:00 Martin Pool * patches/freebsd-mknod.diff: committed 2002-06-13 14:58 Martin Pool * NEWS, src/serve.c: FreeBSD mknod/mkfifo fix. (Claes Wallin) 2002-06-13 14:54 Martin Pool * src/dopt.c: Doc. 2002-06-12 02:44 Martin Pool * NEWS, man/Makefile.am: Makefile.am patch from Petter Reinholdtsen to correctly install and distribute manpages. (They need to be updated to include just quick reference information and to point to the sgml manual.) 2002-06-12 02:15 Martin Pool * packaging/: README.rpm, distcc.spec: RPM spec file from Ben Elliston. 2002-06-12 01:53 Martin Pool * NEWS, OLDNEWS: Roll over NEWS 2002-06-12 01:52 Martin Pool * src/: bulk.c, distcc.h: Refactor bulk file transfer code in preparation for gzip compressiong. 2002-06-12 01:51 Martin Pool * src/io.c: Doc. 2002-06-12 01:47 Martin Pool * src/zip.c: Skeleton of zip compression. Not used yet. 2002-06-12 01:39 Martin Pool * man/: .cvsignore, Makefile.in: Keep files generated by automake, but not by configure. 2002-06-12 01:39 Martin Pool * patches/freebsd-mknod.diff: Patch from Claes Wallin for FreeBSD. 2002-06-12 01:37 Martin Pool * man/.cvsignore: Ignore autoconf generated files. 2002-06-12 01:36 Martin Pool * linuxdoc/.cvsignore: Ignore generated files. 2002-06-09 02:58 Martin Pool * linuxdoc/distcc.sgml: Bump version to 0.4 2002-06-09 02:53 Martin Pool * ChangeLog, contrib/ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, man/ChangeLog, patches/ChangeLog, src/ChangeLog: update ChangeLogs 2002-06-09 02:51 Martin Pool * configure, linuxdoc/Makefile, linuxdoc/Makefile.am, man/Makefile, man/Makefile.am, src/Makefile.in: Shuffle Makefiles 2002-06-09 02:50 Martin Pool * NEWS: Update news 2002-06-09 02:40 Martin Pool * src/Makefile.am: Add missing file 2002-06-09 02:38 Martin Pool * configure.ac: Bump version to 0.4 Get rid of old test scripts Add new Makefiles 2002-06-09 02:34 Martin Pool * NEWS: Doc. 2002-06-09 02:32 Martin Pool * src/dopt.c: Hide --tasks from help since it does nothing. 2002-06-09 02:09 Martin Pool * linuxdoc/distcc.sgml: Add section on SMP. 2002-06-09 02:02 Martin Pool * src/dparent.c: Doc. 2002-06-09 01:58 Martin Pool * ChangeLog, contrib/ChangeLog, linuxdoc/ChangeLog, patches/ChangeLog, src/ChangeLog: update changelog 2002-06-09 01:50 Martin Pool * src/dparent.c: Factor out code to collect children. Keep track of how many are running. 2002-06-09 01:44 Martin Pool * src/: daemon.c, dparent.c: Change server to a more traditional Unix model of forking after accepting -- possibly less efficient, but I was having trouble managing an orderly shutdown of all children and this is simpler. 2002-06-09 01:43 Martin Pool * src/Makefile.in: Run autoconf 2002-06-09 01:42 Martin Pool * NEWS: Doc 2002-06-09 00:23 Martin Pool * NEWS: .S and .s probably works now. 2002-06-09 00:21 Martin Pool * src/: arg.c, distcc.h, serve.c: Correctly infer preprocessed filename from source filename. So for example if we're processing a .S file, then we need to call the tmpfile .s so that the compiler driver understands that it should just run the assembler. 2002-06-09 00:08 Martin Pool * linuxdoc/distcc.sgml: Note that network errors will not be detected. 2002-06-09 00:05 Martin Pool * src/dopt.c: Doc. 2002-06-09 00:03 Martin Pool * src/arg.c: Server should log input and output filename too. 2002-06-08 23:54 Martin Pool * src/: arg.c: Log input and output filename. 2002-06-08 23:45 Martin Pool * src/dparent.c: Daemon parent tries to close listen_fd after forking children, because it's no longer required. 2002-06-08 23:43 Martin Pool * src/: Makefile.am, daemon.c, distcc.h, dparent.c: Split daemon-standalone-parent code into a separate file. 2002-06-08 23:35 Martin Pool * src/daemon.c: Lots of doc updates. 2002-06-08 23:30 Martin Pool * src/daemon.c: Update docs. 2002-06-08 23:24 Martin Pool * NEWS: Note --pid-file. 2002-06-08 23:10 Martin Pool * src/daemon.c: Add log message for stdin being a socket 2002-06-08 23:09 Martin Pool * src/srvnet.c: open_socket_in: check that port number is reasonable 2002-06-08 22:54 Martin Pool * linuxdoc/: .cvsignore, Makefile: Fix Plucker filename 2002-06-08 22:49 Martin Pool * linuxdoc/.cvsignore: Add Plucker-ized manual 2002-06-08 22:48 Martin Pool * linuxdoc/Makefile: Better name for Plucker file. 2002-06-08 22:40 Martin Pool * src/daemon.c: Consistently call dcc_exit(). Notice immediately when one of our children dies, and reap all of them. When all children die or the parent is signalled, the parent should kill the process group and itself. 2002-06-08 22:31 Martin Pool * src/util.h: Fix function attributes. 2002-06-08 22:16 Martin Pool * src/distcc.h: Clean up prototypes. 2002-06-08 22:11 Martin Pool * src/daemon.c: Clean up exit codes. If fork() fails, log an error, but keep trying. Try to listen on socket before going into background, so that failure is visible to the calling script. 2002-06-08 22:00 Martin Pool * src/distcc.c: Detect invocations like "distcc -c" 2002-06-08 22:00 Martin Pool * src/exitcode.h, linuxdoc/distcc.sgml: Renumber exit codes so that 100 is a generic distcc failure. 2002-06-08 21:44 Martin Pool * src/dopt.c: Fix help message for --pid-file 2002-06-08 21:43 Martin Pool * src/: daemon.c, dopt.c, opt.h: Add --pid-file option to save daemon's pid. 2002-06-08 21:42 Martin Pool * Makefile.in: Update autoconf stuff 2002-06-08 14:24 Martin Pool * linuxdoc/Makefile: Don't build Linuxdoc by default because many machines won't have the tools. 2002-06-08 13:49 Martin Pool * src/dopt.c: Fix overzealous memory mistake. 2002-06-07 16:17 Martin Pool * ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, man/ChangeLog, src/ChangeLog: auto-update ChangeLog 2002-06-07 11:09 Martin Pool * man/: .cvsignore, Makefile, distcc.1, distccd.1: Correction from Juan F. Codagnone for Makefile -- should call groff, not man, to transform manpages Also, add a little stub distccd page. Both need to be updated to show just the basic information and refer to the manual for more info. 2002-06-06 18:21 Martin Pool * linuxdoc/distcc.sgml: Improve cross-compile section. 2002-06-06 17:52 Martin Pool * linuxdoc/distcc.sgml: Update doc: test suite has now been written. 2002-06-06 00:22 Martin Pool * Makefile.in, NEWS, configure, configure.ac, src/config.h.in, src/daemon.c, src/distcc.h, src/dopt.c, src/exitcode.h, src/opt.h: Improvements to demon: - make daemon put itself into background when running alone - daemon preforks children according to --tasks option, notes if they die, and kills them when terminated - --port option to set listening port (currently not useful, since you can't set port on client) 2002-06-05 19:00 Martin Pool * src/dopt.c: Fix mostly-harmless leaks of poptContext. Detected by valgrind -- how cool! 2002-06-05 18:53 Martin Pool * NEWS, src/tempfile.c: Add support for TMPDIR. Not tested. 2002-06-05 17:22 Martin Pool * src/: bulk.c, daemon.c, distcc.c, exec.c, where.c: Doc. 2002-06-02 15:02 Martin Pool * NEWS: Test cvs 2002-06-02 14:28 Martin Pool * linuxdoc/Makefile, man/Makefile: Fix recursive make targets 2002-06-02 14:18 Martin Pool * linuxdoc/Makefile, man/Makefile: Fix recursive make targets 2002-06-02 14:10 Martin Pool * Makefile.in, linuxdoc/Makefile: automake 2002-06-02 14:09 Martin Pool * src/: Makefile.in, daemon.c, exitcode.h: Start using consistent return codes across all programs. 2002-06-02 14:07 Martin Pool * contrib/make-j: make-j script from Alexandre Oliva for use with distcc Tests which machines are up, and runs Make with concurrency set appropriately. 2002-06-02 13:59 Martin Pool * src/: .cvsignore, Makefile.am, Makefile.in, arg.c, clinet.c, daemon.c, distcc.c, exitcode.h, h_scanargs.c, help.c, serve.c, srvnet.c, trace.c, trace.h, util.c, util.h, where.c: Many changes: Start using consistent return codes across all programs. Add h_scanargs to allow pyunit to test argument analysis. If -fprofile-args, -ftest-coverage or -x is seen in arguments, run locally. Handle "gcc -c -c hello.c" Better help message. Start handling .s files (doesn't work yet) Fix insertion of program/pid into trace msgs. 2002-06-02 13:56 Martin Pool * configure, configure.ac: FreeBSD installs its version of libpopt into /usr/local/, but does not put that on the default library and header path. We used to add that path if building on *bsd*, but bje points out that will break cross-compilation, and it's kind of ugly anyhow. 2002-06-02 13:55 Martin Pool * autogen.sh: Don't configure from autogen.sh 2002-06-02 13:54 Martin Pool * Makefile.am, Makefile.in: Also descend into linuxdoc, pyunit and man directories. 2002-06-02 13:51 Martin Pool * linuxdoc/distcc.sgml: More documentation, especially about bugs. 2002-06-02 13:50 Martin Pool * NEWS, OLDNEWS: Roll over news. 2002-05-31 16:36 Martin Pool * configure, configure.ac: Apparently FreeBSD needs sys/types.h before netinet/in.h. From Frerich Raabe. 2002-05-31 16:20 Martin Pool * linuxdoc/distcc.sgml: Add distcc link. 2002-05-31 16:10 Martin Pool * linuxdoc/Makefile: Move to distcc.samba.org. 2002-05-31 16:09 Martin Pool * linuxdoc/distcc.sgml: Manual is now current for 0.3 2002-05-31 16:08 Martin Pool * linuxdoc/footer.html: Fix distcc homepage link. 2002-05-30 08:31 Martin Pool * configure.ac: Documentation from ben 2002-05-29 14:35 Martin Pool * linuxdoc/distcc.sgml: More notes from recent discussions. 2002-05-29 14:21 Martin Pool * src/arg.c: Doc. 2002-05-28 23:11 Martin Pool * ChangeLog, Makefile.am, Makefile.in, linuxdoc/ChangeLog, src/ChangeLog: Commit Makefile rule 2002-05-28 23:09 Martin Pool * Makefile.am: Need to distribute ChangeLogs across directories 2002-05-28 23:04 Martin Pool * ChangeLog: Update ChangeLog from CVS 2002-05-28 23:00 Martin Pool * Makefile.in, aclocal.m4, src/Makefile.in: autoconf 2002-05-28 22:58 Martin Pool * Makefile.in, src/Makefile.in: update autoconf 2002-05-28 22:58 Martin Pool * src/NEWS: Moved to parent directory 2002-05-28 22:56 Martin Pool * NEWS: Go ahead and release. 2002-05-28 22:38 Martin Pool * aclocal.m4, configure, configure.ac, src/Makefile.am: Bump version to 0.3. Try to get "make dist" working. 2002-05-28 19:50 Martin Pool * Makefile.in, configure, src/Makefile.in: rerun autoconf 2002-05-28 19:32 Martin Pool * configure.ac: Suggestion from Frerich to fix check for *bsd*. 2002-05-28 15:38 Martin Pool * src/.cvsignore: Ignore temp file. 2002-05-28 15:29 Martin Pool * aclocal.m4, configure.ac, src/Makefile.am, src/Makefile.in, src/t_version: Add another trivial test suggested by bje 2002-05-28 15:18 Martin Pool * Makefile.in, configure, configure.ac, src/config.h.in, src/help.c: Export gnu host triple in --version 2002-05-28 15:07 Martin Pool * Makefile.in, aclocal.m4, config.guess, config.sub, configure, configure.ac, src/Makefile.in: Detect BSD, and add /usr/local/ to the CFLAGS and LDFLAGS. 2002-05-28 14:31 Martin Pool * aclocal.m4: Silly autoconf 2002-05-28 14:24 Martin Pool * patches/: distc, distc++: Single files that call 'distcc gcc' -- possibly needed for Makefiles that assume the compiler is a single word. (Does this include libtool?) 2002-05-28 14:18 Martin Pool * src/: .cvsignore, Makefile.in, config.h.in: Check in extra autoconf-generated files. 2002-05-28 14:17 Martin Pool * src/timebuild: Very primitive script for timing tests. 2002-05-28 13:52 Martin Pool * src/: h_exten.c, h_issource.c: Additional fixes for rs_program_name. 2002-05-28 13:48 Martin Pool * Makefile.in, configure, configure.ac, src/serve.c: BSD needs sys/signal.h. 2002-05-28 12:43 Martin Pool * .cvsignore, COPYING.FDL, Makefile.am, Makefile.in, aclocal.m4, configure, install-sh, missing, mkinstalldirs: Keep a copy of autotools files in CVS, to help people on machines with different versions. Bah, humbug! 2002-05-28 12:37 Martin Pool * ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, man/ChangeLog: Regenerate ChangeLogs 2002-05-28 12:28 Martin Pool * src/: ChangeLog, daemon.c, distcc.c, trace.c, trace.h: Clean up rs_program_name shmozlle 2002-05-27 00:58 Martin Pool * src/srvnet.c: Doc 2002-05-27 00:14 Martin Pool * configure.ac: Doc 2002-05-26 01:44 Martin Pool * .cvsignore, src/.cvsignore: Ignore extra garbage 2002-05-26 01:38 Martin Pool * configure.ac: Need to also look in sys/types.h for in_port_t on BSD. 2002-05-26 01:35 Martin Pool * src/arg.c: Good fix from Ian Reinhart Geiser for silly mistake in dcc_set_file_extension that I think would show up in "gcc -c hello.c". 2002-05-26 01:27 Martin Pool * NEWS, src/serve.c: Ignore SIGPIPE in daemon as well as client. Thanks to Ben Elliston. 2002-05-26 01:21 Martin Pool * configure.ac, src/clinet.c, NEWS: Try to cope without in_port_t. Thanks to Luke Gorrie. 2002-05-26 01:11 Martin Pool * src/: daemon.c, distcc.c, h_exten.c, h_issource.c, trace.c: Cope without program_invocation_short_name, as some GNU libc/cc combinations don't seem to have it (???) 2002-05-26 00:54 Martin Pool * src/trace.c: Replace calls to strnlen with strlen, because it will always be short enough and FreeBSD doesn't have strnlen 2002-05-26 00:49 Martin Pool * configure.ac, src/help.c: Ignore strange new automake variables, just use PACKAGE and VERSION 2002-05-26 00:47 Martin Pool * NEWS: Fix Ian's name. 2002-05-26 00:46 Martin Pool * NEWS: M-/ strikes again :-) 2002-05-26 00:42 Martin Pool * src/io.c: If there are no corks on this computer, don't try to use them. 2002-05-26 00:32 Martin Pool * configure.ac, src/arg.c, src/bulk.c, src/clinet.c, src/daemon.c, src/distcc.c, src/exec.c, src/h_exten.c, src/h_issource.c, src/io.c, src/rpc.c, src/serve.c, src/srvnet.c, src/tempfile.c, src/util.c, src/where.c, NEWS: Test for sys/sendfile.h and sendfile(), and if we don't have them use plain read/write instead. Remove unnecessary dependencies on sys/sendfile.h 2002-05-26 00:23 Martin Pool * autogen.sh: Don't say "make all", because on some platforms you might really need gmake. 2002-05-26 00:08 Martin Pool * autogen.sh: Need to also run aclocal to install automake stuff. Also need to run autoheader early on in the process, because automake depends on finding config.h.in. 2002-05-26 00:04 Martin Pool * NEWS: Note help with automake 2002-05-26 00:01 Martin Pool * autogen.sh: Handle ChangeLog 2002-05-25 23:57 Martin Pool * src/.cvsignore: More test cases 2002-05-25 23:55 Martin Pool * src/Makefile.am: Get rid of editing mistake. _SOURCES is a magic name for automake, so don't use it for common source. Thanks to Frerich Raabe. 2002-05-25 23:50 Martin Pool * autogen.sh: Add a script to do everything necessary to build from CVS. This is needed because automake requires a spliff to get out of bed, and the generated files are shipped in tarballs but not stored in CVS. 2002-05-25 23:47 Martin Pool * configure.ac: Fix shell syntax: square brackets can't be used in configure.ac because they clash with m4. 2002-05-25 19:23 Martin Pool * src/: Makefile.am, h_issource.c, t_issource: Add another test 2002-05-25 19:23 Martin Pool * configure.ac: chmod test files 2002-05-25 18:57 Martin Pool * src/: arg.c, distcc.c, distcc.h: Recognize the .ii extension that ccache uses for preprocessed C++ code. (Ian Reinhart Geiser) 2002-05-25 18:55 Martin Pool * NEWS: * Convert to using GNU automake and autoconf, so that distcc can better handle portability, distribution and testing. (Martin Pool) * Start adding some "make check" tests. (Martin Pool) 2002-05-25 18:51 Martin Pool * src/arg.c: Recognize the .ii extension that ccache uses for preprocessed C++ code. 2002-05-25 18:50 Martin Pool * src/: .cvsignore, Makefile.am, arg.c, distcc.h, h_exten.c, t_exten: Add a test harness and script to test the simplest function we have -- finding the extension of a filename. 2002-05-25 18:34 Martin Pool * src/GNUmakefile: This Makefile is no longer needed because we have automake. 2002-05-25 18:33 Martin Pool * .cvsignore, src/.cvsignore: Ignore automake-generated files 2002-05-25 16:02 Martin Pool * configure.ac, src/Makefile.am, src/help.c, src/trace.c: More automake integration fixes. Builds properly now. 2002-05-25 15:47 Martin Pool * .cvsignore, AUTHORS, COPYING, INSTALL, Makefile, Makefile.am, NEWS, OLDNEWS, configure.ac, src/.cvsignore, src/Makefile.am: Convert to automake. Don't know if it works yet. 2002-05-24 16:45 Martin Pool * linuxdoc/distcc.sgml: Add GNU FDL stuff. 2002-05-24 15:17 Martin Pool * src/: distcc.c, distcc.h, exec.c, NEWS: Only fiddle with the compiler's stdin/out/err when running on the server, not on the client. This should make cpp from stdin work. (Reported by Ian Reinhart Geiser from KDE.) 2002-05-24 15:15 Martin Pool * src/distcc.c: Doc. 2002-05-24 15:11 Martin Pool * src/: distcc.h, exec.c: Split out code to redirect stdin/out/err, because we don't want to do this locally. 2002-05-24 13:49 Martin Pool * Makefile: Add always_ChangeLog target 2002-05-24 13:47 Martin Pool * src/serve.c: Use a FIFO to feed preprocessed source from the daemon into the compiler, so that compilation can be overlapped with network transit. 2002-05-24 13:22 Martin Pool * src/NEWS: Support C++ compilation by correctly detecting prefixes. 2002-05-24 13:22 Martin Pool * src/arg.c: Better error messages for when we encounter an argument that is not a source file name. 2002-05-24 13:19 Martin Pool * src/arg.c: Fix little syntax error. 2002-05-24 13:18 Martin Pool * src/arg.c: Change code to recognize source files so that it will detect all the C++ variants. Based on a patch from ian reinhart geiser. Factor source file recognition into its own function. 2002-05-24 13:03 Martin Pool * src/arg.c: Refactor code to set file extension, so that we can handle things like "foo.cpp" where the source extension is longer than ".o". Based on a patch from ian reinhart geiser, but more defensive. 2002-05-23 16:19 Martin Pool * linuxdoc/distcc.sgml: Fix SGML. 2002-05-23 16:17 Martin Pool * linuxdoc/distcc.sgml: Texinfo can't handle having two headings with the same name. 2002-05-23 16:12 Martin Pool * linuxdoc/distcc.sgml: Add explanation of special meaning of "localhost" in DISTCC_HOSTS. Move results around. 2002-05-21 18:17 Martin Pool * src/: NEWS, OLDNEWS: Roll over NEWS 2002-05-21 18:10 Martin Pool * src/GNUmakefile: Set version to 0.2.99 2002-05-21 17:20 Martin Pool * src/serve.c: Doc. 2002-05-20 16:00 Martin Pool * linuxdoc/distcc.sgml: Fix SGML 2002-05-20 15:57 Martin Pool * linuxdoc/distcc.sgml: Add section about libtool. Add results for building glib-1.2. 2002-05-20 14:38 Martin Pool * src/GNUmakefile: linuxdoc/ subdir is no longer here. 2002-05-20 14:30 Martin Pool * linuxdoc/distcc.sgml: Cleaner CVS stuff. 2002-05-20 14:26 Martin Pool * linuxdoc/distcc.sgml: Cleaner CVS stuff. 2002-05-20 14:25 Martin Pool * linuxdoc/distcc.sgml: Better explanation of issues around SSH. 2002-05-20 14:06 Martin Pool * src/trace.c: Doc. 2002-05-20 14:02 Martin Pool * linuxdoc/distcc.sgml: Clarify handling of compiler error messages. 2002-05-20 13:54 Martin Pool * linuxdoc/.cvsignore: Better exclude specification 2002-05-20 13:54 Martin Pool * linuxdoc/: Makefile, footer.html: Add HTML footer 2002-05-20 13:46 Martin Pool * Makefile, cvs2cl.ufile: Add top-level makefile 2002-05-20 13:35 Martin Pool * src/NEWS: News for something that happened last week! 2002-05-20 13:23 Martin Pool * src/HACKING: Cleanup 2002-05-20 13:21 Martin Pool * linuxdoc/distcc.sgml: Add results. 2002-05-19 18:09 Martin Pool * linuxdoc/: .cvsignore, Makefile, distcc.sgml: Move directory 2002-05-17 15:45 Martin Pool * src/GNUmakefile: Set version to 0.2 2002-05-17 14:10 Martin Pool * src/help.c: Add email address 2002-05-17 14:09 Martin Pool * src/: GNUmakefile, distcc.c, distcc.h, dopt.c, help.c: Improve --help messages, and make all programs response to --version properly. 2002-05-17 13:45 Martin Pool * src/daemon.c: Doc. 2002-05-16 17:56 Martin Pool * src/arg.c: If -o is not specified, gcc dumps the object file in the current directory, not the source directory. Make our behaviour the same. 2002-05-16 17:27 Martin Pool * src/: arg.c, distcc.c, distcc.h: Try to handle cases like "gcc -c hello.c" by appending "-o hello.o" to the end. This doesn't work yet for files not in the current directory. 2002-05-16 15:53 Martin Pool * .cvsignore, src/GNUmakefile: Add a nice simple user manual 2002-05-16 13:48 Martin Pool * src/HACKING: Note about cpp performance. 2002-05-15 23:13 Martin Pool * src/HACKING: Doc. 2002-05-15 18:19 Martin Pool * src/: HACKING, tempfile.c, where.c: Doc. 2002-05-15 17:45 Martin Pool * src/where.c: Better trace msg 2002-05-15 17:44 Martin Pool * man/.cvsignore: Ignore generated 2002-05-15 17:44 Martin Pool * doc/distcc-irc.txt: Rough notes from irc 2002-05-15 17:38 Martin Pool * src/: distcc.h, tempfile.c, where.c: Use simple file locks to spread work across hosts 2002-05-15 17:23 Martin Pool * src/where.c: Split out code for parsing list of hosts, and actually picking a host to use. Doc about locking method for distributing work. 2002-05-15 16:15 Martin Pool * src/: GNUmakefile, bulk.c, distcc.c, distcc.h, rpc.h, serve.c, where.c: Back out of the compression changes; they seem like a premature optimization 2002-05-15 16:07 Martin Pool * src/HACKING: Scratch numbers on compression 2002-05-15 15:57 Martin Pool * src/serve.c: Use correct proto version 2002-05-15 15:54 Martin Pool * src/: bulk.c, distcc.c, io.h, rpc.h, serve.c: zlevel is passed everywhere but ignored 2002-05-15 15:51 Martin Pool * src/: GNUmakefile, distcc.c, serve.c: Server accepts GZIP token 2002-05-15 15:45 Martin Pool * src/HACKING: Note about server-side error handling 2002-05-15 15:42 Martin Pool * src/: distcc.c, distcc.h: Bump proto version to 2; send GZIP token in header to request compression 2002-05-15 15:35 Martin Pool * src/: distcc.c, distcc.h, where.c: Parse zlevel out of _HOSTS 2002-05-15 15:27 Martin Pool * src/: bulk.c, io.c, io.h: Factor out common methods of bulk transfer 2002-05-15 15:26 Martin Pool * src/GNUmakefile: Bump version 2002-05-15 15:20 Martin Pool * man/distcc.1: Note about mtimes 2002-05-15 15:13 Martin Pool * src/bulk.c: Doc 2002-05-15 15:10 Martin Pool * src/GNUmakefile: Set version to 1.0 2002-05-15 15:09 Martin Pool * .cvsignore, man/distcc.1, src/HACKING, src/distcc.c, src/trace.c, src/trace.h: Allow log messages from distcc to be separated from stderr 2002-05-15 15:01 Martin Pool * src/: GNUmakefile, bulk.c, rpc.c: Split out file transfer code 2002-05-15 14:56 Martin Pool * src/tempfile.c: Add quote 2002-05-15 14:56 Martin Pool * src/distcc.c: Handle --help 2002-05-15 14:56 Martin Pool * man/distcc.1: Add more links 2002-05-15 14:55 Martin Pool * man/Makefile: Add PDF target 2002-05-15 14:50 Martin Pool * src/distcc.c: Show environment variables in usage message for distcc 2002-05-13 13:30 Martin Pool * src/GNUmakefile: Add "install" target. 2002-05-13 13:27 Martin Pool * src/dopt.c: Fix dumb "break" mistake in option parsing. 2002-05-06 09:10 Martin Pool * src/dopt.c: Add --nice option 2002-05-05 19:23 Martin Pool * src/: GNUmakefile, daemon.c, distcc.h, dopt.c: Start adding daemon command-line handling 2002-05-05 19:22 Martin Pool * src/trace.c: Better formatting when not using the pid. 2002-05-05 19:21 Martin Pool * README: Note library dependencies 2002-05-02 15:17 Martin Pool * man/distcc.1: More stuff. 2002-05-02 14:25 Martin Pool * man/distcc.1: More manpage updates. 2002-05-02 13:26 Martin Pool * man/: Makefile, distcc.1: Add the start of a man page. 2002-05-01 12:42 Martin Pool * src/io.c: "i've always wanted to use sendfile(), but never had a reason until now" 2002-05-01 12:31 Martin Pool * README: Add author name. 2002-04-30 20:48 Martin Pool * README, src/README: Rearrange 2002-04-30 18:15 Martin Pool * src/: exec.c: Doc. 2002-04-30 18:06 Martin Pool * src/serve.c: Make file sizes correct even if compilation fails. 2002-04-30 18:05 Martin Pool * src/: distcc.h, serve.c, srvnet.c: daemon logs client names 2002-04-30 18:04 Martin Pool * src/exec.c: Doc 2002-04-30 17:50 Martin Pool * src/trace.c: you're never going to want program or pid in a syslog message, because it's redundant. 2002-04-30 17:48 Martin Pool * src/: serve.c, exec.c: Log job completion 2002-04-30 17:45 Martin Pool * src/daemon.c: Log opening of port 2002-04-30 17:38 Martin Pool * src/exec.c: If compiler finished OK, that's an INFO level message 2002-04-30 17:34 Martin Pool * src/: distcc.c, rpc.c, rpc.h, serve.c: Record size of files transferred 2002-04-30 17:31 Martin Pool * src/: daemon.c, trace.c, trace.h: More flexible trace formatting 2002-04-30 17:22 Martin Pool * src/trace.c: Fix stderr logging. 2002-04-30 17:19 Martin Pool * src/: daemon.c, trace.c, trace.h: distccd logs to syslog/daemon. 2002-04-30 17:13 Martin Pool * src/: trace.c, trace.h: Big rework of trace system so that the trace implementation gets to format the string, possibly using a helper function. 2002-04-30 16:35 Martin Pool * src/srvnet.c: Delete dead code 2002-04-30 15:46 Martin Pool * src/io.c: Don't ever just exit 2002-04-30 15:45 Martin Pool * src/daemon.c: Don't abort if accept() fails. 2002-04-30 15:29 Martin Pool * src/tempfile.c: Make cleanup code reusable. 2002-04-30 15:28 Martin Pool * src/srvnet.c: Need to listen() on socket before accept() 2002-04-30 15:20 Martin Pool * src/distcc.c: Fix silly pointer bug 2002-04-30 15:17 Martin Pool * src/: GNUmakefile, daemon.c, srvnet.c, util.h: Really simple standalone mode. 2002-04-30 14:43 Martin Pool * src/: GNUmakefile, daemon.c, distcc.h, serve.c: Split out daemon stuff in preparation for listening on our own socket. 2002-04-30 14:41 Martin Pool * src/io.c: Cast from gcc warning 2002-04-30 14:41 Martin Pool * src/distcc.c: Trace 2002-04-30 14:22 Martin Pool * src/: README, distcc.c: Add DISTCC_VERBOSE env var 2002-04-30 14:09 Martin Pool * src/rpc.c: Add necessary cast, thanks to gcc. 2002-04-30 14:09 Martin Pool * src/HACKING: Doc. 2002-04-30 14:04 Martin Pool * src/rpc.c: If we fail to receive a file, delete the destination rather than leaving it truncated. 2002-04-30 14:03 Martin Pool * src/: daemon.c, distcc.c: Don't send the .o file unless compilation succeeded. 2002-04-30 13:54 Martin Pool * src/distcc.c: If no build hosts are set, just run here. 2002-04-30 13:53 Martin Pool * src/GNUmakefile: Add targets to run cflow. 2002-04-30 13:50 Martin Pool * src/distcc.c: Doc. 2002-04-30 13:02 Martin Pool * src/distcc.c: Do clean up temporary files. 2002-04-30 13:00 Martin Pool * src/distcc.c: Better help message. 2002-04-30 12:58 Martin Pool * src/GNUmakefile: Turn on more warnings 2002-04-30 12:54 Martin Pool * src/where.c: Fix gcc warning. 2002-04-29 20:08 Martin Pool * src/clinet.c: Note from Huxley 2002-04-29 15:28 Martin Pool * src/where.c: Doc. 2002-04-29 15:23 Martin Pool * src/daemon.c: Doc. 2002-04-29 15:20 Martin Pool * src/: clinet.c, distcc.c: Doc. 2002-04-29 15:17 Martin Pool * src/clinet.c: Handle EPIPE as a regular error 2002-04-29 14:52 Martin Pool * src/daemon.c: Clean up temp files if build is successful 2002-04-29 14:50 Martin Pool * src/daemon.c: Docs about better performance. 2002-04-29 14:45 Martin Pool * src/where.c: Docs about better methods of choosing compile hosts. 2002-04-28 23:46 Martin Pool * src/: arg.c, clinet.c, daemon.c, io.c, where.c: Clean up 2002-04-28 23:43 Martin Pool * src/README: Notes on building the kernel 2002-04-28 23:05 Martin Pool * src/GNUmakefile: Change version to 0.1cvs 2002-04-28 22:50 Martin Pool * src/exec.c: Better messages 2002-04-28 22:50 Martin Pool * src/arg.c: Better quoting for commands 2002-04-28 22:45 Martin Pool * src/: README, distcc.c, distcc.h, exec.c: Make the magic name localhost Better execution messages 2002-04-28 22:32 Martin Pool * src/: README, distcc.c: Make the magic name LOCALHOST, not LOCAL 2002-04-28 22:30 Martin Pool * src/where.c: Randomize by pid/ppid, rather than time(), because it is likely that multiple copies might be forked within a second by make -j. 2002-04-28 22:29 Martin Pool * src/io.c: Fix headers 2002-04-28 20:54 Martin Pool * src/README: Add title. 2002-04-28 20:41 Martin Pool * src/: clinet.c, daemon.c, distcc.h, io.c, io.h: Also cork response from the server 2002-04-28 20:41 Martin Pool * src/trace.c: Larger log buffer for chunky gcc lines 2002-04-28 20:37 Martin Pool * src/distcc.c: Cork and uncork socket around request. 2002-04-28 20:36 Martin Pool * src/distcc.c: Cope properly when not running cpp. 2002-04-28 20:35 Martin Pool * src/: clinet.c, distcc.h: Add code to cork a socket 2002-04-28 20:26 Martin Pool * src/: exec.c, rpc.c: Better trace 2002-04-28 20:15 Martin Pool * src/: daemon.c, distcc.c: Fiddle debug and tempfile stuff to better support debugging. 2002-04-28 20:13 Martin Pool * src/README: Some initial numbers on performance building rsync. 2002-04-28 19:38 Martin Pool * src/clinet.c: Fix messages 2002-04-28 19:31 Martin Pool * src/io.c: Quieten trace 2002-04-28 19:27 Martin Pool * src/: distcc.c, distcc.h, exec.c, util.c, util.h: Show program and hostname in completion message. 2002-04-28 19:19 Martin Pool * src/io.c: Fix nasty bug that caused us to read much more than we wanted. 2002-04-28 19:16 Martin Pool * src/rpc.c: More trace 2002-04-28 19:16 Martin Pool * src/daemon.c: Fix tempfile names. 2002-04-28 19:07 Martin Pool * src/distcc.c: Better messages. 2002-04-28 19:04 Martin Pool * src/where.c: Typo. 2002-04-28 19:03 Martin Pool * src/tempfile.c: Better error message. 2002-04-28 19:02 Martin Pool * src/: clinet.c, distcc.c, distcc.h: Actually try to use a random remote host. 2002-04-28 18:58 Martin Pool * src/where.c: Add routine to pick a random build host 2002-04-28 18:58 Martin Pool * src/trace.h: Add rs_log_warning 2002-04-28 18:57 Martin Pool * src/io.c: Quieten warning 2002-04-28 18:55 Martin Pool * src/README: Doc 2002-04-28 17:02 Martin Pool * src/rpc.c: dcc_x_file: If a file does not exist, send it as empty rather than aborting. 2002-04-28 17:00 Martin Pool * src/distcc.c: If the remote compiler fails, we don't need to try again locally. (Actually, we might want to, but don't worry about that for now.) 2002-04-28 16:55 Martin Pool * src/: distcc.c, rpc.c, rpc.h: Receive and display remote stdout/stderr. 2002-04-28 16:52 Martin Pool * src/daemon.c: Capture and send compiler's stdout/stderr. 2002-04-28 16:47 Martin Pool * src/: daemon.c, distcc.c, distcc.h, exec.c, util.c, util.h: Get ready for catching compiler stdout/stderr. 2002-04-28 15:20 Martin Pool * src/distcc.c: Show proto ver in version info. 2002-04-28 15:19 Martin Pool * src/: clinet.c, distcc.c, daemon.c: Doc. 2002-04-28 15:15 Martin Pool * src/: GNUmakefile, where.c: Add where.c 2002-04-28 15:14 Martin Pool * src/: README, distcc.c, distcc.h, exec.c: Run cpp in background while trying to connect. 2002-04-28 15:13 Martin Pool * src/GNUmakefile: Should use CFLAGS to link too 2002-04-28 13:22 Martin Pool * src/distcc.c: Better message when compiler fails. 2002-04-28 13:19 Martin Pool * src/: distcc.c, distcc.h, exec.c: Get ready for async subcommands 2002-04-28 13:14 Martin Pool * src/arg.c: Better message 2002-04-28 13:12 Martin Pool * src/: GNUmakefile, arg.c, clinet.c, daemon.c, distcc.c, distcc.h, io.h, tempfile.c, util.c: More splint-based checks 2002-04-28 12:37 Martin Pool * src/tempfile.c: Check permissions on temporary dir 2002-04-28 12:33 Martin Pool * src/tempfile.c: Automatically set up temp dir when needed Fix temp dir permissions 2002-04-28 12:32 Martin Pool * src/GNUmakefile: Turn off dynamic dependencies for the moment 2002-04-28 12:29 Martin Pool * src/: GNUmakefile, arg.c, clinet.c, daemon.c, distcc.c, io.c, io.h, rpc.c, trace.c, trace.h, util.c: Splint codeups 2002-04-28 12:16 Martin Pool * src/trace.h: Remove broken non-gcc stuff 2002-04-28 12:15 Martin Pool * src/GNUmakefile: Add SPLINT target 2002-04-28 12:08 Martin Pool * src/: distcc.h, tempfile.c: Add routine to cleanup temporary files. 2002-04-28 12:03 Martin Pool * src/: daemon.c, distcc.c, distcc.h, io.c, tempfile.c: Better (secure?) temporary name routine. 2002-04-28 12:03 Martin Pool * src/arg.c: Doc 2002-04-25 20:03 Martin Pool * src/distcc.c: Doc. 2002-04-25 20:00 Martin Pool * src/io.c: Use a larger copy buffer. 2002-04-25 19:59 Martin Pool * src/distcc.c: Be quiet by default 2002-04-25 19:32 Martin Pool * src/: arg.c, daemon.c: Fix filename substitution code. 2002-04-25 19:26 Martin Pool * src/arg.c: Fix message 2002-04-25 19:24 Martin Pool * src/: daemon.c, exec.c, io.c, io.h: Split out code for reading length-preceded strings. 2002-04-25 19:11 Martin Pool * src/daemon.c: Properly nul-terminate argv strings 2002-04-25 19:07 Martin Pool * src/distcc.h: Fix header 2002-04-25 19:05 Martin Pool * src/: daemon.c, distcc.h: Drop job structure altogether. The server no longer needs to use the client's argument parsing system. 2002-04-25 19:00 Martin Pool * src/: arg.c, distcc.h: Drop dead code 2002-04-25 18:57 Martin Pool * src/rpc.c: Better log 2002-04-25 18:56 Martin Pool * src/: io.h, rpc.c: Rename to dcc_r_token 2002-04-25 18:54 Martin Pool * src/io.c: IO errors need not cause us to abort. 2002-04-25 18:52 Martin Pool * src/daemon.c: Generate our slightly more proper temporary names. 2002-04-25 18:51 Martin Pool * src/trace.h: Add rs_log_critical convenience. 2002-04-25 18:48 Martin Pool * src/io.c: dcc_expect_token: check expected token is sane, and if read fails then say what we were hoping for 2002-04-25 18:44 Martin Pool * src/trace.c: Show pid in log messages. 2002-04-25 18:43 Martin Pool * src/: arg.c, distcc.h: Add dcc_set_input 2002-04-25 18:37 Martin Pool * src/: arg.c, daemon.c, distcc.c, distcc.h, rpc.c, rpc.h: Clean argc, argv, wait status stuff out of job structure. 2002-04-25 18:28 Martin Pool * src/arg.c: Better log messages from arg scanner 2002-04-25 18:18 Martin Pool * src/distcc.c: Actually go ahead and run cpp if necessary. 2002-04-25 18:07 Martin Pool * src/exec.c: Doc. 2002-04-25 18:06 Martin Pool * src/: daemon.c, distcc.h, exec.c: Cleanup dcc_run_child 2002-04-25 18:01 Martin Pool * src/: arg.c, distcc.h, exec.c: Show whole command being executed. 2002-04-25 17:50 Martin Pool * src/distcc.c: log message 2002-04-25 17:42 Martin Pool * src/GNUmakefile: Sketchy routines to build temporary filenames 2002-04-25 17:38 Martin Pool * src/tempfile.c: Sketchy routines to build temporary filenames 2002-04-25 17:38 Martin Pool * src/distcc.c: Get closer to running cpp locally 2002-04-25 17:37 Martin Pool * src/: arg.c, distcc.h: Add more argv[] utilities 2002-04-25 17:09 Martin Pool * src/arg.c: Fix harmless glitch. Better message. 2002-04-25 17:07 Martin Pool * src/util.c: Fix inverted sense in str_startswith 2002-04-25 16:59 Martin Pool * src/: arg.c, daemon.c, distcc.c, distcc.h, exec.c: Prepare to run preprocessor on client 2002-04-25 15:46 Martin Pool * src/arg.c: Better handle the case of being passed a non-preprocessed file. 2002-04-25 14:12 Martin Pool * src/arg.c: Fix headers. 2002-04-25 14:12 Martin Pool * src/: util.c, util.h: Add str_startswith 2002-04-25 14:08 Martin Pool * src/: distcc.c, distcc.h: Start adding support for running cpp ourselves before going across the network. 2002-04-25 14:07 Martin Pool * src/daemon.c: Error out if we somehow get a request to run cpp on the server. 2002-04-25 14:04 Martin Pool * src/arg.c: Parse out -o options; also work out whether we ought to call cpp. 2002-04-25 13:34 Martin Pool * src/: arg.c, daemon.c, distcc.c, distcc.h: Start refactoring argument scanner. 2002-04-25 13:15 Martin Pool * src/rpc.c: Must truncate temp file as we start receiving. 2002-04-25 12:00 Martin Pool * src/GNUmakefile: Doc. 2002-04-25 11:59 Martin Pool * src/: GNUmakefile, Makefile: The dependency stuff in the makefile current requires GNU Make, so change the filename to reflect that. 2002-04-25 01:33 Martin Pool * src/: daemon.c, distcc.c, io.c, rpc.c, rpc.h: client now receives DOTO file from the server and stores it in the destination 2002-04-25 01:23 Martin Pool * src/: daemon.c, distcc.c, io.c, io.h, rpc.c, rpc.h: Send back compiler wait-status and .o file 2002-04-25 01:11 Martin Pool * src/: daemon.c, distcc.c, rpc.c, rpc.h: Client now waits for the start of the response from the server 2002-04-25 01:11 Martin Pool * src/Makefile: Add rpc.c Make clean cleans .d files 2002-04-25 00:27 Martin Pool * src/: distcc.h, exec.c: Examine and remember the cc exit code. 2002-04-25 00:18 Martin Pool * src/: daemon.c, distcc.c, distcc.h, exec.c, io.h: Server now starts sending a response back. 2002-04-25 00:04 Martin Pool * src/: arg.c, daemon.c, distcc.c, distcc.h: Improve server-side argument argument parsing 2002-04-24 23:52 Martin Pool * src/arg.c: Better debug for server-side substitution 2002-04-24 23:44 Martin Pool * src/util.c: fix file-style 2002-04-24 23:44 Martin Pool * src/distcc.c: message when sending is complete 2002-04-24 23:43 Martin Pool * src/: daemon.c, util.h: redirect stderr to prevent fouling socket 2002-04-24 23:30 Martin Pool * src/distcc.c: Clean up; add error checks. 2002-04-24 23:30 Martin Pool * src/clinet.c: Clean up imported code, and in particular log messages 2002-04-24 23:29 Martin Pool * src/arg.c: Fix comment 2002-04-24 23:29 Martin Pool * src/Makefile: Store version in Makefile 2002-04-24 23:17 Martin Pool * src/clinet.c: Copy in network code from rsync. Currently hardcoded to localhost:4200. 2002-04-24 18:05 Martin Pool * src/: .cvsignore, Makefile, clinet.c, distcc.c, distcc.h: Start changes to connect across the network rather than dumping to a file. 2002-04-24 16:29 Martin Pool * src/distcc.c: Doc 2002-04-24 16:13 Martin Pool * src/: Makefile, arg.c, daemon.c, distcc.c, distcc.h, exec.c, io.c: daemon will now actually compile programs 2002-04-24 00:51 Martin Pool * src/: daemon.c, distcc.c, distcc.h, exec.c, io.c, io.h: Make the server receive the .i file into a temporary file. 2002-04-24 00:50 Martin Pool * src/Makefile: Fix 'make clean' 2002-04-24 00:49 Martin Pool * src/.cvsignore: Ignore any .i files that might be around 2002-04-24 00:21 Martin Pool * src/: Makefile, distcc.c, distcc.h, exec.c: Split out code to run the compiler 2002-04-24 00:10 Martin Pool * src/: README, daemon.c, distcc.c, distcc.h, io.c, io.h, trace.h: Server now reads argv from network. 2002-04-23 17:37 Martin Pool * src/: daemon.c, distcc.c, distcc.h, io.c: Start adding code to let the daemon read requests. 2002-04-23 16:39 Martin Pool * src/io.c: Split out more common code. Send the bulk of the file. Add a no-op distccd. 2002-04-23 16:33 Martin Pool * src/: .cvsignore, Makefile, daemon.c, distcc.c, distcc.h: Split out more common code. Send the bulk of the file. Add a no-op distccd. 2002-04-23 14:55 Martin Pool * src/: .cvsignore, Makefile, distcc.c, distcc.h, trace.c, util.c: Split utilities into their own file 2002-04-23 14:44 Martin Pool * src/distcc.c: Add framework for sending requests to server, but just send them to a tmpfile instead. 2002-04-23 14:24 Martin Pool * src/distcc.c: Put arguments into a jobinfo_t struct. 2002-04-23 14:14 Martin Pool * src/distcc.c: Try to detect .i and .o files 2002-04-23 13:47 Martin Pool * src/distcc.c: Handle empty command line. 2002-04-23 13:25 Martin Pool * src/.cvsignore: Ignore built files 2002-04-23 13:24 Martin Pool * src/: trace.c, trace.h: Copy trace routines from librsync 2002-04-23 13:22 Martin Pool * src/: distcc.c, .cvsignore, HACKING, Makefile: Copy very simple code into public samba cvs distcc-3.4/INSTALL000066400000000000000000000252421404653710500136740ustar00rootroot00000000000000Installation instructions for distcc -*- indented-text -*- distcc is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. distcc comes with ABSOLUTELY NO WARRANTY, for details see the licence. Please report any problems to distcc@lists.samba.com. QUICK SUMMARY ============= 0. Install prerequisites. For example, on Debian or Ubuntu, you could use sudo apt-get install gcc make python3 python3-dev libiberty-dev 1. Build and install ./autogen.sh # If "configure" does not already exist. ./configure make make check # Optional! Should have python >= 3.1 installed. make install # You may need to use "sudo" for this command. make installcheck # Optional! Should have python >= 3.1 installed. update-distcc-symlinks # Needs "sudo". Run this again if you install/remove compilers Repeat installation for each server machine. 2. Run distccd on each server machine, with --allow options to limit access. 3. On your client machine, set DISTCC_POTENTIAL_HOSTS to the list of distcc server machines: export DISTCC_POTENTIAL_HOSTS='localhost red green blue' 4. Build your software using distcc: cd ~/my_sources/my_project pump make -j40 CC="distcc gcc" 5. If you run into problems it is highly recommended to use DISTCC_VERBOSE=1 on the client and "--log-level debug" on the server. DETAILED INSTRUCTIONS ===================== Prerequisites ------------- To build distcc you need GNU Make A C compiler GNU libiberty (distributed with GNU Binutils and GCC) It is also highly desirable to have Python >=3.1 To use "pump" mode, or to run the full test suite with "make check", or to run the benchmarks. If you have any version of Python installed, then you need to have the corresponding Python.h file installed (e.g. sudo apt-get install python-dev). You can optionally have libpopt If this is not found on your system, the popt version that is part of the distcc distribution will be statically linked in. linuxdoc SGML tools To rebuild the documentation from its SGML source. autoconf >=2.5 To rebuild the configure scripts if you edit configure.ac. To build the optional GNOME monitor (--with-gnome), you need the GNOME2 development libraries, and in particular gtk+ >=2.0 libgnome >=2.0 libgnomeui >= 2.0 libglade >= 2.0 libpango The monitor can also be built without GNOME desktop integration (--with-gtk), in which case you need only gtk+ >=2.0 libglade >= 2.0 Preliminaries ------------- distcc can be installed and used without requiring root access. Adjust directories appropriately when installing. Configuring distcc ------------------ Note that the default GNU "sysconfdir" is /usr/local/etc. You may want to change this to /etc. $ ./configure --sysconfdir=/etc You can set an installation prefix if you want to put distcc in /opt: $ ./configure --prefix=/opt/distcc/ distcc needs to be installed on all client and server machines. If you would like a graphical client-side monitor to show running jobs, you can choose either --with-gnome or --with-gtk. If you would like to try running distcc over IPv6, use --enable-rfc2553. You must have a reasonably recent operating system or this is likely to fail in complex ways. Building distcc --------------- The simple way to build distcc is to just do ./autogen.sh # if "configure" does not already exist in this directory ./configure && make but the recommended way is to build in a different directory tree than the source tree: mkdir obj cd obj ../autogen.sh ../configure && make You can optionally run "make check" afterwards to verify that everything built OK. Installing distcc ----------------- If your system supports RPM packages, you can build RPMs with "make rpm" and then install them with "rpm -i packaging/*.rpm". If your system supports Debian packages, you can build them with "make deb" and then install them with "make install-deb". Otherwise, you can use the regular "make install". But it is preferable to install via an RPM or Debian package if possible, because those methods will do a bit more of the setup work. You can optionally run "make installcheck" afterwards to verify that was installed OK. This works regardless of which installation method you used. Starting the daemon ------------------- This stage is only required if you want to run distcc over TCP sockets, rather than SSH connections. TCP is faster but less secure and should only be used on trusted networks. In TCP mode distccd can run either from inetd or as a standalone daemon. Running standalone is recommended. If you installed via the debian or RPM package, then the daemon will be installed as a service, running as a standalone daemon, and it should get started up automatically, so you can skip the rest of this section "Starting the daemon". The rest of this section only applies if you installed via "make install". To run standalone, run a command like this, either from the command line or from the system startup scripts. distccd --daemon If the daemon is started from an rc script, then make sure that it sees a PATH setting which can find any compilers installed in nonstandard directories. You should create a "distcc" account on server machines so that distcc can run with minimal privilege. It is not necessary for this account to own any files or have a home directory. If this account doesn't exist, distccd uses the "nobody" account. By default distccd writes messages to the "daemon" syslog, which typically ends up in /var/log/messages or /var/log/daemon. You can set IP-based access control using the --allow and --listen options, in either inetd or daemon mode: distccd --allow 10.4.20.0/24 distccd does not need to run on machines that will only act as clients. See the manual for more information. Editing the daemon configuration files -------------------------------------- If you installed via the RPM or Debian package, then you will have an /etc/init.d/distcc script which reads several configuration files to decide if and how to invoke distccd. These configuration files are /etc/default/distcc /etc/distcc/clients.allow /etc/distcc/commands.allow.sh If you installed via the RPM or Debian package, then you should edit those configuration files, especially the clients.allow file. If you installed via "make install", then those configuration files will be installed, but they will NOT be used, unless you manually install the init.d/distcc script from packaging/RedHat/init.d/distcc and tailor it for your system. If you start distccd manually, rather than via the init.d/distcc script, then distccd won't use any configuration files; the allowed client IP addresses will be determined by the --allow options that you pass to distccd and the allowed commands will be determined by the DISTCC_CMDLIST environment variable; see the distccd(1) man page for details. See also the doc/example directory and its README file, which has examples of the configuration files that you need. Setting up the host list ------------------------ On the client machines, store a list of servers names in ~/.distcc/hosts or /etc/hosts, or in the DISTCC_HOSTS environment variable. If you're using TCP connections, it should look like this: localhost red green blue For SSH connections localhost @red @green @blue The hosts should be listed in descending order of speed. localhost should normally be first, unless it is significantly slower than another machine. If you many hosts (say ten or more), it's probably better to leave localhost out of the list. The host list also needs ",cpp,lzo" after each host if you're using pump mode - see README.pump for details. Another alternative if you're using pump mode is to set the DISTCC_POTENTIAL_HOSTS environment variable; in that case, the pump script will use "lsdistcc" to set DISTCC_HOSTS, automatically eliminating hosts that are down or inaccessible or that don't have distccd running. See the distcc(1) manual and the pump(1) manual for more information. Using distcc ------------ Distcc will only improve performance if your build is parallelized. So you need to use the "-j" option to make, or its equivalent with your build tools. If your build contains too many sequential steps, e.g. if your Makefile contains all: for subdir in $(SUBDIRS); do make -C $$subdir all; done then you may need to rewrite your Makefile to get better parallelism. This is especially important if you're using pump mode. Using pump mode --------------- To use pump mode, invoke your build command via the "pump" script, e.g. export DISTCC_POTENTIAL_HOSTS="localhost red blue green" cd ~/my_sources/my_project pump make -j40 CC="distcc gcc" my_target Pump mode assumes that source files are not modified during the build. If this assumption does not hold, you should not use pump mode. You can disable pump mode by not using the pump script. In that case, you need to set DISTCC_HOSTS rather than DISTCC_POTENTIAL_HOSTS. export DISTCC_HOSTS="localhost red blue green" cd ~/my_sources/my_project make -j40 CC="distcc gcc" my_target Creating the masquerade directories ----------------------------------- The easiest way to use distcc is in "masquerade" mode, where it is installed on the PATH to "catch" calls to the compiler and redirect them over the network. Other options are discussed in the manual. For instance, you could create the directory named /usr/lib/distcc and populate it with links. # mkdir /usr/lib/distcc # cd /usr/lib/distcc # ln -s /usr/bin/distcc gcc # ln -s /usr/bin/distcc cc # ln -s /usr/bin/distcc g++ # ln -s /usr/bin/distcc c++ If you installed via the RedHat or Debian package, then this masquerade directory is already set up automatically in /usr/lib/distcc. Do this for all compiler names that you use. Then, to use distcc, a user just needs to put the directory /usr/lib/distcc/bin early in the PATH and distcc will handle the rest. export PATH=/usr/lib/distcc/bin:$PATH Use with ccache --------------- The best way to use is to set up a similar masquerade directory for ccache and put it on the PATH before distcc. NOTE: This use of ccache is incompatible with use of distcc's "pump" mode. (If you're using "pump" mode, it might be possible to use ccache on the distcc server machines. But we haven't tried that setup.) Complete the survey ------------------- Once you have distcc working for your own application, please complete and mail in the survey in survey.txt. distcc-3.4/Makefile.in000066400000000000000000001247131404653710500147130ustar00rootroot00000000000000# Top-level Makefile(.in) for distcc # Copyright (C) 2002, 2003, 2004 by Martin Pool # Note that distcc no longer uses automake, but this file is still # structured in a somewhat similar way. ## VARIABLES PACKAGE = @PACKAGE_NAME@ VERSION = @PACKAGE_VERSION@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ SHELL = @SHELL@ # These autoconf variables may contain recursive Make expansions, and # so they have to be done here rather than written into config.h. CFLAGS = @CFLAGS@ WERROR_CFLAGS = @WERROR_CFLAGS@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ POPT_CFLAGS = @POPT_CFLAGS@ POPT_INCLUDES = @POPT_INCLUDES@ LDFLAGS = @LDFLAGS@ CC = @CC@ CPP = @CPP@ # We add a few cppflags. -Isrc is so that config.h can be found in the build # directory. It is before I"$(srcdir)/src" to reflect VPATH semantics. CPPFLAGS = @CPPFLAGS@ ${DIR_DEFS} \ -Isrc -I"$(srcdir)/src" -I"$(srcdir)/lzo" $(POPT_INCLUDES) PYTHON = @PYTHON@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ builddir = @builddir@ top_builddir = @top_builddir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datarootdir = @datarootdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include docdir = @docdir@ icondir = $(datarootdir)/pixmaps desktopdir = $(datarootdir)/applications include_server_builddir = $(builddir)/_include_server # These must be done from here, not from autoconf, because they can # contain variable expansions written in Make syntax. Ew. DIR_DEFS = -DLIBDIR="\"${libdir}\"" -DSYSCONFDIR="\"${sysconfdir}\"" -DICONDIR="\"${icondir}\"" # arguments to pkgconfig GNOME_PACKAGES = @GNOME_PACKAGES@ GNOME_CFLAGS = @GNOME_CFLAGS@ GNOME_LIBS = @GNOME_LIBS@ LIBS = @LIBS@ DESTDIR = INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ # RESTRICTED_PATH is a colon separated list of directory names. It # contains the locations of 'make', 'sh', 'gcc', and 'python' for use # in installation tests. This path is used to avoid confusion caused # by distcc masquerades on the normal path. See the # 'maintainer-check-no-set-path' target. RESTRICTED_PATH = /usr/local/bin:/bin:/usr/bin # The DISTCC_INSTALLATION variable is a colon separated list of # directory names of possible locations for the installation to be # checked. Change the value of this variable to @bindir@ to check the # installation at the location determined by 'configure'. DISTCC_INSTALLATION = $(RESTRICTED_PATH) dist_files = \ src/config.h.in \ $(dist_lzo) \ $(dist_contrib) \ $(dist_patches) \ $(dist_common) \ $(MEN) \ $(pkgdoc_DOCS) \ $(example_DOCS) \ $(popt_EXTRA) $(popt_SRC) $(popt_HEADERS) \ $(SRC) $(HEADERS) \ $(update_distcc_symlinks_PY) \ $(test_SOURCE) \ $(bench_PY) \ $(include_server_PY) \ $(dist_include_server_SH) \ $(include_server_SRC) \ $(check_include_server_DATA) \ $(check_include_server_PY) \ $(conf_files) \ $(default_files) \ $(dist_extra) \ $(gnome_data) dist_dirs = m4 include_server/test_data dist_lzo = lzo/minilzo.c \ lzo/minilzo.h \ lzo/lzoconf.h \ lzo/lzodefs.h \ lzo/.stamp-conf.in dist_contrib = contrib/distcc-absolutify \ contrib/distcc.sh \ contrib/distccd-init \ contrib/distccd-on-servers \ contrib/dmake \ contrib/make-j \ contrib/netpwd \ contrib/stage-cc-wrapper.patch \ contrib/redhat/init \ contrib/redhat/logrotate \ contrib/redhat/sysconfig \ contrib/redhat/xinetd dist_include_server_SH = \ pump.in bench_PY = bench/Build.py \ bench/Project.py \ bench/ProjectDefs.py \ bench/Summary.py \ bench/actions.py \ bench/benchmark.py \ bench/buildutil.py \ bench/compiler.py \ bench/statistics.py pkgdoc_DOCS = AUTHORS COPYING NEWS \ README README.pump \ INSTALL \ TODO \ doc/protocol-1.txt doc/status-1.txt \ doc/protocol-2.txt \ doc/protocol-3.txt doc/protocol-3-impl.txt \ doc/protocol-gssapi.txt \ doc/reporting-bugs.txt \ survey.txt example_DOCS = \ doc/example/README \ doc/example/default \ doc/example/hosts.allow \ doc/example/services \ doc/example/init doc/example/init-suse \ doc/example/logrotate \ doc/example/xinetd \ include_server_PY = \ include_server/basics.py \ include_server/cache_basics.py \ include_server/compiler_defaults.py \ include_server/compress_files.py \ include_server/include_analyzer.py \ include_server/include_analyzer_memoizing_node.py \ include_server/include_server.py \ include_server/macro_eval.py \ include_server/mirror_path.py \ include_server/parse_command.py \ include_server/parse_file.py \ include_server/run.py \ include_server/setup.py \ include_server/statistics.py include_server_SRC = \ include_server/c_extensions/distcc_pump_c_extensions_module.c update_distcc_symlinks_PY = update-distcc-symlinks.py # These are included in the distribution but not installed anywhere. dist_extra = \ README.packaging ChangeLog \ packaging/RedHat/rpm.spec \ packaging/RedHat/logrotate.d/distcc \ packaging/RedHat/init.d/distcc \ packaging/RedHat/xinetd.d/distcc \ packaging/deb.sh \ packaging/rpm.sh \ packaging/googlecode_upload.py mkinstalldirs = $(SHELL) $(srcdir)/mkinstalldirs man1dir = $(mandir)/man1 man8dir = $(mandir)/man8 test_SOURCE = test/comfychair.py \ test/onetest.py \ test/testdistcc.py \ find_c_extension.sh dist_common = Makefile.in install-sh configure configure.ac \ config.guess config.sub mkinstalldirs autogen.sh # It seems a bit unnecessary to ship patches in the released tarballs. # People who are so keen as to apply unsupported patches ought to use # CVS, or at least get them from the list. dist_patches = TAR = tar GZIP_BIN = gzip # This is set on the environment, and automatically read by gzip. # This way we always get best compression, even when gzip is run in a # script we call, rather than being called by us directly. GZIP = -9v BZIP2_BIN = bzip2 distdir = $(PACKAGE_TARNAME)-$(VERSION) tarball = $(PACKAGE_TARNAME)-$(VERSION).tar tarball_bz2 = $(tarball).bz2 tarball_gz = $(tarball).gz tarball_sig_bz2 = $(tarball_bz2).asc tarball_sig_gz = $(tarball_gz).asc distnews = $(PACKAGE_TARNAME)-$(VERSION).NEWS rpm_glob_pattern = "$(PACKAGE)"*[-_.]"$(VERSION)"[-_.]*.rpm deb_glob_pattern = "$(PACKAGE)"*[-_.]"$(VERSION)"[-_.]*.deb common_obj = src/arg.o src/argutil.o \ src/cleanup.o src/compress.o \ src/trace.o src/util.o src/io.o src/exec.o \ src/rpc.o src/tempfile.o src/bulk.o src/help.o src/filename.o \ src/lock.o \ src/netutil.o \ src/pump.o \ src/sendfile.o \ src/safeguard.o src/snprintf.o src/timeval.o \ src/dotd.o \ src/hosts.o src/hostfile.o \ src/implicit.o src/loadfile.o \ lzo/minilzo.o \ @ZEROCONF_COMMON_OBJS@ \ @AUTH_COMMON_OBJS@ distcc_obj = src/backoff.o \ src/climasq.o src/clinet.o src/clirpc.o \ src/compile.o src/cpp.o \ src/distcc.o \ src/remote.o \ src/ssh.o src/state.o src/strip.o \ src/timefile.o src/traceenv.o \ src/include_server_if.o \ src/where.o \ @ZEROCONF_DISTCC_OBJS@ \ @AUTH_DISTCC_OBJS@ \ src/emaillog.o \ $(common_obj) distccd_obj = src/access.o \ src/daemon.o src/dopt.o src/dparent.o src/dsignal.o \ src/ncpus.o \ src/prefork.o \ src/stringmap.o \ src/serve.o src/setuid.o src/srvnet.o src/srvrpc.o src/state.o \ src/stats.o \ src/fix_debug_info.o \ @ZEROCONF_DISTCCD_OBJS@ \ @AUTH_DISTCCD_OBJS@ \ $(common_obj) @BUILD_POPT@ lsdistcc_obj = src/lsdistcc.o \ src/clinet.o src/io.o src/netutil.o src/trace.o src/util.o \ src/rslave.o src/snprintf.o \ lzo/minilzo.o # Objects that need to be linked in to build monitors mon_obj = \ src/cleanup.o \ src/filename.o \ src/io.o \ src/mon.o \ src/netutil.o \ src/argutil.o \ src/rpc.o \ src/snprintf.o src/state.o \ src/tempfile.o src/trace.o src/traceenv.o \ src/util.o gnome_obj = src/history.o src/mon-gnome.o \ src/renderer.o h_exten_obj = src/h_exten.o $(common_obj) h_issource_obj = src/h_issource.o $(common_obj) h_scanargs_obj = src/h_scanargs.o $(common_obj) h_hosts_obj = src/h_hosts.o $(common_obj) h_argvtostr_obj = src/h_argvtostr.o $(common_obj) h_strip_obj = src/h_strip.o $(common_obj) src/strip.o h_parsemask_obj = src/h_parsemask.o $(common_obj) src/access.o h_sa2str_obj = src/h_sa2str.o $(common_obj) src/srvnet.o src/access.o h_ccvers_obj = src/h_ccvers.o $(common_obj) h_dotd_obj = src/h_dotd.o $(common_obj) h_fix_debug_info = src/h_fix_debug_info.o $(common_obj) h_compile_obj = src/h_compile.o $(common_obj) src/compile.o src/timefile.o \ src/backoff.o src/emaillog.o src/remote.o src/clinet.o \ src/clirpc.o src/include_server_if.o src/state.o src/where.o \ src/ssh.o src/strip.o src/cpp.o @AUTH_DISTCC_OBJS@ h_getline_obj = src/h_getline.o $(common_obj) # All source files, for the purposes of building the distribution SRC = src/stats.c \ src/access.c src/arg.c src/argutil.c \ src/auth_common.c src/auth_distcc.c src/auth_distccd.c \ src/backoff.c src/bulk.c \ src/cleanup.c \ src/climasq.c src/clinet.c src/clirpc.c src/compile.c \ src/compress.c src/cpp.c \ src/daemon.c src/distcc.c src/dsignal.c \ src/dopt.c src/dparent.c src/exec.c src/filename.c \ src/h_argvtostr.c \ src/h_exten.c src/h_hosts.c src/h_issource.c src/h_parsemask.c \ src/h_sa2str.c src/h_scanargs.c src/h_strip.c \ src/h_dotd.c src/h_compile.c src/h_getline.c \ src/help.c src/history.c src/hosts.c src/hostfile.c \ src/implicit.c src/io.c \ src/loadfile.c src/lock.c \ src/mon.c src/mon-notify.c src/mon-text.c \ src/mon-gnome.c \ src/ncpus.c src/netutil.c \ src/prefork.c src/pump.c \ src/remote.c src/renderer.c src/rpc.c \ src/safeguard.c src/sendfile.c src/setuid.c src/serve.c \ src/snprintf.c src/state.c \ src/srvnet.c src/srvrpc.c src/ssh.c \ src/stringmap.c src/strip.c \ src/tempfile.c src/timefile.c \ src/timeval.c src/traceenv.c \ src/trace.c src/util.c src/where.c \ src/lsdistcc.c src/rslave.c \ src/dotd.c src/include_server_if.c \ src/emaillog.c \ src/fix_debug_info.c \ src/zeroconf.c src/zeroconf-reg.c src/gcc-id.c HEADERS = src/stats.h \ src/access.h \ src/auth.h \ src/bulk.h \ src/clinet.h src/compile.h \ src/daemon.h \ src/distcc.h src/dopt.h src/exitcode.h \ src/fix_debug_info.h \ src/hosts.h src/implicit.h \ src/mon.h \ src/netutil.h \ src/renderer.h src/rpc.h \ src/snprintf.h src/state.h \ src/stringmap.h \ src/timefile.h src/timeval.h src/trace.h \ src/types.h \ src/util.h \ src/exec.h src/lock.h src/where.h src/srvnet.h \ src/rslave.h \ src/dotd.h src/include_server_if.h \ src/emaillog.h \ src/va_copy.h \ src/zeroconf.h conf_dir = packaging/RedHat/conf conf_files = $(conf_dir)/hosts \ $(conf_dir)/clients.allow \ $(conf_dir)/commands.allow.sh default_dir = packaging/RedHat/default default_files = $(default_dir)/distcc man1_MEN = man/distcc.1 man/distccd.1 man/distccmon-text.1 \ man/lsdistcc.1 man/pump.1 man/include_server.1 man_HTML = man/distcc_1.html man/distccd_1.html man/distccmon_text_1.html \ man/lsdistcc_1.html man/pump_1.html man/include_server_1.html MEN = $(man1_MEN) gnome_data = gnome/distccmon-gnome.png \ gnome/distccmon-gnome.desktop popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ popt/popthelp.o popt/poptparse.o popt_SRC=popt/findme.c popt/popt.c popt/poptconfig.c \ popt/popthelp.c popt/poptparse.c popt_HEADERS = popt/findme.h popt/popt.h popt/poptint.h popt/system.h popt_EXTRA = popt/README.popt popt/.stamp-conf.in # You might think that distccd ought to be in sbin, because it's a # daemon. It is a grey area. However, the Linux Filesystem Hierarchy # Standard (FHS 2.2) says that sbin is for programs "used exclusively # by the system administrator". # distccd will often be used by non-root users, and when we support # ssh it will be somewhat important that it be found in their default # path. Therefore on balance it seems better to put it in bin/. # Package maintainers can override this if absolutely necessary, but I # would prefer that they do not. -- mbp bin_PROGRAMS = \ distcc@EXEEXT@ \ distccd@EXEEXT@ \ distccmon-text@EXEEXT@ \ lsdistcc@EXEEXT@ \ @GNOME_BIN@ sbin_PROGRAMS = \ update-distcc-symlinks check_PROGRAMS = \ h_argvtostr@EXEEXT@ \ h_exten@EXEEXT@ \ h_fix_debug_info@EXEEXT@ \ h_hosts@EXEEXT@ \ h_issource@EXEEXT@ \ h_parsemask@EXEEXT@ \ h_sa2str@EXEEXT@ \ h_scanargs@EXEEXT@ \ h_strip@EXEEXT@ \ h_dotd@EXEEXT@ \ h_compile@EXEEXT@ \ h_getline@EXEEXT@ check_include_server_PY = \ include_server/c_extensions_test.py \ include_server/include_server_test.py \ include_server/macro_eval_test.py \ include_server/mirror_path_test.py \ include_server/parse_command_test.py \ include_server/parse_file_test.py \ include_server/include_analyzer_test.py \ include_server/include_analyzer_memoizing_node_test.py \ include_server/basics_test.py ###################################################################### ## IMPLICIT BUILD rules .SUFFIXES: .html .latte .o .c .c.o: $(CC) $(CPPFLAGS) $(WERROR_CFLAGS) $(CFLAGS) -o $@ -c $< ###################################################################### ## OVERALL targets .PHONY: all include-server ## NOTE: "all" must be the first (default) rule, aside from patterns. all: $(bin_PROGRAMS) $(sbin_PROGRAMS) pump include-server # src/config.h.in is used by config.status Makefile: Makefile.in src/config.h.in config.status ./config.status ###################################################################### ## BUILD targets # We would like to detect when config.h.in has changed: this should trigger # config.status to be rerun. But if the config.h file actually does not change # as a result of running config.status (a feature of autoconf), then # config.status will be rerun every time. That's confusing. So, the rule # # src/config.h: src/config.h.in # ./config.status # # is not sufficient. src/config.h: src/config.h.stamp src/config.h.stamp: src/config.h.in echo "path: $$PATH" ./config.status touch src/config.h.stamp pump: pump.in config.status ./config.status # Grab the dependency files generated by gcc's -MD option. -include */*.d # Disable some warnings for popt/*.c. $(popt_OBJS): CFLAGS += $(POPT_CFLAGS) distcc@EXEEXT@: $(distcc_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(distcc_obj) $(LIBS) distccd@EXEEXT@: $(distccd_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(distccd_obj) $(LIBS) distccmon-text@EXEEXT@: $(mon_obj) src/mon-text.o $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(mon_obj) src/mon-text.o $(LIBS) lsdistcc@EXEEXT@: $(lsdistcc_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(lsdistcc_obj) $(LIBS) update-distcc-symlinks: $(update_distcc_symlinks_PY) cp $< $@ h_exten@EXEEXT@: $(h_exten_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_exten_obj) $(LIBS) h_issource@EXEEXT@: $(h_issource_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_issource_obj) $(LIBS) h_sa2str@EXEEXT@: $(h_sa2str_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_sa2str_obj) $(LIBS) h_scanargs@EXEEXT@: $(h_scanargs_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_scanargs_obj) $(LIBS) h_hosts@EXEEXT@: $(h_hosts_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_hosts_obj) $(LIBS) h_argvtostr@EXEEXT@: $(h_argvtostr_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_argvtostr_obj) $(LIBS) h_parsemask@EXEEXT@: $(h_parsemask_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_parsemask_obj) $(LIBS) h_strip@EXEEXT@: $(h_strip_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_strip_obj) $(LIBS) h_ccvers@EXEEXT@: $(h_ccvers_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_ccvers_obj) $(LIBS) h_dotd@EXEEXT@: $(h_dotd_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_dotd_obj) $(LIBS) h_fix_debug_info@EXEEXT@: $(h_fix_debug_info) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_fix_debug_info) $(LIBS) h_compile@EXEEXT@: $(h_compile_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_compile_obj) $(LIBS) h_getline@EXEEXT@: $(h_getline_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_getline_obj) $(LIBS) src/h_fix_debug_info.o: src/fix_debug_info.c $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) \ -DTEST \ $(srcdir)/src/fix_debug_info.c src/mon-gnome.o: src/mon-gnome.c $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) \ $(GNOME_CFLAGS) \ $(srcdir)/src/mon-gnome.c src/renderer.o: src/renderer.c $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) \ $(GNOME_CFLAGS) \ $(srcdir)/src/renderer.c distccmon-gnome@EXEEXT@: $(mon_obj) $(gnome_obj) $(CC) -o $@ $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) \ $(mon_obj) $(gnome_obj) \ $(LIBS) $(GNOME_CFLAGS) $(GNOME_LIBS) # The include-server is a python app, so we use Python's build system. We pass # the distcc version, the source location, the CPP flags (for location of the # includes), and the build location. include-server: if test -z "$(PYTHON)"; then \ echo "Not building $@: No suitable python found"; \ else \ mkdir -p "$(include_server_builddir)" && \ DISTCC_VERSION="$(VERSION)" \ SRCDIR="$(srcdir)" \ CFLAGS="$(CFLAGS) $(PYTHON_CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ $(PYTHON) "$(srcdir)/include_server/setup.py" \ build \ --build-base="$(include_server_builddir)" \ --build-temp="$(include_server_builddir)"; \ fi ###################################################################### ## DIST TARGETS .PHONY: dist distcheck dist-sign dist-files # The sub-targets copy (and if necessary, build) various files that # have to go into the tarball. They also create necessary directories # -- bear in mind that they might be run in parallel. # This looks a bit gross to me, but it's not as bad as it might be :-/ # TODO(csilvers): add 'make rpm' and 'make deb'. dist: -rm -fr "$(distdir)" $(MAKE) dist-files $(TAR) cf "$(tarball)" "$(distdir)" $(GZIP_BIN) --help >/dev/null 2>&1 && \ $(GZIP_BIN) -fc "$(tarball)" > "$(tarball_gz)" $(BZIP2_BIN) --help 2>/dev/null && \ $(BZIP2_BIN) -vfc "$(tarball)" > "$(tarball_bz2)" rm -f "$(tarball)" rm -fr "$(distdir)" cp "$(srcdir)/NEWS" "$(distnews)" # We create two new directories: one for the build and one to install, # and make sure we can build and install from different directories # than the source directory. Then we run a "make distclean" and # verify it got rid of everything not in the tarball by deleting every # file mentioned in the tarball, and then making sure nothing is left. distcheck: dist [ ! -d +distcheck ] || chmod -R u+w +distcheck rm -rf '+distcheck' mkdir '+distcheck' cd '+distcheck' && $(GZIP_BIN) -d < "../$(tarball_gz)" | $(TAR) xvf - mkdir "+distcheck/$(distdir)/_build" mkdir "+distcheck/$(distdir)/_inst" chmod -R a-w +distcheck chmod u+w "+distcheck/$(distdir)/_build" "+distcheck/$(distdir)/_inst" dc_install_base=`cd "+distcheck/$(distdir)/_inst" && pwd` \ && cd "+distcheck/$(distdir)/_build" \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) && $(MAKE) maintainer-check \ && $(MAKE) install \ && $(MAKE) DISTCC_INSTALLATION="$$dc_install_base/bin" \ maintainer-installcheck \ && $(MAKE) distclean chmod -R u+w +distcheck test `find "+distcheck/$(distdir)/_build" -type f -print | wc -l` -eq 0 \ || { echo "ERROR: files left in build-dir after distclean:"; \ find "+distcheck/$(distdir)/_build" -type f -print; \ rm -rf '+distcheck'; \ exit 1; } rm -rf '+distcheck' dist-sign: gpg -a --detach-sign "$(tarball_bz2)" # For the dirs we copy, we don't want to copy control files like '.cvs'. # We use find for this; if 'find' doesn't work, just don't worry about it. dist-files: $(dist_files) for f in $(dist_files) $(dist_dirs); do \ mkdir -p "$(distdir)"/`dirname "$$f"` || exit 1; \ cp -pR "$(srcdir)/$$f" "$(distdir)/$$f" 2>/dev/null || \ cp -pR "$$f" "$(distdir)/$$f" || exit 1; \ done for f in $(dist_dirs); do \ find "$(distdir)/$$f" -name '.[^.]*' -exec rm -rf \{\} \; -prune ; \ done ###################################################################### ## BUILD manual targets man/distcc_1.html: man/distcc.1 troff2html -man "$(srcdir)"/man/distcc.1 > $@ man/distccd_1.html: man/distccd.1 troff2html -man "$(srcdir)"/man/distccd.1 > $@ man/distccmon_text_1.html: man/distccmon-text.1 troff2html -man "$(srcdir)"/man/distccmon-text.1 > $@ man/lsdistcc_1.html: man/lsdistcc.1 troff2html -man "$(srcdir)"/man/lsdistcc.1 > $@ man/pump_1.html: man/pump.1 troff2html -man "$(srcdir)"/man/pump.1 > $@ man/include_server_1.html: man/include_server.1 troff2html -man "$(srcdir)"/man/include_server.1 > $@ ###################################################################### ## CHECK targets for code that has been build. .PHONY: check_programs .PHONY: maintainer-check-no-set-path distcc-maintainer-check .PHONY: include-server-maintainer-check pump-maintainer-check .PHONY: maintainer-check .PHONY: check .PHONY: lzo-check valgrind-check single-test pump-single-test check_programs: $(check_PROGRAMS) $(bin_PROGRAMS) TESTDISTCC_OPTS = # This target is for internal use by distcc-maintainer-check and # distcc-installcheck. These rules differ only in their choice of the value of # PATH to use. PATH must be set appropriately so that python, distcc binaries, # gcc, and those of the check_PROGRAMS, can be found on PATH. This is done in # the call of this target through use of the variable RESTRICTED_PATH. # # The more prominent of these conditions are checked explicitly checked below. # # TODO(klarlund): the outermost if assumes that the include-server target may be # satisfied w/o actually building an include server (or rather the C extension); # this logic needs to be verified or amended. maintainer-check-no-set-path: @if ! $(PYTHON) -c 'import sys; print(sys.version)'; then \ echo "WARNING: python not found; tests skipped"; \ else \ if ! $(CC) --version 2>/dev/null; then \ echo "Could not find CC on the restricted path used to avoid"; \ echo "confusion caused by distcc masquerades on the normal path."; \ echo "PATH is currently '$$PATH'."; \ echo "Please change RESTRICTED_PATH to change this PATH value."; \ exit 1; \ fi; \ $(PYTHON) "$(srcdir)/test/testdistcc.py" $(TESTDISTCC_OPTS); \ fi distcc-maintainer-check: check_programs $(MAKE) PATH="`pwd`:$(RESTRICTED_PATH)" \ TESTDISTCC_OPTS="$(TESTDISTCC_OPTS)" maintainer-check-no-set-path # If the include server extension module was built, then run the tests include # server. TODO(klarlund): the outermost if assumes that the include-server # target may be satisfied w/o actually building an include server (or rather the # C extension); this logic needs to be verified or amended. # TODO(csilvers): keep track of failures instead of exiting on the first one. include-server-maintainer-check: include-server @if ! test -d "$(include_server_builddir)"; then \ echo "Skipped include-server check"; \ else \ CURDIR=`pwd`; \ include_server_loc=`"$(srcdir)/find_c_extension.sh" "$(builddir)"`; \ test $$? = 0 || (echo 'Could not locate extension.' 1>&2 && exit 1); \ cd "$(srcdir)/include_server"; \ for p in $(check_include_server_PY); do \ p_base=`basename "$$p"`; \ echo "Running:" \ "PYTHONPATH=$$CURDIR/$$include_server_loc:$$PYTHONPATH $(PYTHON) $$p_base"; \ if PYTHONPATH="$$CURDIR/$$include_server_loc:$$PYTHONPATH" $(PYTHON) "$$p_base" \ > "$$CURDIR/$(tempdir)/$$p_base.out" 2>&1; then \ echo "PASS"; \ rm "$$CURDIR/$(tempdir)/$$p_base.out"; \ else \ echo "FAIL"; cat "$$CURDIR/$(tempdir)/$$p_base.out"; exit 1; \ fi; \ done; \ fi # Do distcc-maintainer-check in pump-mode, if possible. pump-maintainer-check: pump include-server check_programs @if [ -d "$(include_server_builddir)" ]; then \ DISTCC_HOSTS=',cpp,lzo' \ "$(builddir)/pump" \ $(MAKE) \ RESTRICTED_PATH="$(RESTRICTED_PATH)" \ TESTDISTCC_OPTS="--pump $(TESTDISTCC_OPTS)" \ distcc-maintainer-check; \ fi # Do distcc-maintainer-check, for non-pumped distcc, and try the include_server # check to check the include server's behavior, if applicable. If the include # server exists, then carry out distcc-maintainer-check in pump-mode. maintainer-check: distcc-maintainer-check include-server-maintainer-check \ pump-maintainer-check check: @if test -n "$(PYTHON)"; then \ $(MAKE) maintainer-check; \ else \ echo "WARNING: pump-mode not being tested"; \ $(MAKE) distcc-maintainer-check; \ fi # Runs the tests in lzo-mode. lzo-check: $(MAKE) TESTDISTCC_OPTS=--lzo maintainer-check # Runs the tests with valgrind. valgrind-check: $(MAKE) TESTDISTCC_OPTS=--valgrind maintainer-check # The following target is useful for running a single test at a time. # Sample usage: # make TESTNAME=Lsdistcc_Case single-test # make TESTNAME=Lsdistcc_Case TESTDISTCC_OPTS=--valgrind single-test TESTNAME = NoDetachDaemon_Case # Override this with the desired test. single-test: check_programs PATH="`pwd`:$(RESTRICTED_PATH)" \ $(PYTHON) "$(srcdir)/test/onetest.py" $(TESTDISTCC_OPTS) $(TESTNAME) # Run a single test in pump-mode. pump-single-test: pump include-server check_programs DISTCC_HOSTS=',cpp,lzo' \ "$(builddir)/pump" \ $(MAKE) \ RESTRICTED_PATH="$(RESTRICTED_PATH)" \ TESTDISTCC_OPTS="--pump $(TESTDISTCC_OPTS)" \ single-test ###################################################################### ## CHECK targets for code that has been installed. .PHONY: pump-installcheck distcc-installcheck maintainer-installcheck .PHONY: installcheck verify-binaries-installcheck daemon-installcheck # Verify that DISTCC_INSTALLATION contains the expected set of binaries. verify-binaries-installcheck: @echo "Locating binaries in" \ "DISTCC_INSTALLATION='$(DISTCC_INSTALLATION)'" @echo "To use installation in @bindir@, remake with" \ "argument 'DISTCC_INSTALLATION=@bindir@'." @echo "Make sure all paths below are where you expect them to be:" @echo "**********************************************************" @for p in $(bin_PROGRAMS); do \ if ! PATH="$(DISTCC_INSTALLATION)" `which which` "$$p"; then \ echo "Binary '$$p' could not be found in DISTCC_INSTALLATION."; \ exit 1; \ fi; \ done @echo "**********************************************************" # Lookup distcc programs to be checked in $(DISTCC_INSTALLATION). The # check_PROGRAMS binaries, however, are to be found in $(builddir). distcc-installcheck: $(check_PROGRAMS) BUILDDIR=`cd "$(builddir)" && pwd`; \ PATH="$(DISTCC_INSTALLATION):$$BUILDDIR:$(RESTRICTED_PATH)" \ TESTDISTCC_OPTS="$(TESTDISTCC_OPTS)" \ $(MAKE) maintainer-check-no-set-path # Check the installation to see whether pump-mode works. pump-installcheck: which_loc=`which which`; \ pump_loc=`PATH="$(DISTCC_INSTALLATION)" "$$which_loc" pump`; \ DISTCC_HOSTS=',cpp,lzo' \ "$$pump_loc" \ $(MAKE) DISTCC_INSTALLATION="$(DISTCC_INSTALLATION)" \ RESTRICTED_PATH="$(RESTRICTED_PATH)" \ TESTDISTCC_OPTS=--pump distcc-installcheck; \ # "make maintainer-installcheck" verifies the currently installed version in # RESTRICTED_PATH. It does not have the "install" target as a dependency so # that you can can check an installation that is installed via some different # method (e.g. rpm or debian package). You must specify the location of such an # installation by overriding the value of DISTCC_INSTALLATION. # # The maintainer-installcheck does not run the include server unit tests; # but the integration tests in 'test' are run in pump mode. maintainer-installcheck: verify-binaries-installcheck distcc-installcheck \ pump-installcheck installcheck: @if test -n "$(PYTHON)"; then \ $(MAKE) maintainer-installcheck; \ elif test -n "$(PYTHON)"; then \ echo "WARNING: pump-mode not being tested"; \ $(MAKE) distcc-maintainer-installcheck; \ else \ echo "Cannot run install-tests: python binary not found"; \ false; \ fi # This tests that the distcc daemon is running, and that it and distcc # and the pump script have been installed correctly, by compiling a simple # hello world program with distcc and distcc-pump. # This can be used after "make install-deb". # # This uses distcc from your PATH and (for the first test) # may use DISTCC_HOSTS from your environment or /etc/distcc/hosts. # # This test might fail if the --allow options passed to distccd # (which may be set in the /etc/distcc/clients.allow file) # do not include 127.0.0.1. daemon-installcheck: mkdir -p _testtmp/daemon-installcheck && \ cd _testtmp/daemon-installcheck && \ echo '#include ' > hello.c && \ echo 'int main(void) { puts("hello world"); return 0; }' >> hello.c && \ rm -f hello.o && \ DISTCC_FALLBACK=0 distcc $(CC) $(CFLAGS) -c hello.c -o hello.o && \ test -f hello.o && \ rm -f hello.o && \ DISTCC_POTENTIAL_HOSTS=127.0.0.1 DISTCC_FALLBACK=0 \ pump distcc $(CC) $(CFLAGS) -c hello.c -o hello.o && \ test -f hello.o ###################################################################### ## BENCHMARK targets .PHONY: benchmark benchmark: @echo "The distcc macro-benchmark uses your existing distcc installation" @if [ -n "$$DISTCC_HOSTS" ]; \ then echo "DISTCC_HOSTS=\"$$DISTCC_HOSTS\""; \ else echo "You must set up servers and set DISTCC_HOSTS before running the benchmark"; \ exit 1; \ fi @echo "This benchmark may download a lot of source files, and it takes a " @echo "long time to run. Interrupt now if you want." @echo @echo "Pass BENCH_ARGS to make to specify which benchmarks to run." @echo @sleep 5 cd bench && $(PYTHON) benchmark.py $(BENCH_ARGS) ###################################################################### ## CLEAN targets .PHONY: clean clean-autoconf clean-lzo clean-include-server .PHONY: maintainer-clean maintainer-clean-autoconf distclean distclean-autoconf # Also clean binaries which are optionally built. Also remove .d files; old ones # may confuse 'make'. clean: clean-autoconf clean-lzo clean-include-server rm -f src/*.[od] popt/*.[od] rm -f test/*.pyc rm -f $(check_PROGRAMS) $(bin_PROGRAMS) $(sbin_PROGRAMS) rm -f `echo $(man1_MEN) | sed -e 's/ /.gz /g' -e 's/$$/.gz/'` rm -f $(man_HTML) rm -f distccmon-gnome rm -rf _testtmp # produced by test/testdistcc.py and daemon-installcheck rm -rf +distcheck rm -rf "$(include_server_builddir)" clean-autoconf: rm -f config.cache config.log clean-lzo: rm -f lzo/*.[od] lzo/testmini clean-include-server: if test -n "$(PYTHON)"; then \ DISTCC_VERSION="$(VERSION)" \ SRCDIR="$(srcdir)" \ CFLAGS="$(CFLAGS) $(PYTHON_CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ $(PYTHON) "$(srcdir)/include_server/setup.py" \ clean \ --build-base="$(include_server_builddir)" \ --build-temp="$(include_server_builddir)"; \ fi maintainer-clean: distclean \ maintainer-clean-autoconf clean # configure and co are distributed, but not in CVS maintainer-clean-autoconf: rm -f configure src/config.h.in distclean-autoconf: rm -f Makefile src/config.h src/config.h.stamp pump rm -f popt/.stamp-conf lzo/.stamp-conf rm -f config.status config.cache config.log aclocal.m4 rm -rf autom4te.cache distclean: distclean-autoconf clean ###################################################################### ## MAINTAINER targets .PHONY: man-html upload-man upload-dist rpm deb install-deb man-html: $(man_HTML) mkdir -p doc/web/man cp -f $(man_HTML) doc/web/man upload-man: man-html svn commit doc/web/man # When uploading the package, we try to update the website as well. # However, that's just best-effort, and if we can't (because, say, we # don't have troff2html installed), we just upload the tarballs. upload-dist: alldist -$(MAKE) upload-man "$(srcdir)/packaging/googlecode_upload.py" \ "$(tarball_gz)" \ "$(tarball_bz2)" \ packaging/$(rpm_glob_pattern) \ packaging/$(deb_glob_pattern) rpm: dist packaging/rpm.sh packaging/RedHat/rpm.spec cd packaging && ./rpm.sh $(PACKAGE) $(VERSION) # This uses the output of 'make rpm' to convert rpm files to deb files deb: rpm packaging/deb.sh cd packaging && ./deb.sh $(PACKAGE) $(VERSION) *.rpm # We copy .deb files to /tmp to avoid problems with NFS root_squash. install-deb: deb tmpdir=`mktemp -d /tmp/distcc-install-deb-XXXXXX` && \ cp packaging/*.deb $$tmpdir && \ cd "$$tmpdir" && \ sudo dpkg -i $(deb_glob_pattern) && \ rm -rf $$tmpdir # deb creates rpm files first, which in turn creates .gz files alldist: deb @echo dist files created: @ls -1 "$(tarball_gz)" "$(tarball_bz2)" @ls -1 packaging/$(rpm_glob_pattern) @ls -1 packaging/$(deb_glob_pattern) ### INSTALL (and UNINSTALL) targets .PHONY: showpaths install install-programs install-include-server .PHONY: install-man install-doc install-example install-gnome-data .PHONY: install-conf # TODO: Allow root directory to be overridden for use in building # packages. showpaths: @echo "'make install' will install distcc as follows:" @echo " man pages $(DESTDIR)$(man1dir)" @echo " documents $(DESTDIR)$(docdir)" @echo " programs $(DESTDIR)$(bindir)" @echo " sbin programs $(DESTDIR)$(sbindir)" @echo " system configuration $(DESTDIR)$(sysconfdir)" @echo " icon file $(DESTDIR)$(icondir)" @echo " application file $(DESTDIR)$(desktopdir)" # install-sh can't handle multiple arguments, but we don't need any # tricky features so mkinstalldirs and cp will do install: showpaths install-doc install-man install-programs \ install-include-server install-example @INSTALL_GNOME@ install-conf install-programs: $(bin_PROGRAMS) $(sbin_PROGRAMS) $(mkinstalldirs) "$(DESTDIR)$(bindir)" $(mkinstalldirs) "$(DESTDIR)$(sbindir)" for p in $(bin_PROGRAMS); do \ $(INSTALL_PROGRAM) "$$p" "$(DESTDIR)$(bindir)" || exit 1; \ done for p in $(sbin_PROGRAMS); do \ $(INSTALL_PROGRAM) "$$p" "$(DESTDIR)$(sbindir)" || exit 1; \ done # See comments for the include-server target. Also, we work around an issue in # the change_root function of distutils/utils.py that turns the absolute prefix # into a relative reference if the root is the empty string: we absolutize the # destination directory in order to substitute '/' for the empty prefix (the # default) when defining the '--root' parameter. # The final complex issue involves installing pump. pump wants to # know the installed-location of include_server.py. The only way to # tell is to have setup.py install it, and then look what it says (via # the --record output). So when installing pump, we look at the # --record output and modify the installed pump to have that location. # Note: --record output is inconsistent (buggy?) and sometimes leaves out # the leading slash in $prefix, even though we require prefix start with # a slash. We use sed to add it back in at cp time. # Also, on Cygwin the --record output is in DOS text file format (CR LF # line endings), so we need to convert it from DOS text file format to # Unix text file format (LF line endings); we use sed for that too. install-include-server: include-server pump if test -z "$(PYTHON)"; then \ echo "Not building $@: No suitable python found"; \ else \ mkdir -p "$(include_server_builddir)" && \ DESTDIR=`cd "$(DESTDIR)/" && pwd` && \ DISTCC_VERSION="$(VERSION)" \ SRCDIR="$(srcdir)" \ CFLAGS="$(CFLAGS) $(PYTHON_CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ $(PYTHON) "$(srcdir)/include_server/setup.py" \ build \ --build-base="$(include_server_builddir)" \ --build-temp="$(include_server_builddir)" \ install \ --prefix="$(prefix)" \ --record="$(include_server_builddir)/install.log.pre" \ --root="$$DESTDIR" \ || exit 1; \ sed -e '/^[^\/]/ s,^,/,' \ -e 's/\r$$//' \ "$(include_server_builddir)/install.log.pre" \ > "$(include_server_builddir)/install.log"; \ if test -n "$(PYTHON_INSTALL_RECORD)"; then \ cp -f "$(include_server_builddir)/install.log" "$(PYTHON_INSTALL_RECORD)"; \ fi; \ $(mkinstalldirs) "$(DESTDIR)$(bindir)" && \ INCLUDE_SERVER=`grep '/include_server.py$$' "$(include_server_builddir)/install.log"` && \ sed "s,^include_server='',include_server='$$INCLUDE_SERVER'," \ pump > "$(include_server_builddir)/pump" && \ $(INSTALL_SCRIPT) "$(include_server_builddir)/pump" "$(DESTDIR)$(bindir)"; \ fi install-man: $(man1_MEN) $(mkinstalldirs) "$(DESTDIR)$(man1dir)" for p in $(man1_MEN); do \ if $(GZIP_BIN) --help >/dev/null 2>&1; then \ mkdir -p "`dirname $$p`"; \ if [ -e "$(DESTDIR)$(man1dir)$$p" ]; then rm -fv "$(DESTDIR)$(man1dir)$$p"; fi; \ $(GZIP_BIN) < "$(srcdir)/$$p" > "$$p.gz"; \ $(INSTALL_DATA) "$$p.gz" "$(DESTDIR)$(man1dir)" || exit 1; \ else \ echo "Warning: no working gzip, installing man pages uncompressed" 1>&2; \ if [ -e "$(DESTDIR)$(man1dir)$$p.gz" ]; then rm -fv "$(DESTDIR)$(man1dir)$$p.gz"; fi; \ $(INSTALL_DATA) "$(srcdir)/$$p" "$(DESTDIR)$(man1dir)" || exit 1; \ fi; \ done install-doc: $(pkgdoc_DOCS) $(mkinstalldirs) "$(DESTDIR)$(docdir)" for p in $(pkgdoc_DOCS); do \ $(INSTALL_DATA) "$(srcdir)/$$p" "$(DESTDIR)$(docdir)" || exit 1; \ done install-example: $(example_DOCS) $(mkinstalldirs) "$(DESTDIR)$(docdir)/example" for p in $(example_DOCS); do \ $(INSTALL_DATA) "$(srcdir)/$$p" "$(DESTDIR)$(docdir)/example" || exit 1; \ done install-gnome-data: $(gnome_data) $(mkinstalldirs) "$(DESTDIR)$(icondir)" $(mkinstalldirs) "$(DESTDIR)$(desktopdir)" $(INSTALL_DATA) $(srcdir)/gnome/distccmon-gnome.png "$(DESTDIR)$(icondir)" $(INSTALL_DATA) $(srcdir)/gnome/distccmon-gnome.desktop "$(DESTDIR)$(desktopdir)" install-conf: $(conf_files) $(default_files) $(mkinstalldirs) "$(DESTDIR)$(sysconfdir)/distcc" $(mkinstalldirs) "$(DESTDIR)$(sysconfdir)/default" @for p in $(conf_files); do \ base=`basename $$p`; \ target="$(DESTDIR)$(sysconfdir)/distcc/$$base"; \ if test -e "$$target"; then \ echo "******************************************"; \ echo "*** Configuration file '$$target'"; \ echo "*** already exists; not installing '$$p'."; \ else \ echo "$(INSTALL_DATA) $(srcdir)/$$p $$target"; \ $(INSTALL_DATA) "$(srcdir)/$$p" "$$target" \ || exit 1; \ fi; \ done @for p in $(default_files); do \ base=`basename $$p`; \ target="$(DESTDIR)$(sysconfdir)/default/$$base"; \ if test -e "$$target"; then \ echo "******************************************"; \ echo "*** Configuration file '$$target'"; \ echo "*** already exists; not installing '$$p'."; \ else \ echo "$(INSTALL_DATA) $(srcdir)/$$p $$target"; \ $(INSTALL_DATA) "$(srcdir)/$$p" "$$target" \ || exit 1; \ fi; \ done # For best results, uninstall-example has to run before uninstall-doc, # so we clean up the doc subdirectory before cleaning up doc itself. uninstall: uninstall-man uninstall-programs @UNINSTALL_GNOME@ \ uninstall-include-server uninstall-example uninstall-doc uninstall-conf uninstall-programs: for p in $(bin_PROGRAMS) pump; do \ file="$(DESTDIR)$(bindir)/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done for p in $(sbin_PROGRAMS); do \ file="$(DESTDIR)$(sbindir)/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -[ "`basename $(bindir)`" = "$(PACKAGE)" ] && rmdir "$(DESTDIR)$(bindir)" -[ "`basename $(sbindir)`" = "$(PACKAGE)" ] && rmdir "$(DESTDIR)$(sbindir)" # There's no setup.py --uninstall. :-( So I depend on # PYTHON_INSTALL_RECORD being set. If it was used at --install time, # I can use it again to uninstall. uninstall-include-server: if [ -e "$(PYTHON_INSTALL_RECORD)" ]; then \ cat "$(PYTHON_INSTALL_RECORD)" | xargs rm -fv; \ cat "$(PYTHON_INSTALL_RECORD)" | sed 's/py$/pyc/' | xargs rm -fv; \ cat "$(PYTHON_INSTALL_RECORD)" | sed 's/py$/pyo/' | xargs rm -fv; \ else \ echo "Cannot uninstall include-server: no PYTHON_INSTALL_RECORD"; \ fi uninstall-man: for p in $(man1_MEN); do \ file="$(DESTDIR)$(man1dir)/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ if [ -e "$$file.gz" ]; then rm -fv "$$file.gz"; fi \ done -[ "`basename $(man1dir)`" = "$(PACKAGE)" ] && rmdir "$(DESTDIR)$(man1dir)" uninstall-doc: for p in $(pkgdoc_DOCS); do \ file="$(DESTDIR)$(docdir)/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -[ "`basename $(docdir)`" = "$(PACKAGE)" ] && rmdir "$(DESTDIR)$(docdir)" uninstall-example: for p in $(example_DOCS); do \ file="$(DESTDIR)$(docdir)/example/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -rmdir "$(DESTDIR)$(docdir)/example" uninstall-gnome-data: for p in $(gnome_data); do \ file="$(DESTDIR)$(pkgdir)/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -[ `basename $(pkgdir)` = $(PACKAGE) ] && rmdir "$(DESTDIR)$(pkgdir)" uninstall-conf: for p in $(conf_files); do \ file="$(DESTDIR)$(sysconfdir)/distcc/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -rmdir "$(DESTDIR)$(sysconfdir)/distcc" for p in $(default_files); do \ file="$(DESTDIR)$(sysconfdir)/default/`basename $$p`";\ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done tags: $(SRC) $(HEADERS) ctags --defines --globals --typedefs-and-c++ --no-warn $(SRC) $(HEADERS) TAGS: $(SRC) $(HEADERS) etags --declarations $(SRC) $(HEADERS) distcc-3.4/NEWS000066400000000000000000002117121404653710500133410ustar00rootroot00000000000000distcc-3.4 "Lax lexer" 2021-4-11 FEATURES * distccmon-gnome ported from gtk2 to gtk3 * Remove debug lag in spawning new threads. (better multi-core performance) * Bug fixes. distcc-3.3 "Charlie the unicorn" 2018-3-3 FEATURES: * Use masquerade as compiler white-list. Bug #155 d849ca2. (Shawn Landden) * New --allow-private (the default) which allows non-global IP and IPv6 addresses. (Shawn Landden) * Cross-compilation support. PR #244. (Shawn Landden) * Fix parsing of IPv6 addresses. PR #175 (Bing Sun) * Python 3, not python 2. * Can build without python (and without pump mode or tests). distcc-3.2 "Back in black" 2011-10-11 FEATURES: * IPv6 support (adshea, Benjamin R. Haskell, Bob Ham). * Optional support for GSS-API authentication (Ian Baker at CERN) * Added an environment variable DISTCC_SKIP_LOCAL_RETRY for skipping the local retry in case of a remote compilation failure (Ryan Burns). * Some constants that were previously hard-coded in the sources are now configurable via environment variables: DISTCC_MAX_DISCREPANCY, DISTCC_IO_TIMEOUT (Lei Zhang). BUG FIXES: * Fixed the following 20 issues : 30: 3.0 on OSX: ValueError: Expected absolute path, but got '(framework'. 33: distcc --scan-includes dumps core 34: Zeroconf fails if avahi supports IPv6 35: Include server internal error: ': ('bogus escape (end of line)',)' 36: distcc-mon-gnome displays multiple rows for same host/slot 39: build with gcc 4.1 snprintf.h error "expected declaration specifiers" 42: distcc --show-hosts fails when using Avahi with IPv6 support and +zeroconf for distcc. 43: Remove duplicate hosts from zeroconf list 44: Failed tests on make check (gentoo gcc-4.3.3) 46: Add TAGS target to Makefile.in 49: make check fails on PreprocessAsm_Case 57: Fix warnings 58: PUMP mode can`t PARSE the HOSTS 60: CPlusPlus test case fails with GCC 4.4.1 61: Gdb tests fail in pumped mode on Ubuntu 9.10 amd64 66: pump mode fails to compile certain KDE-4 packages, finds/looks for incorrect headers 70: variable overlapping causing errors.. 75: include_server documentation, distcc_fallback flag incorrect 81: distcc 3.1 will not compile correctly with current version of gcc distcc-3.1 "Humming along" 2008-11-21 FEATURES: * New "--scan-includes" option to distcc. This shows which headers distcc would send to the remote machine in pump mode, without actually compiling anything. This provides a simple interface to the include server. * New "--disable-Werror" option to configure. This disables the use of gcc's -Werror option when building distcc, allowing compilation of distcc to succeed even if gcc issues warnings. DOCUMENTATION: * Document all of the exit codes in the man page (Carsten Wolff , via Debian). BUG FIXES: * Handle "-Wp,-MMD,...". * Report a better error message if a host specification contains ",cpp" but not ",lzo". * Fix a bug where the "m4" directory wasn't included in the source distribution tarball, which caused it to stop working if you ran autogen.sh. PORTABILITY: * Fixed a bug where the pump script was hard-coding /etc/distcc/hosts rather than using the prefix specified to configure. * Fixed build errors on Gentoo Linux and some other systems (Matsuu Takuto). distcc-3.0 "The moment has arrived" 2008-08-06 DOCUMENTATION: * Minor improvements to the man pages. distcc-3.0rc4 "Pump up the volume" 2008-08-04 BUG FIXES: * Fixed a bug in 3.0rc3 that broke pump mode for C++ compilations that use -I options that refer to a subdirectory of one of the default system include directories, e.g. -I/usr/include/foo. distcc-3.0rc3 "Third time lucky?" 2008-07-31 FEATURES: * New "--without-avahi" option to configure (Lei Zhang). BUG FIXES: * Fixed a problem where pump mode was falling back to local compilation when compiling with -I options that refer to a subdirectory of one of the default system include directories (Nils Klarlund, Fergus Henderson). * Allow distcc to distribute commands that use "-MF" rather than "-MF ", and likewise for "-MT". PORTABILITY: * Fixed a build problem on ARM and Solaris systems. * Fixed a build problem on some Linux systems reported by Daisuke Nishikawa. * Fixed failure of "make install" on Cygwin. distcc-3.0rc2 "Anti-aliasing." 2008-06-19 BUG FIXES: * Fallback to local compilation for "-march=native" or "mtune=native" (Maks Verver). * Fix for deadlock in pump mode. distcc-3.0rc1 "My prices are insane." 2008-06-09 FEATURES: * New protocol, version 3, allowing for preprocessing on distcc servers ("pump" mode). * New component: an include server for incremental static analysis of include dependencies. This software is written in Python 2.4. * Support for getting hosts via avahi (Lennart Poettering) BUG FIXES: * gcc debug option -d must be run locally because it produces secondary files. Reported by Nadim Khemir. * Improved checking for errors on socket connection. Patch from Dan Kegel. PORTABILITY: * "Pump" code tested under Linux only. Processing of object code rewrites debug info (so server paths are replaced with client paths), but this works for ELF code only. * Fix failure of 'make maintainer-check' in non-English locales. (Niklaus Giger) * Locks taken through F_SETLK or lockf() must be explicitly released, because closing the file does not do so. (Sascha Demetrio) * Use python2.4 if available. * Execute compiler with correctly redirected output using win32 apis on Cygwin/Mingw. Place temporary files using GetTempPath. (Alex Besogonov) * Make distccmon-gnome link properly with gnu ld's new --as-needed flag. (Ben Skeggs, Lisa Seelye) OTHER CHANGES: * New web site: . * New repository: . * New maintainer: Fergus Henderson. distcc-2.18.3 "Porsche safari" 2004-11-30 BUG FIXES: * Fix for incorrect handling of -x and -specs from Michal Welnicki. TESTS: * Fix false pass in tests for -x and -specs. distcc-2.18.2 "Bees and lavender" 2004-11-12 BUG FIXES: * Fix problem in checking errno after connect(). Fix by Jean Delvare and Dan Kegel. PORTABILITY: * Fix prototype problem causing build failure on amd64. Patch from Andreas Jochens. (Debian #280399, #280644). distcc-2.18.1 "Reality-based computing" 2004-11-03 BUG FIXES: * Fix run-time warnings about gtk_tree_model_row_changed() when built with recent versions of GTK+. * gcc option -specs= must be run locally so that it can read the local spec file. Reported by Chris Yeoh. PORTABILITY: * Fix Solaris build problem reported by Dimitri Papadopoulos. * Fix problem with reading hosts files in DOS CRLF format. Reported by Sebastien Perochon. distcc-2.18 "Billionaires on stilts" 2004-10-12 BUG FIXES: * Fix longjmp() bug that can cause distcc to crash when a timeout elapses. * Fix compile-time problem with dcc_trace when configured with --enable-rfc2553. Reported by Greg Earle. * Fix warning about warn_unused_result for older versions of gcc. * No timeout on local preprocessing or on compilation. No timeouts on DNS lookups other than whatever is built in to the DNS resolver. There are timeouts on network transmission and on opening connections. * Remove mmap() for receive of uncompressed data, to avoid various problems. CHANGES: * The --allow option is now mandatory for daemon mode. As a security feature, distccd will refuse to run without an IP access control list. * conftest.* built by autoconf is always done locally, to make configure tests faster and safer. DOCUMENTATION: * Better description of use with ccache. PORTABILITY: * Fix various warnings reported by Dimitri Papadopoulos. * Fix Tru64 build problem reported by Gary V. Vaughan. distcc-2.17 "Divers Alarums" 2004-07-31 FEATURES: * Performance improvements for distccmon-gnome. * Added timeous for connection to servers, transmission of jobs and remote compilation. If the timeout expires, the job is run locally. This should make distcc cope better if some or all of the servers are unreachable or failing. * Also add timeouts in server to kick out stalled or disconnected clients. BUG FIXES: * If remote compilation fails because of a signal in a later phase of the compilation causing an exit with code >=128, retry compilation locally. Patch from Jakub Stachowski. DOCUMENTATION: * Manpage fix from Jean Delvare. PORTABILITY: * Cygwin portability fix for WCOREDUMP, reported by Eric Frias. distcc-2.16 "Salt" 2004-07-08 SECURITY: * Fix bug that might cause IP-based access control rules not to be interpreted correctly on 64-bit platforms. (CAN-2004-0601) BUG FIXES: * Fix small memory leaks in distccmon-gnome and distccmon-text. FEATURES: * Use a GNOME status bar with a grab handle for distccmon-gnome. Patch from Nathan Fredrickson. PORTABILITY: * Better detection of systems with a popt library installed but no popt.h. Reported by Sean Kelly. * Fix bug in reporting crashed daemon children that showed up on systems without strsignal, such as Mac OS 10.2. Reported by Benjamin Reed. * Update testdistcc.py to work on ia64 linux. INTERNAL: * Simplify dcc_log_child_exited. * Include copyright and licence in --version output, as suggested by GNU programs. distcc-2.15 "feel good for ten seconds" 2004-07-06 BUG FIXES: * Fix crash bug in receiving LZO compressed data into a mmapped file. Reported by Arkadiusz Miskiewicz. * Remove redundant temporary file cleanup in non-forking mode. FEATURES: * Client calculates and can display the overall throughput in preprocessed bytes per second for remote jobs. REMOVALS: * The deprecated fork-after-exec mode controlled by the --no-prefork option has been removed. * mmap is no longer used for compressed data to simplify the code. PORTABILITY: * Additional fixes to Red Hat / Fedora scripts, by Colins Walters. INTERNAL: * Daemon now chdirs to $TMPDIR at startup rather than /. This allows dumping core, among other things. distcc-2.14 "Lake Albina" 2004-05-02 FEATURES: * The host file is looked up in $DISTCC_DIR/hosts, not hardcoded to ~/.distcc/hosts. The default for $DISTCC_DIR is still ~/.distcc. Suggested by Sebastien Perochon. * Source file name is included in success/failure messages, e.g. distcc[6655] ERROR: compile ./cases/bad.c on cardhu failed * distcc can now be built with a build directory separate from the source directory. Patch from Dennis Henriksen. * Added --randomize option to host list to help spread the load across large shared clusters. From patch by Google (Josh Hyman ). DOCUMENTATION: * Add documentation of DISTCC_DIR, and other fixes. Patch from Thomas Schwinge. * Slightly improved distcc --help. BUG FIXES: * Decompression buffer can dynamically resize to allow for very gassy files. From a patch by Joe Buehler. PORTABILITY: * Add sample scripts for Red Hat / Fedora, by Colin Walters. * mmap is always disabled on HP-UX, because the inconsistent page case is a bit dangerous for the way distcc uses mmap. Suggested by Joe Buehler. distcc-2.13 "Carnal Bunt" 2004-03-02 SECURITY: * Enforce IPv4 access control lists when the daemon is listening on an IPv6 port. This only applies when the server was compiled using --enable-rfc2553 and run with --allow. FEATURES: * Hash comments are allowed in host list files. INTERNAL: * Use TCP_DEFER_ACCEPT on Linux to avoid some wasted context switching when a new connection comes in to the server. BUG FIXES: * Some fixes for connections over SSH when built using --enable-rfc2553. Reported by Jeff Rizzo. * Handle arguments like "-xcpp" and "-Wa,-xarch=v8". Suggested by Ben Scarlet. * Fix resource exhaustion when DISTCC_SAVE_TEMPS is set. Reported by Mark DeGeorge. * Fix problems in running IPv6-enabled builds on kernels without IPv6 support. Reported by Lisa Seelye. DOCUMENTATION: * More instructions for distributors/packagers. PORTABILITY: * Many portability patches from Albert Chin. These patches were tested on: AIX 4.3.2, 5.1; HP-UX 10.20, 11.00, 11i; IRIX 6.5; Redhat Linux 7.1, 9; Solaris 2.5.1, 2.6, 7, 8, 9; Tru64 UNIX 4.0D, 5.1. * Possibly fix mmap problem on HP-UX with compressed transfers. Reported by Joe Buehler. TESTING: * Add test for compilation with compression. * Testsuite portability patch from Albert Chin. The tests pass on: HP-UX 10.20, 11.00, 11i; IRIX 6.5; Redhat Linux7.1, 9; Solaris 7, 8, 9; Tru64 UNIX 4.0d, 5.1. distcc-2.12.1 "Shatner's Bassoon" 2004-01-09 BUG FIXES: * When checking if a process exists, accept EPERM as indicating it exists but isn't ours. This allows watching the directory of a different user, subject only to filesystem permissions. Reported by Ernst Bachmann. * Correct a bug introduced in 2.12 that made distccd fail to start when run by root because setgid failed. Fix from Wayne Davison. * --without-gnome, --without-gtk now turn those options off rather than on. DOCUMENTATION: * New man page for distccmon-text, by Shri Shrikumar and Martin Pool. distcc-2.12 "Figgy Pudding" 2003-12-19 FEATURES: * New --log-level feature allows logging of only errors rather than messages for each connection. * IPv6 support now works better when distcc is configured with --enable-rfc2553. The server can normally accept either IPv4 or IPv6 connections. * New --with-docdir configure option to set install location for documents. The default is the same as previously. Patch from Harold L Hunt II. INTERNAL: * GNU-style ChangeLog is now included in the package. Please keep it up to date if you make your own changes! PORTABILITY: * setgroups() was broken by Mac OS X Panther so that it will not accept setgroups(0, NULL) to clear the group list. Instead we now set the group list to our single primary gid. Suggestion from Wayne Davison. * sendfile problems on FreeBSD 4.9-RC fixed. Patch from Allan Saddi. * MAXPATHLEN is provided if it's not defined, which is the case on GNU Hurd. Reported by Santiago Vila as Debian #219600. BUG FIXES: * Check pkg-config information GNOME/GTK+ is now checked at configure time, not build time. This is a bit quicker than running the script for every file we build, and means that PKG_CONFIG_PATH only needs to be set for configure. DOCUMENTATION: * Small documentation corrections. distcc-2.11.2 "Muscovado" 2003-10-23 BUG FIXES: * Correct the handling of --without-gnome. Reported by Dimitri Papadopoulos. * Fatal signal handlers for client and daemon should reset the signal vector before doing anything else, to protect against an (unlikely) spin if the signal is re-sent. * Corrections to .desktop file from Dag Wieers. INTERNAL: * Remove dependency on libglade for GTK+ and GNOME monitor programs. PORTABILITY: * IRIX portability fixes from Dimitri Papadopoulos. * Use AC_TYPE_SIGNAL to generate correct signal handler return types. (It can be either int or void.) DOCUMENTATION: * Various manual updates. * Update to xinetd example from Dag Wieers. distcc-2.11.1 "Burnt sugar" 2003-10-08 FEATURES: * The graphical monitor can now be configured with either --with-gnome or --with-gtk. In the second case, the GNOME libraries are not used. In both cases the resulting program is called distccmon-gnome and the functional differences are fairly small. BUG FIXES: * An error message is emitted and compilation fails if distcc cannot use the specified TMPDIR. This can happen if distccd is started by root with a TMPDIR only accessible to root. Reported by Brett Dikeman. * GNOME data files are now only installed when the application is configured with --with-gnome or --with-gtk. Files are installed into a distcc/ subdirectory of the configured data directory. (By default this is /usr/local/share/distcc/). Reported by Erik Jan Tromp and Noe`l Ko"the. * Fix bug in sending compressed files where errors were ignored. * C++ compilation using -frepo must be local. Reported by Andrew Slater. PORTABILITY: * Don't use stdint.h, which is not available on FreeBSD 4-STABLE, IRIX or Solaris. Reported by Frerich Raabe. DOCUMENTATION: * Corrections to distcc manpage reported by Lionel Sausin. * Documentation of how to write monitor programs, from Frerich Raabe. INTERNAL: * Fix state.h for use with C++. Patch from Frerich Raabe. distcc-2.11 "Sugar fix" 2003-09-23 INCOMPATIBILITIES: * The GNOME monitor is now configured using --with-gnome (not --enable-gnome) to be more consistent with GNU standards. * The state file format has changed, so old distcc monitor programs will not see new compiler processes and vice versa. FEATURES: * Nice new GNOME monitor, showing strip-charts (or "scarves") of the state of each processor slot over time. * --allow 0.0.0.0/0 is accepted as meaning "allow access from anywhere". Debian #207831, suggested by Matthijs Kooijman. BUG FIXES: * If we fail to determine the number of CPUs on the machine, assume it is 1. This may fix problems on exotic machines where the detection call is almost but not quite right. * In non-forking mode, make sure to close the accepted fd after processing a request. * Use "safe" LZO1 decompression for protection against program or network errors. * Lock and state files are created with the weakest permissions permitted by the umask. This is intended to reduce problems seen when $DISTCC_DIR is shared between two users, such as when compiling as root during program installation. * Client deletes temporary files when interrupted. INTERNAL: * Add debugging option DISTCC_MMAP, which can be set to 0 to disable use of mmap for receiving files. * New --enable-profile configure option to turn on gprof. * Many changes to the representation of the client state to make it easier to draw a history. State is now stored as a natively encoded struct in a disk file, rather than using our network protocol. PERFORMANCE: * Sleep only one second when blocked waiting for a CPU, to try to reduce idle time when recovering from an overloaded period. DOCUMENTATION: * Document problems with "no_subtree_check" on NFS. * The GNU Free Documentation License is no longer distributed, because the documentation is now included under the GNU GPL. * Document bad Makefiles or mismatched compilers as common causes of failure. * Describe where to put "localhost" in the host list. PORTABILITY: * Fixes for BSD/OS (BSDi) from Nick Amato. * Fixes for portability issues in autogen.sh from Lisa Seelye and Alexandre Oliva. distcc-2.10.1 2003-08-12 BUG FIXES: * Fix problem in "make clean" reported by Lisa Seelye. distcc-2.10 "Hunger is the best sauce" 2003-08-11 SECURITY: * Fix issues in temporary file handling that could allow a local attacker to interfere with another user's distcc processes. FEATURES: * Daemon niceness is incremented by +5 by default. (This can be changed by --nice.) * The per-user configuration directory can be set by $DISTCC_DIR. It defaults to the old value of ~/.distcc/. * For regular compile failure, don't say "with exit code 1". BUG FIXES: * The server now emits warnings to the log and to the client if its PATH is set such that it will recursively run a distcc client. This check is done at run time for the requested compiler name. The server's $PATH is not modified in other ways. This may help reduce problems with finding the right remote compiler. PORTABILITY: * SCO/Caldera operating systems are no longer supported due to their recent absurd attacks against Linux and IBM. * TMPDIR is no longer required to start with '/', so that Cygwin paths starting with a drive letter may be used. Reported by Heiko Elger. DOCUMENTATION: * Various man page updates. INTERNAL: * Daemon now sits in the root directory while running, not the temporary directory. * Temporary directory is gone. Working files are created directly under $TMPDIR. * Lock files and state files are stored under DISTCC_DIR, rather than in /tmp. TESTING: * Test cases are more robust in choosing a daemon port number. distcc-2.9 "Grace under pressure" 2003-07-21 FEATURES: * Optional LZO1X compression of network traffic, to make distcc faster on slow or overloaded networks. This is turned on by appending ",lzo" to each host specification. Both client and server must be updated for this to work. Old clients and servers are supported when compression is off, which is the default. Compression is probably only worthwhile on networks slower than 100Mbps, but it will depend on the usual factors of CPU, network and code complexity. Thanks to Markus F.X.J. Oberhumer for the LZO library. BUG FIXES: * Handle invocations like "distcc foo.o -o foo", which can be generated by Mozilla. * Handle invocations like "distcc -Wa,-al=foo.lst -c foo.c", which write an assembler listing to a file and cannot be run remotely. * When trimming the path to avoid recursive invocations, stop as soon as we find one non-symlink compiler. This should help avoid the path getting trimmed down far too much on the server. Patch from Wayne Davison. PERFORMANCE: * The daemon by default allows 2+NCPUS, rather than 3*NCPUS. The two extras are to allow for some processes to be blocked on network IO, but allowing more than two of them is probably not useful on multiprocessor machines. * Larger files are sent and received using memory mappings where possible. * Use of mmap and compression makes distcc substantially faster in at least some cases. DOCUMENTATION: * Convert the documentation to a series of regular Unix manpages for easier reference and so they can be used more easily on diverse platforms. The Linuxdoc-SGML manual has been removed from the distribution. Thanks to Tim Potter for review suggestions. TESTING: * Add tests for new -o and -Wa,-al handling. distcc-2.8 "Play in the traffic" 2003-07-09 FEATURES: * Small enhancements to GNOME monitor appearance. BUG FIXES: * Fix problem with nonblocking IO for SSH connections that causes a busy spin. SSH connections are now far more efficient. Reported by Marcelo Matus. * distccmon-text flushes output after each line, even if stdout is not a terminal. This allows it to more easily be run in polling mode under another program. Suggestion from Hamish Rodda. * distccd now works properly with SSH servers that use pipes rather than socketpairs to run the daemon. Previously it would fail with an error when trying to write to stdin. Suggestion from Felix Lee. * Correctly handle invocations like "gcc -ofoo.o -c foo.c", where the output filename is run on to the -o option. Based on a patch from Tsutomu Yasuda. INTERNAL: * mon.h is now safe for inclusion in C++ programs, and protected against multiple inclusion. Suggestion from Frédérick Forjan. * Increased timeout for nonblocking network IO apart from connections to 5 minutes. PORTABILITY: * Detect and avoid Apple gcc cpp-precomp brokenness. Patch from Matt Watson. * Better handling of builds on machines which do not have the linuxdoc-sgml toolchain. Suggestion from Frerich Raabe. DOCUMENTATION: * Include an example xinetd configuration file from Andrew Morton. distcc-2.7.1 "Expedition" 2003-06-25 PORTABILITY: * distccmon-gnome now depends only on GTK+ 2.0, not on the GNOME libraries. * Fix for compilation of the GNOME monitor on BSD. * Fix for compilation of the monitor on Cygwin. distcc-2.7 "The Hard Way" 2003-06-16 FEATURES: * Graphical compile monitor for GNOME 2.x. Configure with --enable-gnome to build it. PORTABILITY: * Possible fix for compilation on HP-UX. INTERNAL: * Sanity check GNOME libraries during configuration if --enable-gnome was specified. distcc-2.6 "The Watcher in the Water" 2003-06-12 FEATURES: * New program distccmon-text shows the state of any distcc processes run by the current user. It can be run by hand or read by a shell script. Should be popular with vmstat fans. * New environment variable $UNCACHED_ERR_FD allows client errors to be redirected from stderr to another file descriptor, so that distcc errors are not cached by ccache. This is an improvment because (almost?) all distcc messages are transient things such as failure to connect to a remote host, and it is confusing to have them cached. (This needs a corresponding patch to ccache to set this, or for it to be assigned to a duplicate of stderr before invoking cccache.) * In compilation log message, just show the basename of the file to make it more compact. BUG FIXES: * If an compiler cannot be executed then try searching the path for the basename of the compiler. This can fix cases where the compiler is invoked with an absolute name but it is in a different directory on the server. Patch from Paul Russell. PORTABILITY: * Fix build on platforms that don't have hstrerror(), such as Solaris 2.6. * Handle sysconf(_SC_NPROCESSORS_ONLN) returning 0 processors, which has been observed on ARM Linux and previously threw distccd into a spin. Patch from Sean MacLennan. INTERNAL: * New mon.c interface for writing compilation monitors. * State directory name includes hostname for robustness when the temporary directory is shared. * Client writes out notes about its state to files that can be watched by external monitor programs. * Partial GNOME-based monitor interface, built when distcc is configured with --enable-gnome. TESTING * Fix silly typo that made maintainer-check give a false failure in ParseHostSpec_Case. distcc-2.5.1 "disable extra paranoia" 2003-06-05 FEATURES: * Fifteen second timeout on connection attempts. Hosts that are unreachable in this time are blacklisted for another minute. BUG FIXES: * Fix setpgid() failure when started directly from init(8). Reported by George Garvey. * Correct parsing of old-style TCP multiplier specification (e.g. "phathost/10:3600"). Patch from Wayne Davison. PORTABILITY: * Fix socklen_t compilation problem on Darwin. * Fix compilation problems on Solaris 8. Report from Tomas Ögren. * Fix compilation problems on IRIX. (IRIX cannot accept a variable named "sa_len".) Report from Peter Naulls. * Fix compilation on SuSE Linux 7.1 for Alpha. DOCUMENTATION: * Add more details about starting distccd to the user manual. TESTING: * Add test for correct parsing of old-style TCP multiplier specification (e.g. "phathost/10:3600"). distcc-2.5 "give them heaps" 2003-05-27 FEATURES: * The standalone daemon now "preforks" before accepting connections to reduce per-request overhead. Can be disabled by --no-prefork, which restores the standard Unix behaviour. * Restrict the number of jobs accepted onto the server at any time. By default this is determined automatically depending on the number of CPUs on the server, but it can be set using the --jobs, -j option. Replaces never-used --concurrent, -n option. * When the daemon is terminated, the entire process group is shut down, including any compilations in progress. * Load limits on TCP hosts can now be specified in the more consistent form of "HOST:PORT/MUL" rather than "HOST/MUL:PORT". The old form is still supported. * Better error message for "bind failed". * Better "listening on" message at startup. * More meaningful reporting of transmission and compilation times in logs. BUG FIXES: * Fix bug that caused some messages to go to the 'user' syslog facility rather than 'daemon' as presently. * Fix problem with terminating the daemon when running under Valgrind. INTERNAL: * Refactor daemon loop. * Server-side temporary object files are called .o, not .out. Suggestion from rishikesh shetty. * Temporary directory name changed to decimal userid, rather than hexadecimal userid. Easier to recognize. * Daemon changes into state directory at startup. * SSH child is collected and checked when the connection is closed. distcc-2.4.2 "hard and fast" 2003-05-23 BUG FIXES: * Fix compilation directed to /dev/null by handling output files the same way as the GNU BFD library. Reported by Hal Duston. * Better error messages if DISTCC_HOSTS or host files are empty. Patch from Wayne Davison. * Fix string allocation bug in dcc_sockaddr_to_ip that could cause a server crash. distcc-2.4.1 2003-05-22 PORTABILITY: * Add strndup() for non-GNU platforms. Patch from Frerich Raabe. distcc-2.4 "sparky will reign" 2003-05-21 FEATURES: * Preliminary support for distribution of Objective C and Objective C++ compilation. Based on a patch from Dara Hazeghi. * If remote compilation fails, give a visible error. People might want to know, particularly if something is failing on one particular machine. * Error messages report host definitions more consistently, rather than just hostnames. * Better handling of attempts to run more concurrent compilations than there are available slots. distcc now sleeps for a few seconds to avoid thrashing the client machine. * Unavailable servers are now shunned for 60 seconds so as to avoid wasting time connecting to machines that are down, not running distccd, etc. (However hosts that are simply not responding (e.g. firewalled) are not handled perfectly yet.) BUG FIXES: * If an IO error occurs while trying to get a lock, bail out rather than getting stuck. * Don't use the RFC2553 getaddrinfo/getnameinfo API by default, because it seems to be slower on OS X and possibly problematic on other systems. It can be enabled with --enable-rfc2553 if you want to use IPv6, multi-homed servers, or want to test the new API. PORTABILITY: * Preliminary STRATUS VOS portability work from Paul Green. DOCUMENTATION: * More description of execution over SSH. distcc-2.3 "come down like a ton of bricks" 2003-05-16 FEATURES: * Respond more gracefully to protocol derailments. In particular, banner messages sometimes seem to get into the stream when distcc is run from inetd, and they were previously a bit hard to diagnose. This won't fix the configuration problem that causes them, but it should make the problem obvious. * The client now tries all addresses for each server, in the order returned by the resolver. * Client and server now use IPv6 if requested, where this is supported by the system. The server still binds to an IPv4 address by default, but this can be set by the --listen option. Client access control is not supported yet for IPv6. BUG FIXES: * Fix possible bug in loading host list files. * Startup errors are now reported to stderr, unless that is a socket in which case they are sent to syslog. This should be a better tradeoff between making errors obvious and the requirements of inetd mode. DOCUMENTATION: * Add description of --listen to manual, plus other improvements. Patch from Frerich Raabe. * Various clarifications to the manual. * Add documentation of DISTCC_FALLBACK, DISTCC_SSH, execution over SSH, and host list files. PORTABILITY: * Two Mac OS X fixes from Benjamin Reed: Use the BSD method to discover the number of CPUs, and include types.h where it is needed. * Improved portability of snprintf fallback implementation. Now works again on dietlibc/Linux. Some fixes merged from Samba HEAD. distcc-2.2 "nosurname" 2003-05-05 FEATURES: * If $DISTCC_HOSTS is not set, the host list is taken from from ~/.distcc/hosts, if that exists, or otherwise ${sysconfdir}/distcc/hosts. (The location of this last one is set by the configure option --sysconfdir. It defaults to /usr/local/etc.) * Add --listen option to distccd, to control which IP address is used to listen for connections. May be useful for access control on dual-homed machines. Based on a patch by Neil Mansilla. DOCUMENTATION: * Add documentation for --allow and --user, by Frerich Raabe. TESTING: * Add test case for host list file. * Try to prevent server messages getting into syslog during testing. distcc-2.1 "Don't mind if I do!" 2003-05-03 FEATURES: * Support for execution over ssh! Hosts to be contacted over SSH should be specified as '@HOST' or 'USER@HOST'. distccd must be installed on the volunteer host, but it need not be running and there is no need to set up ssh tunnels. Compilations run under the user's account, and connections are securely authenticated and encrypted. SSH is substantially slower than plain TCP connections, but they can still be faster than local compilation. * The search path is examined in both the client and server, and directories containing distcc (and ccache, where appropriate) masquerade hooks are removed. This should help prevent distcc accidentally invoking itself recursively on either client or server. Patch from Wayne Davison. BUG FIXES: * Fix up warning about pid file being removed twice. * Better error handling when corks are not supported on a particular system or socket. * Fix incorrect display of CPU usage statistics in server log and client. * Change behaviour of distccd for log messages encountered during startup, before options are parsed. These are now written to stderr only if that is a tty, and otherwise to syslog. This is intended to prevent log messages from distccd getting mixed into the network protocol when it is run from inetd. * Correctly trap unexpected end of input when copying a file using read/write. * Test harnesses may need snprintf.o linked in as well. Reported by Joe Meslovich as broken on Solaris. TESTING: * Add test that --allow does in fact deny connections as it should. * Add tests for parsing of --allow options. * Add DISTCC_FALLBACK environment variable. If set to 0, means that failure to distribute will be considered an overall failure. By default, a networking error means that compilation will be retried locally. INTERNALS: * Many cleanups of error handling code. * Trace distcc version at startup to help with bug reporting. * Update IO code to handle nonblocking sockets, because we (may?) need to use nonblocking socketpairs to talk to SSH. distcc-2.0.1 "colorful savings on all your favorite medications" 2003-03-28 BUG FIXES: * Fix comfychair.py library missing from distribution. distcc-2.0 "shoot through like a Bondi tram" 2003-03-28 BUG FIXES: * Fix small signal handling race that would occasionally cause distccd not to exit when signalled. Pointed out by Vance Lankhaar. * If DISTCC_LOG is an empty string, treat as undefined. * If the file specified by DISTCC_LOG can't be opened, then show an error and use stderr. Previously, error messages were just lost. FEATURES: * New "masquerade" mode: distcc can be linked into a directory on the search path as 'cc'. By Wayne Davison and Martin Pool. * Detect number of online processors on the server. At the moment it is just logged but in the future it might be used to guide scheduling. Thanks to Dimitri Papadopoulos-Orfanos for describing how to do this on many operating systems. * Log signal name when terminating, on systems with strsignal(). PERFORMANCE: * Internal CPU efficiency fixes in logging and RPC code. PORTABILITY: * Apparently now builds on IRIX. Reports about whether it works would be welcome. * Fix cast in call to sprintf for platforms where ssize_t != int. Found on Alpha Linux in the hp Compaq testdrive. * Clean up some warnings on IRIX. * Fix problem with vsnprintf() declarations on Solaris 8. * Cope when in_addr_t and socklen_t are not defined, as is the case on FreeBSD 3.3. * Fix test suite to allow for 'true' and 'false' being in /usr/bin on BSD. TESTING: * Many internal updates to ComfyChair framework. * Test suite now works with Python 1.5 or later. * Add new undocumented (heh) "--lifetime" option that causes the daemon to expire after a certain period. * Specify limited lifetime when running daemon, so that if it is not cleaned up by the tests it will go away after a little while anyhow. * Use "--allow" to limit connections to localhost when running daemon for testing. * Use randomly chosen TCP port for the server when running tests. This makes repeated or concurrent invocations of the test less likely to conflict. * On machines without Python, just say "test skipped" rather than failing. * Test DISTCC_LOG being set to an unwriteable file. REMOVALS: * The GNU Info form of the manual is no longer included in the source distribution or installed by default. It can be built from SGML if desired, with "make install-linuxdoc-info". distcc-1.2.3 "stubborn tiny lights" 2003-03-02 PORTABILITY: * Don't use ':' in lock filenames, because that's a bit too tough for Windows. This only affects Cygwin clients, not servers. Pointed out by Heiko Elger. * Check existence of ctype.h. Fixes warnings when building popt. Pointed out by Tom Matelich. * Fix "access denied" errors on lock files on HP-UX and Cygwin, so clients on those platforms should work. Reported by Tom Matelich, Heiko Elger and others. distcc-1.2.2 "clustering darkness forever" 2003-02-27 BUG FIXES: * "make distclean" should not remove ./configure. PORTABILITY: * Don't assume POSIX-style reentrant file locks, which can't be supported on Cygwin. * Check for inet_aton in libresolv, which might fix Solaris 2.6. * Remove some gnudity from the Makefile in an attempt to build with non-GNU Make. * Attempted fix for header files on BSD. * Attempted sendfile implementation for HP-UX. TESTING: * Add a simple "make distcheck" target to test that the tarball is built properly. distcc-1.2.1 "you know you're right" 2003-02-25 BUG FIXES: * Better detection of python2.2 during configuration. * Allow installation from CVS on machines that don't have the Linuxdoc tools. * Check for autoconf >= 2.53 when configuring. Remove dependencies on features from later versions of autoconf to allow autogen to run on Red Hat Linux 7.2 systems. TESTING: * Add "make installcheck" target. * "make check" now fails if any of the tests fail to run. * distcc is now built on the build.samba.org build farm. Please contribute machines if you want your platform to be properly supported. PORTABILITY: * Remove libiberty, and use Samba's asprintf() implementation instead. Yay copy and paste. This should fix problems with asprintf and ansidecls.h on Solaris, BSD, and Cygwin. distcc-1.2 "lizard drinking" 2003-02-22 FEATURES: * New scheduler makes a better attempt at keeping remote machines solidly loaded by allowing only one request at a time to be in transit to remote machines, therefore letting the actual compiler start sooner. Gives about a 10% improvement in some circumstances. The new algorithm should also be a better foundation for adding compression or server-side load limiting. * New --allow option for distccd allows IP-based access control in either inetd or standalone daemon modes. * Locking mechanism now distinguishes between daemons on different ports of the same machine for the purposes of load balancing. * Print timing and estimated rate on bulk data transfers. * Open binary files in O_BINARY mode on Cygwin. May fix some corruption problems on this platform. More investigation would be appreciated. Based on a patch by Helind. PORTABILITY: * Use putenv() rather than setenv() to fit into SUSv2 and work on Solaris 8. Pointed out by Dimitri Papadopoulos. * Add some functions from libiberty to aid portability. distcc-1.1 "balls to the wall" 2003-01-28 BUGS: * Flag platforms that have a sendfile() function, but that aren't explicitly supported, because it seems to vary substantially. At the moment only FreeBSD and Linux are known. * Fix configure test for hstrerror(). Patch from Frerich Raabe. * Check for inadvertent recursion, where distcc calls itself as the compiler. Causes an exit with value 111. * Don't log client hostname, only the IP address. It's not really necessary and can slow us down. * If run by root, discard privileges rather than flagging an error. The persona to assume is set by the --user option and defaults to "distcc". The user "nobody" or uid 65534 is used as a fallback if the named user is not found. BENCHMARK: * Allow for running benchmarks repeatedly, printing the mean and standard deviation of run time. * Projects may now be selected by an unambiguous prefix of their name, so you can just say "benchmark hello" rather than "benchmark hello-2.1.1". * Print better explanatory messages while the benchmark is running. TESTING: * Update some tests to work with changed behaviour of gcc 3.2 as well as 2.95. DOCUMENTATION: * Many updates to distcc User Manual. * Comply with GNU Standards by keeping all messages in the NEWS file, not just those for the current release. distcc-1.0 "consider the oyster" 2003-01-16 BUG FIXES: * Fix sendfile() bug on FreeBSD that could cause files to be mistransmitted. Perhaps not manifest on x86? Reported by Kris Kennaway. PACKAGING: * Distribute as .tar.bz2 rather than .tar.gz. (We pay by the byte.) DOCUMENTATION: * The recommended convention for gcc names is -gcc-, and GCC 3.3 will install itself under this name. (Alexandre Oliva, Claes Wallin) BENCHMARK: * New macro-benchmark and test suite for distcc. Invoke it with "make benchmark." It takes a long time to run and causes a lot of source code to be downloaded, but should be self-contained. This is the start of a script that runs distcc to build various open source programs, as an overall test of correctness, and to measure performance of a distcc installation. It relies on the user to install and configure distcc servers and clients, but handles the work of downloading, preparing, and building packages by itself. There are still some rough edges on the script, but it may be of interest. * Add control over which phases of the benchmark are run. * Add ability to run tests repeatedly and report mean and standard deviation. REMOVALS: * Remove Plucker file: nobody seems to be downloading it, and it's easy enough for people to build if they're interested. * Remove PDF and Postscript from documentation in tarball. They are still available from the web site or may be built from source. distcc-0.15 "petrified forest" 2002-12-12 INCOMPATIBILITIES: * Change default port from 4200 to IANA-assigned standard for distcc service "3632". Compatibility with old installations can be retained by explicitly setting --port=4200 on the server, or using "HOST:PORT" on the client. * Fake-root directory for "make install" is now set by DESTDIR, not TARGET_ROOT. (Alexandre Oliva.) BUG FIXES: * Run the preprocessor with output sent to stdout and redirected to a file, rather than by using the -o option. This should fix some compilers that can't handle "-E -o". It may improve gcc behaviour with -MD, but because gcc behaviour has changed over time it may not be a complete fix. For gcc 3.2 it is recommended that -MF be used to explicitly set the dependency output filename. TESTING: * Add test case for transmission of a zero-byte file. * Add badly-behaved compiler drop-in for use in testing. PORTABILITY: * Use the correct autoconf macros to detect whether install(1) is available and working, and if not, fall back to using the included install-sh script. This should fix "make install" on Solaris. (Mike Santy) * Fix waitpid() takes three options. Required for Irix. (Michael Santy) * Fix autoconf detection of resolv.h on Solaris. (Dimitri Papadopoulos) DOCUMENTATION: * Describe information to include in a bug report. * Remove "Results" chapter from manual: there are now many more detailed results on the web site, and this information is better suited to storage there, because it will be updated on a different cycle. End-users don't really need to have it in their reference. * Remove "MOC Compatibility" section from manual because at the moment there is nothing to say. * Add a new section about the complexities of gcc -MD. * Remove "Bugs" section from the manual, and put it into a new TOOD file instead. Keep information about reporting bugs and using the test suite, but put it in a different section. distcc-0.14 "no agonizing hanging weights" 2002-11-13 BUG FIXES: * Take lock on localhost only when compiling locally, not for all compilations. This removes the accidental limit of only 4 overall jobs. (Martin Pool) * Fix Makefile bug that caused HTML documentation to be missing from the distribution tarball. (Frerich Raabe, Martin Pool) * Make PreprocessPlainText_Case run in appropriate subdirectory. (Martin Pool) PORTABILITY: * Test for wait4 and wait3, which are missing on IRIX. (Mike Santy, Martin Pool) DOCUMENTATION: * Include example init.d script. (Jason Thomas) distcc-0.13 "Armistice" 2002-11-11 FEATURES: * New --no-detach option to cause the server not to detach from its parent. It still forks normally when a connection is accepted. This may be useful with daemontools or other frameworks that prefer the daemon not to detach. (Martin Pool) * Log messages on the server of severity "warning" or higher are captured and sent back to the client. (Martin Pool) * If the local preprocessor fails, do not re-run the job locally because it would presumably fail in the same way. (Martin Pool) * By default, the client only sends "warning" or higher messages to stderr, so that nothing extra is logged unless there is possibly a failure in distcc itself. With a DISTCC_LOG file, "notices" and higher are logged. (Martin Pool) * Better messages when a compiler exits or crashes. (Martin Pool) * If the compiler because of a signal, return 128+SIGNAL, per Unix convention. (Martin Pool) * Compilers and preprocessors are now run in their own process groups, and terminated if the daemon is killed. (Martin Pool) * When the daemon parent is terminated, it does not kill all its children. Instead, they're allowed to finish whatever they're working on, and then exit. This allows for more graceful shutdown. (Martin Pool) * More specific exit codes for some error cases. Don't panic. (Martin Pool) * Include popt library and --with-included-popt configure option to aid installation on systems that don't have it. By default it is statically linked in only if the build machine does not have a suitable library and header. (Martin Pool) REMOVALS: * Remove support for feeding the compiler from a fifo. The gain from using fifos does not seem to justify the maintenance burden. (Martin Pool) - This makes the behaviour more consistent, because some platforms (Cygwin) or filesystems (NFS, strangely) can't use fifos. It removes a code path and a slightly complex autodetection. - Using fifos makes some potential scheduling improvements hard: the server can't make good decisions about how many tasks to run, because each one will only use a fraction of the CPU. The client cannot serialize file transmission, which would probably be desirable. - Using fifos makes reliably handling compiler failures slightly harder: the compiler may crash or exit at any time, which will in turn cause the server to hang if it later tries to open or write to the fifo. In previous versions, distcc tried to handle this by catching SIGCHLD when the child terminated, and aborting the operation, but I am not sure that the method is completely reliable. BUG FIXES: * Detached daemon now ignores hangup signal. (Martin Pool) * When the parent is terminated, don't kill its process group. Allow children to finish in their own time. (Martin Pool) * Detect the case where cpp claims to have succeeded, but did not actually produce any output. (Martin Pool) * Do not use atexit() to clean up temporary files, because this can cause havoc if it's ever called from a child process that forked but failed to exec. (Martin Pool) * Handle "gcc -S foo.c -o -", which ought to write assembly to stdout. (Alexandre Oliva) * Fix bug in handling IO errors (e.g. dropped connection) in the server. (Martin Pool) * If we fail to cork a socket, continue anyhow. (Martin Pool) * Make error handling for IO more consistent. (Martin Pool) * Follow Unix convention of returning 128+SIGNAL if the compiler exits with a signal. (Martin Pool) TESTING: * Add tests for parsing slot limit from host specification. (Martin Pool) * Daemon tests collect dead servers faster, so the tests run a bit faster. (Martin Pool) * Nicer handling of ^C while running tests: print "INTERRUPT" and terminate the whole test. (Martin Pool) * Add new tests for scanning command lines with an implied compiler name. (Martin Pool) * When the parent is terminated, don't kill its process group. Allow children to finish in their own time. (Martin Pool) * Detect the case where cpp claims to have succeeded, but did not actually produce any output. (Martin Pool) * Add test case for #error directive. (Martin Pool) * Add test case for preprocessing non-C text, as is done by (for example) xrdb. (Martin Pool) * Add test case for invocations like "distcc -c test1.c test2.c". (Martin Pool) * Add test for handling of a compiler missing from the server. (Martin Pool) * Allow distcc's version to be set to something like "0.13cvs-nofifo". (Martin Pool) * Add test for handling of a compiler missing from the server. (Martin Pool) * Improved ComfyChair testing framework. (Tim Potter, Martin Pool) PORTABILITY: * Includes example init.d script for SuSE 7.x and 8.0. Not installed by default. (Brandon Forehand) DOCUMENTATION: * Document use with Gentoo Linux. (Dean Bailey, Ernesto, Martin Pool) INTERNAL: * Get rid of recursive Make and fix various small Makefile bugs. (Martin Pool) * Add $(TARGET_ROOT) variable for "make install", for use in building binary packages. (Martin Pool, Nick Moffitt) * wait4() on Solaris can't handle a pid of -1, which means "any child" on Linux and BSD. Use pid of 0 instead to collect any children from the same process group. (Kevin Bailey) * Client does not abruptly drop network connection on compiler failure but rather reads the 0-byte object file token. (Martin Pool) * Rework logger library to allow multiple logger callbacks to be active at once. This is used for the server, which can write to its own log files and also send a copy of messages to a buffer to be sent to the client. (Martin Pool) distcc-0.12 "Klein, kosten- und schnörkellos" 2002-10-07 BUG FIXES: * Handle "gcc -S foo.c -o -", which ought to write assembly to stdout. (Alexandre Oliva) PORTABILITY: * wait4() on Solaris can't handle a pid of -1, which means "any child" on Linux and BSD. Use pid of 0 instead to collect any children from the same process group. (Kevin Bailey) TESTING: * Add tests for "-o -". (Martin Pool) distcc-0.11 "Nuclear Bedtime Story" 2002-09-25 FEATURES: * More helpful message explaining that popt is needed if it is missing at build time. (Martin Pool) * Better stripping of options from remote command lines. (Martin Pool) * Handle the new -MM, -MG, -MP, -MF, -MT, -MQ options for gcc 3.x. (Stephan Kulow, Martin Pool) PERFORMANCE: * Whenever a command by either the client or the server, it counts towards the load on that machine. This covers undistributed commands, cpp, and compilation. This should avoid the bias in earlier versions towards overloading the client. (Martin Pool) BUG FIXES: * IO errors should not cause the process to terminate straight away, because they are properly handled and we may have important cleanup to do. (Martin Pool) * Fix error handling in code for executing compilers. (Martin Pool) * Fix leakage of file descriptors when trying to acquire a lock. (Martin Pool) * Do not object to running as group 0, because on BSD this is "wheel" and many non-privileged users are in it. (Frerich Raabe, Martin Pool) * Fix (non-exploitable) buffer overrun bug. (Dave Zarzycki) PORTABILITY: * Fixes to build on Linux libc5. (Richard Zidlicky, Martin Pool) TESTING: * Keep $TMPDIR separate for each test case. (Martin Pool) * testdistcc.py now optionally takes arguments saying which tests to run. (Martin Pool) * Test permissions on output files are correct. (Martin Pool) * Add more test cases for implicit compiler name handling. Extend h_scanargs to exercise this. (Martin Pool) * More tests for argument stripping. (Martin Pool) distcc-0.10 "shiny fast red thing" 2002-09-12 FEATURES: * Allow distcc to be directly used with the same syntax as a compiler: "distcc -c hello.c". At the moment, always calls "cc". (Martin Pool) * If distribution fails, show the name of the server that we were trying to use. (Martin Pool) * Strip -D, -I, -L, -M* options before passing the command line across the network, for clarity (and perhaps a tiny performance improvement.) Also, this allows new clients which support -MD to be used with old servers that can't handle it. (Martin Pool) BUG FIXES: * Correctly handle "gcc -c -S hello.c", which should only assemble, not compile. (Alexandre Oliva) * If the volunteer compiler exits without reading all of its input, return the compiler's own exit code across the network, rather than EXIT_DISTCC_FAILED. (Martin Pool) * Attempt to fix a race where the compiler process could exit without opening its input before we started writing to the FIFO. In that case, the daemon would hang forever waiting for the compiler to arrive. In the new code, SIGCHLD causes a longjmp to break out of trying to feed the compiler. (Martin Pool) * If .o file is 0 bytes or not created on the server, do not create it on the client either. (Martin Pool) * Fix bug that caused compilation to fail if an old compiler output file existed. (Martin Pool) * Try to make sure to uncork client socket before closing if cpp fails, to work around Linux 2.2 bug that causes the socket to jam in FIN_WAIT1. See . (Martin Pool) * Invocations of gcc that use -MD or -MMD can be distributed, although -M cannot be. Both client and server must be updated to make this work. (Martin Pool) * It turns out that .s and .S files in fact cannot be assembled remotely, because they might use the gas '.include' pseudo op, which is resolved by the assembler and would end up reading something from the volunteer's disk. (Richard Zidlicky, Martin Pool) PORTABILITY: * Solaris portability fixes. (Dimitri PAPADOPOULOS-ORFANOS) TESTS: * Test handling of -c and -S. (Martin Pool) * Test handling of a file that causes a preprocessor error. (Martin Pool) * Test compiler that succeeds without reading input. (Martin Pool) * Test many simple compilations, in case there is an infrequent error. (Martin Pool) * Test many concurrent compilations. (Martin Pool) * Test using -D on the compiler command line. (Martin Pool) * Tests for .s and .S files. (Martin Pool) distcc-0.9 "samui desu ne?" 2002-09-03 FEATURES: * Add new environment variable for client and server, DISTCC_TCP_CORK. Defaults to on, intended mostly for performance comparison or debugging. (Martin Pool) PORTABILITY: * Properly support platforms with 32-bit pids, such as Cygwin. (Aaron Lehmann, Martin Pool) * On FreeBSD, the sa_family_t type is defined in (Dennis Taylor) BUG FIXES: * Fix bugs related to leftover fifos in the temporary directory causing occasional server hangs. (Martin Pool) * Stop the compiler from inheriting file descriptors connected to the network. This was causing the client to hang if the server abnormally terminated while the compiler was reading from a fifo. (Martin Pool) * Handle the case of sendfile() transmitting only part of the supplied data, similarly to a short write on a socket. This doesn't often happen, but can occur if a ptrace debugger attaches while sendfile is running. (Martin Pool) * When run with --daemon and not --no-fork, the parent does not detach until the pid file has been created. This removes a slight race window that sometimes confused the test scripts. (Martin Pool) * Message for completion of local cpp now gives the correct hostname. (Martin Pool) * Do not try to collect daemon children if --no-fork was specified. (Martin Pool) * Set SIGPIPE handler back to default before starting compiler tasks. (Martin Pool) * If a network error is detected while feeding input to the compiler, then it is terminated with a SIGHUP. (Martin Pool) * If transmission to the server fails, close the socket sooner rather than later so as not to make the server process wait around unnecessarily. (Martin Pool) * Better handling of the case where the compiler command exits without reading its input. (Martin Pool) * Make sure compilation children are always properly collected, even if transmission failed. (Martin Pool) PERFORMANCE: * Write token/parameters using a single write() call. May be very slightly more efficient in CPU and perhaps packets. (Martin Pool) TESTS: * Display test names while they're running so that long tests are easier to follow. (Martin Pool) * When cleaning up after running the dameon, make sure it's really dead before proceeding, so that tests don't trip over each other. (Martin Pool) * New test of compilation of a largish (~4MB) C file to a ~5MB object file. (Martin Pool) distcc-0.8 "cat and girl" 2002-08-15 FEATURES: * If for any reason a job can't be distributed, it is run locally rather than failing. This includes servers which are not running or unreachable, servers which crash, bad host specifications, etc. (Martin Pool) * --help for distcc explains more about host specifications. (Martin Pool) BUG FIXES: * Correctly handle compilation of C++ code under ccache, by properly recognizing the .ii extension. (Stephen White, Chris Halls) * Boolean environment variables (e.g. DISTCC_SAVE_TEMPS, DISTCC_VERBOSE) are now consistently required to be literally "1" to count as true. (Martin Pool) DOCUMENTATION: * Document that $DISTCC_HOSTS can now specify ports. (Martin Pool) * Document --no-fifo and --log-stderr. (Martin Pool) distcc-0.7 "Pipeline Authority" 2002-08-05 FEATURES: * Can now either use fifos for feeding the compiler or not. This can be controlled by --no-fifo to the server. By default, it tries a fifo and falls back to using regular temporarily files if that fails, as it will on Cygwin or an NFS-mounted /tmp. (Martin Pool) * --log-stderr option, intended mainly for debugging or testing. (Martin Pool) * DISTCC_HOSTS can now specify non-default port numbers using "host:port" syntax. (Martin Pool) DOCUMENTATION: * Built documentation (HTML, PS, PDF, Info) is now shipped in the distributed tarball, so that you can more easily install it on a machine lacking the Linuxdoc SGML tools. You still need them to modify and rebuild the documentation, of course. (Martin Pool) BUG FIXES: * Log pid even if running with --no-fork. Remove pid file on exit. (Martin Pool) PORTABILITY: * Try fcntl locks in addition to lockf and flock; apparently this helps portability to Cygwin. (Martin Pool, Marco Alanen) * Port to Cygwin. (Martin Pool, Marco Alanen) * Partial port to Solaris. (Dimitri PAPADOPOULOS-ORFANOS, Martin Pool) TESTABILITY: * Further internal improvements to test suite. (Martin Pool) * Test suite should now run whether or not there is a daemon listening on localhost, because it uses a non-standard port for testing. (Martin Pool) distcc-0.6 "reptilian agenda" (12 July 2002) FEATURES: * Daemon now refuses to run as root, because this is just too ridiculously insecure. (Martin Pool) * Output shows CPU time taken by distcc and programs that it runs. (Martin Pool) * distcc will now distribute jobs which use -s to compile but not assemble. Previously they were always run locally, but there's no strong reason why they must be. Unfortunately you need to upgrade both the client and server for this to work, because old servers will refuse to run gcc with -s. (Martin Pool) BUG FIXES: * -M option implies that cpp must be run locally, because it will want to write dependency information to a file. (Martin Pool) * Add --daemon and --inetd options, so that you can properly start a remote daemon with a single-line ssh command. (Martin Pool) * Fix bugs related to collecting child processes. (Probably not very user-visible.) (Martin Pool) * Fixed some Makefile-related bugs causing "make install" breakage and similar things. (Martin Pool) * If the system supports sendfile, but the particular filesystem we're on (e.g. tmpfs) doesn't, then fall back to using read/write. (Eivind Magnus Hvidevold, Martin Pool) * Change to argument analyzer to placate Valgrind. Possibly this was a memory corruption bug, but I can't see it. I think Valgrind was just too picky. (Martin Pool) PORTABILITY: * Build on FreeBSD, though you do need GNU make. (Lauri Watts, Martin Pool) DOCUMENTATION: * Better description of how to do cross-compilation. (Martin Pool) TESTING: * Improved Python test suite. (Martin Pool) INTERNAL CHANGES: * Get rid of automake; just use plain autoconf 2.53. (Martin Pool) * If $DISTCC_SAVE_TEMPS is set to "1", then files are not actually deleted -- good for debugging. (Martin Pool) distcc-0.5 "Unacceptable Behaviour" (27 June 2002) FEATURES: * Use more specific return codes when the remote compiler fails: EXIT_COMPILER_CRASHED for a signal, or the return code from the compiler if it exited non-0. FIXES: * Fix bug in h_hosts that caused us to write off the end of the real argv[], rather than a copy. Thanks to Julian Seward. (Martin Pool) PORTABILITY: * Cope on compilers without varargs macros. (Petter Reinholdtsen, Martin Pool) * Build on Solaris. (Petter Reinholdtsen, Martin Pool) * FreeBSD fixes. (Claes Wallin, Frerich Raabe, Michael Nottebrock, Martin Pool) DOCUMENTATION: * Manpages are correctly distributed and installed. (Petter Reinholdtsen) TESTING: * Test suite now runs a server on localhost and tests against it, and shuts it down on completion. (Martin Pool) * More test cases. (Martin Pool) distcc-0.4 "Wisdom Like Silence" (9 June 2002) ENHANCEMENTS: * Assembly and assembly-with-preprocessor files can now be assembled remotely. (Martin Pool) * Client now emits no messages unless there is a warning or error, or $DISTCC_VERBOSE is specified. This improves operation with ccache. (Martin Pool) * Client and server both respect $TMPDIR if set. (Martin Pool) * Standalone server puts itself in the background and detaches from controlling tty. (Martin Pool) * Server has --port option. Currently useless, since there's no corresponding option on the client. (Martin Pool) * Server has --pid-file option. (Martin Pool) * Server now allows multiple concurrent compile tasks, forking per connection. (Martin Pool) BUG FIXES: * gcc invocations with -fprofile-arcs or -ftest-coverage that would emit coverage information to a local file are always run locally. (Martin Pool) * Handle lines like "gcc -c -c hello.c". (Martin Pool) DOCUMENTATION: * Various enhancements to the user manual. (Martin Pool) INTERNAL: * Add a partial test suite based on PyUnit. Python 2 is now required to run the test suite, though not to just build or run distcc. (Martin Pool) distcc-0.3 "The Anticipation of a New Lover's Arrival" (28 May 2002) ENHANCEMENTS: * Support C++ compilation (including with ccache) by correctly detecting prefixes. (Ian Reinhart Geiser, Martin Pool) * Use a FIFO to feed preprocessed source from the daemon into the compiler, so that compilation can be overlapped with network transit. (Martin Pool) BUG FIXES: * Only fiddle with the compiler's stdin/out/err when running on the server, not on the client. This should make cpp from stdin work. (Reported by Ian Reinhart Geiser from KDE) (Martin Pool) * Prevent server crashing on aborted connectiong by using EPIPE rather than SIGPIPE in daemon as well as client. (Martin Pool, Ben Elliston.) PORTABILITY: * Builds on GNU/Linux, FreeBSD, and others if you're lucky. (Martin Pool, Frerich Raabe, Luke Gorrie) INTERNAL: * Convert to using GNU automake and autoconf, so that distcc can better handle portability, distribution and testing. (Martin Pool, Frerich Raabe, Ian Reinhart Geiser) * Start adding some "make check" tests. (Martin Pool) distcc-0.2 (17 May 2002) ENHANCEMENTS: * First public release * Correctly and usefully builds various large programs Local variables: mode: indented-text indented-tabs-mode: nil coding: utf-8 End: distcc-3.4/README000066400000000000000000000050401404653710500135150ustar00rootroot00000000000000 distcc -- a free distributed C/C++ compiler system https://github.com/distcc/distcc by Martin Pool "pump" functionality added by Fergus Henderson, Nils Klarlund, Manos Renieris, and Craig Silverstein (Google Inc.) distcc is a program to distribute compilation of C or C++ code across several machines on a network. distcc should always generate the same results as a local compile, is simple to install and use, and is often two or more times faster than a local compile. Unlike other distributed build systems, distcc does not require all machines to share a filesystem, have synchronized clocks, or to have the same libraries or header files installed. Machines can be running different operating systems, as long as they have compatible binary formats or cross-compilers. By default, distcc sends the complete preprocessed source code across the network for each job, so all it requires of the volunteer machines is that they be running the distccd daemon, and that they have an appropriate compiler installed. The distcc "pump" functionality, added in distcc 3.0, improves on distcc by distributing not only compilation but also preprocessing to distcc servers. This requires that the server and client have the same system headers (the client takes responsibility for transmitting application-specific headers). Given that, distcc in pump mode yields the same results that distcc would in non-pump mode, but faster, since the preprocessor no longer runs locally. For more details on the pump functionality, see README.pump. distcc is not itself a compiler, but rather a front-end to the GNU C/C++ compiler (gcc), or another compiler of your choice. All the regular gcc options and features work as normal. distcc is designed to be used with GNU make's parallel-build feature (-j). Shipping files across the network takes time, but few cycles on the client machine. Any files that can be built remotely are essentially "for free" in terms of client CPU. This is even more true in "pump" mode, where the client does not even have to take time to preprocess the source files. distcc has been successfully used in environments with hundreds of distcc servers, supporting dozens of simultaneous compiles. distcc is now reasonably stable and can successfully compile the Linux kernel, rsync, KDE, GNOME (via GARNOME), Samba and Ethereal. distcc is nearly linearly scalable for small numbers of machines: for a typical case, three machines are 2.6 times faster than one. distcc is distributed under the GNU General Public Licence v2. distcc-3.4/README.md000066400000000000000000000056171404653710500141260ustar00rootroot00000000000000# distcc -- a free distributed C/C++ compiler system [![Build Status](https://travis-ci.org/distcc/distcc.svg?branch=master)](https://travis-ci.org/distcc/distcc) by Martin Pool Current Documents: https://distcc.github.io/ Formally http://distcc.org/ "pump" functionality added by Fergus Henderson, Nils Klarlund, Manos Renieris, and Craig Silverstein (Google Inc.) distcc is a program to distribute compilation of C or C++ code across several machines on a network. distcc should always generate the same results as a local compile, is simple to install and use, and is often two or more times faster than a local compile. Unlike other distributed build systems, distcc does not require all machines to share a filesystem, have synchronized clocks, or to have the same libraries or header files installed. Machines can be running different operating systems, as long as they have compatible binary formats or cross-compilers. By default, distcc sends the complete preprocessed source code across the network for each job, so all it requires of the volunteer machines is that they be running the distccd daemon, and that they have an appropriate compiler installed. The distcc "pump" functionality, added in distcc 3.0, improves on distcc by distributing not only compilation but also preprocessing to distcc servers. This requires that the server and client have the same system headers (the client takes responsibility for transmitting application-specific headers). Given that, distcc in pump mode yields the same results that distcc would in non-pump mode, but faster, since the preprocessor no longer runs locally. For more details on the pump functionality, see README.pump. distcc is not itself a compiler, but rather a front-end to the GNU C/C++ compiler (gcc), or another compiler of your choice. All the regular gcc options and features work as normal. distcc is designed to be used with GNU make's parallel-build feature (-j). Shipping files across the network takes time, but few cycles on the client machine. Any files that can be built remotely are essentially "for free" in terms of client CPU. This is even more true in "pump" mode, where the client does not even have to take time to preprocess the source files. distcc has been successfully used in environments with hundreds of distcc servers, supporting dozens of simultaneous compiles. distcc is now reasonably stable and can successfully compile the Linux kernel, rsync, KDE, GNOME (via GARNOME), Samba and Ethereal. distcc is nearly linearly scalable for small numbers of machines: for a typical case, three machines are 2.6 times faster than one. ## Licence distcc is distributed under the GNU General Public Licence v2. ## Resources * [Continuous Integration System](https://travis-ci.org/distcc/distcc)(Travis CI) * [Mailing list](https://lists.samba.org/mailman/listinfo/distcc) * [Stack Overflow questions](http://stackoverflow.com/questions/tagged/distcc) distcc-3.4/README.packaging000066400000000000000000000066421404653710500154510ustar00rootroot00000000000000$Id: README.packaging,v 1.7 2004/02/20 04:11:26 mbp Exp $ -*- indented-text -*- Please read this file if you distribute packages of distcc and consider these requests. - If you make available packages or ports for some system, please send mail to the list so that I can include a link on the web site. - If you make change to program, please append to the version number so that it can be distinguished from the upstream version, e.g. in bug reports, and document your changes. (For example, change it to "0.13-foo11" if you modify it for the Fooix distribution.) I request this because I have had distributors introduce broken patches into distcc, and if somebody asks for support I want to know they're not using the same source. I have seen this happen on samba and rsync as well and it wastes everybody's time when the two parties see different programs as "foo-1.2.3". In the steady state there ought to be little need for distributors to patch anything; any reasonably portability fixes will be merged and if they add new features it deserves a different version. - Please install distccd into a directory that is on the default $PATH. (If sbin is not on the path for all users, please don't put it there.) This is important to making ssh work without hassle, and is compliant with the Linux filesystem hierarchy standard (FHS). - distcc uses the standard GNU configure options to set installation directories. In particular, you may want to change --prefix=/usr, and --sysconfdir=/etc. In addition you can use $(DESTDIR) when doing "make install" to install into a virtual root directory. - Because the daemon does not authenticate connections, please check that the administrator understands the consequences before starting it. Do not start it automatically when the package is installed. - If your installation script prompts for parameters, consider asking for a list of allowed netmasks to pass to the daemon's --allow option. - When installing the daemon, please create a system user called "distcc" for the use of the daemon. This is better than running the daemon as "nobody". You can either remove the user or leave it around if the package is uninstalled, depending on your distribution's policy. - I'd prefer for distributions to arrange for distccd to run as a standalone daemon (--daemon), not from inetd. It is a bit easier to support, and in the future there may be optimizations that only work in standalone mode. - If any patches are necessary for portability please forward them to me so that they can be considered for inclusion upstream. - Check that distcc uses shared libraries for popt and other things, if that makes sense on your system. In particular, make sure libraries in /usr/local are linked properly. - Try to make sure gcc is installed with fully-qualified names to aid users of distcc. (e.g. 'gcc-3.2', 'i386-linux-gcc-3.2' and 'i386-redhat-linux-cc-3.2.2'). This makes it much more likely that people will be able to plug-and-go for cross-architecture or cross-OS builds. It's good to name even native compilers this way so that they can participate in heterogeneous builds. If you don't maintain the compiler packages for your OS, please talk to the person who does. - Consider putting this line into /etc/services distcc 3632/tcp # distributed compiler Thankyou for your help. distcc-3.4/README.pump000066400000000000000000000052131404653710500144770ustar00rootroot00000000000000See README for basic information on distcc. Distcc's "pump" mode improves on plain distcc by distributing not only compilation but also preprocessing to distcc servers. The pump mode uses an "include server" process that runs during the build. The include server parses and analyzes source (including header) files. It runs on the workstation that initiates the build. The include server analyzes each header file only a few times during a build, sometimes just once. In contrast, during ordinary distcc operation, the preprocessor examines each header file multiple times, even hundreds of times for a large build. In pump mode, a static analysis algorithm inspects each #include directive and computes a superset of the possible values of its argument. The resulting dependency graph among header files persists during the lifetime of the include server, which then acts as a cache for include analysis. The include server compresses source files into a temporary directory as they are encountered. In this way, a given source file is compressed only once during the build. It may happen that a header file is included via an absolutely specified include directory such as -I/absolute/path. But on the compilation server the path -I/absolute/path does not exist; instead the server places foo.h under /server_temporary_path/absolute/path for some /server_temporary_path root directory. This directory has no meaning on the workstation. Before compressing foo.h, the include server therefore inserts a #line directive in foo.h, to inform the preprocessor that the real location is /absolute/path. The distcc client asks the include server for the list of compressed files that constitute the transitive closure of the source file to be compiled. It then spools these files to a distcc server. The distcc server unpacks these files in the /server_temporary_path directory before preprocessing and compiling. The server also rewrites include options, such as -I's, to reflect the new locations of the files on the server. The .d and the .o files are both rewritten as necessary to refer to client-side filenames and returned to the pump-mode client. Pump mode is able to distribute compilations up to 10X faster than plain distcc. But because building also involves linking and perhaps generation of source files, the overall speed-up of the build time is variable. The pump mode was developed to be used with large clusters of distcc servers, providing hundreds of CPUs. With versions of gcc >= 4.1.1, pump mode will probably not show major performance gains using clusters of less than ten CPUs. The preprocessor running on the workstation is fast enough to keep that many machines busy. distcc-3.4/TODO000066400000000000000000001115751404653710500133400ustar00rootroot00000000000000TODO list for distcc --> See also TODO and FIXME comments in source files and doc/todo/ should rewrite non-ELF, non-DWARF2 object files The existing include-server code will rewrite ELF files to refer to source-file names (in the DWARF2 sections) as they would appear on the client machine, rather than as they appear when rewritten on the server machine. We should enhance that functionality to work with other object formats, such as Mach-O (used by OS X). should probably actually check the number of CPUs for use on localhost failing to resolve a host should be a soft failure State files depend on host byte order and break when DISTCC_DIR is shared between heterogeneous machines. Of course sharing this directory is probably a bad idea anyhow. error messages get badly interleaved Large writes are not always atomic. When running parallel compiles that produce many warnings/errors, the errors can get mixed up, both between lines and within lines. Someone suggested writing out through stdio, but I don't see why that would particularly help. This needs to be done even when writing to a file. It might be more useful to voluntarily write output one line at a time so as to increase the chance that each line is written atomically. hardcode "gcc" not "cc"? I don't think distcc works with anything else. So why take the risk of calling anything else? monitor/state/lock files be on NFS What happens if the processes are missing? Should we perhaps specially handle files created by a remote machine, e.g. but the hostname in? Handle ESTALE or short EOF. http://groups.google.com/groups?selm=netappCJyvKo.MrI%40netcom.com if connection fails, reschedule remotely? See messages from Heiko Perhaps if compilation on one remote machine fails, try another, rather than falling back to localhost? However, we do need to make sure that if all remote possibilities are eliminated, then we still run locally. Perhaps we should more carefully distinguish e.g. "failed to connect", "server dropped connection", etc etc. Backing off from downed machines makes this a little less unnecessary. auto-check socklen_t mess Dmitri says: > By the way, about the accept() argument type (int, size_t, or socklen_t) > issue I had already reported in a previous post, an autoconf macro is > available after all. See: > http://www.gnu.org/software/ac-archive/htmldoc/ac_prototype_accept.html > http://www.gnu.org/software/ac-archive/htmldoc/ac_func_accept_argtypes.html > It would be better to fix this specific issue, as I think it could break > 64-bit builds where the type of the argument is actually important. Perhaps it should be int if not defined. See accept(2). some kind of memory leak in gnome monitor? "compiler not found" Perhaps distinguish this as a separate error case. We need to trap the error from exec on the server, pass that back across the network, and then handle it specially on the client. Back off from the machine where it failed and retry locally? This would be more useful when we explicitly set compiler versions. scheduler should allow for clock/bus speed (Perhaps front-side bus speed is dominant, since compiling won't fit in cache?) Suppose we have one 2GHz and one 1GHz machine. Jobs will take roughly twice as long to run on the second one; conversely we can run two jobs on the first one in the time it takes to run one on the second machine. gkrellm monitor for distcc Ought to work with client-server mode Possibly easier than writing everything ourselves Show number of running jobs? don't change the path Rather than getting into this mess of changing the $PATH, perhaps we should just check more carefully at the moment that we execute things? One problem with this might be interaction with ccache. If we have doubly masqueraded distcc:ccache:gcc, then ccache probably needs to see itself as the first item on the path to be able to find the right gcc. Perhaps we should remove items from the path, rather than trimming the path? It would be good to unify the code in dcc_support_masquerade() with dcc_trim_path(). Perhaps distccd should do path munging when it gets a request rather than at startup. It's ugly that the daemon's idea of the correct path may be wrong if files are changed after the daemon is started. DEPENDENCIES_OUTPUT The problem is when the preprocessor and compiler are both run with this variable set. The compiler appends directions for compiling from the temporary .i to the temporary .o, which is unwanted. This is a problem for ccache (now fixed), but not a problem for distcc because we always run the preprocessor and always locally. The remote compiler doesn't see the variable. multiple cleanup calls at end why is this happening? monitor There's two things that could be monitored. First is the daemon running on `this' computer and the client that is sending processes across the network. lisa writes: Some things I'd like to see for the daemon: 1) Uptime 2) Configuration (port, lzo compression? ssh enabled? etc) 3) Number of jobs done (and a spread of the types of errors reported) 4) Average throughput 5) Current compiling tasks (pid, Src, filesize, filename, time recv'd) For the client (ie, distccmon-gnome replacement): On a per job basis For SEND and RECEIVE state: 1) Current throughput 2) Type of connection (ssh? port? lzo?) 3) pid 4) filename For (remote) COMPILE state: 1) The actual pre-processed filename 2) Type of connection (ssh? port? lzo?) 3) pid For (local) LINKING state: 1) The actual pre-processed filename 2) pid 3) Where the object code was compiled 4) The post-linked filenamed (gcc ... -o [display this]) For (local) PREPROCESS state: 1) filename 2) pid A tall order to be sure, and it'd suck to do the GUI... but you asked. :) unlink .i file as soon as it has been opened for sending Might help with vm performance by hinting to the kernel that it will be discarded. Possibly reduces the chances of temporary files being left behind. However, will not work on Windows. variable to add extra remote cflags, to handle icpc handle -xc++, etc Can be either one or two arguments. handle -Wp,-MF Some makefiles seem to generate this. Aarg! Installation as an SSH subsystem Might make use easier on Windows. I don't see any real advantage on Unix. I think the daemon should already be OK for this. It just requires a slight change in the way we call ssh from the client. In fact, if you just wrote a small script that rearranged the arguments and put that in DISTCC_SSH then everything would probably be fine already. control through command line Handle options like --distcc-verbose --distcc-hosts= to allow options to be set on the command line. I'm not sure this is a good idea or useful. If we have produced a .i file and need to fall back to running locally then use that rather than the original source. On the other hand, falling back to running the original command is possibly more robust. * @todo Make absolutely sure that if we fail, the .o file is removed. * Perhaps it would be better to receive to a temporary file and then * rename into place? On the other hand, gcc seems to just write * directly, and if we fail or crash then Make ought to know not to * use it. * * @todo Count the preprocessor, and any compilations run locally, against the * load of localhost. In doing this, make sure that we cannot deadlock * against a load limit, by having a case where we need to hold one lock and * take another to make progress. I don't think there should be any such case * -- we can release the cpp lock before starting the main compiler. * allow more control over verbosity For example, for the client, it would be nice to get just 'info' level messages about things that can or can't be distributed. split gcc-specific argument parsing into a separate module boredom When there are too many jobs submitted by make, then we have to wait until any slot is available. Unfortunately there is no OS-level locking system I can think of that allows us to block waiting for any one of a number of resources. If there are no slots to run, then at the moment we just sleep for 2s. This is OK, but can leave the processor idle. It would be better to be woken up by other processes as they exit. One way to do this would be to listen on a named pipe for notifications. This must be backed up by a sleep timer because we may not get the notification if e.g. the other process is killed. Also it won't work on Cygwin, which doesn't have named pipes. Simply doing a select() on a pipe allows us to block for a while or until signalled. Simply doing a nonblocking write of one byte to the pipe ought to allow waking up exactly one of the sleepers. Using an OS level semaphore to guard access to slots might work with some fudging, but there is no good portable implementation of them so it is moot. When woken, the clients can do one full round of trying to get a slot and then go back to sleep. This "guides" the OS scheduler towards keeping (almost) the exact number of clients activated, without too many of them spinning. We can't make the timeout too high, or the client will idle for a long time waiting for it. But if we make it too low then we have the thundering herd problem that currently exists... Perhaps this is overengineering: people shouldn't make the -j number so high that this is hit very often, and we need to have the timeout anyhow, so why not just rely on it. Just listening on a pipe is cheaper than checking all the locks. intel CC Does not understand the .ii extension. We need to specify -xc++ to make it properly compile C++ from preprocessed source. Is it OK to just get the user to add this? Perhaps we could add it always? Do we need a DISTCC_ADD_OPTIONS variable? clean up temp files when a client is signalled Interrupting a compilation is pretty common. It might be good to handle this more cleanly. We can also remove status files. This would reduce the need for monitor clients to handle dead state files, which might reduce problems to do with viewing compilations by another user. globally visible status files Perhaps store in a world-writable /var/lib/distcc, so that they're visible even when TMPDIR or HOME has been reset, as when building with emerge. Another good case to support is compilation from inside a chroot jail. It might also be nice to be able to see other people using your machine either as a client or as a server. This requires passing a trust boundary when publishing information across accounts. The directory needs to be writable and the programs need to be robust against other users trying to cause mischief. It's perhaps not great to allow that kind of security issue in a default installation. Should we really create a mode 777 directory by default? umask will put some restrictions on what can be seen. Alternatively, have an environment variable that sets the state location. If people want it globally visible they can set it to a global location. dnotify in monitor This has been implemented, but I pulled it out because I'm not convinced it is a good idea. Signals into GTK seem to cause some trouble when running from valgrind etc. Polling is not too expensive, and is nice and simple. It also allows easier ways to handle corner cases like cleaning up state files left over after a compiler is terminated. Could set up dnotify on the state directory so that we don't have to keep polling it. This would slightly reduce our CPU usage when idle, and might allow for faster updates when busy. We still have to scan the whole directory though, so we don't want to do it too often. I'm not sure how to nicely integrate this into GNOME though. dnotify sends us a signal, which doesn't seem to fit in well with the GNOME system. Perhaps the dummy pipe trick? Or perhaps we can jump out of the signal? We can't call GTK code from inside. state changes are "committed" by renaming the file, so we'd want to listen for DN_RENAME I think. We need to make sure not to get into a loop by reacting to our own delete events. Masquerade It might be nice to automatically create the directory and symlinks. However we don't know what compiler names they'll want to hook... Probably the best that we can do is provide clear instructions for users or package distributors to set this up. Packaging What about an apt repository? Statistics Accumulate statistics on how many jobs are built on various machines. Want to be able to do something like "watch ccache -s". Perhaps just dump files into a status directory where they can be examined? Ignore (or delete) files over ~60s old. This avoids problems with files hanging around from interrupted compilations. refactor name handling Common function that looks at file extensions and returns information about them - what is the preprocessed form of this extension? - does this need preprocessing? - is this a source file? check that EINTR is handled in all cases check that all lengths are unsigned 32-bit I think this is done, but it's worth checking a bit more. in plain (non-pump) mode, abort when cpp fails The same SIGCHLD handling approach used to feed the compiler from a fifo might be used to abort early if the preprocessor fails. This will happen reasonably often, whenever there is a problem with an include, ifdef, comment, etc. It might save waiting for a long connection to complete. One complication is that we know the compiler ought to consume all its input but we don't know when cpp ought to finish. So the sigchld handler will have to check if it failed or not. If it failed, then abort compilation. If it did not fail, then keep going with the connection or whatever. This is probably not worthwhile at the moment because connections generally seem faster than waiting for cpp. feed compiler from fifo Probably quite desirable, because it allows the compiler to start work sooner. This was originally removed because of some hitches to do with process termination. I think it can be put back in reliably, but only if this is fixed. Perhaps we need to write to the compiler in nonblocking mode? Perhaps it would be better to talk to both the compiler and network in nonblocking mode? It is pretty desirable to pull information from the network as soon as possible, so that the TCP windows and buffers can open right up. Check CVS to remember what originally went wrong here. Events that we need to consider: Client forks Compiler opens pipe Client exits Server opens pipe There are a few possibilities here: Client opens fifo, reads all input, and exits. The normal success case. Client never reads from fifo and just exits. Would happen if the compiler command line was wrong. Client reads from fifo but not the whole thing, and then exits. Opening the fifo is a synchronization point: in blocking mode neither the compiler or server can proceed past here until the other one opens it. If the compiler exits, then the server ought to be broken out of it by a SIGCHLD. But there is a race condition here: the SIGCHLD might happen just before the open() call. We need to either jump out of the signal handler and abort the compilation, or use a non-blocking open and a dummy pipe to break the select(). If we jump out with longjmp then this makes the code a bit convoluted. Alternatively the signal handler could just do a nonblocking open on the pipe, which would allow the open to complete, if it had not already. This was last supported in 0.12. That version doesn't handle the compiler exiting without opening the pipe though. streaming input output We could start sending the preprocessed source out before it is complete. This would require a protocol that allows us to send little chunks from various streams, followed by an EOF. This can certainly be done -- fsh and ssh do it. However, particularly if we want to allow for streaming more than one thing at a time, then getting all the timing conditions right to avoid deadlock caused by bubbles of data in TCP pipes. rsync has had trouble with this. It's even more hairy when running over ssh. So on the whole I am very skeptical about doing this. Even when refactored into a general 'distexec', this is more about batch than interactive processing. assemble on client May be useful if there is a cross compiler but no cross assembler, as is supposed to be the case for PPC AIX. See thread by Stuart D Gathman. Would also allow piping output back to client, if the protocol was changed to support that. web site http://user-mode-linux.sourceforge.net/thanks.html sendfile perhaps try sendfile to receive as well, if this works on any platforms. static linking cachegrind shows that a large fraction of client runtime is spent in the dynamic linker, which is kind of a waste. In principle using dietlibc might reduce the fixed overhead of the client. However, the nsswitch functions are always dynamically linked: even if we try to produce a static client it will include dlopen and eventually indirectly get libc, so it's probably not practical. testing How to use Debian's make-kpkg with distcc? Does it work with the masquerade feature? http://moin.conectiva.com.br/files/AptRpm/attachments/apt-0.5.5cnc4.1.tar.bz2 coverage Try running with gcov. May require all tests to be run from the same directory (no chdir) so that the .da files can accumulate properly. slow networks Use Linux Traffic Control to simulate compilation across a slow network. scheduling onto localhost Where does local execution fit into the picture? Perhaps we could talk to a daemon on localhost to coordinate with other processes, though that's a bit yucky. However the client should use the same information and shared state as the daemon when deciding whether it can take on another job. At the moment we just use a fixed number of slots, by default 4, and this seems to work adequately. make "localhost" less magic Recognizing this magic string and treating it differently from 127.0.0.1 or the canonical name of the host is perhaps a bit strange. People do seem to get it wrong. I can't think of a better simple solution though. blacklist/lock by IP, not by name Means we need reliable addr-to-string for IPv4 and IPv6. Any downside to this? Would fix Zygo's open Debian bug. DNS multi-A-records build.foo.com expands to a list of all IP addresses for building. Need to choose an appropriate target that has the right compilers. Probably not a good idea. If we go to using DNS roundrobin records, or if people have the same HOSTS set on different machines, then we can't rely on the ordering of hosts. Perhaps we should always shuffle them? ssh is an interesting case because we probably want to open the connection using the hostname, so that the ssh config's "Host" sections can have the proper effect. Sometimes people use multi A records for machines with several routeable interfaces. In that case it would be bad to assume the machine can run multiple jobs, and it is better to let the resolver work out which address to use. DNS SRV records Can only be updated by zone administrator -- unless you have dynamic DNS, which is quite possible. better scheduler What's the best way to schedule jobs? Multiprocessor machines present a considerable complication, because we ought to schedule to them even if they're already busy. We don't know how many more jobs will arrive in the future. This might be the first of many, or it might be the last, or all jobs might be sequenced in this stage of compilation. Generic OS scheduling theory suggests (??) that we should schedule a job in the place where it is likely to complete fastest. In other words, we should put it on the fastest CPU that's not currently busy. We can't control the overall amount of concurrency -- that's down to Make. I think all we really want is to keep roughly the same number of jobs running on each machine. I would rather not require all clients to know the capabilities of the machines they might like to use, but it's probably acceptable. We could also take the current load of the CPUs into account, but I'm not sure if we could get the information back fast enough for it to make a difference. Note that loadavg on Linux includes processes stuck in D state, which are not necessarily using any CPU. We want to approximate all tasks on the network being in a single queue, from which the servers invite tasks as cycles become available. However, we also want to preserve the classic-TCP model of clients opening connections to servers, because this makes the security model straightforward, works over plain TCP, and also can work over SSH. http://www.cs.panam.edu/~meng/Course/CS6354/Notes/meng/master/node4.html Research this more. We "commit" to using a particular server at the last possible moment: when we start sending a job to it. This is almost certainly preferable to queueing up on a particular server when we don't know that it will be the next one free. One analogy for this is patients waiting in a medical center to see one of several doctors. They all wait in a common waiting room (the queue) until a doctor (server) is free. Normally the doctors would come into the waiting room to say "who's next?", but the constraint of running over TCP means that in our case the doctors cannot initiate the transaction. One approach would be to have a central controller (ie receptionist), who knows which clients are waiting and which servers are free, but I don't really think the complexity is justified at this stage. Imagine if the clients sat so that they could see which doctor had their door open and was ready to accept a new patient. The first client who sees that then gets up to go through that door. There is a possibility of a race when two patients head for the door at the same time, but we just need to make sure that only one of them wins, and that the other returns to her seat and keeps looking rather than getting stuck. Ideally this will be built on top of some mechanism that does not rely on polling. I had wondered whether it would work to use refused TCP connections to indicate that a server's door is closed, but I think that is no good. It seems that at least on Linux, and probably on other platforms, you cannot set the TCP SYN backlog down to zero for a socket. The kernel will still accept new connections on behalf of the process if it is listening, even if it's asked for no backlog and if it's not accepting them yet. netstat shows these processes just in It looks like the only way to reliably have the server turn away connections is to either close its listening socket when it's too busy, or drop connections. This would work OK, but it forces the client into retrying, which is inefficient and ugly. Suppose clients connect and then wait for a prompt from the server before they begin to send. For multiple servers the client would keep opening connections to new machines until it got an invitation to send a job. This requires a change to the protocol but it can be made backward compatible if necessary, though perhaps that's not necessary. This would have the advantage of working over either TCP or SSH. The main problem is that the client will potentially need to open connections to many machines before it can proceed. We almost certainly need to do this with nonblocking IO, but that should be reasonably portable. Local compilation needs to be handled by lockfiles or some similar mechanism. So in pseudocode this will be something like looking_fds = [] while not accepted: select() on looking_fds: if any have failed, remove them if any have sent an invitation: close all others use the accepted connection open a new connection I'm not sure if connections should be opened in random order or the order they're listed. Clients are almost certainly not going to be accepted in the order in which they arrive. If the client sends its job early then it doesn't hurt anybody else. I suppose it could open a lot of connections but that sort of fairness issue is not really something that distcc needs to handle. (Just block the user if they misbehave.) We can't use select() to check for the ability to run a process locally. Perhaps the select() needs to timeout and we can then, say, check the load average. problems with new protocol Does anyone actually want this? I really need an example of somewhere where it would be useful. The server may need to know the right extension for the temporary file to make the compiler behave in the right way. In fact, knowing the acceptable temporary filenames is part of the application definition. Compression Can compression automatically be turned on, rather than requiring user configuration? I can't tell at the moment when would be the right time to do that. Is it cheap enough to always have it on? We not only pay the cost of compression, but we also need to give up on using sendfile() and therefore pay for more kernel-userspace transitions and some data copying. Therefore probably not, at least for GigE. User Manual The UML manual is very good - Add some documentation of the benchmark system. Does this belong in the manual, or in a separate manual? - FAQ: Can't you check the gcc version? No, because gcc programs which report the same versions number can have different behaviours, perhaps due to vendor/distributor patches. Just cpp and linker? Is it easy to describe how to install only the bits of gcc needed for distcc clients? Basically the driver, header, linker, and specs. Would this save much space? Certainly installing gcc is much easier than installing a full cross development environment, because you don't need headers or libraries. So if you have a target machine that is a bit slower but not terrible (or you don't have many of them) it might be convenient to do most of your builds on the target, but rely on helpers with cross-compilers to help out. -g support I'm told that gcc may fix this properly in a future release. There would then be no need to kludge around it in distcc. [Yes, this is now fixed in gcc 4.0 and later.] Perhaps detect the -g option, and then absolutify filenames passed to the compiler. This will cause absolute filenames to appear in error messages, but I don't see any easy way to have both correct stabs info and also correct error messages. Is anything else wrong with this approach? kill compiler If the client is killed, it will close the connection. The server ought to kill the compiler so as to prevent runaway processes on the server. This probably involves selecting() for read on the connection. The compilation will complete relatively soon anyhow, so it's not worth doing this unless there is a simple implementation. tcp fiddling I wonder if increasing the maximum window size (sys.net.core.wmem_default, etc) will help anything? It's probably dominated by scheduling inefficiency at the moment. The client does seem to spend time in wait_for_tcp_memory, which might be benefitted by increasing the available memory. benchmark Try aspell and xmms, which may have strange Makefiles. glibc gtk/glib glibc++ qt gcc gdb linux openoffice mozilla rsync-like distributed caching Look in the remote machine's cache as well. Perhaps use a SQUID-like broadcast of the file digest and other critical details to find out if any machine in the workgroup has the file cached. Perhaps this could be built on top of a more general file-caching mechanism that maps from hash to body. At the moment this sounds like premature optimization. Send source as an rdiff against the previous version. Needs to be able to fall back to just sending plain text of course. Perhaps use different compression for source and binary. librsync is probably not stable enough to do this very well. --ping option [Done - see "lsdistcc"] It would be nice to have a --ping client option to contact all the remote servers, and perhaps return some kind of interesting information. Output should be machine-parseable e.g. to use in removing unreachable machines from the host list. Perhaps send little fixed signatures, based on --version. Would this ever be useful? non-CC-specific Protocol Perhaps rather than getting the server to reinterpret the command line, we should mark the input and output parameters on the client. So what's sent across the network might be distcc -c @@INPUT@@ -o @@OUTPUT@@ It's probably better to add additional protocol sections to say which words should be the input and output files than to use magic values. The attraction is that this would allow a particularly knotty part of code to be included only in the client and run only once. If any bugs are fixed in this, then only the client will need to be upgraded. This might remove most of the gcc-specific knowledge from the server. Different clients might be used to support various very different distributable jobs. We ought to allow for running commands that don't take an input or output file, in case we want to run "gcc --version". The drawback is that probably new servers need to be installed to handle the new protocol version. I don't know if there's really a compelling reason to do this. If the argument parser depends on things that can only be seen on the client, such as checking whether files exist, then this may be needed. The server needs to use an appropriately-named temporary file. gcc wierdnesses: distcc needs to handle $COMPILER_PATH and $GCC_EXEC_PREFIX in some sensible way, if there is one. Not urgent because I have never heard of them being used. networking timeouts: Also we want a timeout for name resolution. The GNU resolver has a specific feature to do this. On other systems we probably need to use alarm(), but that might be more trouble than it is worth. Jonas Jensen says: Timing out the connect call could be done easier than this, just by interrupting it with a SIGALRM, but that's not enough to abort gethostbyname. This method of longjmp'ing from a signal handler is what they use in curl, so it should be ok. configurable timeout? Maybe make the various timeouts configurable? Isn't it possible to choose values that suit everyone? Maybe the initial connection timeout should be shorter? waitstatus Make sure that native waitstatus formats are the same as the Unix/Linux/BSD formats used on the wire. (See , which says they may only be interpreted by macros.) I don't know of any system where they're different. override compiler name distcc could support cross-compilation by a per-volunteer option to override the compiler name. On the local host, it might invoke gcc directly, but on some volunteers it might be necessary to specify a more detailed description of the compiler to get the appropriate cross tool. This might be insufficient for Makefiles that need to call several different compilers, perhaps gcc and g++ or different versions of gcc. Perhaps they can make do with changing the DISTCC host settings at appropriate times. I'm not convinced this complexity is justified. Rusty is doing this in ccontrol, which is possibly a better place for it. use spawn() on Windows fork() is very slow. Can we get away with only using spawn()? Installable package for Windows Also, it would be nice to have an easily installable package for Windows that makes the machine be a Cygwin-based compile volunteer. It probably needs to include cross-compilers for Linux (or whatever), or at least simple instructions for building them. autodetection (Rendezvous, etc) http://dotlocal.org/mdnsd/ The Apple licence is apparently not GPL compatible. Brad reckons SLP is a better fit. Automatic detection ("zero configuration") of compile volunteers is probably not a good idea, because it might be complicated to implement, and would possibly cause breakage by distributing to machines which are not properly configured. OpenMOSIX autodiscovery what is this? [This is probably moot now - I think ZeroConf support accomplishes the same goals?] central configuration Notwithstanding the previous point, centralized configuration for a site would be good, and probably quite practical. Setting up a list of machines centrally rather than configuring each one sounds more friendly. The most likely design is to use DNS SRV records (RFC2052), or perhaps multi-RR A records. For example, compile.ozlabs.foo.com would resolve to all relevant machines. Another possibility would be to use SLP, the Service Location Protocol, but that adds a larger dependency and it seems not to be widely deployed. Large-scale Distribution distcc in it's present form works well on small numbers of close machines owned by the same people. It might be an interesting project to investigate scaling up to large numbers of machines, which potentially do not trust each other. This would make distcc somewhat more like other "peer-to-peer" systems like Freenet and Napster. ------------------------------------------------------------------------------- DONE TODOs ------------------------------------------------------------------------------- preprocess remotely [Done! This is distcc 3.0's "pump" mode.] Some people might like to assume that all the machines have the same headers installed, in which case we really can preprocess remotely and only ship the source. Imagine e.g. a Clearcase environment where the same filesystem view is mounted on all machines, and they're all running the exact same system release. It's probably not really a good idea, because it will be marginally faster but much more risky. It is possible, though, and perhaps people building files with enormous headers would like it. Perhaps those people should just use a different tool like dmake, etc. SSH connection hoarding It might be nice to hold open SSH connections to avoid the network and CPU overhead of opening new ones. However, fsh is far too slow, probably because of being written in Python. It's only going to work on systems which can pass file descriptors and therefore needs to be optional. Probably this only works on Unix. Building the kernel between the three x2000s seems to make localhost thrash. A few jobs (but not many) get passed out to the other machines. Perhaps for C++ or something with really large files fsh would be better because the cost of starting Python would be amortized across more work. I don't think this needs to be done in distcc. It can be a completely separate project to just rewrite fsh into C. Indeed you could even be compatible with the Python implementation and just write the short-lived client bit in C. [This has been done, in ssh itself: the -M option and the ControlMaster and ControlPath configuration settings.] Packaging Perhaps build RPMS and .debs? [DONE] Is it easy to build a static (or LSB-compliant?) .rpm on Debian? [DONE] Local variables: mode: indented-text indent-tabs-mode: nil End: distcc-3.4/autogen.sh000077500000000000000000000015141404653710500146400ustar00rootroot00000000000000#! /bin/sh -e # Usage: autogen.sh [srcdir] # Run this script to build distcc from CVS. ## first try the default names ACLOCAL="aclocal" AUTOHEADER="autoheader" AUTOCONF="autoconf" if which $AUTOCONF > /dev/null then : else echo "$0: need autoconf 2.53 or later to regenerate configure scripts" >&2 exit 1 fi srcdir=`dirname "$0"` builddir=`pwd` echo "$0: running $ACLOCAL" (cd $srcdir && $ACLOCAL -I m4 --output=$builddir/aclocal.m4) echo "$0: running $AUTOHEADER" [ -d src ] || mkdir src # Needed for autoheader to generate src/config.h.in. $AUTOHEADER $srcdir/configure.ac echo "$0: running $AUTOCONF" $AUTOCONF $srcdir/configure.ac > configure chmod +x configure if [ "$srcdir" = "." ]; then echo "Now run './configure' and then 'make'." else echo "Now run './configure --srcdir=$srcdir' and then 'make'." fi exit 0 distcc-3.4/bench/000077500000000000000000000000001404653710500137155ustar00rootroot00000000000000distcc-3.4/bench/Build.py000077500000000000000000000232221404653710500153320ustar00rootroot00000000000000# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. from Project import Project from compiler import CompilerSpec, prepare_shell_script_farm import buildutil from buildutil import make_dir, run_cmd, rm_files import re, os, sys, time # For parsing output of 'time -p'. RE_TIME = re.compile(r"""^real \s* (\d*\.\d*)\n user \s* (\d*\.\d*)\n sys \s* (\d*\.\d*)""", re.VERBOSE | re.MULTILINE) class TimeInfo: """A record of real, system, and user time.""" def __init__(self, real=None, system=None, user=None, include_server=None): self.real = real self.system = system self.user = user self.include_server = include_server class Build: """A Build is a combination of a Project and CompilerSpec. Note: when done with an object of this type, call its restore function; otherwise PATH will remain changed to an inappropriate value. """ def __init__(self, project, compiler, n_repeats): self.project = project self.compiler = compiler self.n_repeats = n_repeats self.base_dir = os.path.join(os.getcwd(), "build", self.project.name, self.compiler.name) self.unpacked_dir = os.path.join(self.base_dir, self.project.unpacked_subdir) # Some packages need to be started from a subdirectory of their # unpacked form. For example, Samba is compiled from the "source/" # subdirectory of the unpacked source. if self.project.build_subdir: self.build_dir = os.path.join(self.unpacked_dir, project.build_subdir) else: self.build_dir = self.unpacked_dir self.log_dir = self.build_dir self.configure_done = os.path.join(self.log_dir, "bench-configure.done") def __repr__(self): return "Build(%s, %s)" % (`self.project`, `self.compiler`) def _run_cmd_with_redirect_farm(self, cmd): """Initialize shell script farm for given compiler, augment PATH, and run cmd. A shell script farm is a set of scripts for dispatching a chosen compiler using distcc. For example, the 'cc' script may contain the one line: dist /usr/mine/gcc "$@" """ farm_dir = os.path.join(self.build_dir, 'build-cc-script-farm') make_dir(farm_dir) print ("** Creating masquerading shell scripts in '%s'" % farm_dir) masquerade = os.path.join(self.build_dir, 'masquerade') prepare_shell_script_farm(self.compiler, farm_dir, masquerade) old_path = os.environ['PATH'] try: os.environ['PATH'] = farm_dir + ":" + old_path return run_cmd(cmd) finally: os.environ['PATH'] = old_path def unpack(self): """Unpack from source tarball into build directory""" if re.search(r"\.tar\.bz2$", self.project.package_file): tar_fmt = "tar xf %s --bzip2" else: tar_fmt = "tar xfz %s" tar_cmd = tar_fmt % os.path.join(os.getcwd(), self.project.package_dir, self.project.package_file) make_dir(self.base_dir) print "** Unpacking..." run_cmd("cd %s && %s" % (self.base_dir, tar_cmd)) def configure(self): """Run configuration command for this tree, if any.""" make_dir(self.log_dir) configure_log = os.path.join(self.log_dir, "bench-configure.log") distcc_log = os.path.join(self.log_dir, "bench-configure-distcc.log") rm_files((configure_log, distcc_log, self.configure_done)) make_dir(self.build_dir) print "** Configuring..." cmd = ("cd %s && \\\nDISTCC_LOG='%s' \\\nCC='%s' \\\nCXX='%s' \\\n%s \\\n>%s 2>&1" % (self.build_dir, distcc_log, self.compiler.cc, self.compiler.cxx, self.project.configure_cmd, configure_log)) self._run_cmd_with_redirect_farm(cmd) # Touch a file if the configure was successfully done, so we know. open(self.configure_done, 'w').close() @staticmethod def _extract_time_info(log_file_name): """Open log file and look for output of 'time -p' and include server time.""" log_file = open(log_file_name, 'r') text = log_file.read() log_file.close() match = RE_TIME.search(text) if not match: sys.exit('Could not locate time information in log %s.' % log_file_name) time_info = TimeInfo(float(match.group(1)), float(match.group(2)), float(match.group(3))) # Now locate include server cpu time if present. lines = text.splitlines() for line in lines: if line.startswith('Include server timing. '): is_time = float( line[len('Include server timing. '):].split()[9][:-1]) time_info.include_server = is_time break return time_info def did_configure(self): """Returns true if configure was successfully run for this build in the past. """ return os.path.isfile(self.configure_done) def build(self): """Actually build the package.""" build_log = os.path.join(self.log_dir, "bench-build.log") prebuild_log = os.path.join(self.log_dir, "bench-prebuild.log") distcc_log = os.path.join(self.log_dir, "bench-build-distcc.log") rm_files((build_log, distcc_log)) make_dir(self.build_dir) print "** Building..." if self.project.pre_build_cmd: cmd = ("cd %s && %s > %s 2>&1" % (self.build_dir, self.project.pre_build_cmd, prebuild_log)) self._run_cmd_with_redirect_farm(cmd) distcc_hosts = buildutil.tweak_hosts(os.getenv("DISTCC_HOSTS"), self.compiler.num_hosts, self.compiler.host_opts) # We use built-in 'time' to measure real, system, and user time. To # allow its stderr to be grabbed, the time command is executed in a # subshell. cmd = ("cd %s && \\\n" "(time -p \\\n" "DISTCC_HOSTS='%s' \\\n" "INCLUDE_SERVER_ARGS='-t --unsafe_absolute_includes %s' \\\n" "%s%s \\\nDISTCC_LOG='%s' \\\nCC='%s' \\\nCXX='%s' " "\\\n%s)" "\\\n>%s 2>&1" % (self.build_dir, distcc_hosts, self.project.include_server_args, self.compiler.pump_cmd, self.project.build_cmd, distcc_log, self.compiler.cc, self.compiler.cxx, self.compiler.make_opts, build_log)) result, unused_elapsed = self._run_cmd_with_redirect_farm(cmd) return (result, Build._extract_time_info(build_log)) def clean(self): clean_log = os.path.join(self.log_dir, "bench-clean.log") make_dir(self.build_dir) print "** Cleaning build directory" cmd = "cd %s && make clean >%s 2>&1" % (self.build_dir, clean_log) self._run_cmd_with_redirect_farm(cmd) def scrub(self): print "** Removing build directory" rm_files((self.configure_done, )) run_cmd("rm -rf %s" % self.unpacked_dir) def build_actions(self, actions, summary): """Carry out selected actions. Catch exceptions and handle.""" try: # The time_info_accumulator is normally a list. But if something # goes wrong, it will contain a short string indicating the problem. time_info_accumulator = [] if 'sweep' in actions: self.scrub() if 'unpack' in actions: self.unpack() if 'configure' in actions: self.configure() # This is a safety measure, in case a previous benchmark # run left the build in an incomplete state. if 'clean' in actions: self.clean() for i in range(self.n_repeats): if 'build' in actions: (result, time_info) = self.build() if result: # that is, if result is bad! time_info_accumulator = 'NON-ZERO STATUS' elif isinstance(time_info_accumulator, list): time_info_accumulator.append(time_info) if 'clean' in actions: self.clean() if 'scrub' in actions: self.scrub() summary.store(self.project, self.compiler, time_info_accumulator) except KeyboardInterrupt: raise except: apply(sys.excepthook, sys.exc_info()) # print traceback summary.store(self.project, self.compiler, 'FAIL WITH EXCEPTION') distcc-3.4/bench/Project.py000077500000000000000000000134151404653710500157040ustar00rootroot00000000000000# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. import re, os, sys, time from buildutil import make_dir, run_cmd # Trees of software to be built. trees = { } class Project: """Defines a project to be built and tested. The Python process remains in the top-level directory for the whole process. Commands are kicked off in subdirectories if necessary. 'subdir' variables give just a single component of a name; 'dir' variables give a full path.""" def __init__(self, url, package_file=None, name=None, md5=None, unpacked_subdir=None, build_subdir=None, configure_cmd=None, pre_build_cmd = None, build_cmd=None, include_server_args=""): """Specification of a project to build. url: the url to download the file. package_file: the filename of the downloaded url. If not specified, taken to be basename(url). This should rarely need to be specified. specified on the commandline to just benchmark a single project. name: the name used to identify the project when listing projects on the benchmark commandline. If not specified, taken to be package_file, but with the .tar.* extension removed. md5: the output of 'md5sum package_file'; used to verify a download. unpacked_subdir: The top-level directory created when we untar the package_file. If not specified, taken to be self.name, which is typically right (at least for projects make using autotools). build_subdir: the subdirectory of unpacked_subdir where building should be done; we create it if needed. Defaults to '.'. You should only need to change this if your project does not have its configure script in the top-level directory. configure_cmd: the command to generate the project's Makefile. It is run in build_subdir. Defaults to './configure'. pre_build_cmd: a command to run before running the build command. It is run in build_subdir. Defaults to running nothing. build_cmd: The command to build the project from the Makefile. We add VAR=val arguments, so build_cmd must be a single command that is either a form of 'make', or takes the same style arguments. Defaults to 'make'. include_server_args: include server tweaks such as stat reset triggers for builds that modify source files. """ self.url = url if not package_file: package_file = url.split('/')[-1] self.package_file = package_file if not name: name = re.match(r"(.*)\.tar(\.gz|\.bz2|)$", package_file).group(1) self.name = name self.md5 = md5 self.configure_cmd = configure_cmd or "./configure" self.build_cmd = build_cmd or "make" self.pre_build_cmd = pre_build_cmd self.package_dir = "packages" self.download_dir = "download" # By default, we assume the package creates an unpacked # directory whose name is the same as the tarball. For # example, Wine's tarball is "Wine-xxxxxxx", but it unpacks to # "wine-xxxxxxxx". # TODO(csilvers): figure out automatically if only one TLD. self.unpacked_subdir = unpacked_subdir or self.name self.build_subdir = build_subdir self.include_server_args = include_server_args def register(self): trees[self.name] = self def __repr__(self): return "Project(name=%s)" % `self.name` def download(self): """Download package from vendor site.""" make_dir(self.package_dir) make_dir(self.download_dir) if not os.path.isfile(os.path.join(self.package_dir, self.package_file)): # XXX: snarf gets upset if the HTTP server returns "416 # Requested Range Not Satisfiable" because the file is already # totally downloaded. This is kind of a snarf bug. print "** Downloading" run_cmd("cd %s && wget --continue %s" % (self.download_dir, self.url)) run_cmd("mv %s %s" % (os.path.join(self.download_dir, self.package_file), self.package_dir)) def did_download(self): return os.path.exists(os.path.join(self.package_dir, self.package_file)) def md5check(self): if self.md5: print "** Checking source package integrity" run_cmd("cd %s && echo '%s' | md5sum -c /dev/stdin" % (self.package_dir, self.md5)) def pre_actions(self, actions): """Perform actions preparatory to building according to selection.""" if 'download' in actions: self.download() if 'md5check' in actions: self.md5check() distcc-3.4/bench/ProjectDefs.py000077500000000000000000000136421404653710500165100ustar00rootroot00000000000000# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003, 2004 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. __doc__ = """distcc benchmark project definitions""" from Project import Project # Consider the following when adding a new project: # 1) Should be fairly large. That's where distcc helps most. # 2) Should have minimal dependencies. That way, the build will # succeed without you needing to install lots of libraries # on your machine. # # See Project.py:Project.__init__.doc() for documentation of the # named arguments that are allowed for Project. Project(url='http://ftp.gnu.org/gnu/hello/hello-2.1.1.tar.gz', md5='70c9ccf9fac07f762c24f2df2290784d *hello-2.1.1.tar.gz', ).register() Project(url='http://ftp.gnu.org/gnu/make/make-3.80.tar.bz2', md5='0bbd1df101bc0294d440471e50feca71 *make-3.80.tar.bz2' ).register() Project(url='ftp://ftp.gtk.org/pub/gtk/v2.0/glib-2.0.7.tar.bz2', md5='5882b1e729f57cb18af653a2f504197b glib-2.0.7.tar.bz2' ).register() Project(url='http://us1.samba.org/samba/ftp/old-versions/samba-2.2.7.tar.gz', build_subdir='source', md5='824cd4e305f9b744f3eec702a7b96f7f samba-2.2.7.tar.gz', ).register() Project(url='http://us1.samba.org/samba/ftp/old-versions/samba-3.0.20.tar.gz', name='samba-3.0.20', build_subdir='source', # newer versions of popt can be incompatible configure_cmd='./configure --with-included-popt', pre_build_cmd = 'make proto', ).register() Project(url='http://archive.apache.org/dist/httpd/httpd-2.0.43.tar.gz', md5='8051de5d160c43d4ed2cc47dc9be6fd3 httpd-2.0.43.tar.gz' ).register() Project(url='http://yate.null.ro/tarballs/yate2/yate-2.0.0-alpha2.tar.gz', name='yate', configure_cmd='./configure --without-libpq --without-mysql --without-wphwec --without-libgsm --without-libspeex --without-spandsp --without-pwlib --without-openh323 --without-libgtk2 --without-gtkmozilla --without-libqt4 --without-coredumper --without-doxygen --without-kdoc', md5='b9fd116bc5c8142de6e130931cd3bdf2 yate-2.0.0-alpha2.tar.gz' ).register() Project(url='http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.25.tar.bz2', md5='db95a49a656a3247d4995a797d333153 *linux-2.6.25.tar.bz2', configure_cmd="make V=1 HOSTCC='$(CC)' defconfig", build_cmd="make V=1 HOSTCC='$(CC)' bzImage", include_server_args='--stat_reset_triggers=include/linux/compile.h:include/asm/asm-offsets.h' ).register() Project(url='http://www.python.org/ftp/python/2.5.2/Python-2.5.2.tgz', name='Python-2.5.2', ).register() Project(url='http://ftp.gnu.org/gnu/binutils/binutils-2.18.tar.bz2', configure_cmd = './configure --disable-werror', ).register() # disable-sanity-checks is needed to stop it wanting linuxthreads -- # the resulting library is useless, but this is only a test. Project(url = 'http://ftp.gnu.org/pub/gnu/glibc/glibc-2.6.tar.bz2', build_subdir = '_build', configure_cmd = '../configure --disable-sanity-checks', ).register() Project(url='http://mirror.trouble-free.net/mysql_mirror/Downloads/MySQL-5.0/mysql-5.0.51b.tar.gz', md5='e6715a878a7c102f7a4c323f9ef63e8f *mysql-5.0.51b.tar.gz', configure_cmd = './configure', ).register() Project(url='http://sources-redhat.oc1.mirrors.redwire.net/gdb/old-releases/gdb-5.3.tar.gz', ).register() #### Commented out: gimp 1.2.3 has makefile bugs that break -j ## Project(url='ftp://212.8.35.65/pub/FreeBSD/distfiles/gimp-1.2.3.tar.bz2', ## md5='b19235f19f524f772a4aef597a69b1da *gimp-1.2.3.tar.bz2', ## configure_cmd='./configure --disable-perl', ## ).register() Project(url='ftp://ftp.gimp.org/pub/gimp/v2.2/gimp-2.2.10.tar.bz2', md5='aa29506ed2272af02941a7a601a7a097 gimp-2.2.10.tar.bz2', configure_cmd='./configure --disable-perl --disable-print', ).register() Project(url='http://ibiblio.org/pub/linux/system/emulators/wine/wine-0.9.4.tar.bz2', md5='73205d83a5612a43441a8532683c0434 wine-0.9.4.tar.bz2', ).register() Project(url='ftp://ftp.slackware.com/pub/slackware/slackware-9.1/source/xap/mozilla/mozilla-source-1.4.tar.bz2', name='mozilla-1.4', configure_cmd="LIBIDL_CONFIG=libIDL-config-2 ./configure", unpacked_subdir='mozilla', ).register() Project(url='http://ftp.mozilla.org/pub/firebird/releases/0.6/MozillaFirebird-0.6-source.tar.bz2', name='MozillaFirebird', unpacked_subdir='mozilla', ).register() #### Commented out: configure script hasn't kept up with modern gcc's. #### For instance, they check whether setrlimit takes an enum as the #### first argument by grepping for 'setrlimit(enum' in the .h file, #### but crosstool gcc's use a typedef, so it's 'setrlimit(newtype'. ## Project(url='http://download.dre.vanderbilt.edu/previous_versions/ACE+TAO+CIAO-5.6.5.tar.bz2', ## name='ace-5.6.5', ## unpacked_subdir='ACE_wrappers', ## build_subdir = '_build', ## configure_cmd='../configure', ## md5='32157a0a4cc9bd8dc03d98b90b707759 ACE+TAO+CIAO-5.6.5.tar.bz2' ## ).register() distcc-3.4/bench/Summary.py000077500000000000000000000102311404653710500157240ustar00rootroot00000000000000# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. import buildutil import os import statistics class Summary: """Stores and prints results of building different things""" # Table is a sequence, because we prefer to have things printed # out in the order they were executed. def __init__(self): self._table = [] def store(self, project, compiler, time_info_accumulator): """ Args: project: a Project object compiler: a Compiler object time_info_accumulator: the string 'FAIL' or a list of Build.TimeInfo records The time information is a list because we can build projects repeatedly. """ self._table.append((project.name, compiler.name, time_info_accumulator)) def print_raw(self): from pprint import pprint pprint(self._table) @staticmethod def print_mean_and_sd(times, unit='s', no_sd=False): assert len(unit) == 1, unit mean = statistics.mean(times) sd = statistics.std(times) if mean is None: print "%s%s " % ("n/a", sd_space), else: print "%8.1f%s " % (mean, unit), if not no_sd: if sd is None: print "%9s " % "n/a", else: print "%8.1f%s " % (sd, unit), def print_table(self): import time, os, sys import statistics # if nothing was run, skip it if not len(self._table): return """Print out in a nice tabular form""" print """ ======================== distcc benchmark results ======================== """ print "Date: ", time.ctime() hosts = os.getenv('DISTCC_HOSTS') print "DISTCC_HOSTS: %s" % `hosts` print "Total hosts: %d" % buildutil.count_hosts(hosts) number_CPUs = os.sysconf('SC_NPROCESSORS_ONLN') print "Local number of CPUs: %s" % number_CPUs sys.stdout.flush() os.system("uname -a") print ("%-20s %-30s %9s %9s %9s %9s %9s" % ('project', 'compiler', 'time', 's.d.', 'CPU time', 'CPU util', 'incl serv')) for row in self._table: print "%-20s %-30s " % row[:2], time_info_accumulator = row[2] if isinstance(time_info_accumulator, str): print ' ' * 4, time_info_accumulator else: real_times = [time_info.real for time_info in time_info_accumulator] Summary.print_mean_and_sd(real_times) cpu_times = [time_info.user + time_info.system for time_info in time_info_accumulator] self.print_mean_and_sd(cpu_times, no_sd=True) cpu_util_ratios = ( [100 * cpu_times[i]/(number_CPUs * time_info_accumulator[i].real) for i in range(len(time_info_accumulator))]) self.print_mean_and_sd(cpu_util_ratios, unit='%', no_sd=True) include_server_times = [time_info.include_server for time_info in time_info_accumulator] if None not in include_server_times: self.print_mean_and_sd(include_server_times, no_sd=True) print distcc-3.4/bench/actions.py000077500000000000000000000061311404653710500157330ustar00rootroot00000000000000# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # Tuples of (name, default, descr) all_actions = [('download', True, ''), ('md5check', True, 'check file was downloaded correctly'), ('sweep', True, 'remove build directory before unpacking'), ('unpack', True, 'unpack source'), ('configure', True, ''), ('build', True, ''), ('clean', True, 'run "make clean" or equivalent'), ('scrub', False, 'remove build directory')] # Actions done on a per-project (rather than a per-build) basis project_actions = ('download', 'md5check') def action_help(): print "Actions:" for action, default, descr in all_actions: default_ch = default and '*' or ' ' print " %c %-20s %s" % (default_ch, action, descr) print " (* = on by default)" # Filter out only actions where 'default' is true default_actions = [a[0] for a in all_actions if a[1]] def parse_opt_actions(optarg): opt_actions = optarg.split(',') action_names = [a[0] for a in all_actions] for oa in opt_actions: if oa not in action_names: raise ValueError, ("no such action: %s" % `oa`) return opt_actions def remove_unnecessary_actions(opt_actions, force, did_download, did_configure): """Given a list of actions (as a string), and a force value (as described in the help text for benchmark.py), and a bool indicating whether 'configure' was successfully run for this build or not, return a new list which is the actions to actually perform for this build. Returns two lists: one that can be done on a per-project basis, and one that has to be done on a per-build basis (as we build the project with various different flags). """ if force == 0 and did_configure and did_download: remove = ('download', 'md5check', 'sweep', 'unpack', 'configure') elif force <= 1 and did_download: remove = ('download', ) else: remove = () new_project_actions = [oa for oa in opt_actions if oa in project_actions and oa not in remove] new_build_actions = [oa for oa in opt_actions if oa not in project_actions and oa not in remove] return new_project_actions, new_build_actions distcc-3.4/bench/benchmark.py000077500000000000000000000201451404653710500162260ustar00rootroot00000000000000#! /usr/bin/python # benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003, 2004 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # Unlike the main distcc test suite, this program *does* require you # to manually set up servers on your choice of machines on the # network, and make sure that they all have appropriate compilers # installed. The performance measurements obviously depend on the # network and hardware available. # It also depends on you having the necessary dependencies to build # the software. If you regularly build software on Linux you should # be OK. Some things (the GIMP) will be harder than others. # On some platforms, it may be impossible to build some targets -- for # example, Linux depends on having a real-mode x86 assembler, which # probably isn't installed on Solaris. # Note that running this program will potentially download many # megabytes of test data. # TODO: Support applying patches after unpacking, before building. # For example, they might be needed to fix -j bugs in the Makefile. # TODO: In stats, show ratio of build time to slowest build time. (Or # to first one run?) # TODO: Allow choice of which compiler and make options to use. # TODO: Perhaps add option to do "make clean" -- this might be faster # than unzipping and configuring every time. But perhaps also less # reproducible. # TODO: Add option to run tests on different sets or orderings of # machines. import os import re import sys import time from getopt import getopt from Summary import Summary from Project import Project, trees from compiler import CompilerSpec from Build import Build import actions, compiler import ProjectDefs # this adds a lot of definitions to 'trees' def error(msg): sys.stderr.write(msg + "\n") def list_projects(): names = trees.keys() names.sort() for n in names: print n def find_project(name): """ Return the nearest unique match for name. """ best_match = None for pn in trees.keys(): if pn.startswith(name): if best_match: raise ValueError, "ambiguous prefix %s" % name else: best_match = pn if not best_match: raise ValueError, "nothing matches %s" % name else: return trees[best_match] def show_help(): print """Usage: benchmark.py [OPTION]... [PROJECT]... Test distcc relative performance building different projects. By default, all known projects are built. Options: --help show brief help message --list-projects show defined projects --cc=PATH specify base value of CC to pass to configure --cxx=PATH specify base value of CXX to pass to configure --output=FILE print final summary to FILE in addition to stdout -c, --compiler=COMPILER specify one compiler to use; format is {local|dist|lzo|pump},h,j -n N repeat compilation N times -a, --actions=ACTIONS comma-separated list of action phases to perform -f N, --force=N If set to 0, skip download, unpack, and configure actions if they've already been successfully performed; if set to 1 (the default), only skip the download action; if set to 2, do not skip any action The C and C++ compiler versions used can be set with the --cc and --cxx options. Use of distcc features is set with the -c/--compiler option. The argument to -c/--compiler has three components, separated by commas. The first component specifies which distcc features to enabled: "local" means run cc locally, "distcc" means use plain distcc, "lzo" means enabled compression, and "pump" means to enable pump mode and compression. The second component specifies how many distcc hosts to use. The third component specifies how many jobs to run (the -j/--jobs option to "make"). Multiple -c/--compiler options specify different scenarios to measure. The default is to measure a few reasonable scenarios. """ actions.action_help() # -a is for developer use only and not documented; unless you're # careful the results will just be confusing. ###################################################################### def main(): """Run the benchmark per arguments""" # Ensure that stdout and stderr are line buffered, rather than # block buffered, as might be the default when running with # stdout/stderr redirected to a file; this ensures that the # output is prompt, even when the script takes a long time for # a single step, and it also avoids confusing intermingling of # stdout and stderr. sys.stdout = os.fdopen(1, "w", 1) sys.stderr = os.fdopen(2, "w", 1) sum = Summary() options, args = getopt(sys.argv[1:], 'a:c:n:f:', ['list-projects', 'actions=', 'help', 'compiler=', 'cc=', 'cxx=', 'output=', 'force=']) opt_actions = actions.default_actions opt_cc = 'cc' opt_cxx = 'c++' opt_output = None opt_compilers = [] opt_repeats = 1 opt_force = 1 for opt, optarg in options: if opt == '--help': show_help() return elif opt == '--list-projects': list_projects() return elif opt == '--actions' or opt == '-a': opt_actions = actions.parse_opt_actions(optarg) elif opt == '--cc': opt_cc = optarg elif opt == '--cxx': opt_cxx = optarg elif opt == '--output': opt_output = optarg elif opt == '--compiler' or opt == '-c': opt_compilers.append(optarg) elif opt == '-n': opt_repeats = int(optarg) elif opt == '-f' or opt == '--force': opt_force = int(optarg) if opt_compilers: set_compilers = [compiler.parse_compiler_opt(c, cc=opt_cc, cxx=opt_cxx) for c in opt_compilers] else: set_compilers = compiler.default_compilers(cc=opt_cc, cxx=opt_cxx) # Find named projects, or run all by default if args: chosen_projects = [find_project(name) for name in args] else: chosen_projects = trees.values() for proj in chosen_projects: # Ignore actions we did in a previous benchmark run, absent -f. # We only run the project's pre-actions if one of the builds # needs it because it hasn't successfully run 'configure' yet. project_actions, _ = actions.remove_unnecessary_actions( opt_actions, opt_force, proj.did_download(), 0) proj.pre_actions(project_actions) for comp in set_compilers: build = Build(proj, comp, opt_repeats) _, build_actions = actions.remove_unnecessary_actions( opt_actions, opt_force, proj.did_download(), build.did_configure()) build.build_actions(build_actions, sum) sum.print_table() # If --output was specified, print the table to the output-file too if opt_output: old_stdout = sys.stdout sys.stdout = open(opt_output, 'w') try: sum.print_table() finally: sys.stdout.close() sys.stdout = old_stdout if __name__ == '__main__': main() distcc-3.4/bench/buildutil.py000077500000000000000000000056411404653710500162750ustar00rootroot00000000000000# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. def make_dir(d): import os if not os.path.isdir(d): os.makedirs(d) def run_cmd(cmd, expected=0): import time, os before = time.time() print '%% %s' % cmd result = os.system(cmd) after = time.time() elapsed = (after - before) print '%16.4fs elapsed\n' % elapsed if expected is not None: if expected != result: raise AssertionError("command failed: expected status %d, got %d", expected, result) return result, elapsed def rm_files(file_list): import os for f in file_list: if os.path.exists(f): os.unlink(f) def count_hosts(hosts): """Parse a distcc Hosts Specification and count the number of hosts.""" num_hosts = 0 for host in hosts.split(): if host == '+zeroconf': raise ValueError, "Can't count hosts when +zeroconf is in DISTCC_HOSTS" if host.startswith('-'): # Don't count options such as '--randomize', '--localslots=N', # or '--localslots_cpp=N' as hosts. continue num_hosts += 1 return num_hosts def tweak_hosts(hosts, max_hosts, opts): """ Parse a distcc Hosts Specification and construct a new one that has at most 'max_hosts' hosts in it, appending 'opts' to each host in the Hosts Specification. Arguments: hosts: the original hosts specification; a string. max_hosts: the number of hosts to allow; an integer. Returns: the new hosts specification; a string. """ num_hosts = 0 hosts_list = [] for host in hosts.split(): if host == '+zeroconf': raise ValueError, "Can't limit hosts when +zeroconf in DISTCC_HOSTS" if host.startswith('-'): # Don't count options such as '--randomize', '--localslots=N', # or '--localslots_cpp=N' as hosts; but keep them in the host list. hosts_list.append(host) continue else: hosts_list.append(host + opts) num_hosts += 1 if num_hosts >= max_hosts: break return ' '.join(hosts_list) distcc-3.4/bench/compiler.py000077500000000000000000000164771404653710500161230ustar00rootroot00000000000000# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. import commands import os import shutil import stat import sys import tempfile import buildutil STANDARD_CC_NAMES = ['cc', 'gcc'] STANDARD_CXX_NAMES = ['cxx', 'c++', 'g++' ] def _find_executable(name): (rs, output) = commands.getstatusoutput('which "%s"' % name) if rs: sys.exit("Could not determine location of '%s'" % name) return output.strip() class CompilerSpec: """Describes a compiler/make setup. Used to define different situations such as local compilation, and various degrees of parallelism.""" def __init__(self, where, cc, cxx, prefix='', make_opts='', pump_cmd='', num_hosts=1, host_opts='', name=None): """Constructor: Args: where: 'local', 'dist', 'lzo', or 'pump' cc: location of the C compiler cxx: location of the C++ prefix: a string, either 'distcc ' or '' make_opts: options to make, such as '-j120' host_opts: for appending to hosts in DISTCC_HOSTS such as ',lzo,cpp' name: a string """ self.where = where self.real_cc = _find_executable(cc) self.real_cxx = _find_executable(cxx) self.cc = prefix + self.real_cc self.cxx = prefix + self.real_cxx self.make_opts = make_opts self.host_opts = host_opts self.pump_cmd = pump_cmd self.num_hosts = num_hosts self.host_opts = host_opts self.name = name or (self.pump_cmd + self.real_cc + "__" + self.make_opts).replace(' ', '_') def prepare_shell_script_farm(self, farm_dir, masquerade): """Prepare farm directory for masquerading. Assume the compiler is not local. Each standard name, such as 'cc', is used for form a shell script, named 'cc', that contains the line 'distcc /my/path/gcc "$@"', where '/my/path/gcc' is the value of the compiler.gcc field. If the compiler is local, then the same procedure is followed except that 'distcc' is omitted from the command line. """ assert os.path.isdir(farm_dir) assert os.path.isabs(farm_dir) def make_shell_script(name, compiler_path, where): fd = open(os.path.join(farm_dir, name), 'w') fd.write('#!/bin/sh\n%s%s "$@"' % (where != 'local' and 'distcc ' or '', compiler_path)) fd.close() os.chmod(os.path.join(farm_dir, name), stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) for generic_name in STANDARD_CC_NAMES: make_shell_script(generic_name, self.real_cc, self.where) for generic_name in STANDARD_CXX_NAMES: make_shell_script(generic_name, self.real_cxx, self.where) # Make shell wrapper to help manual debugging. fd = open(masquerade, 'w') fd.write("""\ #!/bin/sh # Execute $@, but force 'cc' and 'cxx'" to be those in the farm of # masquerading scripts. Each script in turn executes 'distcc' with the actual # compiler specified with the benchmark.py command. PATH=%s:"$PATH" "$@" """ % farm_dir) fd.close() os.chmod(masquerade, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) def default_compilers(cc, cxx): return [parse_compiler_opt('local,h1,j1', cc, cxx), parse_compiler_opt('dist,h10,j20', cc, cxx), parse_compiler_opt('dist,h10,j40', cc, cxx), parse_compiler_opt('pump,h10,j20', cc, cxx), parse_compiler_opt('pump,h10,j40', cc, cxx), ] def parse_compiler_opt(optarg, cc, cxx): """Parse command-line specification of a compiler (-c/--compiler). XXX: I don't really know what the best syntax for this is. For the moment, it is "local", "dist", "lzo", or "pump", followed by ",h" and the number of hosts to use, followed by ",j" and the number of jobs to use (for the -j option to make). """ where, hosts, jobs = optarg.split(',') if hosts.startswith("h"): hosts = int(hosts[1:]) if not os.getenv("DISTCC_HOSTS"): raise ValueError, "You must set DISTCC_HOSTS before running benchmarks" max_hosts = buildutil.count_hosts(os.getenv("DISTCC_HOSTS")) if hosts > max_hosts: print ("Warning: can't use %d hosts: DISTCC_HOSTS only has %d" % (hosts, max_hosts)) hosts = max_hosts else: raise ValueError, ("invalid compiler option: " "expecting '...,h,...', found %s" % `hosts`) if jobs.startswith("j"): jobs = int(jobs[1:]) else: raise ValueError, ("invalid compiler option: " "expecting '...,j', found %s" % `jobs`) if where == 'local': return CompilerSpec(where=where, name='local_%02d' % jobs, cc=cc, cxx=cxx, num_hosts=1, make_opts='-j%d' % jobs) elif where == 'dist': return CompilerSpec(where=where, name='dist_h%02d_j%02d' % (hosts, jobs), cc=cc, cxx=cxx, prefix='distcc ', num_hosts=hosts, make_opts='-j%d' % jobs) elif where == 'lzo': return CompilerSpec(where=where, name='lzo_h%02d_j%02d' % (hosts, jobs), cc=cc, cxx=cxx, prefix='distcc ', num_hosts=hosts, host_opts=",lzo", make_opts='-j%d' % jobs) elif where == 'pump': return CompilerSpec(where=where, name='pump_h%02d_j%02d' % (hosts, jobs), cc=cc, cxx=cxx, prefix='distcc ', pump_cmd='pump ', num_hosts=hosts, host_opts=",cpp,lzo", make_opts='-j%d' % jobs) else: raise ValueError, ("invalid compiler option: don't understand %s" % `where`) def prepare_shell_script_farm(compiler, farm_dir, masquerade): compiler.prepare_shell_script_farm(farm_dir, masquerade) distcc-3.4/bench/statistics.py000077500000000000000000000023671404653710500164740ustar00rootroot00000000000000#! /usr/bin/env python2.2 # benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. import math def var(m): """ Variance of m. """ if len(m) < 2: return None mu = mean(m) return sum((x - mu) * (x - mu) for x in m) / (len(m) - 1.0) def std(m): """ Standard deviation of m. """ v = var(m) return v and math.sqrt(v) def mean(m): if len(m) < 1: return None return sum(m)/len(m) distcc-3.4/config.guess000077500000000000000000001263431404653710500151670ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2017 Free Software Foundation, Inc. timestamp='2017-05-27' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || \ echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "${UNAME_MACHINE_ARCH}" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; *:Sortix:*:*) echo ${UNAME_MACHINE}-unknown-sortix exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; e2k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; k1om:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; mips64el:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; NSX-*:NONSTOP_KERNEL:*:*) echo nsx-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac cat >&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: distcc-3.4/config.sub000077500000000000000000001072431404653710500146300ustar00rootroot00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2017 Free Software Foundation, Inc. timestamp='2017-04-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | wasm32 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; asmjs) basic_machine=asmjs-unknown ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; e500v[12]) basic_machine=powerpc-unknown os=$os"spe" ;; e500v[12]-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` os=$os"spe" ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; nsx-tandem) basic_machine=nsx-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; wasm32) basic_machine=wasm32-unknown ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -ios) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; pru-*) os=-elf ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: distcc-3.4/configure.ac000066400000000000000000000424041404653710500151300ustar00rootroot00000000000000dnl Process this file with autoconf to produce a configure script # "We are ugly but we have the music" # -- Leonard Cohen # # http://jerkcity.com/jerkcity1335.html # This is the configure script for distcc. # Copyright (C) 2002, 2003, 2004 by Martin Pool # As of 0.6cvs, distcc no longer uses automake, only autoconf. AC_PREREQ(2.69) AC_INIT(distcc, 3.4, distcc@lists.samba.org) AC_CONFIG_HEADERS(src/config.h) AC_CONFIG_MACRO_DIRS([m4]) # FreeBSD installs its version of libpopt into /usr/local/, but does # not put that on the default library and header path. # Solaris doesn't even ship libpopt. We used to add that path if # building on *bsd*, but bje points out that will break # cross-compilation, and it's kind of ugly anyhow. Anyhow, you can # either set CPPFLAGS and LDFLAGS when running configure, or use # --with-extra-foo. # Check for socklen_t, and do something appropriate on systems # that don't have it. AC_CHECK_TYPE([socklen_t], ,[ AC_MSG_CHECKING([for socklen_t equivalent]) AC_CACHE_VAL([dcc_cv_socklen_t_equiv], [ # Systems have either "struct sockaddr{,_in} *" or # "void *" as the second argument to getpeername dcc_cv_socklen_t_equiv= for arg2 in "struct sockaddr_in" "struct sockaddr" void; do for t in int size_t unsigned long "unsigned long"; do AC_TRY_COMPILE([ #include #include int getpeername (int, $arg2 *, $t *); ],[ $t len; getpeername(0,0,&len); ],[ dcc_cv_socklen_t_equiv="$t" break ]) done done if test "x$dcc_cv_socklen_t_equiv" = x; then AC_MSG_ERROR([Cannot find a type to use in place of socklen_t]) fi ]) AC_MSG_RESULT($dcc_cv_socklen_t_equiv) AC_DEFINE_UNQUOTED(socklen_t, $dcc_cv_socklen_t_equiv, [type to use in place of socklen_t if not defined])], [#include #include ]) dnl Android requires -llog for printf and friends dnl and will only run position independent executables AC_MSG_CHECKING([if building on Android]) AC_TRY_COMPILE([], [ #ifdef __BIONIC__ int ok; (void)ok; #else choke me #endif], [AC_MSG_RESULT(yes) LDFLAGS="$LDFLAGS -llog -pie"], [AC_MSG_RESULT(no)]) # TODO: Handle program transform rules by autoconf. ### Checks for configure options AC_ARG_WITH(included-popt, AC_HELP_STRING([--with-included-popt], [use bundled popt library, not from system])) AC_ARG_ENABLE(pump-mode, AC_HELP_STRING([--disable-pump-mode], [include server support (pump mode), requires python]), [pump_mode=${enableval}], [pump_mode=yes]) # We prefer to use the latest Python if test "x${pump_mode}" = xyes; then AM_PATH_PYTHON([3.1],,[:]) AC_ARG_VAR(PYTHON, [Python interpreter]) AC_SUBST(PYTHON_RELATIVE_LIB) fi AC_ARG_ENABLE(rfc2553, AC_HELP_STRING([--enable-rfc2553], [use getaddrinfo, getnameinfo, etc])) if test x"$enable_rfc2553" = xyes then AC_DEFINE(ENABLE_RFC2553,1,[use getaddrinfo(), getnameinfo(), etc]) fi AC_ARG_WITH(gnome, AC_HELP_STRING([--with-gnome], [build GNOME-based monitor])) if test x"$with_gnome" = xyes then GNOME_BIN=distccmon-gnome AC_DEFINE(WITH_GNOME,1,[Use GNOME]) fi AC_ARG_WITH(gtk, AC_HELP_STRING([--with-gtk], [build GTK+-based monitor])) if test x"$with_gtk" = xyes then GNOME_BIN=distccmon-gnome AC_DEFINE(WITH_GTK,1,[Use GTK+]) fi AC_ARG_ENABLE(profile, AC_HELP_STRING([--enable-profile], [turn on gprof])) if test x"$enable_profile" = xyes then CFLAGS="$CFLAGS -pg -g" fi AC_ARG_ENABLE(Werror, AC_HELP_STRING([--disable-Werror], [don't use gcc's -Werror option when building])) # Now get the package configuration information for whatever packages # we need. It's faster to just do it once during configuration. if test "x${with_gnome}" = xyes then GNOME_PACKAGES="gtk+-3.0 libgnome-3.0 libgnomeui-3.0 pango" elif test "x${with_gtk}" = xyes then GNOME_PACKAGES="gtk+-3.0" else GNOME_PACKAGES="" fi for pkg in $GNOME_PACKAGES do AC_MSG_CHECKING([version of $pkg]) if gnomevers=`pkg-config --modversion $pkg` then AC_MSG_RESULT($gnomevers) else AC_MSG_ERROR([$pkg was not found by pkg-config]) fi done if test x${with_gnome} = xyes -o x${with_gtk} = xyes then INSTALL_GNOME="install-gnome-data" UNINSTALL_GNOME="uninstall-gnome-data" AC_MSG_CHECKING([GNOME/GTK+ cflags]) GNOME_CFLAGS="`pkg-config --cflags $GNOME_PACKAGES`" || AC_MSG_ERROR([failed to get cflags]) AC_MSG_RESULT([${GNOME_CFLAGS}]) AC_MSG_CHECKING([GNOME/GTK+ libraries]) GNOME_LIBS="`pkg-config --libs $GNOME_PACKAGES`" || AC_MSG_ERROR([failed to get libs]) AC_MSG_RESULT([${GNOME_LIBS}]) fi AC_SUBST(GNOME_PACKAGES) AC_SUBST(GNOME_CFLAGS) AC_SUBST(GNOME_LIBS) AC_SUBST(INSTALL_GNOME) AC_SUBST(UNINSTALL_GNOME) dnl Checks for programs AC_PROG_CC WERROR_CFLAGS="" POPT_CFLAGS="" PYTHON_CFLAGS="" if test x"$GCC" = xyes then CFLAGS="$CFLAGS -MD \ -W -Wall -Wimplicit \ -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings \ -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes \ -Wnested-externs -Wmissing-declarations" # -Wuninitialized requires -O case "$CFLAGS" in "-O"*|*" -O"*) CFLAGS="$CFLAGS -Wuninitialized" ;; esac # Would like -Wunreachable-code here, but it generates too many false # positives. # We want warnings to be treated as errors, # unless the --disable-Werror configure option was used. # Note that we can't include this in CFLAGS, # because that would affect the configure tests, # causing some of the tests to fail when they should succeed. if test x"$enable_Werror" != xno then WERROR_CFLAGS="-Werror" # -Wp,-U_FORTIFY_SOURCE is to turn off _FORTIFY_SOURCE on systems where # it's in the Python Makefile (and hence inherited by us). # -Werror -D_FORTIFY_SOURCE gives compiler errors for some distcc routines that # ignore the return value from libc functions (like getcwd). # That would cause this code to not compile, which is no good. PYTHON_CFLAGS="-Wp,-U_FORTIFY_SOURCE" fi # Additional flags for compiling Python extension modules. # We disable -Wmissing-prototypes and -Wmissing-declarations, # which don't apply to python extensions (it exports global fns via a # pointer), and -Wwrite-strings, which just had too many false # positives (for Python 2.2, anyway; looks like these may be fixed # in Python 2.5). PYTHON_CFLAGS="$PYTHON_CFLAGS -Wno-missing-prototypes -Wno-missing-declarations \ -Wno-write-strings" # For popt/*.c, we disable unused variable warnings. # When using Apple GCC/Clang you have to explicitly disable unused parameters. POPT_CFLAGS="-Wno-unused -Wno-unused-parameter" AC_MSG_NOTICE([Adding gcc options: $CFLAGS]) fi AC_SUBST(WERROR_CFLAGS) AC_SUBST(POPT_CFLAGS) AC_SUBST(PYTHON_CFLAGS) AC_ISC_POSIX # Apple's OS X gcc has a cpp-precomp "feature" that breaks standard # variadic macros. If we can disable it, do so. # This is needed for our included version of lzo. CPPFLAGS="$CPPFLAGS -DMINILZO_HAVE_CONFIG_H" # This is needed for our included version of popt. # TODO(csilvers): figure out what that above comment means, and if it's true. CPPFLAGS="$CPPFLAGS -DHAVE_CONFIG_H" # Needed to get various GNU-only functions. They're all autodetected # by configure so we can cope without them, but we want them if they're # there. CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" AC_PROG_MAKE_SET AC_PROG_INSTALL AC_C_INLINE AC_C_BIGENDIAN ######################################################################## ### Checks for header files # Some of these are needed by popt (or other libraries included in the future). AC_CHECK_HEADERS([unistd.h sys/types.h sys/sendfile.h]) AC_CHECK_HEADERS([ctype.h sys/resource.h sys/socket.h sys/select.h]) AC_CHECK_HEADERS([netinet/in.h], [], [], [#if HAVE_SYS_TYPES_H # include #endif ]) AC_CHECK_HEADERS([arpa/nameser.h], [], [], [#if HAVE_SYS_TYPES_H # include #endif ]) AC_CHECK_HEADERS([resolv.h], [], [], [#if HAVE_SYS_TYPES_H # include #endif #if HAVE_NETINET_IN_H # include #endif #if HAVE_ARPA_NAMESER_H # include #endif ]) AC_CHECK_HEADERS([float.h mcheck.h alloca.h sys/mman.h sys/loadavg.h]) AC_CHECK_HEADERS([elf.h]) AC_CHECK_HEADERS([fnmatch.h]) ###################################################################### dnl Checks for types AC_CHECK_TYPES([in_port_t, in_addr_t], , , [ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_SOCKET_H # include #endif #if HAVE_NETINET_IN_H # include #endif #if HAVE_ARPA_NAMESER_H # include #endif ]) ######################################################################## ### Checks for libraries. # The following test taken from the cvs sources via Samba: # If we can't find connect, try looking in -lsocket, -lnsl, and -linet. # The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has # libsocket.so which has a bad implementation of gethostbyname (it # only looks in /etc/hosts), so we only look for -lsocket if we need # it. AC_SEARCH_LIBS(gethostent, [nsl]) AC_SEARCH_LIBS(setsockopt, [socket]) AC_SEARCH_LIBS(hstrerror, [resolv]) AC_SEARCH_LIBS(inet_aton, [resolv]) if test x"$with_included_popt" != x"yes" && test x"$with_included_popt" != xno then # If not explicitly requested, guess. # People might have the library but not the header, in which case we # still need to use the included copy. AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes]) AC_CHECK_HEADER(popt.h, , [with_included_popt=yes]) fi AC_CACHE_SAVE AC_MSG_CHECKING([whether to use included libpopt]) if test x"$with_included_popt" = x"yes" then AC_MSG_RESULT($srcdir/popt) # popt_OBJS gets appended to distccd object list BUILD_POPT='$(popt_OBJS)' POPT_INCLUDES='-I"$(srcdir)/popt"' else AC_MSG_RESULT(no) POPT_INCLUDES='' AC_CHECK_LIB(popt, poptGetContext, , AC_MSG_ERROR([Cannot find system libpopt])) fi AC_ARG_WITH(libiberty, AC_HELP_STRING([--without-libiberty], [build without libiberty (no @file support)])) if test x"$with_libiberty" != xno; then AC_CHECK_LIB([iberty], [expandargv], , AC_MSG_ERROR([Cannot find libiberty])) AC_CHECK_HEADERS([libiberty.h libiberty/libiberty.h], [break]) if (test "$ac_cv_header_libiberty_h" != yes) && (test "$ac_cv_header_libiberty_libiberty_h" != yes); then AC_MSG_ERROR([Cannot find libiberty.h]) fi fi ######################################################################## # Check for types AC_TYPE_SIGNAL ######################################################################## # Checks for library functions, using libraries discovered above # The line below was commented out: it should not be necessary for the # AC_CHECK_FUNCS, which link against libraries on the host. For the subsequent # explicit compilation tests below, no distcc libraries are used. # TODO(klarlund): remove the line. # CPPFLAGS="$CPPFLAGS -I$srcdir/src" AC_CHECK_FUNCS([getpagesize]) AC_CHECK_FUNCS([sendfile setsid flock lockf hstrerror strerror setuid setreuid]) AC_CHECK_FUNCS([getuid geteuid mcheck wait4 wait3 waitpid setgroups]) AC_CHECK_FUNCS([snprintf vsnprintf vasprintf asprintf getcwd getwd mkdtemp]) AC_CHECK_FUNCS([getrusage strsignal gettimeofday]) AC_CHECK_FUNCS([getaddrinfo getnameinfo inet_ntop inet_ntoa]) AC_CHECK_FUNCS([strndup strsep mmap strlcpy]) AC_CHECK_FUNCS([getloadavg]) AC_CHECK_FUNCS([getline]) AC_CHECK_FUNCS([fstatat]) AC_CHECK_DECLS([snprintf, vsnprintf, vasprintf, asprintf, strndup]) AC_MSG_CHECKING([if mmap() supports MAP_FAILED]) AC_TRY_COMPILE([ #include #ifdef HAVE_SYS_MMAN_H # include #endif],[ #ifdef HAVE_MMAP if (mmap (NULL, 0, 0, 0, 0, 0) == MAP_FAILED) return 0; #else #error mmap unavailable #endif], AC_MSG_RESULT(yes), [ AC_MSG_RESULT(no) AC_DEFINE([MAP_FAILED], [(void *)-1L], [Define if MAP_FAILED constant not available]) ]) dnl dnl Test if the preprocessor understand vararg macros dnl AC_MSG_CHECKING([for vararg macro support]) AC_TRY_COMPILE([#define func(a, b...) do { } while (0)], [func("a"); func("a", "b"); func("a", "b", "c")], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_VARARG_MACROS, , [Define if your cpp has vararg macros])], [AC_MSG_RESULT(no)]) AC_CACHE_CHECK([for va_copy],dcc_cv_HAVE_VA_COPY,[ AC_TRY_LINK([#include va_list ap1,ap2;], [va_copy(ap1,ap2);], dcc_cv_HAVE_VA_COPY=yes,dcc_cv_HAVE_VA_COPY=no)]) if test x"$dcc_cv_HAVE_VA_COPY" = x"yes"; then AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available]) fi AC_CACHE_CHECK([for __va_copy],dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY,[ AC_TRY_LINK([#include va_list ap1,ap2;], [__va_copy(ap1,ap2);], dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY=yes,dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY=no)]) if test x"$dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY" = x"yes"; then AC_DEFINE(HAVE_UNDERSCORE_UNDERSCORE_VA_COPY,1,[Whether __va_copy() is available]) fi AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[ AC_TRY_RUN([ #include #include #include #include #include static int foo(const char *format, ...) { va_list ap; int len; char buf[5]; va_start(ap, format); len = vsnprintf(0, 0, format, ap); va_end(ap); if (len != 5) return 1; if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) return 1; return 0; } int main() { return foo("hello"); } ], rsync_cv_HAVE_C99_VSNPRINTF=yes,rsync_cv_HAVE_C99_VSNPRINTF=no,rsync_cv_HAVE_C99_VSNPRINTF=cross)]) if test x"$rsync_cv_HAVE_C99_VSNPRINTF" = x"yes"; then AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [define if vsnprintf is C99 compliant]) fi AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[ AC_TRY_RUN([ #include #include int main() { int fd[2]; return (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != -1) ? 0 : 1; }], rsync_cv_HAVE_SOCKETPAIR=yes,rsync_cv_HAVE_SOCKETPAIR=no,rsync_cv_HAVE_SOCKETPAIR=cross)]) if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then AC_DEFINE(HAVE_SOCKETPAIR, 1, [define if you have a working socketpair]) fi dnl Checks for structures AC_CHECK_MEMBER([struct sockaddr_storage.ss_family], AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1, [define if you have struct sockaddr_storage]),, [#include ]) AC_ARG_WITH(avahi, AC_HELP_STRING([--without-avahi], [build without avahi])) dnl check for avahi if test x"$with_avahi" != xno; then PKG_CHECK_MODULES(AVAHI, [avahi-client >= 0.6], [AC_DEFINE(HAVE_AVAHI, 1, [defined if Avahi is available]) CFLAGS="$CFLAGS $AVAHI_CFLAGS" LIBS="$LIBS $AVAHI_LIBS" ZEROCONF_COMMON_OBJS="src/zeroconf.o src/gcc-id.o" ZEROCONF_DISTCC_OBJS="" ZEROCONF_DISTCCD_OBJS="src/zeroconf-reg.o"], [ZEROCONF_COMMON_OBJS="" ZEROCONF_DISTCC_OBJS="" ZEROCONF_DISTCCD_OBJS=""]) AC_SUBST(ZEROCONF_COMMON_OBJS) AC_SUBST(ZEROCONF_DISTCC_OBJS) AC_SUBST(ZEROCONF_DISTCCD_OBJS) fi AUTH_COMMON_OBJS="" AUTH_DISTCC_OBJS="" AUTH_DISTCCD_OBJS="" #check for GSS-API AC_ARG_WITH([auth], [AS_HELP_STRING([--with-auth], [provide mutual authentication services via the GSS-API])]) if test x"$with_auth" = xyes; then AC_SEARCH_LIBS([gss_init_sec_context], [gssapi gssapi_krb5 gss], AC_DEFINE(HAVE_GSSAPI, 1, [Define if the GSS_API is available]) AUTH_COMMON_OBJS="src/auth_common.o" AUTH_DISTCC_OBJS="src/auth_distcc.o" AUTH_DISTCCD_OBJS="src/auth_distccd.o", AC_MSG_FAILURE([--with-auth was given but no GSS-API library found]) AUTH_COMMON_OBJS="" AUTH_DISTCC_OBJS="" AUTH_DISTCCD_OBJS="") fi AC_SUBST(AUTH_COMMON_OBJS) AC_SUBST(AUTH_DISTCC_OBJS) AC_SUBST(AUTH_DISTCCD_OBJS) AX_PTHREAD LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" dnl ##### Output AC_SUBST(CFLAGS) AC_SUBST(LDFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(POPT_INCLUDES) AC_SUBST(BUILD_POPT) AC_SUBST(GNOME_BIN) AC_DEFINE_UNQUOTED(GNU_HOST, ["$host"], [Your gnu-style host triple]) # The '.stamp-conf' files force creation of the containing directories in the # build tree. AC_CONFIG_FILES([Makefile] popt/.stamp-conf lzo/.stamp-conf) AC_CONFIG_FILES([pump], [chmod +x pump]) AC_OUTPUT ##### Finalization # Display success, installation paths, and GPL licence statement. echo ' ' ${MAKE-make} showpaths echo ' ' cat < Portions Copyright 2005 Google Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. After installing distcc, please complete the survey in the file "survey.txt". EOF distcc-3.4/contrib/000077500000000000000000000000001404653710500142765ustar00rootroot00000000000000distcc-3.4/contrib/distcc-absolutify000066400000000000000000000024061404653710500176530ustar00rootroot00000000000000#! /bin/sh # Copyright 2002 Free Software Foundation # by Alexandre Oliva # This script is Free Software, and it can be copied, distributed and # modified as defined in the GNU General Public License. A copy of # its license can be downloaded from http://www.gnu.org/copyleft/gpl.html # This is a wrapper for distcc that turns relative pathnames into # network-neutral ones. It modifies anything containing a slash and # not starting with dash or slash, as well as -B flags. We need not # be concerned about -I and -L, since distcc always does preprocessing # and linking locally. # If the first pathname is relative (.../xgcc, ./libtool, etc), case "$1" in [^/]*/*) nargs=$# basedir=`${NETPWD-netpwd}` # then process arguments for arg do case $arg in -B[^/]*) arg=-B$basedir/`echo "X$arg" | sed -e '1s/^X-B//'` ;; [^-/]*/*) arg=$basedir/$arg ;; esac set fnord ${1+"$@"} "$arg" done shift $nargs # take list of fnords out shift $nargs # take original args out ;; esac # Now run the real distcc thingie, or just run the program directly if # distcc is found to be missing. if test -x ${REAL_DISTCC-/usr/bin/distcc}; then x=${REAL_DISTCC-/usr/bin/distcc} else x=$1 shift fi exec $x ${1+"$@"} distcc-3.4/contrib/distcc.sh000066400000000000000000000021611404653710500161030ustar00rootroot00000000000000#! /bin/sh # This file, contributed by Dimitri PAPADOPOULOS-ORFANOS # may be installed as "cc" somewhere on your $PATH ahead of the real gcc. That # allows you to just use regular Makefiles without modifying them to change # hardcoded calls to cc. # This script will be a bit slow because of the overhead of running # things through a shell. In a future release, this function should # be supported directly by distcc, which should be a bit faster. DISTCC_HOME=/usr/local/distcc name=`basename $0` if [ "$name" = distcc ]; then echo "In normal use distcc is not called by its real name." 1>&2 echo "Instead create links to the actual compiler you wish to run, e.g." 1>&2 echo " ln -s distcc gcc" 1>&2 echo "and make sure the link is before the real compiler in your path." 1>&2 exit 1 fi unset found IFS=: for item in $PATH; do if [ -x "$item/$name" -a ! -d "$item/$name" ]; then if [ `cd $item; /bin/pwd` != `/bin/pwd` ]; then found=true break fi fi done if [ -n "$found" ]; then exec "distcc $item/$name $@" else echo "$name: not found" 1>&2 fi exit 1 distcc-3.4/contrib/distccd-init000066400000000000000000000032711404653710500166020ustar00rootroot00000000000000#! /bin/sh # # distccd Debian init.d script contributed by Jason Thomas. (Debian #161136) # # skeleton example file to build /etc/init.d/ scripts. # This file should be used to construct scripts for /etc/init.d. # # Written by Miquel van Smoorenburg . # Modified for Debian GNU/Linux # by Ian Murdock . # # Version: @(#)skeleton 1.9.1 08-Apr-2002 miquels@cistron.nl # PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/bin/distccd NAME=distccd DESC="Distributed Compiler Daemon" DAEMON_ARGS="--nice=10 --port=4200 --pid-file=/var/run/$NAME.pid \ --log-file=/var/log/$NAME.log --daemon" test -x $DAEMON || exit 0 set -e # we need permission to write to the pid file touch /var/run/$NAME.pid chown distccd /var/run/$NAME.pid case "$1" in start) echo -n "Starting $DESC: $NAME" start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ --chuid distccd \ --exec $DAEMON -- $DAEMON_ARGS echo "." ;; stop) echo -n "Stopping $DESC: $NAME " start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \ --oknodo \ --exec $DAEMON echo "." ;; restart|force-reload) # # If the "reload" option is implemented, move the "force-reload" # option to the "reload" entry above. If not, "force-reload" is # just the same as "restart". # echo -n "Restarting $DESC: $NAME" start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \ --oknodo \ --exec $DAEMON sleep 1 start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ --chuid distccd \ --exec $DAEMON -- $DAEMON_ARGS echo "." ;; *) N=/etc/init.d/$NAME echo "Usage: $N {start|stop|restart|force-reload}" >&2 exit 1 ;; esac exit 0 distcc-3.4/contrib/distccd-on-servers000077500000000000000000000056531404653710500177530ustar00rootroot00000000000000#! /bin/bash # Copyright 2007 Google Inc. All Rights Reserved. # # A script for installing and controlling distccd on servers. # # This script allows for easy testing of distcc. It does not depend on # RPM, debian or other packaging techniques. function Usage { printf "Usage: server-test {start|stop|restart|install|ps|status}\n\ Obligatory environment variables:\n\ DISTCC_LOC Location of distcc, a path of the form ../distcc.\n\ DISTCCD_MACHINES Hostnames of compiler servers.\n\ DISTCCD_REMOTE_LOC Path where distcc_pump/distcc resides on servers.\n\ DISTCCD_ARGS Arguments and options for distccd command on server.\n\ DISTCCD_TMPDIR Exported to server as TMPDIR before start.\n\ See script for details.\n\ " } trap "Usage" EXIT : ${DISTCC_LOC:?} : ${DISTCCD_MACHINES:?} : ${DISTCCD_REMOTE_LOC:?} : ${DISTCCD_ARGS:?} : ${DISTCCD_TMPDIR:?} trap EXIT function Doing { printf "\nDOING $1\n" } function Install { bad_server=0 for SERVER in $DISTCCD_MACHINES; do Doing $SERVER ssh $SERVER "mkdir --parents $DISTCCD_REMOTE_LOC"\ || { bad_server=$SERVER; continue; } ssh $SERVER "rm -rf $DISTCCD_REMOTE_LOC/distcc" \ || { bad_server=$SERVER; continue; } scp -r -q $DISTCC_LOC $SERVER:$DISTCCD_REMOTE_LOC/distcc \ || { bad_server=$SERVER:; continue; } done if [ "$bad_server" != 0 ]; then echo "ERROR: installation on $bad_server failed (and maybe others)" 1>&2 return 1 fi return 0 } function Start { bad_server=0 for SERVER in $DISTCCD_MACHINES; do Doing $SERVER ssh $SERVER \ "TMPDIR=$DISTCCD_TMPDIR; $DISTCCD_REMOTE_LOC/distcc/distccd $DISTCCD_ARGS"\ || { bad_server=$SERVER; continue; } done if [ $bad_server != 0 ]; then echo "ERROR: starting distccd on $bad_server failed (and maybe others)" 1>&2 return 1 fi return 0 } function Psing { for SERVER in $DISTCCD_MACHINES; do Doing $SERVER ssh $SERVER \ "ps ux | grep \"$DISTCCD_REMOTE_LOC.*[d]istccd\"" done } function Status { for SERVER in $DISTCCD_MACHINES; do Doing $SERVER # The [d] construct prevents the grep command itself from being recognized. ssh $SERVER \ "if ps ux | grep -q \" $DISTCCD_REMOTE_LOC/distcc/distcc[d] \"; then\ echo $SERVER is running distccd;\ fi;\ " done } function Stop { for SERVER in $DISTCCD_MACHINES; do Doing $SERVER ssh $SERVER \ "while grep Stopping \ <(ps ux | grep \"$DISTCCD_REMOTE_LOC.*[d]istcc\" | \ (read X PID Z; \ if [ -n \"\$PID\" ]; then\ echo \"Stopping process\" \$PID; kill \$PID;\ fi)); do\ :;\ done; " done } case "$1" in start) echo "Start" Start ;; stop) echo "Stop" Stop ;; restart) echo "Restart" Stop sleep 1 Start ;; install) echo "Install" Install ;; status) echo "Status" Status ;; ps) echo "Run 'ps'" Psing ;; *) Usage exit 1 ;; esac distcc-3.4/contrib/dmake000066400000000000000000000007421404653710500153050ustar00rootroot00000000000000#! /bin/sh # Example script contributed by Luke Gorrie # "Drop-in" front end to 'make' that uses the distributed compile farm # via `distcc' # Compile farm hosts are stored in ~bluetail/distcc-hosts. We exclude # the local machine to free up resources for preprocessing and # linking, since it seems to be the bottleneck (at least on # kookaburra). DISTCC_HOSTS=$(sed s/$(hostname -s)// < /home/share/bluetail/distcc-hosts) make CC='/home/share/luke/bin/distcc gcc' -j 7 "$@" distcc-3.4/contrib/make-j000066400000000000000000000010101404653710500153550ustar00rootroot00000000000000#! /bin/sh # make-j script from Alexandre Oliva for use with distcc # Tests which machines are up, and runs Make with concurrency set # appropriately. hostlist=$DISTCC_HOSTS distcc_port=4200 DISTCC_HOSTS= count=0 for h in $hostlist; do echo trying $h... >&2 if test "x$h" = xlocalhost || nc -z $h $distcc_port; then echo added $h... >&2 DISTCC_HOSTS=`echo $DISTCC_HOSTS $h` # remove leading blank count=`expr $count + 1` fi done export DISTCC_HOSTS exec make -j $count ${1+"$@"} distcc-3.4/contrib/netpwd000066400000000000000000000014261404653710500155250ustar00rootroot00000000000000#! /bin/sh # Copyright 2002 Free Software Foundation # by Alexandre Oliva # This script is Free Software, and it can be copied, distributed and # modified as defined in the GNU General Public License. A copy of # its license can be downloaded from http://www.gnu.org/copyleft/gpl.html # Turn a local pathname into a network-neutral one. It assumes # /net/$HOSTNAME/pathname can access $HOSTNAME's /pathname from other # machines, and that /net/$HOSTNAME is actually mounted (by amd) # inside /.automount/$HOSTNAME/root, so it compensates for that. dir=`${REAL_PWD-pwd}` case $dir in /net/*) ;; /.automount/*/root/*) dir=/net/`echo "$dir" | sed -e '1s,^/\.automount/,,' -e 's,/root/,/,'` ;; *) dir=/net/${HOSTNAME-`uname -n`}$dir ;; esac echo $dir exit 0 distcc-3.4/contrib/redhat/000077500000000000000000000000001404653710500155455ustar00rootroot00000000000000distcc-3.4/contrib/redhat/init000066400000000000000000000026711404653710500164410ustar00rootroot00000000000000#!/bin/sh # # Init file for Distccd - A distributed compilation front-end. # WARNING: Don't enable on untrusted networks # # Written by Dag Wieers . # # chkconfig: - 80 20 # description: Distccd - distributed compilation front-end (daemon) \ # WARNING: Don't enable on untrusted networks # # processname: distccd # # config: /etc/sysconfig/distccd source /etc/init.d/functions source /etc/sysconfig/network ### Check that networking is up. [ "${NETWORKING}" == "no" ] && exit 0 [ -x "/usr/bin/distccd" ] || exit 1 ### Default variables SYSCONFIG="/etc/sysconfig/distccd" OPTIONS="" USER="distcc" DISTCCPATH="$PATH" ### Read configuration [ -r "$SYSCONFIG" ] && source "$SYSCONFIG" RETVAL=0 prog="distccd" desc="Distributed Compiler daemon" start() { echo -n $"Starting $desc ($prog): " PATH="$DISTCCPATH" daemon --user "$USER" $prog --daemon --log-file="/var/log/distccd.log" $OPTIONS RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog return $RETVAL } stop() { echo -n $"Shutting down $desc ($prog): " killproc $prog RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog return $RETVAL } restart() { stop start } case "$1" in start) start ;; stop) stop ;; restart|reload) restart ;; condrestart) [ -e /var/lock/subsys/$prog ] && restart RETVAL=$? ;; status) status $prog RETVAL=$? ;; *) echo $"Usage $0 {start|stop|restart|condrestart|status}" RETVAL=1 esac exit $RETVAL distcc-3.4/contrib/redhat/logrotate000066400000000000000000000001231404653710500174640ustar00rootroot00000000000000/var/log/distccd.log { missingok copytruncate notifempty } distcc-3.4/contrib/redhat/sysconfig000066400000000000000000000003731404653710500174770ustar00rootroot00000000000000### See distcc(1) manual page for more information on these options. ### #OPTIONS="--nice 5 --jobs 5 --allow 10.0.0.0/24 --port 1234" #USER="distcc" ### Set this if don't want distccd to use gcc or g++ by accident. #DISTCCPATH="/usr/lib/distcc/bin" distcc-3.4/contrib/redhat/xinetd000066400000000000000000000007561404653710500167730ustar00rootroot00000000000000# default: off # description: Distccd - distributed compilation front-end (xinetd) \ # Please disable the daemon if you enable this. \ # WARNING: Don't enable on untrusted networks service distccd { disable = yes socket_type = stream protocol = tcp port = 3632 type = UNLISTED wait = no user = distcc server = /usr/bin/distccd server_args = --inetd --log-file="/var/log/distccd.log" only_from = 127.0.0.1 } distcc-3.4/contrib/stage-cc-wrapper.patch000066400000000000000000000076741404653710500205010ustar00rootroot00000000000000Index: Makefile.in =================================================================== RCS file: /cvs/gcc/egcs/Makefile.in,v retrieving revision 1.110 diff -u -p -r1.110 Makefile.in --- Makefile.in 8 Jul 2002 21:40:41 -0000 1.110 +++ Makefile.in 14 Aug 2002 02:49:35 -0000 @@ -251,7 +251,7 @@ GCJ_FOR_TARGET = # variable is passed down to the gcc Makefile, where it is used to # build libgcc2.a. We define it here so that it can itself be # overridden on the command line. -GCC_FOR_TARGET = $$r/gcc/xgcc -B$$r/gcc/ $(FLAGS_FOR_TARGET) +GCC_FOR_TARGET = $(STAGE_CC_WRAPPER) $$r/gcc/xgcc -B$$r/gcc/ $(FLAGS_FOR_TARGET) AS_FOR_TARGET = ` \ if [ -f $$r/gas/as-new ] ; then \ Index: configure.in =================================================================== RCS file: /cvs/gcc/egcs/configure.in,v retrieving revision 1.176 diff -u -p -r1.176 configure.in --- configure.in 6 Aug 2002 09:26:29 -0000 1.176 +++ configure.in 14 Aug 2002 02:49:38 -0000 @@ -1554,10 +1554,10 @@ cat >$sedtemp < stage_last stage2_build: stage1_copy - $(MAKE) CC="stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" \ + $(MAKE) CC="$(STAGE_CC_WRAPPER) stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" \ STAGE_PREFIX=stage1/ \ $(STAGE2_FLAGS_TO_PASS) $(STAMP) stage2_build @@ -3342,7 +3342,7 @@ stage2_copy: stage2_build echo stage3_build > stage_last stage3_build: stage2_copy - $(MAKE) CC="stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" \ + $(MAKE) CC="$(STAGE_CC_WRAPPER) stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" \ STAGE_PREFIX=stage2/ \ $(STAGE2_FLAGS_TO_PASS) $(STAMP) stage3_build @@ -3355,7 +3355,7 @@ stage3_copy: stage3_build echo stage4_build > stage_last stage4_build: stage3_copy - $(MAKE) CC="stage3/xgcc$(exeext) -Bstage3/ -B$(build_tooldir)/bin/" \ + $(MAKE) CC="$(STAGE_CC_WRAPPER) stage3/xgcc$(exeext) -Bstage3/ -B$(build_tooldir)/bin/" \ STAGE_PREFIX=stage3/ \ $(STAGE2_FLAGS_TO_PASS) $(STAMP) stage4_build distcc-3.4/doc/000077500000000000000000000000001404653710500134035ustar00rootroot00000000000000distcc-3.4/doc/example/000077500000000000000000000000001404653710500150365ustar00rootroot00000000000000distcc-3.4/doc/example/README000066400000000000000000000030531404653710500157170ustar00rootroot00000000000000This directory (distcc/doc/example) contains example configuration files for the distccd service that need to be installed manually when distccd is installed via "make install". For a typical Linux system, these files would need to be installed in the following locations: /etc/init.d/distcc /etc/logrotate.d/distcc /etc/inetd.d/distcc /etc/defaults/distcc /etc/services # Just append one line to this file. /etc/hosts.allow # Just append one line to this file. The details of how to set up services are quite system-specific, so depending on your system you may need to do things differently. If you install distccd using the RPM or Debian package, appropriate versions of those files will be installed automatically, so you don't need to install them manually, and you don't need to bother looking at the files in this directory (distcc/doc/example). However, you may need to edit the /etc/hosts.allow file. In addition to the above-mentioned configuration files, you may also need to edit the following three files in distcc's sysconf directory (/etc/distcc, or /usr/local/etc/distcc, or some other location, depending on how your configured distcc). Example versions of these configuration files get installed automatically by "make install" and by the RPM and Debian packages. Two configuration files on the server machines are used by the init script for starting distccd: /etc/distcc/commands.allow.sh /etc/distcc/clients.allow One configuration file on the client machine is used by distcc: /etc/distcc/hosts distcc-3.4/doc/example/default000066400000000000000000000001031404653710500163770ustar00rootroot00000000000000# This should go in the file /etc/default/distcc. STARTDISTCC=true distcc-3.4/doc/example/hosts.allow000066400000000000000000000002121404653710500172310ustar00rootroot00000000000000# A line like this should be appended to /etc/hosts.allow. # You'll need to edit this to allow access from other hosts. distcc: 127.0.0.1 distcc-3.4/doc/example/init000066400000000000000000000023661404653710500157330ustar00rootroot00000000000000#! /bin/sh # # chkconfig: - 60 20 # description: The distcc daemon # http://code.google.com/p/distcc/ # # processname: distccd # This is a Red Hat init.d file to start distccd. To install it, copy # it into /etc/init.d/distccd, and add appropriate links into the # rc?.d directories. # It may need to be tweaked for other distributions or versions. # You may wish to accept parameters from the user to set access # control options. # Get config. . /etc/sysconfig/network # Get functions . /etc/init.d/functions # Check that networking is up. if [ ${NETWORKING} = "no" ] ; then exit 0 fi RETVAL=0 SERVICE=distccd start() { echo -n $"Starting $SERVICE: " daemon /usr/local/bin/$SERVICE --daemon RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$SERVICE return $RETVAL } stop() { echo -n $"Stopping $SERVICE: " killproc $SERVICE RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$SERVICE return $RETVAL } restart() { stop start } # See how we were called. case "$1" in start) start ;; stop) stop ;; status) status $SERVICE ;; restart) restart ;; condrestart) [ -f /var/lock/subsys/$SERVICE ] && restart || : ;; *) echo $"Usage: $0 {start|stop|status|restart}" exit 1 ;; esac exit $? distcc-3.4/doc/example/init-suse000066400000000000000000000046651404653710500167140ustar00rootroot00000000000000#! /bin/sh # # Copyright (C) 2002 C. Brandon Forehand # # This code is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # /etc/init.d/distcc # # and symbolic link # # /usr/sbin/rcdistcc # ### BEGIN INIT INFO # Provides: distccd # Required-Start: $network # Required-Stop: $network # Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Description: Start the distcc daemon ### END INIT INFO . /etc/rc.status . /etc/rc.config # Determine the base and follow a runlevel link name. base=${0##*/} link=${base#*[SK][0-9][0-9]} DISTCC=/usr/local/bin/distccd DISTCC_OPTS=--daemon DISTCC_USER=daemon # Shell functions sourced from /etc/rc.status: # rc_check check and set local and overall rc status # rc_status check and set local and overall rc status # rc_status -v ditto but be verbose in local rc status # rc_status -v -r ditto and clear the local rc status # rc_failed set local and overall rc status to failed # rc_reset clear local rc status (overall remains) # rc_exit exit appropriate to overall rc status # First reset status of this service rc_reset case "$1" in start) echo -n "Starting distcc daemon" ## Start daemon with startproc(8). If this fails ## the echo return value is set appropriate. startproc -u $DISTCC_USER $DISTCC $DISTCC_OPTS # Remember status and be verbose rc_status -v ;; stop) echo -n "Shutting down distcc daemon:" ## Stop daemon with killproc(8) and if this fails ## set echo the echo return value. killproc -TERM $DISTCC # Remember status and be verbose rc_status -v ;; restart) ## If first returns OK call the second, if first or ## second command fails, set echo return value. $0 stop && $0 start # Remember status and be quiet rc_status ;; reload) $0 restart # Remember status and be verbose rc_status -v ;; status) echo -n "Checking for service distccd: " checkproc $DISTCC && echo OK || echo No process ;; *) echo "Usage: $0 {start|stop|status|restart|reload}" exit 1 ;; esac rc_exit distcc-3.4/doc/example/logrotate000066400000000000000000000004631404653710500167640ustar00rootroot00000000000000# logrotate.d example configuration for distcc, contributed by Dag # Wieers. # The "copytruncate" option means distcc can keep appending to the # same filehandle. You would otherwise need to shut down and restart # distccd. /var/log/distccd.log { missingok copytruncate notifempty } distcc-3.4/doc/example/services000066400000000000000000000001361404653710500166040ustar00rootroot00000000000000# Append the following line to /etc/services distcc 3632/tcp # Distcc Distributed Compiler distcc-3.4/doc/example/xinetd000066400000000000000000000016701404653710500162600ustar00rootroot00000000000000# default: off # description: distccd serves C/C++ compilation requests from distcc clients. # WARNING: This service should ONLY be used on trusted networks. # xinetd service description for distcc, contributed by akpm, updated # by mbp. # To use this, just check the parameters below and copy this file into # /etc/xinet.d/distcc, or the appropriate location for your system, # and then restart xinetd. You should also create a 'distcc' user. # ===> Note that running from inetd is generally NOT recommended for # distcc. distccd should give better performance when it can run as a # standalone daemon and regulate its own load. service distcc { disable = yes socket_type = stream wait = no user = distcc server = /usr/local/bin/distccd server_args = --inetd # This makes xinetd cope if there is no service listed in # /etc/services type = UNLISTED } distcc-3.4/doc/protocol-1.txt000066400000000000000000000146031404653710500161470ustar00rootroot00000000000000description of distcc protocol version 1 Copyright (C) 2003 by Martin Pool disclaimer ---------- This document is provided as explanation for people developing or debugging distcc. Discrepancies between this document and the distcc code are an error in the document. This document is intended to describe distcc 2.0. Because this program and document is licensed free of charge, there is no warranty of any kind, to the extent permitted by applicable law. If anything is unclear, please ask on the mailing list. purpose ------- The distcc protocol allows a compiler command line plus C preprocessed source code to be transmitted from a client computer to a server, where it is compiled. The results (object code, exit status, and/or error messages) are returned to the client. protocol versioning ------------------- This document describes version 1 of the protocol, which is used by distcc releases up to and including 2.1. Future versions of the protocol may vary in any way. The client begins its request by identifying the protocol version that it will use. The server must either respond using the requested protocol version, or respond with an error in the appropriate protocol version, or drop the connection. There is no mechanisms for negotiation of versions. It is envisaged that when software using a new protocol is released, users will upgrade both clients and servers at the same time. Since distcc is only used within organizations rather than on the internet this should be realistic. foundations ----------- The distcc protocol runs over a bidirectional non-delimited byte channel. This is normally a TCP connection, although operation over the OpenSSH secure shell is also supported. Each compilation of a file ("job") corresponds to one invocation of the client program and connection. control flow ------------ The overall structure of the protocol is very simple: 1: The client opens a connection, which is accepted by the server. 2: The client sends a request. 3: The server sends a response. 4: The client and server mutually close the connection. connections ----------- Connections are initiated by the client. TCP connections are opened by connecting to the server port, normally 3632. SSH connections are initiated by running the command "distccd --inetd" over SSH. Either party (client or server) may drop the connection at any point, in which case the job is discarded by both parties. In particular, the server drops the connection if the client's IP address is not allowed to connect, or if the client makes a protocol error. packets ------- The request and response both consist of a series of packets. Each packet consists of two or three parts: token -- four ascii bytes, defining the type of the packet parameter -- eight ascii hexadecimal digits, corresponding to a 32-bit unsigned quantity body -- optionally present, depending on the token The sequence in which tokens are sent by both client and server is always fixed and is specified by this document. If the type of packet (determined by the token) requires a body, then the length of the body is given by the parameter. Otherwise, the meaning of the parameter depends on the token. Closing the channel has no meaning and does not indicate the end of a packet, although it should correspond with the end of the last packet. An early close indicates an error. [note: Because the sequence of tokens never varies they are strictly redundant: each party could just read the parameters and bodies in order and know what they mean from context. Sending the tokens provides a check that both parties understand the data to mean the same thing and guards against code or network errors. It also aids any person examining the network stream.] [note: Sending the parameter as hexadecimal is redundant, because four bytes would be sufficient to encode the 32-bit integer. Sending as hexadecimal serves as a further check that the client and server are synchronized. Incorrect values for the parameter are detected as a program or network error.] [note: The fixed length of the token and length-preceded body allows IO with a small number of system calls: the header can be read in exactly twelve bytes, and the body can be read in a single chunk without needing to parse its contents.] [note: The length-preceded format means that data cannot be streamed out until the process that produced it is complete and the length of the data is known.] request ------- The following packets comprise the request: DIST Greeting from client, followed by the protocol version, which is always 1. ARGC Specifies the number of arguments in the command, including the compiler name. ARGV Repeated times. Specifies the string value of one element of the command. DOTI The contents of the preprocessed source (.i) file. response -------- The following packets comprise the response: DONE Introduces the response. The version must be 1. STAT Gives the Unix wait status of the compiler. This 0 for success, or otherwise (EXITCODE << 8) | (TERMSIGNAL), depending on whether the compiler returned an error or was terminated by a signal. (See or a POSIX standard for a full definition.) SERR Contains messages sent to stderr by the compiler. SOUT Contains messages sent to stdout by the compiler. Normally empty -- errors and warnings for most compilers go to stderr instead. DOTO Contains the object file (.o) produced by the compiler. In very early versions, this is missing if the status code is not zero. In versions up to and including 2.7.1, zero-length output files are not supported. If compilation fails, then the server sends the file with a length of zero, but the client does not read it. From 2.8, things work as follows: regular success: status zero length nonzero succeeded, but zero-byte output: status zero length zero output file is created/touched failed: status nonzero length sent as zero This is a little complex but is compatible with earlier releases. This does mean we cannot represent a compiler that produces output and then fails, but I don't think that is very important. distcc-3.4/doc/protocol-2.txt000066400000000000000000000023221404653710500161430ustar00rootroot00000000000000description of distcc protocol version 2 Copyright (C) 2003 by Martin Pool disclaimer ---------- This document is provided as explanation for people developing or debugging distcc. Discrepancies between this document and the distcc code are an error in the document. This document is intended to describe distcc 2.9. Because this program and document is licensed free of charge, there is no warranty of any kind, to the extent permitted by applicable law. If anything is unclear, please ask on the mailing list. protocol -------- Protocol 2 is a variation of protocol 1. It gets a new version number because that's the simplest way to indicate the change. The protocol number (DIST) sent by the client is set to 2. The server must respond (DONE) in version 2. The content of the "bulk" tokens (DOTI, DOTO, SERR, SOUT) are compressed using the LZO1X algorithm. The token parameter gives the length of the compressed form. As a special case, if the uncompressed form is zero bytes, then it is not compressed but rather sent directly as zero bytes. (Compression slightly expands a zero byte string.) The distcc client and server can handle either protocol 1 or 2 depending on whether the user configures compression on. distcc-3.4/doc/protocol-3-impl.txt000066400000000000000000000061261404653710500171110ustar00rootroot00000000000000A list of the important changes done to distcc to support protocol version 3. More or less in dataflow order. Does not include various little changes, such as a bug fix in argutil.c, and making functions from static into global, which happened all around the code. - A new protocol version (3) is added. It supports preprocessing on the server. It also transmits bulky data compressed, like protocol version 2. - distcc.h: Added the enum for where to do the cpp. - hosts.c: Map a set of features (currently a subset of where to do cpp and whether to do compression) onto a protocol number. - rpc.c: The client sometimes sends either a file or a link to the server. The server needs to be able to accept either, so dcc_r_sometoken_int introduces some alternation to the protocol. - Talking to the include server: - compile.c: dcc_build_somewhere tries to talk to the include server, and pushes the information about the .d file to dcc_compile_remote. This is where the fallback-to-the-original-protocol code lives. - include_server_if.c: Talk to the include server. - The communication from client to server. The client needs to send multiple files, and perhaps links, to the server; the client also needs to send its current working directory, - remote.c: Entry points for sending multiple files to the server. - rpc.c: The server needs to handle not only files, but also links (directories are handled implicitly). - clirpc.c: Added a function to send the current working directory. Added a function, dcc_x_many_files. It sends multiple files to the server. In addition, it changes the filenames to chop off the additions of the include server. - serve.c: Added a function to receive the current working directory. - On the server side: the server receives multiple files and the working directory, and builds a directory structure (which it keeps a manifest of, to clean it up at the end). - srvrpc.c: Added a function, dcc_r_many_files, to receive multiple files. In addition, it changes the filenames to put all the files under a "fake root" directory. - serve.c: lots of work to set up "fake root" directories, chdir to the right place, produce a .d file, and absolutize include directives. - tempfile.c: Creation of whole temp directories, not just files. - cleanup.c: Since we are receiving multiple files, we need to keep a dynamic list of what temporary files we create. Cleanup can now handle directories. - ".d" files: the client needs to find out where the dotd file should go; the server needs to produce it, remove all references to its (the server's) local filesystem (there are no gcc options to do this) and send it back to the client. - dotd.c: Most of the code that handles the dotd: figuring out if we need it, and where it should go; also, cleaning it up after it gets created on the server. - fix_debug_info.c: Rewrite an ELF .o file to refer to the client-side filenames. - clirpc.c Changed dcc_retrieve_results to retrieve the dotd file. distcc-3.4/doc/protocol-3.txt000066400000000000000000000045031404653710500161470ustar00rootroot00000000000000description of distcc protocol version 3 copyright (C) 2007 Google, Inc disclaimer ---------- This document is provided as explanation for people developing or debugging distcc. Discrepancies between this document and the distcc code are an error in the document. protocol -------- Protocol 3 is a significant extension to protocol 2. It is used to send not the preprocessed file, but enough information to do the preprocessing on the server. The low level protocol (connecting, responding, encoding of short strings, encoding of numbers, etc.) is the same as with protocols 1/2. Files are sent compressed, just as with protocol 2. The protocol number (DIST) sent by the client is set to 3. The server must respond (DONE) in version 3. request ------- Protocol version 3 introduces a alternation point, between LINK and FILE. Thus, in this version the tags are not purely decorative, as in the previous protocols. The following packets comprise the request: DIST Version is 3. CDIR The working directory on the client side. Sent just like any ARGV in protocol versions 1/2. ARGC Just like in protocol versions 1/2. ARGV Just like in protocol versions 1/2. NFIL How many files or links will be sent. Similar to ARGC. NAME The (absolute, crossing-no-symlinks) name of the next file or link to be sent. Similar to any ARGV. FILE The contents of the file. Similar to DOTI in protocol version 2. LINK The contents of the link (i.e., the filename pointed to by the link). Similar to any ARGV. response -------- Exactly as for protocol version 2, but with the following addition at the end. DOTD The contents of the result .d file. Similar to DOTO. Notes ----- This protocol is most useful in conjunction with an "include server" that discovers, for each compilation unit, the list of needed files without actually preprocessing. The protocol for talking to the include server is simple: distcc sends a CDIR packet, and an ARGC/ARGV sequence with the command line, and receives an ARGC/ARGV sequence with the needed files. Ideally, compression of files should be independent of whether preprocessing happens on the server or on the client. That's not currently true though. distcc-3.4/doc/protocol-gssapi.txt000066400000000000000000000052231404653710500172730ustar00rootroot00000000000000description of distcc GSS-API mutual authentication protocol copyright (C) 2009 CERN disclaimer ---------- This document is provided as explanation for people developing or debugging distcc. Discrepancies between this document and the distcc code are an error in the document. protocol -------- This protocol exists independently of, and occupies a logical position beneath, all existing distcc protocols. Due to this fact it should remain compatible with all future version of the distcc protocol. Mutual authentication transpires after the network connection is established between the client and server and the clients IP address has been evaluated, but before the client transmits a request. control flow overview --------------------- The overall structure of the protocol is very simple: 1: The client attempts a handshake with the server. 2: The server responds with a handshake with the client. 3: The client and server attempt to establish a secure context using the GSS-API framework by exchanging an unspecified number of GSS-API tokens. 4: After successfully establishing the secure context distcc and distccd function as per the higher level distcc protocol. handshake --------- A client wishing to perform mutual authentication attempts a handshake with the server by sending an * (asterisk) character. A mutually authenticating server responds by sending back an * (asterisk) character. GSS-API context and tokens --------------------------- Applications utilising the GSS-API are required to exchange tokens, tokens are opaque to applications and consist of the length of the token, and the token data itself. distcc and distccd now exchange context-level tokens when establishing a secure context. The underlying mechanism can require several token exchanges before a secure context is established. When transmitting tokens to the peer both distcc and distccd first transmit the token length, followed by the token itself, as per the following packet specification. TLEN Non-authenticating clients and authenticating servers ----------------------------------------------------- An authenticating server expects the first character it receives from the client to be the handshake character. A non-authenticating client will not transmit this character which will cause the server to disconnect. Authenticating clients and non-authenticating servers ----------------------------------------------------- An authenticating client expects to receive the handshake character from the server. If this is not received within a predefined time period the client will timeout, close the connection, and try to compile locally. distcc-3.4/doc/reporting-bugs.txt000066400000000000000000000060541404653710500171200ustar00rootroot00000000000000How to report bugs in distcc -*- indented-text -*- If you are having trouble with distcc, please send email to distcc@lists.samba.org. Please don't send mail direct to the author: if you use the list, other people may be able to help you faster and the answers are archived to help others. * The first aim of a bug report is to let the programmer see the failure with their own eyes. If you can't be with them to make it fail in front of them, give them detailed instructions so that they can make it fail for themselves. * In case the first aim doesn't succeed, and the programmer can't see it failing themselves, the second aim of a bug report is to describe what went wrong. Describe everything in detail. State what you saw, and also state what you expected to see. Write down the error messages, especially if they have numbers in. * By all means try to diagnose the fault yourself if you think you can, but if you do, you should still report the symptoms as well. * Write clearly. Say what you mean, and make sure it can't be misinterpreted. * Above all, be precise. A good bug report for distcc should include these details: * What version of distcc you're using, e.g. "2.7.1". If you got it from a distribution package rather than building from source, please say so. * Your platform (e.g. "Red Hat 8.0", "HP-UX 11.11") and compiler "gcc 3.3" * What you're trying to do: e.g. "install distcc", "build Mozilla", "build my own program". * What went wrong: e.g. did you get an error message, did it hang, did it build a program that didn't work, did it not distribute compilation to machines that ought to get it? You'd be surprised how many people don't say what actually happened. * If you have an example of a compiler invocation that failed, quote it, e.g.: distcc gcc -DHAVE_CONFIG_H -D_GNU_SOURCE -I./src \ "-DSYSCONFDIR=\"/etc/\"" -I./lzo -g -O2 -W -Wall -W \ -Wimplicit -Wshadow -Wpointer-arith -Wcast-align \ -Wwrite-strings -Waggregate-return -Wstrict-prototypes \ -Wmissing-prototypes -Wnested-externs -o src/clirpc.o \ -c src/clirpc.c * Turn on client and server error logging. On the client, set these environment variables, and try to reproduce the problem: export DISTCC_VERBOSE=1 DISTCC_LOG=/tmp/distcc.log Start the server with the --verbose option. If the problem is intermittent, leave logging enabled and then pull out the lines from the log file when the problem recurs. * If you got an error message on stderr, quote that error exactly. Find the lines in the log files pertaining to the compile, and include all of them in your report, by looking at the process ID in square brackets. If you can't work that out, quote the last few hundred lines leading up to the failure. An error report with all the necessary details is often answered and resolved within two days or less. If you don't include enough information to know what is going wrong it can take much longer. distcc-3.4/doc/status-1.txt000066400000000000000000000032601404653710500156260ustar00rootroot00000000000000description of distcc status indicators, version 1 Copyright (C) 2003 by Martin Pool purpose ------- This file describes a mooted design for a mechanism for distcc to indicate its status for the benefit of a separate display program. This is an external protocol so that there can be different implementations of status monitors to suit different purposes. The protocol is supposed to stay stable for some time to allow people to write their own monitors. interface --------- The programming interface to this is through the functions in mon.c/mon.h. Monitor applications should not access the files directly. state ----- The state of a compiler process is described in a few variables cpid Process ID of the client state String describing its progress in compilation file Short source filename host Host definition being used File or host may be empty strings if they are not yet known. states ------ The following states are defined. The list may change in later releases. In 2.6 the client progresses through these states in order, although not all states may be reached by any particular process. Startup Examining command line, host definition and other settings, and finding a host to use. Starved Waiting because all defined hosts are completely busy. Connect Opening a TCP or SSH connection to the host and sending the first part of the request. Preprocessor Waiting for the preprocessor to complete. Send Sending the preprocessed source. Compile Waiting for a local or remote compiler to complete. Receive Receiving compilation results. distcc-3.4/doc/web/000077500000000000000000000000001404653710500141605ustar00rootroot00000000000000distcc-3.4/doc/web/benchmark.html000066400000000000000000000257551404653710500170160ustar00rootroot00000000000000 benchmark results for distcc

benchmark results for distcc

The following table shows the effect of distcc on several real-world compilation tasks; in this case, compiling various open-source projects. In each case, we compiled in four modes:

  1. local_01: all compilation done locally
  2. dist_h38_j40: using distcc with 38 compilation servers (152 CPUs), and make -j40, which gives 40 parallel compilations. distcc is used in non-pump mode (local preprocessing).
  3. pump_h38_j40: like dist_h38_j40, but using distcc in pump (remote preprocessing) mode.
  4. pump_h38_j80: like pump_h38_j40, but using make -j80 instead of make -j40.

The client machine is an 2.8GHz Intel Pentium 4 machine, with 2G of memory, running Linux 2.6.18.5 (modified Ubuntu 6.06). The server machines were all 4 CPU 2GHz AMD Dual Core Processor 270 machines, with 2G of memory, running Linux 2.6.18.5 (modified Ubuntu 6.06).

Each test was run 5 times. We report the average time over the 5 runs, as well as the standard deviation. In order to minimize disk caching effects on walltime results, we read all the files in each project's tarball before building.

Projectmode wall
time
std
dev
cpu
time
cpu
%

binutils-2.18local_01 125.8s 4.0s 102.9s 81.9%
binutils-2.18dist_h38_j40 35.4s 1.0s 25.6s 72.2%
binutils-2.18pump_h38_j40 28.7s 1.5s 16.6s 57.7%
binutils-2.18pump_h38_j80 29.8s 1.5s 16.6s 55.9%

glibc-2.6 local_01 946.4s 5.1s 568.7s 60.1%
glibc-2.6 dist_h38_j40 534.0s 7.0s 390.5s 74.7%
glibc-2.6 pump_h38_j40 357.8s 6.5s 241.6s 67.5%
glibc-2.6 pump_h38_j80 365.4s 4.2s 243.0s 66.6%

hello-2.1.1 local_01 0.7s 0.1s 0.4s 62.8%
hello-2.1.1 dist_h38_j40 0.9s 0.2s 0.3s 40.3%
hello-2.1.1 pump_h38_j40 1.1s 0.1s 0.4s 31.3%
hello-2.1.1 pump_h38_j80 1.1s 0.0s 0.4s 31.6%

httpd-2.0.43local_01 139.8s 1.4s 117.2s 83.9%
httpd-2.0.43dist_h38_j40 85.1s 2.1s 51.3s 60.4%
httpd-2.0.43pump_h38_j40 80.1s 2.0s 33.7s 42.1%
httpd-2.0.43pump_h38_j80 81.7s 4.1s 33.7s 41.4%

linux-2.6.25local_01 818.3s 7.9s 543.9s 66.5%
linux-2.6.25dist_h38_j40 203.2s 1.7s 185.3s 91.2%
linux-2.6.25pump_h38_j40 134.9s 5.3s 96.5s 71.6%
linux-2.6.25pump_h38_j80 135.6s 4.3s 97.7s 72.1%

samba-3.0.20local_01 314.0s 2.4s 258.8s 82.4%
samba-3.0.20dist_h38_j40 101.8s 0.6s 94.0s 92.3%
samba-3.0.20pump_h38_j40 31.4s 2.4s 21.1s 67.4%
samba-3.0.20pump_h38_j80 31.8s 1.7s 21.2s 66.9%

Discussion

  • For all but the smallest projects, distcc results in a significant speedup in compilation time over compiling locally. This is because distcc is able to compile many source files in parallel. Such parallelism may not possible for small projects such as hello, which involves four small compilations.

  • In almost all cases, distcc's new pump mode results in a significant speedup in compilation time over non-pump mode. Sometimes, as for Samba 3.0, the speedup is more than a factor of three!

  • The parallelism of the various projects' Makefiles affects the obtained speedup significantly. Makefiles that run make sequentially in subdirectories benefit less from distcc. They will see little added benefit from distcc's pump mode because the sequentiality of their execution allows only some, but not many, compilations to be issued near simultaneously.

  • All these opensource projects are built by running configure plus make. In each case, we count only the make time, not the configure time. However, projects such as binutils run extra configuration during the make step (for binutils, the initial configure run is trivial, and the make command does more intensive configuration in various subdirectories before building). This will affect times as described above -- especially reducing the benefit of pump mode -- since the configuration steps are not run in parallel.

  • Even when pump mode does not speed up the build much, as for httpd, it still reduces the CPU burden on the local machine, making it more usable during compiles. Note, however, that this is balanced by an increased CPU burden on the server machines (about 10% in our tests), and may also require more memory on the host machine than non-pump mode does.

  • With a multi-processor client machine, the speed-ups would have been less, both for non-pump distcc over local compilation as for distcc-pump over non-pump distcc. Still, with four-processor client machines, distcc's pump-mode is up to 2 1/2 times faster than its non-pump mode for large projects benchmarked at Google.

  • As a side note, while collecting benchmark results, we found sometimes that pump mode did not give the expected speedup. On analyzing the logs, we discovered the reason: that distcc had encountered an error running the test in pump mode, and had fallen back to plain distcc mode. This can happen for several reasons. For example, the Linux kernel needed special attention because it rewrites header files during the build.

Copyright © 2008 Google Inc.
distcc is a trademark of Martin Pool.

Send comments to distcc(at)lists.samba.org. distcc-3.4/doc/web/compared.html000066400000000000000000000227101404653710500166420ustar00rootroot00000000000000 distcc compared to other systems

distcc compared to other systems

Summary

The main advantages of distcc compared to other tools are:

  • distcc is free software under the GNU GPL.
  • distcc is simple to install and configure.
  • distcc can be installed by a non-root user, without requiring a kernel patch or any change to installed software or filesystems.
  • distcc has very little impact on machines helping with the build.
  • distcc doesn't require a shared filesystem.
  • distcc can optionally use strongly encrypted and authenticated ssh channels for communication. In this mode it is safe to use on untrusted networks.
  • distcc can use machines with different processor architectures (i386, ppc, ...) or operating systems (Cygwin, Linux, BSD), if appropriate cross-compilers are installed. distcc runs on many operating systems and architectures.
  • distcc works reasonably even over wireless networks, when the LZO compression option is turned on.

The disadvantages of distcc are:

  • distcc requires that the same compiler version be installed on all participating machines. (Every other distributed build system requires this too.)
  • Only C/C++/ObjC/ObjC++ compilation can be distributed, not linking or other tasks. (Some clustering systems can distribute any task.)
  • distcc comes with no warranty (as does most software), though it has been successfully used by many people for many years.

OpenMOSIX

OpenMOSIX is a kernel-level single-image clustering system for Linux. It can be used to spread software builds or any other parallel task across multiple machines.

OpenMOSIX requires a kernel patch. All the machines must be of the same architecture and running similar kernels.

MOSIX and OpenMOSIX give you essentially a "single system image" cluster, which looks like a fast computer. distcc just looks like a fast compiler.

Some people have reported that distcc is much faster than OpenMOSIX for software builds in some situations. Short-lived, CPU-intensive compiler processes may be a very difficult load for a design based on process migration.

Other differences:

  • You don't need root to install distcc
  • Installing distcc doesn't require a kernel patch or reboot; presumably it can't destabilize anything else on the machine.
  • distcc copes reasonably gracefully if a machine goes away abruptly or the network goes down; it will just keep compiling locally.
  • distcc works (at least in theory) on any POSIX-like operating system, not just Linux, and on any processor. It has been reported to work on Linux, FreeBSD, HP-UX, Solaris, AIX and Cygwin, and you can spread load across machines using different systems. OpenMOSIX works only on Linux, and (perhaps?) only on x86 and IA-64.
  • distcc volunteers can have different processor architectures or even operating systems to the machines they're serving. (You do need to install a cross compiler though.)
  • distcc is only about 13000 lines of C, so you may find it easier to hack or patch.

Barnowl writes:

Currently openMosix (oM) only runs on Linux and currently only on x86 and IA64 arch. distcc works like a champ when used combined with oM. While oM does help some with short run jobs, its forte is big computation jobs so it works better for things like video edits or DNA decoding. If you just want to speed up C compiles with out a lot of work or custom kernels distcc is the way to go.

Cook

Cook is a Make replacement written by Peter Miller and distributed under the GNU GPL. Cook can do parallel builds and has built-in support for distributing builds across machines on a LAN.

Using Cook requires you to convert your Makefiles to a cookbook, though there is a make2cook program to help with this.

Cook runs commands over rsh by default, but it seems like you could use ssh instead. Cook uses rup to calculate load on different machines.

It seems like Cook requires a shared filesystem and the same tools on all machines. There is a mechanism to group machines into classes and run particular commands on particular classes of machine.

pvmgmake

pvmgmake is a fork of GNU Make which can spread tasks across multiple machines using the PVM protocol.

pvmgmake requires that all the machines see the same filesystem, and have the same tools installed.

XCode

Apple XCode Distributed Build is based on distcc.

Apple add patches for Rendezvous-based discovery of servers and transport of precompiled headers. These features may come back into the mainstream distribution in the future. Apple also add GUI to configure distcc, and support for some Apple-specific gcc features.

Apple's tools only work on Mac OS X.

The Apple version at the moment does not seem to support LZO or SSH.

Copyright © 2002–2004 Martin Pool. distcc is a trademark of Martin Pool.

Send comments to distcc(at)lists.samba.org, or talk to us on #distcc on irc.oftc.net.

distcc-3.4/doc/web/compilers.html000066400000000000000000000137471404653710500170570ustar00rootroot00000000000000 supported compilers

supported compilers

gcc
The main focus of distcc is GCC, the Free GNU C Compiler.

Compilation of C, C++, Objective C and Objective C++ can be distributed by distcc. All recent versions (from 2.9 up) should work. This includes versions of gcc distributed in development kits from various vendors, including those for the Sony Playstation and Apple OS X.

Other languages supported by the GNU compiler collection such as Java, Ada and FORTRAN are not supported because their compilation process is very different.

icc
icc is a proprietary C/C++ compiler for i386 and ia64 from Intel. icc is claimed to be source, object and command-line compatible with gcc and so should work with distcc. (However, some people have reported bugs in particular versions of icc that cause problems with distcc.)

Sun CC
Sun's proprietary C compiler is reported to work with distcc in C mode. It appears that Sun CC cannot compile C++ templates correctly when using a separate preprocessor, so it is generally not practical to compile C++ using Sun CC and distcc.

Microsoft C
There is experimental support for Microsoft's compiler using a wrapper, wrapmsvc.exe, that makes it behave like gcc.

For all compilers it is very important to have the same version installed on all machines participating in the build.

The main feature required by distcc is that the compiler must be able to run the preprocessor separately, and then compile the preprocessor output from a file. This was a basic part of the original design of C, but some compilers seem to have lost the ability to do this. However, this feature is not required if you use distcc's "pump" mode.

Secondarily, distcc is currently hardcoded to suit gcc's behaviour and command-line syntax, so only compilers that act like gcc will work. This could in principle be changed.

If you want to report results with any of these compilers or information on a new compiler please send mail to distcc at lists.samba.org.

Copyright © 2002–2004 Martin Pool. distcc is a trademark of Martin Pool.

Send comments to distcc(at)lists.samba.org, or talk to us on #distcc on irc.oftc.net.

distcc-3.4/doc/web/distcc-green.css000066400000000000000000000022221404653710500172370ustar00rootroot00000000000000BODY { font-family: verdana, arial, helvetica, "Lucida Sans", sans-serif; color: black; background-color: white; margin: 1em; padding: 0; font-size: 12pt; } TT { font-family: monospace; color: #002200; } .bold { font-weight: bold; } a { color: #003300; } a:hover { color: #336633; } div.caption { font-size: 80%; text-align: center; } div.navbar { background-color: #ffffee; padding: 1em; border-width: 1px; border-style: solid; border-color: #888; font-size: smaller; } .navbar UL { list-style-type: none; padding-left: 0; margin-left: 0; line-height: 1.3; } .navbar UL LI { padding-left: 0; margin-left: 0; } .navbar UL UL { font-weight: normal; padding-left: 10px; margin-left: 0; } .body { line-height: 1.3; padding: 1em; } .navbar A { color: #030; text-decoration: none; } .title { font-weight: bold; color: #003300; vertical-align: bottom; } .banner { margin-top: 30px; margin-left: auto; margin-right: auto; text-align: center; } UL { list-style-type: square } blockquote.quoted { color: #222; } BLOCKQUOTE { margin-left: 4em; } DIV.thanks { font-size: small; color: #222; }distcc-3.4/doc/web/distcc-lca-2004.html000066400000000000000000001172561404653710500174530ustar00rootroot00000000000000 distcc, a fast free distributed compiler

distcc, a fast free distributed compiler

Date: December 2003
Author: Martin Pool <mbp@sourcefrog.net>
Presented at:linux.conf.au, Adelaide, 2004
Licence:Verbatim reproduction of this paper is permitted.
HTML at:.../distcc-lca-2004.html
PDF at:.../distcc-lca-2004.pdf

1   Abstract

distcc is a program to distribute compilation of C, C++, Objective C and Objective C++ code between several machines on a network. distcc is easy to set up, and can build software projects several times faster than local compilation. It is distributed under the GNU General Public License.

distcc does not require all machines to share a filesystem, have synchronised clocks, or to have the same libraries or header files installed. They can even have different processors or operating systems, if cross-compilers are installed.

This paper begins with some background information on compilation and prior distributed compilers, then describes the design of distcc, presents the outcomes and some applications, and some lessons learned that may be useful to other small free software projects.

2   Background

It is common for a software developer to have access to more than one computer. Perhaps they have a laptop and also a desktop machine, or perhaps they work in a group where each member has a workstation. It would be nice if the spare computing power could be used to speed up software builds.

distcc offers a straightforward solution. The distccd server runs on all the machines, with a low priority and a cap on the number of processes. Any client can distribute compilation jobs onto other machines. distcc can be installed by any user, without needing root access or system-wide changes.

Faster compilations allows "clobber" builds (make clean; make all) to be run more frequently, which can catch bugs that might be hidden by incorrect Makefile dependencies. It allows test engineers to get builds to test faster. It makes nightly, or hourly check builds more feasible, so bugs that are checked in can be caught and fixed with less disruption. In general it removes one limitation from the developer's work flow and allows them to work the way they want.

The ability to build quickly is particularly useful when building binary software packages with dpkg or rpm. These tools often want to build the whole tree from scratch so as to ensure a repeatable build. Using distcc and ccache makes repeated package builds faster.

Fast distributed builds are also useful for operating systems distributed primarily in source form, such as Gentoo and Linux From Scratch.

2.1   Previous work

There have been several prior distributed build systems, including pvmmake, doozer, and dmake. These systems typically require the build directory to be on a networked filesystem shared between all machines participating in the build. Furthermore, each machines must have the same header files and libraries installed. If one of the header files is inconsistent, it can, at best, produce confusing error messages, and at worst, it can cause unpredictable crashes when different modules see different definitions. All of the machine clocks must be tightly synchronized so that the timestamps are accurate.

This can be reasonable for a dedicated build cluster, but is less practical in ad-hoc networks, where users may be able to upgrade libraries on their machines at random, or where using NFS may not be desirable.

Another approach is to use kernel-level clustering such as OpenMOSIX. This allows any parallel tasks to be distributed, but introduces very tight coupling between machines. Systems based on process migration may not perform well with the many short-lived processes generated during compilation.

2.2   C compilation

It's worthwhile to briefly discuss how C programs are built. Typically, a build tool (such as Make) invokes the C compiler for each source file to produce an object file. Within this compilation, there are several steps.

  • The source is run through the cpp preprocessor, which folds in header files, handles #ifdef and other directives, and produces a single preprocessed output file.
  • The compiler proper cc1 reads the preprocessed source and produces assembly output.
  • The assembler as reads the assembly text and produces an object file.

One interesting property of the C build process is that the preprocessed text plus the compiler command line completely specifies the output. By running the preprocessor locally, distcc avoids any requirement to have the same headers on all machines.

Before distcc, the compilercache and ccache programs used this observation to remember the results of building a particular source file. This can be useful when trees are cleaned and rebuilt, or when similar trees are built in different directories.

Using GNU make's -j option several jobs are run in parallel. Make uses its graph of dependencies between targets to make sure that only independent jobs are run in parallel -- or at least it does if the Makefile correctly specifies dependencies.

Although sending a file across a network takes a relatively long time, it takes few CPU cycles. On Linux and BSD, distcc uses the sendfile system call so that transmission of the preprocessed source from the client is done in a single system call.

3   Design

distcc distributes work from a client machine to any number of volunteer machines. (Since this is free software, we prefer the term volunteer to the slaves that are used by other systems.)

distcc consists of a client program and a server. The client analyzes the command run, and for jobs that can be distributed it chooses a host, runs the preprocessor, sends the request across the network and reports the results. The server accepts and handles requests containing command lines and source code and responds with object code or error messages.

3.1   Simulating gcc

The client is invoked as a wrapper around the compiler by Make. Because distcc is invoked in place of gcc, it needs to understand every pattern of command line invocations. If the arguments are such that the compilation can be run remotely, distcc forms two new sets of arguments, one to run the preprocessor locally, and one to run the. compiler remotely. If the arguments are not understood by distcc, it takes the safe default of running the command locally. Options that read or write additional local files such assembly listings or profiler tables are run locally

For commands that need to be run locally, distcc runs the compiler locally, avoiding the overhead of the network protocol and of separately running the compiler. Early versions of distcc directly replaced their process with the local compiler using exec, but in current releases the compiler is run as a child process so that its progress can be monitored. Some cases are difficult because the precise meaning of some options such as -MD has changed between versions of gcc.

The client supports a "masquerade" mode, where a directory such as /usr/lib/distcc is filled with symbolic links which have the same name as the real compiler, but point to the distcc client. This directory is prepended to $PATH, so that when Make executes gcc, it really invokes distcc. distcc specially handles this case to work out the correct real compiler to invoke, and guards against inadvertently running itself recursively. Masquerade mode allows distcc to be used with most existing source trees without the need to change the Makefile or build process.

3.2   Networking

The server runs on each of the volunteer machines, either as a standalone daemon, through inetd or indirectly through sshd. distcc normally runs on TCP port 3632.

distcc uses a simple custom binary network protocol to encode requests and responses. Variable-length fields are preceded by a length word, allowing a very simple and efficient implementation.

The request includes a protocol version, the compiler command-line arguments, and the preprocessed source. The response from the server includes confirmation of the version, the compiler's exit code, any errors or warnings from the compiler, and the object file if any.

The distcc protocol includes four-letter magic words before each element. These words are not strictly necessary because the order of elements is always the same, but they make it easier to scan network dumps, and provide a protection against networking or program errors.

distcc relies on TCP or SSH to ensure integrity of the stream and does not have a checksum of its own. This is the same level of protection as HTTP or NFS, and no failures have been reported to date.

3.3   Scheduler

distcc uses a basic load-balancing algorithm to choose a volunteer to run each particular job. Scheduling is managed by small state files kept in each user's home directory. In addition, each server imposes a limit on the number of jobs which will be accepted at any time. This prevents any single server being overloaded, and provides basic coordination over servers being used by several clients. By default, the limit on the number of jobs is set to two greater than the number of processors in the server, to allow for up to two jobs being in transit across the network at any time.

The server uses a pre-forking design similar to Apache: the maximum number of client processes are forked at startup, and all of them wait to accept connections from a client. This puts a limit on concurrency, and slightly reduces the latency of accepting a new connection.

Clients keep a temporary note of machines which are unreachable or failing. These notes time out after sixty seconds, so machines which reboot or are temporarily unreachable will shortly rejoin the cluster. Machines which are abruptly terminated or shut down while running jobs may cause those particular compilations to fail, which can normally be addressed by re-running Make. If distccd is gracefully terminated it will complete any running jobs and decline future submissions.

Client processes are coordinated by Unix lock files held in ~/.distcc. flocks have the strong advantage that they are always released by the kernel when the process terminates, even if it aborts because of a signal.

As with a kernel scheduler, distcc does not have enough information about future jobs to make perfect scheduling decisions. In particular, make does not communicate the global state of the build and how many jobs will be issued in the future. All distcc knows is the number of jobs are running at the present moment. If it knew about future load, it might schedule jobs in the middle of a build differently from the last few jobs. Jobs on the critical path of the build and, in particular, the last jobs of a build ought to be scheduled for minimum delay rather than maximum throughput, which might mean running them locally rather than remotely.

At the moment the client does not maintain an estimate of the speed of volunteer machines. Estimating this accurately is difficult because the performance depends on the source and computer in a complex way. Different files of similar size can take very different times to compile depending on the difficulty of the code.

The primary shortcoming of the current scheduler is that adding slow machines to a build farm can reduce the overall performance. There is a significant opportunity cost to waiting for a job that on such a slow machine, particularly if it is a dependency for Make to proceed.

3.4   SSH

distcc has the option of using a helper program such as ssh to open connections rather than simply opening a TCP socket.

When OpenSSH is used to open connections, all data is strongly encrypted. The volunteer machines do not need any additional listening ports or long-running processes. All remote compilations run under the account of the user that initiated them.

Using OpenSSH or another pluggable connection method is a powerful Unix design pattern. Just a few hundred lines in distcc to fork the connection program and open pipes allows it to use world-class encryption and authentication that easily integrates into existing networks.

A key advantage of this pattern is that distcc's security exposure is very small. Any connection that reaches distcc is by definition authorized either by ssh opening the socket, or because the administrator allowed connections from that address. Most of the distcc code can therefore be quite trusting of the requests that are received.

If someone wanted to implement a simpler transport that did challenge-response password authentication but not encryption, then they could plug it in through the DISTCC_SSH variable without needing any changes to distcc itself.

3.5   LZO compression

distcc can use the LZO fast compressor to compress requests and replies. This option is explicitly set by the client in the host list.

The preprocessed source is typically very gassy because of long runs of whitespace and repeated identifiers, and compresses well. Object files also compress moderately well.

Compression improves throughput when the network is the limiting factor. This can be the case when the network is very slow, such as a 10Mbps wired network or a wireless network. Compression can also be useful when there are many remote machines, which can saturate even a fast Ethernet connection.

4   Outcomes and applications

4.1   A performance model

The goal of distcc is to reduce the overall elapsed time to build or refresh a complete tree.

Performance is predicted by the network bandwidth, the time to run the preprocessor and the compiler, the relative speeds of the client and volunteer computers, and the overhead of the distcc client and server. The speed of compilation on a particular machine depends on available memory, contention for the CPU, and the speed of the CPU, RAM, and bus.

In many cases other aspects of the build process become the limiting factor once compilation is parallelized. For small packages, running an autoconf script is much slower than actually compiling the package. Make can also be a limiting factor, because it has high overheads and cannot schedule efficiently across source directories. One user found that distcc alone doubled build speed, but switching to the SCons construction tool in combination with distcc gave a five-fold improvement.

4.2   Estimate of feasibility

Before any code was written for distcc, the author did a brief feasibility study to see if the idea was practical. This involved measuring the elapsed and CPU time for some of the basic operations: running the preprocessor and the compiler together and separately, copying a file across the network, and starting a simple wrapper program. The compiler used 90% or more of the CPU time in most trials. This indicated that the bulk of compilation could in theory be run remotely, and distcc might win when more than one machine was available.

Feasibility studies such as this are heartily recommended before starting a project, especially one where success depends on achieving a quantifiable result. Knowing that a concept ought to work can be a worthwhile spur to writing a good implementation that achieves the predicted result. Conversely, knowing that an idea is impractical can avoid sinking time or money into a project that can never win. (It might still be worth documenting your results in a web page or email, in case the situation changes in the future or somebody else can think of an improvement.)

4.3   Is it safe?

In eighteen months of widespread use of distcc to build diverse source trees, there have been no reported unexplained failures. Bug reports are due to, in order of frequency:

  1. Mismatched compiler versions or broken compiler installations.
  2. Concurrency bugs in a makefile or other build process.
  3. Known bugs in gcc or other software that are provoked by distcc.

One persistent problem has occurred because of a quirk in the way gcc produces debug information. The compiler's working directory is inserted into the debug stabs to help in finding the source for the program. This is a problem for distcc and ccache because the compiler is invoked in a different directory from the preprocessor. This should be fixed in an upcoming gcc release by including the compilation directory in the preprocessor output.

4.4   Scalability

Reports from users indicate, distcc is nearly linearly scalable for small numbers of CPUs. Compiling across three identical machines is typically 2.5 to 2.8 times faster than local compilation. Builds across sixteen machines have been reported at over ten times faster than a local builds. These numbers include the overhead of distcc and Make, and the time for non-parallel or non-distributed tasks.

Amdahl's law states that the possible speedup from parallelizing a task is limited by the reciprocal of the fraction of a task which must be serialized. distcc is able to parallelize the compilation phase, but execution of the makefile, preprocessing, linking, and the distcc client must all be local. The balance of these tasks for a particular source tree determines how much it will benefit from using distcc.

Performance tends to plateau between ten and twenty machines. This is consistent with measurements of the preprocessor using roughly 5-10% of the total CPU time: when twenty preprocessors and distcc clients are running, the client is completely saturated and cannot issue any more jobs.

Lack of access to a large test lab has so far prevented a systematic exploration of the limits of scalability.

4.5   Compiler versions

Incompatibilities between different releases of gcc proved to be a more serious problem than was expected.

It turns out that it is not even sufficient to check the gcc version string. Across different Linux distributions, two gcc binaries claiming to be the same version can have incompatible APIs, because of distributors merging or backporting different patches. gcc is not necessarily compatible across different BSD forks.

In general C++ causes more trouble than C because the ABI is more complex and has been more unstable.

Incompatibilities typically manifest either as errors reading system headers which depend on gcc internals, or as link errors. In the absence of a satisfactory way to check compatibility, for the moment we just advise people to check compiler versions if an error occurs. Some automatic checking may be added in a future version.

4.6   Makefile bugs

Because distcc can use CPUs on more than one machine, it is common to use much higher -j levels than for local builds, with ten or even twenty jobs in flight at once. This will sometimes uncover dormant concurrency bugs in Makefiles.

For example, a source file may depend on an automatically generated header, but that dependency may not actually be specified in the Makefile. For a non-parallel build, Make might happen to run the rules in such a way that the header is always generated first. When many concurrent tasks are run, the compile may start earlier and then fail because the header is not yet ready. As with threading bugs, these failures can be intermittent and hard to track to a root cause. Make's --debug will eventually explain the problem after enough scrutiny.

Some large packages such as XFree86 have stubborn Makefile bugs and must be built without parallelism. Concurrency bugs have also been discovered in tools such as libtool that are called from makefiles. Another source tree used a single temporary file name for all object files, so that they overwrote each other when run in parallel.

4.7   Lifting compilation

distcc can be useful even without parallel builds. It is fairly common for a developer to be working on a relatively slower machine: perhaps on a laptop, or an embedded system, or perhaps a large server machine is available. It is quite possible for the benefit in running on a faster CPU to be greater than the overhead of running distcc and transferring the build across the network.

Being able to do most of the work of compilation remotely makes it feasible to do development entirely on embedded platforms that are large enough to run an editor and linker, such as the Sharp Zaurus.

distcc support sociable computing by making it possible to do development on quite large projects from a laptop, if compilation is lifted off to one or more larger and noisier servers in another room.

4.8   Security

distcc is intended to be quite secure when used according to the documentation.

Remote execution of compile jobs introduces a trust relationship between the client and server machines. The client completely trusts the server to compile code correctly. A corrupt server could introduce malicious code into the results, or attack the client in other ways. The server completely trusts an authorized client. A malicious client could execute arbitrary commands on the server.

The distccd TCP server does not run as root. If started by root, before accepting connections it gives away its privileges and changes to either the distcc or nobody user, or to a user specified by the --user option.

The distcc client may be run as root. Compiling or doing other unnecessary work as root is generally discouraged on Unix, but distcc permits it because some build processes require it.

In TCP mode network transmissions are not encrypted or signed. An attacker with passive access to the network traffic can see the source or object code. An attacker with active access can modify the source or object code, or execute arbitrary commands on the server.

The TCP server can limit clients by either checking the client address, or listening only on particular IP interfaces. However, in some circumstances an attacker can spoof connections from a false address. On untrusted networks SSH is the only safe choice.

In SSH mode the server is started by each user under their own account on the server. There is no long-lived daemon. Connections are authenticated and encrypted. Every user is allowed only the privileges that their normal account allows.

Because the server and client necessarily trust each other, there has been no security audit of the code that runs after a connection is established. It is possible that a hostile server could gain control of a client directly, as well as modifying the object code.

Some people have proposed that the server should perform reasonableness checks on the command or source code submitted from clients. This is probably futile because gcc is not secure against hostile input, and it might be possible for an attacker to gain control of the gcc process through a carefully crafted input file or command line. The only safe assumption is that anyone able to submit jobs is able to execute arbitrary operations under the account used by distccd.

Alternatively it has been suggested that client should check whether a server is trustworthy by re-running compilations on a different server. This approach can be useful in some distributed-computing problem spaces such as SETI@home, but is not practical for distcc. Firstly, the damage from a single compromised object file is very high, so every single file would have to be extensively checked. Secondly, the performance constraints are such that building every single file two or more times would often make distribution worthless. Thirdly there would sometimes be false alerts from minor differences in gcc patchlevel that are not visible in normal use but that do change the output file at a byte level.

Only one security issue has arisen to date, which was that distcc used a predictable temporary directory name. A local attacker by creating that directory could cause distcc to fail, but no more damage.

4.9   distcc press-gangs

Systems have been developed which allow non-Unix machines to be co-opted to contribute to compilation.

One such is distccKNOPPIX, which allows a machine to be rebooted and to work as a compiler volunteer without needing any installation onto its hard disk. The compiler and distcc server are loaded across http, so that they can easily be matched to the versions on the client.

distcc packages are now available for Cygwin, allowing cross compilers to be run on Microsoft systems.

4.10   Good logging

Most releases of distcc has discovered bugs in either distcc or other software that could not be reproduced on the author's machine. It has the honour of helping find a serious bug in the Linux 2.5 TCP stack by being the first program to flood the network fast enough to provoke a timer wraparound.

At the default logging level, distcc emits only warnings and errors, such as when a compile host is unreachable or compilation fails.

When verbose logging is enabled, distcc reports the success or failure of most non-trivial system calls and internal functions. Failure can indicate either a problem on the machine, or a bug in distcc. In the first case, the logs can help the user find out where the problem is. If there was a bug in distcc, the trace helps work out where exactly the failure occurred, what actions led up to that point, and what the consequences were. Many of these bugs are at heart incorrect assumptions about, for example, how distcc will be called or how a system call behaves on different platforms. The trace often calls out which assumptions were incorrect.

The goal of distcc's error handling is to have any problem cause at most one failure. It ought to be possible to look at a verbose trace and work out what went wrong and the fix.

Errors and trace messages from the server are written both into a log file, and also into the compiler error stream passed back to the client. This makes it more likely that if a problem occurs on the server, it will be obvious to the remote user without their having to look in the server's log file. This pattern is very useful, though it might not be appropriate for software that handles requests from untrusted users. Errors during server startup are written to error output as well as to the log file, to make it more obvious to the administrator that the server did not actually start.

4.11   Generalisations

There has been some interest in adapting distcc to compile other languages such as Java or C#. These languages have quite different mappings from source files to output, and in particular there is no separate preprocessing phase. A Java compiler must read class files as directed by import statements, and those classes in turn may need to be rebuilt from source. A distributed compiler for these languages would be possible but might need to be more tightly integrated with the compiler than distcc is.

distcc could be generalised still further to distribute arbitrary non-interactive jobs, rather than just compilation. A good step towards this would be to move all the intelligence about command lines into the client, so that the server just managed temporary files and executed specified commands. To date no compelling application for this sort of distribution has presented. Scientific and technical computing users seem reasonably well served by clustering and batch-queueing software.

4.12   Changes in gcc

gcc version 3.3 includes some performance improvements that make distcc less immediately useful.

One is precompiled headers, whereby the internal state of the compiler is dumped out to disk after reading a set of common header files. This is useful for programs that include a large and fixed set of headers, where parsing the headers takes a large fraction of the compile time. At the moment distcc can support this by putting the .pch state file on a shared filesystem. A better solution may be added to distcc in the future.

gcc has also recently gained an integrated preprocessor option, to avoid the overhead of running the preprocessor as a separate task. Since distcc must run the preprocessor separately, it cannot benefit from the integrated preprocessor and it's performance compared to gcc is slightly worse.

4.13   Worse is better

distcc adheres to the "Worse is Better" philosophy, summarized by Richard Gabriel as four points:

  • Simplicity: the design must be simple, both in implementation and interface. It is more important for the implementation to be simple than the interface. Simplicity is the most important consideration in a design.

distcc does not require changes to the kernel, the build system, or the compiler. It can be described in a couple of pages, and installed in a matter of minutes. There is no central coordinating process or global knowledge of the cluster's state.

The most prominent place where the implementation is less simple than necesssary is in network IO, which is moderately optimized. This is perhaps justifiable as network speed is important to the program being useful.

Masquerading as gcc makes the implementation more complex, because distcc must identify that it is masqueraded, and then make appropriate adjustments to the path to invoke the real compiler. However, masquerading makes the installation and use of distcc much easier, and so it is a reasonable tradeoff. If it had turned out to be hard to find a reliable and reasonably simple masquerading algorithm, the feature might have been dropped.

distcc is written in C, which makes a correct implementation slightly harder and more complex than it would be in a scripting language. This is justified because to perform adequately, distcc absolutely must have a very small startup cost, which is not the case for any popular very-high-level language.

  • Correctness: the design must be correct in all observable aspects. It is slightly better to be simple than correct.

There are no known cases where distcc generates an incorrect and unexplained result. The edges cases such as debug information are being fixed in a simple manner, by correcting gcc, rather than by complicating distcc.

Almost all free software trees will build, with the restriction that trees with concurrency bugs cannot be built in parallel.

When distcc encounters an unexpected condition, it tries to "fail safe" by, for example, running the compilation locally, backing off from a particular machine and avoiding accidental recursive invocations.

  • Consistency: the design must not be overly inconsistent. Consistency can be sacrificed for simplicity in some cases, but it is better to drop those parts of the design that deal with less common circumstances than to introduce either implementational complexity or inconsistency.

Almost all the code in distcc is common across platforms, and most of the code is reached on any particular execution: there are relatively few special cases.

There are some special cases and inconsistencies in the way the daemon starts up, in an attempt to make it more friendly to administrators and as historical accidents.

distcc is very consistent with modern free Unix practice in details such as responding to --help, using the GNU autoconf system for installation, and installing into standard directories.

  • Completeness: the design must cover as many important situations as is practical. All reasonably expected cases should be covered. Completeness can be sacrificed in favor of any other quality. In fact, completeness must sacrificed whenever implementation simplicity is jeopardized. Consistency can be sacrificed to achieve completeness if simplicity is retained; especially worthless is consistency of interface.

distcc is intentionally not a general-purpose clustering system. They are too hard to write, and none that can be installed in a matter of minutes. distcc has very incomplete coverage of all the tasks people might want to distribute across machines, but it does handle a large task that is important to a significant audience.

Within the space of C compilation, most tasks can be distributed. Even if a few jobs during a software build cannot be distributed, others run in parallel might be, so there is still an overall benefit. distcc's documentation and diagnostic output make it reasonably easy to identify problem commands.

Some gcc options that could in practice be distributed are run locally for the sake of implementation simplicity. Commands that produce assembly listings are one example: there is no reason why the assembly output could not be relocated back to the client, but this option is rarely used so the complexity is not justified.

5   Conclusions

distcc has a simple design and gains large performance improvements for software builds. It is reliable and straightforward to install and manage.

A few maxims about demonstration of software projects have been borne out by distcc's development. Before development began, a feasibility study demonstrated that the concept could work. The design is intentionally simple and the scope modestly focused on a subset of important problems. Strong logging helps get useful results from distributed community testing. Performance features such as compression and new network APIs were used selectively in places where they are shown to increase distcc's speed.

As the world's body of source code continues to grow, distcc will help get it built, tested and released more quickly and painlessly.

distcc-3.4/doc/web/distcc-lca-2004.pdf000066400000000000000000003710301404653710500172500ustar00rootroot00000000000000%PDF-1.4 5 0 obj << /S /GoTo /D (abstract.0) >> endobj 8 0 obj (1 \040 Abstract) endobj 9 0 obj << /S /GoTo /D (background.0) >> endobj 12 0 obj (2 \040 Background) endobj 13 0 obj << /S /GoTo /D (previous-work.1) >> endobj 16 0 obj (2.1 \040 Previous work) endobj 17 0 obj << /S /GoTo /D (c-compilation.1) >> endobj 20 0 obj (2.2 \040 C compilation) endobj 21 0 obj << /S /GoTo /D (design.0) >> endobj 24 0 obj (3 \040 Design) endobj 25 0 obj << /S /GoTo /D (simulating-gcc.1) >> endobj 28 0 obj (3.1 \040 Simulating gcc) endobj 29 0 obj << /S /GoTo /D (networking.1) >> endobj 32 0 obj (3.2 \040 Networking) endobj 33 0 obj << /S /GoTo /D (scheduler.1) >> endobj 36 0 obj (3.3 \040 Scheduler) endobj 37 0 obj << /S /GoTo /D (ssh.1) >> endobj 40 0 obj (3.4 \040 SSH) endobj 41 0 obj << /S /GoTo /D (lzo-compression.1) >> endobj 44 0 obj (3.5 \040 LZO compression) endobj 45 0 obj << /S /GoTo /D (outcomes-and-applications.0) >> endobj 48 0 obj (4 \040 Outcomes and applications) endobj 49 0 obj << /S /GoTo /D (a-performance-model.1) >> endobj 52 0 obj (4.1 \040 A performance model) endobj 53 0 obj << /S /GoTo /D (estimate-of-feasibility.1) >> endobj 56 0 obj (4.2 \040 Estimate of feasibility) endobj 57 0 obj << /S /GoTo /D (is-it-safe.1) >> endobj 60 0 obj (4.3 \040 Is it safe?) endobj 61 0 obj << /S /GoTo /D (scalability.1) >> endobj 64 0 obj (4.4 \040 Scalability) endobj 65 0 obj << /S /GoTo /D (compiler-versions.1) >> endobj 68 0 obj (4.5 \040 Compiler versions) endobj 69 0 obj << /S /GoTo /D (makefile-bugs.1) >> endobj 72 0 obj (4.6 \040 Makefile bugs) endobj 73 0 obj << /S /GoTo /D (lifting-compilation.1) >> endobj 76 0 obj (4.7 \040 Lifting compilation) endobj 77 0 obj << /S /GoTo /D (security.1) >> endobj 80 0 obj (4.8 \040 Security) endobj 81 0 obj << /S /GoTo /D (distcc-press-gangs.1) >> endobj 84 0 obj (4.9 \040 distcc press-gangs) endobj 85 0 obj << /S /GoTo /D (good-logging.1) >> endobj 88 0 obj (4.10 \040 Good logging) endobj 89 0 obj << /S /GoTo /D (generalizations.1) >> endobj 92 0 obj (4.11 \040 Generalizations) endobj 93 0 obj << /S /GoTo /D (changes-in-gcc.1) >> endobj 96 0 obj (4.12 \040 Changes in gcc) endobj 97 0 obj << /S /GoTo /D (worse-is-better.1) >> endobj 100 0 obj (4.13 \040 Worse is better) endobj 101 0 obj << /S /GoTo /D (conclusions.1) >> endobj 104 0 obj (4.14 \040 Conclusions) endobj 105 0 obj << /S /GoTo /D [106 0 R /Fit ] >> endobj 108 0 obj << /Length 2871 /Filter /FlateDecode >> stream xÚYYã¸~Ÿ_aä%2v¤EIdv73˜ › ‚Þ¼dó@[l[Û:IžYÿûÔE‰>¦4ÐâQ¬*¿:H«M jSVQR%›"Ï¢"¯6ûîM¼9À̇7J(R•Gy…½“¡NuTé|yT(íÓÜѪ<‰â´Ø„9H³‰¿{zóí{UlT%*Û<=oT^DqRnÑSý¯ n¦y¿ß†*x» u¬ƒŸ$x6[L8>ËôGì[˸rlvçÙÖ<@\ ëNM ‹ýqûï§¿¼ùóÓ¢«Š³Hªy¬£²È_ߖІ1mK'›*ªrM»+ª8ßä Ø+V´«ÌlQð·ïË•0I£8O€3Rünf`µà§èžþwÛ¤ vÛþ[Ø­Ö:HâX3/_j(ÜBRÓ’x¾;ÏÇa¼“«sBºÊÕ•NƒA®ç¦g!Ÿ¶I¶C¹CË”ZYTe¤a‹Ìâ·&M²2J³ L 2A NŒ¡ø‡gTGzädTßT7Q,˜¦Ó¨àô'ጠ`Ë>†CÔ;ƒÎ·jê4b•_«yz¦¹SηÆ-#ÔîŽ(¶º:¢O£PÁ~«“`&=½¥Ì|wp¹Ž2­×ƒS… m`}09ÿ ­ˆQ»~ŽðLÏoùDßÕ¶5H[[IHÐM(*‚|EÿÚìm¿¿±."•ø`*³8øç6 ™QnÇRG{ÂAÆV¶çÓQA3ú†gþÎGxá wsºr…u*,رkfðþHv”nTÁÙ¸-Uº„­¢,a§T W%YðuœfOÌþ):³$†È—ý< qèQßÂù†ǽ%¾Aø»Q°‘$K¯¸MBóš\±7ƒ)_0ÙlŠqŒxb·MÇýyàéšN,4ΈTœe°A|…ÁŽ™Æé“<øÞrûþ›o¶Ò©‚¿CL˲à—%ÚÍÍgİðý^tB×<äVØ.늒¸³J‚,‚*ø\% BYkòŽwŒf¤_„ ¹a¨UÌç`?/ãXÓâÀØì1ð2{;ñ í[q²‚õ½uŒÁ¸ø%Ú†©.ÄŠî”iI#,H™.ÌÌ®væ:Ë ¨²Õ40¾7¢÷)š¶öv1`\µ1#[—ÆáʤY,¾²ÕDj±%F4AšflüŽf&y6ÓŒNI³hÔ;íâê$ƒ9¤ nH]Æ „®mXUðqæ¥âišß¯f.ç¾^Ó:lË‹>@óo?1¯¶wê§Á'´Ò®möö‹aùõÎ-EŒ$Uš^‘^{l˜ä ç°Bkâ!d4ÌÜíè€FË}ƒÖi¹}+Dàw:ºs£eüù9V)®gi—‰³G÷U¨ˆ‘Ács(Nò¨zŠ·"húehÓ$ÏødZÞ¾L€LN)‘P8 änWvâŠÎ‰N’¦“^Kç9š±qÇ8ñŠÒ 6aMm¥Ûmoèšå˜f¶¥$PÂRšÆÁÓÑ­¸0FaÏÏÃeäÎj(¥n@¶^ÐC›yžC&ƒœµ›\å9Þlhpù‹SbxärÞ‘í&=1ÕQJ”¢–(ÍN!EÏáªÄx‰Aœaz$Q˜¨•äøÎOGŠDeœŒË§Ü÷âåÁY+”/ ‚#MCG0’%ˆæ2x9ŒT’õ5“"†±sÙ†ù«E7¼#VC‹y™ç€h†¢‡{$ò÷¬#ó·ãD7Œj(£o–¸î1ÞÐÖqÃñ]t¬Ms5”ñäâÝ_*F[*Óæ‰9¬ÜR.\gÙ¿·„x ó ©A†'<ì†Á,•“Û¬z€«õ„­Tw¨€•Öšq)™kÆÜ|43¯êÈá/ÜYpëÎK y>sT£nàYô…ùèÊ6¢ëŽÜ¥JÝzº½š¸°Ü“2Ëý‚V=ªýÀ :0p8J¤êû]}¿Õœ®ôC51©Ü¹À!QQ)uãÇYÜŠL–!¬:1#?;ŒBÛðçõe€&8ípZMX8¯2߯ÅI”qÔÝ0 orR#º ý*ÔsÈ©#…Ìo~ (žpt—ˆºÑHq© (O3îÛk¡íV"#÷x͒ç—e‘ˆ0è¾’ˆMU\™÷Fj'Ú©½p‡ªºa|á5t¯]eAg‘ö)°. ³J¹hJH|d,SbÚ} è$CÄ]+›¼ˆ¹²‰]]HnRóÈâJ¸¾§[ôqz)k`l:Q\Ç&†}  $"dÓ ÈŸ«ÚÑQÞJ+™Ü'çê$iàïÄÈ ­üy*A¯lKpyö-Ð¡Š KR8ßÿ·”ÒÎUÎxO¯ˆ½˜ošÃ‘b*ûíÙŒµ -[gè#,t3ÈqrÕ™w)ªJz¯‰½÷§ûÆ„w!b“Ÿ‰QÚH‰nâ…ørŒƒx7:¾bâÊ#%S»dy¨± ¥åÞ’éHgÉ•™_Y"551ô׬ØÐ \xr&5xÑ“:öQ5ü’F8ÃotA÷qNs˜ÕHÄãÇ‘†e墨ˆ¨¶‘LÇ‹—š ;Þ ÈOÚ²ÒOÐ\"º÷÷˰PT9R$ \ê­Ù|ä‘îÊÚ¤<ú£^sµ® ¹CùšÕ Ó¸²ÉÍñ.±mz±6v(û±P8É.Wt’cf¦X„ÛZ*?¹Ò„ÊEôɹ¸£ñÕ"‘ À/M½¦GÞ®éöë÷~[BþxØvZâ90Â@þMý4øYétß;—ß0Ùr嫯Y|ïsI¬"°âNyÕ3HÊ{(?úßs{E/ºõG§Q; E±Àüâ•)¯óD7HÞʼn祠Ùí Xʼ¼ŠmtisU?g™ö‚/\xÔ¦f½U…ižzˆÇŽ™ý92Ñ­ƒw)ª¬p¸s‘L¨– Tt)¬k¯Jeñvh7½{G£ÝRñäæe¹çx—Fä¼ðôr*åkÛï+UXês×= }Th4/†xÎõÊ.ÖŽŽlàÙƒ²kØø$³]Þüs®ÐbL‡óüèÍw²Sa‚‚YñÄR³rú#?·î²ãX¾öŠfœ¾Ð$” «{S<[35»å†‚2WÉB;­Öƒ×YìJjæ[ZZ €œtÜFÍT» ‘Æä´7gÜ"ßF¡¿Ô[)ß™ul("Q«]ã ,àˆLéë´Ö+i¦y÷zBÚ<Âh»a}  r(^jÍÔ½RSx¡K£»ÜU•¼ÓwLÆ·l>,Uð[ãzm9óò#ñõ±*¯ƒJ[REÇ”œD*÷p',}¥¸ÂX"õµÒ˜é8^¼r妧*0ÇŽP×cÈàë!ø I`B¡ˆ†›‰¿'ºWÌÍþÜRËÍß_ÐpJßÞ—CU"E“ƒ S¶2ã…T^»È¤iÂô¢\ÏÌAžk¾ö8ä ž›ôDyRºŠìôrxôÛ™*…û몪K"¥+!OÝ}Éä·N$ˆX{8ÉÝCå훓§R¶nå™Û?eÿ¹<÷_b¡ÇÕ.8­{ +¹²žÀŰ#o”=Jº‘ààÀ_3ùòÀ+úé<®œ ¼€‰¿Ø^yªçFf6;É^­ŽP‹ø©ô'~äp „ÛÛR]{ïXCÒë[¦pî¼$wÊñ&õ˜Ùr8Ý‚hÕ :­Wm#/ŸãV®ÿ~¹Qp}ϳôá'î÷æîçÇŠ÷u$üëѨ,΢ªÔdýGö¬Rendstream endobj 106 0 obj << /Type /Page /Contents 108 0 R /Resources 107 0 R /MediaBox [0 0 595.276 841.89] /Parent 135 0 R /Annots [ 123 0 R 129 0 R ] >> endobj 123 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [257.459 605.37 347.012 621.31] /Subtype/Link/A<> >> endobj 129 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [88.296 517.782 115.25 528.63] /Subtype/Link/A<> >> endobj 109 0 obj << /D [106 0 R /XYZ 89.292 765.769 null] >> endobj 110 0 obj << /D [106 0 R /XYZ 89.292 740.862 null] >> endobj 124 0 obj << /D [106 0 R /XYZ 89.292 568.508 null] >> endobj 6 0 obj << /D [106 0 R /XYZ 89.292 568.508 null] >> endobj 128 0 obj << /D [106 0 R /XYZ 89.292 532.67 null] >> endobj 130 0 obj << /D [106 0 R /XYZ 89.292 411.182 null] >> endobj 10 0 obj << /D [106 0 R /XYZ 89.292 411.182 null] >> endobj 131 0 obj << /D [106 0 R /XYZ 89.292 367.518 null] >> endobj 107 0 obj << /Font << /F17 113 0 R /F32 116 0 R /F8 119 0 R /F11 122 0 R /F34 127 0 R /F35 134 0 R >> /ProcSet [ /PDF /Text ] >> endobj 138 0 obj << /Length 3684 /Filter /FlateDecode >> stream xÚÛŽã¶õ}¿Â@"kE¤îÙm7HÑd‹î-ÐôA#ÉceeÉ•äLúó=7R”¥ñŒy9$ÏýJíøS»,÷u®wiûi’ïÊó›`÷3ß¿Q©ÄOrìmLâ öó,ÜœÞ=¼ùöC¶Ëý< wÇ "_‡É. ?ËóÝCõoïÃ>‹¼bÜ”7ía’{Õ^yÍ8 Í#4®S]ñ0õšþW#C-–Ö÷ØË¼ëXcïˆð-`»¸Ý_öz3Àx15ü<ñ,mô2NõrPÕìÏL¸¢y¼Âÿ‰v¨øÌ Ÿ‹|áe°/ïÙ#üP"|½ÿÏÃ_wùyÁ¯òó8&B{܃Ž} ëÂЯå^gÞ‰{@#Xúæ/–æ*üPE»Te´±'†'ø‡Ã }pÀW ºÙñú¾î‹©'²õ+$2¸B¨–HÜȆ¹{tû:Ö‹£‹®º=Nƒ%úÞÙ@ß;øvG<øoÀ:{×ߘô £!ÉJÆÈûír `S lºE5W~œ&w)c`î"x³"èãaß~£‘ #ÞVû:ƒÛê~ Nû€ L•޽¿£’~Aî¯(Þiä=ïCT™üÌ[;ÈA?ÌXaN5êN¸2Ü…ã þ“ÁÇY½@r`(fÕ© P­å9ÖTNìU¤ø0²T1œbý‡måìúb5³>¢;:Í@÷ÊöJ–D”Q» S¿Š‹Ï„ƒ†‹tÿN˜2ZÀÒNN«ŒrÊBâ‘fVa _élØ’¬F¬/MY´í ƒõñ Y4‚RÞIÚbø*c‹`D˜rêYÚ‰¿HüÌ“…½ØŸ‚»YG(<ã¿~àËT¼ú—@Em½¢+/O…=¹šOV6ÈaΔ„0J€ë-7Î…(p¨6$‚¹K1àýÒ0äøÅ±Ñ0ßÈf–HQêJ‡¿?D™f¥%Ã;ÌÖÂöö*hk£Ü« >Ћ…Ñl}WèðjéÃ+U@¤ÌÁØ‹ólÿ ¢Ó©.ª½S¤g„QHöF[ò:¤6Ccf›nœž–'Êë§Úûý-í;ƒCèõ26dÀ¦¨fÍx,.ÚƒÑüõÝØˆ„°ƒ JF^31TYt2RȈˆ /’¹ËÐo‰Nu5V\<µé.GKzdw'~»ãàÏ|ÂX<1òxX„‹jˆ#YÐxÈ4\Á9½° NWÜñ2¸ `™Å­ŠÇÖExG‹O.U 3Ø9ÑÐ?d[$ÔÝ Ò¹'m'Z±Ì(ƒ`ͪÁ}æ=xÐ €J&Öýø™ðÿnш M—HÜÄÏ qïàå;Ó­Œª’³/í‘Ïf¨cQ'= ÃÌ‚lÁÖKÁ±l‹4c\6òŸ™ða,z»š›w•QV(½I6bâí8™±ôhJ«0°ó›¢@<œljN†&ËþŠRÖZyŸ±˜è–´˜¶ëxƒJÅ:ð>-ƒAl¯­ïc1’… bÖâ|;ê®"Fzd€³Ñl0 ScÀg» Vã }“°ƒ}=ó_€¼öšéÄ;YO`Î*ˆŒ²õx¢èo²šÓÌ™IusE¡ îðTwõ@ý•ÈÅ*Ú]ΊNù¾j3 V™›–Ìí='j%䟘8´\¶ ùZ¶ÆÉÚÓ7€³†€Žâp¾8ùÝçS#VCChFÙ=@‘]njˆ âaIµsáéSÏî„:ïy#¦ÜiÅÙ%çK'°û›P UZˆ<¿ØÐ©@¤ +‚Ø“°„¼¨ÁLÊ?<01ú–»¿q`ð»Ú(B…Ú©c²ÌÏÒ È…tú±ø\¯(©C?:2ì¯ØDJû™J\o:û÷l©QT2G¡ýž‹€$ݹ¥¸.ËA4œDzcJYî„ä´sÏ¿Ž¬Zû€ã®À=¨|{¿Ö¥IW`PB¿–„Õ<¼6“v2¤êE8‹ ÎF†ßÞ Â02º »Fã¡r ë\S}ý[ã/É(T¾Ê¶Œ¿Féd» 8{­R©À=«<FÚ­Éi¨È©FéÄWqdNgPéªø…Óa|Ƀ¹=Í-}…p”sØFÜQ’ZÀ69ª$##¹´!æ@ùút2}‘c8r> Ò¾ÒJ$¹¼\Ö¢ø¡ ÀœÒ,ì «~±jh@5Cü¨ÊÚV,5ˆh#Hb‚ëä—8ä”Lšh?J¢efÌ']Ý-Œý$Mó?5Ǫ>®nFp»T`(©Ö9C·.@#—`$ÂÞ+ov ”E‚é7Y$‚_Nyœd­]ž‘Í‚Ÿ±éžPŰM¤¬9â3±9.`ÇbPºNNˆ$3´¸úµÈËW:cD;̵ŸFú¾ø;@¯Ê¿ùšÜ=ÐhÀí*àžG:@qŒë@m‘"ƪ»)æd©¸©Yeb0³ÕeÉ×·W ·¨=¶ HlX[qìÇvŽRßGNn×f’^¦ ý‹I⃻ÏD ó:ä«,¼sšåàò´-·1ÿøåâ–,Ä0™Bß0, Q2è&ôf*¾=ššìÀ5âßöìÚÂh®óÀ¤Ã륒 9—UyœM”/Á¿ò³ I‘úAÎ6ú£äa:N¸Eå H79T¶…ç8©¹‰c'I0uQ¥MIÛïùg® à¦1HÓ”HxÇ“Á2þŠô›ó™ “œgrHÞK6Z„ÀË×êêœÙ榹ä"¸K†%Äó¥­§‹à: ¼ñ©u‰U«ˆli&Å'lX㈡£N¼w²l@ »ŽB—'YcÈí×/Mˆ”LQ9‚ ö–ÚMEË’¼\f¢ˆå;Xf½ UaYòµ·F>8Ðë÷¾Å~Ž´©*çdt… ¤~‡KtnßÖæ:J&[ ±õê˜Ä~¤Â?x{}÷à›éþ¥yvxíÖ9ÜB¤»·˜»‡çpë$_Î: ùyd¹¸J>¯Y›îç‚à—=X›Á+êã~ë`c={h9É ¸À’¦Ë,JL'Õ³' ¥b¶ŒùâùÏÔýq¸àŸ =LMy¥ÜxàQŸèAZ“õWñ%žyÃvÙÖEÇ!0Ƴ—›“Ùi+‰êÅ;ò”"5¶fÒ2; µue&Çš©$v¦‘ ^yT˜çLØK%‚†­ä«ÕÌŸG2µxâ÷?ýÌ ÷qô›@=Kü ú„~]é ‹inRþ"ob dI#ïW#Ša Äâ ¢‘ßKAåf¬Ò¡D™÷ãÞâÊË䣡g3ɶ (Z'¦÷ø­jñTÝÞ¼|ub?F›çÖ‚ê®äçºùÙÀ}5•7´¸ÅðTÓ©” á×%)Œ×AZÖÉc§ïè!9À”«š“7®®ÚËsXÑNÿ(çfSK¼@¾^—%N˜øŸœ9Èâ‰á82/Æ­§™ÆHZ?‡@âΚãÂí…XŠ¡ ³Âº%´aÏU ÑZñ±£TÍq1iEÃ;þñ»–èÊù´N‰ZI‡­ÙÁÂ0Ï:ÙÚ§¾ÞÖÉfàÎá=>¼ÓàTØr‘MgCÑÓ²@)‘/QµšJìƒÆ.YF†bb°›Žõ37Þãç ?s»|)Ï¢ù[!ÝG4qÀŸÈdd«Ã%‰5L½ûôç·ÜÂÏ9ЫéX;I#H¶®VÄÊRS­qGVö"Šœ’Åøbßp%Í ”œ’"à+"þN'ŽyÉPtã™c ‘lâÎ!¹rhýÕ$ž‰–Ç~¦–T³u<Ì#%ò%‘ý†ÚeÛ,ìrãHrßÕKƒ^ˆüÏZ­‰ñ“!‚U&‚SuFê%R/µ†)!JÅùÏõHúÍú²†dH+6qó§qÈhübëùtÂ~tB½™øeÿ,h°ý}YÑó‡s¼ °V oã˜ãOb ÞÛ+¿«° œ£–|ȧ$X[þDñÓŒ‡6ìÜè°¸6üèó»+˜Ú·<ül½Ôpë£ÉŠ­-œœ¯VVlǾ֑hÀ—ž2µnâÂEL÷Zé ¾‚™Š¶IAæ’aꆈ fï‘‚*®Þ’þ®Ê‡¹dv_ë™(2™sx‰(é uÎ’úédî½Òb1ÖÊVß7 Ä ¤1‰·?¯ƒ³Ž…c_E©Ý†Þ^n2·nœõ_ImKendstream endobj 137 0 obj << /Type /Page /Contents 138 0 R /Resources 136 0 R /MediaBox [0 0 595.276 841.89] /Parent 135 0 R /Annots [ 140 0 R 141 0 R 144 0 R 153 0 R 154 0 R ] >> endobj 140 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [149.317 716.011 182.927 726.859] /Subtype/Link/A<> >> endobj 141 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [203.628 716.011 292.572 726.859] /Subtype/Link/A<> >> endobj 144 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [369.695 550.79 428.696 561.638] /Subtype/Link/A<> >> endobj 153 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [181.723 310.363 244.35 321.211] /Subtype/Link/A<> >> endobj 154 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [264.417 310.363 294.36 321.211] /Subtype/Link/A<> >> endobj 139 0 obj << /D [137 0 R /XYZ 89.292 765.769 null] >> endobj 142 0 obj << /D [137 0 R /XYZ 89.292 717.007 null] >> endobj 14 0 obj << /D [137 0 R /XYZ 89.292 717.007 null] >> endobj 143 0 obj << /D [137 0 R /XYZ 89.292 685.23 null] >> endobj 145 0 obj << /D [137 0 R /XYZ 89.292 515.921 null] >> endobj 18 0 obj << /D [137 0 R /XYZ 89.292 515.921 null] >> endobj 146 0 obj << /D [137 0 R /XYZ 89.292 481.819 null] >> endobj 155 0 obj << /D [137 0 R /XYZ 89.292 215.718 null] >> endobj 22 0 obj << /D [137 0 R /XYZ 89.292 215.718 null] >> endobj 156 0 obj << /D [137 0 R /XYZ 89.292 172.663 null] >> endobj 136 0 obj << /Font << /F8 119 0 R /F34 127 0 R /F37 149 0 R /F14 152 0 R /F35 134 0 R >> /ProcSet [ /PDF /Text ] >> endobj 159 0 obj << /Length 3613 /Filter /FlateDecode >> stream xÚÙŽä¶ñ}¿bp70­Õ}<Ɖ7v; ì /q8jN·¼:Ú¢äÙÉ×§.RT·z 0Í£XE릢‡þ¢‡² â*~(ò,(òê¡î>„'˜ùû‡H Ò(ò {“‡,Ì‚ªL†ïŸ>|üT>TA•'O/Q˜q’?I”Uõðtü÷îØì£Ù¢ÝT×ûCœe»zèMc&ýáÓ⟺mt¿ËÝÄýËë‡Ó¨:ë+x£7ý«¸ìiTìž°s†)-„¯p«^µ0ûö_Z%û™`äl ]‡Sª‡A¡;ÎÐî¡S„° hËÄ ntÜÿçé‡( ª4…ß(¨²ŒñÛðÌœˆKàÅYáÊpW~DÃ3ψ˜6 yxÂæiOúȳ89q³ÞÃ"<é€ýÝ`܉ʈ8”΃™pÛU$gp{Aû2jf8¡© m`ÀaYNÎíGŒŒ+Úý>Û–‘=ªzŒŒ W,êõ„·óЇ`ùøuHòбÛŽÀ…5Œ(G8A[ mæv2 Yœîžì0ozd)q] .Øá‰VÄ3ŠÎÙj™Þ< lîr «v“jz¼Ÿþ$S R'ØoÏÞ6½ÃK’„%f˜‘*a×<Ĕ蒎{M—­ĨÇ%{WõÚÀ Hä¤ü7K¸žÞÃ>Œ<«Ç‘.‡{t,¦eÔ‰žïã§$}°|ÁÓÆEP–l’0DÅÙî 2ªÛ'ñnnª_C\+ÒÝ L¡òŒ ²­ AÄ×[ïQ›: _O5xð‚õ…ÔŸd`øêìÝvµS§xÙëˆjy¹X…ä##Ü8Ì–ÓEèô—Â5_šÖòsd€gÜË·VL¥Xÿ½fýŸ­žËiŽ`Ñ\Ò¶ãfï²>×­H]p#ÊŠM\&lká÷Dƒ5©s²k&u¨†G&‚t7³™sDzFÉÙE€ÕžýE£Ê£5Mz$Û;ò,_]ǶèÞzÙ¤N6Cjj†ÞEÛò“àZ¬ÈÿxÂvVJTê[¾¨¹ ³„oÞ;ó ƒ…˜æ„¼{lË–/Èë–÷Cе¸ê<ÓveÛXi[Öuä۷=ìû‘gÜEƒˆ°é ÷¬)$. h¯_yÆèI`¡HØœí2üQ@úµ¥Í‰x±I”Ã&{n¸³‚ÛDkˆ~` ɯ='Э½˜“òa<; H—°MìN°éX‚Ï–'x¡‰Çá•úào™'KP—ÐR{š;Ï;# ¸ÅaÚ Vi=šI|¨Ø¿CVN…±m¯ŒÜa 0¨?81‰nŒ>Ä!aè>vŽú…´½•Ex…ø;}ç3ŸEp†àäõKò"Þýó2!Š¡w›@°uÞQ+qÖ°¿ŽÍä9“#*|#ªÁ,d¹ÿk¥ìa‰™kd€xÅ2ÃW‡ãÏ-ÛÂL3oÖ;àØƒqÊФžÛ•cL)Ze—N¤ìÞ¬J¶L ϽŒ}B–!Õ4K®Økx-AšÅ zÖO`]¨†ð¤I8Ú.áo/Ûª| VØ "D&XÃÐ,ŽˆŸµÛÚZ!ˆÂÆ9ôj±žÍÑ:SÚ¶Ä\[Áéà9~&ùHóœE4_T6Í‹u¨†à_†oPT¨Z†v‚ëa3.òR£"Ŧa¾Ðž6ŽÊÌ|ÒJáÊÄ¿L“Ý„Èb‘(Ï4¬LöV®’"Ù-OžÀzq'z¶Š¤@ÄÙfä&ÙÎëè™”K¢®x‰6Ôé6~À¨È+8ªÊ–X2:ˆ„b8žFÓ·áRU Ä##|ž'n4=ÿÖ`ŽëÈÉ?t«•M)H„’( ’0Yû{Gq|}G8È þZŶ’1Å?ìˆÉÉyd“¡8a$HŶµrLfð`'w^;SByÑÞX<'ºfÜT¯",w_P¬; ¥x§¨}F ZÅ‹îˆX´œÔ}n9gK’Ðn`#„Iç¡}Y$²12Æ.Nùz‚Ã@ˆ0t8xûžŽ)佪¼ r'T‡Ÿÿv#SWE"ÄzAîÒPÕŸH9âÊE‹¹Ðºç™µ½¡ÓÛ8„,.‹ 6® Õ Kæ‰=ppÏÀS^†É*çOÃx‰ù.~‰Š~’´cßõ;še=ª£þƒt«¤ˆ€¨Ú½žõ¨WHŽÍ¸$UÃø&´ghbo‹÷IY™ k?ÎfüØ6Ï%举‡2ÒÜ7Â5‚ªZsƒ<*e±âÆâª‹„-óÖí%|†´ Öiª|4êéWýWRK{\vV¾×@.@Ã(«+Ø£ÂPæ Þq !â^ÅÛNFÐ~…Ù )hÂp¥Übãê:°˜Ü¡ß;’ÇÅåÞ*é"$YæX5 ¬+ ×þ`Ì',Àåª"!FcÉ#Cp|s×Q^ajÕèÏŸÿòôã­õ΃(ó­7 3ƒ åD%ùsu®ž§l–É=ð l|¦%ºÝM$ÕLj+ñŽ2)º½Dú" &1¥ÝÜæ©Öi¤QéÊi¬<°Ä° ј-{Ôôz% ±‡6¼¢i)×øñ"ÇÑB„bieÍ,M üËyÖ›(&ŸÙJ/A84jW³Ò »/ºiXnŠ.MXb· ’Dânqè4“¡Ø4J'Õ¸|xâ1ÒUu”ÀÇÝ4KµÄ1çÇW§eéÄ\i18KB j„Ù0¯ ¬.å(’„Í,µ00–@X±6—8Â×EÑæ«á!ï¶Ñ¦ã†ˆQIäòédÍèã:®BãlùAUªo”aXטÞVÑR/>©ökcp{³`Ybµ“¡IÙ3ÕÉÐÒ­,JoÕBk}¯êhTÌmZÁ¹Šs8sz¯ŒV.e´XÊh¿Ø;˜°”öŠÿ@¢%¡¼SEóŠhqVlÓq*_¥(ŠgÑ·1ŽpA_²reIog[~›´¸S.jðJ T_wîC  ÊJö*Õ'Õ½-ñÐÕÝÀÕy GRåÓyÃÓVa¥ÖwB:s¼áÑA`Vñ‡\muååÛ7OdîÓ­Ò’1¡kÌùø~ÄŽþ(M—2Ê!¡ÎÜd©æ“tIHOoýl…KBî&9{ÉÃ0Hã꽬(Mœ)ÐÅ–âÓt4nØ®g3alœ‘Êâ5*ñ“8Ò/bé Zhh³$ÜÈ3QœužÔÕ£á~…æ½2–‰èÀÀòq_UÇÃl ð8,:#;dY†¥›~ „žâxŽbM:õÕÌÝýÊû פjr)þµ§ºc²|ÂÒÈ´ý]ª­øðÞieµåý´‚Oˆa‘Ü•k‚ ¡åOOŸ–^F`ä—OöEª\8@£xmˆjÈ&Zp¬kB8"*¬ûÍ7(™^çVG5éÿ3Jìw5æe¸õîˆ:¥1áI0·®´É"²â¼s ƒ'ø×š›CBLb« öS-Z¼ËÍ’³¢t%(§edkOeh¥xòá‡'÷©¤|iÅQgéæÇ”rð`®¿¥Œ«,ˆÒ¡!kwMÊ~”¹Aë.{iñendstream endobj 158 0 obj << /Type /Page /Contents 159 0 R /Resources 157 0 R /MediaBox [0 0 595.276 841.89] /Parent 135 0 R >> endobj 160 0 obj << /D [158 0 R /XYZ 89.292 765.769 null] >> endobj 161 0 obj << /D [158 0 R /XYZ 89.292 693.097 null] >> endobj 26 0 obj << /D [158 0 R /XYZ 89.292 693.097 null] >> endobj 162 0 obj << /D [158 0 R /XYZ 89.292 658.387 null] >> endobj 163 0 obj << /D [158 0 R /XYZ 89.292 443.581 null] >> endobj 30 0 obj << /D [158 0 R /XYZ 89.292 443.581 null] >> endobj 164 0 obj << /D [158 0 R /XYZ 89.292 408.871 null] >> endobj 165 0 obj << /D [158 0 R /XYZ 89.292 241.886 null] >> endobj 34 0 obj << /D [158 0 R /XYZ 89.292 241.886 null] >> endobj 166 0 obj << /D [158 0 R /XYZ 89.292 209.501 null] >> endobj 157 0 obj << /Font << /F8 119 0 R /F34 127 0 R /F35 134 0 R >> /ProcSet [ /PDF /Text ] >> endobj 169 0 obj << /Length 3822 /Filter /FlateDecode >> stream xÚË’ã¶ñ>_¡[¤ªÍ·ÈÜÖk;ñV¹’ÔÎVŽ’’èåC&¨òíé”8ŽkªF@£Ñý£MѦ(ƒ¸Œ7‡< y¹©ú‡ps‚‘¿=D‚‘Fy—Ø[Üga”E²Ù{¾}|øæ‡bSežlv$ вÜ<Ö?ou³ÛGÛ¯»¸Ø6“êvû¸L·U×6‚fìöim¿}呺9ªë.Úvó»Ý> £í|nx¤kûvææ8àoâÆˆNëwñaûÀÖÖq<2Þ¯€2>iî´ò«±Òó(¿Hñÿ à45jn&=!5xÚH†)·WÓî—ÇÀÁ}e–Op;IxØ^`â„ô‹mEÛÕzœ4ŽÛÆF£cbƒw: 3‘AQL;ÆAÕu#ošºÇqÂF¾½^„Šà-N†€_‰#Øò×°þ‰Á­ÙÇD§Öx ´bÅ,žÒÎôÍv‡Æ¬uØŽˆöEæ™ùtm¯+ šÛ¾ ¥A™¦‹ÁG¤Ÿ–ñ ;†BÀpÍ…d¾ù!9xRšQ’Ã’Hí2í2ÀÞÃ<`Ùa;žæyÂÅAòÏÓj¾sX¬= ²ÐNÑ>"â6ßã£€çæ¯;PiìÕKÛ“èö ¤ÿ—BŒ$QjÉ)qhÁÆp‹>.t+ É2LIràüÔpã(÷‚D„Á9ß ëYM3²ô‚ÂvÈðÊ õ”Û$Ñ0ŽÖ3„n]‘¨ |”9ÉLs8õF$:4ÔžñÆAöy¤cEÅ?„†K·´cÒ¸¬H–f  Ô¾8åÌ <ÂŒ4“”È$‰1'ØDs‚¿Õ8TW\qj†êuW$Ûw<`O mm—?éºW˜ŒD h\…ë<Äkã<°"¼ïˆ"Ó‰ƒ¸VÅSQnæv8 ”†æ™ ÁV³^5·ÄÁ7想¶ y!÷-Ë„x‹?3ÞQežé•çà #n;dO¿ÉFv P>·.pÒ“LÂKÀŠÚ)ê©3ô&Æ="´íØø gˆcTw–Ý›}w2ãê=£°Bܳ`¼Â]§`V.Av{D%îefSä ÍZ¿Ã­€:ŒŒ@‹)>dkïAó w|ìN k2+ã(ÛeÄlð‰zÇyÜU'º$”·œ£ÕÚ®“]ŸÇiæI÷uj~Å´¥q.(ýë¬ÑœÍY&`þ!N¶?9ëeï9‡$ù¥¢Ä'ÁÆJÍõ2›àzñ½áøzPó(1~5)Ýôj²`¸–lú™¶@(-B†Ã¸*Ä!_vü^!!Ô40•rNµ)¤cŸG-½ ‰ýÜVW²æ ÚP’…þB—¢Dß´L™ìQÑè;†zRÀkÜF˶Ÿ²)kîq²ªkºpöªÈ&FaÅöÔì'9=þ;­œù'ÅjŽjT†Ûâ3çÑÒ8sãëVÏUUß¹½4 Â"$Œ™’´„hˆyx¤x’pÕ8J&æƒØŠó€Nœíœˆ=þDFÃ’@®0&›e€Öó ƒPBU¿’ûšÄ2qeÑÂ7èëSßj Wªÿ„…[ÊÒeÜ&—d  ³ÅËÐJ³ÒOõN"*1þ5Ž'öF±ýyh_¸Õ eü„þF)òË_åltµÛ Á׸»ä8-àrÿý&à‹¾¿çCLxÜÓɃ2‰døØÕ}G"I‚Ò œîÿ«D¸9'gÓÈjK÷’d!0=[0]Õ_wYNâ^Èà™Ð›ÌhbIFlºccOÁav€‡5æ¦kë}ÍèOÖê;Z¸kÎ48ú3¶í’ýy+½_× Ú 9—pÛ|µQ˜Pnò;¯¨··2™¸F,©Á…ó¢ Æ¥ -Л"ÿž } Š:“§©Xc Œj qk2”œ¤)ñÖºÚ[Åtj Zç§âݹMí mì4^O²1R,d{%Á#cQìÇ …A “],ù[ñC¯LŒœ%ÅGÈ„£ Áx@[Wé"ÁÎ/@°iCÕŠÉÙççÁ†#OèzÈÑAØ]xzÝc æÙÃ(ÛƒJ)(϶"£ƒp#ª8ýÔQ.ŒyRHÌ3#æ}øLÂC ŒsA{Ÿ®ä‰k«Ag›Nïì8ôlâŽYˆõzÐi9G¹:îUÊ>ýÕÉßÌWocì–Û÷Æ£JÝÚˆ}xwÚ,†¿9»~!üfö…ËÇ%´â“$aã>4¡aÊ62w »€7Y yDèGf†î;#÷M3Z–fl~¡¬éY¨i"K&!F7ªú¶B¡§¦4W¥Wf» ”M ki»'_}KAL']’!AÅ?ȶ+K_Ý‚ƒKšÉKè(œD—Ÿ~§´Hû‘x Ù#éT¼ýÈÛŵ^†%E× f$ý ½CC‡ôÌVýÕd¿äiWlñ€GEæB¾Bò9]6vÏ©4bY¹ËOY¡IšêÄ*ÎE̹hÁ¹¨`+(¢ƒ‹F~4 nLsÍ(\‚FOBêê8¥öc ;òÄŒjd®©ƒ­EÜ^i]x"k|:_ÈKvÍq½É%Ò·îTØm”dè˘×äÖ½K®Mè´¯q¢r¡Âd&J Æ›^’ÊŽR^ÈýW\#›Ã÷fk”H‰Œ@{©·ËDä0ÑòBH¨=Ó Ãlºc4›-£)SŒsÞ% 6zn{¶æ˜6oÖÐâ—8aô‹Ü$:vl˜|CWˆ»öÓ;›ÊozÂïyβ‰E#ƒ ©ð“…­ò¤v˜T=‡Ôj^D-äÕ•S0s$h\|;I¹ŠÝ¡- ª•Y™C:)k^.ÌoÆ‚DrªÄÎŒ*,´Ì~E¶¹œD ,Eßˈô«scoÊ7]óÂ0ª¶r(Ê’µÏAɾC®¡áã2¦˜a~2a¿•‘«1R‡BÉßYX¸BC³‹W`ÈE–RÐA`m–çoùˆê¯¦~UJ‰™ÏvÁüž%uãÝ¥eN@\M®5ñ¥@b/Fu7d3¨úÿTƒ‘ETòlm¨4½2Ø”E$…·Û*SajlüB²­®Óä¢{qŒ¥Ôüœs¬¯oKP4S´É Îâ,Þ-hj‡6JˆÑ>RöÆP…ÿÜúž5­<*QŒ$3ņ¬X)Iâ°å/´G?¾fñPœ+º×{J‡Qx`?…=€Ï!;*èbŽÇBQ®”•./¦Ì5“Aâ˜Æ‹¦Ú¢›¸‘¦ ìÊ¢Ã|œVBV©—¢#õŒýM½×†›¾ï‘™Ú]ˆá²Î)~kY'r¾¦96ååV/r¯U;µZ–ÓQû'§Ð‰HH’Ü—ù›ÚdîéÆˆÇy‚¢(ˆ7I“RÀŽÀy|úô÷»4YYI]hK§QΙ™æ6—¡1rÅšÒ¯(ã× øµ™¨-Ó®â1W¸˜Ç2æ4škL=ƒîî ç+½RîÈ’à›:†Öç»ãEe`Ÿqè™w+®S6ÏH¥§†Êëšá“Ä>ØöcØ|dY²¬,µÎwc%‘´ïþéIç¢d´tþ£bÿ¿ýúDrˆ·ÿØE&a>A.œà$–ð{Õ6Û:ˆ©‡ßåN T-ßiˆ=XOŠXŒ ÕjVKú,:$¨Ã‰Àf¨¦W”Ø}–GbÈÉ}¬b$o©ëùùM‘: #“!gaÈñ5,±š\_z•›l9fíœ46öÄ‹W‚Á>*+MàÚÖM‰–§¼ý0G™,Ìf²ˆ?ñ‹Ì8¯y]/Öh;å=8IJ¢Du€z-þ{"A…Bƒy;—,Ž[„eZ±ª-ÛñVнš¿)§ŸµÅ’Û`Ifo>å¿© î¦À!ØPUžUñVÈ=ò$›ÆÍ<ɘÄ‘4"#(#|~7vGS‡—j€ìÛATTŸ¹sï¶O<`m¨ñs#!’/â›§"G!q­q—ïìÂJe©–òŒž!ö "øyF×ÙÇQZ¥þs_S¢Ë׎ûøF_“½±&Íx£,…È“#ñÅGrj€ÝVZÍ̈Z°8#áïC¦†” =ÉÀýÙ£*ólB^rhzöC&ëžL1Müâ7[HÖæ‰„ðŒmr­7£²2ñÕû æb­é9]ódr~)¶ÔŒGÑfÈKxUzù·ù7"(¡ÛâÃè$“åë«‹¼)ʳ}"Çïa!ÜFÍ Ž†Ø<[±=5{cM˜/Bjð‹Þ̰ûhk-é”$ë + ÁÜ“¼º$y,µ­<¾1ê\0Í1%“ÇËç<$ã¢*x qìzâNëi}¦Ì¸ z—)$qD‡R2ï~üôøáb=|ÿè>‰LË - eHƒ4Ç/{øù—pS?„›a”ÅæÚa•å¦H‚()¤×=|zø—û|R(í)úxrñŸÅA•f5ÜÕZzáG–…l›ÊÔª'¾j~N-€Pœ-.‹ò"ó@€ŸYù^d!&¦ê ™bŲãÏ4ºTí³<ëqÒËbw4Šã³S¾â(ȳtõ3SAÙ{8·_™ÆeDéÁ’Á㥷K™ÏUWÖúVmÁmendstream endobj 168 0 obj << /Type /Page /Contents 169 0 R /Resources 167 0 R /MediaBox [0 0 595.276 841.89] /Parent 135 0 R >> endobj 170 0 obj << /D [168 0 R /XYZ 89.292 765.769 null] >> endobj 171 0 obj << /D [168 0 R /XYZ 89.292 394.217 null] >> endobj 38 0 obj << /D [168 0 R /XYZ 89.292 394.217 null] >> endobj 172 0 obj << /D [168 0 R /XYZ 89.292 361.832 null] >> endobj 173 0 obj << /D [168 0 R /XYZ 89.292 180.567 null] >> endobj 42 0 obj << /D [168 0 R /XYZ 89.292 180.567 null] >> endobj 167 0 obj << /Font << /F8 119 0 R /F37 149 0 R /F35 134 0 R /F34 127 0 R >> /ProcSet [ /PDF /Text ] >> endobj 176 0 obj << /Length 3450 /Filter /FlateDecode >> stream xÚZY“ã¶~ß_1/©âT­hÞ‡_RöÖnʉ·ÖåŒ_ç¢(‰2'¿>}á %ͦæa@ Ñh4Ý_7>ð>¥•ÑCž¥~ž•U÷.x8ÁÈßÞ…B‘„™Ÿ•øucp—©_ñÃÎáðýÓ»o>ÅÉCúeš><Í*qàeùðtø·û¡—>îÂ0J½¡ý¯/»8O½j€î2Ö0æM|4ØÓ?þçéïß|*J¿Ìbd<ì æwh€hÂ9sU=î¢ 8©‰·è¡š¿çsÜÞ}|2 ³ÜO@Ø<Œü4ä­bÿx‚ŸMk⥦=;Âmø¡„?·«9Œ–«U7 Ö$o­U~¸Zꨦ™·Z nükÒÁ4Œ¢…á. Œõï wÌÒ™zª?`#†ÑK‹:çsòwIzOøqÆ3òÙÎÍÐó$Ý]ÿyi‘ªjæöµ À8Òb6°©æÕwq{ûǨð^¹=Ÿyå8ù‘†¸Õ=’yÓ_“ž‡IFÛfš}Z8Lü2IVË>‘¾LD'—þ¡² ^K”T(fËÐÆÆJæá6ñÿL"_h§H¥PÌö•çýƒ´AäÿÊ3Nj𤹇s¯æ‰® ãàpd&ÈpèOü1.=“¹/g<¥™é¢´ˆtŽ4IŸáNÎÁÕGFú¸°$$ÈLÛFýôDÐz gük&õ8½çaæ 0¯‹Ycš´ñ8^ŒZÜÚP’z_  {OSï7Þ¼òo #Y¥e훥®-:!‚åŒÔ(즋Y`‹m{×(>\3'³Ž“Âk:êp?öXqñ¤dÉ@Ng¤[fžõr®eþL´½–Ž,‡ô3ŒÏ²ˆËOèÛ¦kæg¸ãˆ»ªôFÔi€E‹{D¶(Yz¯Ï–Y×7Œ€÷_)mIGw¶§öšá`_kñsúŸ™w€ã¬¢ñ•{'}¤ûIru©êÌ4Jf*þ ƒÏû oˆ„iF´J±K‹æ°=q1äZø¶ž¦{2³%ÿŸ€ï£pƒ 0Ê[{2¹š?öfxBKË]+-bÇ|vÍ“&Fž…C'×í•{ÆšM{^Q°æðÄ{ïd„6®½³Ö-ÉmÌ>&5“'S³,^óaõ7”¡øæp°ÁÖGG|²äY<ôÐî(àe§xŽ0!ñã$“ˆG`xìu_èÊ0, Ï‘K¢ÆE‰š R˜,kƒ@€uûE˜0k¡ðÿ9¡¯ßÅZø#ò±Ùá}êÉiæ} Dw¨Û¯"°ûNR-WŽ#€+áìkÄÎâÆÀ˜ñ *™ÏÎúé~ÈÝáHÂu«.&<ˆ×›®^sÝ£œ&$x+x¹#ØòYª>±îÒÖ³faîK}×=þÄrÉët¢²2’Py6L8œmЄ6—¡ì&Þu‰8Aáèá…bÑ|F×dÄVÏ=`kàÿ(ÇÒëEä–‘€«@ï„+RTIwE½ç -ЈHMëÞe ‹z[1ÞÜVÍxEu¼ÀΉ‹‰¶õaâ6›ÀYCî­…`û:øÌ|h—G=^‹@4êÄËeÖ¡;´³ÝÕ\ã3·\ ¡¯¾á'6Ð<Ž’»²G8DêQÖ$pÊ­®ªŒ Á,%Z¡ÚF4ÍŽ:‘ÿlëðyQ#aÔjiÕÈ#+7ÚkOœZð ÷‰ª0f¹ø¢pÑVíÛµRØ»uħ ‰' ‰Ô20žr¡Õ X–o—Ƶr;?ü½¿la— {§ Ç!£'°P>²Øz—8è²úù»Ïk¦‘·70ô®øE "¯S½¾ÍŽ1“E@0ÀÊ#7ÕäØ|5œdà\Ò`ëÄq+Û+Ë”=L7žf®¡tU5"…¨Jãí ºcN÷\XžMKµmÝ6ÿ5ÎL9ƒù„OÐ$ÊX©PÊD†qÐz~L3OLOÒ@»00-?ÎQ’"Ç© IQû9¤€ö2‹W‘+Éü L…jª´Ïj.3K§÷Ó¡D›°qvDo㵇Á±ùŒÀ[ ÜE§?¤¶(-ý¢Ø`LWËfoƒ.¡}Y+Æ¿ÞudÀRïú³z®¯vÁ¡@ÚöÌšÔEb­HF·é{T$~ö€mQ~¥h Ä;‡z›Èoø¡hd¥¨Ž^4Á u#Lœä~l¤Ù4Í[Blù hwQ`µ`—à,JÔÌüˆp:¶›ZÞ$›çZ„À¥QšûyºÍ6úA…"E›Dƒ«žkî¬!#ÌÈXuæOÉÜ*U9œºIÏ¡ë`Ô䪊‘–…÷E»| Ô>2crÀK/þ†É£¨™G ¨ƒÕ½^Ž&¡ëjëÃøH^µi1ƒ‰ó­³æKŸ%ìúPÕqáM/Í,WMCî È¡ÿ|_¶öšÄ~ÃÑâ}Ï¿j°B½sȯ,v÷óσ”!’¸Dìo¢?ù-Nh«3;¶åÒÏŠb-è•-3Í[âÅ)\¨t%]#kK`@³ÙS¦¤¬\ Ý3·6ÐU{R q3Î0ãbå±fÁ¤»ãÐJmléÜê;öïd09xÌÂf0‘d0'rW481ÂËsäæ±VîcO®+Èðú•ìå{“«˜}&Yà™€Ž•TSdŒÒfºüø16óŒ¥ üÐÛ) 2ò§¨ÐºkŸI±k>Ó¬´„38pC1—=…&‘pƒäx“Tïrdå‘éá•'Ð5Ñ#µ,۰ư‹cù0mÅ % Jg×aÀç žÙ©ô;Éòx]EÒ¦7Ç>´N @^38TÓ2Z×ÏÕš¿Møp06>üô‹SêƒôGR%tM a7¬ß½xpÊÏ®ýÔà 4®žÁ™¾EŸ™ÝÂ$†54lú'vψÍV¤=ÖÂ` j¡œ‡SÍø‘ç=ÕMf5ryáu‚ëÁÐ,\ å(©¸x+y¡PbJ‰&Oïä¥ï™J3@ïY&~ÓÏžšîÒj„žre†tzY)™¦°ÆN4Ü1ø§—[»&WšÂÉ¿Dœ2ø‹Ô!FžÓÑõ–ÊÄõî-öÊñt8§†.ª±COÇuu<”µQ-=Ä™Sxdrk5F¦ GŒ8 cg5 Ší3p*PÜMê©ÌS˜'7 =Z8ý˜hѧ-xÂ*㢟–6ën`)[*α·M†ÜN‡xǾ=¼èÇ)ñb Ú(šv©¤›AB|'åÔ5r5iãáÜ€/ìŸÅ›ÙåâLŠsm3›¼L»F¼º‡Æ-­n Õä$c|paFØsÓÊ3FÚG81 l·Ø0yt¥3БVòq“š‘¿Å):ÙƒýÿfÜ{6£z[<©šU¾qã]C”Ÿá1Ò$.‹ OÎ3BÑÎaO¶,œŸgæüê?ŒôØËÿ~_øÜÑLè±?÷­¬;ÖÓÒÎxkÒÈûGÏåð-I¸°ÙÌ+–®*ãïdhXÐKý ¡îÚºòxÙp:%kAçÆš|&¾¶ˆÜ ÕdŠH#wPx…ÿ[v‘wØ'ï1ÔÇ/(lÍ  È£†ÙÄÆBßzõÚ‚²êÛ\¦‡3ßÄÝRÁ'ŸšOCprCï$,Óµ$þÜ룑3NK'H ¾Üð¨c’ÿb êpZ8¥ø4÷,ÎI8€ÄþÙ®o|2HBž=EŸÜׯ²ësén¨âöÍrÞ›”|Túݨ¯Ý÷K~Ïjzynú5Hƒä•«Ó[ |&píö* Œ©¡:™ò` > endobj 179 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [166.459 709.577 188.515 720.425] /Subtype/Link/A<> >> endobj 184 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [283.064 467.056 348.042 477.904] /Subtype/Link/A<> >> endobj 185 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [242.14 443.145 350.684 453.993] /Subtype/Link/A<> >> endobj 177 0 obj << /D [175 0 R /XYZ 89.292 765.769 null] >> endobj 178 0 obj << /D [175 0 R /XYZ 89.292 722.141 null] >> endobj 180 0 obj << /D [175 0 R /XYZ 89.292 628.824 null] >> endobj 46 0 obj << /D [175 0 R /XYZ 89.292 628.824 null] >> endobj 181 0 obj << /D [175 0 R /XYZ 89.292 583.223 null] >> endobj 182 0 obj << /D [175 0 R /XYZ 89.292 583.223 null] >> endobj 50 0 obj << /D [175 0 R /XYZ 89.292 583.223 null] >> endobj 183 0 obj << /D [175 0 R /XYZ 89.292 563.306 null] >> endobj 186 0 obj << /D [175 0 R /XYZ 89.292 432.186 null] >> endobj 54 0 obj << /D [175 0 R /XYZ 89.292 432.186 null] >> endobj 187 0 obj << /D [175 0 R /XYZ 89.292 397.476 null] >> endobj 188 0 obj << /D [175 0 R /XYZ 89.292 253.848 null] >> endobj 58 0 obj << /D [175 0 R /XYZ 89.292 253.848 null] >> endobj 189 0 obj << /D [175 0 R /XYZ 89.292 222.016 null] >> endobj 190 0 obj << /D [175 0 R /XYZ 89.292 190.191 null] >> endobj 191 0 obj << /D [175 0 R /XYZ 89.292 174.251 null] >> endobj 174 0 obj << /Font << /F34 127 0 R /F8 119 0 R /F35 134 0 R >> /ProcSet [ /PDF /Text ] >> endobj 194 0 obj << /Length 3304 /Filter /FlateDecode >> stream xÚZY“Û¸~÷¯˜—T4µ‘Và%*o¶§œ]W\ñlå!É$Q<9!)ÏL~}úën€Ðe§¦jˆ£qõñu£!s7§?sW.gÉ2¹[ùlQ,ïÖ‡7ó»õüåQŠÌ³b‰Ú•Îiº4³E™Q!›•‹«$Æd3³\ÞMé|V.y‘wo~þPÞ-gË"½{ØÞ™$¥4Þ“)'Ï÷S3iî§išNVÔxÜõRqÚ¸[¯QÈ&m' í°'º ã´¥o·ƒÌEÿlW =“ÙAHBë5v¼ò7ükñŸ'Û€ ¡MPëŒÚ¸~ÀòfÂÜ!¾›YYâÜtº$ç£ü­‘Ýdå‚&Ÿ& ¿53éQ )ªs )&O]‹sÖÕAÆð.{)·4¾œÈŠGl´«62j5μ¶Ç^×k·ÒkåóŒqÝ£ÔÜ=3Åa_I8´ j9!v¼Ö:l—Ù`î¨tcÏq‘0ƒ4m™eP¹Ù2f80cÛv;`ù¶™Ñxâú6Ιµ=<9fgÔï!óy*l»GÞúNFlPé*8´ ~•§ƒxMfuÕ àwË—D/$^cP>? “óð’Xé¬24™]«ŸÐ`D/©ã_s“aån,™Ÿ0ïš±Š»ÀT4%“-ÔI9& ÝÜD÷ȼ–ÄCœÔþkå#V£‡Ëùqhè²67P­Ô¨ºÙ5x¿×½]Q7Þ¥DŠ÷¼”áõ]]uas—¬p͹űµ)7ékÅø˜™ÄÙTÄ 'õgðŠÀg{•Ž-Ÿÿ • jÏÉê©c¬aËfi³*A=³LY‹áý¾…ò׺½«¤ñêp¾ýTÍY5w2Ú[ZÌœ‚™ÓUue{Õ ÁÁ‚\³®¬fa®Œ¿W@[Új†:×*fž°*ØLª#—;&ÅFæ7ô}Ýã€ÞãÀ@øó‡4»óâÝâ8É‚€±äãd3"Ìh¸IòÉ—µ;íŠ ÿ†ûÛáY"/–”ä•Ä?ü]÷^òþ–Ï|²A“m³VœEŸkøÜk;pϤUTß+·¦×q à¶«_eâÚ5ž!³ûö^¬ÎR{æÍuÚ˦`ÑUûi‰G6:…ZT§k¹1ìýçßzVÂtò¾å)¦W4Dà2hi¬]w-o¨—: ´«*©¹ZŽóG¶Ø-r€“ÓaЪt°ó“°Þ=ëZu†Z“Y.c¹¡Ôw¨¢=lÕ“§L±gàRÝŽ†á7ã㇨¯÷´§ðñîȾÁB…^˽{¼¸*¬UŒ‡Ä¼rH"d?‹æoêñAáœL€¡j'΄š8ˆ ï6„è£ Ä©|ƒJıµýpB+üÀœò©O±‰9Sh$ÄBßô×Bþ4F‘«ªð_‹õŒz>Ôå¥E1>•/ŽP±È J_a» 4~/ÇÈ –¶H‚‹DÁ®‚ ÌŒSáÝ"2˜>±u‘ªUµîç´ÿʱÙ=ˆ†a¬[Á¼DL5Q¾GO#Œ»¥¼=l,øP#îȲœ¥Àºñ,þ Cz©“Ø_RGM£TOÄ ÷¿èéŸD ÕþÆM¸%î’Ž'wÿõV«‹ØþQJ.Ú cx`õ3{g!»«n†fê0þÜ#Bë²TdŽïÔx«âIؿĄVée¿DýÌ6§ÖÇ}¬”Ç~þ`o¨Œî,1B%ñNnn7JüCúxN ^ЉêÙ±ÝÜ/qª¶?ñüö–fY"&˜E—©ìÇW"2,˜ŒeÂãn¯qšò©™ÿîloä(·ã'ߦöß´™üÞï§9ýç=3:3“H1c¯|×crq5-;w¤:¼ÃÅÝûiF†ŒX†¢ô!CB…¦Ó4÷Ø & 1B˜ ¿¥Ë3ú@®M¢æ…›µòØYqÕHA„Ó`®4í ]ùý±ºb‚¶‰nF‡Öçt¾Bh«þ¦ý*ñà#¢ÎR ˆ¾v=êBši²íR­Ùì*í¬: ݤà“7 é[ùrÜIÿ(G‰³DÌ…q¥þUƒDÍš¬¥Yœ ÜuÍW ¿‹Ž$…ýºƒú›ÄCˆa›.ez#c¦–éäÿ¼Üåz¹{/àF;äðœƒþEAG¥ë®øöÞ!ìiú[×=¹í}lp‰¥ó­ØóžÇíóâ~¥s„¦ÈÄYjì*¯± îçÔÒ7d½PyŠÒ’>Ê5û“G÷ÿ¹¸$jS½›#€é\«žu™§öP— ¤îVRo×’#Õ‹†‹ë!ŠnèòG f’NÄ¢WÑÐrp’$cÞ­NRql­}Õ·晪?G‹µ±9‘k:ÃJÒB xT ¸‰¦kQ8½Xø·~¡“¬B=roõB‡qçR½¥Ð¿ºpÁ~™3ò¼r- Õz„JåÉø(:OÛz8Í XëŠ(£ùù¾+¶.«…& ‰%Š¥·B˜½oï!Ld'ï@¼L+_}ñš.¤ŠNв‰Nïm—˜¿»ˆÎ"g†{Ê_Ù†´ƒEôÍõÚ§²h}€9>Ф;¾xdê„.eõØä·2Âê£N]Ç£–‹'¹^Ÿ´¾´݉%t ¡Û¼ºâ7ã‹àÁFAmôà.lNžRÿ¦Ç2zËèÎ;S“ý% áWH©þ8¬+4¬ûd9‚㔫Bx—ýn÷îÁ‹ó<"Cöƒ((Q 4¾6õ2ŠCÜEÐEá“ÚÚF›®_B¡x÷„ÈßOhRu?9ë賫?wq†|·¯:å]>;›³$¥ÓãØÓ¯l™*A¬ulÕº±"‰"ÄÂø©‰s,’ÖÆÕÆ2÷g #•æqúYÞät’“[·|ïj~½FIÅé R‚KÓ•Xí¶ÐWu,G0¼¢}B£F͸©JT4&Å/­ã8Æ?ch¤N†,v¸yò“Wçƒ:ròko?hØi à_»ÎÒÕš¢©«ïûý@8I©Àðb# A,36Ã2¹HEÑe*˜uË<¯Kï_¢äÑFÚYCK$|ƒf<¬Ÿ¹O¢Ùf :§ˆApÃóñ òØåø›‰2z)ŸÞt}ç‡PA”i„j4­\îqqEGÉÐjï˜_¤qýøð'€âT\ñ\mW~º–h…r.“SQZ¡oX‰ð !¹N~…(ýÓ ?7)ƒNÔ‡Ïæ3YÞ(.ÕzoŸîÍ){h.ÉÔá+©mã·’å‚…rdµDÍiwôùtÔ¬|ä§.âˆu/9øBe~҉⨥äæÐek? IJÛ$Ê•‘‚›!4Ç“=ýƒZè>øŒÌÙo‡ô‡N&1³"Ï®þtHI¦Íù/‡’e>3Ù"LÆçKåó|¶,ÓkkýòÄE5endstream endobj 193 0 obj << /Type /Page /Contents 194 0 R /Resources 192 0 R /MediaBox [0 0 595.276 841.89] /Parent 135 0 R >> endobj 195 0 obj << /D [193 0 R /XYZ 89.292 765.769 null] >> endobj 196 0 obj << /D [193 0 R /XYZ 89.292 740.862 null] >> endobj 197 0 obj << /D [193 0 R /XYZ 89.292 661.216 null] >> endobj 62 0 obj << /D [193 0 R /XYZ 89.292 661.216 null] >> endobj 198 0 obj << /D [193 0 R /XYZ 89.292 626.506 null] >> endobj 199 0 obj << /D [193 0 R /XYZ 89.292 435.611 null] >> endobj 66 0 obj << /D [193 0 R /XYZ 89.292 435.611 null] >> endobj 200 0 obj << /D [193 0 R /XYZ 89.292 400.901 null] >> endobj 201 0 obj << /D [193 0 R /XYZ 89.292 257.826 null] >> endobj 70 0 obj << /D [193 0 R /XYZ 89.292 257.826 null] >> endobj 202 0 obj << /D [193 0 R /XYZ 89.292 223.116 null] >> endobj 192 0 obj << /Font << /F8 119 0 R /F34 127 0 R /F35 134 0 R >> /ProcSet [ /PDF /Text ] >> endobj 205 0 obj << /Length 3776 /Filter /FlateDecode >> stream xÚ•׎äÆñý¾bßÌ4C3ùítÐYgذ [†ÃC/‡3CØA«ñ×»RN8ÈX`§CuuuuåfüÁ_üTVaR%OEž…E^=Õý»èé3z „Šó0¯°wgr—EYX•éÓÎÃðÝË»o?–OUXåéÓËÁî‘FaYUO/ûõ8Ôë4=ÇA󼋃á9©‚åy—æ*XôŒC_`nÆ‘,Їml®üûúE,'7Wý¹í\¿×ÏI\í¼èIvhôÔµfë ÇÒ@{n,§f`°€hÀG×ç]RMKôÊ´ÉF ×pãd°êýþV΂¤Ëó¿_þ üÛÅqXeqä‚´6HaÓÏå¹Lƒðy§Ò$x?3Ä[ 'ß%UŘ½o÷‘_‘Ä#шŒŠrànœK5 ó­´\ÐÖz|^Ì@ÜÒL}»,Þ•xg­që=·Ot]ÒYFùtð_¶ÃÚGÊû¬©õ:Ó–È¥‚¿ê/Ĭ?ÌüíÇ4s²–«0JK@€ w»}óºÊÈZi*@om‡wœ¦Aó+¡u¹ê®#þó4Nüv†N·1W±­œ™ÆWœ'ОAôça X'JXŒê /aa6Ãm+8)²aš%ņŸÇ¾Á»©€Šé(Í3r·îfy x™IóJD"tNd Ü‘K@FŽX(d¡>¶sÍ@vñÔìyº°ÅIt7 7½Û(ñ6nd7³0)\víë2ŽÝ=áM-)¿^ç$÷P#OöÌ·4Sažç¸œVHázÔÁ¬¤‘³Ñ³4ÞãròìXRåÁ<®“aiÃC É¢5%ÝÏP¹qpf»Ô ÌÒôgf ]Þta$´û³à,‚A÷ÒB+5Êæ¨ŽÔ-ÛeYð‹!®^<,3{)Ð+Û £n­‹;¢èùè ELÆémÑò†Uí$°lD¿ßþäD4|Z¥al†'¶¡z2º¤˲$êT° ‹“,ø ß·l‡#ú?…>ºìöô‚ 47"ƒ.Ô]ï¾µzXÃ5&iÅ·I–?õ„>Q‘ÓÙïaí^ åÀ=rEhÓFàÈ,´ÝÞàBñŠ“àÓÂÓèñ÷ ‘²©»0Ö±¾e+)ù Ù{0²d5E^FNÄŽÔ>“ì}Á½†ãyÀýÒ8%ß?Ö’tš¿ÝñÂ@³¥eãÍ“˜NÐCXýIš?¢†eÁ™y=ôYÂX ‰! Óg²&g”蘌0Ó'`âk{Î=Å{²‹½ñ¦¿Ârv&Oº!Ä€~æ–Q¬ì“X@”m csJ‘{Á˜â‘HµÐKµfW)N¥1P ¿ÿ!¡a­‹1óܾv³ „° Œ‹dÓ ^Ò>ˆ5ï0XJcf8LiîR\$ìä~ü™AP¤pÀˆÔ-WŽŠY‡¿œô@Áw'ÜÄ”ø×F¸ƒ èp û…”¢–Àb• éÛ0ši±–ÝnXäuõŒd´Žk* úšÞž§ÿÂQÈÏû]½ 83ØÞÄ=Ø!ÅËb"Zšýh]ÑY P¸‚m£˜ÜcˆˆìÛ.¦Øª $ƒSK>Xf20ÂzÆîlf<í¿Qƒ}Tºóuã¹o$Ø}‰È|;)i‘.vÐÜ*¨(n²'%-²€cÊå@\§CÌ‚¥OyfeH\Ž¡ÀãX?N ·è02J†¤HíÜš Ž|Œ‡“ÉÂÞ1üz؃“Äÿýï òJ ò>7¿À}‚»ü_‘Úpöž©ÍØkÌöÎ ëR|èøîV¢.vpy€Þ¶±mê…‡Ö·ðÅQ À÷_ì8ÓÃÙSšØmzI´rc꺠Ÿ¬õgÛßüæèeqITÅn~ýÒBÿByúÌaÉ(Ý2m­1Ä¢ yÚu/vŽÃ|jEÓUebçT›F¨ZNBFݵVñp‚$1Qå•ä=Tº^’’I›»å‰ ^¼T$­Ôf§´J­~uæ ìEqj™\¦>ój½@{¶îá×Mœ[±êùÈIy ÂZÛu9z½tRôÒ³à½d2¶ý,„ßáÌUµh\)Ò„r±®¼´_½Ü][¯»¶nÇuænm“&†ÇÈ=+¾eî®^‘‹‹M;+ ¯^/‹-|ñúÆÛ —µÛ(ïH¿ž9…GT¢¹xyTVUÁ‹Áù;Xcƒ©®YXt)ƒq’ŒH"𗜥wSû_kH`( à#º6÷9šl%œ–‡ñ:AÄe5+ +Ù Ü)zm[&pËû^’M"ä¸5Çù&­GC³eÌC“BŒL ¦¹2¬RÆ¥ú€¹ãÒŸÊUHp±•6ŠA‹ÜÔ|iÖDe‰„P4fkŸœƒ|:ðU­¹¸”¡ÿ¯¸Ž%k@ΖopmᇖœÉQ4g ÍÙF8ZÃÐÔh&燶¥¥+ƒ£¤¼3߀sV¶º@í"ÓT…¤ùGcB„Ó•CÌ)öÜŽÅbQZ'ü8ÅA&8ÑÂùÂ$©Â,¯¤¶§ì(Cõ¾všài!€d°qºE'a”)À3`þÿö·8MC[9^çfB}O$ õΠù!¸5³â¹G„sS眹V%aY¤›k0AŸçÍ£N®jÙ‚óveËß,R¨77ÁìÈ+f¬¹ÃX$ìÀyÆÕzqniO?ß}˜1ク©=¸'3[º>L*׈ªrs´Ñ¢hÎè¿ ] ˜wL¯”¿LVãS†rUmÄ~Þjç–¼ß ¤E*âGÁp‘¸¢:vº¶']6ããɹÇÌ÷`í}!¥]RH¶uE*γᛴ Vá%VÅU°sôмwñªTËDdŠÓñÖ¾øÙº’<4¤œNwB˜D\å–¶^!ÅÆKLƒO&j*]b:Q•ÕÓ, |Šà¯‚þëu1*©¿°Al?ó;¨ ¥éé ^{>ݶKàJ®€áþ·j€ÈøÙ±J¡™ÿx Ë•d§%d³pÍ+·¨fÑ:èn‰—k,uï¿y©´KW ÷³ö¶Eêê*øüÚ?8n«»xã³f}hŒv`æ8¶6#úªÑÇ×zÜäóܾ²ûQäÚ³ËBšžx*ó¢Ìâž K+ôãØpfÝëcÉuñ½Áê^îèöypdqט’„c°Ê©l ÚÐçÙF½¸7ÐÇ^‚ /•Ôb¹Ù‘Èw6ÓsòŒ×ZEÄ=-uŒ=Xø„}OÖ'ûÇJ¢úV… Ïæ5{É*’pä@ÏÇeŸ<ø^Îya@Çjì™ñ'žVîï¾™u7F_=Êø]dÙÖƒ0q²>NFšŠYúqµQ&vß³hÒWŸ)äó‘­‘¼)$°¡´ñäa†^xêhbM=µÆ4ºBz¯Åh6ýçtkѸ M'yz¶Ä|¶ÜV$V¸Èñ¸ê\»x>C¯Y>~« w&UÊ5QmlÂE¬tC0mߣfî›ïY¾£Ê;öÑ<Óàl+ë˜U‹~užæt¾)»O²­Yv¿¢RIälKñG,òÌd?SÕíEÓ™W‘oíöÑ~ÜY²«uÛW:Í"¾ñ´&%˜„ ùvK‚-f™õÈ|udFE¥ÂöÅÕN=…º÷Ùƒ t¤lõPøË!2â=úŽgóFã7_©ïi4w`lÛ§)å}…‡íkv#°½mÃvŸŒé€eSσS£çqЯ…ذE‘b’FPuM¦è•€ˆ{l©¥ÖsÕ?/ùq~¯>mQyå-±;¯(ø½;ä•÷°‘û%±„¹Ez9Ñ{̉WÆæ™?ã#^ž•Ìx'{™”ŽM®HøÙÃï g‰½o'5Šö,AžÆyáâ,ÌPý˜œä»Jk ´•%6k;žŒÈË—‘¥ÙÂH gVV[aƾÕÃ-_XÞÉIry*€_QÄ\9EåkLÒÂ\m¾þ4ì¹ÿ'q˜gêî yƒô`®Ÿ“* cUX4Èáâz+ó-ì½þÈÈÉ­endstream endobj 204 0 obj << /Type /Page /Contents 205 0 R /Resources 203 0 R /MediaBox [0 0 595.276 841.89] /Parent 212 0 R /Annots [ 209 0 R ] >> endobj 209 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [88.296 538.226 149.068 549.074] /Subtype/Link/A<> >> endobj 206 0 obj << /D [204 0 R /XYZ 89.292 765.769 null] >> endobj 207 0 obj << /D [204 0 R /XYZ 89.292 657.231 null] >> endobj 74 0 obj << /D [204 0 R /XYZ 89.292 657.231 null] >> endobj 208 0 obj << /D [204 0 R /XYZ 89.292 622.521 null] >> endobj 210 0 obj << /D [204 0 R /XYZ 89.292 505.294 null] >> endobj 78 0 obj << /D [204 0 R /XYZ 89.292 505.294 null] >> endobj 211 0 obj << /D [204 0 R /XYZ 89.292 468.647 null] >> endobj 203 0 obj << /Font << /F8 119 0 R /F35 134 0 R /F34 127 0 R /F37 149 0 R >> /ProcSet [ /PDF /Text ] >> endobj 215 0 obj << /Length 3748 /Filter /FlateDecode >> stream xÚZÝã¶¿¿Âo±³c}ÙÒ[Ó \Û4A³E ´}àÚZ[YYr)év÷¿ïüf†%{/Å+‰‡ó=CG‹-ýE‹¼ØÄE¼Øï²Í~W,—Ûʼnf~ü)Dí6»_w&×Ù6Ûy²XþøðáÛOù¢Ø»dñðä÷H¶›¼(Ç-¯v-ÛÕ:Η‡rµŽ–]·Z'Ûý²?Ó„m‡=ÎÚ-<3XÇ žèe¨ë7´}y”瑱¯ëÐË׿·QJßu){´ÏL0¶—‹itU]TSnVë4É–˜>Ë~¼ 8݆yÒaÒ‰š¼\ûŠ yÈô«ÿ<ü‰8¶Ž¢M‘eÌÓ¬èøoøÇ¨ _J Í£’Š^Ø„×;<^ªŸéò·pÌUãëty+ÀåkypDön°ò±ÂÖØ7l¯$“ý²´†Oâ±b!qIyo1˜ÐÑJYeù¡èDÅR :†= 죜õ– G¥;ކˆÒM‘¦°ïê¾´ ³²ú\%$§û%‚çÙtxÉi+>ïÞÈ\7œN¥l Á“ /9ÔUÉÒP\};Ô+>F+Â{.ùñ,C/ç²?lÁ˜ p”VˆÕ©JIì-ÚõÀô ` ñNÏpk}‡¶\ÛÌhXaO¤i)Ù@{Á–WªjbÈo:™c­LÅ–èIVd‰Ò­p,HÒlF>L"—g•V‚sb§«m =„5J‡iÅ#Ûw)£ªb¶2_)Q]{)%ÓÕõ¶‚$«õDcv|úàœCïîr±­èÿE†:)* ðÃC@wºƒ!Ëä¯4þÃÃç?œ[˜4/û¸"GGÖÂö#PÎäèµi{ÁpµæÐWSËç ^&:ޱ3§ã~Âqmד*çéR7UÝ1s1'p)Ù1-˜€H”œUW5'öo‰÷kâcù~öB\ZgÙò7q ½ †n’0³£§ªÀ›±œÎe®ke”e;ìÜÆ#aØÀaµwæÅ˜ †‰ÀôŠ]-ú[Ê×^5—X¹µtú¤³*bUñ@ž=Ž„‘‹]@Øñ½P’"WlêÙˆ)|°"­%PðŽàãeζãêÄX…ío:9d„7Vµª>z'Ør<Ÿϧ’¿å s[؉ÅÂuÕ+ÏKkU>}u‘`,Ÿ/ ¬!5‹ˆÂÃS_6ºÊ<{Ie¤á£Õ‚ð¶ñ(Ô¹A¯˜|I¶%_ÂÚtAû®ÔÓ}«((u9’{{x§2äâå“©½`„ÜAí·HÈYæ½Õ4àF¼Ë¿X6‡RÂâÛŽYGY¼ÞÕe¨— :Ðb•LhL«ƒ_ª®r‘|Üd z.F± ³C=ýý7²OF£0xæxi‡^|«|NÔ(eª1läó‘£V¯“î¨õ8.Îûg—DÅä~Ú”g;=Åa°;X~7Üu¼Hs4ŠWÎÆËúäp‰Áaxæ£19f00ò¸Ú’AÅqúl‹‘•˜ z­5b¤ïqÆbÕ·jÐé¶`50¢Ùd*»ývù&òe­ 3Çú6}o4Ñ£š;0ªƒ-)“ xÅë4Q@»¿ÉZñ\ÎâyÄ0œl¬a<­!÷¹”Lõ÷Är7s|7ÿY‹•˜ÐsøâƒÆô¨˜í~xðõa”¥›]”.P&ÆE*%$&ìI!þ“z€Ï‹É9Æ›âÏýùúüåó?çÄĤPÑ>›3«gÌ×H˜ã …/ç*È*1bêšk8>“ÉÃò V_Ù¡ÅyÆhÐçé2*Þ •Š(-Ugèz¿Ï n^@ìתC®xªV—L$ΚÞÖ\rSŽe`¼|©z)•zùnÆÒg/vå.T“ìˆx$õ&Í‰âæªËÙwRA²}Ú£À/z†sÌ"Ê#Jtio¥.Y „?8 „–R­ÊЬJ»S¥[ ‹ukŽ’>Sð;Ø–;äÉÎL-‡Ì2Ë8[UÍJì4ÈoÞ4 s©D/¥‘tÙå­ITOô!zÒ‹¢8*úv¹§ù¡`ty(§o[0Æó±ô}×àç¡1O–W£‰4ãI2¡Äe2 œ¿è;JZÈMÞeLj.æ6ºK7Ñv¿HwÅ&‹ßqz€ßXë #NôýÛé…Tp¾w±ßl)BLöžû…ùêŽ3<Î?É,¸úH¸¡:ůN•ë0!æÉÔõ„çuVì“ÓŶ‘±Ÿ$ûQ­h&wÊÄÚãí~³O÷“­{ "#rÿ+8G[ŽÎéòGh¥è¿dìŸÙ"4ŸôÀïDç\˜õSÛÁbvåGµšt,Ùí@==SŸ`Œ]ƒÎÊzhÃz2hs7ÇÅS'Ü‹ gYMú9ó¸f"°ö*d­8Þ½ïVb¥Ï¼°|šgaÄåþB˜Hõ¶õaË qz|Ý ¯Ÿg*õLBœ“Áq½³ý¦“1—g@3¤×I¸>÷2é8‰w…×7L®•y&@ÀW—hB{ Rfæ¶F~y“Ù")ŠMü{y^Ðs››ác=ñp63è™DæBS5çÖ_*à†W1$Š7»í4Æ› b*–ßÿ"/b.Î#Þd@1YØn‘äû ívש8˜ut›÷ìÈ™d¹QAD©úžÁ®ÐØ@/ˆƒ.‰2,q†ÑR½A°™W3U6@䊎@|Ú H3€æI•ÈïSŠòœÎÁ6¼ýh¡­ï&Є‘=8•R_““%^ÉT/–ûƶÜýJÙ57=Wh‹cx`¸ÉÐËŒ¸¬Så9­â%Öï‹yJÁ§Åû…ó ¯ hNŠO«}[…p‰›_l¹á¥Å[åa«<êÆñ–‚Ý?Ĥ ”¯|·=‹Ÿ¥Œ Ò Cˆw”š˜šÇ þ—®Qr¿f©'Sù~Ë»âøGHsš®{¨¹­ëk STC.“¤o×z¥Wßü#Ë#ÊPb”/T À–aI®íLÈå½[}oØãåÎ-EGôeIš±ç© 3À ‹xM¥Öpƒbü-Ãç¡UësÊ|;-æ­¸+©Û¼"4®ÜbáÆ‹é|B§’˜îÉdÔÃÇ:z0½Î Ĺf‘Ç5l›H«k]”ÃØ´>ÕŠ¿½›2£1¹—&·.¥[ÞȰ“ŽPO%égðY)Ákø°¬Ÿ9ÚâͱívëÚ±¹Ziç€Ó¹¬¯·8Çv™•IlâL/ßKƒ—bOéÖëâÙÝŸ©sxºÃ„ A“íØxJ“ˆOc.á]y„×IÆ3gÚ‚ÆdoÍ¡,¼G}íüªäÏ2 %YøV÷¦i9“÷ê;jWÖR…;ûRŒíãKU×2:6h.‰óIšpøÏAƒ‰‘áЛá[nègXÃ[îNJë‚ÆìJÒ_ÇbŽdú'æÜÅ_"øÎ–z;^òiÛÝUx€ÅUÂÃX•¿LZÄ\ÞwÝ€»|ƒ ¨yÁw„únÐcrã"_žZnâÓ§ÒEè9Q/ ­wÛr%åËÅ"—»äB[=E~Û¿Ä Wi|Ì|X\®½Ë ½<™¿Û˜<×”*|³—Í_~$‘Há8MðXhïå®a1im\%Ëìºê±.§ mx·Ï*–éÕÃ,aðŠÀÞ‘¯*œsO’©oÔ[9;¼£ˆCå{±­Ö5¼ws¼í¡ ¼®¾’ìü0Éè’,V<™÷æ»ø_ÂDÚTÁèxÛ›E²èæ×_”éÅß’ôb™ïögùÔ,£Ujd-yñ7Áp"hÜ8Nb—ºÓU¾\4ãÕõ=ÙOòEN?âhšíòH×Û^,õ­s®WºÜ1ÅLwéÁ ¸OGcªB ÞÖzOyÌÃÖ0i¤=«;bhþE ¦ørouõìb"¸ÂTOBƒ)tÅYÿÇ99[IÄñåA¸Ê“™Tõî¹êÐ7Œàa10šÐñMÜ—ªÕ4c,—<™laËKÛë»^pYÅôq…°²Ò©À·@uô>Ú¡¯ÇZñYf*¶{] ÝUOù r‰è_\ÄúCä(rQ¬ WÓëo˜4;–nzü F§¿9‘Bjë"ÊQ^»òqøR9Æ3þBv$÷ÓL_¹ÁÀÉ5fžÄeÇËŽâ/¥1Z$_¹™u.Þgp-AÏÿ¿ƒŸéu.øH±›óv/·ØYå`„uCšä˜v«ˆŽœéyÑ&ù­{qc=÷´úá*c¾Ã•·^'QÏ@s¥n(_}¯ƒïCÎE®‹CÌO)š›‘FEìêxÕŒˆæ| ”fƒß*ÐÛêeä^l‡rß)º»…9®Âßଋ|¨}˜«îŸJã½óÊö"9çùGSe»›7r‹ôÜ/¨ 6ó~“þØ2Š£Í.»Ç¥ ëæ¶…m¢tïÑ€Ž|¾•ûíç½þJýz:endstream endobj 214 0 obj << /Type /Page /Contents 215 0 R /Resources 213 0 R /MediaBox [0 0 595.276 841.89] /Parent 212 0 R /Annots [ 219 0 R 220 0 R 223 0 R 224 0 R ] >> endobj 219 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [153.618 502.361 228.172 513.209] /Subtype/Link/A<> >> endobj 220 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [263.111 466.495 298.035 477.343] /Subtype/Link/A<> >> endobj 223 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [400.899 396.307 506.98 407.155] /Subtype/Link/A<> >> endobj 224 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [88.296 384.352 153.742 395.2] /Subtype/Link/A<> >> endobj 216 0 obj << /D [214 0 R /XYZ 89.292 765.769 null] >> endobj 217 0 obj << /D [214 0 R /XYZ 89.292 573.545 null] >> endobj 82 0 obj << /D [214 0 R /XYZ 89.292 573.545 null] >> endobj 218 0 obj << /D [214 0 R /XYZ 89.292 538.835 null] >> endobj 221 0 obj << /D [214 0 R /XYZ 89.292 455.536 null] >> endobj 86 0 obj << /D [214 0 R /XYZ 89.292 455.536 null] >> endobj 222 0 obj << /D [214 0 R /XYZ 89.292 420.826 null] >> endobj 225 0 obj << /D [214 0 R /XYZ 89.292 158.2 null] >> endobj 226 0 obj << /D [214 0 R /XYZ 89.292 158.2 null] >> endobj 213 0 obj << /Font << /F8 119 0 R /F34 127 0 R >> /ProcSet [ /PDF /Text ] >> endobj 229 0 obj << /Length 3532 /Filter /FlateDecode >> stream xÚZKã6¾Ï¯hìbÓŠ%êaå– 6ÙXÈ4ÃflK¶•ÑÑäôt~ýVÕW¤èÇÌ 4)²X,ëMÇú‹¶e””ÉC‘gQ‘—»îÍæá@3?¼‰"ó(/ùëÎäc¶É¢rk ß=½ùú{“>ÄqTfÙÃÓÞïb6Ѷ,žªÿ®Òh¯âxýÇIºú¡¦Îª¯GÛ64>Ù™›¡ŸÖÿ{úéëï·eTæ†Qmãmd¶Àòt¬GZjâÍêh'tž×I±ª‘†6åjâþÐ)dÓ¯“íj¦ ftiöó²ÊVöDs3}Ç«æ*ê6‚nÞí04hwCwjZÝc˜ ~ÁÖZAs¶‡Z 4gÜ­‰à£nª“?Y&òÏu–­,f†3ïþ1W„ÊapBðÑ–iš]íÆ#GEHÿæs£LHÓ'ûm›K¦(¯$]u< <9ñõôE½g衞i8r¦…š¶žËc®q;0æ“üKC…Y é¦ety_;ÎÍîÜJï¦ó=l·rWÜöÚIfÊÎ tk †»™ÂMS¡¹‚hý˜o¶«o1suW4¢²0â«ã鳈}µ­ªµ“ÐW ‹}ëXÄÓVçäfÆZ8ê¥VP$ì„úZb²K5a¾ä—¦; ã|£K&ò¤$X†™fáG¼êjÜùD×a¨ã®Ã$tkÇ`H^•x"‡ÉLr¨ µLâyì± ³,Û¯øèkOz `xÕW|Œõó™™ÞÎøÞ˽tø€³¨Œ;w iË5ÐtÕL3‹^ó,Ò¤{±”<êICYÙ ÜTJTìíÌ:Dâúã%rbL/̪A$²Âˆ?œäcTSó¬7,`B#ú]s8:5#pb“âbVwÐ åƒê¨: LÈ+Æ :|\(3É\ 䃸'bhÇ ìNã;7à^fazŠ£Ðv‚Ë»±ÂiÝ騃ê?ëV|õrcÞäóÂgÐ)¿<±Îö8Û6½x*“¬ô"|ù©¿k5Nrìlx‚ïßήçn;³ê1ÿûÙ‹$ˆRéJW×*ù¢¶£ˆË+y ­T*å´ÁG˜fK-ƒùN €1Ïo™¤&àÛ‰MZœ­žÖÛTnž *1ÌÜ뇋5 “ïA#ž³'ÖÛ¶ÙA¨h,YãIa&KLÞŠÌöºáä°­U-òØ$Òb¸Ó:¹X¡ôv—¥ùöÞßïÜ 6ÊP¶ ›XÙ¹¡pªF8ÄG¢C´˜f‡*ŠÜ°;f¸óä5•odC× ÷Òa¹Ùiè­ØÜW ½¨dÇbÏó‚æO?­¤¨s•þÎ-# ö+<1žúg1 8Áãóÿqv,ócw%{¹’DõÖz.GêçÃКÐ'ET$EU'U¿ƒÉFÀYdðÐÔ˜ÄÝBëƒXìr°etªƒàœ§‹•‰ :·-Ÿ­E¡õ“ÞÜ;9£C¨øŒÃHR¿ÓIÆéÝ…bI¸³I+b,Oûvöƒ³XåöÆå”pÞ>¦“­ºÎ iCÊÕ¾Þ¹)’¯½øõ;Þ jý³º©„b4Ñ)j•¸t¢¬ìÒ)ö«Gö Ññ„«NÖj>:¬‹ wüïY#Èë'¬A‹úRë,&÷›ñ®Ü¡ezKä3ç.¸%T 7ð ha>|ÒÙÙýæ<©è`å³'² Tn S̓Ä/„5=ÆÁ*ô%@@Æö1/É>Rß¹8^îZ5 ´X-Ö;r9C›EŽswמ+ „z[;Ü‚á[qa?†Áù&<'}È9©]D€“º@tÛ ÙU;Nžm› 6£¾.× ýÒçUE&3K|rNWzWÅN;¸o4{³É°8ÉM”lÊÈ”.ÉN»ãÑKÒ(M·—9ɲ0!ã„wÔZ4ÓÑŽ¬ÓÜŽœùA(AÌË6¹¤(r¯h³ÏQ4|LŒ‰¶iqÁÑihϳ³¶ì ‚;nÐÀ’=Q(n+1¼•FìÃ`½¿ ÷÷¢ëçK7s/œ‡K À™0÷IàZ8-þJ$曆VÇK£KÑ]…¾Dô. ·£³cð½&^ >IN^hh‰4JR4B0 8#3iS– #4yï14ŠOlª,»ô,ã¦P¤·Ö Ö~d.õ½óú†kG± ¹8¯{43 ¤ôÜ¢™ê“E!ˆ ØsYòµn¯ÞÃ,éüµ6Ž ¸@_ òš<µeŽKÒ®*#tutÑoïhyÃn³D+Üô3mŸ¾©j(„/ñ|$2ÌQY ¤ 3"÷½*ÈH k .î4óW…ÑÅZ¬¾FB¬Ú·%˜ÒõâÜ@d;1™wŽÔZŸ˜Ky'‘hüÝðÌhxöëºLyq­Ñ™FiÏ\æ[ÕsàL?©]‡<\B«˜J Và”Òºìˆú¿Å&eÌoþõäë¹qi¢´LL^FI¬õ`ž ñKPüuиR¯12Á¿Jr3úK÷ÍD}Û8#§IKr2„à‚´«j´ƒùA×x˜ €©ð5í0 §#L¬¨ðbñSˆRDŽš¿äVûlú¿4;þ:rJ.?°^=Ë"M@dØê±%>»:B‘FYréÔ9ª²Lß\sG+ìÆl£Íö.sbâ@’ß/㓵Û~ªÂ“-ŒKæé‚[x§Á-'yg©ß_#¢âF¾LÅä¡?C磃¹ÙÐÁ††6Œ‹‹ ß7Ý©•¬±Ñ7þfý˜l ¸å''Í¡G¿CM&gÍË‚kñJñÕ\l(L3"OYÐ( ¬×’¦È´¦Þ<ÅîNMàI°÷v·Î5WöäG¦¤ÈU(·‘,É‘E’%„q¶ýŒQ”-i¼ÃñJ"Š)rÔÐ0ì@±œ”ÖLî˜ r´ØsŒ)úéw¹OAOÖøø£Äee[%ÕÉ…Ì×Èh³A<ÊÔHd#¬ÐóÈÚØ,>q­Ñ½$ƒm·b±¢¸¸_›¤¤¢2aÈy8î{×!I|3ÖVMï}-L— ¯sÍæxiêè½c«ËÆ,E®œë¡dh)ÔÑêéUë €&â/Ðâ­Á; жi¹úÑ•¸”<õ'“¶¥h¶ÈÙ)²à’ Ww¯0ÔµÜA×ËŽAʳ§ NÎÊ“§Ë£ŽáJÚm[ûO´;tVÌ¿ô†%6—tñú(DNh{-š9Àf¢”|§:·Ó2«TO›ÞÎaA& CÏMš-‹Úá˜åóC/ñå î áµ¤[f¹c©°·K²¿š‚êÏlç/âO¸ûB`¿ %–xå30• ³/ÎÒÈ‹2-êº¹Ø Û:Lä¬Ï@jB«ùŽ~¡,ÔÜ ‡¨«}Ó¼zÌM𢯰¶@êíS²Ú×KUlàHö¼è?C“¸ÿrl‚Õ´Ð"8ÍtZH¯5¼•Éá4ûÂSóW]±öd%1Ø­r­F—ãQÞ?u0(&»²®õ<Þ½'—„ó%)á®0ì{'æî|vl}v¤xa:·T9ð­ªÜ8‘–ÂùIñú–:¥èÍRÅa=ÐT†8”!LTÀ;vákòbà %0è€A± ¡q¯<÷”Эg».¼N‹˜¦%-2p›•+<泌ÿù'^Ç—!íFcs®ÒOÞÜ©+¦r»YÞJi è=DŒŽGŒèrQ§±qɯÌTúLj î.· Ì;+/x…þiî—ìו‡L±<¤0ÌXÂ^<üExéø÷°v/rf}O‘ VÊ,ùãL:U¹Ì8)óåÄKq*)©HJïÄÚáiÖ!­£Ž”ñLŠšeî‹<Ö±…?œ`ÙÇN'ÌÝOº÷›{ïQ>b[}†v÷»¼!èõŒ“ÊäÀ?—7h²A{¼j7úp-RT]¾ˆÕÁ„ù0æ!©C8­Ét¯Ã×”Êcœ}vtZwõ"ïèˆWïðBñ¦ƒ†žÐ¶‡ADu>voÕ©ÑÙ×ÖרäÚ<}ùÓ“À&ùßè<:RÓQ£XýÝge)Lh_Ɔ¢–&<$JûŽAߢOþàéÒåÍοŒùŸ]áµ%³®%Ó“¿÷ÿЉ£¤‹RÎFñbíë°~²éÀØ?~ù-Ù«gt/w‰Ãš q±CZ4Åwúæ´Ëo"üÔPvÒVÍRãÞ.ÝFl”­¨« r,Ðkt/=JBuDk¡ÉÀÊÇÐrXñû nœÄQN‰æ½ÄQA˜›ä¿Ì¢8-<æky½•ûMÛ½þeNÃÇendstream endobj 228 0 obj << /Type /Page /Contents 229 0 R /Resources 227 0 R /MediaBox [0 0 595.276 841.89] /Parent 212 0 R /Annots [ 236 0 R ] >> endobj 236 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [192.498 366.286 264.815 377.134] /Subtype/Link/A<> >> endobj 230 0 obj << /D [228 0 R /XYZ 89.292 765.769 null] >> endobj 231 0 obj << /D [228 0 R /XYZ 89.292 724.465 null] >> endobj 232 0 obj << /D [228 0 R /XYZ 89.292 579.066 null] >> endobj 94 0 obj << /D [228 0 R /XYZ 89.292 579.066 null] >> endobj 233 0 obj << /D [228 0 R /XYZ 89.292 544.517 null] >> endobj 234 0 obj << /D [228 0 R /XYZ 89.292 415.335 null] >> endobj 98 0 obj << /D [228 0 R /XYZ 89.292 415.335 null] >> endobj 235 0 obj << /D [228 0 R /XYZ 89.292 381.174 null] >> endobj 227 0 obj << /Font << /F34 127 0 R /F8 119 0 R /F35 134 0 R /F14 152 0 R /F37 149 0 R >> /ProcSet [ /PDF /Text ] >> endobj 239 0 obj << /Length 3377 /Filter /FlateDecode >> stream xÚµZI“㶾ϯèÊ%TÕHáN199.ÇårI»rˆs€(HÂ4… ¦»óëó6,RKc_\S5±<oýÞCgO)üËž¶í&o󧦮6MÝ>uçôé#?~ÊdF™Õ›ºÅ¯;ƒë*­6í¶xZGþúüéOÛ>µ›¶.žž~"ÝlÛöéyÿïDíìÔ_VY²èÕ:Kzh½¯ÖEÖ&Ã*o±8°`ç69©U¾M¾âš§)þq]Y2vÀÕ÷¼˜ )œ°\ÎÜ×MÜû>ó,yÅL0nâIÆ2½q’c,'Ù½£ ¬|¦™ÇՈǑSÀN@j:ã]z5Ççß¡oí÷<žÖ«ÿ<ÿºÎ²M[UÄ¢^‡ËáMŠ‚Ø¤ÆãEõW|úáÙKB˜\·ð[ÝUòÈëûb,A†$œeå&±­ipV gy½ÉªÒíŽÇÿ%ÍšÛ3fE¶ÉŠê‡\»)·»M´[»eM¼Û÷À™É©Á¼ª2àü×-£¶öÏ«uU,½2m“=NÔ–X?BW–‚ÖeÉÅ.ü±[U9òÛ’™n©2#‹ˆ§JQHØKÇØ!u=U»^6Uö°›ÕºÎªä§é8R1¬óØ´=«ÅÒ¿ßQŒÑY:UVNüËýØnk†3Ñ2åªI-¹ÏÌW¤³*],¨êf»Ei´`ú%íú|Ò3RkòDq£HFæ:6_ 9N¨°¯#Ïê”>Ó„×°~oìÒuÜ}$ýù¨,>µ¸5JH'›cIèÎù< î¹}ñ„Þ qî2uÔ2:k:$Ü”"Ãk‹× åmY^1Zïš$²/ƒŸöÒáUOøÕ$Jz÷nójÓ‘éì:7»¥e;²tæ5¸|GƒÐ"!†T¾áˆÞG–òË8êg¼›Ðˆ3£žÁÉ•ÒgçÝ1sv'î–xË# wŸ¯”¯&žÌj9aWÊrr;`»›@“›ZèäGs %¤{Owxÿ]?LhùVŒŠ6 KÏtuà”îòô_^r¨Bm0IJ-8ßæ“·’gqG0¤dzd]ÜÄI9[ùˆ5Ä'âl'3 ¯^f£…àÂ~×ü’åA™ž¿¬:è?pSti[::(i ´8¨ßh—þü3 xÄSRº&—àݰf û eÜï{·g±Í“";qÆË'0È‚›¤Ó Ί) ¯ö!öÛ?;öKÎˉ g2ÄÈhWÅöböA„(*=wlTûÍgk¬×'ÝŸ?¸,ðX€ÏÀgâ‚ði(¹T#o‚>bûÇüÌ EaKàÏ4¢i¤NôŠ>„lý)® ’ Ÿ½˜ñ4â¦[±“œ4”†ã½=Ú¢­RpₚeÑÞDØ4£z„ÆÊ¼ì”ý.p,¢ý¹9¿Ⱦq΀Èn7¼Éâ =&“Øš.Õ¼’ˆŽ¶ ªàYÑf‘á‡Ä¯T:yd±ð ©ò;·Ìpæ ˆJÖX.’õ±Š¹ÈQÊúÁæ™Ðêî÷ šÄA_Po êöÝ n*I€®B‘FY;Œe aá-.%yh×n?À4îµ§‰B—Lò`´ÝFüp[íå8ÄìÁs™wè3Ðù˜¢JÙÿU)*(e£pCîÿÈ?ì5þ% yuÇ*õZM.“Bly³¿@wƒ89ÒYB4•/ûã²W°¸S¶#‚o"6äDzèåˆâ -འ¸¤„kèÄ%®2Ü£BRtኻŽÀ¸Yõk0—Yâ½Ô°{vJ¾ÒÂU Xjß=p`p„uJÀFÏîµ@³Ðd0ëÖ…³‰GN4´çE:_ýnË7J'jÓÀ=gU±• ÷£IAÙþÜ÷®—I)&2(©Z tÇß¹Þ‚°4^FEB\xR’!|Ūsí]¶ LgŠªŸ‹ËP8ðG³:ʈKðÀÝ—ÏrÊ-ÉK¿/x°MAæÓ¹×Ü1˜ãIWQÖR‡äê O öÃ^ˆLtwYÂ>ÿAR’¡puÈç?UÊ¥?ÙÁÝ=‡C¼š¬?1u'S<¿WóQze_¤%Ì;™§ µ¢!ä"`Ÿôú䮣cI\ äz·5Q]û]gúqÒP¢€ÊSäM´gÕI“(GgIŸ‘ ˜¤áX”4æÄ¨Dj\KY‚lJ®ˆ–ƒW ÃႇFG]–yòk–¬4r"Å?ýÊD¾L»°Uf‰m#죷æA_æ/¬‹#Âb«¿•y¯ò‘Ù°2é=Vi EZ˳¹tÊTür ÙwÏý‘îÓ‘Â †Ð¶HZŒô)q—[\U{$¹»VÇ)~ù•"*ã7E¼Ÿ/M£ö!ÃPBy=5üÑò¢½àþË ]ÂwNoI{™„,SÇ” ìš.ËY¬?ŸUæMI6‰½³fåⱓ‡#šslùâŒÀËͦ~ôF”ŽM;dl çƒ¨+˜úãòŸ”ö£©É‹–ø-fa¯}}t#’ù7NM'ƒ… ’œØ™†óþ°Ø‡'˜æ´ Û½w\lxøMÑÖð[:4‚–7®Å—òñœƒ{ñrÈçž9 ®b.]êþmÍxÍ—ëÍâð}¶Àú+1{ༀ}Ì·9$妋wl@hz^µ˜*kžÌ5&uû¸GŦª õ86 YMþÓkŠôÌ#uøÁ ñež‡ ´£4(Éa5‰ú슿05hŽsÝ;Ιµeñj‚gØqÔ{á%hôë IHÝA&=}|æÌ`bq•ü˜]‚Ìsê¾ÃåóoWŽóU-U+QÎqFŒâÿ›Ó.,Yþå¿Æ—Ë•¨Ñ1aàà²G‰6 ŒpÎTä›mË_ÁŠ RAN:FŠÎno‘,,ÍËæÙ# ËÈ)@ÓûÏÅ8ÁçÌ,GŽGEPBÃ!‰Úýu‹žåe[ OxŽ\7uº¢Otå*è)ÎB‘Ÿ=ñ¤èîÖÀ¡ŸÐïéxoÔÎÝì¦FÎJù E󲙌ËÓ¤,cTË(f”9ü°®øOUj2K]•w+ 2e͹ý›)‡¡Ú“Á‹eéí^îlöôækXendstream endobj 238 0 obj << /Type /Page /Contents 239 0 R /Resources 237 0 R /MediaBox [0 0 595.276 841.89] /Parent 212 0 R >> endobj 240 0 obj << /D [238 0 R /XYZ 89.292 765.769 null] >> endobj 241 0 obj << /D [238 0 R /XYZ 89.292 216.277 null] >> endobj 242 0 obj << /D [238 0 R /XYZ 89.292 216.277 null] >> endobj 243 0 obj << /D [238 0 R /XYZ 89.292 175.452 null] >> endobj 237 0 obj << /Font << /F8 119 0 R /F14 152 0 R /F37 149 0 R /F35 134 0 R /F34 127 0 R >> /ProcSet [ /PDF /Text ] >> endobj 246 0 obj << /Length 869 /Filter /FlateDecode >> stream xÚuUÉŽã6½÷Wè h)Ú-{€IœˆoA´D-Ó’èˆTÿ}X åîƒÚdÕ«•¯Ji¸¿4¨›8k²àT•ñ©j‚vyI‚Ái~}IQ¤U\5p{¢ŒÊ¤Œ›:¢¾œ_~þ¥š¸©òàÜiRÄY^§<‰ë¦ ÎÝŸâ-ŒŠ2½ºÑa £Tȧ0¥£!±¼„QV ½;¹%Q§½»I;éD™Ð=© Xjímè¬navrswúB\ÝqÓaTVâ;ISÑZ5J°ùþ1bŸ¥V‘HoëÃé#7°Èqç<'cÛŒ2á_ç߃(-â¦(Üo7e‰mèœõuq1ÜÑÆaÔ$¹ø‚q{ç[o©®0(fP88“a8çA®¯®Î¬’ä½’Øhðeë {t'5ꬓîJJh3v*%-4RZŒØÆŽ’ÃÚ‘RŸD«×QWl ”ž|*ºÕûì<äÕ žÈ½îöî®î²8‰3{Ê«Úåpä<¬d0RŒêæ¶M˜©œç;Í´øfv'Áí‡0¤ÕWÿÜ [43€ÎxÇ=iÚÝß kNPrøýâ§,#ú'½˜–+SÊJÿŽn ™ªÎÞ …qý)òTüMÝô:y0 “¿ž×ó•âgM.Å^ws°jŸI´)³ÏÖÐ¥‡7Ö Yu@’ÇÓO$ºêŠÌÖË9ïëG>–hbìš!~Rø7¤òF_$R&OS ªÝ7_…!¡Ù[€pK„d)§€­¢w2¸³vtX½«ßÕc7hˆóNÎÞ¾¹óoìµjã”öã%Ù'uqV­>Oä ˆœ½Î²UæSýÖÉ^ »Fu§‹ßWp6£Æ\ÁWž «éwZÛÇY‘äÓ®A‰!ò#£™¦0bÇ“5ôV L…¢Ïå Vè2©ýàb¤µûå‚Ëp÷tí|HxZýøîнC4y6*ûZ˜Åꆫk&ܨÉ1ö hJñ2YR#_§Ù¾Ò£xJCë ¼þo;ojö}‹öö7ÌЄ´|ÇÕà´DºÜM¯DâÏÌJ§¯ êþË×óññäooš¥qUO?¯ ‰>`~üº:½SU‡H> endobj 247 0 obj << /D [245 0 R /XYZ 89.292 765.769 null] >> endobj 244 0 obj << /Font << /F8 119 0 R >> /ProcSet [ /PDF /Text ] >> endobj 102 0 obj [106 0 R /Fit] endobj 90 0 obj [106 0 R /Fit] endobj 248 0 obj << /Type /Encoding /Differences [ 0 /minus/periodcentered/multiply/asteriskmath/divide/diamondmath/plusminus/minusplus/circleplus/circleminus/circlemultiply/circledivide/circledot/circlecopyrt/openbullet/bullet/equivasymptotic/equivalence/reflexsubset/reflexsuperset/lessequal/greaterequal/precedesequal/followsequal/similar/approxequal/propersubset/propersuperset/lessmuch/greatermuch/precedes/follows/arrowleft/arrowright/arrowup/arrowdown/arrowboth/arrownortheast/arrowsoutheast/similarequal/arrowdblleft/arrowdblright/arrowdblup/arrowdbldown/arrowdblboth/arrownorthwest/arrowsouthwest/proportional/prime/infinity/element/owner/triangle/triangleinv/negationslash/mapsto/universal/existential/logicalnot/emptyset/Rfractur/Ifractur/latticetop/perpendicular/aleph/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/union/intersection/unionmulti/logicaland/logicalor/turnstileleft/turnstileright/floorleft/floorright/ceilingleft/ceilingright/braceleft/braceright/angbracketleft/angbracketright/bar/bardbl/arrowbothv/arrowdblbothv/backslash/wreathproduct/radical/coproduct/nabla/integral/unionsq/intersectionsq/subsetsqequal/supersetsqequal/section/dagger/daggerdbl/paragraph/club/diamond/heart/spade/arrowleft 129/.notdef 161/minus/periodcentered/multiply/asteriskmath/divide/diamondmath/plusminus/minusplus/circleplus/circleminus 171/.notdef 173/circlemultiply/circledivide/circledot/circlecopyrt/openbullet/bullet/equivasymptotic/equivalence/reflexsubset/reflexsuperset/lessequal/greaterequal/precedesequal/followsequal/similar/approxequal/propersubset/propersuperset/lessmuch/greatermuch/precedes/follows/arrowleft/spade 197/.notdef] >> endobj 151 0 obj << /Length1 772 /Length2 576 /Length3 532 /Length 1127 /Filter /FlateDecode >> stream xÚSU ÖuLÉOJuËÏ+Ñ5Ô3´Rpö Ž44P0Ô3àRUu.JM,ÉÌÏsI,IµR0´´4Tp,MW04U00·22°25çRUpÎ/¨,ÊLÏ(QÐpÖ)2WpÌM-ÊLNÌSðM,ÉHÍš‘œ˜£œŸœ™ZR©§à˜“£ÒQ¬”ZœZT–š¢Çeh¨’™\¢”šž™Ç¥r‘g^Z¾‚9D8¥´&U–ZT t”‚Бš @'¦äçåT*¤¤¦qéûåíJº„ŽB7Ü­4'Ç/1d<8”0äs3s*¡*òs JKR‹|óSR‹òЕ†§B盚’Yš‹.ëY’˜“™ì˜—ž“ª kh¢g`l ‘È,vˬHM È,IÎPHKÌ)N‹§æ¥ ;|`‡è‡Gy;kCã,˜™WRYª`€P æ"øÀP*ʬPˆ6Ð300*B+Í2×¼äü”̼t#S3…Ä¢¢ÄJ.` òLª 2óRR+R+€.Ö×ËË/jQM­BZ~(ZÉI? ´©% q.L89åWTëY*èZš 644S077­EUš—YXšêé¢`j```añYriQQj^ 8 ÆOËljjEj2×ÍkùÉÖ-YÓ·µ­¬s]|a«>çÏk_Þd?±£nvfJm°é¼@Åô’%¯>ÚÚwX<û¢„W²õTá¢-’½~=q_ ¯ÙÚµ`YÄ„Óýz7‚Å+›»¦ñþÓVåy¸0lÆœÖGÒVû‹ÏêTÖ¹ùE¹þϼ”NQ‹÷}¿w[H+h’–’”ùÍìwÅÄ+ï>¿,ÿiGýôã¶ÉïÎÞòñ /vëR¿˜fÇô%ñۮش²‹µŸ9¼òâQ¹DÊÿžýÑod;”ÚU? ^Vñµ«Nºúú©vñK¯{~­ñçäÚ/ëtôî…Ã-Çé÷7¸ï“õ‘9ñØ8ã·Ô m¿i"é÷Œ™6=Û!y:ëIèÆõ†íÿ_°K-­û±,1{Îö)².oª —ï¶ý*Þ[«ç½mFäû%»s_Û-j(lå¦sÿÏùœ~gغŒ|K·~›¶#£ïµ¾øÓ·&g®]p_ò¸!—GrnM`ìv®^ÿD·l½ŸÞë>Z`.x‹“Yh—ý.Ž#ÁÇ8©¯Øw6O~¡—5“{Þ„U7¶ð807ì™õ…ûk4鹇Wñ»5þô öŒïùfÕŸ”ÛV¼ RÅ—÷mõ‰_A¢ëX¦¼OïjW;[Ã(Ï´ÿÇê¼uï,¥n˜ q(ï»°õÆA®æ…Ëü+Ì»·3z^›"_Õöûÿ‘Ù“O:†~ýUûI¯H$P†kR¦½ÏíÏ-‚©¢áúº×y'y=øØ'sµñó‰BˉêÿcÙWdtDÇ?û:`‡‘µªñ½w¦[K½ð_°È€BÀ5jÀ°0 9'5±¨$?7±(› Jcx¢endstream endobj 152 0 obj << /Type /Font /Subtype /Type1 /Encoding 248 0 R /FirstChar 15 /LastChar 15 /Widths 249 0 R /BaseFont /WSZKSC+CMSY10 /FontDescriptor 150 0 R >> endobj 150 0 obj << /Ascent 750 /CapHeight 683 /Descent -194 /FontName /WSZKSC+CMSY10 /ItalicAngle -14 /StemV 85 /XHeight 431 /FontBBox [-29 -960 1116 775] /Flags 4 /CharSet (/bullet) /FontFile 151 0 R >> endobj 249 0 obj [500 ] endobj 250 0 obj << /Type /Encoding /Differences [ 0 /Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/Omega/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/suppress/exclam/quotedblright/numbersign/sterling/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/exclamdown/equal/questiondown/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/quotedblleft/bracketright/circumflex/dotaccent/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash/emdash/hungarumlaut/tilde/dieresis/suppress 129/.notdef 160/space/Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi 171/.notdef 173/Omega/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/suppress/dieresis 197/.notdef] >> endobj 148 0 obj << /Length1 1325 /Length2 8364 /Length3 532 /Length 9189 /Filter /FlateDecode >> stream xÚí”UXœK—¨qHã.Aww',¸·n ‘nh\Ü%X°àÁ-àÁ%hp‚†½gæß™.Ϲ:Ïéî‹ï]kUÕÛ«ê+FZMÎ ˜XuãäåâÊ©é*óòy¹xxdŒŒrp°¥}iéòŠŠòÀVOO?1A!1^!#Pæì ‡ØÚ¹YäXÿ*¾pÃ!Ö–P š¥›ØéikKG Ìvóæ¾ptjÿ5¨ vÃ=À .//±vZm!P÷_NÊPPø?à wçÿNy€á®OR@–¿5YO’ ÔÑÛ¸ÕaO«Ÿ\þohýûä ê–NMÿw§þWÞÒ âèý_0'gw70¨áÐ/5ÿ§œqwú÷¬²›¥#ÄúÔÖ ääàâøÏ8ÄUâiBܬí€6–Ž®à¿ã`(èßMžú÷··ö möÿÚÚ¿“𖍛®·3ÈóOõßÌû?5 ñóY9ýƒO‡ú>YÁþÀ'+ç?ðÉÊå|²‚ÿOV®à“•Ûødåþ>YyüOVžÿ ß“•×ødåý>Yùüÿû´Ëʼ|9y…øœ|‚<9 E…Dýÿg¥ââV~ äáááù;j퇃¡n_4O¯Ò³ äé탽ÀÖ€ùY˜µxˆýû¦°²ù‚o娬®”é%!#í¡ éâ\?WÄ ¦áÍãº`êSüP|{H^ê/•Ü Á5ò¦~ý¾:Ü¡søýØD¬y:èGÖ?MÌrúºq>DîÌÓl97³-Ð_¬z´£V«îñ ç“ÿŠB)û>{àðftm3 Dÿ#`šÓªšÖß]M¾9P„Àæ‹HM2.æÉ»—'–°ÓE£sÔgÒ%ïžñ°zÙ¬x3hæ_g‹*=Ö4ìàÒr zÌj¦Ï©c —”¸ôàQÙOÚ£ ÇÓÉ¡g¬ Vè6xr™}›®ì?çnH*G)èxõ|í`=Œ×´=ë~˜ywj—‡yTì&sÚ¦twÇ4®WÏw3-ä;7,-3LcfKÎD’;÷Às}l|LrÑ8BPAO=DÓM‘åþ¬×¾×1ÿEA-ͧwR¸ã& ŸKoÌW8¨@¥›Kr“To¾ú$[+N®ÅŒô`÷Mé'¢Ð`†I ážÌë÷œnÛŠ!pŸN̬WbS ”t_ –€… ]ºS¶!3µQµë»‰ð"›æ[*Ty5ìÙ¾¯÷¾á«OÈô›®Nøç•AÏäé=A6R$A¨QÖ|Å W€M;xëu S¢ö¹.e+H»>{Fß “<1.k¢‚écðO`6W¿&~>H„UÜ´Iᙟmãé £îæ¦1gÇhÚÛŒ¸Á»w¸+ÙØaò~Ε5ú?¯qÔ:‹Z§õÖM¡¼oy©´Ç5k:üo@gyAÔ€_m\¾UÊTZ1ÄÂé}k‘3³f”êœìrX«47ô#u¦)&js¡¼g>@I¬Œ5…O÷Fw¡jgÚ3ÜŸ¼m2.£Ñ£f#ÐåÓ⻸„Á¥núÏÁ÷çþì|òÒE,›{kæcdÙðÛÇ.aêw8C‡‘p)Ç_:›¶±®üÖœÇvUÇþ·¢â …¢Å…=©W|eoŸí¯3øúo9F†¦=š9§ð2˱¥hLS.[Ìn¢f¼¾Ñƒžñ¼ójô#)±l?`†¼ü²Ïhy¤N=º¾/w¸˜¢Gxε<.Z¥ÍFÕ½¤-=PÚ0HlFêŽpå6&lÙÙmÊË[ «Ý‰Õ*ÖÌ;¸+´>¨³àæì7Äq.n}nÜ÷‰>Á×°G…pÈóÞ$ìÊX-Ò”€))_èÒ3¬AùS+ø²n îåbLxÛ.c°A ×,Ѽq±|©ã³U|?(޶³‡R ÎÃm­“r ¿œø¬ô5Nú˜J­sÑ/&çÎC1ŒG+{GÊW¤m²ûöû°—§Z’õª)YíÚ߯2çɰªVòpÓeUű¤£Yãõëçï3ÙS i\ñ¾z®ªù®"ÐëHø}¨ÞÇ*I< ÔZï„Ú¿+A+z“D/Å«ƒIkã-ë±¹¸çßœñ;~ [NŸF~]uå=HaáªjÈŸ]‹=·P¹ÜO³Š'ê¦÷Ûw•fwhWA'Ûó 5”åÈ‹t}FU깺ë"ãÌEhPByɈ" ¾,;qmúÎ]í-ƒïZK²¦[HÔ ‹|i›y3I¾\Iª—Ê ƒÆvª±Ã*ʘÛàÆâí÷ШS‘Òt‘Ha#œw=hÃ&¿ßyö©œEdés&üø¹[±Û·kú7Ð%r¶S™tŒ!ÂP»—d4 HÚe!'¨ÖÐ@ÈI¼ùç+ù­ÓXŽ|ø `Å}–RuNÓ^¤å‰ð®×ïÀÄ‚A;,Ud9k‚; bõô-²2ªGnFÈàlšÈÚ¥žtÑ1[Æ«þÁß_Þ¼®2ݨ¯XAx(%„„÷}»‚ Š/°ùåí—)v²%hF#ñ(ã7WûrBßWÜMel‰´¦·¥²{{ºŒùc,h*£FêåÉt•-A)߽ͬ¤j÷uü´²‡ý×½¼ë/h|Ì ×K h-ÕC1XlÂyMVlDê]ãù)4EÈØñÃu§œPõ?ܦ’#¨Ö;xOÇMä+$õÅ—båû¨G’wGÖÏŠÙ–Œ‘Â*´ÂÁ;¯2…¤*¡é.¿“;Öóêø€ïPãÈH¡+Ô£þè[WXÄýÂ7º¹ÈGÔ¦[aøèï'_6 i$c ÄqÂvƒWð¦ Ó@7¬¾’ Ç KÊK Aé7ú j5DÕ¼í Qt¼êæ{§áÎÑüÑmÓ.Gv{¹…¸vvUC1˜eŸ¼ÚWH’Ô׿#w ’Άcvý Gë·€¾ï~Éf•^ªÙþ%Ä7²§ï%â Iù¬Æån½i™:¾‰¸ˆÀ­6*FŒñ†î¸yÁ>@ä+æ&²ÓÙO9ᦄ˜¿çŸ.áÉɾäD¼#—.©Xƒd‰Ë¦XºY]‚f8êl_ ºù%C/ŒäÉÕÉ?KMË@’ a¼rçŽ9 Œ}°q2 7ž&HQü›´Ý-‡ÉPAW} Wà³Úô-} ^êÁ6Ϫý0ûÜ(vx€ý’ AƒzéfÝB5)¶†ïQWø‚ÔOWÓÄ0躜ÞB³?Ó® Ž8 ÷ýçooŠY`·/éÅÎÌ9>–)ÎFW1´Aì'¬Â€ó™ÒGtH^Î>–£ ß&‰5S›d«ÃÚÊW©;Oô‡²™£>î${ ½1&}øŒ4‘ÖàÙŒÎGÞ5‚x|Ýuãiâ»´î×þ<² sVÉщ½wíFRVù¼Ç YL™¯Ö€²Ì×öL)š×ÅùûVÏKƒ¥êæg±Œ ’4[”,6]ç…°è,N/¢=B’Ó)ýRéÕv°¾Ì†hô=_ê±Ä]Ï a½R?,B6øsFÀnÛm½\w†@J¨ƒ—kýc@s Þ=ÎóÙkÛO_»¸¦¬ºËßsûÓcóYx˜£ãŒbyõI~à<—Rc’¿ÌÜ¢ïåÚÛb ЛYE±É~U¤•ÚXÜ·‹ƒþÆæŠq¡CÐSÂá<í”ÆÌܱTu5L¢±ÄûY÷eéý~BæÃ,=§OÊÈ(¦/ôvp—§Ïn2T\°ÚÒ}O5ו?é};ƒPœmØ0¤?vw±D¶‘®§¢ïß¡PæyQ5•ˆDµ”f™¯HÄÛ–æÆ…Õö©¿½ê€­q›ô` (°Œæ•ԪçH2ëÀÍ3y…"± É7[ZI(ž Òw(3èîîñ?õ­èø~$ïó½¢áo‰s6¾—†óþ ž[°9òÈ`‹çRàÙsûè…–IOø&E*>uõóV¤ÞêU°ß:½…XÒ˯)>M±’M\ä ½µˆŠÂø“lT;S}‘4)'Y©4˜àSH#“]æcåã»Ù«|åퟲ~Jìœa.zÂ%‘9è¶¥ñ]›w%åfŠyÛh‹ÊƒÁ1®Ç.seZ^<Ó˜Àãy+f"qh¦u»<Ù²ÑyÍ´™XÖŸ²XÖÌÁRcvF„´ƒu-:'ì®”2ÿêÌò£fe1¦/ë§‹û>ÇÆ[[îf![± ×’3ú¶éW+'5âù®´…3Ãô¶¦^ÓŸÄ•‡Mx3¬+ç­9™_϶|_Jßa';²Æ¼|ù­uiHÐõ½¸ÎØ‚@ÊÊ }ÕNö=&£%F:qäGPIŠýg&ý.Q~÷kü4:#z ±ú{i&ËóÆÄ•Pãk‚ƒþ?K·NzñS*îwäã!yKí`ßþÖ¦×T–ŒmꑪX•ÉׂˆÌ˜EmŒò§=µKdÃÃté_ô©ëѳŒH_M>Ȩ¢a?ëX×ø4Ôª& ºwB ôb¨í1²{}ÂÕÕPRoVj*Rƒ0ŸÞ—ZðqJ²Ç—i3EQ *xŽé”Õ†¿¯#¾¦ÄãJÉ0•Ç´_Z†$/ú|‹`é+iÖe¸¤ü5÷›ˆzûa¥™ZŠºïsB[yìþcFÑ~Ù#£2¦¦ÁT'¤l"6×66ôENmñúò’1¨Ênv”hál%Ж)ÊlŽø»¿Žˆ‚µ‰äéÅ{Â^NkQu¹%åôú1)ß®i*çLkBƒ†LN‘ô>#ÀrA·ä§;ϯÖ}©pS:Ìz¿øMþ,õf¥ÙLµ>š¹Íþ5c·?¢€@ÚcAQc¦Žnð.ª"6y_kþp˭ж´Å{Ì…$ÊÕ¯–Ð[!íŒÙUüQ²–i0“úõ%F›rš¢8‘PÌèZì" -æÙ2úùÇ: λâM襮áQåa­låjÈ£B2Úͺd èì® =±vQ·5pá{Òkä”PÅiŠ=\ëÌΰ‰Ö;•âŽî«%ìµÃM¹ÚmWãÔãP‰œ0q¨Ãž{9;}ç½uCÏ›Ü2ឣ—ª“áÏt ü/„ƒ'ü39ãìÛ{0ÉÃÖʉe”µ¶W•ÉÁ‡¯Üô f#·2§¸ YÊag5¬†*-"WrßÝ@ÑöS¬Ôš’GHNχ߿êÃêbõ5\¶ñ| Œnƒ“áîÒ‡¶AôÜ<…¥YÕÝ2*æÃ*-¨þû±:ã§W/2Ö´¶69tm³¥´ëª²ÖüÊìIÀuÑAâÉÇÖ²¿AÛ5Œt»L¨a'üÒ7‘ Ôh8¥ã…¹ŸÌ,¾™¾4Ì&)k<¸ÐOSÒ¡á|[מ_J™ŸzBÞ 4ÙÀ¢rxy.Žh݋ﶷ^å>«hüø¥–L¼h¹øe7±eøO/*,œ¨UѾ$•óÆÛ³œƒgÒ–Ø ›È \€¬(ÊXWdæÁ”¼y7ñµÏ‘C‚Ø¢‡3°(7'c}ƒ8…}}·×UJKíd½¡»A|éü¤m9’dBOCA_ù­{/‹ŠÀ…Fð³¤[vç|6"—¹Øúò5 übD¤¯6\1x!6o¿©Iƒ¾óÁy €‡¤ê¹ÏæãÇg™ÃµŒõÆeZ«ëmiAmZåiÄÒ{ÈšÅÜ,ãªvkØÓ“3´ß'˜­×ßþ¨ñ´2‘ÀÙü6lsP<ÒñVŽžëœRéüêµp%ê£_ünÁjŸXƒ£ÁRšj{¢Glz»Äž9Ôƒg˿ß ÁÎ h¯ÔY2U$O 4Ð*áÅ‹b“ÑqÚub@6½|_YîUOÉEY† Þ(ï÷@Ês‘ŠÙhÃîd§röÜßÓ_Rvã3‘f 0·{ÙÿeQZý FQoqÊ<Ì“¶4Ü^ÝQôñÝIZÆëÒÓäDc³ÊJP@xÆ¡sxªÍ4%ÔÝu鈵Äí†C[®ËI;¿*ª©ßõ¡ˆ;ÒrUö î§­EDaÙ÷V»ŽíX„èðǵZzjç›ä&P¬÷~X u‹›µù 2KåéBh>ʵ¨ìð±+¿Ly7OâP¨"ÁdTZ^î&*[Y á­˜\G¥£4Q@y×A÷FêMš`y~=|çŽ)]‘ ´÷Ðb,[ëÏ}÷óóÛWö¯›=yÆ;$Ã~› e›¢*&¡-<§'ÉC–¾Œx ¾uÔ£9¯‰\:š¬Á;üàthd˜Â²Žm“úª;º#´Úá _¥„>™éÏ\_lñM'A7HpQÝÔvH_Öê\3z¡>H¯îÊÊ?t:.5DEäi/uË+–—ƒèñ¼v5Í›”×*©§™H9‹—ïó|º#ã\U7 ˜ou_dÎv›jßó8wHØZ›  ŸfÖ|5±ÑÖzœEãõÜ£§ô ,ÊȵTz«7ˆ :®v >ʼó 6Î Dª®9X:Y áôho±•Zƒâ+%äaƒ0T¶?ü¾#±éذ(W:~Ým¢°±egGîÃxÔ’HÐ^ãð!…ÐÖ]b&A´€2­d s¯ïZÖü팾!­ùqö6ÉŒaݺøÞÖÔ!hGs¡üy¸wÛHc)bw@Á1ê§ê.ß©è÷ã o¥óðoü¸kÓs5}c¬Ö¤ÄéÜôý§’ÛºÇý&*\ê4yðÛ3¢±U¢~9*ä&Q¨sTÿ€G;ìP„_Mí¿”Ïr&l`åôŒŒu:¶Î'`Y|pX/dÿ*=ÙäŒ_ ‚sÞé|8Nl•_”‘â`E4o7AE@.-[gò/8oém%ú^5 w–Ú7õ¹ 0 ê“á ûg? d0Bb ‰ØÌJê¾=3·óY-Óâ!ë%ig¯bi0 øB—“ iv˜cˆt¡×…7?[³cz×>Û²]W~d¦¶Ã7-í AжèžÙµ´²ýtÁŽ˜³èõ}›^‡Ëã[ZÏ*Y‡ª‘_(ÌïÆ##üü‚ˆß·:zH×{¿7/íëå*¥óŸß)ËöP±< º Ö¶¢2”ñæt ÖóÚ¯á¹æŸÕ|C ³]j«¢$öì ä«Å´…| M>w)àÜ%Nëà½(õa{ ¿‚mMcéj½>VÕäa¢Š`I7´pÛNüÅAÛè³Y{vµ›v·¢ì•LK8ã°ç²T†“pij{2´ù³<YáKiîZ 1zîBʇ¹…òtë­_>5ŒmÓõå× óÙ«\¤á§i5Kù¥Sû8/Tœ›ˆŸðâ¼l›L–Í@ñ2;Bp®Õ²š¥ŽJ"a^Í{~fX¡ä³'ÆP¯™ûÍÄ•CEvWšG¤®8 ±ÿcZ %«®ëD—jÕPÇ Ü©!囤Á¯„Å{‡=S-Ak@ÄY 1h͘K÷EÈ1‘ ×Åø k"x튷ÁÁDÂî%ùG³–Ïqc¶r(¯«½ ZrŽ[¶ª?+TööKœaV7®•RÏ“H+¿xq‡aÆr ô.V¯N9=B”ÄwnŽU±}_¨ÚÓ)»òÆR^¨ÑÝt¸B–â{ãˆxtÌ‚½I‹_‹Å½úqTc¯·µ.Êïxðt+oG϶¾óå¨nxZŠÕƒ›Gz‹{¹æï"ã¢Ù»Û{vrij˜ïyc>%×o•…HèÜ!ZB8bªB$Æõ®”ß×RVJßõn–òû§†·¤“œ„oô(9È•}.ÀOZ8䀺7 ŽU¨"h?Í'¦½¨R Ò:ŽÍ‡öø€`sx¬“•¦…ŠÃ›j'‹1Ô6•ö݉RÀô„Ù}u`²4ÁÊ,¥@^¾ü³#ë8|Ø.Þêh‡ùoQtl1_æ’×ßר¨¥©Ýê&GïÞmÎ#%é@²AƒkÜù.¼^UG{êgë?%öþº7ú5]̆Ø+ÎÒµ,ÇNÆÅ|J„„Þnñdšù\]]¢ÞóÔ¯ñdÄ^+á*,^é%ÞëMÝÁþ€+jdB"›Gæ:\%ŠhhÕŠãù¸_èNMУí×ö°ÈÌPÀ Ë÷÷„¬âÞŒmçÕD;%/Êb|äJÛ§ƒßÔi÷¡£pLå)*˜¸í»Ãð½1ônr|¹· øD&‡ÞT8O2»hÃD}˜itjK"+ŠoJð×Ù“˜[foc&Ó!;“?«—c­ôNyÃÓùµÚ‰q0˳ ËÑ !,íß"XO•ïÀ v©vÌgö>•%tW—8:¨A4Ô§¼6šˆ±òx[†œ±å2íD±¸,„{~³Â‰ÅÆï ó»ým{©º!ùh’‰ œŠ”ã6¦0U¨DrøÍØ+Ü„¤ÙíÊɨ8ãÙ("Í„ìÁŠp{CÙE¸æ îïŸDemëê‡ó°i™ã¸©gŽÄ®BÅ^ˆ¢‰HfGýÄY ‘–F›!ï2¾š®'Loä¸;Œ¤·TŸyÆGɹvÎêÁH¬\…z FYÊEIvÈÇ.QÞéf}̈(Îûä9%¯úYûëK²Ð$S’ ÑùIËW«ÚQ³ÃbÅËrÚRžŸ¿£{ñM,5­8.…”s畃ըN0˜×ü§k•èچǢ(Š»Ôü§ÉÈóœ7ËÝŠêÞ̸ÙA–Ê! ”Ž%wIª»?CxŠ‹^UzTÂp^“‰Ö]ÈÎý0ñ@HÆ•ÏÔ3l>¡Êøq"^‰KÍš†žãwä ÓiÛùmø,ÑYA;Y…ÄÁ¡ TFG§Ñª%$±ŽJT@Á?ù*{öFX"n#"º¦D‹9©;ÔÖH”ïèY³ÀqR¬&×{áìÁoénÐø E·VA‘,aU8i§´Wd¥ÁÜŸëóõxi“çM°.¤¬ï@/äV´Žip7³)… ¾ëF÷²†µžîKûN´7¿ÿ¹kô™7ÃÃ4“ØVãÅM…îÂjdÝÖÀõÇ®=í«qn´CîVS RqdS…j1ðWZ‰ÏX>#4 RÎ|mÂæÿ^7·,ñ:6ØÖœËÜ0×EO¨9·E> endobj 147 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /RAWRWW+CMTI10 /ItalicAngle -14 /StemV 68 /XHeight 431 /FontBBox [-163 -250 1146 969] /Flags 4 /CharSet (/fi/comma/hyphen/period/colon/semicolon/A/C/I/M/S/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) /FontFile 148 0 R >> endobj 251 0 obj [562 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 307 358 307 0 0 0 0 0 0 0 0 0 0 0 307 307 0 0 0 0 0 743 0 716 0 0 0 0 0 386 0 0 0 897 0 0 0 0 0 562 0 0 0 0 0 0 0 0 0 0 0 0 0 511 460 460 511 460 307 460 511 307 307 460 256 818 562 511 511 460 422 409 332 537 460 664 464 486 409 ] endobj 252 0 obj << /Type /Encoding /Differences [ 0 /Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/Omega/arrowup/arrowdown/quotesingle/exclamdown/questiondown/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/visiblespace/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde/dieresis/visiblespace 129/.notdef 160/space/Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi 171/.notdef 173/Omega/arrowup/arrowdown/quotesingle/exclamdown/questiondown/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/visiblespace/dieresis 197/.notdef] >> endobj 133 0 obj << /Length1 1330 /Length2 7113 /Length3 532 /Length 7946 /Filter /FlateDecode >> stream xÚí”e\”]×öiiI¥F`º[:¤¥k€!f†¡»¤AiE¤A@@ºKº[JZ ‰w®ë~îKßûùø¾Ÿžß33ÎÿÚÇ^똵׹™´t¸dl`Vàg0¨/7¯(@N]W—àåeq™™å`K7 *oéðŠˆ€2p$àŠòƒ?\f€ î€ØÙ»ØäØÿ dœÁˆµ% néfvFæ°¶tèÀ¬!`7on€Œ“@û¯®m°+á¶áÆååØ@¬ÝV`;—ç/OÊP[@è_awø¿—<ÀW¤)Ûß6ÙH“60¨“7Àl‹Ë£CV#½üÿ°õŸÉŸ¹;9iX:ÿ•þïNý·uKgˆ“÷)`Îpw70 ³# ÿ)5ÿËœ:ØâîüŸ«Ên–Nk¨üWâú â¶Ñ‚¸YÛÜîà¿Ã`¨Íz@vîoû&€ª9ùe¨$õŻޜ㾃7Zlòº;–P:=>vf… >ËtÒ‹ ¯aácÐ&zåRŹâI”šŒ±2à‰ý‰sé¬Åäº;?åÎåÊ+6$›;ß0æ ™ÉE)¼b"owµgJ@©}ßÎÃl•UÙùº2vº ºÐ|±Ø>¾®ÓTÝé2}³cÅ1B¹Ó¯Æö`\ÄÕàðAÙ3mŒQ…†ru"GWôŠP¥p ¨HáìqªT–æ!˜3Ôè]kñGbŸ{ZÕÑPº:¢úðÇéãm[ÀøZ×Óò…”ùNo„F~*=O’/iP[d îHªøÎÚ÷“°ï‰Ç2ÈÔg¿Áßöt~=e{sÀüU€ùÝ£Ž¶aœŸô²Žþ2ûøa+Ö¬:i…è¥{Øë\Ây »×Þ¹L%©ŠÜo+=qìpÚˆK'U€ PòBZî/1¢ÉµòøÎ7Õ]„ÊÜf ìµW ¥œA_.iË»[óêæ‰÷qq[ ÕÆC~q@縵#ÆÍ0ÞA׌³í±s “°ãÐþ±äÞ~±H+´c#°Ñ«Ó s‰GÅÿW!l¶*~ ¨‰ú%áó¯*°¿}w>/I’àhYilaG93[(ÄT¹5š¾ìû.$wó0ücÌ#c.¹ßëA‰W•ÅE2«Nâi•Écƒ­ñº<% ÀWãÒË›™)Bò«& f±·÷ZKÇú{:·Ú77¢Ñ(昂úK úL)Ýè ï`qí̸ì ªíØŸU³C mi‘Ú‡ªfÞëšäfǹ×yá'çhFžÚ‘µ„È u’q>%*·pÎ"ݧ.X ®è‰À1¶ùÆ>1½ô’œ|; Œ©*Â.|¡S61*?, > œ e½âÜØÙW.mr¯<ê]YŸo·W—``% *k¤ÕNq—!Ö™q=ð6˜ß¿¬ñ”ÜŸbaK&·®Ù öp<ÕŽ‹±&am;”'èà_\èÌ«ñ@ã#æÄåK±m_3T€Ò“ær}~ÃÀWWêKˆ½ã!-•îsA¹öˆfµ=¶-,ñ<@§ÿeÆó€‹_~(è¦4å 5?`‘`KYÖ~|ОÅM@VÖ‰sô%ön%±$BµÓb¨U4Ä‘Žÿ®[%qêº«Š¾Æ}-uwŽR*±¿cUÝ>3M-UùQkw¦…¨Rƒd Á~»Ëþú§T§43/É7$ëï;>&¯¥)¾¥NØpÇÆáß8uÀ—Ð-ge Î3?£.^ž‰Àì¯P\†–© [z“oÈgKF"'aúú/|ªâí%Þ¤Þ›!ú†œž¼¼á_ÊWlUgÊÎùMDÇ·kËÁÄ"T”/˜’ÄM‹'¾Iu.U&éÂ(øV÷ªjÒ(š©›,ƒkªCI¦µƒ …ɇö]Br¯¢´ò AÁs13MϯGF %Ç9ƒ“¯|kÃ@¶éæT øû=x-•溠ž ëSyû™³®¤* mî–ã0pµþ×*iðÔà²Îy±ÂÈÎ𑙌¥¤Z޽‚uû;:4‹»ÓÑ'á´Ç@-T,x5m[iÄÞ¡­¨ÿл”IL¦´ïý¨>ÖÑiz³a!Ùß ¢Ï+“˜)Lo䨊ó‰ÕѲèµ+k'f„k›r9ëó²ƒO†lûz*l«rð­q(ÛT)ø9>HiÆÞX¢qqí“õõ«|ÖÕ©š6}»AôG…™ì¾—Ÿx:S#¬ºøÍdzyŸ9Ù-¬²§õ%`¦ÕŽm-2`‚”Dˆ9>}¹à–Ì£Àœb{v Ò‰Ájåé$¿²ýDônBÿÞ+eêà²jï eÛáð}Û; Ôò&zd¬eóÛ·»NDjfÓd”Óö#"²»ëƒ§º«)5[À9à‰Þ™—‰B7.óÛË rÏUhOVñ'K7ÕÌvƨ^ºM†F˜×µ‰%´[$Qá hv˜D¸,Q7™Jˆ#Ö_Ê/Í\¤fÝáÓ4LV~0Ûto¾Èßf-00$β'¥å§`åËý ‹‡„s¦å£160™n±;•ÑдpÏY¢EÍc§†ª¿@¶v}SYÂ/ HV—g±¨¹V£ÄܺÆ^4®}6ÝÊB4we˜©u--ž­yûÜLlmœx‡j Õ.ïGMjÚŽ”Ø\¡FX}-¢>Æ€µ¼XÒ2dø«f:¿ý8’6N€7ä*ê|ñ‰IÊÉüeèOÖöôå»é'ÐÏCZŽoÊ9TjHbò™ÈjüF6ÞR¿suKmÙÖƒF«³ÿTÐÆaæchœR¿ü’«‘­I S3ŒW+ñ¸ÊÝ^l^u‹ÎÚ0rœç“›=$”ºüG7œ1¹V_"3Qz¶ŠDYÛ1;V£c­4n†ªc ö|I¥bð@Ð_³ú f‹\iJýþ‹,N0é…p+ÕóçòîÔüXþv~|ú?eiäýÉÍ¿^eïeÎôó2‰IˆÙêMÄ$h5Ë4ÖëÐQ3VêžD5 “3†*–ÎÑ&1?($»÷”÷5£Né. 2Û˜88ÛñŸ§iêÈ**ëЃ*.”á#s“鬫%×ñAg_‚ïÒ—¤ø¯ãxÜÞ•JSGÃn‡“¹ùÃkÉËçæšð‚ž±å1Öàñ_ñ"¾Ë`–äN6×[d|¦¹7Ðãü’3n¥i÷ipÜwè±±†v‰ÌJôت±ÿ[ï ý:“W»¿Bš …+¾M‚ŽÕw L TXÝÑ‹Cïz\9æqråòAWê°šGPÁÈa±\6œ&Ý/Â(7”Ëë„ùÖoâPçz¾q(»kâ4?,7ÅqGCïO’gª¥Ò#\’ðrŽŸr Þy[¯d7§ “Ã{ÄW½%©í‡±gC¼gXü v£&"fZTž6íN)x¹ì¾,|»¥P7ý~1ˆ°µFa©¼»Ê´ÏÍKÁ²Ø€¾ÉêÓ瘟OƒÊsIÉ’Õ˜¦_¾”¯ ÔjìN‘Wÿ%Ñ´Þ$«Çvæ~5åžÚjûD KTI~Ì—½¾&ºó›¬n,QÕÖ2ú,›"®gèƒH$'i2ò¶àD ­ ,J[ ¼n}¬ÚtOJ­$ÕÒgo íÔÜ’>h0£šì0´&xJ̲F1Ç*„‚„kB£Á&ºâÀ›’žñ'•í`™R%ªÑÙDŒF:Á,¯CƒöÆ¯Ž£~ëYõÐÔÞ«0‰»Nr< Ü,±áÆ“™¯}XªÛzMÅVÔFåõöÁ% =ô­IC͆k–<Ûåí4æL|€®Heß½À’Â*íz^ÖVÍ«M²l Šž|3.&¦çöJõòÓXS5ú}ˆ+îw–u‚rO;¢Dg Ȇ­ízjÿà'cY­Æ8üÖÚÜŒáŸæØêÞ¿.)qäÄy@@ÇÃGJ?Àöl’yÄžcüøÔø{»Î×áÙujd“ÖÍR®:+I£JÞ1cùFÊy,uMÇó{.±Œ€䤜ù*d»w3Ø{ú[xüF;ãÄÉ‘—â þ‚¾¯Ê«Ý‘ é“^¨cïcˆ’ ­Œ".0êô?¡imûì“ZôcÒ.¬1&U¨%§õÁ•äªV9ÉOð•#ð}/UÒ–%0*0öóüÆ6 ôSRâÜä¤28ôzüBØn«±6!®ˆ²k,·`y ðÜÖ\`Á}ÁpÅ5$»sœ5ÓÿU›u•Q•ä@Y-†ñ\0j¡Á…©‚$j½û„;S¡äéÍöë’”2€Öô…ø]ã£ýîÛæYÙü>8¿Ð[8±E…ׄt çÓÒÑ~Ã`Ý' ňdÃÿ2=ö©¿ U–ç‚Å­ü›“O'án„Ö@ÎyÎkùvYM˜Ì‚ô(7!÷‘xÕò ‡‰ë`r›ªXi$£~ð{Û¨nµãŽoñ} Ah>.¡xGœù=ùªÔòSãÔÓÔ¤Ã'ržž”¦ŠRÁ{ä*—\»®¯ê–ƒº\÷±ZK¸â‚I5«M<Ô…1Ûò-Å­—00ì7B;J¢]Bšx?LzÇïxm€7vŸ¹Ú˜ý**ì}X»zqÑy>Ãg“´ÔûÛltˆüa‘Íé«4w£ ”¤h–VJ_$Ç‹ü’œá(ÀítVÙœ7õëUš+ñz˜³€ú¨¦Â@*…”lÐs©g÷?mUoÜ)°Ç1òm’ßi¹ÒŠo`êÊÖHèŽtš šLÎ2–8ãäMsÅé°O…«qóLI^ím,ÊÓ$5¤¦²]ûÏd›}*жziÉ>¸ìÅ”,m2¤°ÑQé¥Ä†Î¿Ö'¦ ÑVŒ#¯?È2¬‹®æU8eŸK#ÆÄ›ÿØÉRœEyOŒ«Çžà,X6o÷U»³šçÄ<·Ù¬`ä~81Ã}æçTißO¿šë–\¹9”Ê£Ù&–¿°þ}#@°«l½(æî—Y™•D@MØîúýŒ êsÊÒË…·æ(—£QDj0|VC㙺\3ÕÅs"KŒŸî{øø•d¸Æ®¤-_q˜¸Ì ÂgáÍÑ L¥gåpSPµý­וђž*î' û³]§àÆ ŠŒKz.¹¼¸;Ê81œÔ6y©­¦Ókµ;MW˜¤·Ã–:ÇkšæZúÃeÛt¬¾½ó’.l‹ÆŽ34—2ãDD\L6P‚X~ææ@%K© jJÖŸ\¯ó¹›¥»\n¶«AŒy×¾©&„Úô‡–U‚hQ‡Þe÷*©RèT:^ÓÞ‹G³LÊ(bqbî¡’Kc¿ÊެQE£9Õ¶_Êp`}ˆ˜oÌÍùvÈž$ƒå½>_à%äú„ü§ƒ»uÉX_ùËc-:AÓÜž•S¦.Àìúœ6šÅµÂ˜Ô;’BHX›<ÖUí£ý—æ“<=¢ôc"È´¹®1=×`8xÏN³T0ªÓ|ÆÆ,µ®ƒ%X~™à39í´=µ5“® ‰\óéI̬æ| …ÎÜ©'Ó „²óåß/–¬¥f“ì”ß‹Kj›'‰ì„ '©-|÷@ŒçöÕ÷Šé·‚KÒßXÙ•\QZä5Î|'}ËÅFkðÄ¡OPTÏ«õ ›»h ø³;—WÂ5a4´ydòãNÓ€X쀟{-QÝí©—6æ¬iÇÆŠËè,îG¹ß¥»‘•d—H5r^%{u'ÐY4ñÕ¶Ž¾ç‰¸'´ˆßõà¡X1]r }ºžÙŒNJa×g[͸•ŽW¸óió8·ÏtVŽÑóm:^ãÿx§64lPAQ×ÂQEç9\'ŸˆI ’òéêL© ¦ù:¿ ^mí³hW­P|…ëäÜZ¯Ú{©ñéý\ÔŠ†_+Ë:-µñGCÇH×îþZk9‡7Þ´½<ÂØK¨NùÛBP‡DbÒœëã3ñìZ”­¹POrQ™e›ÁÉ&O°W sa‰KlÍï¯Jæeøê«IýžŠHôVs¾Øý*ÛàÈ+ë-¾E[ilOñj‚=&ãuŒ)Ì3_A®š%ÿ>TÕ»ðÛ_¤tû¾x^Cyþ‹wÀ"¬$}#íÈ\£ê5é‡G •öc7˩ě´$=] Þ_ñ–Ku¼L›”3·,ÒGð-Çêðsgu_Hö…úÊj±áÚ í)î ìˇ9Ú@Ç(`«pAQ rãFb-N!ÝÌ•ŸÙ"’éCi—|xk­`Ñ>ð …¡¨¢èðÁP®gÑL1zb’M‚ÇtÒ¹­ _ŠMÉnõegm~ C-D€š'E3ÔcÛD5/!Ðþí7ïì‹}Œa2E+ý±R ™ë#:žNf‚ʬ⠙OÔÌGuÊ>$£X`ßK‡½ƒ‹å¤IŸ¹“ëòàgló?³3Üív=}™p“2HXX\¬š*ä2Œò>àP—‰¾¦·¦}³…Ú™ÁBS¾ˆï2û¥€ÃÕ˯ÙHÓæ˜ñ‰Q1UWݳ³·>ž¼¦ÓcÝu™S}ÏP‚æS ÍüÙ픬r~fot£Ýô™‡gâR{uXë5¢\Bî6¢!,ÔR1Šß U‘7£“ÉâÉcåÌ~­ªN–‡?._@-î@©í ³‡¾”íÆ¡‡AE«°¼EÜ›„µàÞ$¤ß ŒJ ôO B;46&;èäÚpÑÒ«dȯX]úKGÖË93DuO4«3P¾t×h†d–’xl2Q5á®I’À $È%f¯ŸúIÜÐ~OUœ‚)™^rêyÆt)Ϙ«%öZ:íPX…ó¬B)¿zÔ±mEm^ÉkÔqÄí¡˜ zåÉÓûâ¬Jê,hŸªõùäiszŹǘ{Á!9~žÈ{xOîLáìô)ä}¼‚ûRók{Æ=¡nˆ);º«NœˆnÇ4ÚEñ‚;æ½ZÝÚ!‡†£âÄìæVMm‰lI\ŽêÓ\o¸&oQ³]P‰÷aÝë€4û/wÎÄ1‰ÕŸ3d«-¿›ÉŠF…Ä”_SЫö£k;–NÚ¹Uc‘ÞŸ Ùë³Û¤rD«¾MÝñwWØôæüâÀÜ|VJÇp¶Ð,dNF¹ÎÀBL<êfÃi¤b /Æ)ÍÉ+ƒ¥¯û³ù¹û^ ½-Ñn\GeÖš­ž¼4Üd.:(0?×ÔÎqÍD×R»%euùË©¿9aQc¥Ô‹Ñô QÿlDªî˜ƒ0$cudã–Eù¹Î°¸a† 0;#å}OÒzgœéƒG~\R‘ ÿø òºŸf!bUBòoiöO ðé!²ò Ê©-\bÒ¥é¦vI•Îü‘p¥Çž¢I½(ï{ßrÞ=Ÿ+Çpæ6\ÉÊ4m~‡eêïáÑGÑ 'ƒCÊäXy IŸø×TT§QšÞ]ßLÖY&Ú  Z²y÷-e Ò.’‰GQ ‹û€9Yå »]h휩ÎóS©‚¦ùåÝ…øÃ´›Go ÖZÃYæùëCo²pñåBõ–üWŸÿ ¿?¬rŸÌØx#û&ïólÖ̱ÌD –™K__”BÈÄ:ïÉœKƒé`8î þb ~×aK×Vw»ŒììõÌy‡ZY@éf©<]«>΀R|»õªÛm?4«š˜Šòe,ˆÙÖÔS2^nÍT”Ûá;*ºS xP ¢[cWKòR¶©—8ÿ1†Át4MþÑñ<õíZYÑ{eóí>€2Ί´Îaxöh¨‰zïBÆt(Œ²ý9?~u Ÿ5$NôëÂéu×É™Q,qèŠ{1?ýÌËŒ¦™Gb»ðZ¯D6•—FŒ·¦öNZ[jý¶gS·Ó^ >Xˆ=‘³êÂ×­¥·¥Ì_Ý ¾þœ¦óBD6ÆÄ?hF¼í‡ç‹@ÛˆÑÂ9?)ÑJÞžþ›-Â"à K{'OÍÈnÖ6ŠFü@à@aPrø[ŠÌtI1y¿áÈŸéÔ(تdœJ­;®G¬*ïü;Í6 2yâåH%õ&˜—äô×ë|E቗Ay•¨}Quï†q–BuÞPÚ²Ñ)†x#”u=2¶üWK‚ƒ²‚’ ×óRr´[q.t(ŽÊeŸ<[˜ÿ¶¨‚¨í·®I£yÎkÈÆ]ÌÚ‚³áÀ®à¦ƒáÝ=ðö›åM2ØzøÿøÁýßÿ#X;-n0gK„#îÿϘrendstream endobj 134 0 obj << /Type /Font /Subtype /Type1 /Encoding 252 0 R /FirstChar 35 /LastChar 126 /Widths 253 0 R /BaseFont /ZOHSXH+CMTT10 /FontDescriptor 132 0 R >> endobj 132 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /ZOHSXH+CMTT10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-4 -235 731 800] /Flags 4 /CharSet (/numbersign/dollar/hyphen/period/slash/semicolon/A/C/D/H/I/M/P/S/T/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/x/asciitilde) /FontFile 133 0 R >> endobj 253 0 obj [525 525 0 0 0 0 0 0 0 0 525 525 525 0 0 0 0 0 0 0 0 0 0 0 525 0 0 0 0 0 525 0 525 525 0 0 0 525 525 0 0 0 525 0 0 525 0 0 525 525 0 0 0 0 0 0 0 0 0 0 0 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 0 525 525 525 525 0 0 525 0 0 0 0 0 525 ] endobj 254 0 obj << /Type /Encoding /Differences [ 0 /Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/Omega/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/suppress/exclam/quotedblright/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/exclamdown/equal/questiondown/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/quotedblleft/bracketright/circumflex/dotaccent/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash/emdash/hungarumlaut/tilde/dieresis/suppress 129/.notdef 160/space/Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi 171/.notdef 173/Omega/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/acute/caron/breve/macron/ring/cedilla/germandbls/ae/oe/oslash/AE/OE/Oslash/suppress/dieresis 197/.notdef] >> endobj 126 0 obj << /Length1 1540 /Length2 8748 /Length3 532 /Length 9648 /Filter /FlateDecode >> stream xÚí”U\œÛÒ§ñà š¦ƒ{ãNðàî.Cãî‚»îÜÝ‚Cp‚k€ Ó{Ÿïìdιœ¹šßô{ÓO­ZUÿªUkQQ(©2‰˜ALÀ’{&3ˆ &/ªb€˜YQ©¨ÄœÀÆ.V{qc0ÄË ˆ¸ZØX .>v>NT*€ÄÁÓÉÊÂÒ@+F÷—7@Äìdejl7v±ÛAc˜ÛT!¦V`Of€ˆ­-@å¯Î°3ØÉ lÆŒ ̬L]&` +{T–¿IÛ›CÜÿ2›¹:ü{É ìä  …Ф@%šAìm=f`sT4ªäÿ†¨ÿ .éjk«`l÷Wø¿»ô_ëÆvV¶žÿã±spu;ä!f`'ûÿtÕÿKœ(Äö¿ÒH»ÛZ™ŠØ[Ø‚¬ÿ2Y9KZy€Í”¬\L-æÆ¶Îà¿í`{³ÿ”mÛßX$Ä”DT”þç<ÿ^T2¶²wQótø'ì_Þ3è7C»ãdåÐeefeA¡ß¿ÿéÿG2 {Sˆ™•=t 8¹ÆNNÆž¨ÐÉ€'À°²7{ÀPÅ,Ìöè´%¾sˆê_Ç •Åbnõ—íoäà°Xz:X‚훸,ÐSƒ˜ý6ñX¼ÀNß^ Äüs²X\ܯs‚ léþÃ㯼W§ßö¿„¸ýáÁ`q†6á†Js»ý¡ Z0Ë¿Žð 7€ÅÞê!\Ð¨Ž®`ç¿.Ðo#4’Èo‚FýMÐb¿ Z¨øo‚V)ñqCk’úMÐzÞý&hZéßÍ ÷› ä4ƒÂo‚fPü‡x ]TúMИª¿ Eóâ…zêü&èšño‚f0ùMÐ ¦ÿˆºÑì„Öþÿ:¤?ªÀâ„åíªÕaóBUØþPv¿•aÿBe@þ@¨ ‡?š×éük.þ@h³]þ@¨ ×?*Ãí„Êpÿlмžã_hQQˆ‡7tJ™Ø Ó ±ó¸9Y}ÿwGu{+è´I‹C/++7t^þ²šº:9í]þ~A¡Å¿ÙÜ ú´€Á`SÔÅyˆ)ˆujcX©ŸDþt"=¬¨ESœB]÷\ZðB<¬mѨ¬#ýÚg­ûò <Ì]ÄÝ×î$Αí>Ê’§Žqi_ŸvÝŒv3¼ZH´.2ä=w€?ƒ±Ú¿\qÂ*ή•&i |<<ü¤D+®¶÷b…¦G×­¾'3„‹[K2ÃV=<ô35;… všciGøª;vRÂêT°Ÿu8r3Ãò9¤Ý÷>97ñÉÞlBÃè§ìIŠ'Æ–Î}ÜøOÜÚý’È-×\ùtí˜ÊÝ•×Y ]Û‹¨Ì/4—Œ.zéUKU_² t8ʤÞËpcXE¶vP¨ÃÔÆUSûO5­æµ[é(ÜçÏ“ZÊJ=7DxñoÔÏaÆ´vÒÐ߀¨_bVÓfÒQ>˰ˆ.ÆÎ‡Jk¨¾…ÀAdS¬aPŽu¹æ™·¯‚Ïæ\Ó!+ç~tÉâ=Ç;üÇ’­•l[©l¡“ œ\5ÿdÃS♬® íP*À¿¸Í^}êë©SUSFŠ+%©7L¥Öýnj:‰>¬y0ïÁÇü³i»gÅê]Y¤@—h‹=–bºê ;KüèáÆo>—IßSHÕ×â¸hëXÆh,B‹ ‡Û³<½¢ebø-§iÛNËn‡«¨pQ?>Ö÷E½f¢l~Ü f90APg ”hl=ëc ­baí_ðè ˲LGøJÃ@ß>–¦à‚Ùe·a´{¨>Nñ¹°¦«hë§3öÞ 5ûתaúWádè>k§ÔêÄZRÖ£Md]WqÓõë«^#ƒæ|Ëî"/_’ã6ãò¥ÍUYœ¹ª ò9ó…q£5ɾ!ï[ Œ -^lRq0‰§Ó1ªI#4ÎÃÃ3š^¤¿mi›¦ÂˆìYÙžx¸íÙ0¥Ý¼¥=#pª·î€ì)2õ” †ÛÐìè@ÊÏúŽbÂÖÍbç:”Vÿ%G¸Ú#PQÆdx¶Ýu^ñàóÆÓ‹Ià‘¾;ÊÇ]Û¤=ò,tˆ™#KÉÊ–£D~öжPšJ[«‚Z—LôûÆUiãâ†^k}˹ô÷uÎ:\–BÀ‰WY¤Q¦t%"ÜrMÀá{¹ÀÝTµûÒk;ÍF+˜ ì¡©E'D§ qÁ#íy¶F€óg9šË‚¹^h—ù¶]ZGò›n¡XìÜw$ªƒ.-µIº<áÐïá?º®)™ <+Eºá33aœ U{åÇÁ/pÔFIÜ%5ËŠ™ÒÞÄ‘u¸’ÕJQeûJT.À‡e¨ßi¬£kO Y YÔú‘ÛÒ8¦xÛ)è^;k¾(=Ö¸D«º÷“_fŒÀk­Ã}kÁ¾šÑ3œµvð†š¾ody;~Û8¹üÔ”<,âÉíL“‡$ùS´ÅÀK÷PœûÂk$ƒî+¶­/ËÛKpïÀÄ–² Ií–/M½}€BVoýÐþB¯;³©Û <Є&M²{Z}âKÎôØÀp³´}ãÆ©võ%‘ƒ´xUÉØTàXÈEÂæ+*Ð4ŽÉТ‡Îc:aV®å;… 2iØhôˆ¡r-i,^CBC‘ uIʆ1 XŒ…îeRrÈ2bVë‘Gˆï)´Âq7ç¦õ î ”äý:g+Ò&˜dQ>ZxV®p(½7aJ<]\3ò€1(åöÂUæ O’”ê1Pk®•¯ú®âó®o™…دiÓîß¼›ãhò›O-ÊA®/cŒèòûQé~``8ø$U í¸ÞHpJåÑ¡z3¦a8÷¨(.B‡Þ.·Q¨„üĪh•Ózìãã‘#$sgˆÉê’ŽëTI °oJ+oÐö‹Q–µª½9\†²ÇÖt(µ0¿¤(S*¯®ÖXt€æùdDÓ™Iºôn‰¯1ôcˆ©ÛÁÛ¥.vó ½4k¡IŸt»åuŸè<¥ P?ŒnñÀÛOŸ¢Œ'Ò)é± uÍ*«€ ¦?'Ò­DÒÚÚeØè~ÊÆÙÉ^‘يǯáw›.jþRÇi÷ոس’Ä 8‘ðöÚj4\°9 ¹¬@BnN–%½¶j!Ú.Í·Ýš¢-‹Ý+tcà-Õù)ÒhÂFQØYãЊ·»4úJN² }Ÿ¹±­MÑ[j}_úLƒzzp^Þ>Ü „YZž.…w+jÙ¹úÑ»‰)ž·³ÕK{%ʺ¯•ÍÅœ~óµ¬tlµèg÷7Ÿ; 1i50tœ®5_lÑð gžõû74xì“iØLÜ!ñ"îÜ»Óã˜åŒàŠNØ!Úó\W¸G4DJFK\rÕAÒÑž é–;Jq9áý‹Æ£JœÝƇ8ä¢2ÕêF_/ÏÃ¥µ3cÅGyCª I5¥ómi¸ë§½ÒÖ9‹…C^°n§ÃáÀ¥»7{iT 5õ]–ÀéÕ h9„Å.Rkq1·_Ÿêñð‡€„›ÇçêbóÆ:xÔ~|J‡» Ê!˜‘¥ü’Ù)2.„T~lqÒw„Ç™`˜ÔÌÀ…-Àƒyk4·È R¦‰«äEòZ§”"i¥,*üD”MHJΖKl êQ[ÑëX. }eV IÐÛÅA°Ø9FDÂÜÜÊbCQ ¢cìÆ€HéZM¦±é 8‹â°|=çR‹&ݱs!¹¯ÇŽÏH«/xИp+xÔ –/Qž0ºKíºï«îS³¼ôFfš±CmT?J_äÄ—hU6§^kx~d¤Õø€ñºðùuЉâ¼E¹³ÑªœD(~Ìëõ—­ò3¯R-,´4}d×K×W¾ÞUQ³ãC´"aGòû(×QMq&ÅöÔj;Uù*{üÛpÚßOtNK©¢e%?ªGé]q¨¨k÷uñV#ß=øM•èÿXèíÄ—9ƒ%©ž3SP_ŽÙöN’5x:廸yw*r‰eùÕ3ž8­ëø–e¿âžI¼õ–†¡~мMŽqwí*›"Ý(I_url=BNÒŒîS˜üÅŸ€—¯«Oì¼*PM$9Þë‹ó@ÛVûPc¹PwÌߢ“1Ì0ˆØD}™Þñ½J°¡Ägx`:¼•>áF´ø­ÃÀíw?†ØU^JR›åx„Ã/r'â ž•×Au¬ÒΉtíR ¤…è­ÇçÄfªS¥òIΙ.F»Ä½î´5Ðh¼47Å–o¾%s-u}7×äš“ǦWÝWî& _©ïÑ4oµ³Þj“àKNfžÐ šA‰‡ £·îº(0â4psz*]ý|Ô.¨:i­qÞk?Mˆÿ@5aùc;{ó{ø—(˜ÇoƒœõŠö£@²$0Çu¯}só´_¸+œ’øe¡²Wn¯ %†ëIK[‡’-¢‘÷fÓëÛ´!Wpû~0±·þŽÕ²ù/bʰ(Éõ6ÊÎ{®usaQ‡ñ]W¬‚¡/|@š¿”t~М{;I•›©ñÔÉÓ¦…Jæ Ü\K"g–êÒqš>‘#Ù«rb!œf«pMÓÃ^mË›îY›®LQiµcÊ£|úÔug÷ªxDrLïlüu‰-fœÎÚ§g¥aSËìn«ˆLš¸Öù‰¨‘Ëý„nFâéž¡£üYÇ<¥'ɑџtHøc~9 Û{Uvoám¥èzrx„.}DÂ'‡½ ·ÄD-­>W;=‚ý º2¶ô¦\x ×ãÝ`ýÁîEjÃâÀ«Am; b‘-¼Í•œŠ÷¨Ì¬ŒH¢ þ¨ÜµÞ–¢ç¶õR9ŒïÔSùGŽrŽ¡H´ýWG[ÏïLc⮈(†=wÕîI3EP6]áW0­qÓ­¾šb#†4¢Ž#/DKlÙVQÀyÇ*•_´tøè(ZlbïYóEí¡$£ÍåM¡‡&ÚÖQw/®×zf‰“œƒ4yiÕý›v²s_íÆÍÌúÆD¿§Èzµpåü±Ã5MJbÎáeÞÆ:ÌêJD…ðÁ“#—@~½ ´0Ø™Îh ËÀÃΚ„+ªOß“ݲÇÈ1v€ w‚¿©bø&Ü¢÷Ä®’ÒE‡:*–Gž0êFXćtOBG¸êR7=·EV÷2%˜ÜÓáÄÙì"¾ì_^Ùîm¬ŒêÓ‚‚q jêU’¨žß—–~˜ EàK0hžûy9P‡ˆ\¯v*áâ]å<žrZÅ“cƒù£¨üÕ}:)èZB­èè$avŠ=ä0&’S%bhíšÛÞÅø*u)Á(Ø}GÒœ–ðÆ{|©Ã€êËn£à¸Ï`Û׃u©ý¦LPTòËÖ¸|S uz3ŒéHÕBÓsÔˆàK`æ^“$b ¦;®—Ù%n„#…@¹ÇYÑÒ–c*ÙGð3÷ªvØÌ‚Cø=© #h¥¶Ã Ë{hÝÃ+ѧúÐ÷6Yt]ÈùÒ¸1¥”úÅ+^¶ïja=°E¨Í(âDÙN/ES]!JІTì&¸¥¼ÚËW1ÉÐ2Ì ]æÑÈæ7~WÒ ìJÈ©9/¦¾ßZÜÛ­ ‰$Ošïp'T¡¸ÍÌ\TŒ]eµ!Ìíº`䞬Šhãä°l³˜ä¯ÖXÆŠWÜëÈŒË8¯~ý¶”ÙJyzÛ«Žµ?îà Nƒ¿aJg“Ó”H3ÀCµ¡²Q#!j¯!tþ„3^aΦ ”*Öª7¼óÉ‘ 1L¤VaÇr0Üü ]lå“ëÖHjÕ ÿ0jF :¯BËï§ÈÞ1·ê§>"Tº÷œ[^Q£ÎÅú¥¥-òQ H²ñs‰eG¾fÀ™)¯ãtÝá!.ϰ´Óµ8g6>­éX‘#x?±¹—6/µ6ƒé#Ÿ'MTÐz|SÎÞy¼žØCO÷?ß$©Û¿êCð× ÁÀèÌw›ÉZÓ¡šTd€kPbÐú(­º)a¡‚ôš@bÊfùGP°ûQÍìiŸÞZÒÛáò^”)ŸÇ ʱQIÏ=‰»t·V¯¨OêOQ>:åÙLæ\6fñ'Ê:.±a]fD‰_ùVË3d^|zª=“êbRä¨] –—ĵ駰h Nì<Ç;/úè3<údÛ˜‘äÙL]N¼€Qó¦Þu­¢¨¡õ5ÑW^·¥ÃY¾\‚QRï^ 7„™<'ÈáfÃ@¼÷c,3Œ“Óú`12ý©jª»ýZ(g¨ œÐ¶£ÏÈÇýó–/5Í{ó­ î{KXeÛÛy Šã¶.v——U’Éœ–Jù‰ @°Å<|[Ñ“åÖOª/Óâ}&„½çR5QF5²!D]ZYì5{=Gî $,{öûÛ/¶|“m~eŒ­ùøLšü¡½"áp' žÖ–yMH[}øü=úíÖaþái·ƒ_O&`Ãg;WËóLï[„ÛÕ£úÁaÚ­äÁô›£N *jŸ_1ƒìZÓôÒ—™KNÆúdîçç|­©,Šh©+¨Õ)rl±PC€ùsÀ„s·® ²ÊþÛ(¾ûDÎÜCAâ·a·á†6~u÷C;BÝÕfWÉÓSIß`Ͱtgãå üúá9©9}¼½@çrƒ/ãÇ –z¸˜ë.j[ ¿´Ý-&_Jp<ï·Æï†Œø‘¯¬µ~á*]þÎ!pkAxÙ÷@à׬VÙJ½‰À+4D²Ê#>5΋™Ý1þô÷Ir ñýNoÙˆfnvªùCØ~‹­w¬´ß±ŽHL#ÄM¾¸,Äãñ@r¤?¤Î¦Õ¬ÊU/éJ-ôò$æ¼È¬¥œÍÞOÛ9 êŽy7§ñu;bø¯ÒáëhV–8 Ò×è­ró¦ÞSÄ—i×™CÖùX·œ&ÚθQÑÔWqŽÅ7©KÖ(†ó ¦Oë*E¾rƒ0°1 ¿Í±ty1ï#—v g6:ãTÂhg—¡~ñ!57}2P綆;'Ø%C‡Mašû0†°’úÌ\wpÃ÷lm3)œÍ g¯ø,ŸîœÆW!䛣gôKǘMíAΫq;øÎÓio P=ßTàèI]N`ö¾kÞi»ôÄ¤Úø8ŽßçÀÁP3ÈS‰“NɯÁ•+2†Iô^ÚI¿Fê1ïzkµ7ÆbZ‘MË«‘·Þê.<㪪€åG*DÑpäL0â²-X‚ï¶éoUë(K·U—RØ&aúáNRÀ=Àô> ´tñ:B„¡1e^%ĂϾKÞ¾B“ç½ÍÚ_ íöE}-ÞãT…^î*’ö‘xFŒ)ö‹È¼NŸ Qå¿1CŽì­À8{K|‘‘¥/ç2(•h~Yάa¥TQMÀ\î]nãgƒ«‚pœòu¬iH™±F ØìÝ~û|PEÃŒ›b¦š¢ýñè¯cP $t¼¿ïuP6!£R†q¹AÊý|®•Ö>M£ÝCÂ\orcÆ!¸­±ŽÈ@ptïÆ–¾x{5³äânïó‹i–[k—äAn‘ð+åöµæFêä=Û•ôRãŠ_M~öÁ‡¤—Òj €^òty%ïÚý+Ü Ž6f Á–.BF¯:ºŒ‘ìçÎü¤‡g°wº"k^j»èW„2`á«…>Æ).:Å#5–§Ê:-?cÌr'BÒ@àcæ›-s³ zX'ÅgÈ'I{ÚƒÎ:U¢¹‰`ušs”/…?½õŒ£ŒM*ô‹¹éEL Ò5á«ËBã?h‰Ú!8çÜí·±þþPÿ€ÿ'˜Ú‚\ vÆN6¨ÿ ßë%Yendstream endobj 127 0 obj << /Type /Font /Subtype /Type1 /Encoding 254 0 R /FirstChar 12 /LastChar 121 /Widths 255 0 R /BaseFont /ECPARP+CMBX12 /FontDescriptor 125 0 R >> endobj 125 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /ECPARP+CMBX12 /ItalicAngle 0 /StemV 109 /XHeight 444 /FontBBox [-53 -251 1139 750] /Flags 4 /CharSet (/fi/hyphen/period/zero/one/two/three/four/five/six/seven/eight/nine/question/A/B/C/D/E/G/H/I/L/M/N/O/P/S/W/Z/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/y) /FontFile 126 0 R >> endobj 255 0 obj [625 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 375 313 0 563 563 563 563 563 563 563 563 563 563 0 0 0 0 0 531 0 850 800 813 862 738 0 884 880 419 0 0 676 1067 880 845 769 0 0 625 0 0 0 1162 0 0 688 0 0 0 0 0 0 547 625 500 625 513 344 563 625 313 0 594 313 938 625 563 625 0 459 444 438 625 594 813 0 594 ] endobj 256 0 obj << /Type /Encoding /Differences [ 0 /Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi/Omega/alpha/beta/gamma/delta/epsilon1/zeta/eta/theta/iota/kappa/lambda/mu/nu/xi/pi/rho/sigma/tau/upsilon/phi/chi/psi/omega/epsilon/theta1/pi1/rho1/sigma1/phi1/arrowlefttophalf/arrowleftbothalf/arrowrighttophalf/arrowrightbothalf/arrowhookleft/arrowhookright/triangleright/triangleleft/zerooldstyle/oneoldstyle/twooldstyle/threeoldstyle/fouroldstyle/fiveoldstyle/sixoldstyle/sevenoldstyle/eightoldstyle/nineoldstyle/period/comma/less/slash/greater/star/partialdiff/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/flat/natural/sharp/slurbelow/slurabove/lscript/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/dotlessi/dotlessj/weierstrass/vector/tie/psi 129/.notdef 160/space/Gamma/Delta/Theta/Lambda/Xi/Pi/Sigma/Upsilon/Phi/Psi 171/.notdef 173/Omega/alpha/beta/gamma/delta/epsilon1/zeta/eta/theta/iota/kappa/lambda/mu/nu/xi/pi/rho/sigma/tau/upsilon/phi/chi/psi/tie 197/.notdef] >> endobj 121 0 obj << /Length1 793 /Length2 1151 /Length3 532 /Length 1727 /Filter /FlateDecode >> stream xÚíRiTSבª¡¬2©¤j=,ŒiF !¡€aDŒE™e˜{Cn¹¹/74€ˆª²,bÑ%£¨(V: Ô«ÐN¤U„–µHÕª8õ‚uu•þ|ï×[ïœ?gû;{ç;›áÎ’@øzXŠc$‹Çæ‰A€\.ãquæri F+HÇ$,<‘ȬТ€ï¸B±ÀC,Ò OÕH²šnÌ ’H40(+H5¬¡j((Ç•LêÙ@‚¢`ÍÄ4°Nƒ‰tbÓx<!J¬‡“ŒÆ™Ð$ÃT8¾!mêÛT:L¤Q¢€Û¤L& DB8†ê«hœU8Õ ¦´ü7dM-.Õ¢è*…f¢ü¤SÿÊ+4ªÿ‹kRµ$L9Á6• ¿'‡!D«™š•‘ QJ°d,Þ26wÙI“": CH¥¨h<‰Ã4U åߤŽ4Ø?Tèþ××N&ÃFFèSaÀý›=óþŽ)“Dâ¸l.—G©ýö”0¥Y¦Ä!K|'P„BO£†ˆŠÀÀÁ:ë(Å6†“Ô@9“T8A›øWO.à pZÚúàNòÄìQîM`ÿ~š¿?®3°<ø€ÅP­¸Ë¼€PÀÍú'1C6haY p½„^‚IT©%#'‡Š²ím¬B(§aX+i¦¸Ò{Ë'{Om«Éªê“Í—ë`1-¡ìôÊ=pÔ¯w ¯ŒßÆ«pSõ¥¹ñûž:¾2Ñ[ow§Ü²-”É­®—ø¼˜ÅeêTý4Þþ”…¦˜RÑŠpñÌùž×¢ÊK€Åû>.%1¾ÍM¡òßgt1E.%ïvËr³ŠC¢e‘#óŽV8(kæ¡>ÁÕtK¸¾um‹Æ»g®_ëRßÉ÷)â¥6îa¬I{ÉøcÑŽéOž?ï}öº€Þò@ip±p>>-ÚÝk¿_º›û³K·¾ú™Ñ%V¡þâ.)ñ éµY^ЦùÁ¯?³yTbD×sœnùÌÕħÝiö–(_ëþu“qw|ÎB{û¨¿òáo[ öó¥q½Ig"nº_ªm8_èX›7=ÁØ$•V-jš‰÷ øÏuñuœï=ÛNoŽê¦ ݺÂûê³™‚ñ±ÇÄžº_xþXil>ì¹ Ûzpó¼”ìûK ^¿[ ­MÒwzÕž0~?gÉ^("“µzoʱšÐšmý#Ѭ=GEõyVå™gŸHš¾S•… Î-tãÓ¥Ì6ƺ˵H»Â°ç•Il"ÖïLK+F`æãc†tþ™× ¼ã“_uû^s°Ú°kãƒG7—-ؾŽ&¶éïÑSƒ>-Î~½e¤'XkcÔÔgÂî-¹ý}"Ø|ö ½ÖÕ'æ«Å¾-ôºó¿Œ._ÍâÛ«" \4Ö=ß²œ5Wjj“ù’¿"ÙÍäl”;~+{⌛S ¶IIÆ¡—'ªŠ£8Ùæžå'=]È•£•b,|±ìºÔbÚí飋ÍO‰M®†ÊwB~·*ÂÖŽTŒûÜé׿8^Îïøù´‡\%¾'i®*C¯ëœ“ÑÔU:Ï®\ÀrÛrúcÃçü/N4n²˜C¬’…AßXªÛ·]s¼e«ámŽéøÏŽÄtäZ½›•¿‚N߀,®Õí« )5÷Ùq1#òý<ã·(çÒ âW–±Quƒí–eñ‡øb‡Fec}Áî •E¶E¡DiD®²íVâæCòº†ã»l¶óª3‹ºfç5Ϙ¿cÓON–¤‡W|¹Ö÷œ07=ê¬TÐç7ë[×……jJÌ:1XT} ùnPOHæ3¿ïÞƒÞ±Yô8úLI~Þs³º÷´Wy‘lèr§äfënFmÚT]š·[>»ÆaÝ;Áv‡Ú/‹¯Úùìj/jlh£/!_¼Š;¹Ôék}R!/°»àapËÊ ;܂ڮêmthócçäHJý»®ïV'6t\+Ëù‹ o ·Uí›Å‹Ìáø¶Í ЬfÜûàJì§ß$U Fϵ$\íù|dõá S‡™PÈRË»sLëŸd„Ê­¢×ösÿÃEûÿ‰JV$®Q)´?·’”endstream endobj 122 0 obj << /Type /Font /Subtype /Type1 /Encoding 256 0 R /FirstChar 60 /LastChar 62 /Widths 257 0 R /BaseFont /FGBKFD+CMMI10 /FontDescriptor 120 0 R >> endobj 120 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /FGBKFD+CMMI10 /ItalicAngle -14 /StemV 72 /XHeight 431 /FontBBox [-32 -250 1048 750] /Flags 4 /CharSet (/less/greater) /FontFile 121 0 R >> endobj 257 0 obj [778 0 778 ] endobj 118 0 obj << /Length1 1991 /Length2 15060 /Length3 532 /Length 16157 /Filter /FlateDecode >> stream xÚí¶eT]Ͷh‹»»;w‡àîî www·àînÁÝ î,¸;¿|{Ÿ³“sîÏ÷~½ö€¶Úê£ÆÕGUÍ9!'VP¦4±3ˆÙÙ:Ó1Ñ3q Ë*111Ñ32 Á“ ; -ìlE ÜDL\\ÌDb£Ï/ŸÜl¬ÜlÌ0äDÂvöŽfæÎD”ÂTÿ$q Ú-Œ m‰d Í6Ÿ5Œ ­‰”íŒ-ÎôD‚ÖÖDJÿ\áD¤p8ºLèa˜˜ˆL,Œ‰Œf¶0 ÿ(IÚšÚqü;lâbÿßC®G§O)"ÊiR}JšØÙZ{™Laäì>g|ºü¿¡õ¿‹‹¹X[ËÚüSþŸ…ú¿† m,¬=þ+ÁÎÆÞÅàH$kgp´ýߩꀻÉL,\lþ÷¨¤³¡µ…± ­™5€ˆñß! '1 w€‰‚…³±9‘©¡µà_q€­Éÿ–ø\¹)0 ŠËHÉÐü{Oÿ5¦`haë¬âaÿŸªÿ$ÿ‹™þðçê8Z¸i3~./ÓgâçïÓý_s‰ÚÛ™XØš1³±::zÀ|žžOb#òb"²°5¸Ü?…èmíœ?/!ú\"S;G˜6ôsÏLÿû72¢ÅdùDë?ÈúOòŸa–Ovp±s˜Yÿ{£ÿ3ÂFÄ`ëbcôÏ91³ýæ b°8lÿJåú¯"ÿ³+ãgª¡#ÀÖ`úW”é¿¢ÿ+ùÓÓÞÚÅéOàÓÌØÎÆÆðOäÓÈÜÃÞðdž•ý_6v&BœD žG»?O;;[À˜íSËÙíÏ8Û§³¹#ௌ–ÐÎÅñOàŸE´pý+ãSÎés{ÿßjN׿Ì>·’ð?:dû\9[‹¿E8ÿéÐÚîÏEìŸe ÿ\ÁþYUð}VúCŸÕ„ÿÐg)‘?ôÙ±èˆã³_±?ôÙ­øúìTâ}¶)ù‡>e¤þЧ‹ôút‘ùCŸ.²èÓEî}ºÈÿ‡8?]þÐçìJèsvå?ô9»Êúœ]õ}ήö‡>gWÿCŸ³kü‡¸>çÓúCÌûÿ8“Ÿ5†?çŒë³„ÑúlÀøÏýÃøYÑä/ü\NÀ_øÏÉù ?[2û ?{2ÿ ?›úëFeüìÊò/üt²ú ?¥þº?­lþà磉Áö/ü´²û ?­ìÿÂO+‡¿ðÓÊñ/üç(ÿ…ŸVÎá§•Ë_øiåú~Z¹ýõ$ú´rÿ ?­<þÂO+Ï¿ðÓêó9lèôïú¿ÇBBvî^tÌŸ·ëçã?;ÁEÄÅÎåó?3Um-\’"Ÿ·9##Ë¿¢Æ.ŽŸç½?çøo6µø|3îc˜Õ%;cž`ËÔæÐr_Ñ™ pj`!³–x¹ï½ó]°A+ ÀÖ%cÒÔ› Ï•¨à„n¯¸N‘ÞŠ“b—ñi‹ï®žm¸7²ûö$A§ˆÍ wglÀòs›ãåÉšECÙWçù ”"*‡?‰ú´]û2ƒÙ94Ä2¬UÃB(Xˆ•ÒÊÃYÃ6Ü’Á6¦ƒ|-àZiÖ¯í:]Pž ¡ò’ÞuÑã; Y”~Q£)òŸ•…!!Ö þ¨È$2Sv$:_ƒR“ ÊA ­ÍöÄÕŸ½Âœ —u½¤mëÔ ~#g×Ý,ÙÓg¡Ñ7/’Z)f¼J,´«Šùòåù~B”ò›« S:ÉlÛÿÒ1É9?FM‡J œ¾Í’Sk(#sÍ“ á.KGІĞ?ùÃËE CWÐ§Ä ÆbéÙRˆêÕWÞqp˜Wá83§‰@FzP Ó‘ VàzG(Öƒ¾v[GKa>Z YöuNVÄ»‡eÙÌxS@©´Z¹Y°À7`/ Ù=xŠÍW??†:ÎËP5ÔñëA D‚œ(&„«ëAG#uYU'_ݘ—'Ï{™ü9×Ä‹ŠvCç`ŽFª dev²ªõÂÙ¥z¦9PóOîÚ`Xþá@JGöX!ç ˆ1öÚ8c±>\áÇ 2bZéeà‡üR™Œäs ¤â€úݶ ’xí2QÚY!pk92bGÊ~À5š¤â–¶ sã[a“‹gÓa*ue)DNúëo¬l‡Öõ»o í'Y×mÞ=#)’±IQ8˜HÍöŸcÒÍõ0u4/4 'ÊÃݧ¬ð†àxa`Q¸íNô‹ ½èIãðÛWžË•ÕA `m"ƒ² ¨EýŒÅ2óH~±c¯Õ¹ð'{ªýv ƶ£H²f˹[yñ&q®ÆpòjÓôÇYÌ©3›  ôÍ7f#¶câÀ¨‹³ž4xÑÕÖîÍû†u©Ý4#cÌÊ.’¸Çš³lb|f9J~ò¢vnÒÔ¿ßoW†y¢ÒßÚE¾O£— ŠŽäOºåk$”šÚ'rÉ´”1ýµ‚ð8jU ±¿Æ:7 ù8zº°O¿ãŠ9PS5î=Ä” áVaÓ²M«—báÖùÖu7£!"çã“às’îÝ .Oo†-íU8 {§òZ›AÄgÕD1·ØÄL°3—W¯§ÜÙº»döanƒ¶­Î†‰¤”CX|îx¸-ÑêMd iVäôüM/sŽÎÉCÉèýäéG)qÿ‚e’9ny*<ôõ‰|¾šUÊ/âP)Ñ©µ3ã¼ÜÙ ×ùÄÝùÎ K/SˆÈôy¼{™å-£µ„‰ʈ±|;bÕ‰ØdZ¶•I¾e ¬X:F¤ø[œ&DÆ*·¹AÑöGf–k\nÇ~«É"!YPk’Âv‹ýß¾E@ 8<ÌL{v)UÜÖRòvÄÛ Ý—ÊÛ·²ö l„³dìJÐÃÌÄÁHlOn óSðU< ß‘ÕèÁ0î€È¬£9Û¢€": I>ƒƒ7]ÝåÈxóyÀ[„Ƴ©,ïŠ($Ööè¿TuÝò‘³eÎÕæ™›‚¨Eýp&¹% Wp³ö­8¼îqo cVQ„Pþjl^”¦£_y‰±Sé°÷räÍ3¼¯»k‡Ût‰ö¦Á>&‹šóû„ Ъ¤ jüNŠÑ4ãîÜbïp¬–Zùþ{ °þà\?ð®ªæ‘lò]9,LË/ªc”!©³X+èÈÇüGQÉkãf·(Eiv[«¨Rs”÷D„Ûô%CüV¸Ë‰/é9ä^¯žJ¾éoxÈÆ³°A]†Ëã)´r%¾á~í!›… ùÑ–Æá»ãùܧ_b@ØduÎEˬjìˆ9!Ž‹Ó^?èã$£Ê)f~Æbx1o4úh9ÓóýjGenà•æyŒ&ÙÏSàrAi+Wi€®>âøé¨·Ï)ºV–­98AöôCÆgÃjSuÊ.B}T¿9œ´íI¤}"‹ÑéxÑtv©¨»¬€qàÜ¿­ ‘šñ6+^9˜;‹'ŒŸHDw.õÇG¤8ʸ/c°ks½”Ë£¯¿yGOè¡–û]ÚÜ:'O£¹±6½‰…¿WnIçN»ö0+}Ë¡»FÔè ‘Šþñ¶ì€=ÿo£ôl¢I«Î‘ÇK‚2¹£ŒPþ˹,zÑ‘ r™Pì!?¯ÁÃ3\ß™_ÛÝ/^•%°̛¹«è15Øjà5@%h »Ë ÄöQy÷n²rô=Ö[³®JÌ–Voçýiu е­´«{ÆÝ:ÕhªÙCK˜ˆ¾P‘ãv»B^ÜÛ+3;’æ£NcðQ£ˆBîõ]uf•¬”™'ßÊb“fY¡ ò¨}{ÝxWåØÉËa‰iXñ4ðƒØRР2•û;²°¤ôùÂÒ"åM¿ ó÷  ”Ëbé´DÉö-ªH6ýsDÖ=ðñÄju…Ð+~O‰ns¥¹õä4²äÔÕ]ÊŠ¯OË©K·¾@Àó¼ÝÀ޾‡Ný.‘ÛƒœÛŸ(t¢eÒ†ÅâÃìÛZ^sLiNðð¥ b…À<`Àbµ7·vz‹d Ã{q04 5¿Wíÿ-lcãÎR«¤NŸl‰U—mÌ¡ú臘e¶@³…ö‘Ü_ò’¯ÚƒKjßóà^Çè Qcž#•‡E/ðâªÚïÛ‹<œ¦®™km¹øìÅ;Íž4b„eªÄ»œ§ú¨«•¸Éãn*HÝðÛå^/úqÏ(ÃÚ'¹­ÁªÈTšá׺٠â:= Þ¿‰-º"äÛdèx3ôk5„Ù¶:£qÖ1…FCæn<°±ÓÛ•ÉtëùZ\lkøzÍ4%Yg [†Ezìà6h°6Žô=ôÁ&‘*±~»'%³ù¨už×ÉúÇ÷¡qhš»xFÍç“9|h–ÐážÿFòþ.˜÷ÊÏä8ÄÖ$Fßo'DÒëÑúqE¿¥9A¬yë/Zeä´@¥2 ]ºE³äkÁ_bÔ<#hêªÚÝk×—2ÀŸIba8~&ƒÒP+Ñyغ>|ww*Ä*¦¬ÀÌWY5‰,˜F—Gª®W7Ë¡·„Ê¢L¤ ¬_)G¾”ß–À¼t»¾Œâc£sôên/k³–a X…’Ô'šhµêË· ŸãM%»ÌÖ-0±ÎxÙœ_ˆ‘V‰n" Éç8aNNÎÊ7µ½‡=R>V…´†N1„cthÎrÞ™ztË[Ìr>:Ô€PÅŠF裚˜¥ÙäÍÄI™Æˆ`NÖ¹*Ÿ8»!Ã)³þÂÆ;ü¥7 ‡7¾‚ÜžG< Ôn®e‹È´jÅg(2ÇWS˜`Ýe÷•ãrƒ‹(´ø¦ç{ŽxrI-e}Õ·ö€ ˆyšõ r?ÈÌýÁ3W—G|+§’“îˉ‡,ÿ Nø[­œÖ:ãÇYÉX¹;agɭΜ²äÇÀüÖH»Üê:»c6à´A$Â/D÷“º4WÙ"Kp ‚ 1<Ü/…¼^Øù¤‰|Åœ.öSj-:ö• üs-†.g:ÃØ&£ö„¬w¨YWä#s¯sƒŽÕ¬ !ßx¥NqYŠ’‘m_á,èÞõÎã'd»Ð@†Ô5ÃÒN‹(x"rû§r’Þî3ʦŒz€ŸCDŠLnæçk™œnB¦kACTN¾ÖÖ36äՌɡ9™¬ ¥6{iÀ:ËCØzr ­w&¾R<™õgÿÞ·|¿˜ ·…ëEcj-çÉ1¬Dúz‘´0ºíð k2E8§QÁÙªKÁbjBmZñr¨AÒzmßDÎÕ¹PÍà,ö„RéÄS /¹œZBZX_„ri¾êá{È…ÆšEµ¤5qŸ¤Ý^¢%mšø6Ö;L.âcC*«#·[(¢þÙ[dÑa´Å„XuÔ¢YF{x$Z£ú=,J6{¬êR‰z’“Mg¬b¢¥p2øTkî8AK›è7áþpË^Å…ô[†¸)K«ßv ®·WÉ_õ$MTU6ü‹E¯ úÀ÷È#ø¿utúˆø0—ÜÏ·o:¾¿Âã²N7¥jižò™Ó’þ®ÁSbtužþÞš÷þØ[ÛÆÉ[ qSûÀ .ÇGÄk9×™M:@?9»ÙS(xÕ&ÀÜã·Úæ÷íòÍšáWzÃü XsˆÄR¢î†é›Bv‡ù“0<¹ü  +›˜>ö–W‰Ä ÕaúŠì0¾_ÙØæ¼R¯”–¥Øƒ_›rz܆õ/2„d¾…#ïnzúŒ ’æ8wDðÒçIY¿J–|èNò"8ò@~Ôñi’.J*våpÏ‚õv=å>îŠ8•Ys)ª…9¢Äv­'jrZ V<óQ | ÌA@¥¬¡ó+aÞ¶èÌîKö­R9YúˆˆÓôÙÂÏôºë<ÏŸéÆDyÛ¿¦)Æ$GRâsž‹]¿Å¬ó›Éàˆ<ÏpVìÕ ó¬Š]Xè¬1»ÏQ¨šÄ‘Ê$qÙY A=ø`láô<¬Úè¸  Ë8ÕUgÞizƒp#”ήå¼:O¯6ºœzHÀ Q¬=ªmÅ2š7r~¯{Ÿíî;xȲóíG…TC}¼`)^+Jy¥"?BéX)Zlåd儱 ×Àh9ežÔD/h|hFßTªaâu’‘cWæ?„ý)—Û†]‚†ðœ¢ ƒeó}†á]œgÑÔ/‘k@‚ñ¼=c{'¨bL¹Bá­­e4¥2Øì¼™Av^ÅÁ·"é—ÀWKñÝgyNz*e#¬6R†Ž á·s ¹§Š¢è1* ~¤ÒãÛ8Ö5ÔKps¼ÃÝßÝB3¼œt2¢&^T¾¼ñúè™ËGÞ„£j„÷qRƒ‘(UæÙTIEõ5h§4ªÝÁÖF+BVåy+› O&6.eМêcà ï WÜøJzgÊ/¯G¿DÖt˜zC·Ï¡Ã kÂZ2öÊKd3ú äÊD¿baÒð¤Ú"¶eá}8‡o›¬iPÈhøÀ½g#eÖ *ruyð¦Ù!w€èôIÎ\T?/b0@ˆ1Õ» ùuànâI‚{5L3ÇD!éJjŠAc&÷ø1zD¯àÙãwïÈñ“±k ”Ù„Ù߇FñÜ I­¦C¬µ )H'R'Ø¿6—16¡2]…²Ø·}=«ø‰QŒ!ÐíAé울¾À ÆÑQæÓ(Í„“Ð Ïiv]eS࿵>æÀþm¢úzäÌ@Mƒ¼®¤þ?ÌešÕ)SÃþ´”"–b$nŽõŠ*¿ç5Ý!Bˆì$»ѬQ!Ó³UA+{MûÂDBܰ[XÓ$Aóp˜Ap¢Dvΰö€‘Õи4ÌÝl{Q^ÁÔm£ÄœçwÃ}Eá’,}<…Z˜Z€ÜÏl•“Y—dÞg´Àß]9çLœÐ vÇ®3o»y ØKÜŠc~`TÿÅ«qŽu¢=¨ÄªÎêx>ª#˜%`|Nížêí²—nŽë˜4ãºeEÝñÅ(Em©ê$ÉU6C/ð¾vniœVI“bäxÊ^`â…„ PêÛOß|§¤JE»!l4KÛ› X‹×B‹ÁY/n…g¢³Ì;wâÐ%dk9òÍ,`¾ #¯#}ÝÌ?g×Òkúeˆ^ƒr‡G½¡^‹Ö_óù’‹¹ˆ‡üõk•Q>?|ÁJÅ××:(æ^VšuÖH…š¾äTmh擦¨–9Ü醨¡Tð{z Pt‘Ëo…crýØ-5ñŲß%žf¾Ùà¡ í}³!.ïùsœ?õûûçצ”•Ç=¾ËÀ/æ|Hã»Áí ¢áfZGÐÒÚìaïGª4¸+W›Ç óM”!ÂïÂ÷;„ÇOëä}øS…[ŠRô`½?4ŽA(5) BÕNî¡Ü vŠÛq]°M:l|8›dC·J«A‡%j–2‹fØ7‚úý£ZàÄ‘çã ‡FþÁ{ôBé(–ù'C-Ê'.ˆ’bµxÀœÀØeÈÜJùO¬³"©Ø¬Ñë&šM›3ï¢jäœ%îºq\êd(×>4‘LÏÔÍ$¬.Nwáy*%cGþæulêKs±:Ñæ6BË¢Žmª~y– D=#_!b踀Œm3S=/ =õcÛg²}.. T™'Äd« z¿ôæÍˆ¥£z#vâuÑzûQ½§ù¤Hä§gvÐ*æýsˆ­8-õ Pâ•Ì@Ç ÿJn}Œœ8K qGê6e¢‰!îêý2•DòïNçW2Ip£ÁÎÐ%ôwy†¶Å/ÙæHÖìõ?`p&QM#O¦òqæ,c¸r™Óä‹ilÏdQõÞ –9nRDùg$ jy¤Yž«ð#Q[uØ›Nhâ&‰*Šªeí¹[§,,ø3Û“úT“ÃíU]JNñ·ÊçzõÎu½^¥ […ËŸ2¿ÚP‹Á.Üìò±# ¬¡ºcÁ3K8'‚ZÍ<–Û]`qÙfîÖ-%?wødCLãtÞ;½-‘Vz™ehßÕC–{„©´).%º³¸jXév§æƒ{ïÛK÷4͉)ǡќtn:â|äÌtï{áj­øËIŽ ñK-gµzÎ_SõBÒ`¨ðF“Q±#À C”VX4haiœ›KÖŠÉ0NT¾õ…·˜»ÊW ­Báî¬|×+Ɖ´ãÔYۧw•QU׋ڻ¸™r–’Éêgc@Õ\nµ`ÐõÖ_'ÄÄþ®Ö|Ì±Ææ.fKÒC Èø(Ý&óW±¤Ó)оoêÔW2à-ÙŸjÞ•ióåbò7s|Å@I“Øx\’i&1?Òåä9•èìÉà’Œ½VÛ’_÷Î&—:IM ‘畬ìlh ‰-ÅvJc<’½{¯´svÔMܺÕj£´* s½È:óü(#!Z¶3&”NUœÏsÞ#nØŠºc¶Ê|úB³fÏGeNߌKÜ»^k‘ÂjKè%§÷õ—~8ø7Ïe¸âe[ùÞÇðЀ-çL£-áþ"ãFÒ%6ÌÑw‘iƒ>þÈ¥Aз}t¦qï“K+ ´pQöRé v<‡ƒ<»Ebt®_ñaço¶mÛd×äÓ!jvZ† û/O†?•RÎ¥qž‘«”Þt¹6L¦&…”Žù~ÞÞgxˆAÕzjíËœÞIÁ…8ææÁ^ê"w¼*eQÜ{Ê—F”*êä7V8èzÔ«ŒÊ›‰§gÛv!M嘦V9C ·œÃ:qÓD8…ëåCº·Wú„A‹„º×xç2lì¹ÁoÌ0ÅTŠÑžý”‰v¤–—ka4{vÁH€›H3Œ‰~õa.Èe”¬©ˆe%_SÝ@äN]ž³ŸS,Ò5ý±Ù¼E1–#N€ ±£¯k”± ²PÿRFák‹…JKw09þq#Ì/NéWý}‚Ð.Š7îíÙµsd¿ßé0Xrw…¦ãŒòüˆÖEjè2’auChô–þÖ,i7Í©y1¾Õ„AgT»|íÜ Ï—%\ðÜÅøù*ÀœÓ‹³ú9êJ×0º*laÚ © §¼ÚÓi7¦}3Æða4ãÇ=[ÝüA.›™4?ÛŒß$_mƒL#p…‘m@ Qûúv”“‰n”O(~Õ‡’f'û¥šå±»~q€Š±MJÈqÙ<V] M®pžº/X&*U\‚ó=™%{¼t=ò"Xgû´5í‡&ËZô’­Ôû~éoSà¶ÂÒß»[™ÅH!N?yY[tÞ¾ñP£—„L«£2^ÜAäÒÜWLÊ+Dÿä<Ù~þeÔ-á"ÍÜ\ûMÕ—v¸£ÑîW 3%¤Ç7{nm-æË¯d±ûªÚ·«EÒÂÙ0ý.Ól<ãóbIèÊØW2°êTÖ˜í5M[hdJ8Æiª†>å NöØGæ~€•æÊk¡ è³F6¯ KD6ëÊ#OÅMºSÖãp”„¼¤ê+*÷-Aiîfµ>«—,™Ø$#‡æ’à[>2§€ì©«÷©Xý»M“?GxhGkž•Šl\ÏïD¸"¢#' í0)[¯#>ÚV†È+þº½îÛ²±$4ðí¡Ö˜ ½Ê* ¾x ìèÇBx2½Tù+ö™uYôæÃHð þLa–áL‚,Óš@âP"ĵrEX%+(r6&jÖ£ê Ýý1¬ÕLÍ]FO ¢ÓBãFl?yƒ^·|eTÁÍèÕ+¸ü9uJœ¨{ÆèÜVÞŠ#2d4&÷´Fzi#dÆ»RƒMÕAƒ~êßw碻ùÿl ïŽØRR±¢ê„ü{§ÉãY:ð Ñuœ-ïm¹>—Â.î}gΛ’mèÚ1ðê"ª¡ãÉ%tØgr¢¿˜HÆðu¥Ç‚ú[äM§ >*ƆwÔx¶ìÄ©ðº#f•ªU¤Þ‹ÚÉ×yj0|©íT(4òÅÿÚÿ6Ë»Ü97j6*áô.zô%ù‹úÛ4éiÎOÓ¯²{®‰˜%RBgŠr~O'¯áÿ:Í1`¹ªÚc–Ùv Ž€ ;<î "ç£:3–ç‡ÚA¦æèùA¤i’(§ÎS¬ÄV–îˆqof„ÑB¼G“æd+ÔxsNçÂ`¦Vÿiž%; Bã ˆ0H}ågG#6¾~™ådºŒ“&!Np‘/$ÐÊW`Ôà{ŽqŒê*\€hÉ^`”h—Cwï%Š.GÃdÆFqL–o*"{udF-‹7³&¸ ^âvIBÏl2%}à®*"P,¡£í=¢ÅÓq“P¼gWª1PøãT„‘z>ÐÀ…ÍÒF„Э2\<§l'Vm¢wH¢ÝÌ—NZaÁpé'µè‹^óϦ[Y¤HXH+œ sÒ¸ò”‡Ü2‘2º¶ÃÜÊ~ äš«‹„« ¸ßçsZ,°²#!åxu„&òKëÙŒ¾Me4· >G“ÃYüÚhtkù5)Eÿ³F±EԈ› é¢W #Ô•*F¯Æwìµ­ahØÇ¯ œîÙ˜HÊ¿T§,­1#eå»ôfj¨Ü†mB€.Úë³¢¥Ç˜?f9ôkâÆû/i³ªý$F9§¶VL€•[ù'-]&¨ª€Ù£‡´Xõ]x«œš‹é÷Y¥|¬ùôFÒ§§€†$im^GŽ‚£vj»ÚÄpvʰã¬Mê¨ÂpÂH˜ÌU®4ž+ ë(½æ³ëÌ<¨…Î&o}xfÒî^ ëÐ^x¤,Fïm5pé2O7Cõ !t·ò—ʙҴw¹p<…¹É!0­™Àm2X±ßÞªMêpê5ä-‚çÙÀ¤†6!gý|¡ìQ¾‘÷˯T!I,-éz¿"Øa!ÎÝÒá[!¥. pô¯© MÄ»‹ÍL†#Rj¬*ZCX‡·,€Áž]œ²E^€ Âä¶&7û¦¶ŒkºBÊ6è( £UZµ]D4RË~|K{ lCc:Ì™e7yö×ýæa¶9iïÓ”BÁFÛ_±¾GŸ&ôÖ”‘ã+N S5à©Åâí™̔ЍK*mÍyhóß»ï=2êÜó’‹‚¿\ÑþPmêР¿`…xQ”V«±ïçuÓ5ÜçÎP-OLÿ~:K÷6ÐaÒ\³r9x=V,j0}—:òi—‘"ÿ¹:¶~3Žéî¾dx:ÞzâÿUÕ§ÈTYËŸwA©R 9g™ì¾éýD˜mÝ;€^æÛ¶¾Þ°DÓÒ‘ÚÊh»5Ѝ¸U&_ÿÎJÿ^V«âd©fŠhd¯Ÿ¶Þ6UÝm0¶N!vÞ Š¸Ê¾v!Kת=E]¿Ê Œ=/Õ¤,Ïåe¯/il¤ÐàkÃòv¬Ížü0šY^3V³_N†z[ÎH°Åê6)5P‰Ÿ‰O¯>+*©Ñ¦?öÊË–Í”ˆ¤êÞÁâtJá…€p0N·àIº»øèÝÔ±”ˆ0‰í~;ç­Wµoaœ‚ü]:-Sد_x¨te’^ò:ÊmÚÊ:ŸBÕ•šäî-€{¨èÔë*¥:æÁÛ„ ,—ß\ž½Ý5Éy¥A‡\ˆW!„¹rElËW{C0”Ë«#¨¡pÁàI3® µÄn!x$ä«%!¹jÏñ'+W6q5Æú5¯y²‹í\Ä0·¯ÂíØ6IÉê¶z޼Ái™ƒÝˆ»Ð—°3qg›l°ì=´bš•ìqœ;¦û—ʽµ+û‘ –5];ë2ñ±X);îÆ(–gáS äXùJUÌø·Úœê€¸Úöö¡p“ÊØiûì¬ßðÖܾhôÅsð̒ȹ:| ½I*°²ý HE®iœŽ¥{¥§¦·BË‚¸veíh¨ÔÆ®d] ”Å@ÿ,D©Dшh(4žh-7ÊE%=Mº½’Eš¢ÄñÏɈld¼¾6ªù=UØÉÛQ`¼’ÉŸ~;g-b°ÞÚ°’žã;3ÚÆ¬Û—ðëHèªIÐ\±’LDõÄ¥-“ÓLÇ04ЙËn#“2Ã_;høÐøàKØöáÕ[N½ƒ6ÜÔR+›#ÕS¾¯oÞÛøyÝ{[?‚žž´PS srÓY—áZÿüJ¬ì„Ïùµz]kòÇA†RF-VgJ…7“¿B£^Fš£!m=a÷uq´cfë $gó°´k.ë]ýÈÞN'‡ÊÉ ï2®Ðén›ïEùw»GìðÖä.Né‚$&Šh‘nþD$ׯ…¾5¢°!0p€ôè­›C~’†öÞ©‡]€»p±†ýøc–ó äJu•ƒ–’êÃh&ó{ßôcùz|^!xµ7eý; 1=CçqóLú¨Ð»¦·A%ÆÇˆö¶][Vk—_ÕSxRÅÓÅvÄ‘ù5‹ïáÛQlá¯Ö=ÈU—›þúé_X¦áÈ"hTÁùÚ¹g¤E¿š)¡ó=Tö^¿lqO÷íñÆQìêæ¢8ecCn7YÕ¯í)h–>·žª5¬ÁÐÇd0ŽÂ·Ñ˜Á ý©­Ìâ@³IIð˜-kõNB FnÛ¦Iîu1_8÷<7kIljd°uÏõškd¢³ª*"¦u ÜAòÌá«=ìñ”:Š Kéi⓵+ÚBØ@»ŒÍ°Ït4™§5@Í¢”óm›y‘øhFo±#¨»¥M>XÕ8¬ìPâ½–…ElišµÕ­)$ÖÞÿ&‘3ÒS-§Ú™vh-3°-$P¿†>¾R哚Ë$6+V\ÌÒ«Èœ&k–S³Ì+ÿµZàÚ4@#ï­C¯ÕO‘Øêz³"jtb‰æÅÒv¹Æ|ÊÚqSDŒ]ÊH­ÀÖE„{(ŒU·{ÂÜÀìYüaüM6Î/ŸR*YÞZ»Uvš(ÕÿU4׃¤"SÒ›9d‡âXôQ¬vÊ©ŽyAßcû‘ØQေHŒôW+ûe«¬»Š½—Pç]†ãTDÄà»Öø5ú¼«~j­gý<íDé(Ò9µUƒɼ œ‰¬¾Eì–çãïõÏ!=¼töŠzÚ¥V ‡ØO ”7ˆ*C—¶ZÆñÃ…´Ìž,EÚ{–!ÍîOø*Û%^e—Ú{ß‘`9Ò ¤äLƒŒÄþ„K0Þ~ fB÷2k ´qj’¸Q··a¿çÒüÌ1¼™Š’¾×—ùÃß©›öüYÂåI¢VÀ£"QZ/M»0ÂÃÓ¥MøØüÁ‘y3° {‰šèà±F|º(E´šÏû«‹¥‘ˆ&Kè¸ÙÀ_ÕÈò?~š=N>—Õ·'2ÿúÄK2ŒËv¨Fçò%[‰ ¼OJz5ˆÊ©E®h㚯{=â•_ÜF6U¨øâ9ð#è‡N–HÆ’$žB„´vŠÁˆ@÷oFDSŒæ®¹]Í“ª ãç ’$AáÒ ý‹ ×­ \Bžvç½óª¹+—teǸ>„ËKo¥Áb!qW9ž€Þ˜Û”¨ ÒEÿ³'gÌ K§º_ R…‚Âi¼Ó™ˆ°L-eQ[­&$z~œ4x_©Ù÷J ‡y³GÍ¥)îÄ9ä|B~ÆþR2Ó#Qì •_}~›àÄoè¿ß~ï͇ZfJž”j~´2ÙnεZðÔ Ã¯(XòmuŸŠŠ’î)¹Ó‹È…/šEc~¡-Kb{^îñeaÍK±Š”èñ0‘fÙ ¶³ \™¥D³™äC1ÏW ’wúf_„±j/\ìSÖÖ3­)G!X!ÄNZ.pÛÂX:ac'ˆ<ך N;¶•baÒ Z¸n ÇéÍÈÄô&NŸxnè0`:«ŠBËiaïr'm®Q·¦î‚T+°%︊YÍ2‘½n]Ó‚ÆÖ@›Üà—N§z§ÖŒ0”myÑXÑjg'Ôga™þ-Ǽ)«‚ì·1êÝ.‰7ù`¦,_=p UÊÙ»@P—òåÐ'Z?÷ò'_±ª®gÑnÀ {á×ð³é ÕÙ[!ß41έÜfgªW=Á Øý‚ˆž\s£ú‘©ágªùH)JKÁÀô#Ôf›Š"ÿ¦TæÞ„#M‚ÄÛݳЧhîO9§t£ð/$ç($f² Vpåð‹¯³AÓçj¯³½Ý¥ÂŒqñÚ£DêÑ+L7æâûpº²njË>½¸Ge}¡P^Ï<ÏÁÇý·BtÉ“ûwýŸþ½ú)ÝQ%¼ ÅsEѲوT¼ØLP{px5'Ç5éÚÛ·½€7L¢ÓÝÛºJ¥~)ÑÚ‰9{wÿ xµºµî¥°C>Þ‹¶þÜÒ¸Ð~]¦R:@¿ÂÍé\ÊÒtÁœ–ltÍÙ†è ²ˆK¿%eFý/ØZ‘²¯JY.gEÇg¾Â¦Ð¼¿ôt|<µ&L‘ÕñÇ| üxJšwxF¡W–Ž!(ýŒmôCTybO?ÎÍ”œ»iÚ¢[PXfn·1¼<Ê'yõq ¾‚ ¥šÓœß¡Q˜q&Ø2! ¾Û¸NºÈçä´à†½nOÑÉÑbI Hf­ÀÆ jÛ€UÒÛÑY‹]½{#t.M€?[î2ï½ÎQƹ€-¤ˆ”\¼LŒ«ÐÓ¯FùEµá™ò3¡y=óAÝâç½uQ[…t7d“¼>-#ï^)3®âS”¼ nCí=ØŠDg—~xÆ9µ•Sà<­'îç° q—Àɹ„¿¨´ÍdƒÛW?ÿ\]÷Ððf(Ç÷ŠÇu9¡ØäÃêø\}ÏtªÀ~Ømݼ™!úÑFy´ÜôÎXDú51#áRPÇÁaЬþÀ»gÓƒ|ùÍÛ‹?|pÚ ŠÜzÛÁn¡Ë?·ˆ~¸°'‘EÎeIGP…1jÊsl[É`f¨›oËÕé2hÛ\¦n?,Õ§vXf)pÞh<žs„—°R ²±€: F{QÚ3³~ ±¿ë_öÃÄˆÄø‡ØDÆ÷-¼|Ô+åz¨Sž1#n·›‚®‚çp3cþã`îÇô»»éç¯Û*¢l¾:ZÚÏ`^Ço´°é‹øÒ½©Ä5Ó‘ŒM³ïdZN+ü?)‚³ML ;ö˜;X.ÄãñaZ|A “‘[©Áj+Äæ-nØØp jÂ’®QÞ;†CXáuŠÓæT*Ž/Zã>Ñ5ã´J‡RËR3¶2ö]ò[¨m-tªœ¤_O01äÞ{y"¹°MƒŠ¤mêè5¡¾I´•§œÝØ^7¤×´¨¡—?+Ÿ~tôU‚Y< ­ümAwS9SCha÷`]o÷r‡¸´9İ \o(ö)F¦xu§©ö¡\ ¡3Â'–ë£$xô¿Ñ&Ê©£Ò^çÊ )zälï´ý`djÔWC•ºùÑÔ˜AfjÏš)›•Iy³æŽËñ1<ªk¬¼Ýȶc]3š9·Ø¼él¡Þ „&öp UÙû6øêŠè!oQµBÅHÁ…ܧFÈÉnœ›3säV6 Ÿ:ÙèÈ›/œrd;ìnòþuÆYo¿<¨"zÝdü5è‰t¤ñx¡tÕq–Ó߃[bN¤9ß ¦a]St>•ª9€žàwHÝñÄIê%ôð8viüÀþ3sÉüÞÞY%~Çw¢yíï þ’”Ÿ°p²A‹´n=Ú;æãFñɃ$­Ræàdt=™ðgjÓú!ÂÈ8Sé l ²ýÅl »½žz ¾{Ôy¶Ž.Ñ…ïÝ5òûÙkS|È$|^1ô‡‹á!k‚ŽœìˆÌob¸¬ðõ‡©íèÕ<§Y\–m!ã¡:¬zŽ“ÀðÕ:z%Îz¹”Y-¹à.¬!6Œ`|J»·N3Q±ÞrT“w»L+)åøómÍ?é  Ü‹ÅÊÄ<rx³†nžGËt²Užbs»Ø‚¦ö’ï0x“Û$—p+jböæªQ¥f“Èç ½«EYé~=Ä0þ€$_PÇœrùvA›ò ŽÂM:¿1i¹pWºÆ‹#È=–Ûq4,ÐAÆEÂnéÞƒÿu'øàŒ½¨6BÅ0£KÏ“öY°±©Ü±—=ozˆ@ýâ2÷d¶ï€Ñ_Üðçvœ+ð”_•–“ü»k1X޳䤟‰H¯Wަ™Æ‡¾qC»ë¯Á,T› áuó:Æíô6êæ˜T3aávÇ2Òå°%‰æ{›ç™]ŠÄm(¯;«ÚJ »U„pH…9üqùWäíéšÆ2µøå* E üœÅ'–,½Á,V‘qí:LÐQë7 f+6I Ÿ³Aˆ¼\¸tb{D¥÷a³Òq»vA˧ŸÚ±4W6¤VE¨øðì]ì'mî²#xP¹Æ`7iÒ°÷ut}™=];C°lß&M#¨~{èãÔO'H,«Lã”`çŸ|³gÛfEx(ßðçŠæNÙq×ë±fF$‡`ÿU®˜3nYÿ‡šÓ¶ÜpYš.E_Ò·(›ðuýè 7…ó™l„9Éw{ ÂúM!?¯¦²œ(õÈnì¬côàÇ_ó™ òÄ7Ôj…çÖñîË!­ý‘}]K°½¦ôØäúÉh7p¸÷4ö“IPäpÓ#¾nºÁºþ½——ªï1šøhó22M>©Ä”¹i…ç(~ç 2_“ ”¸D ù'Í·‰]Ø÷›¢¬8f懛+®){-Ržä³âžÏ2âôºäØe”zCKŸ½Ž§á%#[:&t­#DR¹a4©LßËH¯–äsPë€=W|§eQ¨¥ï$‹œ9ÜÄ`¶ýµnʯ·ªŠÁ‘Ó“áábà Ë» ;JiÆÂ@]ßÏ®3œø&P$D¢•Ëy¬?]Ÿ®àm«JÄ×cx[¦pà•æ¯¾ç‹à‚ˆ }³R=BYÁ•’ЂÞB&µÞI+‘=€ô[)¬Mµ=ŸBOAÏzÈLÏE³é·­ÌûUÇÏônZ(!è¡×…€fÉ£Ð1xÈŠ“BÃR4Ïg¡ˆÕNŽ4í¯lK–{c÷x§ÀbHç:¬;Âb¯½Lºî+¯B#° ?¼±` ØÓ°ï¾¥0<'„pKB lò§‘6'ÅÒQÄ¥\5²¨ë gúL¸Lµ¥‘?/c¼ ¹K¾g'‹YµÚ·ª("7[•v1Ïþ¨Jõ%™Y°¬ŽTâM’7ž—ø¶Æ°Ì¿J½=ÎK*’šŽ«„ž/)׎Î]05ºÓ’Ù+ÌŽ¬.)JD¯iatÆ Éë2Sá kÑ\OT½”-¨ïÎ!Sùœ—¢5Âøÿðæÿ/ðÿ‰ÆÖCGg;CG+˜ÿ Ö§endstream endobj 119 0 obj << /Type /Font /Subtype /Type1 /Encoding 254 0 R /FirstChar 11 /LastChar 123 /Widths 258 0 R /BaseFont /CAGLJL+CMR10 /FontDescriptor 117 0 R >> endobj 117 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /CAGLJL+CMR10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-251 -250 1009 969] /Flags 4 /CharSet (/ff/fi/fl/ffi/quotedblright/numbersign/percent/quoteright/parenleft/parenright/plus/comma/hyphen/period/zero/one/two/three/four/five/six/seven/eight/nine/colon/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/V/W/X/Z/quotedblleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash) /FontFile 118 0 R >> endobj 258 0 obj [583 556 556 833 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 833 0 833 0 278 389 389 0 778 278 333 278 0 500 500 500 500 500 500 500 500 500 500 278 0 0 0 0 0 778 750 708 722 764 681 653 785 750 361 514 778 625 917 750 778 681 0 736 556 722 750 750 1028 750 0 611 0 500 0 0 0 0 500 556 444 556 444 306 500 556 278 306 528 278 833 556 500 556 528 392 394 389 556 528 722 528 528 444 500 ] endobj 115 0 obj << /Length1 984 /Length2 4081 /Length3 532 /Length 4751 /Filter /FlateDecode >> stream xÚí—WXSé·ÆAŠô&" AzM€Ò!@¤÷Ž ! H‘Pƒ‚t¤J•*HTDºHB‘*U”^”*8" H8ÑùÏŒgæòœ«óœ½÷Å÷[ß»Ö÷>kí}±ùL-$58$‡õ‘”–’VhAl¥Ai)B'(¨…GÂ|P8¬6Ì©VT”@‘.¤éQ’+äéZ¸<ÊÍÝ ¢%úC¤ÐÄ ñ(8 0‚ù¸#1¤p`ƒ£>)€& 0ÿ‘á 0Gz#ñ~H„´4‚û\n(,ð‡'=¬+ ðGá{ãÏ-?$Þ›d òÓ¦(€dâ Ò•hŒ#†$yùß°õÏâP_4Ú†ùQþg§þµàЄÿ(p˜¾>H<À‡@â±ÿ”Ú ÿ0Á¡ÿuŒž ‚kbÝÐHèÊŠ @"LQ>pw€+ íüGbÿ´@jÜO@+{MSñÿÌôç¦) …õ±$Üø«ìõO–þ›IÝÁ£ R{¥IBÒýçÊñ‡é`á8 ë‘“ÀðxŽôöHpS€Â"dÉ1P ‹ó!¥H- ¸âðt?*/jþýAW@í¿HA4ü‹®€@Ó¿ˆ4K ìoRá‘4ˆ$Eü‚Ò ò€î¿ Éêo$õ ˆýI¹¸_”‹ÿI¹Þ¿ ɰÏ/Hòèûÿ=pSR–dMRFô# PËýw¥åå‹ÔÓÈ@ Rw~Dá¾x<ëóó› ÿOvE‘^$2 §›|‡ƒ+Gxd|"™]Ògà%6Wm{X–}Ži…j…×ÿ;·wló-³èf¨WRæÛ“?ç•ìÀnÛíl#ÂòËßÂ7˜›ž}ý$Gn2:×ÿ8Í®øÕý/]¦"Ú–«ggøÈÚüjÛr"äl¡Ùh«èÈj!Y>s–L¯ÇwÀѳþ,i)”³CáÁÑ4/ħ·p;l‡E4RO®“À©ãâ¼¹îŒûÐ3NýέÔ0_« ©(×µ˜·ú4ÿùãºA#à3nâ²ý‚øw¨V€ÃÞ5þÅÆZžÃEíÙÞ2n•~",,iBµÛúàmËI?§dåbVÆ6bŒæåYò!SpZoOBDvõGÕPÇÓäSsýr¼K…Ù+¦Æá»µV£‹¨½5ù ;ê÷ËÝêsêE}£ø®[èV­ç¸¥nAŸ Rî@ΞT}%ã~âXŽ™^’ñ2&äêMˆìHʼnP 4‡hn­jXtæÓ}Beû¾&“ÊOÃÔìiÉÞ a%K”IÜãór-‘RÚ¤Ä$÷ÄGÏUª¬¼ž7yn–ÅÌ5âC»Åç¯êî?O9_*"–¸Rþö’™iç•j¡t\A]±HcךäôE­e€Rï|Š?í])ñÛKŠ®Iz—ûýA‰‰1 —M3ÏæZÛ=Ë“Î/$æTí~ÕR3ÞìvRÏmÐ8ãZ„\ŸÚ+ÆKn‹P‹ å÷Y[+Ò¿¥ŸõIAcÂ{hSJ N»ï4µ4ÌÎh%nÔÊËÑ9ð©$¥“Iû¸å% +g³…ö°ôê7/¸Ü˾CÙQžPÑ«]P¡›`Ù³ª2–šÂV‡9vjºÐˆ¡Þ§œT/¿÷°î2zŽ…G)¬ 8@U‘¶$„z}eñõ»×±%­=±n­êQ{¬×QÊ_V™E•ºM'7àÌü <Òlp‰–bÔáÕg)¨2”=<¢Œ’u¡¹_Y#1g'•ãí°,yªžÔ¾™ÊkÝKZ„Þ ·îþ¾àf—ÈÀS—ŽZ~k”x¸°óû‚¿Gãy0dE{&ôFX n¡¢WÁÀzp=vîA-ûºXõž$Øa†œ‰Áó4ÉÃéËA3 5¸t‹Öš/×ö*qÈg›„/°Í3Nd%ó¼š Å…Ôæin‰š´–ÙÌ?í¾Ýiª^dÿêßW³Ý"úŒm¹ZR YâE„Úõ7iöfé»J³%«N-Ò,×vGŠ%5^S+Þ,¼ÐÒ^[oà­•ï¼­£|ešÌ-)PdÃ){.º“÷fé}8üG;/sºµëSÞ¸kw:M­ÏjÙÃîEìžr±†w§UN•欽]Ý}UÎí“ÞÖœsÑ7ÿžl~ÛlúV:1/f×u}¬Ø-àn*{uK¬¯µ0ÀÂx’!tÅ–ÞIÚLñ¨_0€\ M9Hï¸a™Âƒç°¬ÑïB=Qïó½Ah›¤=¯‹.ïÙý4ïQzý0Ù.ÇzÇEzæÊ厯ýŒ—ØA=²Iójoµ¦òÕ ¶Ôß÷»mtÆ¿ ^p–-Z¹ãgÆ/-©U.îñÙ<‰°óv+,gAp¶àžñ±s¯™¿‹kϽp}4¿¾vÈF7E%ÌÒšaš¥×Ppú²¹}vñd8¹²Öh|ï$ï¸ÈCÈø­Ö´¬0R…öê÷ûóN„ëƒ7LÎ8ûÖÑI°ð(m=áGVm²|ížéɾÇÕÑ©qˆXîú¬ÎtX=¶Œ^îpò³x õ¥Ìj؃^"—ïÀˆ‰çé8Ï·ã[U¡PÏÏfm6ØI•¥Óg³&1SîÖAAߪ3£óRY޷ܪ2î¯<ʳN.||<6”wïÊö¼ð$£)ïña‰z9êÈÄÓM0¨oQ Û[æ9y%ÐpöÖí2«Éü½¤iösRËdò/—œƒG.;žD’-Ͻ¥ °ÁÈá®õݽi¶ä2é¥né+ŸCKY•¶ÜЖ$ät"((¾$Fm˜ßÄTn&8Û¢¢;©ÏxþcÅ“–uL¨Bì™.yÇÁPÏ‚Îd—ù‹»´œ‚cf5æ‘™Ããa±ñ¹RÕ&GvKá±B8&gs/Ѓ 7.Mp‚;à^-Øë³š(鄆2çK•&svš›ˆ7d|C;°ÝÅ\„f(êÖo£*úOLÖf¬6Œ½tÌ•tYY[i”êÍhaÞ–\Ÿ8…/2µ‡‹Âjf¦a*©{’qæC½Ô™“‰æ †½¼wâN^óWçV}?ùÔÛÀé+ìÖ ™%9EÙ^÷ aµ¤ó%fa+sYèÌ'ˆD5%³ðÚ­dWéøKÞuÐÍd~¿"%'C äsw)OaN?%œU÷Ê£h ¶Õtd¼¹~LžS«ëÎÈ?Zãð‚ó;‹Ä[rLVÓ•ØN ¡é^™À•YZõˆoiÁ¨-ZÕ»Âýµf€:A'ŒÛ¡øˆ-ñèíF8Z1³ŠElî¦ó30o§öG˜ý tdU|ÉŒ Ðÿlù ŒÝÎôÑHtuãó0Y¬äwþާc§ÍlÔ¸•’Üœ#ÔÑa ‹ä‚í éœ~çETÕ§êyxÁ%ëš&Ý^ ®R_´Vˆêgln•ßKá·Æ\zÖpšø(¨ÏÏ“öQ9A³ü¹á{ë¸ÿv¡Pà‹ñ’º½W‰«¨§w“˜p_kÞÖõ,òí\jÃi«ÌŸéÅż‹•-‹ ×ҘϪoör9­×lM¼»®dÀ‘)©ý,n„Þ€ð£î¨½s@aíÕÅY#[d$^[öoþ¾@c0“ýìxÛêu8ÑO‡A }Å×¾ïKä³õ»yò:|õz…wËtKÂÌ{Æß}±@õ*b?\..j09^;ÞŸ~7™UTAŸ~-[„VóùûÖ˜Q«Æøþq#òÛØ®»5Ÿ9,Ï﵆{šôtñ<Šw3þ2l×ðÄÊú^Kdh{ Ú‡µöʆêëª ÎÓÁ¬Fó£w)·KD’xB´™/ßæZŸK°´/¡ÕTëÑ û ­q±Î,¿‰î§­OiŽ÷Ð>¨aÜ:·°àõI×#-ãù°Ç2È µD!y¢3[}ˤz§Éû~ÜtG}×eúLÀöv“ݹL|+ÖÉ (;¨!‹î¤î»l³½CMò@]4©«™Œ|]ߪ2éj ¼3Öág°¬vÖ»-oVz†W/¶sœÆÕ•d—TÉÐïVQ•2Q¦•­BÓØvÜÑ?N¾ÚæHŸ‚ïιËÔ¸W>°¯ÿÊ|!çlf÷V¨ž¿?¥¦£Ë{î¾ghoÆ1±[)GBnmÆIþSfÖ£úsâ IƒÌ㯑ÞÎ^ŸrWÈÚs¿ëÅ’!˜â†øo¡•¾Sün{~–kJ¸ô°ÒYƒBqŒŽdJf¦äœN²µŽQÛUÿ:⎑kªÔÑHŠ S‡ÕŽóôbÞK}™‡³`Õ|ÑS¬œ×úkšß¸—÷Ê4.¿ô»P¶û’[øy#=Ïe‚ŽŸÅMm×#cTgy5= á²wÅ£xØ‹óÛæO¨¾4ê‚Åm·9 š%Ðð®¤{r_ú`š{ðð'_”°‰÷8–f÷¹òõ®0ó&8ôðR’×wq¹_üø(Ʊ^t'˜öÃÈkú Á|ŸeÍá!–D¬Š)°É6·.ŸFe’qe*ŠO;8c`:<„iyýy!óP«`EvÒû"¡afÕ>ÄÙî)O£S¢¾Š~þSíµ±£ìZÆ\²ó¢Óà gÍ©.Sx_ûªýìc«-{ZžáÇi`¾ì7…£-»äaïD‘ßKj\Ÿ\0+ôAÇ<þÂ×xIcñ |Óô裈>úR¿QCRÝâø{«XîÑüAD‘íRY½ÂŒ,] ±#~ÛH[§n6ƒæ¥£Øœ|Á-¡.¡Í ‰­7ÎŽ.-ÊX³.÷6‰PÖ†ò/ÙÓ:挴&ÄùoëZ4Iw¬æ(O Ín_½ðÖÑiÞjª€ÍmD“—ˆôe\ÇãYg<EÀ—pgJL×°5 ɰ˵Âq¶T\©´Î½ä~¡õÄSJeÙÒh±wI‚¼ ËÑlŸ‰…+M–0—Y“Û³PÏ2÷†ûÖýÃ1AeÊ™®Y”‡LœÎK‹3ly½•lÙã+`º>º€+Î1 ´äýºׂSÌ;˜B2yóR/Ed]óJv•à{øh=Üìy¥ú‡SšsMX:NÞrߊƒ»[À™òpÿþû¡ôµ‹ëSÌKƒùKËS¯ÚWêo“þÎ[°ub Qƒcªd‚ô‚ø1 ›È@ðÝ}–oû.1Öq''æ€ÜÔÞûlÄú*Û”züp‰á¡¥€7ó¥‘Öàw•·Ga,ýèxâ|®É]ÝroW»—8¡úb¢M ïÌpBmY½jB·™Ïù[=|¿ž6ã?ÇàÖ«í³‹SLCÇÓ¤@À -Ϋ…»/û´/î[\rµŸ 3EŸý ¯ÚçvxÛ¡”ÙÀkS¬Ÿ ‰;òºÕJ¹SEfdç*‡€âW4 Jû”B¦œ4Ùi"•`b(®‡©†MäÊ‘|¥é­í¹í‹1'j…Õô<=TSY}¿Ýšo»½^Øý/ºÿ/ð¢„á}pޓüyêendstream endobj 116 0 obj << /Type /Font /Subtype /Type1 /Encoding 254 0 R /FirstChar 65 /LastChar 117 /Widths 259 0 R /BaseFont /EUZAKP+CMBX10 /FontDescriptor 114 0 R >> endobj 114 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /EUZAKP+CMBX10 /ItalicAngle 0 /StemV 114 /XHeight 444 /FontBBox [-301 -250 1164 946] /Flags 4 /CharSet (/A/D/L/P/a/c/d/e/h/i/n/o/r/s/t/u) /FontFile 115 0 R >> endobj 259 0 obj [869 0 0 882 0 0 0 0 0 0 0 692 0 0 0 786 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 559 0 511 639 527 0 0 639 319 0 0 0 0 639 575 0 0 474 454 447 639 ] endobj 112 0 obj << /Length1 983 /Length2 3248 /Length3 532 /Length 3911 /Filter /FlateDecode >> stream xÚí“y0-è³ÍO¹[yíb»îÒM¯È„ÞÝio§é¤«¯ømW“Lü¦<ÏlÜšc¯(}¿6g6ëþô6'öRVCÊrã\†¹ØËχ> 1ÕØ{¿¨I–W°ÕMÂ[……”œ“²8–à•s[.lØçXlôþáw·ÜÃXË%?¬*iœ›™¬é1»W9¦g€xŠôîKÉâ—)&ÆevÄ‹d‰?·Ï÷ÃqnËЕÄ~Z‡€ì„q=šc@àwæª"pr2«Ç‡é…wÁ|j…ëbf *hצ£Ûî,Äz­húüLþ?T²,Õ½ÔsŸ~–ˆxÐ .°Ÿúsæ‹ÀOG¶9E"gVZËÖµ—en}íxbä›Q”òd¦Àìu¡ðÂzæèu„¢ƒ^]n½ì€øš¾¦Shhp-çì³6Õ^ý|€|¬»ýŠ©t\BÜF‹™Ùú®¡php¯h´°>nvìñ@þÚ˜bY,¹;„ÏIŽmÚ5)PÝö@ÇaÑ?¸´è îj‘àÚYEù¶¦3#/OŠõ” FÙÖ>Lª3À¿ÂIu±ðâü¥ß¿©‹ ¨wbóÕi@ —Oµë¸Ã®â2j¥•çQ|ÒSŽ'_;gü­ëVJEÿ] ûy¶kÑ´Í„3?­öÙõŠèƳßZìîçÝwøt%G¶B2g…º†£o¶ZNŠº òhÊ=ï•ã?Ym„˜¾É‡:Ñ,"UºÅ‡Aµ[‡Ÿ%”Ë&H*¶>þµ´¨æFÔXñ÷ë2}$“Ná®6 ù§ ‰jAŠ‹¢L»Û–óíìxí›B&9Õu7˜¸„Þ#|¼6ÄvR§®í^Š.›¿­VlnîvN žéŽÿu1`ËÓN½ú†œ}ž'>= <4a£uu"d[4h ñ>DòñP©˜4%… º©urkEù°Ì ðKüú-sn’^”ÑŠ¶4ßYÜH-&„¨+¯½àó™Õûá&h}²ÜSuÒzB)ê˜p/WȦrŒIÊê¢Ó¹B Wm“+ëŽU3ðä­ÈÏçWŽÜþ~IÇ=£¢œež“p°™Rw ë|n@ó•ínßCb“{Qñ ¬Ææ…žÇRÏSçKÚPÉš>X‚CjÚ¯Ôo§[ï+qD÷…áNVÔ” »AH¬› 'ë]„ü&íÒœèµ2ø—c—*J8Dxm¥Ø8÷ÛIí/B?h qøíçHm‡n¶‘žõïÆò˜[Å.µr(kÎŒÈ>T嫉æÅêÌvòǪŸÎݶò^ûfgUY´:›Ù œ2*ɹ) ôCØIîÆçíØlµÓ“U+Ûàd^%Xb“c_w®âÏ{ØþØ‹‘~%¦±ƒØ ×S© þÇí°GùÌÉÂ$«B–Þ{…ùm¹2/ý`ÔÖØ¬ZeSà gåÒp\ÀëBÔi~%º¾ë§xƒ+÷#ð­ŽYëŠ-/II†Û·löãŽhh~í (KÒ›~oþ¢ÞfMŸ—¼qv'²6`ÅodAµzXëŒÊócŸ‡{ûô¸¹óøÖEÆnL‡j\5;osè•b3i÷5üÄÈåy ‘,¹\ÉÿÒõBË¥4Ê…&1LOÂÔµkëz¹fݚœI“æR}÷ÝLjtêYw‹ïûà[ôFe¹…ûûÍIqƒPÉg]à|kµAvpjSðIñ3‘Ÿ$ç/h½¹ýþ²ýÒ&ÓéIýW<Ú*ÁÌÁñZ9-Ý֟Ѫ$=6iv³ æÎH±TXÖPȇ`½®B/DöÑÛ{y¢mCEÃð:÷2Ò˼?LI¬ºÝÕ§rǪÙúQ»ž—€¢åغ‰Mâ]OE¬O» Mb¯ôuHk’EÉá¹>§4óo¼»ÁÌ2W¤ìa¿¤\™j.í^UãŠ~ÍÂíÀôp“ß=Üïk‘},¿Ñp¢.X£4 ©Hlxó ò¢çp‰-2\õûxû÷wn_gð&u_&€Ÿb6ó!Ö­\¼hkƒ©ò~Úš¿çh$°B?Ôp"4—»Òô9ìãšÛ%ÂM=…š”< ŽŸ›SwU¿¸Ë¨EØ5ÓWOm_[:¨l9íÊ©ø´7‚ÞHe6ã‹ (= u8i¢Ô¿Qmõs‡çn²'UÃáþ¦n«ÕÕÐ;÷:Â8XNùNlT<°ÚC╞Žð¨…Ù½˜æëþ–Yë=â4Ì_`9b §v­Môk‰T¾dŸ‰Ì2¸3ÞK6{o!ß(P»rÒYluy鉸i-®<Ä¢,ÜÅ´#T«39Ëåzyù=§EvóM×*¿Ìñå£;B3Ås¯¦ ÒYz d©‡»ƒ½Oq`dÆÕ4ûW#<Æ{ÓËX×»…íœô6C‡ëµ˜ÝGç—‘ç !’áÕÎá´K øU!2oX˜l[.3ño>o±(õS1D‚“39÷ûBfç÷#¹âf*ë»Sžµ¶4š­íôûE.?è¢l Tʲ¶nîGç­ž|<ð8MÚXúrØÞ…{ûôÖ^¬ÂíMˆ áÍÉ^Nè-ý7ÅTûÂr]ªë¦ÍKØÓKn´Ž#p%ÿ5’8!X wj3Ѝ™¤tí`Òý¥²•ùÄ΢6ÊQó<*Y™h 3{‚ÝhJ—ïcÿ)yó<Ž6ÖÚ—ºª*çÐ,϶ãme̓‘˜Îú”°}vŸÜMqU',»Ïå»·§—|JaIqúìŽàrú^×à5tò¬Lë@!mÝ¡¬?xà§‚-ì >ìxÂij>›”Náºf,hä{‹úC•tL€ÛžŠx¹`£âÓ‘ ç`Îên´áIuŸïhÿ–_p÷¤rz SÒ™W!Xw°¬xª¢ÿû£{»WÂGÔA)Kq†Ò~3¥ÃÞaª‡bƒ”oò¢ŸT>oª¸Ð;SÅüxƒn‘:C[Ä®ÂuvQ'^ŸR¶­Pj2-÷tÆË™v. Fª‚›Áàˆ¥W{œ ‘Ã~­Ç}-ETUUkwg?Íœ}nUZ|ÀFk/_Yʸ|å[ËW$Mä¶`LÉöÃ|C©ÔŒ\¤n„ûˇãHöbkt ±¤·Í¯½¼›ýÙ¨$¿_Y ha€Å1jóhÔv~Á?‘÷¢j h+à2¨4­Už¯ÁªÖ{â¢3ÛD3:ឦúy2ÿàõ¸*[‰å—Úü狪W,¸t:ý¿Ä_yÐdÔàä åp–r¨¢«Z$¢“\ÝfÞ‰¿®ù£¥ø TG‚²êj#¶ÁbgbÚ›sØÀg__ŸswÇjž÷™Äp§"X¯ñüþ¨t}èÿðý¿Àÿ 4‹"SIÙô/hoúendstream endobj 113 0 obj << /Type /Font /Subtype /Type1 /Encoding 254 0 R /FirstChar 44 /LastChar 117 /Widths 260 0 R /BaseFont /SSHEVG+CMR17 /FontDescriptor 111 0 R >> endobj 111 0 obj << /Ascent 694 /CapHeight 683 /Descent -195 /FontName /SSHEVG+CMR17 /ItalicAngle 0 /StemV 53 /XHeight 431 /FontBBox [-33 -250 945 749] /Flags 4 /CharSet (/comma/a/b/c/d/e/f/i/l/m/o/p/r/s/t/u) /FontFile 112 0 R >> endobj 260 0 obj [250 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 459 511 406 511 406 276 0 0 250 0 0 250 772 0 459 511 0 354 359 354 511 ] endobj 135 0 obj << /Type /Pages /Count 6 /Parent 261 0 R /Kids [106 0 R 137 0 R 158 0 R 168 0 R 175 0 R 193 0 R] >> endobj 212 0 obj << /Type /Pages /Count 5 /Parent 261 0 R /Kids [204 0 R 214 0 R 228 0 R 238 0 R 245 0 R] >> endobj 261 0 obj << /Type /Pages /Count 11 /Kids [135 0 R 212 0 R] >> endobj 262 0 obj << /Type /Outlines /First 7 0 R /Last 47 0 R /Count 4 >> endobj 103 0 obj << /Title 104 0 R /A 101 0 R /Parent 47 0 R /Prev 99 0 R >> endobj 99 0 obj << /Title 100 0 R /A 97 0 R /Parent 47 0 R /Prev 95 0 R /Next 103 0 R >> endobj 95 0 obj << /Title 96 0 R /A 93 0 R /Parent 47 0 R /Prev 91 0 R /Next 99 0 R >> endobj 91 0 obj << /Title 92 0 R /A 89 0 R /Parent 47 0 R /Prev 87 0 R /Next 95 0 R >> endobj 87 0 obj << /Title 88 0 R /A 85 0 R /Parent 47 0 R /Prev 83 0 R /Next 91 0 R >> endobj 83 0 obj << /Title 84 0 R /A 81 0 R /Parent 47 0 R /Prev 79 0 R /Next 87 0 R >> endobj 79 0 obj << /Title 80 0 R /A 77 0 R /Parent 47 0 R /Prev 75 0 R /Next 83 0 R >> endobj 75 0 obj << /Title 76 0 R /A 73 0 R /Parent 47 0 R /Prev 71 0 R /Next 79 0 R >> endobj 71 0 obj << /Title 72 0 R /A 69 0 R /Parent 47 0 R /Prev 67 0 R /Next 75 0 R >> endobj 67 0 obj << /Title 68 0 R /A 65 0 R /Parent 47 0 R /Prev 63 0 R /Next 71 0 R >> endobj 63 0 obj << /Title 64 0 R /A 61 0 R /Parent 47 0 R /Prev 59 0 R /Next 67 0 R >> endobj 59 0 obj << /Title 60 0 R /A 57 0 R /Parent 47 0 R /Prev 55 0 R /Next 63 0 R >> endobj 55 0 obj << /Title 56 0 R /A 53 0 R /Parent 47 0 R /Prev 51 0 R /Next 59 0 R >> endobj 51 0 obj << /Title 52 0 R /A 49 0 R /Parent 47 0 R /Next 55 0 R >> endobj 47 0 obj << /Title 48 0 R /A 45 0 R /Parent 262 0 R /Prev 23 0 R /First 51 0 R /Last 103 0 R /Count -14 >> endobj 43 0 obj << /Title 44 0 R /A 41 0 R /Parent 23 0 R /Prev 39 0 R >> endobj 39 0 obj << /Title 40 0 R /A 37 0 R /Parent 23 0 R /Prev 35 0 R /Next 43 0 R >> endobj 35 0 obj << /Title 36 0 R /A 33 0 R /Parent 23 0 R /Prev 31 0 R /Next 39 0 R >> endobj 31 0 obj << /Title 32 0 R /A 29 0 R /Parent 23 0 R /Prev 27 0 R /Next 35 0 R >> endobj 27 0 obj << /Title 28 0 R /A 25 0 R /Parent 23 0 R /Next 31 0 R >> endobj 23 0 obj << /Title 24 0 R /A 21 0 R /Parent 262 0 R /Prev 11 0 R /Next 47 0 R /First 27 0 R /Last 43 0 R /Count -5 >> endobj 19 0 obj << /Title 20 0 R /A 17 0 R /Parent 11 0 R /Prev 15 0 R >> endobj 15 0 obj << /Title 16 0 R /A 13 0 R /Parent 11 0 R /Next 19 0 R >> endobj 11 0 obj << /Title 12 0 R /A 9 0 R /Parent 262 0 R /Prev 7 0 R /Next 23 0 R /First 15 0 R /Last 19 0 R /Count -2 >> endobj 7 0 obj << /Title 8 0 R /A 5 0 R /Parent 262 0 R /Next 11 0 R >> endobj 263 0 obj << /Names [(Doc-Start) 110 0 R (Item.1) 190 0 R (Item.2) 191 0 R (Item.3) 196 0 R (a-performance-model) 182 0 R (a-performance-model.1) 50 0 R (abstract) 124 0 R (abstract.0) 6 0 R (background) 130 0 R (background.0) 10 0 R (c-compilation) 145 0 R (c-compilation.1) 18 0 R (changes-in-gcc) 232 0 R (changes-in-gcc.1) 94 0 R (compiler-versions) 199 0 R (compiler-versions.1) 66 0 R (conclusions) 241 0 R (conclusions.0) 242 0 R (conclusions.1) 102 0 R (design) 155 0 R (design.0) 22 0 R (distcc-press-gangs) 217 0 R (distcc-press-gangs.1) 82 0 R (estimate-of-feasibility) 186 0 R (estimate-of-feasibility.1) 54 0 R (generalisations) 225 0 R (generalisations.1) 226 0 R (generalizations.1) 90 0 R (good-logging) 221 0 R (good-logging.1) 86 0 R (is-it-safe) 188 0 R (is-it-safe.1) 58 0 R (lifting-compilation) 207 0 R (lifting-compilation.1) 74 0 R (lzo-compression) 173 0 R (lzo-compression.1) 42 0 R (makefile-bugs) 201 0 R (makefile-bugs.1) 70 0 R (networking) 163 0 R (networking.1) 30 0 R (outcomes-and-applications) 180 0 R (outcomes-and-applications.0) 46 0 R (page.1) 109 0 R (page.10) 240 0 R (page.11) 247 0 R (page.2) 139 0 R (page.3) 160 0 R (page.4) 170 0 R (page.5) 177 0 R (page.6) 195 0 R (page.7) 206 0 R (page.8) 216 0 R (page.9) 230 0 R (previous-work) 142 0 R (previous-work.1) 14 0 R (scalability) 197 0 R (scalability.1) 62 0 R (scheduler) 165 0 R (scheduler.1) 34 0 R (section*.1) 128 0 R (section*.10) 178 0 R (section*.11) 181 0 R (section*.12) 183 0 R (section*.13) 187 0 R (section*.14) 189 0 R (section*.15) 198 0 R (section*.16) 200 0 R (section*.17) 202 0 R (section*.18) 208 0 R (section*.19) 211 0 R (section*.2) 131 0 R (section*.20) 218 0 R (section*.21) 222 0 R (section*.22) 231 0 R (section*.23) 233 0 R (section*.24) 235 0 R (section*.25) 243 0 R (section*.3) 143 0 R (section*.4) 146 0 R (section*.5) 156 0 R (section*.6) 162 0 R (section*.7) 164 0 R (section*.8) 166 0 R (section*.9) 172 0 R (security) 210 0 R (security.1) 78 0 R (simulating-gcc) 161 0 R (simulating-gcc.1) 26 0 R (ssh) 171 0 R (ssh.1) 38 0 R (worse-is-better) 234 0 R (worse-is-better.1) 98 0 R] /Limits [(Doc-Start) (worse-is-better.1)] >> endobj 264 0 obj << /Kids [263 0 R] >> endobj 265 0 obj << /Dests 264 0 R >> endobj 266 0 obj << /Type /Catalog /Pages 261 0 R /Outlines 262 0 R /Names 265 0 R /PageMode /UseOutlines /URI<> /ViewerPreferences<<>> /OpenAction 105 0 R /PTEX.Fullbanner (This is pdfTeX, Version 3.14159-1.10b) >> endobj 267 0 obj << /Author(Martin Pool )/Title(distcc, a fast free distributed compiler)/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.10b)/Keywords() /CreationDate (D:20040321191400) >> endobj xref 0 268 0000000001 65535 f 0000000002 00000 f 0000000003 00000 f 0000000004 00000 f 0000000000 00000 f 0000000009 00000 n 0000006017 00000 n 0000119299 00000 n 0000000055 00000 n 0000000088 00000 n 0000006197 00000 n 0000119176 00000 n 0000000136 00000 n 0000000172 00000 n 0000011387 00000 n 0000119102 00000 n 0000000224 00000 n 0000000265 00000 n 0000011568 00000 n 0000119028 00000 n 0000000317 00000 n 0000000358 00000 n 0000011750 00000 n 0000118903 00000 n 0000000403 00000 n 0000000435 00000 n 0000015928 00000 n 0000118829 00000 n 0000000488 00000 n 0000000530 00000 n 0000016110 00000 n 0000118742 00000 n 0000000579 00000 n 0000000617 00000 n 0000016292 00000 n 0000118655 00000 n 0000000665 00000 n 0000000702 00000 n 0000020653 00000 n 0000118568 00000 n 0000000744 00000 n 0000000775 00000 n 0000020835 00000 n 0000118494 00000 n 0000000829 00000 n 0000000872 00000 n 0000025437 00000 n 0000118380 00000 n 0000000936 00000 n 0000000987 00000 n 0000025619 00000 n 0000118306 00000 n 0000001045 00000 n 0000001092 00000 n 0000025801 00000 n 0000118219 00000 n 0000001154 00000 n 0000001205 00000 n 0000025983 00000 n 0000118132 00000 n 0000001254 00000 n 0000001293 00000 n 0000030009 00000 n 0000118045 00000 n 0000001343 00000 n 0000001382 00000 n 0000030191 00000 n 0000117958 00000 n 0000001438 00000 n 0000001483 00000 n 0000030373 00000 n 0000117871 00000 n 0000001535 00000 n 0000001576 00000 n 0000034885 00000 n 0000117784 00000 n 0000001634 00000 n 0000001681 00000 n 0000035067 00000 n 0000117697 00000 n 0000001728 00000 n 0000001764 00000 n 0000040204 00000 n 0000117610 00000 n 0000001821 00000 n 0000001867 00000 n 0000040386 00000 n 0000117523 00000 n 0000001918 00000 n 0000001959 00000 n 0000050435 00000 n 0000117436 00000 n 0000002013 00000 n 0000002057 00000 n 0000044834 00000 n 0000117349 00000 n 0000002110 00000 n 0000002153 00000 n 0000045016 00000 n 0000117260 00000 n 0000002207 00000 n 0000002252 00000 n 0000050403 00000 n 0000117183 00000 n 0000002303 00000 n 0000002344 00000 n 0000005347 00000 n 0000006318 00000 n 0000002396 00000 n 0000005834 00000 n 0000005895 00000 n 0000116383 00000 n 0000112191 00000 n 0000116222 00000 n 0000111803 00000 n 0000106770 00000 n 0000111641 00000 n 0000105889 00000 n 0000089449 00000 n 0000105728 00000 n 0000089208 00000 n 0000087200 00000 n 0000089047 00000 n 0000005494 00000 n 0000005956 00000 n 0000085510 00000 n 0000075579 00000 n 0000085348 00000 n 0000006076 00000 n 0000005665 00000 n 0000006136 00000 n 0000006257 00000 n 0000074042 00000 n 0000065813 00000 n 0000073880 00000 n 0000116813 00000 n 0000011871 00000 n 0000010218 00000 n 0000006454 00000 n 0000011265 00000 n 0000010389 00000 n 0000010559 00000 n 0000011326 00000 n 0000011447 00000 n 0000010739 00000 n 0000011507 00000 n 0000011628 00000 n 0000064179 00000 n 0000054707 00000 n 0000064017 00000 n 0000053530 00000 n 0000052123 00000 n 0000053369 00000 n 0000010911 00000 n 0000011094 00000 n 0000011689 00000 n 0000011810 00000 n 0000016413 00000 n 0000015687 00000 n 0000011994 00000 n 0000015806 00000 n 0000015867 00000 n 0000015988 00000 n 0000016049 00000 n 0000016170 00000 n 0000016231 00000 n 0000016352 00000 n 0000020895 00000 n 0000020412 00000 n 0000016510 00000 n 0000020531 00000 n 0000020592 00000 n 0000020713 00000 n 0000020774 00000 n 0000026226 00000 n 0000024535 00000 n 0000021005 00000 n 0000025254 00000 n 0000025315 00000 n 0000024690 00000 n 0000025376 00000 n 0000025497 00000 n 0000025558 00000 n 0000025679 00000 n 0000024878 00000 n 0000025086 00000 n 0000025740 00000 n 0000025861 00000 n 0000025922 00000 n 0000026043 00000 n 0000026104 00000 n 0000026165 00000 n 0000030494 00000 n 0000029707 00000 n 0000026323 00000 n 0000029826 00000 n 0000029887 00000 n 0000029948 00000 n 0000030069 00000 n 0000030130 00000 n 0000030251 00000 n 0000030312 00000 n 0000030433 00000 n 0000035188 00000 n 0000034447 00000 n 0000030591 00000 n 0000034763 00000 n 0000034824 00000 n 0000034945 00000 n 0000034586 00000 n 0000035006 00000 n 0000035127 00000 n 0000116930 00000 n 0000040625 00000 n 0000039126 00000 n 0000035298 00000 n 0000040082 00000 n 0000040143 00000 n 0000040264 00000 n 0000039289 00000 n 0000039492 00000 n 0000040325 00000 n 0000040446 00000 n 0000039662 00000 n 0000039873 00000 n 0000040507 00000 n 0000040566 00000 n 0000045137 00000 n 0000044321 00000 n 0000040709 00000 n 0000044651 00000 n 0000044712 00000 n 0000044773 00000 n 0000044894 00000 n 0000044955 00000 n 0000045076 00000 n 0000044460 00000 n 0000049080 00000 n 0000048717 00000 n 0000045260 00000 n 0000048836 00000 n 0000048897 00000 n 0000048958 00000 n 0000049019 00000 n 0000050332 00000 n 0000050152 00000 n 0000049203 00000 n 0000050271 00000 n 0000050466 00000 n 0000053735 00000 n 0000053759 00000 n 0000064479 00000 n 0000064795 00000 n 0000074355 00000 n 0000074633 00000 n 0000085859 00000 n 0000086205 00000 n 0000089419 00000 n 0000106367 00000 n 0000112033 00000 n 0000116613 00000 n 0000117039 00000 n 0000117109 00000 n 0000119371 00000 n 0000121535 00000 n 0000121574 00000 n 0000121612 00000 n 0000121839 00000 n trailer << /Size 268 /Root 266 0 R /Info 267 0 R >> startxref 122066 %%EOF distcc-3.4/doc/web/distcc-lca2003.ps.gz000066400000000000000000000642051404653710500174650ustar00rootroot00000000000000‹T£Q>distcc-lca2003.psíÝisëÚa&êÏ_¡Ûu¡ŸÃypUW_O‰]7*vW:·ÓÕÅÚ[±¶´£Á>'.ÿ÷Kb‘âEARõ0)z @‚‹ /Öðƒÿë·¿ûá§÷ãô‡­oW?ÿíïþaþä?øéC:zºøÑÕ—O_[_g?ùýÍÓmú£«éÍãÓdòÃÛɨÕh´¿™ýzö»ßŽ>¥?ºj¶gÿþÉýóÝôæîÓOî¿ûÑUcöÝa÷jÐiÍ~õ³ûÉó—ôîé·£¯éÃïnþsnFÙ/~óp3ûñèéæþîGWÿ4º›>Nf›Ì~ñó»éOï¿ÌÍcòíÿüÕÿùùë«fãjš^_}û¯‹ÿî†ÿü—_þì÷¿¸´Zá?ñó_þã/~Õd¿žéŸüægÿz6Zþ¥ÖÕ—çÛ«ÇçqØäéÃÓ§Ñ׫æâ/~¾¸ùÏùá÷écúôýÕŸ¿ýþËÍÝÕâU|ÿeô]ø÷_ÂVómæ?ûóôùëUö¯OOá?¶éw“Ïaó›ë«¯÷_c6û³ 6û×íŠÍþk ›Œn'³—t=º}L¯&ŸG_GOŸ¯®oGOOé]öïùÓx|ÿÝÕò…ÍðÕro/(¼·äÛ?=Ü<¥ó­ÿœ\½§å‘þa3;`_îÿ˜>ÝÏÞôâ/~üp{s7ûùÌ…£ÜXþdµåú& ¹Úòñéáþi²xsËs}s{›½ »ôOÙ{:ý ›ÜÞ?¦Ù¾Óûìå¼~¥¿þ§ìõÍ?€ÇYÁ¾ºùò)ûßOOÉÉzv´ç%íÛIö‹åÇ™ü—ðß«ô?f%+üÇËŸY|Þ³¿|uõç«—òÙ˜•·›?^5¯FÓéU óWû—-Û­¶X¾¬¹›o}sÎÊÍìß½ ¯){«ÿœ¿Ä¿\oî¦áÞÜÝ<½¼¼?ÏÞÍòß‹¯Ãrá?C© Ç(–Yq_ý™Ù ˜ô—Ì¿0ÙOV~ùb®–å?Y}o–û\þÕÁ_þ™åO¶þ•ç¯ÓÑÓìsžÕqw/gñŸ«Ãÿ`ýÀ„¿0/ÿ™>ÜgãæîËèáÓMøƒ³Âñüð0«É¾ÞßÜ=e_Âo_¶~ù‹óí¾}qá[~ž•ƒx‡“ÙßJfÿünþaÍw±xy¡¦›•¼P–ß•eé¿^l;[­¬,7{]4®¾ýnkQ¸M¯Ÿâ݇M_ÞÓúæ7Ÿ>?àå–¡áHÍêŽùwyò9ü!|Y×?ù_\þõ°ÛùOæ¥({-³ïøëcž=e_•—bŽåüe†ºhÓ7?n‡x1ññßó¥dŸÉ!^Ë«w¿óƒäÛŸ¤³R?o…\ýù¡Ô;îüŸ_ÞMþÏã¬u^=Žþ¸ü:|;½™<ýŸÉ¬±ñt•=Ïÿ{¶Õì-,6¸ÿÿzVY.ÏóWWϳq¶ýÕx¾ÃùÆŸïgg–O³:ä/a“Æüùéaô}øWv€F_g¿h.ÿóO7ÓÙÙàå·ÿ~Ÿý¥föƒ/³óÖìÌ1ûŸ«ÿõ¿Ã6ÓÑãçÕl¾ÏÛÑݧçÙ>oÓ?¦·Wúœ>Ìkâ?Ïø«_e;½KÃ÷!T ³¿Î?£é¿??†¯ÎÕ˯fGøáëÃìÃË~þ—ìü1þK|¬gM«WG:¥—ƒ6?Xó—ò—‡ôë¬)¸Üàå(Ï«ÈÕ'mÞMW[¿úÜf§Yc2}ýþaÖ~œñ~‘ÞÎ ÄÍd4«9î¦×÷³¿*ÜYË&ÍþsöŽæÿjêÐØœµ5¯šI8M­µ:«ö\VoO>ÃÙiý>{aËöIJ¡‘|š±¤;¸ŠÎOÉ›†àë†bòiùþ‚n~ÓÈÙ9${ɶfgc¹ihl<=ŒîgM·4¯¹ÚŒ]ö’¶ŠE çÕ®6¢Nãõ›^µ"6½ÉÆ7Ão²;{ôNó&W»Ê-«ÌÞòÝÓìÛ{{u}ÿpõ”~÷t¾×“û/_ŸÃ%IxÇ/ee~M³¨Ä^²«Ùf…úo®þö*k—ïÚ 9ÛÅ×ïçÍÈÙÅRØçü›ßž€‡ûYûrVîŽù›–Çò‹ÿidò¢¶h<<=<§¡MörJ^ãù†¯Oeß~ÿýÛJ;jG%³3qcVeÿùå‡/[Íó_–gá×Ç|qà—¯-œÂŽæmâèt°<2[ŽÊ«æÙ†Óù¼úûl¼={½~=¡aº:E-^À¯ÿéDecv=ûõæ6}È+"«íŠ””­åÛŸþÝßåÇåVUöô³›9??¥ÓÜý½Þ¶Ê^œ»¯WÜØ»‹l“*û¡Jî~^6«²/uÓ¹ÕMÿþÚ…çjwÍÓî®uÚݵO»»Îiw×=íîz{ž5W4ó6håmÐÎÛ “·A7oƒÞÖs«·¹ñÛ>F³ñõήfÿ¹V5ïØà½«æ8txïŠyy\Š|Þ„.gØdÜö±ÿöþþ6¯h„mŠ”ŽmáW£‡ÙKÏ-ƒ/›UÙWJúy5BÊ”õ}!ÿ~ÙFȱv×z·ÙÉjƒ_ü6ïË3ß·ӷsïogõ¯Ëɾ Ê깕Õói7}~zúú£o¿ ±É7£/ãÑ7÷Ÿ¾Í+2ÛZU­ªVUV?r­ªlÔ±l¼ídÙÕ!y¹—Þºj¹—î^úyÞKÿÕýÓÍ3›wã*ÞÒ2wÈ.©¡¦¬^RO“³¸ÛôO7wÏßåµåU¹îýÇÿó¯ó«Ÿÿ}n»1Ú°Êþ~7¿^ÏßÛËfUöu{ó‡4wO‹ªìçé!Msw´ÜªÒ;š}¥ ¼¥ÅVUöô“ç›Ûù@¡ÜE^zþòqî®VúëǼÛT|g­Sî¬}ÊuN¹³î)wÖ;åÎúºWÍjƒ¾ÄJ͆Iæ—Ñäóì>æÕvUÚ_Gù-«åV•Z‹ºÏo+fÛTÙËìƒÈÛI¶I•}üæ.ÿˆ…m´ µ µ ?DËð2ÚOZ?Z?ïZ.ﯟþ4klä¶H^¶«rŽÜ>?>¥EòžW›VÙçÍÝãÓh¶MÞWÛUjuhtUms¥w÷ÏŸ>çîçe³JŸX‘æê¤zkõg÷wý”»£åVÚyÚyÚy@  PX¸Z¹˜LF³×œÛÈYlU¥í1þ>· f›TÙÇ/ï¿Þ¥_óF¤¼lVeŒÖÏ¿»y|Šo&ØÐ˜0cÂê2kb',òÝ1FíÀ9Ä]ú4¿þÏ».|Ù¬RÿÏù—¹a›*{Mîó‡r½lV©Çý—/£»ü˜`µÝù¿ß>?æ÷Yl$‹EÈ"d²ˆ}³w¡Ü…ú(ã³n¦ó÷0ÛSþÍ›hË*{üçô?žo t²]m§E£E£E£·†op=ΓÛB”Î)C”Ù甆Ðý¿ç W›V9Ùüú~—[ZÃ6Uö2_ú>É‚—Í îëgQ_+惷bŽÛl9n;å¸QK‘låÕ_˜ÿܨãìlpÓ¾#€V 4®Xê׸¾ù2ú”æ¶«—[Uêñ›µËóûü.7«4‡æŒÜæS/›iXûûê? k k k k k' ëŠÅæ›o¾É+8Ù&Õ¦o?Œ¾ÿûS¸¿lXeŸÓÑ4}xÌß_´aÅ©ðÓ"ákÂûûjZMxMxMø4á³³¡ë…]× « †.(œæÎq¹çÑããmîd^Ë­ª4´¾}gœJMã”>>Ž>˜Æée»JK¤><X™~¹U•=ýx2;ðó[py;‹6tNrN’I˜ÀÉ7Ør½OÚc±®kÏÿþ)·†mœ«œ«\?9;8;¼o¹8ÅHȧY‘onož Œ†\Û¸Ò¤&7_¾ÞÞL íöõ¶ÕF˜}à“Yx|üQÕ^m\e¿÷×¹{Ë6©tUúø8»Ø¼›¸,¶t®w®w]ê^¹¥,• ®=dq×îU×#@ÎsÈßÜf8º)ºu•ñ Q3yç&UöñÛÏ£Çô1w?/›ßb|K]=Öî>Ò-ßeãö,:ƒ^ó¢ò’vx‹Ò‘\v“~þá½>hþÓµ)~öÊZž«gGwöîV-ÊùβŸf Òå ’ÿ^Eãê‡óÿnÌú¿“?/^Å|å–¤Õ´äê!M?§ß-þköòþ’\æÇ½Lîog×ó)©“FãúzÞ<-ò¼þHÇÅ­éü9mz#¥Þ3 Ã0 Ã0 Ã0 Ã0 çõHw%‘>g†a†a†a†a>k¼Ì›óŒÇ埓ýXQ<ÚžD&Û:Eúœa†a†a†a†aøŒðâ±Gyäôñm™½Æfü²[éëN‘>g†a†a†a†a>;¼Oy’ôqc9ãÑ2Š,›D*$0 Ã0 Ã0 Ã0 Ã0|l6Ž6o)$0 Ã0 Ã0 Ã0 Ã0|2œŸAžOúX*ƒÜ5×e[!a†a†a†a†áCãxåë «`oÌ Ï-}n{¬2ȤQ`a캤3H…†a†a†a†a†5ïc7]=¯gIÜò2ÒÇÜ R!a†a†a†a†ácÌûøjäu#ŠñöÉ ÏØöÆ R!a†a†a†a†áCá]dòúå2ȺL¹–A*$0 Ã0 Ã0 Ã0 Ã0|X¼9ƒL6ý¢hY¯%k†qâÚVH`†a†a†a†aøÀx=jLÞÆ.žAÖqÁìaœ¸¶†a†a†a†a>0^=’mBÉ ë˜>.pîÂØ Ã0 Ã0 Ã0 Ã0 WÀ‹ô1ÎËe5NsÆVH`†a†a†a†a¸:~›5Í kŸ>î‘A*a0 Ã0 Ã0 Ã0 Ã0\ï“A^HúX*ƒTÂ`†a†a†a†ax?\.ƒLÆ®×’5¹¤BÃ0 Ã0 Ã0 Ã0 ÃUpÑ 2‰;Bž @\=’ƆÇáö<\ÿÓÝÎü9+$0 Ã0 Ã0 Ã0 Ã0|œŸA&EÆ>xú¸Í ‹îy¸)âœáæ ûu[!a†a†a†a†áJxW¹¶`v¹ rïÁÓ¯rÏãÛ^‹=Ã7‘d/$‘-% †a†a†a†a†KãÍ䯳‹f‡ ·=½çaœ¸†¬q:¤ÙO«=·²w>i*a0 Ã0 Ã0 Ã0 Ã0\¬Ç{I‘…±ßsÕ™ÍIäþ{Ɖ뛑×Ónöãvôþ³Þý°e_ ƒa†a†a†a†áÂdRdaìmd²{]™Réãn°¡ËfµÜ3waìÙó(ËCÏÈNtÀZÙ_š¤J Ã0 Ã0 Ã0 Ã0 ïÊ “M¹_Ñ 2)²¶u©¾»ïuY$ƒŒž'£>Fƒ´YgÉAÀc% †a†a†a†a†_ámAa~yÂ…cމKe«£Ý›?÷ÒÕ!Yü…þüy:TÂ`†a†a†a†axç¢4»3È IKe;Žö8[Ħ™F(¼= .UÚ!‚ì¼mé÷²Ÿ]K+`87ßíâ{Oœ½`Ó0À0¼;ƒÌÚ$Ýéò9‰ÿ£àsº|Nâÿ(û¼ŽÛoj¹Îö$Òç Ã'Áé¨f½¨' Ÿ3 Ã0¼1ƒLrÆn\Júø’A&qGÈS|TÙÅ ´ôƒ¨ƒA–VLšŠ' oûuœAv‹\?WºøÞ¶ôjûœaÞ˜A†¤Ï°)5Šï›Ž¶'‘>g>!žvëÖ‹º³êúás†aþÐøÕ#aìmdÓÇÎ]û¸UhD´ÛëiE?¼–¾² ÃÛ2Ès­†FqåÚËK"}ÎuÂÃÞ]Ñ]$ÎNziú1JØzy–M©8ƒlfO·÷:WHŠ ÏV“lŃ¡ÊàÈ8»;xݽ¨ö*ƒ¼>ú½Ø‚ݱ×úow¦›«øÍI¤Ê†aøƒàW'÷}2ȧ¹ cŸð£ C*ÞŒÕne¯q’^bñeͧƒ =ÏÖŸ“m¿(ò\wî‘Ažâ£šd׸­x4gè1/o\ÿ⚃£Koõ¾7 .±[Ë Ï³ßЛ 2ü¼×Œ?ªÜáÙÎUg…§á<>Ãì¼1ê¯>íÍÏÉî_Ãá¹ß7>P ›g/õö>ä)*ÀÍdG‘e“HÕв½-Túê&j’ª8tå euÑV˜^` [Ï Ï²5gáŽKg-‰LŠ ÏV“À0 _Þ'ƒ¼ô±Tyò*kÖ÷“FF¹K;kVM‡5.ž£¨eØ 1ƒ×ÏÉÛþ øU».+0éE®ƒò*Æ;Ójh[¹À½æ¦N‘ÎUgŽûѧÚiºì?¼r‚áG*a›'„<¯¦Ôz¹M"Õ$¯k•èóïŒÕ$‡Áƒ¨06C­2½À¶Ê “¸#äyµ†ÞfãÑ2‰L¶uŠÔ&a¾x\.ƒÜ8l»®écÁ ò >ªqc4ãæÙI|^pZ³âÙ‰z@öúšÌ‡Á½è{Û¹àH«7\Ï´ÚœA®árI¤sÕ{⬊mE³öšª¡ƒàN<£7úx%lŸ òÔM©U™¼Œ].‰T“¼~ÎX3ñ2©Iƒ;Q1ì.¶„M»q/êëól mÈ x´©S¤%k`†?.šAî¶]×ô17ƒ<·Ï9{Ýtýãét_wz;ãâ™VÇyqÒÒd> nEßÛá%×a;¥9›~Ck䜟D:W½ÿxÉxÈ[öñŒRÕPUºÁ4£ nÒÿx%¬\ù>M©Q'nf7U¶®I‘®ŸŒ­7¾¿¢&9­ ixL;—[Â6Oy^­¡õ roK"GÚ$0 Ãó3ȤÈÂØuLwdgÿ9‡KàfÜ Õ>ÓËîe¢2×îi2‡/%`Ñ|»n]p¶Gyò~C¯˜öv^³OW©|ôU¶dÍ9á^ÔW©ÛT ÇcÛ[ÝZŠfïÚ”Šc—{¼D—­¦šäõs7Ò«IƒûQÈvëÒKØ>ä©k’a<Ž®µíú17‰Ô&a¾0¼+ƒ\y½gÛ³RÃõ´¸n—ý¡[açíêBÝì’!ŸÛËnGYK¿§É|ܾžÝÑÅ×a¥2Èwê7t]½k¶œ«ÎÖ{Õ ›ª¡ÃàvÔ´>j ËÏ ÏàFîâD“–yNÂç¯úx«†®W÷CÈn9Íï#ªIÛQ9¸øV.ƒ|Ÿšd£ ­·ÝµG+ê ÜèDöµI`†/ oÎ ×G^ç.a\÷ôqÛ5þœ‡av4T;Ì44>‹Iæâ¶Òbtêh¤É|ÜŒ2Èqÿâë°‚äû^¹wóû>nxîÇuý†Î¢Ž-éã¡p¸È¬®J§ÓZÂveu_ý/î>Y4ƒüÕPÜžnÔ$­ehµlʧƒK/aE3Èw­ †{ôaYïEj“À0 _^Ï ¼®ùÈ®¨?zÕý÷÷xÙýAÔ¬èô4™‚£õÄùz|ñuXnYß+÷xÉr¤Ý‘ÆKÆu¨¹k„{ñœ“]Â6guO÷É ?N5ÔiG­¡ÞXMrÜ‹ºÏu>Èd‚ùä9ÜŠ¾ ÷¢îDý)ZSm†áKïn9í^»ÞéãÆ òb?çìŒ=H£Þ&/=yfxÒ<åËÎ^KsÝÔô4™‚;ÑWµßü uØŽ ²öý†öÈ èŽ” MÖ{Õ UC­¨œ‡»x®g—‘>–Ë ?N5–l„vX¸Ã1êªI‚[Ñ(ìQÿc”°]dÝk’á¨|©AÃ0\üªÃû>d½NtÃø=·?ÄçZ)ív6³½m^TV{»  It§x’~:lcy!ý†JeNtÇÄÃxmƒ¦jè0x8©ìÌ”¦<•jEm’ü…±kÕËÏ ?Z54D­¡öXMr<Œ»«‡ÝQÂ6g—Ñ*—AjÐÀ0 ×oËãÇæžóÉž½7žÄï¹ý¡ IvB_,E_dŸödZ|Ï­’{îE¡Q·§É|ÜÛg“U‡5^gÕo¨`éDw|ÜŽïWõ›ª¡ƒànTÂÃÊi½xÎ3È$îyéc~ùA«¡V´¼U¤&9îFI\¯ù‘JØzyI­¡¢¤ ÃpMq‘ rýQãUgâGû£’Ivro â˜9»IŽÈx žf¿n‡;Ì…fñê®nL/–ìi2·£öÙ`ø¡ê°WßçKioÍ èNÐsü¥Âš—°,Š TCÁͨ„›ŠgRdaìÚŽAÙœA~ÐÏy ZÂ`5IœÈf4ä8ýPçªnÜ‹úú¢ZCù¤ Ãp­ñ¶ ²LÄ´ØsR|Óª8ZÍ´ú„ÀíÕóGŸp-ËËD×Aí°:ï4ž§+ûw;êÐ8,r_r glI„;«Ðx‘“¤íT‡½º›p)ííü Ò¹êT¸ŸF%¬ÓR ®×#˜ë‘âÙØ/ƒ¬Iw§õ òCÎý¨ùÔ«I‚q?Àpr=ý@%lÚ{Q__TkhW©AÃ0|x[iÞÇTHÆaá˜øâ;t_f/ù»hî„Î’Ý{îDK…E µ·+ãÞ8*ÛX¶_UY—Õohcé\u2*ÀV” Zª¡ƒàNT¶{ãK,aÓìÞæ`ã™q.—AÖª¶Ê “" cŸóçܬ‚Ç/A–µÊXMrÜéE%¬?øx'ºü…±k[“lÎ 5h`†/çguœbdøqç}¬ïtߌWíçÆúú¦ëªÁêȇÙ'G-MæƒàÖ(*Û£F‹ç4 H ½¡JÌ9¾GY—~Ck¤sUyܯº`—ë3/uÜj†z+U UÅÓU¦“Á%ÏIüím-{Ô.WXߊ‹f5l‡Í3È$îYÛϹ“}0½ì¦jÚ+‰Çýõ›·j’êx´l¼”°i·Î5ɤÌ+)²0vÍk’õ Rk†aøÂð® ²ÆG=ð>ð¨ňÛ¡e¾¹ÿ¼k÷5™‚‡‹d=\̇cÞªq ›Fß­¬œ…õ-sz×–Ë ëÕoè:êÕÑlª†öÀí¸T ‹å‘/¸¥ݦjè ¸}cçSr\jñŒã€WI´®QÚ)ŸAÖ·–¿0vM>çxþåpç¯òÈ"¸áîXMrÜïÅ+Œ×¿ŸA(IÍ0ú(4îFEnä–Ê kU“¬2ȤÈÂØZC0 ÃuÃñ£Òì‹çµ`ö¤|©¼zîM9—`ïMýž&óaðÛk™Z—°éhs¹ âƒPÂÒ·ï³¹~9xÚ&ó®>ãUû ]dz;5UC{à¸ê‰›óÈ,ã¢åcØR ·ãd}p¹³Gl®ÏÖWÂËRî^gveu_ævŸ ò,?çvg˹*{WËUáÞöÃk­>óŪ|#5Éap;J߆Ú×$éðÍ«óúŒ•Yû‚zQã?ûdZC0 ÃçóšÌ¥ç‰Û>çRx-d]ìhgGxš5–¦×@–ƒf´·«ãfœ j_<Óv‘–•ž0ÜtZ,ƒnmÐì‰wW:Ç¿wÓë½Ið'«»vÍþëd{ön‚´²ÆJèÑÆÖ·£¹>ÃRåá.ÃâŽÃdy2H–c}¶æÛU+-Üñö–·B^BÓpG&ÌŽ;n­n$£y± •°v`ÙŽ&éö ²î­¡}2HWt0 Ã0\[:©LB“y°lb%¡»Á¬–ØÖY2^S¶¼ôq÷ ûBÑe~«û¸Ò{îD­±Ðˆ^ôØi¯:ƒ„H¯ºx-úç VýsZýUP: 4B'n/G§i2¿}©ßÐõYíËÇ¡ÔY¤…2ƒJøø™A+/WߨæKâ¶<“„ÓF+ûÉbÙ­W½áâÌ ³ªÃjÛqŸ¸nØsíé…;’(9H£ä ûÉ ûÉ0œè†Ù†!È^öh¸ºå2n¯ç“—Ÿ,ž¡½š¦“¨xæ/Œ}Àôq+.—A&EÆ~‹Ý]51ÒA|³+; ‹Á!WEÇvººñz)Žâ'ÃGµè׆G‡›`½èŽô0º6;N6¢ÒÊVöç½.[Ñó²5ÉâºXvO™>æà}2ȳFÒê9Wm¼ƒq})éãÛ rqçÝ Ã0 _<Îz‹>qaìâÒ \ôV·vð´WcÊ^zÉ"}ܼM²ß5ûŽ~C•ð¾õp…š»Õ»XÁteÓU{Ñ… ƒU~ÙFuèé¸è*0Ž.õà ¸L„.“« ÔÜ—Ýj®®4Óµ~§n2¯.пç¢c±ÕaÛgn+Ò»6žr•§vë”éc~­r\|ÌÌ`1 µµÊ`Ò‹/žéÎ;¡'ÏøÍ·:mÅÃy»µ¯Ãr2Èz~Ϋ±!›ÏUÍåý¿Ù)4û÷ -Ûã÷úJæ´ Šþ‰½ñ¡ßó°»~ÿ1¼ÆÅŽé2Ù~ùV½J¶›«{ëan‡q4÷и³ºË0 áx¸ý°ß‘µ}†Íõ|ûÕ¬ÝåäåöG¸;fD·Š§«†óâ~qs¿F\ûuù®½¨¼çá›®¡Ã¶Ö Ã0 _ ^Ä;ýÊ‘Vç(íí¢mßKêtÔïgÿóš…äd8Yö°H^Fùô¢þ9ýUt< Mó°8k¸©Õ½sñlléÕf× cš^-ùª±>:ù ûã´·‹fê°’d²)wŒÉnGiA¿uúos…q |ÌÌ ½¼n÷ƒÏ7#3‹¶×ËÜëè2waìcu:Úö8Øž7g5üœƒäߦ?!Xš6ÖA+Êiúã÷Jß½)uà÷Ü2È0cÆÅÔ$“I‘öv˜Êf²º-½š2)²0öq{Q­= îùm"ßiSk†a†/÷;û¥íe€d½Ç¨ÅôÚ'ƒ<Ö4Ií¨6]bñlÄ=6¦«¾×ÛÖ’j¾Y²æ´Ã…öiií7´#ƒT‡•Ì “í¹ã«…Œ£µ2ÂÔï×ciÏÌàøCiÜŒöXú¸žA&Ë%½Â{FÃÖ›«þöZC0 Ã0\'< ‹ó½i“„µˆûÃÍK;àA4ùQ»þ­ÞEƒæp‰—=D­«0:¹­l—Î kxåþjPí>¤BRè¹×‹¾ÏÝÖÉ«¡ËÄñØö0%‡âYïÊ ë›>æ/Œ}yŸs7j,u'j’ƒà~8µ;j’Æ~ä!{QoëK}àšd8Š{Q¿™!^#=L›:";ÝÀ0 Ãð¹â4¬ÁFʽ:—‡¹wBï•hn¾N<_vÀÓ삳åAýþ9·zÃÛÇÑqé—‚_Lo§l—É kÜohÇ¢4ê°CàAT‡…ǰuÂjè’q;Ê mų ÞœAÖ=}Ü'ƒ¬ñçÞ\uó0tâR“TÆí¨}:l¨IJgõ­IÖc¯Õ›¡Û}Ô ¢?qºa¾ ¶¤½褜Û©âYøŽàZyéc¹ ²îŸó0ª·[5ÉapsÙê|i{¦C5Iñ ²î5Éî òÕR>q!;ÝÀ0 ל°ÔœiGÅáþsßç¼vÙ`è¼9`&v ï9´ BÁ½ã?¤½]†QÙn†ö¶d½Py!ý†JeÎUåq':½–jè ¸µBoHÅs 2)²0v­¦žÈÏ /ãsîD9ro¬&9îu£/Fg¬&)žA^Fk¨Hyý2 ÈÚT¬éD!a®-~“Av§¯Ÿ“·?*þ| îÄ3àôÛª¡"äEõ*˜A:W•ÇéxÕí;ô›ª†ƒãŬf(ŸA&qGÈ‹Hó3ÈËøœ r8'eͪQWMrÜêF_ŒÑ@MR$ƒ¼¤ÖPÑ 2YNÙŽ.J:éê*Öé†a¸f8]öÎñ\5Z‘ñózyáóJu^šÁËÜ·",&w=®¼çqt¢oV=-µ·«àÅÑèK7m¨†vgI£ÀÂØõê7”›A:Wí=^2ÊCÚmÕÐAðptCf*ž%ÃñÜ…±k»ìÖæ ò¢&+ŠÆƒ´Çj’ƒàá«A;aôMOM²;ƒLŠ,Œ]«š$?ƒ\¿!Ð\5œwÄÚ Ãp ñÆ òÜÎUqÙZ„YO"/ö£ÊZ a®F¼Z]xÏýì×׃î¹å$ݾ&óap¿ð¸“_‡5ß\ \N¿¡¤sU5ÜŽÒ‚~[5tÜM£KànWñÜï“AÖ¤»ÓzyyŸs+:o÷'j’ÃànÔ»/̘¡&ÙžA&qGÈ j íÊ “Ýs>¿<²k£©¦ Ãp½ðZyžçª7døù*‰L%'Š<ÿ*;‡ »ãÑámvÃ-äéô{-Ãa”ïö4™ƒÛèÝ4R í¹ c×·ßÐÆ Ò¹ªž× LÙ§ªŒ›ñD\ã–â¹ÿpÞ‚d­[®2ȤÈÂØµúœ'ÑŠ¼(üP“TÂÙeG³·:´c5É.œ¿0vmk’ÍdÁÖ‹n9†×]§†ášà¸‡Ã¢5p~çª-äoîYßVoöÛQß‚ðhgÍIûØ/{5wZMæáðyvWe8í¨†vá=2ȺôZË «ûQZÐi©†‚qúæ¸)ž{à¢d §zŃj÷É ÏøsŽ2ŽÅŠ)j’êxð&R»žªIvà}2ÈšÔ$ëd¹–ÅØ­qtÛÓO†a¸&8}³òž«6fk¸\yfÕ4»·Þm¯çŽ¡䨵l¥âewÑ™¾&óap/*îj(—Ê ëÕo(^E*al…$gÙX+*0ƒ¶jè0¸ ”è™=bœŸAÖw¡‰ü…±ëø9WíÉE­2V“w¢H­?R“äwò/•AÖª&YeIÙ Š^ŽÎbÁ¯h$ÄÈ2†áóÇoÆ>ÃsÕZ¹ç'‘ç38+ÜgÍ÷øv{öÍåÀ‚®w^EHB³×5jk2Ç3JZª¡|\0ƒ¬c¿¡ëxv§¦sÕAzŽÇñÎúúYª¡=ðd=ƒ™ Ͻñ® ²îËÜî“Ažýç<î¾¹¬&©ŽG«6nxL{j’üN 3ÈÖ$ó 2‰;Bî¿]|V÷«`†Ïï‘Ažü\ß)[Lˆ˜îznwkg£sY²f¼:W6;ë½;{ÙKM»ïUHÑhÆv_“ù0x8ˆEÙ¿¯Ûª¡|œ›AÖ¸ßPîÂØÎU%p/ªî»-ÕÐap?j„99Ï*7ø6fuO÷É kò9w£ñ ݉šä0¸ÕÕ펚¤ ÎÏ ë[“ »Pc|íÖ°W]J ÃðÙáRä;«FoŒ—{$Ë~}ïw´Ã]õ¸7\cÕݰ1IÏ¡´›Ñë4™‚»£××2ª¡bxGYû~C{d ɦçþz¯š×•~¥3üò˜»¶*^Ï /#},—AÖås§ž¾Êà¸xØT“Ä»2Ⱥ×$ûd»&½ÈþD3êOÑŸ(a0 Ãç;—V~ù¾çªQ~ßÇ ÏÓ¸5Ô>ýÑžfûìôÖp«» "ΣLÛošÝîª3@Ñç¤,ø¸5ÇCÕPRêBp-ƒ¼~C¥2H…dûúYÒÇcã¬xNϪx•A&ËÔ¼;-ÿœìÇŽŒ›yd­>ªaª282ÎÚD©ÖPQ¼9ƒ¼ŒÖP¹ ²à›4WW}áy¬„Á0 ŸÎÍ k|¢‹æ(.—Aî}´çͪd¹–K£½5 BÇá¹’~O“ù¸¸æÈž¨†{d¡ßPé›/Ïç†ûÅ2H…†/§­q¢[Ï ®Š×3ÈKêE]4ƒÜãh÷ã» aR×t¢„Á0 Ÿ Þ‘AÖþD·G¹ÏÑÎ…Aè×H×ïö†ÕDóO}ïZH¤…ýëòÏÉ~ì£áQªjì—A^ö•{Ó€4þ8ûºöxNöc …††ã¥„Á0 Ã0 Ã0 ×cŸVÔŸ$¾2zt²Ó–BÃ0 Ã0 Ã0üaq?šškÞ32Yv“tÀ`†…×3ÈSˆo ¼¹;æ>{~³¶õ¸£À0 Ã0 Ã0 ÃåLíIt!Ú ¿H0†áãàÕãtéã¼¹;æþ{^[Ûç Ã0 Ã0 Ã0 ¿ÆiÖc¥Ù\]>; Ãðqð"}<\IJécþFûì97ƒTH`†a†a†áFc-SÓÈV ˜60†áƒãC÷@,˜A¹×åŽ R!a†a†a†_?‡UKã5Ê~ÞuÀ`xËó4[U¾Óy,•{À—†sJØ>äâj'Y²fc©&a†a†aø¼q:z錷ó9)²Ñ)ð¤y)U–8¶¢ë×J*ž0¼|κ ŠNcI\ ƒLv/JS0Ü3ºÜ vý¶\t¹–AªI`†a†a®žvëv!ÚY]‚]ÀG5mEùjxÏ£±â t<Í:wµûo*ƒnv×$;`oÎ “¼MKô@Ü3ºÜ¶0öáÒǵ 2iì\”F ƒa†a†aøŒð« 2ûI7]>'ñ|ž.Ÿ“ø?Ê>¯áÎôÍÅ\{YÃjØB–°dMÚP<ᆇQß‹B–fVŒ;¼9ƒLŠmz¸ ð½ñ0¾G×VH`†a†a®Ž3Èæõ™^” ã¾%ÓíIdÝ?ª8n‡Ž^ce¾|<É‚ÇV¼XS+ýðån:`ðæ`1)W^Bú¸À¹ c+$0 Ã0 Ã0 Ÿßǵ ò,/Êâ 2Œ]î¬%‘I‘áÙgÿQ¥YÓŒ’˜þTÙ†/gÝûÍUвø†÷2æ.Œ­À0 Ã0 Ã0|¦x•A&qGÈóº({›AŽGË$2ÙÖ)²¶Õ$º® Ï“†² _N³ô±åŽa–×þ à¾çàøQ.ƒ¬}ú¸G©„Á0 Ã0 Ã0|tœ¿ÞÌZ’}2ÈS\”mÈ x´©SäE,YÓÞTè9ï%©lÃ0òº•íìßS .…÷É /$},•A*a0 Ã0 Ã0 Ÿ—^óº\yº‹²õ r—J"ëò9go­=‰>ªNøEªlõÆqÙ8`py\.ƒLâŽuO f Ã0 Ã0 Ã'Å›×›Y»ºNÊg§¾([eIܲlYÃÏ9 ï9,•ÃÎ{½ìþ¤Qâ‘4*<>(nf‹A_.¼[eI!ÕÛpI\4ƒ\ûJ^Bú˜›A*$0 Ã0 Ã0 ¿.´æu¹ ò}.ʆãxÀxöܾyNWÏ­¨£Õ|ª¹º/Y3ŠÏ2›ió¤/;]vA ÷>F×I?zÏûd*ýó3Èd÷¢4õMwd Ã0 Ã0 Ãï† ­y]4ƒ|׋²x0öžñN«þñN¯·z_­ÐW®{š=O¢~˜ÍlŸ£ìpŽ®_?'oTüùÃá0¿gth“ñǨÃÖc«·á’xW™ì^”¦îéãÆ R!a†a†aøq¡5¯ó3È3¸( ý7ô}ÜÒrþ<Ÿ@1B»iý?çî*}\ô›ëfϽÎjŸÝ¶ñ08^v¨5üHuØ>¤JÎÍ s‡m_Bú¸–A& c+a0 Ã0 Ã0 WÇýìZ≯á¹Q`Íë]dÝ׎Êgç?Â> ‰¬ÞÚh|Ä=‡´(ê‡:l ƒÛQ9è~¤:¬\©Ò‡s3Ȃö/!}|É “¸#¤BÃ0 Ã0 Ãð±qœb¬? ®y½9ƒ¬{ú¸OY«B2ìÄ}\³ñ¼iã{Ұ#@<=”CWðû¤:¬h©Ò‡sƒÅRö/!}Gï“A*a0 Ã0 Ã0 ï‡ã 2Œ—„©¡ÙEI/-ŸA^FúX.ƒ¬c!YŒ6.²Ûa2ÁñA÷ÜySˆÕq/:ªÆÇ«Ãò3H•>œ,&qGȲdíOt{dJ Ã0 Ã0 ÃUð«Ñœé^k^¯¶IŠ,Œ]«ÑlùdÝ Iš}zÍèsg:Z]݆çQC€xÜŠ¾·ÃéÇ«Ãve*}¸Žå2È ¹ÍV*ƒTÂ`†a†a®ŽWdBÈý2ÈÜI#k:“ÿ® ò¢†¶6ÖãÂI£òž‡­è·#@< ^¬ðÃ+ 5>^¶9ƒTéÃÅñ>dòvé²ÏkËž%¹«¢íx>žË •0†a†a†…ÛÓ(@Ü'ƒLŠ•5Ésy©…$^f9ôŒ ½$÷Í·{Ñ•{¿#@<îFR·ÿQë°õ R¥—Åå2ȤQáqþ¸­À0 Ã0 Ã0|¼>{5¯÷É k2šm=ƒ¼ðB’½çv´„ugÓh£¬À B¤¸eðt_gÇp4 7£/ì¸óQë°U™Y[¥ïaƒC}¶Ïs]pS!a†a†aøxŸ rI#k:“ÿ*ƒLŠ,Œ}…$,C4_)û¥MXC;Íž;ÍÕ§ÝO·t¨G¸³GHéã†çA¤JÎÍ 0†a†a†á£áü 2wÍëB“FÖ.}Ì_ûR É4¤×üG2^#Üë¬w“”>VÆýÉëÜWV2ƒtÀàÜ Òƒa†a†a>2Þ•A\óºÐ¤‘µKßfaíÐVön;YÒËÆ‡å¤‡auÞq¶Ñ$;’iè&˜Ö¦ô›«d±èc†§íUÇÉFtÀ†¹£°¥…žÛqwäAOV<ƒTéù¤Ã0 Ã0 Ã0|¼9ƒ,µæu¡I# nÈüçWäî$në#ˌ ‰aÍénoø BOÓQ©L²­¦ÓU¤wÚBÒF/»Uø=² háÖIÓÇ·ìyóŸ;ytÙ]¡ùÑÎJLÚT‡É Uúpn™Ä!0†a†a†áãâõ r5¯ My”ôq^ÿEÅ=¿‹…láx»ËßÎp?…ÜÉ6jein³ŽÛ~Ñesõ'Ÿ :ì¦MW^Lxaé¸XßË…¤7Øü*BЭ/; îDE¥×y¯N„»2È=ö¼úsïÓq²7Wo\b5Ô\¡ëva¼+ƒTéÃEpüpÀ`†a†a†WdRdaìmdÇOwm´÷žwÍYôhgiÉ4;“,p™wzLBÈewÈÐ52t“lEÝ'ËG—‹89ûC­Õ'ÜÍ~ÒoGŸsè¸8É’­iöR;;W i„¶HÎöÓ‚Ê0dóôéã® rï=/Žöû ÛnE_Àá%.Š”Faâ|£y²R¡aù R¥ÇûdŽ6 Ã0 Ã0 Ãðþ¸w´Ú'ƒ,8iäÁ¦n\Å‹Iñ rï=oÎ OòQESJ†é%Ç!@†41{1aBÊ09eH«š{öºÌ}$›úG¾}´;ï•>nÎ ÷yýªïã®~•ÇME¯¹ ¤¯›X M¯·”°VȱòGÓ¼ R¥—Åå2H †a†a†a¸2Î_{[¼XjÒȃ-³H+Êu–Ü{Ïëd]>ç0:;ŒÔ^äaY88ã¹³Ï9,[:‘5§Š.û÷J÷<½µãäz yê%kº“8Ú]åËÍá*¡ Ó´³·Ã‚Ùì?¸ýnèc>óìß½¬HôÃZJٿٿaVakUèGÙ¿G¡ eÿgÿ“–N²Oæá[•f/r1@U=.Aö ”°ðÇÃMdRdal•>¼cQ †a†a†aø$xŸ rI#·f€ñ£Dt¹ ,}\Ï “·ƒ±/©„ñ¯­âéc˜œ°¿þ“Y½ßŠ‹—}°aÛå2ÈC¾ç]±ðqû¸‡Rºéf…¤™ý{¾pQ²\¿¨ø#—Î0Úó>¤3ƇÇù¤Ã0 Ã0 Ã0|P\.ƒLŠ,Œ]*,šA&EÆ>x¯ËŪ3«ŽZHÒœ`)ëÖÖ¬úÇõß&MïÖ÷qC÷Ń Û.úçùžñ÷)$$Ù1OÃðül\ö4û÷4,˜ÆêO²_ŒÃw8ë;Ê lÎ&“fÿdÿ„Ùèþ~ö‹^áŸý»æÍþÝ ¹_öïvöêÚhºÊV”,†”1$ŽÎirÏrd©/ÆzNµñeÁ‹—}½eèþ«Ø{•­xÛŸ{—½ùÕ%Å^ðžŸó®?§eÃ0 Ã0 Ã0|\4ƒLŠ,Œ½cÒÈý2ÀwÇ»¥¹ B2é¾¹ìoeÁÎ {N³0)ľ­Öæ8bi½_úX¶ãâjËd¿u¶•¸¾ZaüJX4:;‡mOÇ«p´Ðc6ïí‘Aîýž7äaoìœ=ïÐvý<ÙoŸ¹øü^vNîYâhï“/kÀ0 Ã0 Ã0 çg¹k^š4²vécþÂØTHÆ!ÞéeaÎ$Št¦Y‡ÇNog6zãÒ÷M÷<½ ÄS¥£ðMŠö?™\z54ÞY¶š! %,ݱ(Íq_vÑÄoÇž÷쾸Ï>+âJ/»Ðøçïy[7ÍãôqÕ2€a†a†a>&Þ•A\óºÐ¤‘µK÷É /¤dï6,\ÒèæuN›Èm¿WúXüQ(º| 6ÿ‰cõ÷ìGߤÖècTC£õy­Þê›wÝß‚‹f‡yÙûdI™ôíйçBÓ=_ö¶aÛù}/“b‰c¡—].ƒÔ2€a†a†a> ÞœA–ZóºÐ¤‘µKËe—QHB¯ÇFaqåÞˆrÊ÷ëûx1¸}“ýQ z«1ä‘×Ó8?ƒ<äË.éí=xúp¹çBÓ£¼ìÒEór¬öš0 Ã0 Ã0 ÇÆëäk^š4²vécÑ ò{¦e‹d7{ÒÇFÔeRúX‡7ólÂôõAª¡ýºµíÊ ÿ²wwâËI+Mc˜¿Ï½ñq^v¹ r‘×…^v‰ž¦ûdš0 Ã0 Ã0 ÃûàU™Y{[™;idíÒÇü ò² Iš}òÝîÎôq‘]÷¤q/úž…EWÔa{dÇÚsœS½}Š.·= ½ìͬ"^|Ÿò²w±{ÞµéF|€î‹ûd¾’0 Ã0 Ã0 Ãûãy™Ä!÷XóºHPY»ôqWùq I7ލýÍiA8HÒÇ ¸}…†©:¬tyÜ=ïÊ©ê{´ãÕ—Ë }%a†a†a†+ãü…±·Å‹¥&¬]ú¸9ƒü8…dÜÓÇì0ôßÏ£°'Òǽñ¢„e}‹Xšê°âdRdaìŠ{ÞœSÕýhï“A^R +šAjVÀ0 Ã0 Ã0 ï“Aî1idíÒÇõ 2)²0öe’,k¾ê ›½óvgõ9w³Ø§5–>VÄÝx6ÕîPV<ƒLâŽGM×µ:`¯^v¹¾—]Âò…f Ã0 Ã0 ÃðAq¹ 2)²0öE¤« 2‰;B~€BÒÆñNÖßlÚŽ.×CîÆ_§ÒÇŠ¸Ϧ:ŸªÃ àü…±0¸p¾ì€Á0 Ã0 Ã0 ŸÍ “" cï˜4²néãr®ËÜ…±/©sÙ¢¯TÜ[¥ýè(tºăàÁ8^Ë)$!cuXA¼O©Ò‡s3H †a†a†aøh8?ƒÌ]óºÐ¤‘µKóƾ¤BÒ £Í£e°aVÂéêS]ü¼+@< îŒWGµßP‡•Âå2H ÎÍ 0†a†a†á#ã]dÁ5¯ MY»ôqŸ ²¾…¤ß}ó>³¹ ÇÑÕz3ë¹>þZú¸ߘèØN¦ê°R¸hé€ÁE&ÊtÀ`†a†a†7g¥Ö¼.4idíÒÇrd'Ö ï°½z?YLÙZ½ÿnW€xܾ1­±jhœŸA:`pn™Ä!0†a†a†áãâõ r5¯_M:wu§åŸ“ýØ:NË?'ÛÝ™æe5.$ÃÕ» ~¼&JÖë±e°ÃŽñ0¸ÂôUC{à]¤ÁñÃa†a†a>>^eI‘…±·ekWtå5ÁëdÝ I˜ñqñÞº«Ü1üv4ˆ~Û ‡1ï!ßÍŽÚR í7g\ï“A:Ú0 Ã0 Ã0 Ãûãö4JâöÉ _¦·;pÄããN½·, ±Û¶çaïR IXí:NÂ&o.ÄãSz]âap/:ªéãþx=ƒtÀಸ\é€Á0 Ã0 Ã0 WÆù coË k¿æõx{Ç‹-$ÙçÙŽœÞp¤ÃìÔ¬›jíðP5´?^eI‘…±0xÇ¢4 Ã0 Ã0 ÃðIð>ä…¬y]*ƒ¼ŒB2ˆ>ífxÏÍu6l ŒÃª?-ÕÐÞxžA&qGH .‰ó3H †a†a†aø ¸\iÍëº~ÎÓÉ*ý q×®+Î_Ûƒwn´+ƒtÀ`†a†a†€‹f—Ý3íâÖ¼ŽVøŽV éN}1àzã}2HGÎÍ 0†a†a†á£áü Òš×õþœ‡Ã¨/k–ܤ_ ¸Þ¸\é€Á¹¤Ã0 Ã0 Ã0|d¼+ƒ¬ûÈëV4òxÒýxŸsÖ•‰.¸G#_ øpÑ Òƒs3H †a†a†aø$xsyó>–Ë /ïsîD³yv¾ðåàü Òƒs3È$îé€Á0 Ã0 Ã0 ¯g—´êLÑ òò>çQwõΛÙLiϾ¼+ƒtÀà"8~8`0 Ã0 Ã0 ÃÇÇ« 2Ù4!dMÓÇ¢äå}Îiöž›Õ;N}1àKÛ3H .Ž÷É m†a†a†áýñ<ƒ|éB»pI_ô9) N‡Óíä¥~ÎÝÁê=wÂ{N}1àKÃ뤗Åå2H †a†a†a¸2Žc—{ÔjÁìUy©Ÿó¸¿Ý,‚õÅ€/¯2ȤÈÂØ¼cQ †a†a†aø$8„sãv™ç¤,xœ¦—û9§Ùss¼º¢6•mø’ñ<ƒLâŽ\çg Ã0 Ã0 Ã0 ÇϽhöÇv–D^O0ø¢q<û‚ûoçÁ¾U0 Ã0 Ã0 Ã0¼ëyœ¹n„QØYg°i߃?Bÿí=2HIœ›AúJÂ0 Ã0 Ã0 Ãð«ç¬ïc«µºŠt0†a†a†a†a†…ã^`ífÀc †a†a†a†a†áÊxÒ ÁcöÜ s㥠Ã0 Ã0 Ã0 Ã0 ÃÕq6ãck´ìÿ8Ãý¡Ã0 Ã0 Ã0 Ã0 Ãðp¥­,¼î;`0 Ã0 Ã0 Ã0 Ã0 WÆÓ=†UgÙB4“ŽÃ0 Ã0 Ã0 Ã0 Ãpuœ-4Ón‡ô1{ô¦ Ã0 Ã0 Ã0 Ã0 ÃA”>f ×m †a†a†a†a†áÊx: éc6ïc£90†a†a†a†a†«ãi†ÛÓÆË£×tÀ`†a†a†a†a>vVécs8NS †a†a†a†a†áê8 ÁcÔr$}„a†a†a†a†aø`¸Ó_¥Ý®Ã0 Ã0 Ã0 Ã0 Ãð$[¶¹]þ9)¶iX¤eý9Ùö‹¼çù2Ógp´G«ð±ÑÌa:PÂ`†a†a†a†ax ¥I£Â£*nf£ÓÞ{°4ëûØl­^Ô¨¥„Á0 Ã0 Ã0 Ã0 ÃðVg­ñü¹;Ýþœìþõ‘p»ù&ºl Ê$‘‡<`ÝöêUtFJ Ã0 Ã0 Ã0 Ã0 çà8ƒìf]üÆãMÏɶ_y®Š{Qî×,•Dò€&Ñ®CoÌ–Ã0 Ã0 Ã0 Ã0 Ã98?ƒ|×ô1üGœAv³Ü¯ÕÊK"yÀÒ¬;f3:TÞÃ0 Ã0 Ã0 Ã0 Ã…ð® ò ÒÇ dö‚GÓ-Idÿ¬{½ÚO;ünË ÃÏדÈ$Ž"r´Çñ’=ÃùÓt¤„Á0 Ã0 Ã0 Ã0 ÃðrqÔ}¯È£Û?»ôqw¹J"“m"÷?ÚÙŸkF‡p }„a†a†a†a†áµi ã 2L£Ø]nv¢N„»¥yŸô1?ƒL¶uŠ,’Dî8Ú½ñêµ³Cº•*a0 Ã0 Ã0 Ã0 Ã0¼9ƒœl‰÷:^u„<¯ôñmÙÊÞH7 ¡iºü—çì-4£Õ³›é¦$rÇÑž´V¡m#[{fÚRÂ`†a†a†a†ax¯ 2 !ä~äé†mÇä¢ËfÙGTähgï¿ÕXª„Á0 Ã0 Ã0 Ã0 Ãð^dw„,›AžzÒÈÁõî¾[žÛQoÈþ°Àë÷×û[^•0†a†a†a†a.™A&ocÏ ÏrÉš­Ý'ã³ûÃ]‡*,ÞÇ"ëu9(a0 Ã0 Ã0 Ã0 Ã0\2ƒL¶MY$ƒ¬Uú¸Ê “¸#äÆC• ÒnE‡ªßRÂ`†a†a†a†a¸d™4v.J³;ƒ¬aú¸œë2Z${[9ˆ×»Éþ}ÝUÂ`†a†a†a†a¸p™Ä!ËfõM×coÊ §Ýð‹ì9›:rœ*a0 Ã0 Ã0 Ã0 Ã0\ç/Œ½-ƒ¬{ú˜“AfÇ¢=\ý¶×SÂ`†a†a†a†a¸<Þ'ƒ¼Œôqw9ˆŽK3L”~¢„Á0 Ã0 Ã0 Ã0 Ãp)\.ƒLŠ,Œ]«%kÞfÓiöãè=ÛJ Ã0 Ã0 Ã0 Ã0 fIÜr{¤÷ö±g€X¯ïgèòmÙiljëH!a†a†a†a†áJ8?ƒLŠ,Œ½-!Ü»ûb ¼9ƒ,ˆã ²3ŠöÜÌ–£IÇ Ã0 Ã0 Ã0 Ã0 W»2ȤÈÂØ;z îê xÀ‘×ë»)…ã ²1ˆ^ö¨¯À0 Ã0 Ã0 Ã0 Ãððæ 2)²0vn€X6ƒ\ô@Œ¥‡m¿}Í _p'UH`†a†a†a†aø`x=ƒLŠ,Œ]°ûb¹ roü*@,:T{ùÜÆÑå ;$…†a†a†a†a††WdÒ(°0ö¶ 2)ŸþÙtó6ÉëÁØÝBÃ0 Ã0 Ã0 Ã0 ÃÆéuÜp 2)›ûï“A&ÛÆVH`†a†a†a†aø8aìmd²_ßÃÃãrd²}Qšü R ƒa†a†a†a†á²xŸ 2ÙoÁêRËV—Àñ£DúX.ƒTÂ`†a†a†a†ax?\.ƒL¶/J“ÿÈ]8¦4~›>¾}ääžù¤BÃ0 Ã0 Ã0 Ã0 ÃUpÑ 2‰;B_íºTßÇ÷À½öö R!a†a†a†a†áê8?ƒLŠ,Œ]ÃôqW©À0 Ã0 Ã0 Ã0 Ãð¡ð® 2)²0vmÓÇͤBÃ0 Ã0 Ã0 Ã0 Çś3ȤÈÂØ5O×3ȤÈÂØJ Ã0 Ã0 Ã0 Ã0 —ÄëdRdaì‹HWdw„TH`†a†a†a†aø x•A& coË k˜>.çºÜ±(BÃ0 Ã0 Ã0 Ã0 ÕqzõÜ'ƒ¬oú˜¿0¶BÃ0 Ã0 Ã0 Ã0 ÃÕqþÂØÛ2Ⱥ§ûdJ Ã0 Ã0 Ã0 Ã0 —Åûd—‘>–Ë •0†a†a†a†aÞ—Ë “" c×jÉšü R!a†a†a†a†á*¸h™Ä!/"}ÌÏ †a†a†a†a®Žó3ȤÈÂØ5Lwe Ã0 Ã0 Ã0 Ã0  ïÊ “" c×6}ÜœA*$0 Ã0 Ã0 Ã0 Ã0|X¼9ƒLŠ,Œ]óôq=ƒLŠ,Œ­„Á0 Ã0 Ã0 Ã0 ÃpI¼žA&Eƾˆôq•A&qGH…†a†a†a†a†ŠWdÒ(°0ö¶ ²†éãr®ËÜ…±†a†a†a†a®€Óë¨`‘ ²•ý¤;]>'ñ”}>Ün–Ï •0†a†a†a†a.ŽóÆ~A®I£Âã,q~©„Á0 Ã0 Ã0 Ã0 ÃpY\$ƒÌ¢¹F7]>'ñ”}>!îGom”áAöïmÏã‰BÃ0 Ã0 Ã0 Ã0 ÇÆE2ÈšÎû8šF}›m…†a†a†a†a†ßÍ k¸êÌh¼Þ'ƒTH`†a†a†a†a¸:ÎÏ ë»æõª#dÙ R!a†a†a†a†áCáWd6ñã°·|Nâÿ(û|x0.ŸA*$0 Ã0 Ã0 Ã0 Ã0|Xü*ƒ|y\Þš×ù¤BÃ0 Ã0 Ã0 Ã0 ÃGÁ­ùs»½|Nâÿ(û|ƸÓRH`†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†a†?$þô>>Ý?¤É·ß}½¼š?5¯¦éuö¯«ïçO_îÿ˜>Ý'¿þ§äæîæiòyôðxóŸiÒ¸úÁÕcz÷ts—Þ^]ß?\=¥ß=]ýéfúôùjrÿåëóÓèéæþ.ùô8úczu—þéëhö›Æìÿ°Õ›ù—¿w5ûÏh4ÚWsõ·W“Ñíäû]4g»øúýÕãÓÃÍݧ°Ï¯÷_¯ÚW­«‡ûÛÛ«Ñtš¬ÞÚÓýÓmzw•~7ù<o/?XüOc¾yøÅÍÝ—Ñç›Ù¯žÓì8|{}s{ûŸéÃýÕÿüÕÿùùëlÃÛôúiö¿ÙAúöûï_ŽÕË‹½ùò)ûßOOWÉÕŸg»øËìyù×­ŸÇ³_Ü\§·á?²ñòID¯,|aG_Fße¯Žcv\¶“ç¯ÓÑSºx«ó×=û(ngÚäs:ùÃÕãçû?…=6®&ϳôëýÍÝSF_¿šÆ;—‹Ù‘æ°M‘Ò±í/Ü??Í^bn|٬ʾ¾¹ÏÝO¶I•}<ÎÈmš»Ÿ—Íªìk”»›QÅ=|}¸Ÿ>OòßÎj»Jïçnšÿ޲mªìåænV’þ>wG/›U;~éìÐLÒÇÇtZà ¾Ú¸Ê~Ÿ>çfa›JßÝ»üïí]å}Ü~_`/ÙFUö3M¿¦ŠßËf•JÅçÑcú˜_–›UúNÍJÓ—q)Ú°Êþþ*wGUq?Ôn ¼¡ÕvUö¦utN­£J=üöå®vÖ<åÎZ§ÜYû”;ëœrgÝSî¬wÊõO¹³Á)w6<é—ú´UÈIëæI+‘æIk‘æI«‘æIë‘æI+’fψ!7›ZmÐÊÛ ·A'oƒnÞ½¼ úy ò6æ¨üC™{,›¹³™{4›¹‡³™{<›¹´Ù—Yj•ŸafyÿüT I¬vEx=zøR Íy٬ʾÆù—¹ãªW¸“ûçÛü·³Üêüó½ÉýÝÓhV²¦ÿõï ¼«xÛ*{ý¯éíuîþ–[U:Šœ‡ª¥âiôø‡üˆj¹U•=ýþsú˜ÿŽ–[Érd9²YŽ,G–ãJö„W²®í\Ûm)/G:™ÿ¹¯£O³ýà¿ýï®zW½äÛlû]¿6¯¾<ß^uÖÞpöç_±acöiΊѪøüéáæ)ßJUÒÄ%$ùöóýÃÍ~}]ü±oÿ˜><Íÿ3d«×tó›Fö¸š>½zœ•¹4ù—_þì÷¿xù¤[Ù ¿ÌÆrÓù³Ò1º{¼½°äÛÿù“ßüì_¯¶¹fì²—´ýPüâç¿üÇ_üþõ®6¢Nãõ›~y“Mo²ñͰěìνӼÉÕ®rËAåªæõ!»šýg¨I~ùåëmúeö—3¿¬wŠn]¤Úö·®òvv•ÜdöVÓ‡s©æ–G¦H5^y¹Š®âß/{AR½érð²²Z—²Zä¤üºõ´:M´QÁnkªÍßS^s.lS-ñûò¥H¶¸Ú®ÊÞ~þÝèËì%çîmµÌJf%³:³ëv׳®gßµ\L¾~Í=aÍ7©röøççü.Úaç(ç¨s?Gà´á¬à¬ð®åâßþæ6=>ýpüüøýo?ÿÛßæ”M¢Ò¶ôav­˜?‚m¹Ùy`ûíÍìóÏÛÉb#ç@ç@×iïÕ· 7sµ´Þµ\Ì>˜çù=¨Çü.€/Vj Ü??LÒüž”«íê8^úŸÓÿxž}O~”±¼ÚPkAkAkAkAkA}r®­…ÛçɾÏ^6«rNûþþù¯ Mx٬ʾþíonò[,6ª4Ö§ÈD×Õg™¸ÿ{:)0 Òr³*ûú2k0>¥ùmºxËj÷ç§i‘±8ÓÊíÇô»›ü£¸Ø¨Z{ññëýÝcZ¤Á¸ÚR‹Q‹Q‹ÑØcWÎrìŠÑ$‡MâºÇuÏûö­¹½™ýÙÜçb«³Ÿ±Ø©Uç¸SºØ¨Ê~~öüåkî~i1k1k1ˆóe´¾´|´|ö%Û¿ê%k”ìyŽ’ýiÞÀlãa‡5VY5vûò£ôËý]nß­—Í*õÜz=äçË­Î^¿_ÞÍ^ël›¼=­¶“H¤zhé¡¥>9ÛZ÷³bñùþñé¯s;iE[VÊùoŸ Ì*6ª²ŸYIMóoŽ,·ªtGá—¿ûýOú~ñ›ßýþwÿí¯ tß$ªõ;úzÿP¤çÑb3---÷5Ü×P»i')?ü÷^^ÉÈ6©´²àOÿÛôæñi2É_[0Ú²R_ìÑòÛb‹´´´Ì"æ\ÿûýƒ«ûýî÷Ÿçýþ‡t>¡Pî=ÿ—ͪÜ÷Ÿ¥ÜÛ©a½ ô.Ø»t¬Ý]ÐDu¾;z;¸Íúÿžž¿ù曼¶k´a•«ÜßÝߎn lŽ6¬²¿xHÓŸüîgùû‹6¬²¿œ}H÷÷ù»[mWeo¿ÝMF(0r;Þ²Òçw3-ðÙ…*Ý/JÇ7£ü[S/›I^$/’ã¶k=nÛèf‰Äî,fpœ|¾yJ'Oϳ6ÇWŸ/Ýùm±‡ûmðhÃ*ûûÍï ìk±Q¥£7™½Øü±_6«²¯¹(°öör+­S­S­S­ÓC·N?HƒQ{P{ð]ËÅ4ýšÞMgï-·Å´Ú°Òœ–£Ç§ô!¿Ñ´Ú®ÊÞžn¾¤ùm™åVUöÔúf˜»Ÿ°M¥÷sŸÿfî+¿“VwÒªÜ÷lviqWhÐhË*{lçî©]õj ?ÕýDW›Y›Y›ÙLœfâ4§«W7Ç,ŸnoÆ“]@VÛUs:ç7gUÙÏÿû³Ÿçïg±Q¥£/ãQ>ËͪìëŸnîž¿Ëß×Ëf•z²üú7¿*p_6«¶¦Ôý|Õ„ÇXPjµe¥+«ûÇü±À‹ªìç'Ï7·Óü‹ë—Í\õ¸êqÕãªÇU«W=®zŒÊ{=*ox54*Ϩ¼ó•÷ÓÙö£Õ²¿¹›/g¼œÙx•UãÓ¶¯ÿóyt÷)Í]%h±U•ôäÇ?ùenS1lSiþš¿û»ü™k²m$A’ I¹d|ƒÝ«[}ì¿ÿéoóJF¶I¥»1·£›üNZË­ªìéߟ Ü…YlTé¬>ÔÛïóϽіÎÀÎÀÎÀæ¦77½úä\Ûß|óÍ¿ým^ÙXlTiÌh6°!½›Üé¾¾u•=ÿÛßüß?ýiþ._6«²¯‡tôx7ßæÏøújÓJsý˜é¿ê>¾ig}©ÞÎúÕèó>-0͈ZYZYZYz¼˜¹ÅÌ-ÚóWG³1ûý:ôë8Ï~¿¼K¯¯of3ÙMÞÍìõ­õòÐËC/eU/wO±Ÿž¯¯ÿ¾À‚ˋͪìëîþî‡?ÍÝÕr«j Ù¬Lüa护dѦ•æØ=˜ÿl¹U•=ýzv„¾ŽF··éíÍÊæ69“œIÎ$g2›9ØÔµõ»Óy3½Íí¶9ÄŒ[…'ܪز¸MGœ©ÜÝ­¶«4WÁìSŸ>ߦùÓD[j9i9i9饔úä\[³ß>|NGÓÿžW>¢ +¥éÓŸîþE¼lç,ê,zîgÑ:.Šè;ãLQj.ï›Ç§É¤ÈÒ'ó­*Íâ}Ÿ¶©²—å íªè™¯êXšßþüQ4Ù6ÎxÎx®]7ºnTŸ¸¿`söÿú ê/xžýŸgÅ)¯7Ôb£*½ŸFÃzr6Ò Q/Ľ›dÇÚÝž;zE¸Íú5}˜ý¹/£»IîïW›žÿ ´“ûÙç2™5 &^Û¸RÿÏù9·À,ó«í*­–¿B˜”DJ"%ù(ý/£« ÌFfó¾ëÝç.t_í¼ú§û‡üfÐb£J£(>çfÛTºõpÿ%ÿFTبÊ~ LWyƸY³ìi4¾¹½yÊŸËíõ¶•ÖBJó§O ÛhÍiÍiÍeb6³™héjéV+£ÇÇôËø6}ÈíÖoY-ÿ+ÿ  W¨ñVuUÉû‡Yû¯À¤¿Ñ†•Þ×}þ»º¯¸_Üÿ)w'a-Q-Q-Q-QãwV×Ö¯íwý|7™ËÇÜänµa•sþîîŸ „j/›UÙW:?¬ùÑçËfÕ2ÖQÖfبâæŸF_‹,a¾Ü°R?üü^øZZZZZZêÚZ¶g?˜æ°Í¹¯A1)-N*g‹ß?>¥a«íªõc¼[”Ÿ½£M«ìó¯rwõW÷0ûúp3~~Jó;A¼Þ¶Ê^çãŠÌ„´ÚNÛVÛVÛVÛ¶Ö÷Ú³³û»nì¯6h÷;a»ÿ!ß”~Ì_…n±Y¥Öÿs~«+lSe/ÏéõómîŽ^6«²¯ŸßMîŸFŸò/kâ-µ'µ'µ'ÍWb¾õÉç+iÍþß|%æ+9ÏùJæ3”æMS¶©2‹È?Ï>ž?ÌÞ^þ@÷xÛó©=Ÿ$ó±ÐTšUGºÿêþ!¿±³ØH‹@‹@‹@‹@‹@}ràq4³Ö6ŽÆ8šóGóÏó¹iîïV9T‘-«ŒsùñÝ÷¹ÝõÃ6FÓMc4Ñ4¾;µMS‡¶ëy2­×cÍ ùôôõGß~;Ÿ~o2ùæqôe<úæþáÓ·¹sEnu—žÚ|¬’Zñïë}®¬~ÀZõËøëÿóR'æö%x½±úSý©þTV?rýš•ÿÏíì¿)\‘nSjT5ªUYýÈ5ª²¡llûèÿá!M§÷¹£ƒ^6«´ÚØçû"+¶½læÜíÜ}’ž@µ¹Ý´©_Ãÿ5è—¥šdistcc-3.4/doc/web/distccmon-gnome-2003-09-23-01.png000066400000000000000000000433461404653710500212360ustar00rootroot00000000000000‰PNG  IHDRüꀧ²bKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÓ žÄ IDATxÚìÝ\Tu¾?ð×0 6‚†¿­,ƒˆbc5õJ¦ÞÐnx]••U÷>tÙ×È妶K¤Äê5SlÓVC¯@ú€ÔÌv#”$[™’€ ñÓq`~|ÿØušf˜Áá÷ëùxø9çsÎçœ÷çœ9ïó™óC ×é-M*צŸkîÞúâsáé?$ ÖÿxS"""pv<»ãá1Q"¡‹‹Ëøñãåm'P5©pKYЦ¦&xŽaƒ““ZZ[! !‰ ÕjÑÜÜ“Ü%î …Ü:ˆˆhP¨¯¯Çĉíšæûï¿7Œ{{ú™ÀE$v—V ³Ÿ´Z-®ßü·ªoÁÓÝ ?••¡¾¾"‘3”µ {H0l¨êêp³ô'œ˜2i |¼‡së «Ž?˜7o^‡Ÿc ¸Ü\g¢Þàïï£GúÄÄĨD$m 4Þi„²J ©ÇÅϵ¨ªªG}ã]T7kQ[ÓõÝV¨îÔB£iÞ CÙ­2&Ôo¿˜ïÍ{èС 5ÿüóÏQ[[Û­„ÁvÀ©ªªÂ7PWWN©TŠ1cÆ`ôèÑÜÐiPúâ‹/¬Ž ±iú¶å, oKÔáÎúsîÜ©Å8Ÿ‡àᢅóð{øâîO%— µéîh´ðôðÂP™ Õµ•:ñ'²__;ÖÔÔ ¡¡žžž¨¯¯7&y{Òwß}‡òòr<öØc˜>}:„B!êëëñÝwß¡²²Lˆî3©¸wàï,Áè4xhøCpqA$ÐáûŸ~†J C“ÞCd^Њ†¢FÔˆVuTêÜU7ÀIào¶µÓÔÔ„ . ¡¡Á¦³â[·ná»ï¾ƒZ­6Þâ:oÞNNNJ¥hiiÁÝ»wáââ‚'žx¾¾¾í¦ñðð@`` $I‡ój;¾¢¢ååå Á÷ß+W®À`0`Ĉ¨©©Áƒ>ˆï¾ûÅÅÅxà@ƒÁ€O?ýwïÞETT¾ýö[ܾ}z½C‡ÅÔ©SáêêŠo¾ù%%%ð÷÷ÇÈ‘#QRR‚o¾ù£GÆÔ©SÑÚÚjqZ[¶W¢îdéìÝ–ƒzHHˆ±\Ûòõ @‡·HÝ¥3j\%^hRiÐ\_w¡®®4·­­NÐëèð” ÁM†\>Œ-Ií¢¡¡xòÉ';-ÿí·ßB£Ñ 44óæÍ3äLv¦Ã QRR‚±cÇâ¹çž3+gmœ%&L@yy9¡T*1a„ש¼¼Ó¦MôiÓP^^ŽÂÂÂvå¦M›†™3g¢µµW¯^í´— ízÙRÇÔ©SÒÓ0uêT<óÌ3ÐëõhhhÀ£>Š™3gB£ÑàÛo¿5+€€€466v¸L–Æß¸q“&MÂ÷߈ŒŒDTTôz=àñÇGEEFމ¦¦&TUU*++ÑÔÔ„Q£FÁÅÅ………(++C@@BCCQUU…‹/üüü “ÉpõêUÔÕÕ¡¨¨2™ ~~~ƸZš¶+Û+Q_O&lI,ö €^¯ÇíšzÔÜÕA"@}§ê&ô:Ä:=Ä"-$Hà;\ŽaÆñNêPMMñÌÖV:_}õ† ‚G}2™ÌbÙŠŠ ãA¼íí¯ÖÆY2|øp¸ººâË/¿„››†oŒéÙzÛaf=l=d¬·¥¥Å®¸ÙZ‡é»µ³þÎ___³}ØôsÛe7]¦{íkËø††<øàƒ¸|ù2¢¢¢àìì ˜>>ü­î[PP®]»†ÊÊJTVVB¥R!22²G—áá‡Æ×_iÓ¦Ý×|z"AvTmçÓËn0Œß¦O9½7L«ÕB$ÁÝÝ>>>¸}û6nß¾ªª*øøøn¸'::Úø³‰)­Vk|>ŠN§ƒV«mWÆÒ´DýYG?'˜^CÐ¥d@(b¸|(Tõu¸öãhmiùçïw0ÀÅÅžCø ^|ñE³³ª¾|öqóæMüêW¿‚T*…D"Axx8Ž?n×úß[7‰Dâ°×<[ŠWuu5æÍ›‡!C†à‰'žÀùóç¹uÛѦ–¶ÉG}R©£Gƾ}û,–èñï(–öï¶Þxã ¼þúëvMCD}4°Ö}øÛßþ³gÏFee%¢££±víZã¸ÿþïÿÆ©S§P\\Œ   㙇éH_ôÚk¯!88/½ôÞzë-[,kiýï­[SSšššºtà·5aZ»v-–,Y‚Û·o#-- ܺíhSKÛä?ü€;wî ''›6m²Xv Ç¿£8XÚ¿Medd ±±Ñ,èl"êÃÉ€µ.ëÏ?ÿ«W¯†X,ÆêÕ«qîÜ9ã¸Ç{ ¯¼ò Ž;†—^z©ß&!!çÏŸGxx8ÊË˱hÑ"|ðÁ–µ¶þ÷ÞîÚüü|ÄÅÅÁËË sæÌÁ?þÈ­û>Ú®^½Š_|“&MBxx8eü­ÅÁÚþ}èÐ!\¸po¾ù¦Ùðþú@ÄdÀ–îgüä“O°páB|òÉ'˜5kV¿ ޝ¯/âââ’’‚O>ùÄêÙ^oßÏ­×ë¡T*ɃJ¥âÖ}Ÿmú / $$§NBEEÅ ¿µ8XÛ¿OŸ>o¾ùµµµæ;ˆÉ€¡¡¡x÷Ýw¡Ñh°k×.„……ǽýöÛ˜={6¶lÙbÖ-ëëë‹o¿ý¶Ïfîܹøì³ÏÐÜÜŒÆÆF|ôÑG¾é©³õï©õ|æ™gðöÛo£¾¾Xµj·n;Û´m[ÕÖÖ"88>ø rssÛ%¦erü­ÅÁÒþ »wïFZZâããÍž‚fm"ꢮLtï>Æ{ÿ¿ýöÛxùå—±uëVøûûãý÷ß7Žûî»ï0vìX¸»»ãOú“qø¶mÛ ¡Pˆòòò>˜ˆˆ¼ñƸxñ"D"fΜ‰˜ÝÃiËúoÛ¶ ÿöoÿ¡Pˆ[·nuyy:ª×ôï;w"!!&LÀC=„7ò^|;Û´í6¹}ûv<ûì³prrÂþçšÅ»mÙÓe·Kû÷½2ÁÁÁððð@rr2~ÿûßw: õÁ?÷Y4qà,¾ë¼¿î¸÷–[¯×ÿ ¸ººvú~wG¬so×?1¦Œ Ù¿ÿ/[¶ÌX6''111öõ ô÷Gœêõú.ÕQëÜÛõDŒ)cCD÷¿ÿÛœ ”—žØ îXçÞ®°oôƒ-¦Œ ¿– èõúõT[ÔëÜÛõÖ~°Æ”±!âwã}'z½---.@ÖºB{b{»þˆ1elˆÈ¾ýߦd@«Õ¢µµuP­·×y0Æœ1elˆ¨wYMD"D"Ñà H/¯ó`Œ9cÊØQïêðÖÂo¾ù………ƒ&~~~ÐkëÜÛõ³M"<û¿éÃÖîÝZØa2 ‹1""¢Èôxߥç ÑÀò?¾Î P—ý¿%Ü~ '†€ˆˆˆÉ1 """&DDDÄdÀ@Ðm a:ï¿ÉÍÍ…\.‡››Û}Ç•únóDÄž^úÒµWKK “ÉzeÙ7l؀Ç£¹¹™[ª?QQQððð€X,†ŸŸ²²²ztøf@"b2ÐOˆÅb¡¾¾¾Wê/..†B¡`C8ÐgŸ}†˜˜,_¾J¥µµµØ±còòò"b2`’’C,#$$¥¥¥ÆqõõõXºt)<<<0yòdœ>}Ú8nôèщDðööÆž={,ÎóæÍËå:t(räH\¹re@4–µõ·äý÷ßGFFV¬XÑîgú»µ¥vh‘€Ã‡C¥R¡¹¹gΜATTÔ}ÅÙ’ÒÒRh4lß¾ÑÑÑ–ŒŒDrr2êêê T*Ço)"ê›É@zz:²³³!•J‘““cvñUFFòóó1lØ0( DFFRRR P(0bÄÀÑõaøðá˜1cRSSÃßzë-̘1^^^v×gzñ^W/Bt$këoMXX^ýulß¾ÝbKí6ÐÌš5 |ðÒÓÓáããOOO¬]»ááá÷çŽÌ›7îîî(((@ZZZ§åwïÞ¢¢"øúúB¡P è^."ê;ø c¢îÚ¹zéZ{𚺼f rè5DDD400 ê&|Ê 1 """&DDDÔ÷‰¢Á‹€Àž""¢A=Dƒ˜½·.9Úø÷¡|çË´>zÝ®y:ÿ0ÁøwLbüÛc؇”·´Ì––Ó´¼%%™ùÆ¿ÏÍ|¸ËëkKÜ,õÞ8ªí,ÅÐt9ÿz¬]Ë`iMYš'±g€ˆˆˆ˜ “"""b2@DDDLÚéí—õåu6-7ãÔßÛ–mFDLú°ŠŠ „††B,#,, ·oßîÑúù8ÛîqþüyDEEÁÃÃb±~~~ÈÊÊbÛ“jïÕW_…B¡@cc#ÂÃñyóf¥Ÿûì³ÏƒåË—C©T¢¶¶;vì@^^ƒCDL:#°yófÈår :4Ž«ªªBtt4Äb1&L˜€sçÎZ[[1}útèõz€^¯Ç“O>‰ÖÖVã´£G†H$‚··7öìÙc6ψˆ¸¸¸Àßß¿ÝòXšÎ‘òóóñ›ßüb±ñññ=~ÀhÛ}lï:—”” 88b±!!!(--5Ž«¯¯ÇÒ¥KáááÉ“'ãôéÓÎÃÖrýÅk¯½†´´4,Z´îîîH$ˆˆˆ@zzºMqXµj¼¼¼ “É””„+V@&“A&“!33Ó¬ìúõëáéé‰qãÆáÒ¥KÛ¶³}‰ˆ¨Ïô Œ5 7oÞÄ¡C‡°aÃãðøøxÄÆÆ¢¡¡X¹r%ÀÙÙAAA8yò$àÔ©Sxúé§áììlöÅ«Õj‘——‡7‡'$$`Ú´ihllÄÇÜᮣé©¢¢r¹àíí ¥RÙ«eï:¯^½sçÎEcc#æÌ™ƒøøx³6›2e ”J%rss±oß¾çak¹þââÅ‹˜={v—ãþþþ(++ñcǘ˜ˆÀÀ@ܺu YYYØ´i“YÙTVVbÍš5X·n]§Ëgi_""êÖ“OƒÁFc(‹;>>½Öx]]g­VÛápƒÁ'§Î›ßÖrýÅÔ©S‘Ý帙u«µ‰‹µ8ét:‹Û³­ûQwqÈ·|dd$’““QWW¥R‰¸¸8³ñ‹/Æ‚ °dɳá555 …\.lj'ÌÆ`ïÞ½Ðh4í~&°6#EDD`×®]Ðh4ÈÈÈ@DDD¯5TWÖ9<<;wî„F£Ajj*fΜi@­V£¼¼Ë–-3ë‘°¥\”˜˜ˆ„„>|*• ÍÍÍ8sæ ¢¢¢lŠ›½JKK¡Ñh°}ûvDGGß÷¾DDÔg“Ý»w£¨¨¾¾¾P(í¾@zz:|||àé鉵k×"<<ܦ¸ÙkÞ¼ypwwGAAÒÒÒî{_""ê6_3@Dvî\&×ôU¼fÀzyKxÍ€õeà5}›Ã® ""¢ƒÉQ7áS‰ˆÉ1 ""¢¾ "¼€ˆˆˆÚ1Dƒ—é­aöÞòfZÞ–Û m¹ÝÌ–Ûý2ËJ:-cË-„–nÛ˜úËë¬-Ý®h/{cÛ׿c©¬¥¥Édýv¶nÝŠI“&ÁÙÙ'NÄ‘#GŒã233 Lœ8GízþüyDEEÁÃÃb±~~~ÈÊÊêÑe࣊‰ˆÉ@?!‹„úúú~»—.]ÂáÇ¡V«±sçN,_¾Ü8îøñãØ³gÔj5rrrðòË/ø6ýì³ÏƒåË—C©T¢¶¶;vì@^^7x"b2Ð@€Í›7C.—cèС8xð q\UU¢££!‹1aœ;wÐÚÚŠéÓ§C¯×ôz=ž|òI´¶¶§=z4D"¼½½±gϳyFDDÀÅÅþþþí–ÇÒtŽ>{ëÍ3¸úúz,]º˜ml ­V‹¸¸8¸¸¸X-{ôèQ<ñÄ0 øùçŸdœÿ‘#G0iÒ$…Bcâĉv/KóÚk¯!-- ‹-‚»»;$ """žžn,SRR‚àà`ˆÅb„„„ ´´Ôl?Xµj¼¼¼ “É””„+V@&“A&“!33Ó¬ìúõëáéé‰qãÆáÒ¥Kfã:bi_""ê3=£FÂÍ›7qèÐ!lذÁ8<>>±±±hhh@FFV®\ pvvFPPNž< 8uêž~úi8;;›}ñjµZäååaãÆÆá ˜6mññÇ·[KÓ $ñññ˜2e ”J%rss±oß>ã¸ýû÷cÇŽhiié´,¸¸¸`ãÆØ»wo»zššš°k×.:t¨KËÒŸ\¼x³g϶ZfõêÕ˜;w.1gÎÄÇÇ›÷÷÷GYYŽ;†ÄÄDâÖ­[ÈÊʦM›Ìʆ„„ ²²kÖ¬ÁºuëljóŽö%"¢îdó» ñ,Y§ÓA$?K¥R¨Tª_2 ''èt:À—_~‰mÛ¶áøñãX°`^yå ‘””„Ë—/£¢¢jµÚlž%%%ðòòjW¿µéº%H&u÷$©TŠªª*¸ººvº<–ÊÞ£ÓéðñÇ#-- Ÿþ¹q¸V«ÅŠ+°eËŒ5ÊîeéoÜÜÜPUUwww«eª««!‘H R©àíí¦¦¦v±×ëõ …?›–U©TËåP«ÕíÆ™þmm_ê|á?ñ „¶ÇÊŸ@Ø?9ìÝB¡Ðì³^¯Gmm­±[ÝôË+((×®]Ã… pýúuc"óçÏGXXΞ=ÛîwùÖÖVcx[Ö¦H œœœRV(bîܹøê«¯ÌeË–áù矷šØ»,}ÙÔ©S‘Ýi9­VÛy·Z›xX‹N§³¸=Ûº/u‡|»GFF"99uuuP*•ˆ‹‹3¿xñb,X°K–,1^SSƒÐÐPÈårœ8qÂl\@@ýŠ IDATöîÝ FÓîgkÓ $ÑÑÑ8pàÔj5ÊË˱lÙ2»Ë>ÿüó¸víÔj5’““Í®X¼x1yä‹Ý榿kÛ³,}Ybb"pøða¨T*477ãÌ™3ˆŠŠ2– ÇÎ;¡ÑhššŠ™3gv¹¾ÒÒRh4lß¾ÑÑÑ÷½/õÙd`÷îÝ(**‚¯¯/ E»/ÏØØX(•JÄÆšw)¥¤¤@¡P`Ĉ(((0÷Î;ï`×®]ðòò©S§lžÎ‘ñ€húwOÉÈÈ@~~>† …BÈÈH»ËN:sæÌÁ!CŸŸoö[ÿÑ£G±eËãºY[?{–¥/›5k>øà¤§§ÃÇÇžžžX»v-ÂÃÃeÒÓÓ‘ ©TŠœœ³‹ í5oÞ<¸»»£  iii÷½/uËñ6^3@Dö'“}ýy¼fàŸxÍ€í±2Åkú'‡]3@DDD“¢n§ “"""b2@DDD}/ $""Dx!µ#bˆ/Ó[ MÙ{›ž%–æcÊÞyZbéö·™Äø·£n´´Ž¦ì]_K·:ÚÛv¶ÄÇQË@{ˆˆˆ˜ “"""b2@DDDLú´ž~IQOmÏܶ‰ˆÉ@–™™‰àà`¸¸¸`âĉ8zôh¿\Ï?ÿ“'O†³³3üq|úé§fã“““ñÐCáízþüyDEEÁÃÃb±~~~ÈÊÊêÑe࣊‰ˆÉ@?qüøqìÙ³jµ999xùå—ûåz,Y²ÿó?ÿƒ;wî 11/¾ø¢q܇~ˆ>úûÛßp÷îÝߦŸ}öbbb°|ùr(•JÔÖÖbÇŽÈËËãODL:#°yófÈår :4Ž«ªªBtt4Äb1&L˜€sçÎZ[[1}útèõz€^¯Ç“O>‰ÖÖVã´£G†H$‚··7öìÙc6ψˆ¸¸¸Àßß¿ÝòXšÎ‘Ž9‚I“&A(¢¸¸'N챆é,v«V­‚——d2’’’°bÅ Èd2Èd2dffç¥×ëgþaaaðôô4Ž{÷Ýw‘’’‚Ñ£GwºLõõõXºt)<<<0yòdœ>}ºßmð¯½öÒÒÒ°hÑ"¸»»C"‘ ""éééÆ2%%%†X,FHHJKKÍö[ã.°~ýzxzzbܸq¸té’Ù¸ŽXÚ—ˆˆúLÏÀ¨Q£póæM:t6l0Gll,‘‘•+Wœ„“'ON:…§Ÿ~ÎÎÎf_¼Z­yyyظq£qxBB¦M›†ÆÆF|üñÇí–ÅÒtÝ¡©© »ví¡C‡z¬al‰¿¿?ÊÊÊpìØ1$&&"00·nÝBVV6mÚd,—™™‰ððp,Z´qqq8räˆq\aa!6oÞ ±XŒ±cÇZ=ÀÇÇÇcÊ”)P*•ÈÍÍž}ûúÝñâEÌž=Ûj™Õ«WcîܹhllÄœ9so6ÞÖ¸@HH*++±fͬ[·®Óå³´/u'›ßM Œ¿sêt:ˆD"ãg©T •JõK†áäNøòË/±mÛ6?~ ,À+¯¼‚€€ã()) —/_FEEÔjµÙŒqãÆÇ=ûì³øãÿµZ÷Þ{O=õT»¡{¢££qàÀ¨Õj”——cÙ²eýnƒOLLDBB> •J…ææfœ9sQQQÆ2áááØ¹s'4 RSS1sæÌ.×WZZ FƒíÛ·#::ú¾÷%¢î"~Žw¸0¸O»wïFQQ|}}¡P(Ú}yÆÆÆB©T"6Ö¼Û)%% …#FŒ@AAÙ¸wÞy»ví‚——N:eótŽtôèQlÙ²Àø¯§YŠ=8€÷Þ{xçwðÁÇ%''ãïÿ;<==ñþûïã½÷Þ³8ŸŒŒ äççcذaP(ˆŒŒìwü¬Y³ðÁ ==>>>ðôôÄÚµkn,“žžŽììlH¥Räää˜]\h¯yóæÁÝÝf=2]Ý—ˆˆºƒÍ× ‘;—ɵ}¯¸|k!õ7»f€ˆˆˆ&DÝ„O$"&DDDÄd€ˆˆˆú>^@HDD4ˆðB"""jGÄ ^o¾þË Çîç¼Þº­¯¯-ƒ½ËfÊÒ­|¶ÜBhïí¼mÚbÏ“"""b2@DDDLˆˆˆˆÉ@ŸÖ/ b ˆˆˆÉÀ ·uëVLš4 ÎÎΘ8q"Ž9¤a$Tb±¡¡¡¸zõ*ƒBDLË.]º„ÇC­VcçÎX¾|9ƒ2 466báÂ…xñÅ"b2`ÏÕæÍ›!—Ë1tèP<øËýÉUUUˆŽŽ†X,Æ„ pîÜ9@kk+¦OŸ½^ÐëõxòÉ'ÑÚÚjœvôèщDðööÆž={Ìæøûû·[KÓ9ÒÑ£GñÄOÀ`0àçŸFPPP6NWbp¯WàÞ°-qž5k\\\ggg³6×jµˆ‹‹ƒ‹‹K§óXµj¼¼¼ “É””„+V@&“A&“!33ÓâºÖ××céÒ¥ðððÀäÉ“qúôén­X,ƪU«ðý÷ß[]_KÛö½òëׯ‡§§'ƇK—.YWII ‚ƒƒ!‹‚ÒÒÒN×ßZýûöíƒ$ .\Øép""‡ô Œ5 7oÞÄ¡C‡°aÃãðøøxÄÆÆ¢¡¡X¹r%ÀÙÙAAA8yò$àÔ©Sxúé§Í8%%%ÐjµÈËËÃÆÃ0mÚ4466âã?n·,–¦ë...ظq#öîÝÛ£Ó•Ü{SžÁ`0{kžµ8Ož<øË_þ­VkVÇþýû±cÇ´´´Ø{”••áØ±cHLLD`` nݺ…¬¬,lÚ´ÉâºÆÇÇcÊ”)P*•ÈÍÍž}ûº5¶wîÜÁ›o¾‰ÐÐP«ëkiÛ¾'$$•••X³f Ö­[gu^«W¯ÆÜ¹sÑØØˆ9sæ >>¾Óõ·VBBΞ= ¥R‰àààN‡Y<á‡ï&ƃ‹N§ƒH$2~–J¥P©T¿dNNÐét€/¿üÛ¶mÃñãDZ`Á¼òÊ+")) —/_FEEÔjµÙú‡½›@(š}Öëõ¨­­5žÞû²€   \»v .\Àõë׉̟?aaa8{ö,êëëÍæÙÚÚjÖ5mÊÚtÝA(bîܹøê«¯z´Áke[ZZìz1•­õ:99YýÜ–Á`è´Œ£ 477#77טXbmÛn›0Zj+Sm{^:[kõŸ>}‹/Fvv6fΜÙép""‹ßÙŽ˜Idd$’““QWW¥R‰¸¸8³ñ‹/Æ‚ °dÉ󌽦¡¡¡Ëå8qâ„Ù¸€€ìÝ»¦]¹µééùçŸÇµk× V«‘œœÜã× t5#GŽÄ•+Wl*;}út¼÷Þ{¸{÷.rrr:]&GÆÞôš†èèh8pjµåååX¶lYŸØA:Û¶KKK¡Ñh°}ûvDGG[Wxx8vîÜ FƒÔÔT³µ¥õ·Vrr2ž{î9lݺׯ_ït8Q·&»wïFQQ|}}¡P(ÚÄÆÆB©T"6Ö¼k*%% …#FŒ@AAÙ¸wÞy»ví‚——N:eótŽ4uêTÌ™3C† A~~~·ÿŽÝVWcðÖ[oaƌƮÿÎ✖–™L†C‡™]ÏÑ‘îŠ}FFòóó1lØ0( DFFö‰¤³m{Þ¼ypwwGAAÒÒÒ¬Î+==ÙÙÙJ¥ÈÉÉAzzz§ëo­þ¢¢" >3fÌ@jjj§Ã‰ˆ,žœÁÆkh`3 8yò$^}õU\¾|™±±g£;¯Ué ¼f gðšêK:ºf€¯0& >ÕÕÕ?~<Þ{ï=„ˆha2@¨¨¨`º ¿÷ ÝÃ'1 ""¢ÁŒ "{è ¼€h³å¶5Kl¹]®õѾûÐ#KËozÛi|Loß3½eÏ–u¼ŸXuwœí½íqcj–ñoÓ[5m™¥yRïcÏ“"""b2@DDDLˆˆˆˆÉ@ÉÍÍ…\.‡››[À Ó·úÑÀm[¶3 Êd`Æ 8|ø0š››ûtp*** ±XŒ°°0ܾ}›[ÌpþüyDEEÁÃÃb±~~~ÈÊÊêÑe࣌‰hÐ'ÅÅÅP(}>8¯¾ú* ŽÍ›7s‹éç>ûì3ÄÄÄ`ùòåP*•¨­­ÅŽ;——Çà“ά_¿žžž7n.]ºd6N«Õ".....€’’C,#$$¥¥¥Æ²wïÞ…@ 0vZ*kiÞ«V­‚——d2’’’°bÅ Èd2Èd2dffš-ûèÑ£!‰àíí={öØœüü|üæ7¿X,F|||¯0¬Å¨³øYj·¶êëë±téRxxx`òäÉ8}úô€Ûà_{í5¤¥¥aÑ¢Epww‡D"ADDÒÓÓmާ­Û^gûLGªªª ±XŒ &àܹsü–"¢¾Õ3‚ÊÊJ¬Y³ëÖ­3·ÿ~ìØ±---€Õ«WcîܹhllÄœ9sà—îQƒÁ`üÛRYKó”••áØ±cHLLD`` nݺ…¬¬,lÚ´©ÝT«Õ"//7n´y}+** —ËÞÞÞP*•½ÖPÖbÔYü¬µ›©øøxL™2J¥¹¹¹Ø·o߀Ûà/^¼ˆÙ³gw9Öön{¶ÆÞ´ bccÑÐЀŒŒ ¬\¹’ßRDÔíl~7@ 0¼U*är9Ôju»q÷¸¹¹¡ºº‰*• ÞÞÞhjjê°¼=eÛÓëõ …?")) —/_FEEÔjµÍ¿×:;;C£ÑÀÉÉ :®®®f I·7ŽÉzZ‹‘­ñkÛnmI¥RTUUÁÕÕuÀnðnnn¨ªª‚»»»Õ2¶Ä³³mÏÖ}Æôo©T •JõK¶þ¯m¯»ð „íñ „ÖcÂ'ö{7N§3vÙ[£Õjmž§=eͺ6œœ¬~ž?>ÂÂÂpöìYÔ××Û5oTWW*++áããÓ« h-F¶Ä¯³v3 íâ7ÐL:ÙÙÙÙ;Ûöº²ÏèõzÔÖÖ{κ3 "2~ÙS¸´´Û·oGtt´Õ²áááØ¹s'4 RSS1sæL‡”µWMM BCC!—ËqâÄ »¦ˆˆÀ®]» Ñh‘‘ˆˆˆ^k(k1ê,~ÖÚÍô·ëèèh8pjµåååX¶lÙ€Ûà‘€Ã‡C¥R¡¹¹gΜATTT·löì3‰äädÔÕÕA©T"..ŽßRDÔ·’yóæÁÝÝHKK³Z6==ÙÙÙJ¥ÈÉÉ1»@ë~ÊÚ+%% …#FŒ@AA]Ó¾ñÆÈÏχT*ŧŸ~Š7Þx£×ÊZŒ:‹Ÿ­í–‘‘üü| 6 …‘‘‘nƒŸ5k>øà¤§§ÃÇÇžžžX»v-ÂÃûe{´gŸ€Ý»w£¨¨¾¾¾P(MŒ‰ˆ,éÒ5Ô˜íÆØ[ÁkÚã5ÖcÂkú?‡]3@DDD‡ÍÉÏ.û'¶cODä°d€ˆˆˆ˜ Ñdó„DDDÔÿñB"""jGÄ ^–n³…¥[Éì½Õ®F&ét,ÝÖgË´ö.óýÜBh/{oüK^7þmé¶P[Ê8jÙx{àÀÁž"""&DDDÄd€ˆˆˆ˜ ““›› ¹\777¶@˜¾iÐå¨÷ÛŠˆhÐ%6lÀáÇÑÜÜܧƒÓÒÒ‚‚‚Èd2n)èà,àìì ???|ñÅÝZILDýA¯ÜZX\\ …BÑçƒÃ‡/ Lƒ­­­8|ø0–-[†7n0(DÄž[Ϩ֯_OOOŒ7—.]2§Õj@II ‚ƒƒ!‹‚ÒÒRcÙ»wïÏЬ•µ4o@€U«VÁËË 2™ IIIX±bd2d2233Í–}ôèщDðööÆž={ì:hôæ™Ý¾}ûàãã‰D‚… Z,gmýÖ¬YŒ?Þ¬ÍÚª¯¯ÇÒ¥KáááÉ“'ãôéÓzÃwvvÆÂ… qûöm³áUUUˆŽŽ†X,Æ„ pîܹNcdmš{Ûxkk+¦OŸ½^ÐëõxòÉ'ÑÚÚÚé<ˆˆúL2!!!¨¬¬Äš5k°nÝ:³qû÷ïÇŽ;ÐÒÒX½z5æÎ‹ÆÆFÌ™3ñññÆlÛ­¥²–æ þþþ(++ñcǘ˜ˆÀÀ@ܺu YYYØ´i“Ùô%%%ÐjµÈËËÃÆûMã$$$àìÙ³P*•¶XÎÚúEDD ºº¿ýío±víZ‹óˆÇ”)S T*‘››‹}ûö è _­V#%%sæÌi‡ØØX444 ##+W®ì4FÖ¦1M>‚‚‚pòäIÀ©S§ðôÓOÃÙÙÙæyu›ßM Œo•J¹\µZÝnÜ=nnn¨®®†D"J¥‚··7ššš:,oOÙ¶Ãôz=„B¡ÅÏ………HJJÂåË—QQQµZm÷Ù~GËОzê)ÈårÄÄÄ &&í–ÇÚúYk³¶¤R)ªªªàêê:°7x“ úþýßÿ™™™H$fqP©T¿dËNNÐétVcdmÓ6øòË/±mÛ6?~ ,À+¯¼‚€€€NçÑøÂöËÌ'Ú¾l|aÿä°wèt:c—½5Z­ÖæyÚSÖ¬kÃÉÉêçùóç#,, gÏžE}}}¿j°Ó§OcñâÅÈÎÎÆÌ™3;,cëúéõzãYhG C»Ø Tƒ_|ñ®_¿nL:MãT[[kì¹2= [Š‘µiLáÚµk¸pá®_¿nLì™Qw°ëÛ¿´´Û·oGtt´Õ²áááØ¹s'4 RSS-Ìì-k¯šš„††B.—ãĉýªq’““ñÜsÏaëÖ­¸~ýz—Ö¯¸¸Û¶mk×f¦gÉÑÑÑ8pàÔj5ÊË˱lÙ²½áãý÷ßǪU«Œ¿Û@dd$’““QWW¥R‰¸¸¸Ncdmš¶/^Œ `É’%fÃí™Q¯&óæÍƒ»»; ––fµlzz:²³³!•J‘““ƒôôt‡”µWJJ  FŒ‚‚»¦5½ÈÑôïžRTT„áÇcÆŒHMMµ{ý„B!-Z©TŠ‚‚¼óÎ;ëÊÈÈ@~~>† …BÈÈÈ¿ñûûû#)) [·n5Û½{7ŠŠŠàëë …Ba–˜ZŠ‘µiÚŠ…R©Dl¬y÷ª=ó "r´.]3@D¯h¿Ì¼fÀöeã5ý“î ""¢Ãæd€½DDDƒ< """&DDD4Ù|!õ¼€ˆˆˆÚ1Dƒ×›¯4þ}?·øYºíÎôö4[nÍëî[m¹Î4&¦åm¹MÏ´Þû©Ë”½õš²sÓÛ‰^3@DDÄd€! ""b2@DDDLˆˆˆˆÉ@ÊÍÍ…\.‡››[€ˆˆh0&6lÀáÇÑÜÜܧƒ“™™‰àà`¸¸¸`âĉ8zôè ÝPÚ¾±±§ßàèÈõ‹Å ÅÕ«Wù-@DLz£Òââb(Š>œãÇcÏž=P«ÕÈÉÉÁË/¿Ì-f0 hllÄÂ… ñâ‹/2 DÄdÀž3ªõë×ÃÓÓãÆÃ¥K—ÌÆiµZÄÅÅÁÅÅPRR‚àà`ˆÅb„„„ ´´ÔXöîÝ»Æ34ke-Í[ `ÕªUðòò‚L&CRRV¬X™L™L†ÌÌL³e=z4D"¼½½±gÏ›ƒsäÈLš4 B¡ÅÅŘ8qbŸÅZйµõªªªÂ¬Y³àââ‚€€8;;›‹ŽŽ†X,Æ„ pîܹNçy¯îµYÛÏ–Ú©­úúz,]º˜Ýk¾X,ƪU«ðý÷ß[ÝÖ¬ÅËQû„µØX«ß¾}ðññD"ÁÂ… ;NDäžTVVbÍš5X·nÙ¸ýû÷cÇŽhii¬^½sçÎEcc#æÌ™ƒøøxãYÙ½ÿïým©¬¥y€¿¿?ÊÊÊpìØ1$&&"00·nÝBVV6mÚd6}II ´Z-òòò°qãF»ƒÔÔÔ„]»váСC=Þ@Öbni½0yòd466â/ù ´Z­q\||Ü>DD} _TDDDÄd€ˆˆˆ3›/ $""¢þÏa"""¢ƒÉ“"""b2@DDDLˆˆˆˆÉ1 ""¢Á¦ÃÇ«ÕjF†ˆˆh ö8µï`ÏÑ`O"""&DDDÄd€ˆˆˆ˜ “"""b2@DDDLˆˆˆˆÉ@/rssc«õåd€ëîóÇ?þÓ§O‡‡‡¦NЬ¬¬.•miiÁ… 0|øp»—Ážioܸ3f`È!xöÙgQYYi6þí·ßÆøñã!“ɺm¾øâ <ùä“ððð€¿¿?Μ9Ó¥x1 >á믿Fff&jkk‘’’‚Õ«Ww©ì!C޼vHe[IDAT††»—Ážiýë_#66Àïÿ{ã¸>úGÅ™3gPWW×mËðÒK/áõ×_GUU6mÚ„—_~¹Kñ$"b2॥¥xæ™g0dÈ( ”••™ôÑG!•J1zôhìÛ·Ï8¼ºº¿úÕ¯àé鉧Ÿ~ºÓz:šOkk+‚ƒƒ¡×ëz½!!!hmm5Ö1oÞ< 2O<ñΟ?oÖÓ¡Õj±jÕ*xzzÚ´¼sçÎ…§§'BCCáááa6ÎR=¶ôª|øá‡xüñÇa0PSSƒÀÀÀ.•mnnFsss—ÚÑži/^¼ˆ—^z ®®®øÝï~‡Ó§OÇíÙ³o¾ù&FÕ­Ë ×ë1bÄ<ðÀ 1kC{âIDÄdÀ~ûÛßböìÙ¨¬¬Dtt4Ö®]k6þ‡~À;w““ƒM›6‡ÿîw¿Ã”)SPYY‰C‡uZOGóqvvF`` òòòùùùxê©§àìì X»v-–,Y‚Û·o#-- fó´Z­q\gõØÊÓÓ¯¾ú*Þ}÷]‡–u4___üßÿý´Z-ÊÊÊÌz¾ýö[üáÀ!CðØcáìٳݲ {÷îETT–.]Š•+Wâ/ùKŸŠQ `0 Ðh4fg[–¸¹¹uxÖ6tèP”––B"‘@¥Ra̘1øùçŸW¯^ŶmÛðÍ7ßàöíÛP«ÕÆy 6 ?üðƒñweKóïl>_}õþô§?á¯ý+/^Œ 6`úôéÆ:T*Õ/““ñsGõY«ÇÛÛßÿ}‡Ëk­{èt:?~éééÈÏÏïrYk±ìŒ-Óž9s+W®Dee%QTT¥R J¥øÛßþ†Ç{ }ô¶nÝŠ«W¯:|V¯^ÈÈHŒ1_ý5nß¾?üá]Ž'Ñ€ï0ykaNNbbb{Í€N§ëpø /¼€œ:u fãZ[[gð±6ŸÀÀ@\¿~—.]Â7Œ‰À½äF©T»Ÿ;;@[«§¥¥...Ngo=–…BÌž=/^thYG{æ™gpíÚ5444 11~~~Æq^^^=z4D",XÐîg#Gùè£ð«_ý O?ý4^~ùe¤§§÷©õ‹ÁQ3 Å»ï¾ Fƒ]»v!,,Ì8®¶¶ÁÁÁxðÁ‘››k6ÝôéÓ±ÿ~h4?~ÜjÖæÏ?ÿ</^Œ^x¡ÝAëí·ßF}}=***°jÕª.×3mÚ48pwïÞÅÉ“'íª§³kþã?þ?þø#Ôj5Þ~ûív¿q›NßYYK¾øâ <òÈ#]nçŽÖ¡¬¬ ¯¼ò þë¿þË8,** )))P«Õ8pàºe|}}±wï^¨Õj9rcÆŒ¹ï1°ñËØô¤¦¦â“O>Á°aÃpòäI¤¦¦Ëoß¾Ï>û,Ƈ .˜Í+%%þóŸñÐCó·ÄÚ|`É’%¨¨¨À’%K̆ïÚµ ÿøÇ?0aÂDGG›%*öÖ“’’‚ôôtŒ1ýë_Íz5ì­§-???ÄÄÄ`øðá8sæ þüç?w©¬i»˜þmšètÖ¶MÛ‘{·þîw¿ÃóÏ?o¾mÛ6ÀÇÇ™™™ÈÈÈè–eøßÿý_ìß¿ÞÞÞx÷Ýwñþûïw)žDDƒ™Ý× Ð? äåå!11ÿûßûÍr¿ÿþûhiiÁ¯ýëA½ DDƒ¶ ƒkD ‹ýÆŽ‹ŸþãÆ3;ãíjkk5è—ˆˆØ3@DDĞ€ˆˆˆúa‚À1 """&DDDÄd€ˆˆˆ˜ Ñ S+úý˜‡ÀìöBÓÛˆˆˆhàù×m…ß^üxÔ'""¼&€0à÷cFHAÓO?ý>|8ÃCDD4@{ &&'‘áŸãš7Ž!;v¬ ÀGÿ;wL0ÅPôµ¸èTOß "ð‚D0UFah7pÞ3eÊ”ZmK’¤ Eí{!>Ž|_K°ôgX—$IûùG@^`L 9ºµb»IEND®B`‚distcc-3.4/doc/web/faq.html000066400000000000000000001315071404653710500156240ustar00rootroot00000000000000 distcc frequently asked questions

distcc frequently asked questions

Question not answered here? Check the mailing list archives or send email to distcc (at) lists.samba.org

What compilers are supported?

gcc is fully supported, building C, C++, Objective C and Objective C++. Other gcc languages such as Java are not supported. All recent versions of gcc are thought to work, though later versions tend to work better.

Intel's icc compiler is somewhat compatible with gcc and works with distcc, but some problems have been reported.

Sun's proprietary C compiler is reported to work with distcc in C mode. It appears that Sun CC cannot compile C++ templates correctly when using a separate preprocessor, so it is generally not practical to compile C++ using Sun CC and distcc.

The main feature required by distcc is that the compiler must be able to run the preprocessor separately, and then compile the preprocessor output from a file. This was a basic part of the original design of C, but some compilers seem to have lost the ability to do this. However, this feature is not required if you use distcc's "pump" mode. Secondarily, distcc is currently hardcoded to suit gcc's behaviour and command-line syntax, so only compilers that act like gcc will work. This could in principle be changed.

How to build gcc with distcc?

gcc uses an unusual three-stage process to verify that the compiler can recompile itself with the same results. Because of bugs in the gcc integrated preprocessor, compiling locally can produce a program that is functionally identical, but not byte-for-byte identical, with a program compiled remotely.

This can apparently be fixed by specifying 127.0.0.1 in the host list, rather than localhost. This causes distcc to run compilation "remotely" onto the same machine, which should be the same as compiling remotely.

You will also need to make sure that the build directory is mounted at the same location on all machines so that the new compiler can be located.

(More information or instructions here would be welcome.)

distcc gets slower when I add slow machines to the cluster

Make sure you put the preferred (fastest/closest/least loaded) machines at the start of the DISTCC_HOSTS list. This is particularly important when running ./configure scripts because all compilation will be done on the first machine listed. Normally this should be localhost, but if another machine is much faster then perhaps not.

To some extent this is still an open bug that I hope to address in a future version. It would be nice if distcc could automatically detect the best distribution, but it doesn't do that yet.

Restarting distccd on reboot

You may have distccd installed on a machine where you don't have root, and want it to restart when the machine reboots.

One way to do this, suggested by Shane McDaniel, is to put it in your per-user crontab. distccd will be started at regular intervals, but will exit if something is already listening on the port. Remember to set your PATH in the crontab so that distccd and all necessary compilers can be found.

Choosing a userid

It would be awesome if you could run the daemon as a specific user in daemon mode.

It is awesome! :-) From distcc 1.1, root can use the --user option to cause distcc to start as a particular user.

# distccd --user nobody

If distccd is started by root and no user is specified, it will change to the user distcc if possible, or otherwise to nobody. I recommend you create this user when installing the package.

If distccd is started by a non-root user then it will continue running as that user.

Why not use a distributed-make-style system?

A few people have extended make to allow it to distribute jobs across several machines. Projects I know of include Graydon Hoare's Doozer, Sun's dmake, pvmmake, and ppmake. GNU Make apparently has internal hooks to add distribution mechanisms, which I think is how ppmake and pvmmake work.

Unlike distcc, most of programs have no special knowledge of C: they just schedule jobs remotely or locally. The advantage of this is that you can distribute all different jobs, such as linking, or building documentation, or compiling programs in other languages.

The disadvantage of this approach is because it relies on running tasks on any node, all relevant aspects of the nodes must be the same. This typically means that all machines must have a shared filesystem mounted at the same location, that they must all have exactly the same compiler, headers and libraries installed, their clocks must be in sync, and typically that they must all have the same OS and CPU architecture.

In some situations, such as a lab of centrally managed machines, this is quite practical. However, many people have a less homogeneous environment: perhaps some machines run a different OS release, or developers are allowed to upgrade libraries on their own machines, or perhaps you just don't want to run NFS.

In this situation distcc is much easier to set up. You don't even need root on the volunteer machines, let alone a mandate to move /home onto NFS.

(You might get away with having slightly different headers or libraries, but the potential for confusion is so great that I think you'd be crazy to try.)

By Amdahl's law, a distributed make system could in principle be faster than distcc, because it can distribute many different jobs. In practice, however, for many projects compiling C or C++ takes over 80% of the time. Many of the other jobs, such as linking, cannot be parallelized anyhow.

I don't know how their performance compares but I would be interested to hear.

Has anybody yet thought of integrating distcc with ccache?

If you don't use distcc's "pump" mode, then they work pretty well as separate programs that call each other. You can either set CC='ccache distcc gcc', or arrange for both ccache and distcc to be "masqueraded" on the path. (See the manual for information on how to install this.)

Normally it is better for ccache to be run before distcc.

This is very nearly as efficient as making them both part of a single program. The preprocessor will only run once and the preprocessed source will be passed from ccache straight to distcc. Having them separate allows them to be tested, debugged and released separately.

Unless there's a really strong argument to do otherwise, having two smaller programs is better practice, or at least more to my taste, than making one monolithic one.

However, all of that said, now that we have "pump" mode, the trade-offs have changed. Using ccache prevents the use of "pump" mode. It would make sense to integrate caching into distcc so that you can get distributed preprocessing, distributed compilation, and caching all at the same time. This would make a great project for someone...

Also, it would be nice to allow a cache of compiled files to be shared across several users or machines.

Joerg Beyer started a project called gecc to explore this architecture, but development appears to have stalled in 2002.

Temporary files in strange location?

distcc always tries to create subdirs in /root/tmp for its temp files. How do I get around this?

distcc respects the $TMPDIR environment variable when creating its scratch directory. I suspect you have that set in root's .profile. If you unset it in the shell script that launches xinetd, or set it to something not in root's path, then it should be fine.

Server dies after a few connections when run from inetd

i noticed that when you start a make process, the remote distccd receives 10-15 connections from my host (which is good) and those processes die after a while. this is a long compilation (kdelibs) and after the initial processes die, i cannot see any new one's coming in. is this normal ? it seems as if after a while (2-3 minuets) distcc stops working and only my local gcc is still compiling.

If you're running distccd from inetd, then it may be that inetd thinks that the service is "looping" because of all the rapid connections. You need to increase the maximum connection rate. See the inetd manual.

On traditional BSD inetd, you can do this by changing the word t to something like nowait.1000

Alternatively, run distccd with --daemon, rather than from inetd.

Running distccd on a firewall?

another machine i want to add to this "cluster" is my firewall. its not a very powerful one, but it can help speed things up a little more ;) are there any knows security issues with distcc ? how stupid will it be to run it on a server that acts as a firewall ?

It depends on your security profile, but it's not completely unreasonable. Hopefully your firewall already has iptables and tcpwrappers protection against connections from the outside world. Just make sure that nobody else can connect to the distccd port.

What -j level to use?

when starting a compilation, the howto says to use -j8 . is this optimal ? anything else i should be using for better performance ?

For plain (that is, non-pump) mode, you should use about twice the total number of CPUs available, but it depends on your network, program being compiled, available memory, etc. Experiment with different values.

Client machines tend to be saturated at about 10-20 jobs, so using values above -j10 is rarely useful. (Perhaps higher levels would work well on clients with two or more CPUs and very fast network connections, memory and disk.)

The advice above is all for plain mode; for "pump" mode, you may see benefit from higher -j values. Please experiment and let us know what works best.

Should I include localhost in the host list?

Naturally, compiling on the machine that drives compilation has low overhead.

But, if a large number of machines are part of the distcc "farm", I suspect most of the driving machine's time would be better spent doing preprocessing & feeding only, and as such increase the chances of always having something ready to handle to machines that finish their distcc compilation jobs.

I'm just hoping to collect some opinions on this matter. For a large project and for a cluster of about 8 machines, is it actually better to dedicated the driving machine to do preprocessing only? (and so not include it in the hosts file).

It will depend on your source tree, your network, your compiler, and your makefile (or alternative) just what fraction of the work must be done locally, which is the most important thing here. At about the 3-4 machine level it may be worth putting localhost last; at 8-10 machines it may be better to leave it out altogether.

Different gcc versions?

if the host machine is using gcc 3.2, can the other machines use an older version of gcc ? 2.9.x for example ?

distcc doesn't care. However, in some circumstances, particularly for C++, gcc object files compiled with one version of gcc are not compatible with those compiled by another. This is true even if they are built on the same machine.

It is usually best to make sure that every compiler name maps to a reasonably similar version on every machine. You can either make sure that gcc is the same everywhere, or use a version-qualified compiler name, such as gcc-3.2 or i386-redhat-linux-gcc-3.2.2.

In particular, object files can be incompatible because:

  1. Calling conventions or ABIs have changed, particularly for C++.
  2. Different versions optimize differently.
  3. The header files specifically detect the version of gcc being used, to change optimization or to work around bugs. The Linux kernel does this.

In all these cases you would need to "make clean" if you upgraded your gcc.

It is hard to generalize, but using gcc versions which have the first two components the same (e.g. 3.2.1 and 3.2.2) is usually OK. To be safe, use the exact same release on all machines.

It is also a good idea to have the assembler versions be the same too, although the problems there are slightly less complex.

Shouldn't distcc check gcc versions?

It might be a good idea for distcc to check the version of gcc on all the volunteer machines. However this turns out to be hard to do completely reliably, because some programs which both call themselves "gcc 3.2.1" behave differently, presumably because of vendor patches or because vendors have shipped pre-release code.

So since automatic detection would not be a reliable solution, for the moment we depend on the user to make sure they have compatible versions installed.

Using different platforms?

I have a mixed network environment. MacOS X, Linux, and Windows (with cygwin). Seeing distcc really piqued my interest. Using gcc on all of my environments, can I set up distcc to span across this variety of operating systems?

It should be reasonably straightforward. Of course you will need to either install or build appropriate cross compilers for each machine.

For example, on each volunteer machine, build an x86-linux cross compiler and (this is important) install it as "i386-redhat-linux-gcc-3.2.2" or something similar, using the appropriate gcc configuration options to set the name. You also need to make a link to that name on the Linux machine.

Then from Linux, run "distcc i386-redhat-linux-gcc-3.2.2".

Repeat as appropriate for every combination you want to use.

On Windows, you need to use the Cygwin (or perhaps Mingw?) software, which provides a Unix-like environment for running gcc.

The easiest way to build a cross compiler is to use Dan Kegel's crosstool.

Brian Mosher reports that Mumit Khan's description of building a Cygwin-hosted Linux toolchain works well. Mike Santy suggests a slightly different approach.

Compiling between different i386 Unixes?

Do I need to install cross-compilers to distribute builds between different operating systems on the same CPU architecture? For example, OpenBSD i386 and NetBSD i386.

In general, yes you do. Even on the same system, there can be incompatibilites between the output of compilers such as

  • Different object file formats, or variations of the format. (OpenBSD uses a.out, but most Unixes use ELF.)
  • Different patches applied to the compiler, even if it claims to be the same version.

What's hard about synchronizing clocks?

Why do you say it's a feature of distcc that the machine clocks don't need to be synchronized? It's easy to do: you just install an NTP client.

It's not terribly hard, I agree. But it's not quite as trivial as you might think:

  1. Installing an NTP client requires root access on all the machines, not just your own workstation. (There's no way around it, because it needs to change the machine's clock.)
  2. You need to be able to reach a reliable timeserver, which is sometimes a problem with firewalls.
  3. If one of the machines does get out of sync, then builds may be incorrect or you may get errors. You may not notice until after problems have occurred. You can't fix it without intervention from the administrator, who may be on holidays.

What's not there can't break.

What does "listening on 0.0.0.0:3632" mean?

This message means it's listening for connections on a wildcard IP address, so clients coming through any network interface should be able to connect, subject to --allow rules.

If you have more than one interface and want to only allow connections from one of them then use the --listen or w options, or both.

How can I use SSH connection multiplexing?

Can I use ssh connection sharing to reduce the overhead of opening SSH connections?

Yes. Using SSH connection sharing can reduce the overhead of establishing SSH connections by a factor of 10.

Make sure you have a recent SSH (only on client side). I think you need OpenSSH 4 or later.

  $ ssh -V
  OpenSSH_4.6p1 Debian-5ubuntu0.1, OpenSSL 0.9.8e 23 Feb 2007

Create a file ~/.ssh/config, and add this:

  Host *
  ControlMaster auto
  ControlPath ~/.ssh_tmp/master-%r@%h:%p

Then create the master SSH connection:

  ssh -fMN hostname

Subsequent connections to that host will now fly!

For best results, create master SSH connections for each host in your distcc host list.

For more information on ssh connection sharing, see here.

Will compiling with distcc magically make my program distributed?

All objects files were created , but when I issue command for execution as ./executable then program takes so much time as without distcc. Kindly tell me that how this execution time can be reduced. All things work Properly , But all processors of systems are not utilized during EXECUTION of programs.

(This has to be the wierdest question in the list, but it really was sent.)

distcc makes building the program take less time. The program that is produced is the same as for a local build.

If you want your program to be distributed at run time across several machines, you need to design in parallelism and distribution, possibly using a framework such as MPI or OpenMOSIX.

What you seem to be asking for is to mechanically transform an arbitrary C program into a distributed parallel program. distcc doesn't do anything like that. It is perhaps not quite impossible (people have written parallelizing compilers) but it's very very hard.

make-kpkg with distcc?

How to compile the debian kernel with make-kpkg using distcc?

Use the CONCURRENCY_LEVEL environment variable eg make-kpkg kernel_image CONCURRENCY_LEVEL=4 after installing distcc into a masquerade directory.

How to use an SSH TCP port other than 22?

I want to use two machines over ssh. One machine has a different port than 22. But I can't set a port in the host specifications for ssh.

Use something like this in your ~/.ssh/config:

Host bertie
Port 2202

How do I build a cross compiler to Mac OS X?

Dara Hazeghi says:

Basically, you have to download the same source version compiler as the one on your OS X box, build it on you Linux PC, etc. The assembler now works on Linux as well, so that other issue you had should be moot.

That is, you should compile the Apple source on your non-Apple machine. Apple have some patches that are not in the upstream gcc release so a compiler built from the gnu.org source will not be compatible.

Randomly patched kernel crashes/hangs

I installed applied some random unstable kernel patches, and now my machine hangs/crashes/corrupts data when I run distcc!

If your kernel crashes, it is by definition a kernel bug.

If you have applied any patches that are not in the kernel.org stable release, your first step should be to back them out and see if the problem is still reproducible.

distccd sometimes unable to find gcc

distccd inherits its PATH from whichever process starts it, and uses this to find compilers. You may need to make sure the H is set appropriately by the script that starts distccd. You can also set DISTCCD_PATH, which overrides PATH and bypasses checks for distcc masquerade directories. The daemon's path is logged when --verbose is given.

Error about "jobserver unavailable"

This indicates a problem with your Makefile or shell. See the explanation of this error from GNU make.

This can also happen when make is unable to create the fifo it uses to communicate among parallel processes, because TMPDIR is not accessible. Check that the variable is set properly (or unset), and that the directory has the right permissions.

Files written to NFS filesystems are corrupt

List post: Writing object files from distcc to an NFS directory can cause corrupt output: object files will be full of zeros.

This is a bug in the Linux kernel NFS client interaction between mmap and rename. It can be avoided by using the no_subtree_check export option on the NFS server. distcc 2.18 no longer uses mmap to receive files and may not suffer this bug so strongly, but setting no_subtree_check is still recommended.

distccmon doesn't work on NFS

When I set DISTCC_DIR to a directory on an NFS server, or have HOME on an NFS server, the monitors give errors or just don't work.

The monitor checks that the processes recorded in the state files are actually running (using kill -0). If the processes aren't running on the same machine, this doesn't work.

In any case, having DISTCC_DIR on NFS is likely to cause problems with locking. Please set DISTCC_DIR to a local directory instead.

gcc's DEPENDENCIES_OUTPUT option is broken

Programs that use gcc's DEPENDENCIES_OUTPUT option don't work with ccache.

This should be fixed in ccache 2.3. There is no problem with distcc.

distcc fails to build on OS X

I'm trying to compile Distcc on OS X (gcc 3.1) and it fails with the following:

gcc -DHAVE_CONFIG_H -D_GNU_SOURCE -I./popt -I./src "-DSYSCONFDIR=\"/usr/local/etc\"" -g -O2 -W -Wall -W -Wimplicit -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -o src/climasq.o -c src/climasq.c
src/climasq.c:69: only 1 arg to macro 'rs_log_error' (2 expected)
src/climasq.c:114: only 1 arg to macro 'rs_trace' (2 expected)
cpp-precomp: warning: errors during smart preprocessing, retrying in basic mode
make: *** [src/climasq.o] Error 1

There is a bug in some versions of Apple's gcc. Building with CFLAGS="-no-cpp-precomp" should fix it. It should be automatically corrected in distcc 2.8 and later.

Problems with gcc -MD

I'm using 0.12, and having trouble with dependency file creation. The makefiles that are set up to use gcc's -MD option aren't working. I'm getting some of the .d files in their proper directory, and not others.

This problem can only occur if you're using gcc 3.0 or later, have the source and object files in different directories or under different names, and you are using -MD or -MMD but not -MF.

The workaround is to change the Makefile to explicitly specify with -MF the file which should receive the dependency information. Many Makefiles already do this. Note that the -MF option is only available in gcc 3.0 and later.

Because the behaviour of -MD has changed from gcc2 to gcc3 there is no perfect solution available at the moment.

gdb can't find source files

When I try to debug with gdb an executable compiled with distcc, gdb doesn't find the source of the object to be debugged, unless that source is in the directory from which I start gdb.

Unfortunately this is caused by a bug in gcc, which I hope will be fixed in a future release. gcc embeds the directory where the compiler (cc1) was run, when it really ought to record the directory the source came from.

You can work around it for now by using the "directory" command in gdb to tell it where to find the source, or by passing an absolute file name when compiling.

Tim Janik has an unofficial patch for distcc which works around this but I think I won't merge it because it's better to fix it in gcc.

This is Debian #148957.

There was a discussion about this bug on the gcc-patches mailing list. This can affect other programs which rely on debug stabs, such as addr2line, and it results in object files not being byte-for-byte identical when they include the source directory. The same bug affects ccache.

TCP_CORK in linux-2.2

Linux 2.2 has a bug to do with TCP_CORK sockets getting stuck in the FIN_WAIT1 state. distcc 0.10 tries to work around it but it is not completely possible; if it causes trouble set DISTCC_CORK=0.

Hung sockets in Linux 2.5

distcc seems to produce a problem in Linux 2.5 where one machine thinks the socket is CLOSED, and the other thinks it is ESTABLISHED. As a result the transfer hangs.

The CONNECTED/ESTABLISHED state should *never* be reachable by a correct TCP implementation. distcc is triggering a bug in the 2.5 TCP stack, which was found and fixed in 2.5 in June 2003.

libtool and trouble building KDE

Trying to build KDE with make CC=distcc CXX=distcc -j5 fails with a libtool error.

The version of libtool included with some KDE releases is buggy.

The best workaround is to install distcc in "masquerade mode". Wayne Davison writes:

To get distcc going, just follow the instructions in the docs to setup a "masquerade" dir, add it to the start of your PATH, and then never fiddle with CC and/or CXX again (i.e. undefine them). Note that you need to be running a 2.x version of distcc for masquerade support to be integrated by default (e.g. 2.0.1). (Side note: if you're using a binary RPM of distcc, make sure that the maintainer has made a masquerade dir a part of the installed config. If not, ask them to do so, as it is the easiest way to make distcc compatible with the widest range of packages.)

To be explicit, do something very similar (or identical) to this:

# mkdir -p /usr/lib/distcc/bin
# cd /usr/lib/distcc/bin
# ln -s ../../../bin/distcc cc
# ln -s ../../../bin/distcc c++
# ln -s ../../../bin/distcc gcc
# ln -s ../../../bin/distcc g++

You can add links to any other compiler names you use on your system as well.

The other setup requirements remain unchanged: add DISTCC_HOSTS in your environment and run make with the -j5 (or whatever) option, perhaps by setting MAKEFLAGS in your environment.

Linux 2.2 makefile strangeness

Linux 2.2.21 cannot be built with distcc because of bugs in the kernel's Makefile. ($CC is set to the compiler name plus the computed options.) It may be possible to use distcc in masquerade mode.

Compiler command line parsing problems?

distcc parses the compiler command line to work out what operation is being invoked, and what are the input and output files. The semantics of gcc command lines is fairly complex, and has changed slightly over time. There may be some valid command lines that distcc understands differently to gcc, though none are known at the moment. These ought to cause the command to be run locally, but it is possible that it would cause a failure. Either case should be reported as a bug.

Can't handle local file access

distcc can't handle compilers that need to read other files from the local filesystem. This might be a problem with such things as profile-directed optimizers. distcc tries to detect such commands and run them locally, but there may be cases which are not handled properly.

Huge files

distcc's protocol and file IO would probably have trouble with source or object files over 2GB in size. I've never heard of a .c or .o file that large, and I rather suspect gcc would not handle them well either.

KDE builds slowly with --enable-final

Bernardo Innocenti says

Using the --enable-final configure option of KDE makes distcc almost useless.

Frerich Raabe explains:

--enable-final makes the build system concatenate all sourcefiles in a directory (say, Konqueror's sourcefiles) into one big file.

Technically, this is achieved by creating a dummy file which simply includes every C++ sourcefile. The advantage of this is that the compile a- takes less time since there is only little scattered file opening involved and b- produces usually more optimized code, since the compiler can see more code at once and thus there are more chances to optimize. Of course this eats a lot more memory, but that is not an issue nowadays.

Now, it's clear why this makes distcc useless: there is just one huge file per project, and outsourcing that file via distcc to other nodes will just delay the build since the sourcecode (and it's a lot) has to be transferred over the network, and there is no way to pararellize this.

To avoid this, configure with --disable-final.

C++ code that uses #pragma implementation doesn't seem to work properly.

That pragma can't work with distcc because it introduces dependencies between the source and local filenames. It is strongly deprecated in gcc and there are no plans to support it in distcc.

Data corruption in compiles

Typical symptoms include linker errors, weird syntax errors or compiler crashes, caused by corrupt object or source files.

This has occurred several times in the past, typically because of kernel bugs such as Gentoo #36320. See if you can reproduce the problem using a standard kernel.org kernel.

Linux kernel panic using gigabit ethernet

There is a bug in the Linux 2.4.26 kernel [Google groups thread] that is triggered by using distcc. It is timing-related and seems more likely to occur with a gigabit network adapter.

This patch may fix the problem. If it doesn't, please report your problem to the kernel mailing list.

You may be able to avoid it by setting these environment variables on both the client and the server:

DISTCC_MMAP=0 DISTCC_SENDFILE=0

This bug is present in the Fedora Core 1 kernel and is Red Hat bug #114192.

Sun Workshop CC does not work with distcc

I am trying to use distcc on a network of Solaris 2.7 workstations and I also ran into this problem. I modified the src just like you did but I still have problems compiling certain C++ files - specifically those that include STL headers.

Has anyone figured out how to prevent the re-inclusion of the headers?

P. Christeas says:

After some time, the use of distcc with SunWS seems an unresolved issue. Of course, I exclude any attempt to modify the STL headers (which in fact are Sun's version of STL headers). The correct statement is that _Sun's CC does not behave correctly when the preprocessor is involved as a separate process_.

This compiler should still be marked as 'unsupported'. The only way (I know of) to make some use of a compile farm is to exclusively mark the few files that *do* compile, and send those through distcc. Hint: it seems that templates and CORBA implementation source do generally break the precompiler.

So Sun CC will not work for C++ with distcc, only for C.

configure has trouble when hosts are down

I'm having a strange problem. When no distcc-server is available and distcc decides to run a task locally, it fails.

configure:5648: checking for i386-redhat-linux-gcc-3.3.2 option to produce PIC
configure:5825: result: -fPIC
configure:5833: checking if i386-redhat-linux-gcc-3.3.2 PIC flag -fPIC works
configure:5854: i386-redhat-linux-gcc-3.3.2 -c -O2 -march=i386
-mcpu=i686 -fPIC -DPIC conftest.c >&5
distcc[32203] (dcc_build_somewhere) Warning: failed to distribute, running locally instead
configure:5858: $? = 0
configure:5866: result: no

For some reason configure thinks -fPIC is not supported although it works if a distcc-server is started. This causes some software to not work when build with distcc (but without distcc-servers). If build without distcc, it works (as -fPIC is supported).

What could be the cause ? I'm running the latest distcc.

autoconf interprets any message from the compiler as a failure for some tests, even if compilation succeeds. This is fixed in distcc 2.18 by always building autoconf tests locally.

distcc only listens for IPv6 connections on BSD

I use distcc from NetBSD's pkgsrc, which sets --enable-rfc2553 by default. When distccd is run as "distccd --daemon --user nobody", distccd seems to *only* be listening on an IPv6 socket.

By default some BSD systems do not allow applications to accept both IPv4 and IPv6 connections through a single server socket. See this message.

There are several options

  1. Don't build distcc with the --enable-rfc2553 option unless you need to support IPv6.
  2. Tell distcc to explicitly listen on either the IPv4 or IPv6 address, unless you need to accept connections over both protocols.
  3. Set the net.inet6.ip6.v6only sysctl to 0. (This affects all programs on the system, see the BSD manual for details.)
  4. Run two copies of distcc listening on both ports.

distcc fails with "No locks available"

This can happen if your home directory is on an NFS filesystem and NFS locking is not working. Locking in NFS is supported by a separate protocol and daemon which can be down even if other file operations are working OK.

To fix this, either fix NFS locking on your system, or set DISTCC_DIR to point to a local disk. If your system doesn't have a local hard disk you can just use tmpfs or something similar, because none of the files in that directory need to persist across reboots.

How to stop distcc using a particular machine?

I want to stop my machine accepting distcc jobs because I need it for something else.

The easiest way is to just shut down the distccd server. When it comes back up, clients will start using it again.

distcc only builds on one machine at a time

If I set DISTCC_HOSTS="remote_host localhost" then the project seems to be compiled only on the remote host (I see traces in ethereal and compilation is slow).

You are probably not using the -j option to make or scons, so it's only compiling one file at a time. Only the first host in the list will be used in this case.

Errors with temporary files on Cygwin

Some Windows compilers can't handle the default TMPDIR setting when distcc is run under Cygwin. To fix this, put something like export TMPDIR=c:/temp in /etc/profile.

Server won't start on Windows 98 or ME

For some reason the server does not work properly on Windows 98 unless it is invoked with --no-detach.

Make fails with "file not found"

If Make works for non-parallel builds, but fails when you use j and distcc, then there is probably a concurrency bug in your Makefile. It is similar to a threading bug in C, C++ or Java when a program is run on a multiprocessor system.

Sometimes it will work with -j without distcc, but fail when you use distcc. This is probably because distcc lets the compilation run faster and therefore more jobs run in parallel.

You need to just fix your makefile, or not build that particular directory in parallel. It is very unlikely this is a bug in GNU make or distcc.

Internet-wide distributed compilation

I'm a newbie with distcc and linux. I have been able to bootstrap (with lots of effort) Gentoo. I'm having only one computer on my lan that I control, so can't install distcc on the other host. I'm looking for a WAN of public distcc (I would grant access to mine also). I would like have a vast distributed network of distcc that would be public. It may use some ssh. I don't even know if this possible.

Won't it be faster then a laptop and a desktop if we have N hosts? I have heard of sub-ether that create a virtual NIC -- as far as I could understand. Any body know if it work with distcc?

This could be done, but some preparatory work is needed:

This really has to be done across SSH or a VPN; sending commands across the public net unencrypted would be insanely insecure.

Connections across the public internet are slower than on a LAN in both throughput and bandwidth. It's probably only feasible if the machines involved are on the same continent (preferably the same state) and have at least 512kbit connections.

The more serious problem is compiling on possibly untrusted machines. You need to assume that anyone who sends jobs can take over control of the user running distcc: if it's run within a UML instance or some similar sandbox, and each user has their own instance, that might be OK. Clients also need to implicitly trust all the servers not to give them corrupted or malicious data back.

There is also the organizational issue of just locating machines to use and the right public key to get into them.

Probably the best way to prototype this is to find a few friends who live in the same country. Set up ssh access into each others machines, and run distcc over that to try compilation. Please report your results to the distcc mailing list. If this works well, then we can look at scaling it up to run on larger groups or between potentially untrusted machines.

What is the relationship between Apple Xcode and distcc?

Apple's Xcode development kit includes a fork of an old version of distcc, plus Apple patches to locate machines using Rendezvous and a small GUI to configure it.

The source is available from opensource.apple.com.

How can I avoid compiling on workstations when they're in use

This watch-ssaver script from DMUCS enables distcc only when the screensaver is running. distcc-3.4/doc/web/favicon.ico000066400000000000000000000025761404653710500163130ustar00rootroot00000000000000h( ßâàluuOs[•°ŸRƒoSšw‹„ÈÌÉdzt|‡axq‚–Œ[’|„³•Nœoìóîëñí|¨—ÔáÙ¥Á°æçèäéæA’b@’aâãäàåâ¿ÏÄ »¨ÓæÜÒàÛÏ䨥Œ²µ·arhUœmjªc‹qïôòTieÔäÚýþýd y«¢üüüE—gãîæC•eMa^âìådrh¢À®@“bõöõáääž¼ªóôóÜæß“Á©ÙÞÜíîíkš}ÕÞØDm¯Äµy±ºÏÇ‘¬šn‚}Ùåà’Á¢EQPd¡z»ÕÅž¤¤]¡só÷ôò÷óÜéàñóò°ÉºCVUw’€Nj]åçæ;LM?_¬Î½[bgÉËÍw†}ÍÑÎe¥†êòïv­”^¡Ngaxƒ…†™øúúIc\W˜n¡«¥?‘`qž‚ÇÌÌÖÜØS…q®¶¶fopr‡yAiUšzËÐÍ>eK¨Á·ðõóU›mަ–kyoÿÿÿþÿþ¾ÕÇ\¤{ûûûµŸúûúA”cˆŒª²¬„ˆŒðñðRaV›¤ÆÑÉÈËË8`Fíôñt—€x¯•ýþþÑ䨗§ððñîðïêêëÓÞר²ŸÇ³žÅ²æèçz¤Š‹±¢wwwwwwwwwwwwwwwwwwwwKy|g<–2O6’wwwz,.~3fU@wwˆ]>oŠ”V“[n^9wwrjADsb‹\ —%wwe!Yp;4}+aR :Nww„1v€Z•7{‚ ƒSwwWXŽ lFI†wwwkCc_ &/PT`h5wwwxŒE#J"tG)d H'wwwww(L0M-?8wwwwwwwww}*miwwwwwwwwwuq‡Q…wwwwwwwww‘‰$B=wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwdistcc-3.4/doc/web/index.html000066400000000000000000000210151404653710500161540ustar00rootroot00000000000000 distcc: a fast, free distributed C/C++ compiler

distcc: a fast, free distributed C/C++ compiler

Speed, it seems to me, provides the one genuinely modern pleasure.
— Aldous Huxley

distcc is a program to distribute builds of C, C++, Objective C or Objective C++ code across several machines on a network. distcc should always generate the same results as a local build, is simple to install and use, and is usually much faster than a local compile.

distcc does not require all machines to share a filesystem, have synchronized clocks, or to have the same libraries or header files installed. They can even have different processors or operating systems, if cross-compilers are installed.

Just wanted to drop you a line to say that we are now using distcc at work and it is excellent. We have a rack of opteron machines that we use for computational tasks and we are now using them as a compile farm to compile our ~1MLOC C++ tree (which can take an hour on a single CPU to recompile if we change certain header files). We tried using Sun's grid engine to do this (we already use it to schedule our computational jobs), but the combination of its polled operation and the overhead of NFS led to little improvement (and greatly stressed our network). With distcc compile times are way down and my productivity has greatly improved; the two best features for me are its low impact on the network and its simplicity.

Thanks a lot for a great tool! — Jeremy Barnes

60-second instructions:

  1. For each machine, download distcc unpack, and do
    ./configure && make && sudo make install
  2. On each of the servers, run distccd --daemon, with --allow options to restrict access.
  3. Put the names of the servers in your environment:
    export DISTCC_POTENTIAL_HOSTS='localhost red green blue'
  4. Build!
    Wrap your build command in the "pump" script and use "distcc" as your C compiler:
    cd ~/work/myproject; pump make -j8 CC=distcc

For more detailed installation instructions, see the INSTALL file.

Picture of distcc monitor window

distcc is developed on GNU/Linux, but has been reported to work on other systems including FreeBSD, NetBSD, Darwin, Solaris, HP-UX, IRIX, Cygwin and BSD/OS.

distcc sends the complete preprocessed source code across the network for each job, so all it requires of the volunteer machines is that they be running the distccd daemon, and that they have an appropriate compiler installed.

distcc is not itself a compiler, but rather a front-end to the GNU C/C++ compiler (gcc) and LLVM compiler (clang). (There is preliminary support for some other compilers but the main focus is gcc.) Almost all gcc options and features work as normal.

distcc is designed to be used with the -j parallel-build feature in GNU Make or SCons, or other build tools. Shipping files across the network takes time, but few cycles on the client machine. Any files that can be built remotely are essentially "for free" in terms of client CPU.

distcc has been under development since early 2002. It reliably and successfully compiles large, complex free and proprietary software systems. Programs known to build correctly with distcc include the Linux kernel, rsync, KDE, GNOME (via GARNOME), Samba and Ethereal.

distcc is nearly linearly scalable for small numbers of machines: Building Linux 2.4.19 on a single 1700MHz Pentium IV machine with distcc 0.15 takes 6 minutes, 45 seconds. Using distcc across three such machines on a 100Mbps switch takes only 2 minutes, 30 seconds: 2.6x faster. The (unreachable) theoretical maximum speedup is 3.0x, so in this case distcc scales with 89% efficiency.

You don't need a lot of machines to benefit: a laptop and a single desktop is much faster than a laptop alone.

There are several tools available separately that enhance or complement distcc:

  • ccache caches compiler output to accelerate builds.
  • dmucs helps distcc select appropriate servers.
  • ccontrol gives centralized control of parallelism, caching and distribution even while the build is running.
  • crosstool automates building cross-compilation toolchains.
  • distccWebView is a CGI to show which of your servers are up and running.
  • tcpbalance is a load-balancing TCP proxy written in Erlang that works well with distcc.

Copyright © 2002–2004, 2006 Martin Pool.

Send comments to distcc(at)lists.samba.org distcc-3.4/doc/web/man/000077500000000000000000000000001404653710500147335ustar00rootroot00000000000000distcc-3.4/doc/web/man/distcc_1.html000066400000000000000000001207151404653710500173200ustar00rootroot00000000000000 distcc manual page

distcc manual page

Table of Contents


NAME

distcc - distributed C/C++/ObjC compiler with distcc-pump extensions

SYNOPSIS

distcc <compiler> [COMPILER OPTIONS]

distcc [COMPILER OPTIONS]

<compiler> [COMPILER OPTIONS]

distcc [DISTCC OPTIONS]

DESCRIPTION

distcc distributes compilation of C code across several machines on a network. distcc should always generate the same results as a local compile, it is simple to install and use, and it is often much faster than a local compile.

This version incorporates plain distcc as well as an enhancement called pump mode or distcc-pump.

For each job, distcc in plain mode sends the complete preprocessed source code and compiler arguments across the network from the client to a compilation server. In pump mode, distcc sends the source code and recursively included header files (excluding those from the default system header directories), so that both preprocessing and compilation can take place on the compilation servers. This speeds up the delivery of compilations by up to an order of magnitude over plain distcc.

Compilation is driven by a client machine, which is typically the developer's workstation or laptop. The distcc client runs on this machine, as does make, the preprocessor (if distcc's pump mode is not used), the linker, and other stages of the build process. Any number of volunteer machines act as compilation servers and help the client to build the program, by running the distccd(1) daemon, C compiler and assembler as required.

distcc can run across either TCP sockets (on port 3632 by default), or through a tunnel command such as ssh(1). For TCP connections the volunteers must run the distccd(1) daemon either directly or from inetd. For SSH connections distccd must be installed but should not be listening for connections.

TCP connections should only be used on secure networks because there is no user authentication or protection of source or object code. SSH connections are typically 25% slower because of processor overhead for encryption, although this can vary greatly depending on CPUs, network and the program being built.

distcc is intended to be used with GNU Make's -j option, which runs several compiler processes concurrently. distcc spreads the jobs across both local and remote CPUs. Because distcc is able to distribute most of the work across the network, a higher concurrency level can be used than for local builds. As a rule of thumb, the -j value should be set to about twice the total number of available server CPUs but subject to client limitations. This setting allows for maximal interleaving of tasks being blocked waiting for disk or network IO. Note that distcc can also work with other build control tools, such as SCons, where similar concurrency settings must be adjusted.

The -j setting, especially for large values of -j, must take into account the CPU load on the client. Additional measures may be needed to curtail the client load. For example, concurrent linking should be severely curtailed using auxiliary locks. The effect of other build activity, such as Java compilation when building mixed code, should be considered. The --localslots_cpp parameter is by default set to 16. This limits the number of concurrent processes that do preprocessing in plain distcc (non-pump) mode. Therefore, larger -j values than 16 may be used without overloading a single-CPU client due to preprocessing. Such large values may speed up parts of the build that do not involve C compilations, but they may not be useful to distcc efficiency in plain mode.

In contrast, using pump mode and say 40 servers, a setting of -j80 or larger may be appropriate even for single-CPU clients.

It is strongly recommended that you install the same compiler version on all machines participating in a build. Incompatible compilers may cause mysterious compile or link failures.

QUICKSTART


1
For each machine, download distcc, unpack, and install.
2
On each of the servers, run distccd --daemon with --allow options to restrict access.
3
Put the names of the servers in your environment:
    $ export DISTCC_HOSTS='localhost red green blue'
4
Build!
    $ make -j8 CC=distcc

QUICKSTART FOR DISTCC-PUMP MODE

Proceed as above, but in Step 3, specify that the remote hosts are to carry the burden of preprocessing and that the files sent over the network should be compressed:
    $ export DISTCC_HOSTS='--randomize localhost red,cpp,lzo green,cpp,lzo blue,cpp,lzo'
The --randomize option enforces a uniform usage of compile servers. While you will get some benefit from distcc's pump mode with only a few servers, you get increasing benefit with more server CPUs (up to the hundreds!). Wrap your build inside the pump command, here assuming 10 servers:
    $ pump make -j20 CC=distcc

QUICKSTART FOR DISTCC-GSSAPI MODE

Proceed as per the QUICKSTART but in Step 3, specify that the remote hosts are to mutually authenticate with the client:
    $ export DISTCC_HOSTS='--randomize localhost red,auth green,auth blue,auth'
If distccd runs under a specific principal name then execute the following command prior to step 4:
    export DISTCC_PRINICIPAL=<name>

HOW PLAIN (NON-PUMP) DISTCC WORKS

distcc only ever runs the compiler and assembler remotely. With plain distcc, the preprocessor must always run locally because it needs to access various header files on the local machine which may not be present, or may not be the same, on the volunteer. The linker similarly needs to examine libraries and object files, and so must run locally.

The compiler and assembler take only a single input file (the preprocessed source) and produce a single output (the object file). distcc ships these two files across the network and can therefore run the compiler/assembler remotely.

Fortunately, for most programs running the preprocessor is relatively cheap, and the linker is called relatively infrequent, so most of the work can be distributed.

distcc examines its command line to determine which of these phases are being invoked, and whether the job can be distributed.

HOW DISTCC-PUMP MODE WORKS

In pump mode, distcc runs the preprocessor remotely too. To do so, the preprocessor must have access to all the files that it would have accessed if had been running locally. In pump mode, therefore, distcc gathers all of the recursively included headers, except the ones that are default system headers, and sends them along with the source file to the compilation server.

In distcc-pump mode, the server unpacks the set of all source files in a temporary directory, which contains a directory tree that mirrors the part of the file system that is relevant to preprocessing, including symbolic links.

The compiler is then run from the path in the temporary directory that corresponds to the current working directory on the client. To find and transmit the many hundreds of files that are often part of a single compilation, pump mode uses an incremental include analysis algorithm. The include server is a Python program that implements this algorithm. The pump command starts the include server so that throughout the build it can answer include queries by distcc commands.

The include server uses static analysis of the macro language to deal with conditional compilation and computed includes. It uses the property that when a given header file has already been analyzed for includes, it is not necessary to do so again if all the include options (-I's) are unchanged (along with other conditions).

For large builds, header files are included, on average, hundreds of times each. With distcc-pump mode each such file is analyzed only a few times, perhaps just once, instead of being preprocessed hundreds of times. Also, each source or header file is now compressed only once, because the include server memoizes the compressed files. As a result, the time used for preparing compilations may drop by up to an order of magnitude over the preprocessing of plain distcc.

Because distcc in pump mode is able to push out files up to about ten times faster, build speed may increase 3X or more for large builds compared to plain distcc mode.

RESTRICTIONS FOR PUMP MODE


Using pump mode requires both client and servers to use release 3.0 or later of distcc and distccd (respectively).

The incremental include analysis of distc-pump mode rests on the fundamental assumption that source and header files do not change during the build process. A few complex build systems, such as that for Linux kernel 2.6, do not quite satisfy this requirement. To overcome such issues, and other corner cases such as absolute filepaths in includes, see the include_server(1) man page.

Another important assumption is that the include configuration of all machines must be identical. Thus the headers under the default system path must be the same on all servers and all clients. If a standard GNU compiler installation is used, then this requirement applies to all libraries whose header files are installed under /usr/include or /usr/local/include/. Note that installing software packages often lead to additional headers files being placed in subdirectories of either.

If this assumption does not hold, then it is possible to break builds with distcc-pump mode, or worse, to get wrong results without warning. Presently this condition is not verified, and it is on our TODO list to address this issue.

An easy way to guarantee that the include configurations are identical is to use a cross-compiler that defines a default system search path restricted to directories of the compiler installation.

See the include_server(1) manual for more information on symptoms and causes of violations of distcc-pump mode assumptions.

HOW DISTCC-GSSAPI MODE WORKS


In this mode distcc will use the GSS-API framework to access the currently configured security mechanism and perform mutual authentication with the daemon.

OPTION SUMMARY

Most options passed to distcc are interpreted as compiler options. The following options are understood by distcc itself. If any of these options are specified, distcc will not invoke the compiler.
--help
Displays summary instructions.

--version
Displays the distcc client version.

--show-hosts
Displays the host list that distcc would use. See the Host Specifications section.

--scan-includes
Displays the list of files that distcc would send to the remote machine, as computed by the include server. This is a conservative (over-)approximation of the files that would be read by the C compiler. This option only works in pump mode. See the "How Distcc-pump Mode Works" section for details on how this is computed.
    The list output by distcc --scan-includes will contain one entry per line. Each line contains a category followed by a path. The category is one of FILE, SYMLINK, DIRECTORY, or SYSTEMDIR:

    FILE indicates a source file or header file that would be sent to the distcc server host.

    SYMLINK indicates a symbolic link that would be sent to the distcc server host.

    DIRECTORY indicates a directory that may be needed in order to compile the source file. For example, a directory "foo" may be needed because of an include of the form #include "foo/../bar.h". Such directories would be created on the distcc server host.

    SYSTEMDIR indicates a system include directory, i.e. a directory which is on the compiler's default include path, such as "/usr/include"; such directories are assumed to be present on the distcc server host, and so would not be sent to the distcc server host.
-j
Displays distcc's concurrency level, as calculated from the host list; it is the maximum number of outstanding jobs issued by this client to all servers. By default this will be four times the number of hosts in the host list, unless the /LIMIT option was used in the host list. See the Host Specifications section.

--show-principal
Displays the name of the distccd security principal extracted from the environment. This option is only available if distcc was compiled with the --with-auth configure option.

INSTALLING DISTCC

There are three different ways to call distcc, to suit different circumstances:

    distcc can be installed under the name of the real compiler, to intercept calls to it and run them remotely. This "masqueraded" compiler has the widest compatibility with existing source trees, and is convenient when you want to use distcc for all compilation. The fact that distcc is being used is transparent to the makefiles.

    distcc can be prepended to compiler command lines, such as "distcc cc -c hello.c" or CC="distcc gcc". This is convenient when you want to use distcc for only some compilations or to try it out, but can cause trouble with some makefiles or versions of libtool that assume $CC does not contain a space.

    Finally, distcc can be used directly as a compiler. "cc" is always used as the name of the real compiler in this "implicit" mode. This can be convenient for interactive use when "explicit" mode does not work but is not really recommended for new use.

Remember that you should not use two methods for calling distcc at the same time. If you are using a masquerade directory, don't change CC and/or CXX, just put the directory early on your PATH. If you're not using a masquerade directory, you'll need to either change CC and/or CXX, or modify the makefile(s) to call distcc explicitly.

MASQUERADING

The basic idea is to create a "masquerade directory" which contains links from the name of the real compiler to the distcc binary. This directory is inserted early on the PATH, so that calls to the compiler are intercepted and distcc is run instead. distcc then removes itself from the PATH to find the real compiler.

For example:

    # mkdir /usr/lib/distcc/bin
    # cd /usr/lib/distcc/bin
    # ln -s ../../../bin/distcc gcc
    # ln -s ../../../bin/distcc cc
    # ln -s ../../../bin/distcc g++
    # ln -s ../../../bin/distcc c++

Then, to use distcc, a user just needs to put the directory /usr/lib/distcc/bin early in the PATH, and have set a host list in DISTCC_HOSTS or a file. distcc will handle the rest.

Note that this masquerade directory must occur on the PATH earlier than the directory that contains the actual compilers of the same names, and that any auxiliary programs that these compilers call (such as as or ld) must also be found on the PATH in a directory after the masquerade directory since distcc calls out to the real compiler with a PATH value that has all directory up to and including the masquerade directory trimmed off.

It is possible to get a "recursion error" in masquerade mode, which means that distcc is somehow finding itself again, not the real compiler. This can indicate that you have two masquerade directories on the PATH, possibly because of having two distcc installations in different locations. It can also indicate that you're trying to mix "masqueraded" and "explicit" operation.

Recursion errors can be avoided by using shell scripts instead of links. For example, in /usr/lib/distcc/bin create a file cc which contains:

    #!/bin/sh
    distcc /usr/bin/gcc "$@"

In this way, we are not dependent on distcc having to locate the real gcc by investigating the PATH variable. Instead, the compiler location is explicitly provided.

USING DISTCC WITH CCACHE

ccache is a program that speeds software builds by caching the results of compilations. ccache is normally called before distcc, so that results are retrieved from a normal cache. Some experimentation may be required for idiosyncratic makefiles to make everything work together.

The most reliable method is to set


CCACHE_PREFIX="distcc"

This tells ccache to run distcc as a wrapper around the real compiler. ccache still uses the real compiler to detect compiler upgrades.

ccache can then be run using either a masquerade directory or by setting


CC="ccache gcc"

As of version 2.2, ccache does not cache compilation from preprocessed source and so will never get a cache hit if it is run from distccd or distcc. It must be run only on the client side and before distcc to be any use.
distcc's pump mode is not compatible with ccache.

HOST SPECIFICATIONS

A "host list" tells distcc which machines to use for compilation. In order, distcc looks in the $DISTCC_HOSTS environment variable, the user's $DISTCC_DIR/hosts file, and the system-wide host file. If no host list can be found, distcc emits a warning and compiles locally.

The host list is a simple whitespace separated list of host specifications. The simplest and most common form is a host names, such as

    localhost red green blue

distcc prefers hosts towards the start of the list, so machines should be listed in descending order of speed. In particular, when only a single compilation can be run (such as from a configure script), the first machine listed is used (but see --randomize below).

Placing localhost at the right point in the list is important to getting good performance. Because overhead for running jobs locally is low, localhost should normally be first. However, it is important that the client have enough cycles free to run the local jobs and the distcc client. If the client is slower than the volunteers, or if there are many volunteers, then the client should be put later in the list or not at all. As a general rule, if the aggregate CPU speed of the client is less than one fifth of the total, then the client should be left out of the list.

If you have a large shared build cluster and a single shared hosts file, the above rules would cause the first few machines in the hosts file to be tried first even though they are likely to be busier than machines later in the list. To avoid this, place the keyword --randomize into the host list. This will cause the host list to be randomized, which should improve performance slightly for large build clusters.

There are two special host names --localslots and --localslots_cpp which are useful for adjusting load on the local machine. The --localslots host specifies how many jobs that cannot be run remotely that can be run concurrently on the local machine, while --localslots_cpp controls how many preprocessors will run in parallel on the local machine. Tuning these values can improve performance. Linking on large projects can take large amounts of memory. Running parallel linkers, which cannot be executed remotely, may force the machine to swap, which reduces performance over just running the jobs in sequence without swapping. Getting the number of parallel preprocessors just right allows you to use larger parallel factors with make, since the local machine now has some mechanism for measuring local resource usage.

Finally there is the host entry

Performance depends on the details of the source and makefiles used for the project, and the machine and network speeds. Experimenting with different settings for the host list and -j factor may improve performance.

The syntax is

DISTCC_HOSTS = HOSTSPEC ...
HOSTSPEC = LOCAL_HOST | SSH_HOST | TCP_HOST | OLDSTYLE_TCP_HOST
| GLOBAL_OPTION
| ZEROCONF
LOCAL_HOST = localhost[/LIMIT]
| --localslots=<int>
| --localslots_cpp=<int>
SSH_HOST = [USER]@HOSTID[/LIMIT][:COMMAND][OPTIONS]
TCP_HOST = HOSTID[:PORT][/LIMIT][OPTIONS]
OLDSTYLE_TCP_HOST = HOSTID[/LIMIT][:PORT][OPTIONS]
HOSTID = HOSTNAME | IPV4 | IPV6
OPTIONS = ,OPTION[OPTIONS]
OPTION = lzo | cpp | auth
GLOBAL_OPTION = --randomize
ZEROCONF = +zeroconf

Here are some individual examples of the syntax:

localhost
The literal word "localhost" is interpreted specially to cause compilations to be directly executed, rather than passed to a daemon on the local machine. If you do want to connect to a daemon on the local machine for testing, then give the machine's IP address or real hostname. (This will be slower.)
IPV6
A literal IPv6 address enclosed in square brackets, such as [::1]
IPV4
A literal IPv4 address, such as 10.0.0.1
HOSTNAME
A hostname to be looked up using the resolver.
:PORT
Connect to a specified decimal port number, rather than the default of 3632.
@HOSTID
Connect to the host over SSH, rather than TCP. Options for the SSH connection can be set in ~/.ssh/config
USER@
Connect to the host over SSH as a specified username.
:COMMAND
Connect over SSH, and use a specified path to find the distccd server. This is normally only needed if for some reason you can't install distccd into a directory on the default PATH for SSH connections. Use this if you get errors like "distccd: command not found" in SSH mode.
/LIMIT
A decimal limit can be added to any host specification to restrict the number of jobs that this client will send to the machine. The limit defaults to four per host (two for localhost), but may be further restricted by the server. You should only need to increase this for servers with more than two processors.
,lzo
Enables LZO compression for this TCP or SSH host.
,cpp
Enables distcc-pump mode for this host. Note: the build command must be wrapped in the pump script in order to start the include server.
,auth
Enables GSSAPI-based mutual authentication for this host.
--randomize
Randomize the order of the host list before execution.
+zeroconf
This option is only available if distcc was compiled with Avahi support enabled at configure time. When this special entry is present in the hosts list, distcc will use Avahi Zeroconf DNS Service Discovery (DNS-SD) to locate any available distccd servers on the local network. This avoids the need to explicitly list the host names or IP addresses of the distcc server machines. The distccd servers must have been started with the "--zeroconf" option to distccd. An important caveat is that in the current implementation, pump mode (",cpp") and compression (",lzo") will never be used for hosts located via zeroconf.

Here is an example demonstrating some possibilities:

    localhost/2 @bigman/16:/opt/bin/distccd oldmachine:4200/1
    # cartman is down
    distant/3,lzo

Comments are allowed in host specifications. Comments start with a hash/pound sign (#) and run to the end of the line.

If a host in the list is not reachable distcc will emit a warning and ignore that host for about one minute.

COMPRESSION

The lzo host option specifies that LZO compression should be used for data transfer, including preprocessed source, object code and error messages. Compression is usually economical on networks slower than 100Mbps, but results may vary depending on the network, processors and source tree.

Enabling compression makes the distcc client and server use more CPU time, but less network traffic. The added CPU time is insignificant for pump mode. The compression ratio is typically 4:1 for source and 2:1 for object code.

Using compression requires both client and server to use at least release 2.9 of distcc. No server configuration is required: the server always responds with compressed replies to compressed requests.

Pump mode requires the servers to have the lzo host option on.

SEARCH PATHS


If the compiler name is an absolute path, it is passed verbatim to the server and the compiler is run from that directory. For example:

    distcc /usr/local/bin/gcc-3.1415 -c hello.c

If the compiler name is not absolute, or not fully qualified, distccd's PATH is searched. When distcc is run from a masquerade directory, only the base name of the compiler is used. The client's PATH is used only to run the preprocessor and has no effect on the server's path.

TIMEOUTS


Both the distcc client and server impose timeouts on transfer of data across the network. This is intended to detect hosts which are down or unreachable, and to prevent compiles hanging indefinitely if a server is disconnected while in use. If a client-side timeout expires, the job will be re-run locally.

The timeouts are not configurable at present.

DIAGNOSTICS

Error messages or warnings from local or remote compilers are passed through to diagnostic output on the client.

distcc can supply extensive debugging information when the verbose option is used. This is controlled by the DISTCC_VERBOSE environment variable on the client, and the --verbose option on the server. For troubleshooting, examine both the client and server error messages.

EXIT CODES

The exit code of distcc is normally that of the compiler: zero for successful compilation and non-zero otherwise.

distcc distinguishes between "genuine" errors such as a syntax error in the source, and "accidental" errors such as a networking problem connecting to a volunteer. In the case of accidental errors, distcc will retry the compilation locally unless the DISTCC_FALLBACK option has been disabled.

If the compiler exits with a signal, distcc returns an exit code of 128 plus the signal number.

distcc internal errors cause an exit code between 100 and 127. In particular

100
General distcc failure.
101
Bad arguments.
102
Bind failed.
103
Connect failed.
104
Compiler crashed.
105
Out of memory.
106
Bad Host SPEC
107
I/O Error
108
Truncated.
109
Protocol Error.
110
The given compiler was not found on the remote host. Check that $CC is set appropriately and that it's installed in a directory on the search path for distccd.
111
Recursive call to distcc.
112
Failed to discard privileges.
113
Network access denied.
114
In use by another process.
115
No such file.
116
No hosts defined and fallbacks disabled.
118
Timeout.
119
GSS-API - Catchall error code for GSS-API related errors.

FILES

If $DISTCC_HOSTS is not set, distcc reads a host list from either $DISTCC_DIR/hosts or a system-wide configuration file set at compile time. The file locations are shown in the output from distcc --help

distcc creates a number of temporary and lock files underneath the temporary directory.

ENVIRONMENT VARIABLES

distcc's behaviour is controlled by a number of environment variables. For most cases nothing need be set if the host list is stored in a file.
DISTCC_HOSTS
Space-separated list of volunteer host specifications.
DISTCC_VERBOSE
If set to 1, distcc produces explanatory messages on the standard error stream or in the log file. This can be helpful in debugging problems. Bug reports should include verbose output.
DISTCC_LOG
Log file to receive messages from distcc itself, rather than stderr.
DISTCC_FALLBACK
By default distcc will compile locally if it fails to distribute a job to the intended machine, or if no host list can be found. If this variable is set to 0 then fallbacks are disabled and those compilations will simply fail. Note that this does not affect jobs which must always be local such as linking.
DISTCC_BACKOFF_PERIOD
Specifies how long (in seconds) distcc will avoid trying to use a particular compilation server after that server yields a compile failure. By default set to 60 seconds. To disable the backoff behavior altogether, set this to 0.
DISTCC_IO_TIMEOUT
Specifies how long (in seconds) distcc will wait before deciding a distributed job has timed out. If a distributed job is expected to takes a long time, consider increasing this value so the job does not time out and fallback to a local compile. By default set to 300 seconds.
DISTCC_PAUSE_TIME_MSEC
Specifies how long (in milliseconds) distcc will pause when all compilation servers are in use. By default set to 1000 milliseconds (1 second). Setting this to a smaller value (e.g. 10 milliconds) may improve throughput for some configurations, at the expense of increased CPU load on the distcc client machine.
DISTCC_SAVE_TEMPS
If set to 1, temporary files are not deleted after use. Good for debugging, or if your disks are too empty.
DISTCC_TCP_CORK
If set to 0, disable use of "TCP corks", even if they're present on this system. Using corks normally helps pack requests into fewer packets and aids performance. This should normally be left enabled.
DISTCC_SSH
Specifies the command used for opening SSH connections. Defaults to "ssh" but may be set to a different connection command such as "lsh" or "tsocks-ssh" that accepts a similar command line. The command is not split into words and is not executed through the shell.
DISTCC_SKIP_LOCAL_RETRY
If set, when a remote compile fails, distcc will no longer try to recompile that file locally.
DISTCC_DIR
Per-user configuration directory to store lock files and state files. By default ~/.distcc/ is used.
TMPDIR
Directory for temporary files such as preprocessor output. By default /tmp/ is used.
UNCACHED_ERR_FD
If set and if DISTCC_LOG is not set, distcc errors are written to the file descriptor identified by this variable. This variable is intended mainly for automatic use by ccache, which sets it to avoid caching transient errors such as network problems.
DISTCC_ENABLE_DISCREPANCY_EMAIL
If set, distcc sends an email when a compilation failed remotely, but succeeded locally. Built-in heuristics prevent some such discrepancy email from being sent if the problem is that a local file changed between the failing remote compilation and the succeeding local compilation.
DISTCC_MAX_DISCREPANCY
The maximum number of remote compilation failures allowed in pump mode before distcc switches to plain distcc mode. By default set to 1.
DCC_EMAILLOG_WHOM_TO_BLAME
The email address for discrepancy email; the default is "distcc-pump-errors".
DISTCC_PRINCIPAL
If set, specifies the name of the principal that distccd runs under, and is used to authenticate the server to the client. This environment variable is only used if distcc was compiled with the --with-auth configure option and the ,auth per host option is specified.

CROSS COMPILING

Cross compilation means building programs to run on a machine with a different processor, architecture, or operating system to where they were compiled. distcc supports cross compilation, including teams of mixed-architecture machines, although some changes to the compilation commands may be required.

The compilation command passed to distcc must be one that will execute properly on every volunteer machine to produce an object file of the appropriate type. If the machines have different processors, then simply using distcc cc will probably not work, because that will normally invoke the volunteer's native compiler.

Machines with the same CPU but different operating systems may not necessarily generate compatible .o files.

Several different gcc configurations can be installed side-by-side on any machine. If you build gcc from source, you should use the --program-suffix configuration options to cause it to be installed with a name that encodes the gcc version and the target platform.

The recommended convention for the gcc name is TARGET-gcc-VERSION such as i686-linux-gcc-3.2 . GCC 3.3 will install itself under this name, in addition to TARGET-gcc and, if it's native, gcc-VERSION and gcc .

The compiler must be installed under the same name on the client and on every volunteer machine.

BUGS

If you think you have found a distcc bug, please see the file reporting-bugs.txt in the documentation directory for information on how to report it.

Some makefiles have missing or extra dependencies that cause incorrect or slow parallel builds. Recursive make is inefficient and can leave processors unnecessarily idle for long periods. (See Recursive Make Considered Harmful by Peter Miller.) Makefile bugs are the most common cause of trees failing to build under distcc. Alternatives to Make such as SCons can give much faster builds for some projects.

Using different versions of gcc can cause confusing build problems because the header files and binary interfaces have changed over time, and some distributors have included incompatible patches without changing the version number. distcc does not protect against using incompatible versions. Compiler errors about link problems or declarations in system header files are usually due to mismatched or incorrectly installed compilers.

gcc's -MD option can produce output in the wrong directory if the source and object files are in different directories and the -MF option is not used. There is no perfect solution because of incompatible changes between gcc versions. Explicitly specifying the dependency output file with -MF will fix the problem.

TCP mode connections should only be used on trusted networks.

Including slow machines in the list of volunteer hosts can slow the build down.

When distcc or ccache is used on NFS, the filesystem must be exported with the no_subtree_check option to allow reliable renames between directories.

The compiler can be invoked with a command line gcc hello.c to both compile and link. distcc doesn't split this into separate parts, but rather runs the whole thing locally.

distcc-pump mode reverts to plain distcc mode for source files that contain includes with absolute paths (either directly or in an included file).

Due to limitations in gcc, gdb may not be able to automatically find the source files for programs built using distcc in some circumstances. The gdb directory command can be used. For distcc's plain (non-pump) mode, this is fixed in gcc 3.4 and later. For pump mode, the fix in gcc 3.4 does not suffice; we've worked around the gcc limitation by rewriting the object files that gcc produces, but this is only done for ELF object files, but not for other object file formats.

The .o files produced by discc in pump mode will be different from those produced locally: for non-ELF files, the debug information will specify compile directories of the server. The code itself should be identical.

For the ELF-format, distcc rewrites the .o files to correct compile directory path information. While the resulting .o files are not bytewise identical to what would have been produced by compiling on the local client (due to different padding, etc), they should be functionally identical.

In distcc-pump mode, the include server is unable to handle certain very complicated computed includes as found in parts of the Boost library. The include server will time out and distcc will revert to plain mode.

In distcc-pump mode, certain assumptions are made that source and header files do not change during the build. See discussion in section DISTCC DISCREPANCY SYMPTOMS of include_server(1().
Other known bugs may be documented on http://code.google.com/p/distcc/

AUTHOR

distcc was written by Martin Pool <mbp@sourcefrog.net>, with the co-operation of many scholars including Wayne Davison, Frerich Raabe, Dimitri Papadopoulos and others noted in the NEWS file. Please report bugs to <distcc@lists.samba.org>. See pump(1) for the authors of pump mode.

LICENCE

You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warrany. A copy of the GPL is included in the file COPYING.

SEE ALSO

distccd(1), pump(1), include_server(1), gcc(1), make(1), and ccache(1). http://code.google.com/p/distcc/ https://ccache.dev/
distcc-3.4/doc/web/man/distccd_1.html000066400000000000000000000344571404653710500174730ustar00rootroot00000000000000 distccd manual page

distccd manual page

Table of Contents


NAME

distccd - distributed C/C++ compiler server

SYNOPSIS

distccd --daemon [OPTIONS]

DESCRIPTION

distccd is the server for the distcc(1) distributed compiler. It accepts and runs compilation jobs for network clients.

distcc can run over either TCP or a connection command such as ssh(1). TCP connections are fast but relatively insecure. SSH connections are secure but slower.

For SSH connections, distccd must be installed on the volunteer but should not run as a daemon -- it will be started over SSH as needed. SSH connections have several advantages: neither the client nor server listens on any new ports; compilations run with the privileges of the user that requested them; unauthorized users cannot access the server; and source and output is protected in transit.

For TCP connections, distccd can run either from an inetd-style program, or as a standalone server. Standalone mode is recommended because it is slightly more efficient and allows distccd to regulate the number of incoming jobs. The --listen and --allow options can be used for simple IP-based access control.

distcc may be started either by root or any other user. If run by root, it gives away privileges and changes to the user specified by the --user option, or the user called "distcc", or the user called "nobody".

distccd does not have a configuration file; it's behaviour is controlled only by command-line options and requests from clients.

STANDALONE SERVER

The recommended method for running distccd is as a standalone server. distccd will listen for network connections and fork several child processes to serve them.

If you installed distcc using a packaged version you may be able to start the server using the standard mechanism for your operating system, such as

    # service distcc start

To start distccd as a standalone service, run a command like this either as root or an ordinary user:

    # distccd --daemon

RUNNING FROM INIT

distccd may be run as a standalone daemon under the control of another program like init(8) or daemontools. The super-server starts distccd when the system boots, and whenever it exits.

distccd should be started just as for a standalone server, except that the --no-detach option should be used so that the super-server can monitor it.

For example, to add distccd as a process to Linux sysvinit, add this line to /etc/inittab

    dscc:2345:respawn:/usr/local/bin/distccd --verbose --no-detach --daemon

RUNNING FROM INETD

distccd may be started from a network super-server such as inetd or xinetd. In this case inetd listens for network connections and invokes distccd when one arrives.

This is slightly less efficient than running a standalone distccd daemon. distccd is not able to regulate the number of concurrent jobs accepted, but there may be an option in your inetd configuration to do so.

For traditional Unix inetd, a line like this can be added to /etc/inetd.conf:

    distcc stream tcp nowait.6000 root /usr/local/bin/distccd distccd --inetd

inetd imposes a limit on the rate of connections to a service to protect against accidental or intentional overuse. The default in Linux NetKit inetd is 40 per minute, which is far too low for distccd. The .6000 option raises the limit to 6000 per minute.

TERMINATING DISTCCD

To shut down a standalone server, send a SIGTERM signal to the parent process. The most reliable way to do this from a script is to use the --pid-file option to record its process ID. Shutting down the server in this way should allow any jobs currently in progress to complete.

OPTIONS


--help
Display summary usage information.
--version
Shows the daemon version and exits.
-j, --jobs JOBS
Sets a limit on the number of jobs that can be accepted at any time. By default this is set to two greater than the number of CPUs on the machine, to allow for some processes being blocked on network IO. (Daemon mode only.)
-N, --nice NICENESS
Makes the daemon more nice about giving up the CPU to other tasks on the machine. NICENESS is an increment to the current priority of the process. The range of priorities depends on the operating system but is typically 0 to 20. By default the niceness is increased by 5.
-p, --port PORT
Set the TCP port to listen on, rather than the default of 3632. (Daemon mode only.)
--listen ADDRESS
Instructs the distccd daemon to listen on the IP address ADDRESS. This can be useful for access control on dual-homed hosts. (Daemon mode only.)
-P, --pid-file FILE
Save daemon process id to file FILE. (Daemon mode only.)
--user USER
If distccd gets executed as root, change to user USER.
-a, --allow IPADDR[/MASK]
Instructs distccd to accept connections from the IP address IPADDR. A CIDR mask length can be supplied optionally after a trailing slash, e.g. 192.168.0.0/24, in which case addresses that match in the most significant MASK bits will be allowed. If no --allow options are specified, distccd will exit immediately! Unauthorized connections are rejected by closing the TCP connection immediately. A warning is logged on the server but nothing is sent to the client.
--job-lifetime SECONDS
Kills a distccd job if it runs for more than SECONDS seconds. This prevents denial of service from clients that don't properly disconnect and compilers that fail to terminate. By default this is turned off.
--no-detach
Do not detach from the shell that started the daemon.
--no-fork
Don't fork children for each connection, to allow attaching gdb. Don't use this if you don't understand it!
--log-file FILE
Send messages to file FILE instead of syslog. Logging directly to a file is significantly faster than going via syslog and is recommended.
--log-level LEVEL
Set the minimum severity of error that will be included in the log file. Useful if you only want to see error messages rather than an entry for each connection. LEVEL can be any of the standard syslog levels, and in particular critical, error, warning, notice, info, or debug.
--log-stderr
Send log messages to stderr, rather than to a file or syslog. This is mainly intended for use in debugging. Do not use in inetd mode.
--verbose
Include debug messages in log. Equivalent to --log-level=debug
--wizard
Turn on all options appropriate for starting distccd under gdb: run as a daemon, log verbosely to stderr, and do not detach or fork. For wizards only.
--stats
Turn on the statistics HTTP server. By default it is off. (Daemon mode only.)
--stats-port PORT
Set the TCP port to listen on for HTTP requests, rather than the default of 3633. (Daemon mode only.)
--inetd
Serve a client connected to stdin/stdout. As the name suggests, this option should be used when distccd is run from within a super-server like inetd. distccd assumes inetd mode when stdin is a socket.
--daemon
Bind and listen on a socket, rather than running from inetd. This is used for standalone mode. distccd assumes daemon mode at startup if stdin is a tty, so --daemon should be explicitly specified when starting distccd from a script or in a non-interactive ssh connection.
--zeroconf
Register the availability of this distccd server using Avahi Zeroconf DNS Service Discovery (DNS-SD). This allows distcc clients on the local network to access this distccd server without explicitly listing its host name or IP address in their distcc host list: the distcc clients can just use "+zeroconf" in their distcc host lists. This option is only available if distccd was compiled with Avahi support enabled.
--auth
Perform GSS-API based mutual authentication. This option is only available if distccd was compiled with the --with-auth configure option.
--show-principal
Displays the name of the distccd security principal extracted from the environment. This option is only available if distccd was compiled with the --with-auth configure option.
--blacklist=FILE
Instruct distccd to reject connections from users whose principal names are listed in FILE. This option is only available if distccd was compiled with the --with-auth configure option and if distccd is run with the --auth option.
--whitelist=FILE
Instruct distccd to accept connections only from users whose principal names are listed in FILE. This option is only available if distccd was compiled with the --with-auth configure option and if distccd is run with the --auth option.

SEARCH PATHS


distcc can pass either a relative or an absolute name for the compiler to distccd. If distcc is given an explicit absolute compiler filename, that name is used verbatim on both the client and server. If the compiler name is not an absolute path, or if the client is used in masquerade mode, then the server's PATH is searched.

distccd inherits its search path from its parent process. By default distccd tries to remove directories that seem to contain distccd masquerade links, to guard against inadvertent recursion. The DISTCCD_PATH environment variable may be used to set the path.

The search path is logged when --verbose is given. In case of confusion, check the logs.

When distccd is run over ssh, the $HOME/.ssh/environment file may be useful in setting the path. See ssh(1).

DIAGNOSTICS

distccd logs messages to syslog's daemon facility by default, which normally writes to /var/log/daemon or /var/log/messages. Log messages can be sent to a different file using the --log-file option.

ENVIRONMENT VARIABLES


DISTCC_CMDLIST
If the environment variable DISTCC_CMDLIST is set, load a list of supported commands from the file named by DISTCC_CMDLIST, and refuse to serve any command whose last DISTCC_CMDLIST_MATCHWORDS last words do not match those of a command in that list. See the comments in src/serve.c.
DISTCC_CMDLIST_NUMWORDS
The number of words, from the end of the command, to match. The default is 1.
DISTCCD_PATH
When starting distccd, if this value is set it will be used unaltered for the command-execution PATH. The code that normally tries to remove masquerade directories from the path is skipped.
DISTCC_SAVE_TEMPS
If set to 1, temporary files are not deleted after use.

Note that DISTCC_LOG does not affect the log destination for the server.

DISTCC_TCP_DEFER_ACCEPT
On Linux, turn on the TCP_DEFER_ACCEPT socket option. Defaults to on.
TMPDIR
Directory for temporary files such as preprocessor output. By default /tmp/ is used.
DISTCCD_PRINCIPAL
If set, specifies the name of the principal that distccd runs under, and is used to authenticate with the client. This environment variable is only used if distccd was compiled with the --with-auth configure option and if distccd is run with the --auth option.

SEE ALSO

distcc(1), pump(1), include_server(1), gcc(1), make(1), and ccache(1) http://code.google.com/p/distcc/

BUGS

IP-based access control is not secure against attackers able to spoof TCP connections, and cannot discriminate different users on a client.

TCP connections are not secure against attackers able to observe or modify network traffic.

Because ccache does not cache compilation from .i files, it is not useful to call it from distccd.

LICENCE

You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warrany. A copy of the GPL is included in the file COPYING.

AUTHOR

distcc was written by Martin Pool <mbp@sourcefrog.net>, with the co-operation of many scholars including Wayne Davison, Frerich Raabe, Dimitri Papadopoulos and others noted in the NEWS file. See pump(1) for the authors of pump mode. Please report bugs to <distcc@lists.samba.org>.
distcc-3.4/doc/web/man/distccmon_text_1.html000066400000000000000000000052421404653710500210730ustar00rootroot00000000000000 distccmon-text manual page

distccmon-text manual page

Table of Contents


NAME


distccmon-text - Displays current compilation jobs in text form.

SYNTAX


distccmon-text [DELAY]

DESCRIPTION


Displays current compilation jobs in text form. distccmon-text must be run on the client machine, with the same setting for DISTCC_DIR (or home directory) as the user running the distcc client.

OPTIONS


DELAY
repeatedly updates after delay (fractional) seconds.

OUTPUT FORMAT


The output of distccmon-text contains one line for each job currently being compiled. Each line contains the following columns:

PID
ID of the distcc client process.
STATE
Identifies the phase of operation. In order these may be "Startup", "Blocked", "Connected", "Preprocess", "Conect", "Send", "Receive" and "Done".
FILE
The input filename, if known.
HOST[SLOT]
The compile hostname. May be followed in square brackets by the slot index for that host.

When a delay is specified, each block of output is terminated by a blank line.

EXAMPLES


To display currently active jobs (updated every second):


distccmon-text 1

To display the status once:


distccmon-text

AUTHORS


distcc was written by Martin Pool <mbp@sourcefrog.net>, with the co-operation of many scholars including Wayne Davison, Frerich Raabe, Dimitri Papadopoulos and others noted in the NEWS file. Please report bugs to <distcc@lists.samba.org>.

SEE ALSO


distccd(1), ccache(1), gcc(1), make(1) http://code.google.com/p/distcc/ https://ccache.dev/
distcc-3.4/doc/web/man/include_server_1.html000066400000000000000000000366351404653710500210670ustar00rootroot00000000000000 include_server manual page

include_server manual page

Table of Contents


NAME

include_server.py - conservative approximation of include dependencies for C/C++

SYNOPSIS

include_server --port INCLUDE_SERVER_PORT [OPTIONS]

DESCRIPTION

include_server.py starts an include server process. This process answers queries from distcc(1) clients about what files to include in C/C++ compilations. The include_server.py command itself terminates as soon as the include server has been spawned.

The INCLUDE_SERVER_PORT argument is the name of a socket used for all communication between distcc clients and the include server. The pump(1) command is responsible for creating the socket location, for passing it to this script, and for passing it to all distcc clients via the environment variable named INCLUDE_SERVER_PORT.

The protocol used by the include server uses distcc's RPC implementation. Each distcc request consists of (1) the current directory and (2) the list of arguments of the compilation command.

If the include server is able to process the request, then it answers the distcc client by sending a list of filepaths. The filepaths are those of the compressed source and header files found to be necessary for compilation through include analysis. The list also comprises symbolic links and even dummy files needed for the compilation server to construct an accurate replica of the parts of the filesystem needed for compilation. In this way, a needed header file like /path/foo.h is compressed, renamed, and stored in a temporary location, such as /dev/shm/tmpiAvfGv.include_server-9368-1/path/foo.h.lzo. The distcc client will pass these files on to a compilation server, where they will be uncompressed and mounted temporarily.

If the include server is not able to process the request, then it returns the empty list to the distcc client.

There are two kinds of failures that relate to the include server. The include server may fail to compute the includes or fail in other ways, see section INCLUDE SERVER SYMPTOMS. Also, the compilation on the remove server may fail due to inadequacy of the calculated include closure, but then succeed when locally retried, see section DISTCC DISCREPANCY SYMPTOMS.

OPTION SUMMARY

The following options are understood by include_server.py.
-dPAT, --debug_pattern=PAT
Bit vector for turning on warnings and debugging
1 = warnings
2 = trace some functions
other powers of two: see include_server/basics.py.
-e, --email
Send email to 'distcc-pump-errors' or if defined, the value of environment variable DISTCC_EMAILLOG_WHOM_TO_BLAME, when include server gets in trouble. The default is to not send email.
--email_bound NUMBER
Maximal number of emails to send (in addition to a final email). Default: 3.
--no-email
Do not send email. This is the default.
--path_observation_re=RE
Issue warning message whenever a filename is resolved to a realpath that is matched by RE, which is a regular expression in Python syntax. This is useful for finding out where files included actually come from. Use RE="" to find them all. Note: warnings must be enabled with at least -d1.
--pid_file FILEPATH
The pid of the include server is written to file FILEPATH. This allows a script such a pump to tear down the include server.
-s, --statistics
Print information to stdout about include analysis.
--stat_reset_triggers=LIST
Flush stat caches when the timestamp of any filepath in LIST changes or the filepath comes in or out of existence. LIST is a colon separated string of filepaths, possibly containing simple globs (as allowed by Python's glob module). Print a warning whenever such a change happens (if warnings are enabled). This option allows limited exceptions to distcc_pump's normal assumption that source files are not modified during the build.
-t, --time
Print elapsed, user, and system time to stderr.
--unsafe_absolute_includes
Do preprocessing on the compilation server even if includes of absolute filepaths are encountered. Normally the include-server will fall back on local preprocessing if it detects any absolute includes. Thus, this flag is useful for preventing such fallbacks when the absolute includes are a false alarm, either because the absolute include is discarded during preprocessing or because the absolutely included file exists on the compilation servers.

More precisely, with --unsafe_absolute_includes absolute includes are ignored for the purposes of gathering the include closure. Using this option may lead to incorrect results because (1) the header may actually be included on the compilation server and it may not be the same as on the client, (2) the include directives of the header are not further analyzed.

The option is useful for compiling code that has such hardcoded absolute locations of header files inside conditional directives (e.g. "#ifdef") that render the includes irrelevant. More precisely, these includes must be eliminated during preprocessing for the actual configuration. Then the question of existence of the header file is moot and the remote compilation is sound. This is often the case if such includes are meant for unusual configurations different from the actual configuration.
-v, --verify
Verify that files in CPP closure are contained in closure calculated by include processor.
-w, --write_include_closure
Write a .d_approx file which lists all the included files calculated by the include server; with -x, additionally write the included files as calculated by CPP to a .d_exact file.
-x, --exact_analysis
Use CPP instead, do not omit system headers files.

INCLUDE SERVER SYMPTOMS AND ISSUES


The most likely messages and warnings to come from the include processor are listed below.

Preprocessing locally. Include server not covering: Couldn't determine default system include directories
To determine the default system header directories, the include server runs the compiler once for each language needed during its session. This message indicates that the compiler specified to distcc is not present on the client.

Preprocessing locally. Include server not covering: Bailing out because include server spent more than ...s user time handling request
In uncommon situations, the include server fails to analyze very complicated macro expressions. The distcc client will use plain distcc mode.

Warning: Filepath must be relative but isn't
The include server does not accept absolute filepaths, such as /usr/include/stdio.h, in include directives, because there is no guarantee that this header on the compilation server machine will be the same as that on the client. The include server gives up analyzing the include closure. The distcc client cannot use pump-mode.

To overcome this problem in a not always reliable way, set the environment variable INCLUDE_SERVER_ARGS='--unsafe_absolute_includes' when invoking the pump script to pass the --unsafe_absolute_includes option to the include server.

Warning: Absolute filepath ... was IGNORED
The --unsafe_absolute_includes is in use. This situation happens under the same circumstances as when "Filepath must be relative but isn't" is issued, but in this case the include will provide an answer to the distcc client.

Warning: Path '/PATH/FILE' changed/came into existence/no longer exists
These warnings are issued when using stat reset triggers. Because /PATH/FILE changed, the include server clears its caches; the new version of the file (or the lack of it) renders the include analysis invalid. This message can usually be ignored; it does signify a somewhat precarious use of files by the build system. It is recommended to fix the build system so that files are not rewritten.

Warning: For translation unit ..., lookup of file ... resolved to ... whose realpath is ...
This warning occurs with --path_observation_re when a new realpath matching a source or header file is observed.

DISTCC DISCREPANCY SYMPTOMS


The interactions between the build system, distcc, and the include server is somewhat complex. When a distcc commands receives a failing compilation from the remote server it retries the compilation locally. This section discusses the causes of discrepancies between remote and local compilation. These are flagged by the demotion message:

__________Warning: ... pump-mode compilation(s) failed on server, but succeeded locally.
__________Distcc-pump was demoted to plain mode. See the Distcc Discrepancy Symptoms section in the include_server(1) man page.

The pump script issues this message at the end of the build. This means that for at least one distcc invocation a local compilation succeeded after the remote compilation failed. Each distcc invocation for which such a discrepancy occurred in turn also issues a message such as:

Warning: remote compilation of '...' failed, retried locally and got a different result.

The demotion makes subsequent distcc invocations use plain distcc mode. Thus preprocessing will take place on the local machine for the remainder of the build. This technique prevents very slow builds where all compilations end up on the local machine after failing remotely.

Of course, if the local compilations fails after the remote failures, then the distcc invocation exits with the non-zero status of the local compilation. The error messages printed are also those of the local compilation.

The fallback behavior for distcc-pump mode to local compilation can be disabled by setting the environment variable DISTCC_FALLBACK to 0, which makes the distcc command fail as soon as the remote compilation has failed. This setting is very useful for debugging why the remote compilation went wrong, because now the output from the server will be printed.

Next we discuss the possible causes of discrepancies.

The user changed a source or header file during the build.
This yields inconsistent results of course.

A source or header file changed during the build.
The build system rewrites a file. For Linux kernel 2.6, this happens for 'include/linux/compile.h' and 'include/asm/asm-offsets.h'. This condition is fixed by letting the include server know that it must reset its caches when a stat of any of the files changes. Practically, this is done by gathering the files in a colon-separated list and then setting the INCLUDE_SERVER_ARGS environment variable when invoking the pump script, so that it passes the --stat_reset_triggers option; for example,
INCLUDE_SERVER_ARGS="--stat_reset_triggers=include/linux/compile.h:include/asm/asm-offsets.h"

A header file is potentially included, but does not exist, and is then later included.
This occurs when some header foo.h includes another header file trick.h, but the trick.h file has not yet been generated and the inclusion is actually ignored because of preprocessing directives. The include server will probe for the existence of trick.h, because it overapproximates all possible ways directives actually evaluate. The file trick.h is determined not to exist. If it is later generated, and then really included, then the include server will falsely believe that the file still does not exist. The solution to this problem is to make the build system generate trick.h before the first time any header file is included that makes a syntactic reference to trick.h

The include server was started with --unsafe_absolute_includes.
This is a problem if there are header files locally that do not exist remotely and that are actually used. Such includes are often protected by conditional directives that evaluate so that are actually used on only specific and often uncommon platforms. If you are not compiling for such a platform, then it may be correct to use --unsafe_absolute_include.

The include server has calculated the wrong includes.
We do not know of such a situation.

EXIT CODES

The exit code of include_server.py is usually 0. That the include server has been started properly is communicated through the existence of the pid_file.

ENVIRONMENT VARIABLES


DISTCC_EMAILLOG_WHOM_TO_BLAME The email address to use for include server automated emails. The default is 'distcc-pump-errors' (which is an email address that probably will not exist in your domain).

Additionally, the invocation of the compiler may use additional environment variables.

BUGS

If you think you have found a distcc bug, please see the file reporting-bugs.txt in the documentation directory for information on how to report it.

In distcc-pump mode, the include server is unable to handle certain very complicated computed includes as found in parts of the Boost library. The include server will time out and distcc will revert to plain mode.

Other known bugs may be documented on http://code.google.com/p/distcc/

AUTHOR

The include server was written by Nils Klarlund, with assistance from Fergus Henderson, Manos Renieris, and Craig Silverstein. Please report bugs to <distcc@lists.samba.org>.

LICENCE

You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warrany. A copy of the GPL is included in the file COPYING.

SEE ALSO

distcc(1), distccd(1), include_server(1), and gcc(1). http://code.google.com/p/distcc/ https://ccache.dev/
distcc-3.4/doc/web/man/index.html000066400000000000000000000013501404653710500167270ustar00rootroot00000000000000Distcc manuals

Installation instructions:

Man pages:

README files:

distcc-3.4/doc/web/man/lsdistcc_1.html000066400000000000000000000107431404653710500176560ustar00rootroot00000000000000 lsdistcc manual page

lsdistcc manual page

Table of Contents


NAME

lsdistcc - simple distcc server discovery

SYNOPSIS

lsdistcc [OPTIONS] [FORMAT]

lsdistcc [OPTIONS] host1 ...

DESCRIPTION

lsdistcc autodetects listening distcc servers either by looking in DNS for hosts named according to a given FORMAT, or by checking the host names given on the command line.
Hosts are considered good servers based solely on whether their name fits the format and whether they are listening on the right port (and optionally whether they respond when you send them a compile job).
Scans for hosts named according to FORMAT (default is "distcc%d"; see printf(3)) and starting from 1, so hosts such as distcc1, distcc2, and so on. Stops after 7 seconds or the first host name that does not resolve. Prints the names of all such servers listening on distcc's port.
If a list of host names is given in the command line, lsdistcc will only check those hosts.

OPTIONS


--help
Displays summary instructions
-l
Output latency in milliseconds after each hostname (not including DNS latency)
-n
Print IP address rather than name
-x
Append ,down to down hosts in host list
-tTIMEOUT
Set number of seconds to stop searching after [7]
-hHTIMEOUT
Set number of milliseconds before retrying gethostbyname [500]
-cCTIMEOUT
Set number of milliseconds before giving up on connect [900] (0 to inhibit connect)
-kKTIMEOUT
Set number of milliseconds before giving up on compile [1500] (0 to inhibit compile)
-mBITS
Set number of bits of address that must match first host found [0]
-oOVERLAP
Set number of extra DNS requests to send [1]
-gDNSGAP
Set number of missing DNS entries to tolerate [0]
-rPORT
Port to connect to [3632]
-PPROTOCOL
Protocol version to use (1-3) [1]
-pCOMPILER
Name of compiler to use [none]
-d
Append DNS domain name to format
-v
Verbose

EXAMPLES

Scan for servers named distcc1, distcc2, ... that provide a compiler named gcc-4.6 and include their latencies in the output:
    $ lsdistcc -l -pgcc-4.6
Scan for a compiler named gcc-4.6 on the servers hosta, somehost, hostx, and hosty:
    $ lsdistcc -pgcc-4.6 hosta somehost hostx hosty
To use the program in a build script, add the lines:
    DISTCC_HOSTS='lsdistcc'
    export DISTCC_HOSTS
before the line that invokes make. Or, in a Makefile, add the line:
    export DISTCC_HOSTS = $(shell lsdistcc)
Or use pump(1) which automatically invokes lsdistcc if you set DISTCC_POTENTIAL_HOSTS.

EXIT STATUS

The exit status is 0 if any servers were found, and 1 otherwise.
Uses 'for i=1... sprintf(format, i)' to construct names of servers, stops after 7 seconds or at second server that doesn't resolve, prints the names of all such servers listening on distcc's port. Default format is distcc%d.

SEE ALSO

distcc(1), distccd(1), pump(1), printf(3)
http://code.google.com/p/distcc/

AUTHOR

lsdistcc was written by Dan Kegel, Dongmin Zhang, and Manos Renieris.
This manual page was written by Daniel Hartwig for the Debian project.
distcc-3.4/doc/web/man/pump_1.html000066400000000000000000000143021404653710500170220ustar00rootroot00000000000000 pump manual page

pump manual page

Table of Contents


NAME

pump - accelerate remote compilation with distcc

SYNOPSIS

pump BUILD-COMMAND [ARGS] ...

eval ' pump --startup '; BUILD-COMMAND [ARGS] ... ; pump --shutdown

DESCRIPTION

pump is part of distcc. It is used for distcc's pump mode. Distcc's pump mode accelerates remote compilation with distcc by also distributing preprocessing to the servers.

For a detailed description of pump mode, including most notably some important restrictions, see the distcc(1) man page, in particular the HOW PUMP-MODE WORKS section and the RESTRICTIONS ON PUMP MODE section.

The simplest usage is the form

    pump COMMAND [ARG] ...
This will start an include server for distcc's "pump" mode; optionally run lsdistcc to compute the distcc host list; set some auxiliary environment variables; change PATH to use the distcc client in the same directory as the "pump" script; execute COMMAND with the specified ARG(s) ; and then shut down the include server. The COMMAND is typically a parallel build command, such as "make -j80", that will do many concurrent invocations of distcc.

An alternative way of invoking pump is to explicitly invoke "pump --startup" to start the include server and "pump --shutdown" to stop the include server. The "pump --startup" command will start up the include server, and will print out some environment variable settings. These environment variables are used to communicate between the pump-mode "distcc" client and the include server, and to communicate between "pump --startup" and "pump --shutdown". The caller of "pump --startup" is responsible for setting those environment variables before invoking "distcc" or "pump --shutdown".

For example:

    eval 'pump --startup'
    make -j80
    pump --shutdown

Note that distcc's pump-mode assumes that sources files will not be
modified during the lifetime of the include server, so modifying source files during a build may cause inconsistent results.

INVOKING LSDISTCC

When invoked in either the simple " pump COMMAND [ARG] ... " form, or as " pump --startup ", the pump script will invoke lsdistcc whenever DISTCC_POTENTIAL_HOSTS is set and DISTCC_HOSTS isn't. It will pass the value of DISTCC_POTENTIAL_HOSTS to lsdistcc and use the output of lsdistcc to set DISTCC_HOSTS.

OPTIONS


--help
Displays summary instructions.
--startup
Starts an include server, and outputs the environment variable settings needed for distcc(1) or pump --shutdown to access it.
--shutdown
Shuts down an include server started up by pump --startup.

ENVIRONMENT VARIABLES

The following environment variables are all optional.
DISTCC_LOCATION
The location of the distcc bin directory, which is normally inferred from the link-resolved dirname of argv[0]. If this location is in fact the bin directory inside an installation (as will be the case when the pump script in the installation executes), then Python executables and distcc itself will be retrieved from the parent directory of the location.
DISTCC_MAX_DISCREPANCY
see the distcc(1) man page.
DISTCC_POTENTIAL_HOSTS
The distcc servers that will be queried by lsdistcc in order to produce a value for DISTCC_HOSTS. This value may be unset or null. In such cases, lsdistcc will not be invoked, and distcc will use DISTCC_HOSTS or the distcc hosts configuration file, as described in the "Host Specifications" section of distcc(1).
DISTCC_HOSTS
This variable is passed through to distcc but only if DISTCC_POTENTIAL_HOSTS is not set.
LSDISTCC_ARGS
Extra arguments to pass to lsdistcc. See lsdistcc --help for more details.
INCLUDE_SERVER_ARGS
Extra arguments to pass to the include server.
PYTHONOPTIMIZE
If set to "", then Python optimization is disabled.

EXAMPLE

pump make -j20

BUGS

If you think you have found a distcc bug, please see the file reporting-bugs.txt in the documentation directory for information on how to report it.

AUTHORS

The pump script and distcc's pump mode were written by Nils Klarlund, Manos Renieris, Fergus Henderson, and Craig Silverstein. Please report bugs to <distcc@lists.samba.org>.

LICENCE

pump is part of distcc. You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warranty. A copy of the GPL is included in the file COPYING.

SEE ALSO

distcc(1), distccd(1), include_server(1), gcc(1), and make(1)
distcc-3.4/doc/web/results.html000066400000000000000000000254431404653710500165570ustar00rootroot00000000000000 distcc testimonials

distcc testimonials

C lets you shoot yourself in the foot, and distcc gives you a chaingun.

For speeding up our builds we use and recommend distcc to allow us to distribute compilation across two or more machines (i.e. a laptop and a desktop). distcc can be set up in no time and if like us you're continuously and repeatedly building lots of code it'll save you hours if not days of waiting around for compiles to finish. Also check out ccache. — The Rosegarden music software developers.


Paul Daniels:

I'd just like to extend my thanks to the creators (and maintainers ;-) of distcc and associated projects. My projects here are getting rather large in size (relative) such that I have to wait too long between the process of tweak-build-test-*groan* (repeat). 5 mins of distcc across a few unused boxes in this office and everything was much better ... only trouble now is that I no longer have an excuse to walk the hallways and make coffee *curse*.

Seriously though, great project, simple to use, generates real results — hallmarks of a indispensable utility.


Jens Mayer: distcc rocks. Thank you very much for your excellent work!


Alex Landa:

It's a scorcher!

I originally also had a rather low-memory (24MB) Pentium S-90 in the chain. I removed this because it was swapping and its old hard drive was making a total racket. I'm not sure if it slowed the whole cluster, but it seemed to. Learning which order to put the machines in was something that I got the hang of rather quickly. The Xbox did most of the hard work.


Richard Bown:

Previously building on desktop or laptop - times around 25-30mins for complete build. Really getting me down, decided I needed to upgrade my hardware. Then after consideration thought why should I be spending more money on hardware when I've already got so much lying around? Quick search failed to find distcc but instead found old (defunct) project called "doozer" - tried, talked to the author, he recommended distcc. Downloaded yesterday, up and running in no time. First attempts:

With main desktop and laptop: 15mins (make -j 4)
With main desktop, laptop and desktop 2: 18mins (make -j 8)
Jiggled build order and with main desktop, laptop and desktop 2: 13mins (make -j 4)

Excellent results after some prodding about.

6. Any other observations:

Significant improvements with just the two machines (as noted in the distcc web pages) and good enough to stop me from buying anything else for a while. Will continue to play around with configuration settings. Considering putting another (older) machine into the cluster but wonder whether it'll make enough of a difference. Current hard limit to improving times much further is the link stage which can take almost two mins just by itself.

Great piece of software. Many thanks,
Richard Bown
--
Rosegarden. Music Software For Linux


Thank you very much for this great tool. Our only regret is not to have used it before. — Guillaume LAURENT, telegraph-road.org


Stephane Eranian, hp (linux ia64 maintainer):

Yes, distcc is really nice. I have been using it for a month or so for my kernel compiles using a cluster of Itanium 2 machines. What I like is that it is really easy to setup. The danger with the approach is that you can easily overload your local (master) host. As for kernel compiles for 2.5, there are a lot of ld steps which are still all done on the master node. Besides that you can really feel the speed difference. I need to take a look at ccache now that you mention it.


Grant Grundler, hp:

(Endorsement): Stephane and I played around with just distcc for 2.4 ia64 kernels on a smaller cluster of rx2600 (dual CPU). The "master" runs out of CPU around -j16 (8 hosts). But that resulted in 66 second kernel builds. And distcc really is trivial to setup.


Hey Martin-

I've only been using distcc for a little while, on and off, and have only been on this mailing list for a month or so... but I've gotta say, you're doing one hell of a nice job. It seems extremeley rare to see one-man projects with devs so open about what they're doing, why they're doing it, and what potential problems might be these days...

You're doing a bang up job and distcc totally rocks. Keep up the good work!

Rob


distcc just rocks for doing regression tests!


J.T. Conklin:

I'm in the midst of converting the build infrastructure at work from using recursive gmake to Scons, and thought it might be useful to share my experiences.

The gmake build scheme we have been using is much like many others I have encountered over the years. A list of subdirectories are built sequentially by iterating over the list and spawning a new make for each. One problem with this approach is that the end of each module/ subdirectory becomes a synchronization point. For example, when there are fewer files to compile (in a given module) than you have processes in your pool, you're not taking full advantage of your build farm.

This deficiency can be addressed by rewriting your makefiles to avoid recursion (Cf Peter Miller's paper "Recursive Make Considered Harmful" or by using another tool (like scons, jam, etc.) that constructs a full dependency graph before building.

Here's a real-world example that demonstrates the advantages. Our source code is about 600,000 lines of C++, with a small amount of C and assembly thrown in. There are sixteen libraries, a dozen or so executables (including four very large ones), etc.

On a AMD Athlon 2000+, using our old recursive gmake with -j4 (mainly to hide i/o latency):
real: 21m26.052s
user: 19m44.063s
sys: 1m28.127s

On a distcc build farm including the above AMD machine, plus 2 1.0GHz PIII machines and 2 Dual 1.0GHz PIII machines with gmake -j20:
real: 10m33.496s
user: 5m34.436s
sys: 1m0.731s

Our scons build on the single AMD machine with -j4:
real: 13m52.052s
user: 12m54.470s
sys: 0m43.463s

And finally, scons -j20 on the distcc build farm:
real: 3m47.938s
user: 3m16.116s
sys: 0m35.347s

While distcc alone more than doubled the performance, distcc plus a build scheme that takes full advantage of build parallelism really lets it shine by speeding up the build more than 5 times.


distcc was too easy to setup. You should add some obscure dependency so its a bit more difficult to get running. Nice job on a great util!!

Only downside is that I am tempted to buy more boxes now ;) — Justin Kirby, openaether.org:


distcc is awesome: easy install, no maintenance, works right. It's saved us a lot of time, and the price sure beats that of Trolltech's Teambuilder!


I have a Sunblade 100 on my desktop and it takes 4 minutes to compile one project of mine. Using 3 public Sunblade 1000's it now only takes 1 minute. Thank You, Thank You, Thank You.

-- Shane McDaniel, MIT

Copyright © 2002–2004, 2006 Martin Pool.

Send comments to distcc(at)lists.samba.org distcc-3.4/doc/web/scenarios.html000066400000000000000000000144761404653710500170500ustar00rootroot00000000000000 scenarios where distcc can help

scenarios where distcc can help

You don't need an enormous custom-built cluster to find distcc useful. Here are some typical scenarios where spending a little while installing distcc can pay off in improved productivity.

workgroup of developers

You work in an office with several other people, each of whom has a PC, workstation or desktop. Perhaps you work on the same project, or perhaps on different projects.

Your project is moderately large, so it takes a while to build: waiting for it disrupts your concentration and makes development less fun. You waste time needing to rebuild when somebody changes a top-level header.

The solution is straightforward: run distcc on other machines, and make sure they have the compiler installed. Your machine can distribute work onto others, with lowered priority to make sure you don't disrupt other people's work. The machines don't need to be centrally administered, and you don't need root to install the daemon.

Depending on your project and infrastructure, compilation time could easily be more than halved.

Faster compilations give you the advantage of being able to do make clean; make all more frequently, which can catch bugs that might be hidden by incorrect Makefile dependencies. It allows test engineers to get builds to test faster. It makes nightly (or hourly? or continuous?) check builds more feasible, so bugs that are checked in can be caught and fixed with less disruption.

In a variation on this, you also have one big machine. Perhaps it primarily acts as a server or master build machine, but you can also use it to accelerate compilation on your workstation or laptop.

sofa computing

At home, you like to use your laptop and wireless to program on the sofa or in the garden. It's convenient to keep all your working directories on the laptop so that you can take it with you wherever you go.

However, it's slow and gets hot when you build a large project. Fortunately, you also have a faster machine in your home office.

Using distcc, you can push most of the work of compilation onto the faster machine. You have the advantage of keeping all your source in one place, but compilation runs at the speed of your fast machine.

working on embedded or small computers

You're developing on a small Linux machine, such as the Zaurus or an embedded PC. It's large enough that you can run editors and work directly on it, but small enough that compilation is painfully slow. On the other hand, developing anywhere else is indirect, and necessitates continually copying files to and fro.

By running the distcc client on the small machine, you can shift most of the work onto a cross-compiler installed on a faster machine, but otherwise work directly on the box.

Copyright © 2002–2004, 2006 Martin Pool.

Send comments to distcc(at)lists.samba.org distcc-3.4/doc/web/security.html000066400000000000000000000204221404653710500167150ustar00rootroot00000000000000 distcc security notes

distcc security notes

distcc is intended to be quite secure when used according to the documentation, but it must be properly configured.

Anyone who can connect to the distcc server port can run arbitrary commands on that machine as the distccd user. If you are not using SSH, you must use the --allow rule and/or firewall rules to limit access to port 3632. Since version 3.0, distccd now enforces that, refusing to run if the --allow option is not specified.

Someone has written a program to attack unprotected servers. To prevent this attack, use network access control or SSH (which is much slower).

Installation or use of any software caries a certain risk, which should be assessed by the machine operator.

distcc allows remote execution of compilation jobs. This introduces a trust relationship between the client and server machines. The client completely trusts the server to compile code correctly. A corrupt server could introduce malicious code into the results, or attack the client in other ways. The server completely trusts an authorized client. A malicious client could execute arbitrary commands on the server.

distcc supports a choice of two network transports: a simple TCP protocol (normally on port 3632), and connection over SSH or a similar secured connection.

The distccd TCP server does not run as root. If started by root, before accepting connections it gives away its privileges and changes to either the distcc or nobody user, or to a user specified by the --user option.

The distcc client may be run as root. Compiling or doing other unnecessary work as root is generally discouraged on Unix, but distcc permits it because some package installations require it.

In TCP mode network transmissions are not encrypted or signed. An attacker with passive access to the network traffic can see the source or object code. An attacker with active access can modify the source or object code, or execute arbitrary commands on the server.

The TCP server can limit clients by either checking the client address, or listening only on particular IP interfaces. However, in some circumstances an attacker can spoof connections from a false address. If such a situation apply to your network then IP-based access control is not sufficient.

In TCP mode there is no way to limit access by user, rather than by host.

IPSec or IPv6 would probably also help, but nobody has reported testing it with distcc.

In SSH mode the server is started by each user under their own account on the server. There is no long-lived daemon. Connections are authenticated and encrypted. Every user is allowed only the privileges that their normal account allows.

Because the server and client necessarily trust each other, there has been no security audit of the code that runs after a connection is established. It is possible that a hostile server could gain control of a client directly, as well as modifying the object code.

If the DISTCC_CMDLIST environment variable is set when invoking distccd, distccd will only execute commands from that list. (The RPM and Debian distributions of distcc set this variable via the /etc/distcc/commands.allow.sh file which is sourced by /etc/init.d/distcc). This mechanism can be used to only allow the execution of compilation commands rather than arbitrary commands. However, this should not be relied on as a security measure, because gcc is not secure against hostile input, and it might be possible for an attacker to gain control of the gcc process through a carefully crafted input file or command line. You should assume that anyone able to submit jobs is able to execute arbitrary operations under the account used by distccd.

It has been suggested that distccd should take a simple username/password authentication mechanism, but this would give a false sense of security. If you cannot trust your network, the only sensible policy is to use SSH.

Some people have proposed that the client should check whether a server is trustworthy by re-running compilations on a different server. This approach can be useful in some distributed-computing problem spaces such as SETI@home, but not practical for distcc. Firstly, the damage from a single compromised object file is very high, so every single file would have to be extensively checked. Secondly, the performance constraints are such that building every single file two or more times would often make distribution worthless. Thirdly there would sometimes be false alerts from minor differences in gcc patchlevel that are not visible in normal use but that do change the output file at a byte level.

For practical advice, see this description of how to secure distcc using chroot and OpenVPN.

Copyright © 2002–2004, 2006 Martin Pool.

Send comments to distcc(at)lists.samba.org distcc-3.4/docker/000077500000000000000000000000001404653710500141055ustar00rootroot00000000000000distcc-3.4/docker/README.md000066400000000000000000000005751404653710500153730ustar00rootroot00000000000000# Building distcc with different compilers ## Requirements: Docker 1.9.1 ## Build The following command will create three images based on Ubuntu 16.04 using gcc 4.8, 5.4 and clang 3.8 and build distcc inside the container. ``` $ cd docker $ ./build.sh ``` In order to build only one variant use the following command: ``` $ cd docker $ ./build.sh clang-3.8|gcc-4.8|gcc-5 ``` distcc-3.4/docker/base/000077500000000000000000000000001404653710500150175ustar00rootroot00000000000000distcc-3.4/docker/base/Dockerfile000066400000000000000000000005271404653710500170150ustar00rootroot00000000000000FROM ubuntu:xenial-20170802 LABEL maintainer="" ENV DEBIAN_FRONTEND=noninteractive COPY apt-conf /etc/apt/apt.conf.d/ RUN apt-get update && \ apt-get install autoconf \ python3-dev \ python-dev \ libiberty-dev \ build-essential \ make distcc-3.4/docker/base/apt-conf000066400000000000000000000002451404653710500164520ustar00rootroot00000000000000APT::Get::Assume-Yes "true"; APT::Get::Install-Recommends "false"; APT::Get::Install-Suggests "false"; DPkg::Post-Invoke { "rm -rf /var/lib/apt/lists/* || true"; }; distcc-3.4/docker/build.sh000077500000000000000000000014001404653710500155360ustar00rootroot00000000000000#!/bin/bash set -e # exit immediately if a command returns with a nonzero exit code echo "*** Building distcc/base image" docker build -t distcc/base -f base/Dockerfile base if [ $# -eq 0 ]; then compilers=("gcc-4.8" "gcc-5" "clang-3.8") else compilers=("$1") fi for compiler in "${compilers[@]}" do echo "*** Building distcc/$compiler image" docker build -t distcc/$compiler -f compilers/Dockerfile.$compiler . done echo "*** Building distcc" for compiler in "${compilers[@]}" do echo "*** Building distcc with distcc/$compiler image" set -x docker run --rm -it -v /tmp:/tmp -v `pwd`/..:/src:rw -w /src distcc/$compiler bash -c "./autogen.sh && ./configure && make clean && make && make install && make check" &> distcc-$compiler.log set +x done distcc-3.4/docker/compilers/000077500000000000000000000000001404653710500161025ustar00rootroot00000000000000distcc-3.4/docker/compilers/Dockerfile.clang-3.8000066400000000000000000000004531404653710500214670ustar00rootroot00000000000000FROM distcc/base LABEL maintainer="" RUN apt-get update && \ apt-get install clang-3.8 build-essential && \ apt-get remove gcc g++ && \ update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.8 50 && \ update-alternatives --install /usr/bin/cc cc /usr/bin/clang-3.8 50 distcc-3.4/docker/compilers/Dockerfile.gcc-4.8000066400000000000000000000005251404653710500211400ustar00rootroot00000000000000FROM distcc/base LABEL maintainer="" RUN apt-get update && \ apt-get install gcc-4.8 \ gcc-multilib \ g++-4.8 \ g++-multilib && \ update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50 && \ update-alternatives --install /usr/bin/cc cc /usr/bin/gcc-4.8 50 distcc-3.4/docker/compilers/Dockerfile.gcc-5000066400000000000000000000005151404653710500207720ustar00rootroot00000000000000FROM distcc/base LABEL maintainer="" RUN apt-get update && \ apt-get install gcc-5 \ gcc-multilib \ g++-5 \ g++-multilib && \ update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 50 && \ update-alternatives --install /usr/bin/cc cc /usr/bin/gcc-5 50 distcc-3.4/find_c_extension.sh000077500000000000000000000024261404653710500165170ustar00rootroot00000000000000#! /bin/sh # Usage: find_c_extension.sh BUILDDIR # # Write path of directory containing C-extension of build directory. # # More precisely, locate the unique directory of the form: # # _include_server/lib.*/include_server/ # # that contains file 'distcc_pump_c_extensions.so'. Write the path of this # directory to stdout and exit with status 0. If such a path does not exist # then write error message to stderr and exit with status 1. builddir="$1" # We want to catch the file whether it's .so (unix) or .dll (cygwin). # The '[sd][ol]*' glob does that without having to worry about # unpredictable 'ls' behavior when a glob has no matches. # (Side note: there is intense internal debate about whether the # '[sd][ol]' hack is "so ugly I can't stand it" or "kinda cute".) so_files=`ls $builddir/_include_server/lib.*/include_server/\ distcc_pump_c_extensions*.[sd][ol]*` if [ -z "$so_files" ]; then echo \ '__________Could not find shared libraries for distcc-pump' 1>&2 exit 1 elif [ `echo "$so_files" | wc -l` -ge 2 ]; then echo \ '__________Shared libraries for multiple architectures discovered.' \ 1>&2 echo \ "__________Cannot determine which one to use among: $so_files" \ 1>&2 exit 1 else # There was only one such file. dirname "$so_files" exit 0 fi distcc-3.4/gnome/000077500000000000000000000000001404653710500137435ustar00rootroot00000000000000distcc-3.4/gnome/distccmon-gnome.desktop000066400000000000000000000006631404653710500204310ustar00rootroot00000000000000[Desktop Entry] Version=1.0 Exec=distccmon-gnome Name=distcc monitor Name[sv]=distcc övervakare GenericName=Distributed Compile Monitor GenericName[sv]=Distribuerad kompilerings-övervakare Comment=Graphical view of distributed compile tasks Comment[sv]=Grafisk vy av distribuerade kompileringsuppgifter Icon=distccmon-gnome TryExec=distccmon-gnome Terminal=false Type=Application Categories=GNOME;GTK;Development; StartupNotify=true distcc-3.4/gnome/distccmon-gnome.png000066400000000000000000000112731404653710500175430ustar00rootroot00000000000000‰PNG  IHDR77¨ÛÒFbKGDÿÿÿ ½§“pIDATxÚíšyxTå½Ç?çÌ–™ìûD$‚µ€‚,e©Ö+Xik«¶Õbíj±åÑÛǶêµôq-7 Z7J©€z¥²ÔV+´²%”°%HX"²Lf²Ìz–÷½Ì™0¤¡7p­½÷yú>ÏûœsfÎÌù}ßïoükükük|’Cù(k¢Ìò稃øSp°8 ˜€4/>!` `€Ó::¬Ï”„9hænš:õÚçç~aj~Fz&þ®vzº¼„z|xN‚0ëßü£hk•KÄ?˜ °÷`ô›¦Å $á¦Æ’ŸzøÙëçÏN9|ü µ {ðuùˆ†zIKr“îN#3«˜’q“Ct]sö#¯ ØòæÜ@êí·ßÞ:eÊ”û„÷={v °ÍÒ@¥¿z^ÜYöð’¤d•êý;in=‰¦ixl*I.»3 Å‘‚OwâÌFÃîêÉÀÀP,A>²î;< ì±~ó÷€y€ôÅ‹ŸüÁâ{H+LAÉ0™Ï|Îj9º©m'Z›¿Z«ì´Ô4¾’uO®~nòÉC'¦>ÿêsãßxåÑ+7¬øÌÆ×6Í~e­¾ìgcë¿Ò/^|ìËwÞÂOŸü1ÿ°Úu?~œÒ«JÈ*θ¼ýDç•À>Àg=W äPîÉ•kRކ‰hŠbÅÁe³ª(˜ó<¤ £="ñ“Ê?˜Å¯ï¾š¤ô €¥–³ XÓHXÉñu.r?{céË»}L]tßÄ º.¢€–°²Ÿ0ðàØmw~™gW>Íáúliäôá³4ÕœdäÈ‘L›1Q“‡·ì>Õr‚vûàf§§¦Ñxâša¢&*ùÓŸå9…T¼•÷³ûPÅy9´µžÁ4405@alÅ8|ñòrsÈÈÈ`ô˜ÑQ1îr¶~è@;k’j@¤5B0¹€ÌÜ~ðA òó¸bB%EEE1Ñ’ú‡vL¹zâr€#ÍooâøÞî;Wù»_ý¤ê~æ|n6ðçëî>ñCàq@ˆ¹¼¨®ÑÖÙŠ ºt ›ü@E¢p÷âGX0}2SÆŽ¤jÅZv××`†%ã&]I‚%ÿñ ûêê©­ÛÏÞºÔÔ7’’’B×éfügzhnÒvZ§ùp(*§OŸ¦³³¿ßO[[­­­ùð(›þðΔyóæ=P{x/£&¨–[lßõ‹{Ÿ 3-‡Ë0ÓReÇ@6wÛäÙ“ vÖíB`Ç”v„¢:õ.Cóóž-¸õ†Oa7Ï¢˜^nœ^ÎIJ"Ü8Ÿ‘“ç¡fâàŽõMNV&I$ª1mêÕìßôJû!\-;pùqw61ñŠqäædSXTİ¡Cq8¨8\.’=É´·ž™¾gÏvnÞ½Êæ®,(ÍeÒäIÌYðvoÙSì>?íº)466ÒÑìË^"ýÕò‹@n²'CÚ1¥EQÈt;Xtó5̼< [r6Šš‡¢¸"ЂР‡ÂìñÉÌ?‚…Ÿ?Ëâû~Ìö½I3‡Ì–3H`ÂÜÛе(Â4PT†AÓ5´ Î8ÃDÓ{)(Τ4 Â2‰Ò‘¥´µµÅe{¿q{Sa4ëMõqðÈ€-öú'`KwCyæáÿŒ ›×á´'ÒÉN…'ïšÂÈ’±¨®½€ ‰†´b¶ae;jÁÜYE|kr&¯¯¨âêE¯°«ê;ƒjk¬cC‡Äçà6¥/ª˜À¯OÔžò·OY¡Å5À_Ù5. øù²G—òúkñûB:ÃÆ—ò•iC™Ÿz+"[ Š-Ôd[2ŠÍƒ¢&1aì(|îNõ :n^|è;Lß·—%OiÏ,Y„¡ "RàÓ%ÓŽÓéA*vžÙ¼¿•ôp3s¿ümÆÉ²’òq$%£ô:úØ0 «òî7¡L…H󜻓zpß±˜ºàéU¿dXñe,[SÅîm5tµö6‹,¹#€>PúeZ™{Ü¥vޏîëO'‡}{úд}[_ëøYÕ÷¼ODñàíÕ1Ôd”á3PŠ&àrØ^”ÏX§ÆhçYò³òÈ*ÌÄmKFbGØÁǬ]bêwÓJ¹°wL v©§–Ó¾:iÖ£¯"̨ٓ’2þ´ýmV¿ù[w£·#pø>Ðmûæàè¦_ˉón×Õn ý>ò„¯[% ’“AÇ©æÞ°a‘]-ØôãzÜädd’V‹*ÓÁî&b³¡i1÷¦E!¨!1ívD¯†J¨”„)ϯœjþ À[o¿EkS;mǼ+­éëçAÿGp}zQ³iµ>zŒé’¢ül¼­t÷ô¢!š›H×}d«=èɧ+“‚dœIŸmi(öd4§H4 š šDtÃDSìHO‘sΡ˜RAˆsÔýå•êþ²½¼f9Ãnkö$xQi¿˜²¸ÛÛaÚT…ÉŸ®$7;ƒŽÎNœ<Éö÷%Y™ ÉËÄÐ$6’nÔ´4œR!âL‰Òp!³$š !¿ ×¦`ÓÂtœ˜“^Ÿ£ïYa#éü–Ï÷- « YçñÏBq[‹—NN˜Bê†É§ÆN °hþž^Ì-±Õ•¶l2Ý:z†TxpèÝ…¢taAÕ‰þ‘Ät+è2ŠÚmБêÀ-‚8\:n3|Îð¥Š.ÎSË€À»úŒ$ÔƒFb¬W)p¢Ë×Ù0{Î\ÞÙúÅC†‘—— @ØLÃ$3LO8Í¡£¨ ÀP§®‘ësYVCÜF¤š§Sá졲 ‹T"Ñsk-„‰>6ƒ–êuXÓ›à@‰ŒÅ0Xæ–þfÃË—m?ÔH}p,´ð›5oð•[o'5-€³íÍl — ’l(=AL¨~èñHœ‰.j"$©’^ÝEX :ünŠJ ÝN·ÚÛ÷@· 0ÃvÔWC-¡Û%ê]\Õ7ÝUpÃïœxæ£j´6¿³Jqq1n‡µ?*ûØZ^=ØD)L„¢&†(Ýš‰*8`CöbÀ-Y÷îë߬i IËEF¢(íïaJ…üü|ö}ġңÎ%¿ û=V$\›òük€°IÐ#$v)çi²ßu±à~ú“{ziØõ3K{Ït!;"¸v¤d¦§ µ‘v„”©`Hõ\Õ À±$8–3J„ˆ¦@J‰!b‰rIŽ›L» ùh ª4BÐíëˆËðÇ~2ÍÞJlÂ^*¸¿÷³o–ö*4iТ¨u¨2–ÞÛD”$42ÒÓ8z¼™´Œ,r2ӨרŒ;ÉÅèá…ì¨;Jq^&¦ BJL)0…))ÎIE´ÞˆI¼ýön˜;“3­g°I“W¬²ú}‰¯;°èþݳ˜T_ˆÅÁn„(VO0(JÊÙòܣ繌4·“!C† ¥¤Óç§éøq®¬Ï©–öî«çº¹³éèè`_ýæÌši©ªDˆk¦cH"yëÍÓ亹³Ù´µ†ãvÓp ~Ó‡Gæ% óòЕܵðÎ¾Ì ØÐFü»à”~­iÙï»÷Þ{ïw›šŽ=çr¹(˜Š ›4c6¢€ÒÏØÄ…¢Žb=A9÷$¿¿“p0HMõ®ø]_r€ÿ\ø­ïß~õÄ+W+H5¹yéS¿ ¤ÄóÉDy/e KµôýM€™3?kÍùüdfeÓåó’™M0$99™P0€'9%V¾%œ÷]§¤ô‰ÿÞï뤳ӋՉ®¶Ú俾ðÛ_¿öšI«€Dæn¶'ä”âb¶°Ê7ßf˜¦‰Ïç#3+¿¯3vìì<X(8ï¼ï:Ðï: îËTj¬@Ý |iÕŠçWí;pä •—Vü†[n½ã[À«d¿D<nP|m÷üqÏ_X6õ)@~ï'U7¼¸b•|qŪÄ{îJ€4  r)j9Ä*×þ3·WpÿÏç+ºQAòöÛZô»u¯= Œ°JžP¢c¹˜Ä¹XÐSÅò ò¶'}ß­py27VŒ*Ú2nsO'´;/9Î ~‰D"8±Nô®ê=Œ«‹Çã!‰²îÛ¸õ¦9hšÆû;ª¹~öô˜»7­xh‹u†V¯Y˵S§`šfß÷BˆóކaĽa` IÃ} ßÛ¶ea<Xã9ËþÍbÝ`Á})ñâµ×ÿ‹ììl¦N¹!áÍMï` ɼ9Sy}Ýz„|î³³Ù³w§N· EB±Ã‚ËÇU`³ÙÈÎÎÆ4MLÓäСC”•ÅòÓªª*®¼êÓ\;u †a°lù³(H^^±ISÓ±ç€ïZ±÷T¼•×?t)ƒdíTœµx?ñãMŒ,Ñ—V…B!\.B¡ .—ëü`m±$„è›1†„@×õó˜+//§®~?º®S1v BªªªØ¶mk\®g­C—*ý’éA¹Î/%6J[ZZ8|ø0#KG°Ùl${Üx;¼¤¦$“ž–Jk[;YYYddd°»º†¼¼< 9vìyyy|ðÁ”••Q^^NYYcÆŒaôèÑ}G€qc™?ïFJKK©­­ ¢¢b•%ÎëV¡oå‰þ/(ƒa- ‡q:(Š‚” „`ÇŽØív„TTTP[[‹‚ÊÊJvï®aÿþ:¾ñoP]]®ëL›6ýû÷3cÆŒ¾ÅZ¿~=cÇŽEJIaa!.—‹uëÖ1zôhLÓdÓ¦MØí6fΜ‰‚åË—³uëV¬ý‚g¬L(V î`e0ì3ò 6PRR‚ÓédüøñXù÷£¾”†ÉSO=ŬY³èééæÔ©S0bÄ„b·Û‰FciÓ4yòÉ'Y°`eeex½^{ì1|>këëëoʬŠ<0ØÜò<¹‚Á ¡Pˆ]»vqðàAf̘Áˆ#b;øuuÔÖÖöyCMÓúDÜvâÓét2mÚ4JKKBðÞ{ï¡ë:‡ƒI“&±yófü~?>Ÿ¯ï÷Á`»ï¾›ššLÓdüøñ˜¦É /¼goÐfu½.š9  ƒ}ì$ãÎ">¯ÏãÎ$ñ 3: sys.exit('DISTCC_CLIENT_TMP must have at most two directory levels.') self.number_missing_levels = 3 - len(self.client_tmp.split('/')) self.client_root = None def Glob(self, pid_expr): """Glob unpadded client roots whose pid is matched by pid expression.""" return glob.glob('%s/*.%s-%s-*' % (self.client_tmp, self.INCLUDE_SERVER_NAME, pid_expr)) def ClientRootMakedir(self, generation): """Make a new client directory for a generation of compressed files. Arguments: generation: a natural number, usually 1 or slightly bigger; this number, minus 1, indicates how many times a reset of the caches has taken place. """ try: # Create a unique identifier that will never repeat. Use pid as suffix for # cleanout mechanism that wipes files not associated with a running pid. self._client_root_before_padding = tempfile.mkdtemp( '.%s-%s-%d' % (self.INCLUDE_SERVER_NAME, os.getpid(), generation), dir=self.client_tmp) self.client_root = (self._client_root_before_padding + '/padding' * self.number_missing_levels) if not os.path.isdir(self.client_root): os.makedirs(self.client_root) except (IOError, OSError) as why: sys.exit('Could not create client root directory %s: %s' % (self.client_root, why)) def CleanOutClientRoots(self, pid=None): """Delete client root directories pertaining to this process. Args: pid: None (which means 'pid of current process') or an integer """ if not pid: pid = os.getpid() for client_root in self.Glob(str(pid)): shutil.rmtree(client_root, ignore_errors=True) def CleanOutOthers(self): """Search for left-overs from include servers that have passed away.""" # Find all client root subdirectories whether abandoned or not. distcc_directories = self.Glob('*') for directory in distcc_directories: # Fish out pid from end of directory name. hyphen_ultimate_position = directory.rfind('-') assert hyphen_ultimate_position != -1 hyphen_penultimate_position = directory.rfind('-', 0, hyphen_ultimate_position) assert hyphen_penultimate_position != -1 pid_str = directory[hyphen_penultimate_position + 1: hyphen_ultimate_position] try: pid = int(pid_str) except ValueError: continue # Happens only if a spoofer is around. try: # Got a pid; does it still exist? os.getpgid(pid) continue except OSError: # Process pid does not exist. Nuke its associated files. This will # of course only succeed if the files belong the current uid of # this process. if not os.access(directory, os.W_OK): continue # no access, not ours Debug(DEBUG_TRACE, "Cleaning out '%s' after defunct include server." % directory) self.CleanOutClientRoots(pid) # COMPILATION SERVER # An upper bound on the number of directory components in the temporary # directory on the distccd server that corresponds to the root directory # on the client machine. Normally the server root is /tmp/distccd_XXXXXX. # But it could be something different if TMPDIR is set when distccd is # started. See dcc_get_tmp_top() in ../src/tempfile.c. # It turns out that our own test infrastructure (test/testdistcc.py) # sets TMPDIR before invoking distccd, so this needs to be reasonably # high, otherwise 'make distcheck' will fail. MAX_COMPONENTS_IN_SERVER_ROOT = 20 # EMAILS # For automated emails, see also src/emaillog.h. DCC_EMAILLOG_WHOM_TO_BLAME = os.getenv('DISTCC_EMAILLOG_WHOM_TO_BLAME', 'distcc-pump-errors') EMAIL_SUBJECT = 'distcc-pump include server email' CANT_SEND_MESSAGE = """Please notify %s that the distcc-pump include server tried to send them email but failed.""" % DCC_EMAILLOG_WHOM_TO_BLAME MAX_EMAILS_TO_SEND = 3 # TIME QUOTAS (SOLVING THE HALTING PROBLEM) # The maximum user time the include server is allowed handling one request. This # is a critical parameter because all caches are reset if this time is # exceeded. And if all caches are reset, then the next request may take much # longer time, possibly again exceeding the quota. The parameter is also of # importance to builds that involve compilations that distcc-pump does not grok: # an amount of time roughly equal to this quota is wasted before CPP is invoked # instead. USER_TIME_QUOTA = 3.8 # seconds # How often the following question is answered: has too much user time been # spent in the include handler servicing the current request? # # FIXME(klarlund): SIGALRM should not be raised in code that has I/O. Fix # include server so that this is guaranteed not to happen. Until then, we are # careful to wait a full 4 s before issuing SIGALRM. USER_TIME_QUOTA_CHECK_INTERVAL_TIME = 4 # seconds, an integer # ALGORITHMS SIMPLE = 0 # not implemented MEMOIZING = 1 # only one currently implemented ALGORITHMS = [SIMPLE, MEMOIZING] # PYTHON TUNING # The default for the first parameter of gc.set_threshold is 700; see # http://www.isi.edu/~chiang/python.html for a discussion of why this parameter # can be bumped up considerably for speed-up. The new default of 10000 was # tested on a very large application, where include server time CPU time drops # from 151s to 118s (best times out of 10 runs). There was no seeming changes to # memory usage. Trying with 100,000 did not speed up the application further. GC_THRESHOLD = 10000 # FLAGS FOR COMMAND LINE OPTIONS opt_algorithm = MEMOIZING # currently, only choice opt_debug_pattern = 1 # see DEBUG below opt_email_bound = MAX_EMAILS_TO_SEND opt_exact_analysis = False # use CPP instead of include analyzer opt_print_times = False opt_path_observation_re = None opt_send_email = False opt_simple_algorithm = False opt_stat_reset_triggers = {} opt_statistics = False opt_unsafe_absolute_includes = False opt_no_force_dirs = False opt_verify = False # whether to compare calculated include closure to that # produced by compiler opt_write_include_closure = False # write include closures to file # HELPER FUNCTION FOR STAT_RESET_TRIGGERS def Stamp(path): """Return a stamp characterizing a file and its modification time.""" try: st_inf = os.stat(path) # The inode and device identify a file uniquely. return (st_inf.st_mtime, st_inf.st_ino, st_inf.st_dev) except OSError: return None # LANGUAGES AND FILE EXTENSIONS # The languages that we recognize. LANGUAGES = set(['c', 'c++', 'objective-c', 'objective-c++']) # The suffixes, following last period, used for source files and # preprocessed files, each with their corresponding source language. TRANSLATION_UNIT_MAP = { # C 'c': 'c', 'i': 'c', # C++ 'cc': 'c++', 'cpp': 'c++', 'cxx': 'c++', 'C': 'c++', 'CXX': 'c++', 'ii': 'c++', # Objective C 'm': 'objective-c', 'mi': 'objective-c', # Objective C++ 'mm': 'objective-c++', 'M': 'objective-c++', 'mii': 'objective-c++', } # All languages are described by suffixes. assert set(TRANSLATION_UNIT_MAP.values()) == LANGUAGES # DEBUG # Debugging is controlled by the 5 least significant bits of # opt_debug_pattern. DEBUG_WARNING = 1 # For warnings DEBUG_TRACE = 2 # For tracing functions (upper level) DEBUG_TRACE1 = 4 # For tracing functions (medium level) DEBUG_TRACE2 = 8 # For tracing functions (lower level) DEBUG_DATA = 16 # For printing data DEBUG_NUM_BITS = 5 # The cardinality of {1,2,4,8,16} def Debug(trigger_pattern, message, *params): """Print message to stderr depending on trigger pattern. Args: trigger_pattern: a bit vector (as an integer) message: a format string params: arguments to message """ # TODO(klarlund): use Python's logging module. triggered = opt_debug_pattern & trigger_pattern if triggered: i = 1 for unused_j in range(DEBUG_NUM_BITS): if i & DEBUG_WARNING & triggered: print('WARNING include server:', message % params, file=sys.stderr) if i & DEBUG_TRACE & triggered: print('TRACE:', message % params, file=sys.stderr) elif i & DEBUG_TRACE1 & triggered: print(sys.stderr, 'TRACE1:', message % params, file=sys.stderr) elif i & DEBUG_TRACE2 & triggered: print('TRACE2:', message % params, file=sys.stderr) elif i & DEBUG_DATA & triggered: print('DATA:', message % params, file=sys.stderr) i *= 2 sys.stderr.flush() # EXCEPTIONS class Error(Exception): """For include server errors.""" pass class NotCoveredError(Error): """Exception for included file not covered by include processing.""" def __init__(self, message, source_file=None, line_number=None, send_email=True): """Constructor. Arguments: message: text of error message source_file: name of source_file if known line_number: an integer, if known send_email: a Boolean, if False then never send email These arguments are all stored in the exception. However, the source_file and line_number are appended, in a syntax defined here, to the message before it is stored as self.args[0] through invocation of the Error constructor. """ assert not line_number or source_file self.source_file = None self.line_number = None self.send_email = send_email if source_file: # Mark this exception as mentioning the source_file. self.source_file = source_file # Line numbers are not currently used. if line_number: self.line_number = line_number message = ("""File: '%s', line: %s: %s""" % (source_file, line_number, message)) else: message = """File: '%s': %s""" % (source_file, message) # Message, a string, becomes self.args[0] Error.__init__(self, message) class NotCoveredTimeOutError(NotCoveredError): """Raised when spending too much time analyzing dependencies.""" pass class IncludeAnalyzerTimer(object): """Start a timer limiting CPU time for servicing a single request. We use user time so that a network hiccup will not entail a cache reset if, say, we are using NFS. An object of this class must be instantiated so that, no matter what, the Cancel method is eventually called. This reinstates the original timer (if present). """ def __init__(self): self.start_utime = resource.getrusage(resource.RUSAGE_SELF).ru_utime self.old = signal.signal(signal.SIGALRM, self._TimeIsUp) signal.alarm(USER_TIME_QUOTA_CHECK_INTERVAL_TIME) def _TimeIsUp(self, unused_sig_number, unused_frame): """Check CPU time spent and raise exception or reschedule.""" if (resource.getrusage(resource.RUSAGE_SELF).ru_utime > self.start_utime + USER_TIME_QUOTA): raise NotCoveredTimeOutError(('Bailing out because include server ' + 'spent more than %3.1fs user time ' + 'handling request') % USER_TIME_QUOTA) else: # Reschedule ourselves. signal.alarm(USER_TIME_QUOTA_CHECK_INTERVAL_TIME) def Stop(self): signal.alarm(0) def Start(self): signal.alarm(USER_TIME_QUOTA_CHECK_INTERVAL_TIME) def Cancel(self): """Must be called eventually. See class documentation.""" sys.stdout.flush() signal.alarm(0) signal.signal(signal.SIGALRM, self.old) class SignalSIGTERM(Error): pass def RaiseSignalSIGTERM(*unused_args): """Raise SignalSIGTERM. Use signal.signal for binding this function to SIGTERM. """ raise SignalSIGTERM # COMMON FUNCTIONS def SafeNormPath(path): """Safe, but limited, version of os.path.normpath. Args: path: a string Returns: a string Python's os.path.normpath is an unsafe operation; the result may not point to the same file as the argument. Instead, this function just removes initial './'s and a final '/'s if present. """ if path == '.': return '' else: while path.startswith('./'): path = path[2:] return path.rstrip('/') distcc-3.4/include_server/basics_test.py000077500000000000000000000103521404653710500205300ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # __author__ = "Nils Klarlund" import os import os.path import tempfile import unittest import basics class BasicsTest(unittest.TestCase): def setUp(self): basics.opt_debug_pattern = 1 def tearDown(self): pass def test_ClientRootKeeper(self): os.environ['DISTCC_CLIENT_TMP'] = 'to/be' self.assertRaises(SystemExit, basics.ClientRootKeeper) os.environ['DISTCC_CLIENT_TMP'] = '/to/be/or' self.assertRaises(SystemExit, basics.ClientRootKeeper) try: tempfile_mkdtemp = tempfile.mkdtemp os_makedirs = os.makedirs def Mock_tempfile_mkdtemp(pat, dir): self.assertTrue((pat, dir) in [('.%s-%s-%d' % (basics.ClientRootKeeper.INCLUDE_SERVER_NAME, os.getpid(), generation), prefix) for generation, prefix in [(1,'/to/be'), (2, '/to')]]) return (dir == '/to/be' and '/to/be/xxxxxx' or dir == '/to' and '/to/xxxxxxx') def Mock_os_makedirs(f, *unused_args): if not f.startswith('/to/'): raise Exception(f) tempfile.mkdtemp = Mock_tempfile_mkdtemp os.makedirs = Mock_os_makedirs os.environ['DISTCC_CLIENT_TMP'] = '/to/be' client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(1) self.assertEqual(os.path.dirname(client_root_keeper.client_root), "/to/be") os.environ['DISTCC_CLIENT_TMP'] = '/to' client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(2) self.assertEqual(os.path.dirname( os.path.dirname(client_root_keeper.client_root)), "/to") self.assertEqual(os.path.basename(client_root_keeper.client_root), "padding") self.assertEqual(len( [ None for ch in client_root_keeper.client_root if ch == '/' ]), 3) finally: tempfile.mkdtemp = tempfile_mkdtemp os.makedirs = os_makedirs def test_ClientRootKeeper_Deletions(self): """Test whether directories emerge and go away appropriately.""" # Test with a one-level value of DISTCC_CLIENT_TMP. os.environ['DISTCC_CLIENT_TMP'] = '/tmp' client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(117) self.assertTrue(os.path.isdir(client_root_keeper._client_root_before_padding)) self.assertTrue(os.path.isdir(client_root_keeper.client_root)) self.assertTrue(client_root_keeper.client_root.endswith('/padding')) client_root_keeper.ClientRootMakedir(118) client_root_keeper.CleanOutClientRoots() # Directories must be gone now! self.assertTrue(not os.path.isdir( client_root_keeper._client_root_before_padding)) # Test with a two-level value of DISTCC_CLIENT_TMP. try: os.environ['DISTCC_CLIENT_TMP'] = tempfile.mkdtemp('basics_test', dir='/tmp') client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(117) self.assertTrue(os.path.isdir( client_root_keeper._client_root_before_padding)) self.assertTrue(os.path.isdir(client_root_keeper.client_root)) client_root_keeper.ClientRootMakedir(118) client_root_keeper.CleanOutClientRoots() self.assertTrue(os.path.isdir, client_root_keeper._client_root_before_padding) finally: os.rmdir(os.environ['DISTCC_CLIENT_TMP']) unittest.main() distcc-3.4/include_server/c_extensions/000077500000000000000000000000001404653710500203505ustar00rootroot00000000000000distcc-3.4/include_server/c_extensions/distcc_pump_c_extensions_module.c000066400000000000000000000274411404653710500271640ustar00rootroot00000000000000/* Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ // Author: Nils Klarlund /* distcc_pump_c_extensions_module.c -- Python bindings for distcc-pump * extensions */ #include "Python.h" static const char *version = ".01"; /* To suppress compiler warnings */ #define UNUSED(v) ((void)&v) const char *rs_program_name = "distcc_include_server"; #include "distcc.h" #include "rpc.h" static PyObject *distcc_pump_c_extensionsError; void initdistcc_pump_c_extensions(void); /*********************************************************************** CompressFileLZO1Z ***********************************************************************/ static char CompressLzo1xAlloc_doc__[] = "CompressFileLZO1Z__(in_buf):\n" "Compress file according to distcc lzo protocol.\n" "\n" " Arguments:\n" " in_buf: a string\n" " Raises:\n" " distcc_pump_c_extensions.Error\n" " Returns:\n" " a string, compressed according to distcc protocol\n."; static PyObject * CompressLzo1xAlloc(PyObject *dummy, PyObject *args) { PyObject *string_object; const char *in_buf; int in_len; char *out_buf; size_t out_len; UNUSED(dummy); if (!PyArg_ParseTuple(args, "s#", &in_buf, &in_len)) return NULL; if (in_len < 0) return NULL; if (dcc_compress_lzo1x_alloc(in_buf, in_len, &out_buf, &out_len)) { PyErr_SetString(distcc_pump_c_extensionsError, "Couldn't compress that."); return NULL; } string_object = PyBytes_FromStringAndSize(out_buf, out_len); free(out_buf); return string_object; } /*********************************************************************** Token protocol ************************************************************************/ static char RCwd_doc__[] = "Rcwd_doc__(ifd):\n" " Read value of current directory.\n" "\n" " Arguments:\n" " ifd: an integer file descriptor\n" " Raises:\n" " distcc_pump_c_extensions.Error\n" ; static PyObject * RCwd(PyObject *dummy, PyObject *args) { int ifd; char *value_str; UNUSED(dummy); if (!PyArg_ParseTuple(args, "i", &ifd)) return NULL; if (dcc_r_cwd(ifd, &value_str)) { PyErr_SetString(distcc_pump_c_extensionsError, "Couldn't read token string."); return NULL; } return PyUnicode_FromString(value_str); } static char RTokenString_doc__[] = "RTokenString(ifd, expect_token):\n" " Read value of expected token.\n" "\n" " Arguments:\n" " ifd: an integer file descriptor\n" " expect_token: a four-character string\n" " Raises:\n" " distcc_pump_c_extensions.Error\n" ; static PyObject * RTokenString(PyObject *dummy, PyObject *args) { int ifd; char *expect_token; char *value_str; UNUSED(dummy); if (!PyArg_ParseTuple(args, "is", &ifd, &expect_token)) return NULL; if (dcc_r_token_string(ifd, expect_token, &value_str)) { PyErr_SetString(distcc_pump_c_extensionsError, "Couldn't read token string."); return NULL; } return PyUnicode_FromString(value_str); } static char RArgv_doc__[] = "Rargv(ifd):\n" " Read argv values.\n" "\n" " Arguments:\n" " ifd: an integer file descriptor\n" " Raises:\n" " distcc_pump_c_extensions.Error\n" ; static PyObject * RArgv(PyObject *dummy, PyObject *args) { int i = 0; PyObject *list_object = NULL; int ifd; PyObject *string_object = NULL; char **argv; UNUSED(dummy); if (!PyArg_ParseTuple(args, "i", &ifd)) return NULL; if (dcc_r_argv(ifd, "ARGC", "ARGV", &argv)) { PyErr_SetString(distcc_pump_c_extensionsError, "Couldn't read that."); goto error; } if ((list_object = PyList_New(0)) == NULL) goto error; for (; argv[i]; i++) { string_object = PyUnicode_FromString(argv[i]); free(argv[i]); if (!string_object) { goto error; } if (PyList_Append(list_object, string_object) < 0) goto error; Py_XDECREF(string_object); } free(argv); return list_object; error: Py_XDECREF(list_object); Py_XDECREF(string_object); for (i = i + 1; argv[i]; i++) free(argv[i]); free(argv); return NULL; } static char XArgv_doc__[] = "XArgv(ifd, argv)\n" " Transmit list argv.\n" "\n" " Arguments:\n" " ifd: integer file descriptor\n" " argv: a list of strings\n" ; static PyObject * XArgv(PyObject *dummy, PyObject *args) { int i; char **ptr; PyObject *list_object; int ifd; int len; int ret; char **argv; UNUSED(dummy); if (!PyArg_ParseTuple(args, "iO!", &ifd, &PyList_Type, &list_object)) return NULL; len = PyList_Size(list_object); argv = ptr = (char **) calloc((size_t) len + 1, sizeof (char *)); if (ptr == NULL) { return PyErr_NoMemory(); } argv[len] = NULL; for (i = 0; i < len; i++) { PyObject *string_object; string_object = PyList_GetItem(list_object, i); /* borrowed ref */ /* TODO do it properly, catch exceptions for fancy Unicode symbols */ argv[i] = (char*)PyUnicode_AsUTF8(string_object); /* does not increase ref count */ } ret = dcc_x_argv(ifd, "ARGC", "ARGV", argv); free(argv); if (ret == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; } /*********************************************************************** OsPathExists ************************************************************************/ static /* const */ char OsPathExists_doc__[] = "OsPathExists(filepath):\n" " Libc version of os.path.exists.\n" "\n" " Arguments:\n" " filepath: a string\n" " Returns:\n" " True or False\n" ; static PyObject * OsPathExists(PyObject *dummy, PyObject *args) { const char *in; int len; int res; struct stat buf; UNUSED(dummy); if (!PyArg_ParseTuple(args, "s#", &in, &len)) return NULL; if (len < 0) return NULL; res = stat(in, &buf); if (res == -1) Py_RETURN_FALSE; if (res == 0) Py_RETURN_TRUE; assert(0); return NULL; } /*********************************************************************** OsPathIsFile ************************************************************************/ static /* const */ char OsPathIsFile_doc__[] = "OsPathIsFile(filename):\n" " Libc version of os.path.isfile.\n" "\n" " Arguments:\n" " filename: a string\n" " Returns:\n" " True or False\n" ; static PyObject * OsPathIsFile(PyObject *dummy, PyObject *args) { const char *in; int len; int res; struct stat buf; UNUSED(dummy); if (!PyArg_ParseTuple(args, "s#", &in, &len)) return NULL; if (len < 0) return NULL; res = stat(in, &buf); if (res == -1) Py_RETURN_FALSE; if ((res == 0) && S_ISREG(buf.st_mode)) Py_RETURN_TRUE; if ((res == 0) && !S_ISREG(buf.st_mode)) Py_RETURN_FALSE; return NULL; } /*********************************************************************** Realpath ***********************************************************************/ static /* const */ char Realpath_doc__[] = "Realpath(filename)\n" " Libc version of os.path.realpath.\n" "\n" " Arguments:\n" " filename: a string\n" " Returns:\n" " the realpath (or filename if it does not exist)\n" " The semantics of this function is probably not quite the same as that\n" " of os.path.realpath for paths that do not correspond to existing files.\n" " This is why we do not call it OsPathRealpath.\n" ""; /* TODO(klarlund): make logic so that this file will compile in the absence of realpath from libc. In that case, use Python realpath. */ static PyObject * Realpath(PyObject *dummy, PyObject *args) { const char *in; /* We explicitly allocate memory for the output 'resolved' of 'realpath' -- otherwise, some systems will make trouble because they do not accept passing the second argument NULL (as GNU does) for automatic buffer allocation. The glib function 'realpath' comes with the warning to not use it because it's difficult to predict the size of the output. We need the function, however, in its C version --- it's much, much faster than the Python implementation. (We measured about a factor 20 under Linux.) */ # if defined (PATH_MAX) # define DISTCC_PUMP_PATH_MAX PATH_MAX # elif defined (MAXPATHLEN) # define DISTCC_PUMP_PATH_MAX MAXPATHLEN # else # define DISTCC_PUMP_PATH_MAX 4096 // seems conservative for max filename len! # endif char resolved[DISTCC_PUMP_PATH_MAX]; # undef DISTCC_PUMP_PATH_MAX char *res; PyObject *result_str; UNUSED(dummy); if (!PyArg_ParseTuple(args, "s", &in)) return NULL; res = realpath(in, resolved); if (res) { /* On Solaris this result may be a relative path, if the argument was relative. Fail hard if this happens. */ assert(res[0] == '/'); result_str = PyUnicode_FromStringAndSize(res, strlen(res)); if (result_str == NULL) return PyErr_NoMemory(); return result_str; } else { return PyUnicode_FromStringAndSize(in, strlen(in)); } } /*********************************************************************** Bindings; ************************************************************************/ struct module_state { PyObject *error; }; #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) static const char module_documentation[]= "Various utilities for distcc-pump.\n" ; static int module_traverse(PyObject *m, visitproc visit, void *arg) { Py_VISIT(GETSTATE(m)->error); return 0; } static int module_clear(PyObject *m) { Py_CLEAR(GETSTATE(m)->error); return 0; } static PyMethodDef module_methods[] = { {"OsPathExists", (PyCFunction)OsPathExists, METH_VARARGS, OsPathExists_doc__}, {"OsPathIsFile", (PyCFunction)OsPathIsFile, METH_VARARGS, OsPathIsFile_doc__}, {"Realpath", (PyCFunction)Realpath, METH_VARARGS, Realpath_doc__}, {"RTokenString",(PyCFunction)RTokenString, METH_VARARGS, RTokenString_doc__}, {"RCwd", (PyCFunction)RCwd, METH_VARARGS, RCwd_doc__}, {"RArgv", (PyCFunction)RArgv, METH_VARARGS, RArgv_doc__}, {"XArgv", (PyCFunction)XArgv, METH_VARARGS, XArgv_doc__}, {"CompressLzo1xAlloc", (PyCFunction)CompressLzo1xAlloc, METH_VARARGS, CompressLzo1xAlloc_doc__}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "distcc_pump_c_extensions", /* m_name */ module_documentation, /* m_doc */ sizeof(struct module_state),/* m_size */ module_methods, /* m_methods */ NULL, /* m_reload */ module_traverse, /* m_traverse */ module_clear, /* m_clear */ NULL, /* m_free */ }; PyObject * PyInit_distcc_pump_c_extensions(void) { PyObject *module = PyModule_Create(&moduledef); PyObject *py_str; distcc_pump_c_extensionsError = PyErr_NewException( (char *)"distcc_pump_c_extensions.Error", NULL, NULL); if (module == NULL) return NULL; struct module_state *st = GETSTATE(module); st->error = distcc_pump_c_extensionsError; if (st->error == NULL) { Py_DECREF(module); return NULL; } py_str = PyUnicode_FromString("Nils Klarlund"); py_str = PyUnicode_FromString(version); PyModule_AddObject(module, "__author__", py_str); PyModule_AddObject(module, "__version__", py_str); /* Make the exception class accessible */ PyModule_AddObject(module, "Error", distcc_pump_c_extensionsError); return module; } distcc-3.4/include_server/c_extensions_test.py000077500000000000000000000104361404653710500217700ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # """Tests for distcc_pump_c_extensions. Writes out doc strings and calls some distcc rpc functions. Also, the program times the speed-up of using the libc versions of os.path.realpath and os.path.exists provided by distcc_pump_c_extensions. """ __author__ = 'opensource@google.com' import os.path import random import sys import time import distcc_pump_c_extensions def RunTest(random_filename): def _MakeTempFile(mode): return open(random_filename, mode) # Exercise metainformation and documentation strings assert distcc_pump_c_extensions.__file__ assert distcc_pump_c_extensions.__doc__ assert distcc_pump_c_extensions.__author__ assert distcc_pump_c_extensions.RTokenString.__doc__ assert distcc_pump_c_extensions.RArgv.__doc__ assert distcc_pump_c_extensions.XArgv.__doc__ assert distcc_pump_c_extensions.OsPathExists.__doc__ assert distcc_pump_c_extensions.OsPathIsFile.__doc__ assert distcc_pump_c_extensions.Realpath.__doc__ # RTokenString and RArgv # Pack something and try sending it fd = _MakeTempFile('wb') fd.write(b'ARGC 2') fd.write(b'ARGV 6') fd.write(b'tomato') fd.write(b'ARGV 7') fd.write(b'potatos') fd.close() # Now try to read it back with wrong expectations. fd = _MakeTempFile('rb') try: two_string = distcc_pump_c_extensions.RTokenString(fd.fileno(), 'XXXX') sys.exit('internal error 1 - we should not get to here') except distcc_pump_c_extensions.Error: pass # Read it back with appropriate expectations. fd.seek(0) two_string = distcc_pump_c_extensions.RTokenString(fd.fileno(), 'ARGC') if two_string != 'AR': raise distcc_pump_c_extensions.error('internal error 2') fd.seek(0) args = distcc_pump_c_extensions.RArgv(fd.fileno()) if args != ['tomato', 'potatos']: raise distcc_pump_c_extensions.error('internal error 3') fd.close() # XArgv and RArgv fd = _MakeTempFile('wb') darth_vader_barney = ['Darth Vader', 'Barney'] args = distcc_pump_c_extensions.XArgv(fd.fileno(), darth_vader_barney) fd.close() fd = _MakeTempFile('r') args = distcc_pump_c_extensions.RArgv(fd.fileno()) if args != darth_vader_barney: raise distcc_pump_c_extensions.error('internal error 4') fd.close() # Libc functions --- also print out how fast they are compared to # Python built-ins. t = time.time() f = '/' for unused_i in range(10000): distcc_pump_c_extensions.OsPathExists(f) print('Stat', time.time() - t) t = time.time() for unused_i in range(10000): os.path.exists(f) print('os.path.exists', time.time() - t) for unused_i in range(10000): distcc_pump_c_extensions.Realpath(f) print('c_realpath', time.time() - t) t = time.time() for unused_i in range(10000): os.path.realpath(f) print('os.path.realpath', time.time() - t) print('c_extenstions_test passed') def main(): # Module tempfile doesn't work with distcc. Work-around follows. random_testdir = ('/tmp/distcc-pump-c-extensions-test-%s.%s' % (os.getuid(), random.random() * time.time())) try: if os.path.exists(random_testdir): os.removedirs(random_testdir) os.mkdir(random_testdir) except (IOError, OSError) as why: sys.exit('Unable to create test dir %s: %s.' % (random_testdir, why)) random_filename = os.path.join(random_testdir, 'test') assert not os.path.exists(random_filename), random_filename try: RunTest(random_filename) finally: if os.path.exists(random_filename): os.unlink(random_filename) if os.path.exists(random_testdir): os.removedirs(random_testdir) main() distcc-3.4/include_server/cache_basics.py000077500000000000000000001105401404653710500206140ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # """Classes enabling definition and composition of caches. This file defines caches used to speed up the does-this-file-exist test that forms the basis of the C preprocessor's include-file handling, and takes most of its time. When the preprocessor sees a line like "#include " it looks for a file named "bar.h" in many directories: /usr/include/foo/bar.h, ./foo/bar.h, and so forth. More precisely, the preprocessor is given a "search path", which is a list of directory-names. (By default, the search-path looks like ['/usr/include', '/usr/local/include', ...], but it's often extended via gcc flags like -I, -isystem, -iprefix, etc.) To resolve a single #include like "#include ", the preprocessor goes through every directory in the search path, running os.stat(os.path.join(current_working_dir, search_dir, 'foo/bar.h')) until the stat call succeeds. With dozens of search-dirs to look through, dozens of #include lines per source file, and hundreds of source files per compilation, this can add up to millions of stat calls. Many of these calls are exactly the same, so caching is a big win. The cache of stat calls takes a filename as input and produces a bool as output, saying if the filename exists. For reasons that will become clear in a moment, we actually represent the input filename as a triple that breaks the filename into its three components: 1) currdir: the current working directory (usually os.path.absdir('.')) 2) searchdir: an element of the search path (eg '/usr/include', 'base') 3) includepath: the thing that comes after "#include" in source files ("foo/bar.h" in our examples above). Why do we break the input into three parts? Consider what cache-lookups we have to do for a single source file: cache[os.path.join(currdir, searchdir1, includepath1)] # #include cache[os.path.join(currdir, searchdir2, includepath1)] # #include cache[os.path.join(currdir, searchdir3, includepath1)] # #include [etc...until the cache-lookup returns True] cache[os.path.join(currdir, searchdir1, includepath2)] # #include cache[os.path.join(currdir, searchdir2, includepath2)] # #include cache[os.path.join(currdir, searchdir3, includepath2)] # #include [etc] By having the key be a triple, we avoid all those unnecessary os.path.join calls. But even if we do this, we notice bigger fish to fry: the Python interpreter still has to do a string-hash of currdir for every lookup, and also has to string-hash searchdirX and includepathX many times. It would be much more efficient if we did those hashes ourselves, reducing the number of string-hashes from O(|search-path| * |#include lines|) to O(|search-path| + |#include lines|). This motivates (finally!) the data structures in this file. We have three string-to-number maps, for mapping each currdir, searchdir, and includepath to a small integer. We put that all together in a cache, that takes a triple of integers as its key and produces True if the file exists, False if it does not, or None if its status is unknown. The String-to-number Map(s) --------------------------- The basic map that converts a filepath-path -- a currdir, searchdir, or includepath -- to a small integer is called MapToIndex. MapToIndex provides mapping in both directions: index: a dictionary mapping paths (strings) to indices in 1..N, and string: an array of size N + 1 that implements the reverse mapping So: obj.string[obj.index[path_as_string]] == path_as_string obj.index[obj.string[path_as_number]] == path_as_number Note we map from 1..N, and not 0..N-1, which leave us 0 free to use as a synonym for None or False. There are also classes that specialize MapToIndex for specific purposes. DirectoryMapToIndex assumes the input is a directory, and in particular a directory that does not have a slash at the end of it (eg "/etc"). It adds the trailing slash before inserting into the map. This is useful because it allows us to use + to join this directory with a relative filename, rather than the slower os.path.join(). RelpathMapToIndex assumes the input is a relative filepath, that is, one that does not start with /. When combined with DirectoryMapToIndex entries, + can be used as a fast alternative to os.path.join(). CanonicalMapToIndex is a MapToIndex that canonializes its input before inserting it into the map: resolving symlinks, getting rid of ..'s, etc. It takes an absolute path as input. Other Caches ------------ Besides the maps from strings to integers, there are three other caches. One is the realpath-cache, that takes a filename and returns os.path.realpath(filename). We cache this because os.path.realpath() is very slow. This is called CanonicalPath. The second cache, the DirnameCache, maps an arbitrary pathname to dirname(pathname), that is, the directory the pathname is in. The input pathname is represented by a (currdir_idx, searchdir_idx, includepath_idx) triple. The output is likewise represented as a number: an index into the DirectoryMapToIndex structure. The third cache is called SystemdirPrefixCache. It tells you, for a given absolute filepath, whether it is prefixed by a systemdir (that is, one of the searchdirs that's built into cpp, such as /usr/include). This is useful to cache because there are several systemdirs, and it's expensive to check them all each time. Naming Conventions ------------------ currdir: the current working dir. searchdir: an element of the search-path (places cpp looks for .h files). includepath: the string a source file #includes. realpath: a full filepath with all its symlinks resolved: os.path.realpath(os.path.join(currdir, searchdir, includepath)) FOO_idx: the small integer associated with the string FOO. includepath_map: the map that takes includepaths to their idx and back (a RelpathMapToIndex). directory_map: the map that takes currdirs and searchdirs to their idx and back. It also is used to store dirname(filepath) for arbitrary filepaths -- basically, anything we know is a directory (a DirectoryMapToIndex). realpath_map: the map that takes full filepaths to their idx and back, canonicalizing them first (by resolving symlinks) (a CanonicalMapToIndex). searchlist: a list of searchdirs. In gcc/cpp documentation, this is called the "search path", but for consistency, in this code we reserve the name "path" to mean "filesystem component," never "list of dirs". (A list of strings). systemdir: a searchdir that's built into cpp, rather than set via -I. (A string.) resolved_filepath: given an includepath, and a (possibly implicit) currdir and searchlist, the resolved_filepath is os.path.join(currdir, searchdir, includepath) for the first searchdir in searchlist for which the joined string exists. This path can be represented in many ways: 1) a string like "foo/bar/baz.h" (if so, this string has been canonicalized to resolve symlinks and the like); 2) an index into realpath_map associated with that string; 3) a triple of indices; or 4) a pair of indices plus an assumption that os.getcwd() == currdir. Pair Representation of Filepaths ------------------------------- A file is uniquely determined by the triple (currdir_idx, searchdir_idx, includepath_idx) For a single compilation unit, the code will often start with a chdir(currdir). After that, we often refer to a file by the pair (searchdir_idx, includepath_idx) which might be either an absolute filename or relative to $PWD. We refer to this pair as a filepath_pair. TODO(csilvers): find a better name? The function IsFilepathPair(x) tests whether x is a pair that could plausibly have a searchdir_idx as its first element and an includepath_idx as its second. Tests ----- This code is currently only tested by regression tests of modules using this one. """ __author__ = "opensource@google.com (Nils Klarlund, Craig Silverstein)" import os import os.path import sys import basics import statistics import compiler_defaults DIR_ARRAY_SIZE = 500 # We currently use the stat and realpath of GNU libc stat and # realpath. They are about an order of magnitude faster than their # Python counterparts, even when called through the Python/C # interface. try: import distcc_pump_c_extensions _OsPathExists = distcc_pump_c_extensions.OsPathExists _OsPathIsFile = distcc_pump_c_extensions.OsPathIsFile _PathRealpath = distcc_pump_c_extensions.Realpath _path_realpath_works = True except ImportError: _OsPathExists = os.path.exists _OsPathIsFile = os.path.isfile _PathRealpath = os.path.realpath # os.path.realpath might have some bugs. TODO(csilvers): check that here _path_realpath_works = False Debug = basics.Debug DEBUG_TRACE = basics.DEBUG_TRACE DEBUG_TRACE1 = basics.DEBUG_TRACE1 DEBUG_TRACE2 = basics.DEBUG_TRACE2 DEBUG_WARNING = basics.DEBUG_WARNING NotCoveredError = basics.NotCoveredError #### #### SIMPLE CACHES #### class CanonicalPath(object): """Memoizing calculation of realpaths. realpath(x) is the 'canonical' version of x, with all symbolic links eliminated. """ def __init__(self): self.cache = {} def Canonicalize(self, filepath): """Find a really canonical path, possibly memoized. Arguments: filepath: a filepath (string) Returns: the realpath of filepath (string) The following is irrelevant if we always use the distcc_pump_c_extensions realpath function. --- Apparently, in some versions of Python 2.4 at least, realpath does *not* resolve the last component of a filepath if it is a link: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1213894&group_id=5470 Make up for that: follow that final link until a real realpath has been found. Also, realpath is not idempotent. Solution (?): turn filepath into abspath before applying realpath; then we can cache results as well (without worring about value of current directory). The final problem -- that os.path.realpath is very slow, at least an order of magnitude slower than the gnu libc one --- is solved through caching all uses through an object of the present class. """ assert isinstance(filepath, str) try: return self.cache[filepath] except KeyError: if _path_realpath_works: r = _PathRealpath(filepath) self.cache[filepath] = r return r # Fix for os.path.realpath idempotencey bug (Python 2.4). filepath_ = os.path.abspath(filepath) filepath_ = _PathRealpath(filepath_) # Fix for os.path.realpath bug (Python 2.4): symlinks at end not # resolved. for unused_i in range(10): if not os.path.islink(filepath_): break filepath_ = os.path.join(os.path.dirname(filepath_), os.readlink(filepath_)) else: raise NotCoveredError("Too many symlinks in '%s'." % filepath) self.cache[filepath] = filepath_ return filepath_ class DirnameCache(object): """Cache the mapping from filepath pairs to index of their directory names. The key is a triple (currdir_idx, searchdir_idx, includepath_idx). The value is (dir_idx, dir_realpath_idx) where dir_idx is the index of dirname of the corresponding filepath, which possibly is relative, and dir_realpath_idx is the realpath index of the absolute location of the dirname. The value currdir_idx is of possible importance for deteterming dir_realpath_idx, but plays no role in determining dir_idx.""" def __init__(self, includepath_map, directory_map, realpath_map): """Constructor. Arguments: includepath_map: the map used to construct the includepath_idx that will be passed in as arguments to Lookup(). directory_map: the map used to construct both the currdir_idx and searchdir_idx that will be passed in as arguments to Lookup(). It's also the data structure that produces dir_idx. realpath_map: a string-to-int map of canonicalized filepaths """ self.includepath_map = includepath_map self.directory_map = directory_map self.realpath_map = realpath_map self.cache = {} def Lookup(self, currdir_idx, searchdir_idx, includepath_idx): """Return the directory and realpath indices of the dirname of the input. Arguments: currdir_idx: the directory index of the current directory searchdir_idx: a directory_map index includepath_idx: an includepath index Returns: a pair (directory map index, realpath index) See class documentation. Example: if the strings of the arguments indices put together make '/usr/include/foo/bar.h', then this routine will insert '/usr/include/foo/' into self.directory_map, and then return the corresponding pair (directory index of /usr/include/foo/, real path index of /usr/include/foo/). If the arguments put together form "foo.h", then the directory index returned is that of "", the current directory, and the realpath index is that of currdir. """ try: return self.cache[(currdir_idx, searchdir_idx, includepath_idx)] except KeyError: directory = os.path.dirname(os.path.join( self.directory_map.string[searchdir_idx], self.includepath_map.string[includepath_idx])) dir_idx = self.directory_map.Index(directory) rp_idx = self.realpath_map.Index( os.path.join(self.directory_map.string[currdir_idx], directory)) self.cache[(currdir_idx, searchdir_idx, includepath_idx)] = (dir_idx, rp_idx) return (dir_idx, rp_idx) class SystemdirPrefixCache(object): """A cache of information about whether a file exists in a systemdir. A systemdir is a searchdir that is built in to the C/C++ preprocessor. That is, when the preprocessor is figuring out what directory an #include is in, these are the directories it's hard-coded in to check (you can add other directories via -I). This cache records, for a given filepath, whether it starts with a systemdir. This is useful to identify whether the path is likely to correspond to a system include-file (such as stdio.h). Such files are unlikely to change, and are likely to already exist on the distcc servers, both of which are useful things to know for optimization. For speed, users can access self.cache directly, rather than going through the StartsWithSystemdir API. Be sure to call FillCache() to make sure the cache is populated, before accessing it! """ def __init__(self, systemdirs): """Constructor. Argument: systemdirs: the list of system-directories the preprocessor uses. It's a list of strings, probably extracted from the preprocessor itself. Each systemdir should end in a slash. In practice, systemdirs will start empty, and later some routine (in parse_command.py) will magically fill it. So be sure to wait for that before calling FillCache! TODO(csilvers): normalize this; ideally pass systemdirs in to FillCache. """ self.systemdirs = systemdirs # self.cache[i] will be True, False, or None for not-yet-checked. self.cache = [None] def FillCache(self, realpath_map): """Ensures that there's a cache entry for every index in realpath_map. Argument: realpath_map: a string-to-int map of canonicalized filepaths we know. After this function is called, the cache entry is True iff realpath.startswith(systemdir) is True for any of the systemdirs passed in to our constructor. """ if len(self.cache) >= realpath_map.Length(): return # we're already all full for realpath_idx in range(len(self.cache), realpath_map.Length()): realpath = realpath_map.string[realpath_idx] for systemdir in self.systemdirs: if realpath.startswith(systemdir): self.cache.append(True) break else: # we get here if the for never 'break'ed self.cache.append(False) assert len(self.cache) == realpath_map.Length() def StartsWithSystemdir(self, realpath_idx, realpath_map): """Return True iff realpath starts with a systemdir. Arguments: realpath_idx: the index of the realpath we want to check. realpath_map: the map from realpath_idx to a string. Return True iff realpath.startswith(systemdir) for any of the systemdirs passed in to our constructor. (For speed, you can access self.cache directly instead of calling this, but make sure FillCache() has been called first!) """ self.FillCache(realpath_map) return self.cache[realpath_idx] #### #### MAP_TO_INDEX AND ITS SPECIALIZATIONS #### class MapToIndex(object): """Maps every object it sees to a unique small integer. In practice, this class is used to map path-components (which are strings). """ def __init__(self): """Constructor. Instance variables: map: a dictionary such that map[path] is the index of path string: a list satisfying: string[i] is the path such that map[path] = i """ # Do not make the mistake of letting a real index be 0. (Hint: # because "if path:" then does not distinguish between 0 and None.) self.index = {None:None} self.string = [None] def _Invariant_(self): return len(self.index) == len(self.string) def Index(self, path): """Returns the index i > 0 of path.""" assert self._Invariant_() try: return self.index[path] except KeyError: self.index[path] = len(self.string) self.string.append(path) return len(self.string) - 1 def String(self, i): """Returns the path such that Index(path) == i.""" assert self._Invariant_() assert 0 < i < self.Length() return self.string[i] def Length(self): """One more than the number of elements indexed.""" assert self._Invariant_() return len(self.string) class DirectoryMapToIndex(MapToIndex): """Like a normal MapToIndex, but assumes the keys are directories, and in particular, directories without a trailing slash (eg "/etc"). It stores the directories in the map, but appends the trailing slash first. This is another type of normalization, and useful for cheap path-joining (eg using + instead of os.path.join). """ def Index(self, directory): """Return index d > 0 of normalized directory. Argument: directory: a string, either empty or not ending in '/'. The empty string is not changed, but other strings are stored with a '/' appended. """ if directory != "" and directory != "/": assert directory[-1] != '/', directory directory = directory + '/' return MapToIndex.Index(self, directory) class RelpathMapToIndex(MapToIndex): """Like a normal MapToIndex, but assumes the keys are relative filesystem paths, that is, filesystem paths not starting with /. This is useful for "cheap" normalization: this invariant ensures that os.path.join(some-directorymap-string, some-relpathmap-string) can be implemented using +. We actually do allow storing absolute paths if option --unsafe_absolute_includes is in use. But, then, we're careful in Resolve (below) to bail out. """ def Index(self, relpath, ignore_absolute_path_warning=False): """Return index d > 0 of relative path. Args: directory: a string not starting with /. ignore_absolute_path_warning: a Boolean The variable ignore_absolute_path_warning is set to True in order to override the requirement that filepaths are relative. This is useful for the compilation unit filepath and filepaths of -include's: they are permitted to be absolute because the command line can still be rewritten on the server. The server tweaks their location to become relative to the server root. """ if os.path.isabs(relpath) and not ignore_absolute_path_warning: if basics.opt_unsafe_absolute_includes: Debug(DEBUG_WARNING, "absolute filepath '%s' was IGNORED" " (correctness of build may be affected)", relpath) else: raise NotCoveredError("Filepath must be relative but isn't: '%s'." " Consider setting INCLUDE_SERVER_ARGS='--" "unsafe_absolute_includes'." % relpath, send_email=False) # Now, remove leading "./" so as not to start an infinite regression when # say foo.c contains: # # #include "./foo.c" # # which mighy seduce a recursive include analyzer down the forbidden path: # # "foo.c", # "./foo.c", "././foo.c." etc. while relpath.startswith("./"): relpath = relpath[2:] return MapToIndex.Index(self, relpath) class CanonicalMapToIndex(MapToIndex): """Like a normal MapToIndex, but assumes the keys are absolute filepaths, and canonicalizes them before inserting into the map. 'Canonicalize' means to do the equivalent of os.path.realpath(), which mostly involves resolving symlinks in the filepath. """ def __init__(self, canonicalize): """Constructor. Argument: canonicalize: an instance of the CanonicalPath cache.""" MapToIndex.__init__(self) self.canonicalize = canonicalize def Index(self, filepath): """Return the realpath index r of filepath. filepath should be an absolute filename. """ return MapToIndex.Index(self, self.canonicalize(filepath)) def RetrieveDirectoriesExceptSys(directory_map, realpath_map, systemdir_prefix_cache, directory_idxs): """Calculate the set of non-system directories of an index list. Arguments: directory_map: a DirectoryMapToIndex cache realpath_map: a CanonicalMapToIndex cache directory_idxs: a list or tuple of directory_map indices Returns: the corresponding tuple of directories except for those whose realpath has a prefix that is a sysdir The directories in the returned list have their trailing '/' stripped. """ result = [] for dir_idx in directory_idxs: # Index the absolute path; this will let us know whether dir_idx is under a # default systemdir of the compiler. rp_idx = realpath_map.Index(os.path.join( os.getcwd(), directory_map.string[dir_idx])) systemdir_prefix_cache.FillCache(realpath_map) if not systemdir_prefix_cache.cache[rp_idx]: result.append(directory_map.string[dir_idx].rstrip('/')) return tuple(result) #### #### THE STAT CACHES #### class SimpleBuildStat(object): """Stat cache that works with strings, not indices.""" def __init__(self): self.cache = {} def Lookup(self, filepath): """Returns true if filepath exists.""" try: return self.cache[filepath] except KeyError: result = self.cache[filepath] = _OsPathExists(filepath) return result class BuildStatCache(object): """A highly optimized mechanism for stat queries of filepaths, as represented by a triple of indexes: currdir_idx, searchdir_idx, filepath_idx. Given this input, we can say whether a regular file represented by this triple exists on the filesystem, and if so, what its canonical pathname is: that is, the pathname after all symlinks have been resolved. The hash table is three-level structure: - build_stat[currdir_idx] contains an array for each includepath_idx - build_stat[currdir_idx][includepath_idx] is this array, and - build_stat[currdir_idx][includepath_idx][searchdir_idx] is either * False if os.path.join(currdir, searchdir, includepath) does not exist * True if it does * None when it is not known whether it exists or not In addition, we keep a parallel structure for the realpath, that lets us quickly map from a filepath to os.path.realpath(filepath). - real_stat[currdir_idx] contains an array for each fp - real_stat[currdir_idx][includepath_idx] is this array, and - real_stat[currdir_idx][includepath_idx][searchdir_idx] is either * realpath_idx, such that realpath_map.string[realpath_idx] = os.path.realpath(os.path.join(currdir, searchdir, includepath)) when build_stat[currdir_idx][includepath_idx][searchdir_idx] = True * None, otherwise """ def __init__(self, includepath_map, directory_map, realpath_map): self.build_stat = {} self.real_stat = {} self.includepath_map = includepath_map self.directory_map = directory_map self.realpath_map = realpath_map self.path_observations = [] def _Verify(self, currdir_idx, searchdir_idx, includepath_idx): """Verify that the cached result is the same as obtained by stat call. Prerequisite: we've done a chdir(currdir) before this call. """ assert 1 <= includepath_idx < self.includepath_map.Length() assert 1 <= searchdir_idx < self.directory_map.Length() if __debug__: statistics.sys_stat_counter += 1 # Since we know directory_map entries end in /, and includepaths don't # start with / (who does "#include "??), we can # use + instead of the more expensive os.path.join(). # Make sure $PWD is currdir, so we don't need to include it in our stat(). assert os.getcwd() + '/' == self.directory_map.string[currdir_idx] really_exists = _OsPathIsFile( self.directory_map.string[searchdir_idx] + self.includepath_map.string[includepath_idx]) cache_exists = self.build_stat[currdir_idx][includepath_idx][searchdir_idx] assert isinstance(cache_exists, bool) if cache_exists != really_exists: filepath = os.path.join(self.directory_map.string[currdir_idx], self.directory_map.string[searchdir_idx], self.includepath_map.string[includepath_idx]) sys.exit("FATAL ERROR: " "Cache inconsistency: '%s' %s, but earlier this path %s." % ( filepath, really_exists and "exists" or "does not exist", cache_exists and "existed" or "did not exist")) def WarnAboutPathObservations(self, translation_unit): """Print new paths found according to path observation expression option. Args: translation_unit: a string embedded in warning """ for (includepath, relpath, realpath) in self.path_observations: Debug(DEBUG_WARNING, "For translation unit '%s'," " lookup of file '%s' resolved to '%s' whose realpath is '%s'.", translation_unit, includepath, relpath, realpath) self.path_observations = [] def Resolve(self, includepath_idx, currdir_idx, searchdir_idx, searchlist_idxs): """Says whether (currdir_idx, searchdir_idx, includepath_idx) exists, and if so what its canonicalized form is (with symlinks resolved). TODO(csilvers): rearrange the order of the arguments. Args: includepath_idx: The index of an includepath, from e.g. "#include " currdir_idx: The index of the current working dir. Note that we require os.getcwd() == currdir before calling Resolve! searchdir_idx: A single searchdir, which is prepended to searchlist, or None to not prepend to the searchlist. searchlist_idxs: A list of directory indices. Returns: 1) (None, None) if, for all sl_idx in [searchdir_idx] + searchlist_idxs, os.path.join(currdir, sp, includepath) does not exist. 2) ((sl_idx, includepath_idx), realpath_idx) if, for some sl_idx in [searchdir_idx] + searchlist_idxs, os.path.join(currdir, sp, includepath) does exist. In this case, sl_idx is the index of the first searchlist entry for which the exists-test succeeds, and realpath_idx is the index into the realpath_map of os.path.join(currdir, sp, includepath). Again, we require as a prequesite that os.getcwd() must equal currdir: os.getcwd() + '/' == self.directory_map.string[currdir_idx] """ includepath = self.includepath_map.string[includepath_idx] if includepath.startswith('/'): # We really don't want to start exploring absolute includepaths; what's # the sl_idx to return for example? And what about the use of '+' # (as an optimization) below instead of os.path.join. return (None, None) dir_map_string = self.directory_map.string # memoize the fn pointer build_stat = self.build_stat real_stat = self.real_stat if __debug__: dir_map = self.directory_map assert 0 < includepath_idx < self.includepath_map.Length() assert 0 < currdir_idx < dir_map.Length() assert searchdir_idx is None or 1 <= searchdir_idx < dir_map.Length() for sl_idx in searchlist_idxs: assert sl_idx < dir_map.Length() assert os.getcwd() + '/' == dir_map_string[currdir_idx] Debug(DEBUG_TRACE2, "Resolve: includepath: '%s', currdir: '%s', " "searchdir: '%s', searchlist: %s" % (includepath, dir_map_string[currdir_idx], searchdir_idx and dir_map_string[searchdir_idx], " \n".join([dir_map_string[idx] for idx in searchlist_idxs]))) try: # Locate the array (list) relative to currdir_idx and includepath_idx searchdir_stats = build_stat[currdir_idx][includepath_idx] # Locate the corresponding array of realpath names searchdir_realpaths = real_stat[currdir_idx][includepath_idx] except KeyError: # We'll need to grow the relevant arrays currdir_stats = build_stat.setdefault(currdir_idx, {}) currdir_realpaths = real_stat.setdefault(currdir_idx, {}) searchdir_stats = currdir_stats[includepath_idx] = \ [None] * DIR_ARRAY_SIZE searchdir_realpaths = currdir_realpaths[includepath_idx] = \ [None] * DIR_ARRAY_SIZE # Try searchdir_idx if not None, then try every index in searchlist_idxs. # This inner loop may be executed tens of millions of times. # Do not try to form [searchdir_idx] + searchlist_idxs -- too expensive! for searchlist in (searchdir_idx and [searchdir_idx] or [], searchlist_idxs): for sl_idx in searchlist: if __debug__: statistics.search_counter += 1 statistics.build_stat_counter += 1 try: # We expect that searchdir_stats[sl_idx] == False, because # we've usually seen sl_idx before for our includepath and # our currdir --- and includepath does not usually exist # relative to the sp directory. We're optimizing for this # case of course. That should give us a rate of a couple of # million iterations per second (for this case). if searchdir_stats[sl_idx] == False: if __debug__: self._Verify(currdir_idx, sl_idx, includepath_idx) continue if searchdir_stats[sl_idx]: if __debug__: self._Verify(currdir_idx, sl_idx, includepath_idx) return ((sl_idx, includepath_idx), searchdir_realpaths[sl_idx]) except IndexError: # DIR_ARRAY_SIZE wasn't big enough; let's double searchdir_stats.extend([None] * max(sl_idx, len(searchdir_stats))) searchdir_realpaths.extend([None] * max(sl_idx, len(searchdir_stats))) # If we get here, result is not cached yet. if __debug__: statistics.sys_stat_counter += 1 # We do not explicitly take into account currdir_idx, because # of the check above that os.getcwd is set to current_dir. relpath = dir_map_string[sl_idx] + includepath if _OsPathIsFile(relpath): searchdir_stats[sl_idx] = True rpath = os.path.join(dir_map_string[currdir_idx], relpath) realpath_idx = searchdir_realpaths[sl_idx] = ( self.realpath_map.Index(rpath)) # This is the place to catch errant files according to user defined # regular expression path_observation_re. if basics.opt_path_observation_re: realpath = self.realpath_map.string[realpath_idx] if basics.opt_path_observation_re.search(realpath): self.path_observations.append((includepath, relpath, realpath)) return ((sl_idx, includepath_idx), realpath_idx) else: searchdir_stats[sl_idx] = False if __debug__: Debug(DEBUG_TRACE2, "Resolve: failed") return (None, None) class SetUpCaches(object): """Erect the edifice of caches. Instance variables: includepath_map: RelpathMapToIndex directory_map: DirectoryMapToIndex realpath_map: CanonicalMapToIndex canonical_path: CanonicalPath build_stat_cache: BuildStatCache dirname_cache: DirnameCache simple_build_stat: SimpleBuildStat client_root: a path such as /dev/shm/tmpX.include_server-X-1 (used during default system dir determination) IsFilepathIndex: test for filepath index IsDirectoryIndex: test for director index IsRealpathIndex: test for realpath index IsFilepathPair: test for filepath pair """ def __init__(self, client_root): # A memoizing (caching) class to canonicalize a path: mostly by # resolving any symlinks in the path-component. self.canonical_path = CanonicalPath() # The index-map for includepath names: things seen after '#include'. self.includepath_map = RelpathMapToIndex() # The index-map for searchdir names and currdir as well. Also used any # other time we have something we know is a directory (eg dirname(foo)). self.directory_map = DirectoryMapToIndex() # The index-map for realpaths: the full pathname of an include, with # symlinks resolved and such (hence the name realpath). self.realpath_map = CanonicalMapToIndex(self.canonical_path.Canonicalize) # A cache of the directory part of filepaths. Note it uses the # directory_map to actually store the mapping. self.dirname_cache = DirnameCache(self.includepath_map, self.directory_map, self.realpath_map) # A cache of whether a realpath starts with a system searchdir or # not. Note: at this time, system_dirs_default_all will be empty. # It will get filled via processing in parse_command.py. This is # why we need to store the compiler_defaults instance, to make # sure "our" system_dirs_default_all is updated. # TODO(csilvers): get rid of this once prefix_cache TODO is cleaned up self.compiler_defaults = compiler_defaults.CompilerDefaults( self.canonical_path.Canonicalize, client_root) self.systemdir_prefix_cache = SystemdirPrefixCache( self.compiler_defaults.system_dirs_default_all) # The main caches, that say whether a file exists or not. We have # two: a simple one that takes a filepath (string) as an argument, # and the complicated one that works with index-triples. self.simple_build_stat = SimpleBuildStat() self.build_stat_cache = BuildStatCache(self.includepath_map, self.directory_map, self.realpath_map) # Convenient function closures to test for various semantic datatypes. self.IsIncludepathIndex = (lambda x: isinstance(x, int) and 0 < x < self.includepath_map.Length()) self.IsSearchdirIndex = (lambda x: isinstance(x, int) and 0 < x < self.directory_map.Length()) self.IsCurrdirIndex = (lambda x: isinstance(x, int) and 0 < x < self.directory_map.Length()) self.IsFilepathPair = (lambda x: isinstance(x, tuple) and len(x) == 2 and self.IsSearchdirIndex(x[0]) and self.IsIncludepathIndex(x[1])) self.IsRealpathIndex = (lambda x: isinstance(x, int) and 0 < x < self.realpath_map.Length()) distcc-3.4/include_server/compiler_defaults.py000077500000000000000000000375251404653710500217410ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Divination of built-in system directories used by compiler installation. It is undesirable for the distcc-pump to send header files that reside under the built-in search path. In a correct compiler installation, these files must already be present on the server. This module lets the distcc-pump run the compiler in a special mode that allows the built-in system directories to be revealed. The current code is tested only for gcc 4.1.1. TODO(klarlund) Find out what other versions this code works for. TODO(klarlund) The include server halts if the built-in system directories cannot be determined. Should this be improved upon? """ __author__ = "Nils Klarlund" import os import re import sys import basics import shutil import subprocess Debug = basics.Debug DEBUG_TRACE = basics.DEBUG_TRACE DEBUG_DATA = basics.DEBUG_DATA NotCoveredError = basics.NotCoveredError def _RealPrefixWithinClientRoot(client_root, path): """Determine longest directory prefix of PATH and whether PATH contains a symlink. Given an absolute path CLIENT_ROOT and an absolute path PATH that is interpreted as relative to CLIENT_ROOT, figure out the longest prefix of PATH such that every component of the prefix is a directory -- not a file or symlink -- when interpreted relative to CLIENT_ROOT. Args: path: a string starting with '/' Returns: a pair consisting of - the prefix - a bool, which is True iff PATH contained a symlink. """ prefix = "/" parts = path.split('/') while prefix != path: part = parts.pop(0) last_prefix = prefix prefix = os.path.join(prefix, part) if os.path.islink(client_root + prefix): return last_prefix, True if not os.path.isdir(client_root + prefix): return last_prefix, False return path, False def _MakeLinkFromMirrorToRealLocation(system_dir, client_root, system_links): """Create a link under client root what will resolve to system dir on server. See comments for CompilerDefaults class for rationale. Args: system_dir: a path such as /usr/include or /usr/lib/gcc/i486-linux-gnu/4.0.3/include client_root: a path such as /dev/shm/tmpX.include_server-X-1 system_links: a list of paths under client_root; each denotes a symlink The link is created only if necessary. So, /usr/include/gcc/i486-linux-gnu/4.0.3/include is not created if /usr/include is already in place, since it's a prefix of the longer path. If a link is created, the symlink name will be appended to system_links. For example, if system_dir is '/usr/include' and client_root is '/dev/shm/tmpX.include_server-X-1', then this function will create a symlink in /dev/shm/tmpX.include_server-X-1/usr/include which points to ../../../../../../../../../../../../usr/include, and it will append '/dev/shm/tmpX.include_server-X-1/usr/include' to system_links. """ if not system_dir.startswith('/'): raise ValueError("Expected absolute path, but got '%s'." % system_dir) if os.path.realpath(system_dir) != system_dir: raise NotCoveredError( "Default compiler search path '%s' must be a realpath." %s) # Typical values for rooted_system_dir: # /dev/shm/tmpX.include_server-X-1/usr/include real_prefix, is_link = _RealPrefixWithinClientRoot(client_root, system_dir) parent = os.path.dirname(system_dir) rooted_system_dir = client_root + system_dir rooted_parent = client_root + parent if real_prefix == system_dir: # rooted_system_dir already exists as a real (non-symlink) path. # Make rooted_system_dir a link. # # For example, this could happen if /usr/include/c++/4.0 and # /usr/include are both default system directories. # First we'd call this function with /usr/include/c++/4.0, # and it would call os.mkdirdirs() to create # /dev/shm/tmpX.include_server-X-1/usr/include/c++, # and then it would create a symlink named 4.0 within that. # Then we'd call this function again with /usr/include. # In this case, we can replace the whole subtree with a single symlink # at /dev/shm/tmpX.include_server-X-1/usr/include. shutil.rmtree(rooted_system_dir) system_links[:] = filter(lambda path : not path.startswith(rooted_system_dir), system_links) elif real_prefix == parent: # The really constructed path does not extend beyond the parent directory, # so we're all set to create the link if it's not already there. if os.path.exists(rooted_system_dir): assert os.path.islink(rooted_system_dir) return elif not is_link: os.makedirs(rooted_parent) else: # A link above real_prefix has already been created with this routine. return assert _RealPrefixWithinClientRoot(client_root, parent) == (parent, False), (client_root, parent) depth = len([c for c in system_dir if c == '/']) # The more directories on the path system_dir, the more '../' need to # appended. We add enough '../' to get to the root directory. It's OK # if we have too many, since '..' in the root directory points back to # the root directory. # TODO(klarlund,fergus): do this in a more principled way. # This probably requires changing the protocol. os.symlink('../' * (basics.MAX_COMPONENTS_IN_SERVER_ROOT + depth) + system_dir[1:], # remove leading '/' rooted_system_dir) system_links.append(rooted_system_dir) def _SystemSearchdirsGCC(compiler, sysroot, language, canonical_lookup): """Run gcc on empty file; parse output to figure out default paths. This function works only for gcc, and only some versions at that. Arguments: compiler: a filepath (the first argument on the distcc command line) sysroot: the --sysroot passed to the compiler ("" to disable) language: 'c' or 'c++' or other item in basics.LANGUAGES canonical_lookup: a function that maps strings to their realpaths Returns: list of system search dirs for this compiler and language """ # We are trying to wring the following kind of text out of the # compiler: #-------------------- # blah. blah. # ... # blah. blah. # #include "..." search starts here: # #include <...> search starts here: # /usr/local/include # /usr/lib/gcc/i486-linux-gnu/4.0.3/include # /usr/include # End of search list. # blah. blah. #------------ command = [compiler] if sysroot: command += ["--sysroot=" + sysroot] command += ["-x", language, "-v", "-c", "/dev/null", "-o", "/dev/null"] Debug(DEBUG_DATA, "system search dirs command: %s" % command) try: # We clear the environment, because otherwise, directories # declared by CPATH, for example, will be incorporated into the # result. (See the CPP manual for the meaning of CPATH.) The only # thing we keep is PATH, so we can be sure to find the compiler. # NOTE: having the full PATH can be tricky: what if there's a gcc # -> distcc symlink somewhere on the PATH, before the real gcc? # We think the right thing will happen here, but it's complicated. # TODO(csilvers): it's possible we could need to pass in some # other environment vars, like LD_LIBRARY_PATH. Instead of adding # in more env-vars by hand, consider just removing from os.environ # all the env-vars that are meaningful to gcc, such as CPATH. See # http://docs.freebsd.org/info/gcc/gcc.info.Environment_Variables.html, # or the "Environment Variables Affecting GCC" section of the gcc # info page. if 'PATH' in os.environ: trimmed_env = {'PATH': os.environ['PATH']} else: trimmed_env = {} p = subprocess.Popen(command, shell=False, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=trimmed_env,universal_newlines=True) out = p.communicate()[0] except (IOError, OSError) as why: raise NotCoveredError ( ( "Couldn't determine default system include directories\n" + "for compiler '%s', language '%s':\n" + "error executing '%s': %s.") % (compiler, language, command, why)) if p.returncode != 0: raise NotCoveredError( ( "Couldn't determine default system include directories\n" + "for compiler '%s', language '%s':\n" + "command '%s' exited with status '%d'.\n Command output:\n%s") % (compiler, language, command, p.returncode, out)) match_obj = re.search( "%s\n(.*?)\n%s" # don't ask % ("#include <...> search starts here:", "End of search list"), out, re.MULTILINE + re.DOTALL) if match_obj == None: raise NotCoveredError( ( "Couldn't determine default system include directories\n" + "for compiler '%s', language '%s':\n" + "couldn't parse output of '%s'.\nReceived:\n%s") % (compiler, language, command, out)) return [ canonical_lookup(directory) for line in match_obj.group(1).split("\n") for directory in line.split() # Ignore Apple-modified MacOS gcc's "framework" directories. if not line.endswith(" (framework directory)") ] # TODO: Rather than just ignoring framework directories, we # should handle them properly, fully emulating the search # algorithm used by Apple's modified GCC. # The search algorithm used for framework directories is not very # well documented, as far as I can tell, but the source code is in # gcc/config/darwin-c.c in the Apple GCC sources. # From a quick glance, I think it looks like this: # - For each #include of the form Foo/bar.h, # For each framework directory Baz, # Look in Baz/Foo.framework/Headers/bar.h # and in Baz/Foo.framework/PrivateHeaders/bar.h # - If the regular search fails, look for subframeworks. # For each #include of the form Foo/bar.h # from Baz/Quux.framework/Headers/whatever.h # Look in Baz/Quux.framework/Frameworks/Foo/Headers/bar.h. class CompilerDefaults(object): """Records and caches the default search dirs and creates symlink farm. This function works only for gcc, and only some versions at that, because we parse the output from gcc to determine the default search dirs. The 'default' searchdirs are those on the search-path that are built in, that is known to the preprocessor, as opposed to being set on the commandline via -I et al. When we pass an option such as -I/foo/bar to the server, the server will rewrite it to say -I/server/path/root/foo/bar, where /server/path/root is the temporary directory on the server that corresponds to root on the client (e.g. typically /dev/shm/distccd_nnn). This causes problems in this case of -I options such as -I/usr/include/foo, where the path contains a 'default' search directory (in this case /usr/include) as a prefix. Header files under the system default directories are assumed to exist on the server, and it would be expensive to send them to the server unnecessarily (we measured it, and it slowed down the build of Samba by 20%). So for -I options like -I/usr/include/foo, we want the server to use /usr/include/foo on the server, not /server/path/root/usr/include/foo. Because the server unconditionally rewrites include search paths on the command line to be relative to the server root, we must take corrective action when identifying default system dirs: references to files under these relocated system directories must be redirected to the absolute location where they're actually found. To do so, we create a symlink forest under client_root. This will contain symlinks of the form usr/include -> ../../../../../../../../../../../../usr/include After being sent to the server, the server will rewrite them as /server/path/root/usr/include -> /server/path/root/../../../../../../../../../../../../usr/include which will make /server/path/root/usr/include become a symlink to /usr/include Consequently, an include search directory such as -I /usr/include/foo will work on the server, even after it has been rewritten to: -I /server/path/root/usr/include/foo """ def __init__(self, canonical_lookup, client_root): """Constructor. Instance variables: system_dirs_real_paths: a dictionary such that system_dirs_real_paths[c][lang] is a list of directory paths (strings) for compiler c and language lang system_dirs_default: a list of all such strings, subjected to realpath-ification, for all c and lang client_root: a path such as /dev/shm/tmpX.include_server-X-1 system_links: locations under client_root representing system default dirs """ self.canonical_lookup = canonical_lookup self.system_dirs_default_all = set([]) self.system_dirs_default = {} self.system_links = [] self.client_root = client_root def SetSystemDirsDefaults(self, compiler, sysroot, language, timer=None): """Set instance variables according to compiler, and make symlink farm. Arguments: compiler: a filepath (the first argument on the distcc command line) sysroot: the --sysroot passed to the compiler ("" to disable) language: 'c' or 'c++' or other item in basics.LANGUAGES timer: a basis.IncludeAnalyzerTimer or None The timer will be disabled during this routine because the select involved in Popen calls does not handle SIGALRM. See also the class documentation for this class. """ assert isinstance(compiler, str) assert isinstance(language, str) Debug(DEBUG_TRACE, "SetSystemDirsDefaults with CC, SYSROOT, LANG: %s, %s, %s" % (compiler, sysroot, language)) if compiler in self.system_dirs_default: if sysroot in self.system_dirs_default[compiler]: if language in self.system_dirs_default[compiler][sysroot]: return else: self.system_dirs_default[compiler][sysroot] = {} else: self.system_dirs_default[compiler] = {sysroot: {}} try: if timer: # We have to disable the timer because the select system call that is # executed when calling the compiler through Popen gives up if presented # with a SIGALRM. timer.Stop() self.system_dirs_default[compiler][sysroot][language] = ( _SystemSearchdirsGCC(compiler, sysroot, language, self.canonical_lookup)) Debug(DEBUG_DATA, "system_dirs_default[%s][%s][%s]: %s" % (compiler, sysroot, language, self.system_dirs_default[compiler][sysroot][language])) # Now summarize what we know and add to system_dirs_default_all. self.system_dirs_default_all |= ( set(self.system_dirs_default[compiler][sysroot][language])) # Construct the symlink farm for the compiler default dirs. for system_dir in self.system_dirs_default[compiler][sysroot][language]: _MakeLinkFromMirrorToRealLocation(system_dir, self.client_root, self.system_links) finally: if timer: timer.Start() distcc-3.4/include_server/compress_files.py000077500000000000000000000116571404653710500212530ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Compress files in an include closure.""" import os import sys import os.path import distcc_pump_c_extensions class CompressFiles(object): def __init__(self, includepath_map, directory_map, realpath_map, mirror_path): """Constructor. Arguments: includepath_map: MapToIndex, holds idx-to-string info for includepaths directory_map: DirectoryMapToIndex realpath_map: CanonicalMapToIndex """ self.includepath_map = includepath_map self.directory_map = directory_map self.realpath_map = realpath_map self.mirror_path = mirror_path # The realpath_map indices of files that have been compressed already. self.files_compressed = set([]) def Compress(self, include_closure, client_root_keeper, currdir_idx): """Copy files in include_closure to the client_root directory, compressing them as we go, and also inserting #line directives. Arguments: include_closure: a dictionary, see IncludeAnalyzer.RunAlgorithm client_root_keeper: an object as defined in basics.py Returns: a list of filepaths under client_root Walk through the files in the include closure. Make sure their compressed images (with either .lzo or lzo.abs extension) exist under client_root as handled by client_root_keeper. Also collect all the .lzo or .lzo.abs filepaths in a list, which is the return value. """ realpath_string = self.realpath_map.string files = [] # where we accumulate files for realpath_idx in include_closure: # Thanks to symbolic links, many absolute filepaths may designate # the very same canonical path (as calculated by realpath). The # first such one to be discovered is the one used. realpath = realpath_string[realpath_idx] if len(include_closure[realpath_idx]) > 0: # Designate by suffix '.abs' that this file is to become known by an # absolute filepath through a #line directive. new_filepath = "%s%s.lzo.abs" % (client_root_keeper.client_root, realpath) else: new_filepath = "%s%s.lzo" % (client_root_keeper.client_root, realpath) files.append(new_filepath) if not new_filepath in self.files_compressed: self.files_compressed.add(new_filepath) dirname = os.path.dirname(new_filepath) try: if not os.path.isdir(dirname): my_root = client_root_keeper.client_root self.mirror_path.DoPath(realpath, currdir_idx, my_root) except (IOError, OSError) as why: # Kill include server sys.exit("Could not make directory '%s': %s" % (dirname, why)) if new_filepath.endswith('.abs'): (searchdir_idx, includepath_idx) = include_closure[realpath_idx][0] # TODO(csilvers): can't we use + here instead of os.path.join? filepath = os.path.join(self.directory_map.string[searchdir_idx], self.includepath_map.string[includepath_idx]) # This file is included through say -I/foo, but /foo does not exist # on the compiler server. Instead, this file will put under some # /serverrootpath/foo there. The #line directive informs the compiler # about the real location. This is useful for error messages. prefix = ("""#line 1 "%s"\n""" % filepath) else: # This file will be relatively resolved on the served. No need to # change its name. prefix = "" try: real_file_fd = open(realpath, "r", encoding='latin-1') except (IOError, OSError) as why: sys.exit("Could not open '%s' for reading: %s" % (realpath, why)) try: new_filepath_fd = open(new_filepath, "wb") except (IOError, OSError) as why: sys.exit("Could not open '%s' for writing: %s" % (new_filepath, why)) try: new_filepath_fd.write( distcc_pump_c_extensions.CompressLzo1xAlloc( prefix + real_file_fd.read())) except (IOError, OSError) as why: sys.exit("Could not write to '%s': %s" % (new_filepath, why)) new_filepath_fd.close() real_file_fd.close() return files distcc-3.4/include_server/include_analyzer.py000077500000000000000000000412251404653710500215600ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """The skeleton for an include analyzer. This module defines the basic caches and helper functions for an include analyzer. """ __author__ = "Nils Klarlund" import os import glob import basics import macro_eval import parse_file import parse_command import statistics import cache_basics import mirror_path import compress_files Debug = basics.Debug DEBUG_TRACE = basics.DEBUG_TRACE NotCoveredError = basics.NotCoveredError class IncludeAnalyzer(object): """The skeleton, including caches, of an include analyzer.""" def _InitializeAllCaches(self): # Make cache for parsed files. self.file_cache = {} # Make table for symbols in #define's. self.symbol_table = {} # Erect the edifice of caches. caches = self.caches = ( cache_basics.SetUpCaches(self.client_root_keeper.client_root)) # Migrate the cache stuff to self namespace. self.includepath_map = caches.includepath_map self.directory_map = caches.directory_map self.realpath_map = caches.realpath_map self.canonical_path = caches.canonical_path self.dirname_cache = caches.dirname_cache self.compiler_defaults = caches.compiler_defaults self.systemdir_prefix_cache = caches.systemdir_prefix_cache self.simple_build_stat = caches.simple_build_stat self.build_stat_cache = caches.build_stat_cache self.IsIncludepathIndex = caches.IsIncludepathIndex self.IsSearchdirIndex = caches.IsSearchdirIndex self.IsCurrdirIndex = caches.IsCurrdirIndex self.IsRealpathIndex = caches.IsRealpathIndex self.IsFilepathPair = caches.IsFilepathPair # Make a cache for the symbolic links encountered; also for their # replication into root directory. self.mirror_path = mirror_path.MirrorPath(self.simple_build_stat, self.canonical_path, self.realpath_map, self.systemdir_prefix_cache) # Make a parser for C/C++. self.parse_file = parse_file.ParseFile(self.includepath_map) # Make a compressor for source files. self.compress_files = compress_files.CompressFiles(self.includepath_map, self.directory_map, self.realpath_map, self.mirror_path) # A fast cache for avoiding calls into the mirror_path object. self.mirrored = set([]) # For statistics only. We measure the different search lists # (search paths) by accumulating them all in sets. self.quote_dirs_set = set([]) # quote search lists self.angle_dirs_set = set([]) # angle searchlists self.include_dir_pairs = set([]) # the pairs (quote search list, # angle search lists) def __init__(self, client_root_keeper, stat_reset_triggers={}): self.generation = 1 self.client_root_keeper = client_root_keeper self.client_root_keeper.ClientRootMakedir(self.generation) self.stat_reset_triggers = stat_reset_triggers self.translation_unit = "unknown translation unit" self.timer = None self.include_server_cwd = os.getcwd() self._InitializeAllCaches() def _ProcessFileFromCommandLine(self, fpath, currdir, kind, search_list): """Return closure of fpath whose kind is "translation unit" or "include". Such files come from the command line, either as the file to compile, or from a "-include" command line option. Arguments: fpath: a filepath (as a string) currdir: a string kind: a string used for an error message if fpath is not found search_list: a tuple of directory indices (for "include" kind files) Returns: an include closure calculated by RunAlgorithm """ # We allow the filepath to be absolute. We do not tolerate absolute # includepaths, in general, and so must be careful here, because we use # build_stat_cache.Resolve. We prepare to use the searchdir parameter of # Resolve. if os.path.isabs(fpath): file_dirpath, file_filename = os.path.split(fpath) else: # Use empty string as directory name (offset from currdir) file_dirpath, file_filename = "", fpath fpath_resolved_pair, fpath_real = self.build_stat_cache.Resolve( self.includepath_map.Index(file_filename), self.currdir_idx, self.directory_map.Index(file_dirpath), search_list) if fpath_resolved_pair == None: raise NotCoveredError("Could not find %s '%s'." % (kind, fpath), send_email=False) # We must inspect the path to replicate directories and symlinks. self.mirror_path.DoPath( os.path.join(currdir, fpath), self.currdir_idx, self.client_root_keeper.client_root) closure = self.RunAlgorithm(fpath_resolved_pair, fpath_real) return closure def ProcessCompilationCommand(self, currdir, parsed_command): """Do the include analysis for parsed_command. Precondition: currdir == os.getcwd() Arguments: currdir: a string denoting an absolute filepath when command is run parsed_command: the value returned by ParseCommandArgs Returns: an include closure as described in RunAlgorithm """ Debug(DEBUG_TRACE, "ProcessCompilationCommand: %s, %s" % (currdir, parsed_command)) assert isinstance(currdir, str) statistics.parse_file_counter_last = statistics.parse_file_counter (self.quote_dirs, self.angle_dirs, self.include_files, translation_unit, self.result_file_prefix, self.d_opts) = parsed_command statistics.translation_unit = translation_unit self.translation_unit = translation_unit self.currdir_idx = self.directory_map.Index(currdir) # Statistics only. self.include_dir_pairs |= set([(self.quote_dirs, self.angle_dirs)]) self.quote_dirs_set.add(self.quote_dirs) self.angle_dirs_set.add(self.angle_dirs) statistics.quote_path_total += len(self.quote_dirs) statistics.angle_path_total += len(self.angle_dirs) total_closure = {} for include_file in self.include_files: total_closure.update( self._ProcessFileFromCommandLine( self.includepath_map.string[include_file], currdir, "include file", self.quote_dirs)) total_closure.update(self._ProcessFileFromCommandLine(translation_unit, currdir, "translation unit", ())) return total_closure def DoStatResetTriggers(self): """Reset stat caches if a glob evaluates differently from earlier. More precisely, if a path of a glob comes in or out of existence or has a new stamp, then reset stat caches.""" trigger_map = self.stat_reset_triggers old_paths = [ path for glob_expr in trigger_map for path in trigger_map[glob_expr] ] for glob_expr in trigger_map: for path in glob.glob(glob_expr): try: old_paths.remove(path) except ValueError: pass new_stamp = basics.Stamp(path) if path in trigger_map[glob_expr]: if new_stamp != trigger_map[glob_expr][path]: Debug(basics.DEBUG_WARNING, "Path '%s' changed. Clearing caches.", path) trigger_map[glob_expr][path] = new_stamp self.ClearStatCaches() return else: Debug(basics.DEBUG_WARNING, "Path '%s' came into existence. Clearing caches.", path) trigger_map[glob_expr][path] = basics.Stamp(path) self.ClearStatCaches() return if old_paths: path = old_paths[0] Debug(basics.DEBUG_WARNING, "Path '%s' no longer exists. Clearing caches.", path) self.ClearStatCaches() def DoCompilationCommand(self, cmd, currdir, client_root_keeper): """Parse and and process the command; then gather files and links.""" self.translation_unit = "unknown translation unit" # don't know yet # Any relative paths in the globs in the --stat_reset_trigger argument # must be evaluated relative to the include server's original working # directory. os.chdir(self.include_server_cwd) self.DoStatResetTriggers() # Now change to the distcc client's working directory. # That'll let us use os.path.join etc without including currdir explicitly. os.chdir(currdir) parsed_command = ( parse_command.ParseCommandArgs(cmd, currdir, self.includepath_map, self.directory_map, self.compiler_defaults, self.timer)) (unused_quote_dirs, unused_angle_dirs, unused_include_files, source_file, result_file_prefix, unused_Dopts) = parsed_command # Do the real work. include_closure = ( self.ProcessCompilationCommand(currdir, parsed_command)) # Cancel timer before I/O in compress_files. if self.timer: # timer may not always exist when testing self.timer.Cancel() # Get name of the initial source file translation_unit = self.translation_unit # Links are accumulated intra-build (across different compilations in a # build). We send all of 'em every time. This will potentially lead to # performance degradation for large link farms. We expect at most a # handful. We add put the system links first, because there should be very # few of them. links = self.compiler_defaults.system_links + self.mirror_path.Links() files = self.compress_files.Compress(include_closure, client_root_keeper, self.currdir_idx) files_and_links = files + links # Note that the performance degradation comment above applies especially # to forced include directories, unless disabled with --no_force_dirs if basics.opt_no_force_dirs == False: files_and_links += self._ForceDirectoriesToExist() realpath_map = self.realpath_map if basics.opt_verify: # Invoke the real preprocessor. exact_no_system_header_dependency_set = ( ExactDependencies(" ".join(cmd), realpath_map, self.systemdir_prefix_cache, translation_unit)) if basics.opt_write_include_closure: WriteDependencies(exact_no_system_header_dependency_set, self.result_file_prefix + '.d_exact', realpath_map) VerifyExactDependencies(include_closure, exact_no_system_header_dependency_set, realpath_map, translation_unit) if basics.opt_write_include_closure: WriteDependencies(include_closure, self.result_file_prefix + '.d_approx', realpath_map) return files_and_links def _ForceDirectoriesToExist(self): """Force any needed directories to exist. In rare cases, the source files may contain #include "foo/../bar", but may not contain any other files from the "foo" directory. In such cases, we invent a dummy file in (the mirrored copy of) each such directory, just to force the distccd server to create the directory, so that the C compiler won't get an error when it tries to resolve that #include. Returns: A list of files to pass as dummy inputs. """ must_exist_dirs = self.mirror_path.MustExistDirs() # Note: distcc's --scan-includes option needs to # know about this name; see ../src/compile.c. special_name = 'forcing_technique_271828' forcing_files = [d + '/' + special_name for d in must_exist_dirs] for forcing_file in forcing_files: # If for extremely obscure reasons the file already exists and is useful, # then don't change it: that's why we open in "append" mode. open(forcing_file, "a").close() return forcing_files def RunAlgorithm(self, filepath_resolved_pair, filepath_real_idx): """Run FindNode on filepath; then compute include closure. Arguments: filepath_resolved_pair: (directory_idx, includepath_idx) filepath_real: the realpath_map index corresponding to filepath_resolved_pair Returns: include_closure: a dictionary. The include_closure consists of entries of the form realpath_idx: [(searchdir_idx_1, includepath_idx_1), (searchdir_idx_2, includepath_idx_2), ...] where searchdir_i is an absolute path. realpath_idx is a realpath index corresponding to a single #include (more exactly, it's the index of the path that the #include resolves to). This include closure calculation omits any system header files, that is, header files found in a systemdir (recall systemdirs are those searchdirs that are built into the preprocessor, such as "/usr/include"). It concentrates only on header files users might edit. The keys are the most important part of the include_closure; the values are used only to munge the preprocessor output to give more useful filenames via the #line directive. The issue here is that source files in the distcc system are not in their "proper" locations: for instance, /usr/X11R6/include/X11.h might be in /tmp/distcc/usr/X11R6/include/X11.h rather than in /usr/X11R6/include. As the example above suggests, relative position of .h files is preserved in distcc-land, so if the #include ends up being a relative include, we do not need to do any munging, so we don't bother to store anything in the value-list corresponding to realpath_idx. If, however, the #include ends up being an absolute include, we do store the "real" name (as an index-pair) in the list. For debugging purposes, we may store more than one "real" name if there are several, which can happen when multiple symlinks point to the same place. TODO(csilvers): change the code to only store one. Here's a concrete example: suppose we're trying to resolve #include "bar.h", and the searchdir_list is ["reldir/foo", "/usr/foo"]. If "/reldir/foo/bar.h" exists, then realpath_idx will resolve to that, and the preprocessor will emit code like "#line 1 reldir/foo/bar.h". That's correct as-is, no munging needed, so we don't bother to put a value in the include_closure entry for this realpath. If, however, "/reldir/foo/bar.h" does not exist, but "/usr/foo/bar.h" exists, then realpath_idx will resolve to that, and the preprocessor will emit code like "#line 1 /tmp/distcc/usr/foo/bar.h". We'll want to munge that to be "/usr/foo/bar.h", so we do put a value in the include_closure entry for this realpath, to tell us what to munge to. (Note we *could* use realpath to tell us the "real" filename, without needing a separate index-pair, but that's not as user-friendly, since realpath is the filename after symlinks are resolved. Thus, on some setups the realpath of /usr/foo/bar.h could be /netapp1/mnt/foo/bar.h or something equally unhelpful.) This method to be overridden by derived class. """ raise Exception("RunAlgorithm not implemented.") def ClearStatCaches(self): """Clear caches used for, or dependent on, stats.""" self.generation += 1 # Tabula rasa: for this analysis, we must forget everything recorded in the # client_root directory about source files, directories, and symbolic links. # But we cannot delete any such information, because slow-poke distcc # clients that have received earlier include manifests perhaps only now get # around to reading a previous generation client root directory. self.client_root_keeper.ClientRootMakedir(self.generation) self._InitializeAllCaches() distcc-3.4/include_server/include_analyzer_memoizing_node.py000077500000000000000000000641471404653710500246530ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """A graph-based algorithm for memoizing include closure calculations.""" __author__ = "Nils Klarlund" # TODO(klarlund) For computed includes, some static analysis checks must be # introduced to verify soundness of node reutilization in FindNode. import os import basics import macro_eval import parse_file import statistics import include_analyzer Debug = basics.Debug DEBUG_TRACE = basics.DEBUG_TRACE DEBUG_DATA = basics.DEBUG_DATA NotCoveredError = basics.NotCoveredError # RESOLUTION MODES RESOLVED = 1 # filepath already resolved and denotes an existing file QUOTE = 2 # filepath to be resolved against quote directories ANGLE = 3 # filepath to be resolved against angle directories NEXT = 4 # filepath to be resolved against each and every quote # directory; this is how we handle #include_next RESOLUTION_MODES = [ RESOLVED, QUOTE, ANGLE, NEXT ] # Textual representation of RESOLUTION_MODES. RESOLUTION_MODES_STR = [ None, 'RESOLVED', 'QUOTE', 'ANGLE', 'NEXT' ] # MAIN COURSE class UnionCache(object): """Frozen sets and their unions, represented by integers. Frozensets are Python's immutable and hashable sets. We hash them into set ids, which are integers. That allows us to cache union operations efficiently. """ def __init__(self): """Constructor: Instance variables: members: members[set_id] = frozenset([s1,..., sn]), the members of the set cache: cache[(set1_id, set2_id)] = the id of the union of set1 and set2 id_map: the set of frozen sets we have seen mapped to {1, 2, ..} """ self.members = {} self.cache = {} self.id_map = {} def SetId(self, members): """Memoize the frozenset of members and return set id.""" frozen = frozenset(members) try: return self.id_map[frozen] except KeyError: self.id_map[frozen] = len(self.id_map) + 1 self.members[len(self.id_map)] = frozen return len(self.id_map) def Elements(self, set_id): """The frozenset corresponding to a set id.""" return self.members[set_id] def Union(self, set1_id, set2_id): """Return the set id of the union of sets represented by set ids.""" try: return self.cache[(set1_id, set2_id)] except KeyError: frozen = self.members[set1_id] | self.members[set2_id] frozen_id = self.SetId(frozen) self.cache[(set1_id, set2_id)] = frozen_id return frozen_id class SupportRecord(object): """Record the symbols that expressions depend on. A support record is an object that contains a mutable support set of symbols. Each node in the summary graph is associated with a support record. It is the set of symbols upon which the included computes depend. A support record is initially deemed valid. If a symbol is redefined, then it becomes invalid. For efficiency, the valid field is sometimes explicitly handled by a user of this object. """ def __init__(self, support_master): """Constructor. Argument: support_master: a record for holding the reverse mapping from symbols to support records that contain them. Instance Variables: support_master: see above union_cache: a union cache for set manipulation support_id: the id of a set in union_cache; the set consists of all symbols referenced by computed includes in any include dependency of the node to which the support record belongs valid: a Boolean """ self.support_master = support_master self.valid = True self.union_cache = support_master.union_cache self.support_id = self.union_cache.SetId([]) def Update(self, set_id): """Augment the support record with the set represented by set_id. """ union_id = self.union_cache.Union(self.support_id, set_id) if union_id != self.support_id: self.support_master.SupportRecordDependencyAdd( self.union_cache.Elements(set_id), self) self.support_id = union_id def UpdateSet(self, symbols): """Add symbols to the support. This function is similar to Update, but the argument is a list of elements. """ self.Update(self.union_cache.SetId(symbols)) class SupportMaster(object): """Record the support records that depend on a given symbol. A map symbol_to_records is maintained. For each symbol s self.symbol_to_records[s] is the set of support records r whose support set contains s.""" def __init__(self): """Constructor. Instance variables: symbol_to_records: a mapping to record sets union_cache: a UnionCache for memoizing sets and their unions """ self.symbol_to_records = {} self.union_cache = UnionCache() def SupportRecordDependencyAdd(self, symbols, support_record): """Add dependency of support record on symbol.""" for symbol in symbols: if symbol not in self.symbol_to_records: self.symbol_to_records[symbol] = set([]) self.symbol_to_records[symbol].add(support_record) def InvalidateRecords(self, symbol): """Mark as invalid all support records whose set contains symbol.""" if symbol in self.symbol_to_records: for support_record in self.symbol_to_records[symbol]: support_record.valid = False class IncludeAnalyzerMemoizingNode(include_analyzer.IncludeAnalyzer): """A memoizing algorithm for include analysis based on a graph construction. Instance variables: master_cache: a two-level node cache The key of the top-level cache is an include configuration of the form (currdir_idx, quote_dirs, angle_dirs) The value of the top-level cache is a node-cache (defined next). The key of the second-level (node) cache has the form (filepath_idx, resolution_mode, file_dir_idx) A node is the value of the second-level (node) cache. It has the form [filepath_real_idx, filepath_resolved_pair, [node_0, ...node_n-1], support_record] where each node_i, for 1 <= i < n, is a node representing a direct include dependency of node. The direct include dependencies are the edges of a directed graph called the summary graph. TODO(csilvers): document what the values of the node-cache mean. In this class, the top-level key is referred to as 'incl_config', the top-level value is referred to as 'node_cache_for_incl_config', the second-level key is referred to as 'key', and the second-level value is referred to as 'node'. There are many disjoint summary graphs, one for each include configuration. Each node of a summary graph is the image of a key, that is, there are values incl_config and key such that node == master_cache[incl_config][key]. As stated the node cache works pre-resolution. But it may well be that, say, two occurrences of #include "foo.h" in files with different file directories (that is, the files containing the foo.h includes are in different directories) actually resolve to the same foo.h file. In that case, we should reuse the foo.h node -- with a catch: all though the file may be the same real file, their containing directories may be different. For example, the file may be in the real location /D/foo.h, but it may also be known as /E/foo.h, where E is a directory containing a symbolic link foo.h pointing to /D/foo.h. If file foo.h has a quoted include of bar.h, that is, contains the directive #include "bar.h" then bar.h is looked for in /D if the file directory is /D, but it is looked for in /E if the file directory is /E. That is the real file directory of /E/foo.h is *not* the directory component of the realpath of /E/foo.h. Rather, it is the realpath of the directory component of /E/foo.h, that is, the realpath of /E. Thus, if we memoize files according to their real location, then the file directory as understood above must also be taken into account. In particular, we also use as keys pairs of the form: (realpath index of resolved file, real path index of filedir). This realpath-oriented memoization is not a frivolous attempt at optimization. It is essential to avoiding infinite loops as in: D/mem.h D/../D/mem.h D/../D/../D/mem.h generated by an include of the form "#include ../D/mem.h" in file mem.h. One would think that obviosly these prefixes denote the same location. But they need not! For D of the first line could be a symbolic link to a real directory dir1_D. And, the second D could be another symbolic link in dir1_D/ to dir2_D, etc... So, when the include processor is lead astray by includes that resolve this way it is by no means obvious how to investigate the paths with symbolic links of the form (D/..)* This will diverge even if there is just one mem.h file with an include of ../D/mem.h started in the real directory D. [Remember that the include processor does not heed include guards.] For termination, we rely on the fact that eventually the pair (realpath of file, real path of file directory) will be seen again (because there are finitely many files and directories). In practice, with this technique, the recursion is stopped at the second attempt to include mem.h. """ # The magic '3' selects the fourth component of a node, see the class # documentation. SUPPORT_RECORD = 3 def _InitializeAllCachesMemoizing(self): self.master_cache = {} # Keep track of the support of each included file. The support of the file # is the union of the support of expressions in computed includes in the # file or in recursively included file. self.support_master = SupportMaster() # Enable the mechanism that invalidates all support records that contain a # symbol that is being defined or redefined. self.parse_file.SetDefineCallback(self.support_master.InvalidateRecords) def __init__(self, client_root_keeper, stat_reset_triggers={}): """Constructor.""" include_analyzer.IncludeAnalyzer.__init__(self, client_root_keeper, stat_reset_triggers) self._InitializeAllCachesMemoizing() def ClearStatCaches(self): """Reset stat caches and the node cache, which depends on stat caches.""" # First, clear caches as the IncludeAnalyzer class prescribes it. include_analyzer.IncludeAnalyzer.ClearStatCaches(self) # Then, clear own caches. self._InitializeAllCachesMemoizing() def _PrintableFilePath(self, fp): return (isinstance(fp, int) and self.includepath_map.String(fp) or isinstance(fp, tuple) and (self.directory_map.string[fp[0]], self.includepath_map.string[fp[1]])) def RunAlgorithm(self, filepath_resolved_pair, filepath_real_idx): """See RunAlgorithm of class IncludeAnalyzer in include_analyzer.""" incl_config = (self.currdir_idx, self.quote_dirs, self.angle_dirs) try: nodes_for_incl_config = self.master_cache[incl_config] except KeyError: nodes_for_incl_config = self.master_cache[incl_config] = {} # Process symbols defined on command line. for d_opt in self.d_opts: if len(d_opt) == 1: lhs, rhs = d_opt[0], "1" elif len(d_opt) == 2: [lhs, rhs] = d_opt parse_file.InsertMacroDefInTable(lhs, rhs, self.symbol_table, self.support_master.InvalidateRecords) else: # Assume this is a syntax error of some sort. pass # Construct or find the node for filepath_resolved. node = self.FindNode(nodes_for_incl_config, filepath_resolved_pair, RESOLVED, None, filepath_real_idx) # Find the nodes reachable from node and represent as an include closure. include_closure = {} self._CalculateIncludeClosureExceptSystem(node, include_closure) return include_closure def FindNode(self, nodes_for_incl_config, fp, resolution_mode, file_dir_idx=None, fp_real_idx=None): """Find a previously constructed node or create a new node. Arguments: nodes_for_incl_config: a dictionary (see class documentation). fp: a filepath index or, if resolution_mode == RESOLVED, a filepath pair resolution_mode: an integer in RESOLUTION_MODES file_dir_idx: consider the file F that has the line '#include "fp"' which is causing us to call FindNode on fp. file_dir_idx is the index of dirname(F). (This argument affects the semantics of resolution for resolution_mode == QUOTE.) fp_real_idx: the realpath index of resolved filepath (Useful for resolution_mode == RESOLVED only.) Returns: a node or None Raises: NotCoveredError This is function is long, too long. But function calls are expensive in Python. TODO(klarlund): refactor. """ # Convenient abbreviations for cache access. dir_map = self.directory_map includepath_map = self.includepath_map resolve = self.build_stat_cache.Resolve # Now a little dynamic type verification. Remember that "A implies B" is # exactly the same as "not A or B", at least in some primitive formal # systems. assert isinstance(nodes_for_incl_config, dict) assert (not self.IsFilepathPair(fp) or resolution_mode == RESOLVED) assert (not fp or (self.IsFilepathPair(fp) or (resolution_mode != RESOLVED and self.IsIncludepathIndex(fp)))) assert resolution_mode in RESOLUTION_MODES assert not resolution_mode == QUOTE or file_dir_idx assert not file_dir_idx or resolution_mode == QUOTE assert not fp_real_idx or resolution_mode == RESOLVED if __debug__: Debug(DEBUG_TRACE, "FindNode: fp: %s, mode: %s\n file_dir: %s,\n fp_real: %s" % (self._PrintableFilePath(fp), RESOLUTION_MODES_STR[resolution_mode], not file_dir_idx and " " or dir_map.string[file_dir_idx], not fp_real_idx and " " or self.realpath_map.string[fp_real_idx])) statistics.find_node_counter += 1 if fp == None: return # We must remember the resolution_mode when we key our function call. And # for resolution_mode == QUOTE it is important to also remember the # file_dir_idx, because the filepath is resolved against file_dir. key = (fp, resolution_mode, file_dir_idx) if key in nodes_for_incl_config: # Is the support record valid? if nodes_for_incl_config[key][self.SUPPORT_RECORD].valid: statistics.master_hit_counter += 1 return nodes_for_incl_config[key] else: # Invalid support record. The meaning of some computed includes may have # changed. node = nodes_for_incl_config[key] currdir_idx = self.currdir_idx quote_dirs = self.quote_dirs angle_dirs = self.angle_dirs # Retrieve filepath information. That is still OK. Disregard children, # because they will be rebuilt. Reuse support_record. Don't switch # support_record.valid to True before running through all the caching # code below -- we don't want to reuse an earlier result. [fp_real_idx, fp_resolved_pair, _, support_record] = node Debug(DEBUG_TRACE, "Invalid record for translation unit: %s, file: %s", self.translation_unit, self._PrintableFilePath(fp)) else: # This is a new file -- for this include configuration at least. support_record = SupportRecord(self.support_master) currdir_idx = self.currdir_idx quote_dirs = self.quote_dirs angle_dirs = self.angle_dirs if resolution_mode == QUOTE: (fp_resolved_pair, fp_real_idx) = ( resolve(fp, currdir_idx, file_dir_idx, quote_dirs)) elif resolution_mode == ANGLE: (fp_resolved_pair, fp_real_idx) = ( resolve(fp, currdir_idx, None, angle_dirs)) elif resolution_mode == NEXT: # The node we return is just a dummy whose children are all the # possible resolvants. fp_resolved_pair = None fp_real_idx = None else: assert resolution_mode == RESOLVED assert fp_real_idx # this is the realpath corresponding to fp assert self.IsFilepathPair(fp) fp_resolved_pair = fp # we are given the resolvant if fp_resolved_pair: # The resolution succeeded. Before recursing, make sure to # mirror the path. Guard the call of MirrorPath with a cache # check; many files will have been visited before (for other # include directories). (d_, fp_) = fp_resolved_pair if (fp_resolved_pair, currdir_idx) not in self.mirrored: self.mirrored.add((fp_resolved_pair, currdir_idx)) self.mirror_path.DoPath( os.path.join(dir_map.string[currdir_idx], dir_map.string[d_], includepath_map.string[fp_]), currdir_idx, self.client_root_keeper.client_root) # We have fp_resolved_pair if and only if we have fp_real_idx assert not fp_resolved_pair or fp_real_idx assert not fp_real_idx or fp_resolved_pair # Now construct the node, even before we know the children; this # early construction/late filling-in of children allows us to stop # a recursion early, when key is in nodes_for_incl_config. A cyclic # structure may arise in this way. children = [] node = (fp_real_idx, fp_resolved_pair, children, support_record) nodes_for_incl_config[key] = node if not fp_resolved_pair: if resolution_mode == NEXT: # Create children of this dummy node. Try against all # directories in quote_dirs; that list includes the # angle_dirs. Recurse for each success. for d in quote_dirs: (fp_resolved_pair_, fp_real_idx_) = ( resolve(fp, currdir_idx, None, (d,))) if fp_resolved_pair_ != None: node_ = self.FindNode(nodes_for_incl_config, fp_resolved_pair_, RESOLVED, None, # file_dir_idx fp_real_idx_) children.append(node_) return node else: # For non-NEXT resolution modes return node # Now, we've got the resolution: (search directory, include path). assert (fp and fp_real_idx and fp_resolved_pair) (searchdir_idx, includepath_idx) = fp_resolved_pair # We need the realpath index of the current file directory. That's because # we are going to ask whether we have really visited this file, despite the # failure above to recognize it using a possibly relative name. Here, # 'really' means 'with respect to realpath'. Please see the class # documentation for why we need to calculate the realpath index of file # directory as part of the investigation of whether we have 'really' # encountered the file before. try: (fp_dirname_idx, fp_dirname_real_idx) = ( self.dirname_cache.cache[(currdir_idx, searchdir_idx, includepath_idx)]) except KeyError: (fp_dirname_idx, fp_dirname_real_idx) = ( self.dirname_cache.Lookup(currdir_idx, searchdir_idx, includepath_idx)) if resolution_mode != RESOLVED: # See whether we know about filepath post-resolution. if ((fp_real_idx, fp_dirname_real_idx) in nodes_for_incl_config and support_record.valid): statistics.master_hit_counter += 1 # Redo former decision about node: we use the one that is # already there. node = nodes_for_incl_config[(fp_real_idx, fp_dirname_real_idx)] nodes_for_incl_config[key] = node return node # Couldn't find node under real name. We'll remember the node, but have to # continue processing it. nodes_for_incl_config[(fp_real_idx, fp_dirname_real_idx)] = node # All chances of hitting the node cache are now exhausted! statistics.master_miss_counter += 1 # If we're revisiting because the support record was invalid, then it is # time to set it. support_record.valid = True # Try to get the cached result of parsing file. try: (quote_includes, angle_includes, expr_includes, next_includes) = ( self.file_cache[fp_real_idx]) except KeyError: # Parse the file. self.file_cache[fp_real_idx] = self.parse_file.Parse( self.realpath_map.string[fp_real_idx], self.symbol_table) (quote_includes, angle_includes, expr_includes, next_includes) = ( self.file_cache[fp_real_idx]) # Do the includes of the form #include "foo.h". for quote_filepath in quote_includes: node_ = self.FindNode(nodes_for_incl_config, quote_filepath, QUOTE, fp_dirname_idx) if node_: children.append(node_) support_record.Update(node_[self.SUPPORT_RECORD].support_id) # Do the includes of the form #include . for angle_filepath in angle_includes: node_ = self.FindNode(nodes_for_incl_config, angle_filepath, ANGLE) if node_: children.append(node_) support_record.Update(node_[self.SUPPORT_RECORD].support_id) if __debug__: if expr_includes: # Computed includes are interesting Debug(DEBUG_DATA, "FindNode, expr_includes: file: %s: '%s'", (isinstance(fp, int) and includepath_map.String(fp) or (isinstance(fp, tuple) and (dir_map.string[fp[0]], includepath_map.string[fp[1]]))), expr_includes) # Do the includes of the form #include expr, the computed includes. for expr in expr_includes: # Use multi-valued semantics to gather set of possible filepaths that the # C/C++ string expr may evaluate to under preprocessing semantics, given # the current symbol table. The symbols are all those of possible # expansions. (files, symbols) = ( macro_eval.ResolveExpr(includepath_map.Index, resolve, expr, self.currdir_idx, fp_dirname_idx, self.quote_dirs, self.angle_dirs, self.symbol_table)) for (fp_resolved_pair_, fp_real_idx_) in files: node_ = self.FindNode(nodes_for_incl_config, fp_resolved_pair_, RESOLVED, None, fp_real_idx_) if node_: children.append(node_) support_record.Update(node_[self.SUPPORT_RECORD].support_id) # Now the resolution of includes of the file of the present node depends # on symbols. support_record.UpdateSet(symbols) # Do includes of the form #include_next "foo.h" or # #include_next . for include_next_filepath in next_includes: node_ = self.FindNode(nodes_for_incl_config, include_next_filepath, NEXT) if node_: children.append(node_) support_record.Update(node_[self.SUPPORT_RECORD].support_id) return node def _CalculateIncludeClosureExceptSystem(self, node, include_closure): """Explore the subgraph reachable from node and gather real paths. Arguments: node: the node of the translation unit, the initial source file (see class documentation for a description of this tuple). include_closure: a map (see IncludeAnalyzer.RunAlgorithm documentation for a description of this map). Modifies: include_closure. We modify in place to avoid copying this big struct. """ assert not include_closure # should start out empty # We access prefix_cache's vars directly, so we need to ensure it's filled. self.systemdir_prefix_cache.FillCache(self.realpath_map) visited = set([]) starts_with_systemdir = self.systemdir_prefix_cache.cache dir_map_string = self.directory_map.string if not node: return stack = ([node]) # TODO(csilvers): consider using a deque if __debug__: statistics.len_calculated_closure_nonsys = 0 while stack: node = stack.pop(-1) id_ = id(node) if id_ in visited: continue visited.add(id_) # We optimized away: # # (fp_real_idx, fp_resolved_pair, children) = node # # so that the common case (that fp_real_idx is known to compiler) # is dispatched away with quickly: if node[0]: # fp_real_idx if __debug__: statistics.len_calculated_closure_nonsys += 1 # We ignore "system" includes like /usr/include/stdio.h. # These files are not likely to change, so it's safe to skip them. if not starts_with_systemdir[node[0]]: # Add the resolved filepath to those found for realpath. if node[0] not in include_closure: include_closure[node[0]] = [] searchdir_idx = node[1][0] # the searchdir part of fp_pair if (searchdir_idx and dir_map_string[searchdir_idx] and dir_map_string[searchdir_idx][0] == '/'): include_closure[node[0]].append(node[1]) # Even when a node does not describe a filepath, it may still # have children that do if it is a dummy node. # TODO(csilvers): see if it speeds things up to append node[2], # so stack is a list of lists. stack.extend(node[2]) statistics.len_calculated_closure = len(include_closure) distcc-3.4/include_server/include_analyzer_memoizing_node_test.py000077500000000000000000000204251404653710500257010ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. __author__ = "Nils Klarlund" import os import time import basics import parse_command import cache_basics import include_analyzer_memoizing_node import unittest NotCoveredError = basics.NotCoveredError class IncludeAnalyzerMemoizingNodeUnitTest(unittest.TestCase): def _ToString(self, include_closure): """Translate the indices in an include closure to their denoted strings.""" return ( dict((self.realpath_map.string[rp_idx], [ (self.directory_map.string[dir_idx], self.includepath_map.string[ip_idx]) for (dir_idx, ip_idx) in include_closure[rp_idx] ]) for rp_idx in include_closure)) def setUp(self): basics.opt_debug_pattern = 1 client_root_keeper = basics.ClientRootKeeper() self.include_analyzer = ( include_analyzer_memoizing_node.IncludeAnalyzerMemoizingNode( client_root_keeper)) self.includepath_map = self.include_analyzer.includepath_map self.canonical_path = self.include_analyzer.canonical_path self.directory_map = self.include_analyzer.directory_map self.realpath_map = self.include_analyzer.realpath_map def test__CalculateIncludeClosureExceptSystem(self): """Construct a summary graph, then calculate closure and check.""" includepath_map = self.includepath_map canonical_path = self.canonical_path directory_map = self.directory_map realpath_map = self.realpath_map # Create summary graph with structure A -> B -> C -> B and B -> D -> C' -> # E. Note that B has two immediate successors. Assume the current dir is # /curr (for all nodes). The include graph is made for a searchlist [src, /, # /dirlink]. Note that the first directory in the searchlist is relative. # For simplicity, we consider angled resolution only. Here is a description # of the nodes. # # - Nodes A, B correspond to includepaths a.h and b.h, which are relatively # resolved because they are found in src, which means absolute # directory /curr/src. These filepaths are thus resolved to src/a.h and # src/b.h and their corresponding realpaths are /curr/src/a.h and # /curr/src/b.h. The realpaths are all what is recorded in the include # closure, because the files are relatively resolved. # # - Nodes C, C', and E are absolutely resolved includepaths. More # specifically: # # - Nodes C and C' correspond to includepath dir/c.h and c.h, which # during resolution were found in / and /dirlink, respectively. # However, /dirlink is a symbolic link to /dir, which is a real # directory, so C and C' in fact correspond to the same realpath # namely /dir/c.h. # # - Node E corresponds to includepath dir/e.h and was found during # resolution to be in /. So, the realpath of this node is /dir/e.h. # # - Node D is a dummy and it is not recorded in the include closure. Still, # its non-dummy descendants are recorded. src_idx = directory_map.Index("src") curr_idx = directory_map.Index("/curr") root_idx = directory_map.Index("/") dirlink_idx = directory_map.Index("/dirlink") curr_src_idx = directory_map.Index("/curr/src") dir_idx = directory_map.Index("/dir") A_children = [] A = (realpath_map.Index("/curr/src/a.h"), (src_idx, includepath_map.Index("a.h")), A_children) B_children = [] B = (realpath_map.Index("/curr/src/b.h"), (src_idx, includepath_map.Index("b.h")), B_children) C_children = [] C = (realpath_map.Index("/dir/c.h"), (root_idx, includepath_map.Index("dir/c.h")), C_children) C__children = [] C_ = (realpath_map.Index("/dir/c.h"), (dirlink_idx, includepath_map.Index("c.h")), C__children) D_children = [] D = (None, None, D_children) E_children = [] E = (realpath_map.Index("/dir/e.h"), (root_idx, includepath_map.Index("dir/e.h")), E_children) A_children.extend([B]) B_children.extend([C, D]) C_children.extend([B]) C__children.extend([E]) D_children.extend([C_]) E_children.extend([]) include_closure = {} self.include_analyzer._CalculateIncludeClosureExceptSystem(A, include_closure) stringified_include_closure = self._ToString(include_closure) # /curr/src/a.h is not known under absolute pathnames. self.assertEqual(stringified_include_closure['/curr/src/a.h'], []) # Neither is /curr/src/b.h. self.assertEqual(stringified_include_closure['/curr/src/b.h'], []) # But, /dir/c.h is known under two different absolute names. self.assertEqual(stringified_include_closure['/dir/c.h'], [('/dirlink/', 'c.h'), ('/', 'dir/c.h')]) # And, dir/e.h is known under exactly one absolute name. self.assertEqual(stringified_include_closure['/dir/e.h'], [('/', 'dir/e.h')]) # That is all and nothing more. self.assertEqual(len(stringified_include_closure), 4) def _ConstructDistccCommandLine(self, src_stem): # A command line, which is more or less the one found in the # generated Makefile for distcc. We don't need the exact form of # the command." return ("gcc -DHAVE_CONFIG_H -D_GNU_SOURCE" + " -I./src" + ' -DSYSCONFDIR="/usr/local/etc"' + ' -DPKGDATADIR="/usr/local/share/distcc"' + " -Isrc" + " -I./lzo" + " -include include_me.h " + " -o src/%s.o" + " -c src/%s.c") % (src_stem, src_stem) def test__CalculateIncludeClosureExceptSystem_on_distcc(self): includepath_map = self.includepath_map canonical_path = self.canonical_path directory_map = self.directory_map realpath_map = self.realpath_map include_analyzer = self.include_analyzer current_dir = os.path.realpath("test_data/distcc") os.chdir(current_dir) src_stem = "distcc" cmd = self._ConstructDistccCommandLine(src_stem) parsed_command = ( parse_command.ParseCommandArgs( parse_command.ParseCommandLine(cmd), current_dir, include_analyzer.includepath_map, include_analyzer.directory_map, include_analyzer.compiler_defaults)) (include_analyzer.quote_dirs, include_analyzer.angle_dirs, include_analyzer.include_files, translation_unit, include_analyzer.result_file_prefix, _) = parsed_command self.assertEqual(translation_unit, "src/%s.c" % src_stem) expected_suffixes = [ "src/include_me.h", "src/implicit.h", "src/distcc.c", "src/config.h", "src/distcc.h", "src/state.h", "src/compile.h", "src/trace.h", "src/exitcode.h", "src/util.h", "src/hosts.h", "src/bulk.h", "src/emaillog.h"] include_closure = ( include_analyzer.ProcessCompilationCommand(current_dir, parsed_command)) expected_prefix = os.getcwd() + '/' expected = set([ expected_prefix + expected_suffix for expected_suffix in expected_suffixes ]) self.assertEqual(set([realpath_map.string[key] for key in include_closure.keys()]), expected) for rp_idx in include_closure: self.assertEqual(len(include_closure[rp_idx]), 0) # TODO(klarlund): massage command so as to test that with a # different search path files are reported as absolute. That is, # provoke pairs (directory_idx, includepath_idx) to exist in # include_closure[rp_idx]. def tearDown(self): pass unittest.main() distcc-3.4/include_server/include_analyzer_test.py000077500000000000000000000467311404653710500226260ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Test include analysis, including computed includes, as carried out by ProcessCompilationCommandLine. Also, test stat_reset_triggers.""" __author__ = "Nils Klarlund" import os import re import glob import shutil import tempfile import unittest import basics import cache_basics import parse_command import statistics import include_analyzer_memoizing_node class IncludeAnalyzerTest(unittest.TestCase): def setUp(self): statistics.StartTiming() self.global_dirs = [] basics.opt_print_statistics = False basics.opt_debug_pattern = 1 client_root_keeper = basics.ClientRootKeeper() if algorithm == basics.MEMOIZING: self.include_analyzer = ( include_analyzer_memoizing_node.IncludeAnalyzerMemoizingNode( client_root_keeper)) else: self.fail("Algorithm not known.") statistics.StartTiming() self.directory_map = self.include_analyzer.directory_map self.compiler_defaults = self.include_analyzer.compiler_defaults self.canonical_path = self.include_analyzer.canonical_path def tearDown(self): if basics.opt_print_statistics: statistics.EndTiming() statistics.PrintStatistics(self.include_analyzer) def ProcessCompilationCommandLine(self, cmd, cwd): return ( self.include_analyzer.ProcessCompilationCommand( cwd, parse_command.ParseCommandArgs( parse_command.ParseCommandLine(cmd), cwd, self.include_analyzer.includepath_map, self.include_analyzer.directory_map, self.include_analyzer.compiler_defaults))) def CanonicalPathsForTestData(self, dirs, test_data_dir='test_data'): """Absolutize names relative to test_data_dir of current directory.""" return set([ self.canonical_path.Canonicalize(test_data_dir + '/' + f) for f in dirs ]) def RetrieveCanonicalPaths(self, files): return set([ self.include_analyzer.realpath_map.string[f] for f in files ]) def test_AdvancedComputedIncludes(self): includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc test_data/test_computed_includes/src.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData(['test_computed_includes/src.c', 'test_computed_includes/helper.c', 'test_computed_includes/incl.h'])) includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc test_data/test_computed_includes/srcA.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData(['test_computed_includes/srcA.c', 'test_computed_includes/helper.c', 'test_computed_includes/incl.h', 'test_computed_includes/inclA.h'])) # Test: FindNode is called once only if previous query is repeated. That is, # include graph is not calculated for this query. old_FindNode = self.include_analyzer.FindNode class mock_FindNode(object): def __init__(self): self.count = 0 def FindNode(self, *_): self.count += 1 if self.count == 2: raise Exception("Did not expect 2 calls of FindNode.") return old_FindNode(*_) self.include_analyzer.FindNode = mock_FindNode().FindNode try: includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc test_data/test_computed_includes/srcA.c", os.getcwd())) finally: self.include_analyzer.FindNode = old_FindNode # Test: if a -D option affecting the value of the computed include is # presented then include graph is recalculated --- and correctly so. includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( r"""gcc -DINCL=\"../dfoo/foo2.h\" """ + " test_data/test_computed_includes/src.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData(['test_computed_includes/src.c', 'test_computed_includes/helper.c', 'test_computed_includes/incl.h', 'test_computed_includes/inclA.h', 'dfoo/foo2.h'])) # Test: functional macros can be passed on the command line. includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( """gcc -D"STR(X)=# X" """ + """-D"FINCLUDE(P)=STR(../MY_TEST_DATA/dfoo/P)" """ + """-DMY_TEST_DATA=test_data """ + "test_data/func_macro.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['func_macro.c', 'dfoo/foo.h', 'dfoo/foo2.h', 'dbar/dbar1/bar.h' ])) def test_AbsoluteIncludes(self): try: opt_unsafe_absolute_includes = basics.opt_unsafe_absolute_includes basics.opt_unsafe_absolute_includes = True tmp_dir = tempfile.mkdtemp() def WriteProgram(name, text): base = os.path.dirname(os.path.join(tmp_dir, name)) if not os.path.isdir(base): os.makedirs(base) fd = open(os.path.join(tmp_dir, name), 'w') fd.write(text) fd.close() WriteProgram('foo.c', """#include "%s/bar/baz.h" blah blah. """ % tmp_dir) # We don't want to get entangled in absolute includes. # The baz.h program is not supposed to be found (although # real preprocessing will). WriteProgram('baz.h', """#include "../foobar.h" blah blah. """) includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc %s" % os.path.join(tmp_dir, 'foo.c'), os.getcwd())) self.assertEqual( includes, set([os.path.realpath('%s/foo.c' % tmp_dir)])) finally: basics.opt_unsafe_absolute_includes = opt_unsafe_absolute_includes shutil.rmtree(tmp_dir) def test_StatResetTriggers(self): """Check that the include analysis of a file is done from scratch after a trigger path went from non-existing to existing. """ def CheckGeneration(lst, expected): for f_name in lst: self.assertTrue( re.match(r"%s/.+[.]include_server[-][0-9]+[-]%s" % (self.include_analyzer.client_root_keeper.client_tmp, expected), f_name), f_name) def GetFileNamesFromAbsLzoName(lst): """Transform lists with elements like: '/dev/shm/tmpsn6NQT.include_server-12272-X/.../test_data/foo.c.lzo' to lists with elements like: 'test_data/foo.c'""" return [ f_name.split('/')[-2] + '/' + f_name.split('/')[-1][:-4] for f_name in lst if f_name.endswith('.lzo') ] self.include_analyzer.stat_reset_triggers = {"seven*": {}, "ate": {"ate": (1,111,2)}, "nine": {} } try: real_glob_glob = glob.glob def Mock_GlobGlob(f): if f in ["seven*", "nine"]: return [] if f == 'ate': return ["ate"] return real_glob_glob(f) glob.glob = Mock_GlobGlob real_os_stat = os.stat def Mock_OsStat(f, dir_fd=None, follow_symlinks=True): # Return the same as initial value in two cases below. if f in ["seven", "nine"]: raise OSError if f == 'ate': obj = lambda: None obj.st_mtime = 1 obj.st_ino = 111 obj.st_dev = 2 return obj return real_os_stat(f) os.stat = Mock_OsStat real_cache_basic_OsPathIsFile = cache_basics._OsPathIsFile def Mock_OsPathIsFile(f): # We postulate that the test_data/stat_reset_triggers.h file does not # yet exists. Moreover, we pretend that a version ind test_data/dfoo is # in existence. return f in [ "test_data/stat_triggers.c", "test_data/dfoo/stat_triggers.h"] cache_basics._OsPathIsFile = Mock_OsPathIsFile files_and_links = self.include_analyzer.DoCompilationCommand( "gcc -Itest_data/dfoo test_data/stat_triggers.c".split(), os.getcwd(), self.include_analyzer.client_root_keeper) # Check that we picked up the dfoo version of the .h file! self.assertEqual(GetFileNamesFromAbsLzoName(files_and_links), ['test_data/stat_triggers.c', 'dfoo/stat_triggers.h']) # The generation should still be the original, namely 1. self.assertEqual(self.include_analyzer.generation, 1) CheckGeneration(files_and_links, 1) def New_Mock_OsStat(f, dir_fd=None, follow_symlinks=True): if f in ["seven", "nine"]: raise OSError if f == 'ate': obj = lambda: None obj.st_mtime = 1 obj.st_ino = 111 obj.st_dev = 3 # so, this component changed from previous value return obj return real_os_stat(f) os.stat = New_Mock_OsStat def New_Mock_OsPathIsFile(f): return f in [ "test_data/stat_triggers.c", "test_data/stat_triggers.h", "test_data/dfoo/stat_triggers.h"] cache_basics._OsPathIsFile = New_Mock_OsPathIsFile files_and_links = self.include_analyzer.DoCompilationCommand( "gcc -Itest_data/dfoo test_data/stat_triggers.c".split(), os.getcwd(), self.include_analyzer.client_root_keeper) self.assertEqual(self.include_analyzer.generation, 2) CheckGeneration(files_and_links, 2) # Now, check that we picked up the test_data version of the .h file, not # the dfoo one! self.assertEqual(GetFileNamesFromAbsLzoName(files_and_links), ['test_data/stat_triggers.c', 'test_data/stat_triggers.h']) # Third time. def New_Mock_GlobGlob(f): if f in ["seven*"]: return ["seventy"] if f in ["nine"]: return [] if f == 'ate': return ["ate"] return real_glob_glob(f) glob.glob = New_Mock_GlobGlob def New_New_Mock_OsStat(f, dir_fd=None, follow_symlinks=True): if f in ["seven", "nine"]: raise OSError if f == 'ate': obj = lambda: None obj.st_mtime = 1 obj.st_ino = 111 obj.st_dev = 3 return obj if f == 'seventy': obj = lambda: None obj.st_mtime = 2 obj.st_ino = 222 obj.st_dev = 3 return obj return real_os_stat(f) os.stat = New_New_Mock_OsStat # Revert _OsPathIsFile cache_basics._OsPathIsFile = Mock_OsPathIsFile files_and_links = self.include_analyzer.DoCompilationCommand( "gcc -Itest_data/dfoo test_data/stat_triggers.c".split(), os.getcwd(), self.include_analyzer.client_root_keeper) # Now, check that we again picked up the dfoo version of the .h file. self.assertEqual(GetFileNamesFromAbsLzoName(files_and_links), ['test_data/stat_triggers.c', 'dfoo/stat_triggers.h']) self.assertEqual(self.include_analyzer.generation, 3) CheckGeneration(files_and_links, 3) finally: glob.glob = real_glob_glob os.stat = real_os_stat cache_basics._OsPathIsFile = real_cache_basic_OsPathIsFile def test_DotdotInInclude(self): """Set up tricky situation involving an "#include "../foo" occurring in a file accessed through a symbolic link. This include is to be resolved relative to the file directory, namely where the link is, not where the file is. Also, the include processor tries to identify files by their relatives names. This may lead to an infinite recursion according to an increasing sequence of filepath names involving "../" So if the included file includes the original file, an infinite loop may occur.""" # In test_data, we find # # symlink_farm/sub_farm/link_to_dd_dd_dfoo_include_dotdot_foo # # which is a link to ../../dfoo/include_dotdot_foo, that is, to # # dfoo/include_dotdot_foo # # which is a file that contains: # # #include "../foo" # # Here ../foo must refer to the file in location symlink_farm/sub_farm/foo, # which we have made a real file (not a symlink). # # We check that this "foo" is included. Moreover, we have put: # # #include "sub_farm/link_to_dd_dd_dfoo_include_dotdot_foo" # # into symlink_farm/sub_farm/foo, so that a nice infinite inclusion chain # is modeled. That should not faze the include server. In particular, we # do not want to see an infinitude of paths of the form: # # symlink_farm/sub_farm/../sub_farm/../ # ... # /sub_farm/../sub_farm/foo includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc -xc test_data/symlink_farm/sub_farm/" + "link_to_dd_dd_dfoo_include_dotdot_foo", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['dfoo/include_dotdot_foo', 'symlink_farm/foo'], "test_data")) def helper_test_IncludeAnalyzer(self, test_data_dir): """Test basic functionality assuming test data is in test_data_dir.""" # Simple stuff: quoted and angled directories, recursion includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc -Itest_data/dfoo test_data/parse.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['parse.c', 'dfoo/foo2.h', 'dfoo/foo.h', 'dfoo/../dbar/dbar1/bar.h'], test_data_dir)) # Computed includesgg includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc -Itest_data/dfoo test_data/computed_includes.c", os.getcwd())) # The path to the computed angle includes was not provided, so # they were not found. self.assertEqual( includes, self.CanonicalPathsForTestData( ['computed_includes.c', 'p1.h'], test_data_dir)) # Check that symbol_table has been updated. self.assertEqual(self.include_analyzer.symbol_table, {'dfoo_foo2_h': [None], 'A': ['"p1.h"'], 'dbar_dbar1_bar_h': [None], 'm': [(['a'], ''), (['a'], '')]}) # The include path to the angle includes, -Itest_data, is # provided at our next try. This should include abc_pre.c and # abc_post.c. This is especially challenging for incremental # analysis because the previous cached result of include analyzing # computed_includes.c cannot in fact be reused here. That is an # unusual case. includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc -Itest_data/dfoo -Itest_data" + " test_data/computed_includes.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['computed_includes.c', 'p1.h', 'abc_post.c', 'abc_pre.c'], test_data_dir)) # The inclusion chain is baz/start_x -> baz/x.h -> foo/x.h -> # bar/x.h -> baz.h. Only the final #include_next "x.h" in baz/x.h # does not Resolve because we just used -Ibaz for resolution, the # last in the list. This should not raise an exception, because the # failure may in reality not happen: the bad include_next could be # guarded by a conditional for example. self.assertEqual( self.RetrieveCanonicalPaths(self.ProcessCompilationCommandLine( "gcc -E -Itest_data/test_include_next/foo" + " -Itest_data/test_include_next/bar" + " -Itest_data/test_include_next/baz" + " test_data/test_include_next/baz/start_x.c", os.getcwd())), self.CanonicalPathsForTestData( ['test_include_next/baz/start_x.c', 'test_include_next/baz/x.h', 'test_include_next/foo/x.h', 'test_include_next/bar/x.h', 'test_include_next/baz/x.h'], test_data_dir)) # In contrast to previous example, the #final include_next in baz # resolves this time, namely to biz/x.h. self.assertEqual( self.RetrieveCanonicalPaths(self.ProcessCompilationCommandLine( "gcc -E -Itest_data/test_include_next/foo" + " -Itest_data/test_include_next/bar" + " -Itest_data/test_include_next/baz" + " -Itest_data/test_include_next/biz" + " test_data/test_include_next/baz/start_x.c", os.getcwd())), self.CanonicalPathsForTestData( ['test_include_next/baz/start_x.c', 'test_include_next/baz/x.h', 'test_include_next/foo/x.h', 'test_include_next/bar/x.h', 'test_include_next/biz/x.h'], test_data_dir)) includes = self.RetrieveCanonicalPaths(self.ProcessCompilationCommandLine( "gcc -E -Itest_data/test_include_next/foo" + " -Itest_data/test_include_next/bar" + " -Itest_data/test_include_next/baz" + " test_data/test_include_next/baz/start_y.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['test_include_next/baz/start_y.c', 'test_include_next/baz/../foo/y.h', 'test_include_next/bar/y.h', 'test_include_next/foo/y.h', 'test_include_next/baz/y.h'], test_data_dir)) # Test that a directory that has a name matching an include is not picked. # Here the directory is test_data/i_am_perhaps_a_directory.h, which is in # the file directory of the translation unit. Instead, # test_data/dfoo/i_am_perhaps_a_directory.h should be picked: it is a # regular file. includes = self.RetrieveCanonicalPaths(self.ProcessCompilationCommandLine( "gcc -E -Itest_data/dfoo test_data/test_directory_probing.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['test_directory_probing.c', 'dfoo/i_am_perhaps_a_directory.h'], test_data_dir)) def test_IncludeAnalyzer(self): """Run helper_test_IncludeAnalyzer 'directly' without complications of symbolic links.""" self.helper_test_IncludeAnalyzer('test_data') def test_IncludeAnalyzer_from_symlink_farm(self): """Run helper_test_IncludeAnalyzer through a link farm to exercise include processors ability to handle links.""" self.helper_test_IncludeAnalyzer('test_data/symlink_farm') for algorithm in [ basics.MEMOIZING ]: try: print("TESTING ALGORITHM %s" % algorithm) unittest.main() except: raise distcc-3.4/include_server/include_server.py000077500000000000000000000650511404653710500212440ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Conservative approximation of include dependencies for C/C++.""" __author__ = "Nils Klarlund" # TODO (klarlund) Implement abort mechanism: regularly check whether # ppid is 0; if so, then abort. # Python imports import gc import getopt import glob import os import re import shutil import signal import socketserver import sys import tempfile import traceback # Include server imports import basics import distcc_pump_c_extensions import include_analyzer_memoizing_node import statistics # The default size passed to listen by a streaming socket server of # socketserver is only 5. Make it 128 (which appears to be the hard # built-in limit for Linux). This enables requests to the include # server to be buffered better. REQUEST_QUEUE_SIZE = 128 Debug = basics.Debug DEBUG_TRACE = basics.DEBUG_TRACE DEBUG_WARNING = basics.DEBUG_WARNING # Exceptions. SignalSIGTERM = basics.SignalSIGTERM NotCoveredError = basics.NotCoveredError NotCoveredTimeOutError = basics.NotCoveredTimeOutError # USAGE def Usage(): print("""Usage: include_server --port INCLUDE_SERVER_PORT [OPTIONS] where INCLUDE_SERVER_PORT is a socket name. Fork the include server for incremental include analysis. The include server answers queries from the distcc client about which files to include in a C/C++ compilation. This command itself terminates as soon as the include server has been spawned. OPTIONS: -dPAT, --debug_pattern=PAT Bit vector for turning on warnings and debugging 1 = warnings 2 = trace some functions other powers of two: see basics.py. -e, --email Send email to discc-pump developers when include server gets in trouble. --email_bound NUMBER Maximal number of emails to send (in addition to a final email). Default: 3. --no-email Do not send email. --path_observation_re=RE Issue warning message whenever a filename is resolved to a realpath that is matched by RE, which is a regular expression in Python syntax. This is useful for finding out where files included actually come from. Use RE="" to find them all. Note: warnings must be enabled with at least -d1. --pid_file FILEPATH The pid of the include server is written to file FILEPATH. -s, --statistics Print information to stdout about include analysis. --stat_reset_triggers=LIST Flush stat caches when the timestamp of any filepath in LIST changes or the filepath comes in or out of existence. LIST is a colon separated string of filepaths, possibly containing simple globs (as allowed by Python's glob module). Print a warning whenever such a change happens (if warnings are enabled). This option allows limited exceptions to distcc_pump's normal assumption that source files are not modified during the build. -t, --time Print elapsed, user, and system time to stderr. --unsafe_absolute_includes Do preprocessing on the compilation server even if includes of absolute filepaths are encountered. Such includes are then ignored for the purposes of gathering the include closure. See the include_server(1) man page for further information. Using this option may lead to incorrect results. --no_force_dirs Do not force the creation of all directories used in an include path. May improve performance for some cases, but will break builds which use include structures like "" without including other files in foo/. -v, --verify Verify that files in CPP closure are contained in closure calculated by include processor. -w, --write_include_closure Write a .d_approx file which lists all the included files calculated by the include server; with -x, additionally write the included files as calculated by CPP to a .d_exact file. -x, --exact_analysis Use CPP instead, do not omit system headers files. """) # TODO(klarlund) # --simple_algorithm not currently implemented # UTILITIES def _PrintStackTrace(fd): """Print stacktrace to file object.""" print('------- Include server stack trace -----------', file=fd) # Limit is 1000 entries. traceback.print_exc(1000, fd) print('----------------------------------------------', file=fd) class _EmailSender(object): """For sending emails. We limit their number to avoid email storms.""" def __init__(self): self.number_sent = 0 def TryToSend(self, fd, force=False, never=False): """Send the contents of file to predefined blame address. Arguments: fd: open file descriptor, will remain open force: send even if bound has been reached """ if not basics.opt_send_email: return if self.number_sent >= basics.opt_email_bound and not force: return if never: return self.number_sent += 1 # For efficiency, we postpone reading needed libraries for emailing until # now. import smtplib import getpass import socket try: user_addr = "%s@%s" % (getpass.getuser(), socket.gethostname()) fd.seek(0) msg = "Subject: %s\nTo: %s\nFrom: %s\n\n%s\n%s" % ( basics.EMAIL_SUBJECT, basics.DCC_EMAILLOG_WHOM_TO_BLAME, user_addr, "Automated email number %d in include server session.\n" % self.number_sent, fd.read()) s = smtplib.SMTP() s.connect() s.sendmail(user_addr, [basics.DCC_EMAILLOG_WHOM_TO_BLAME], msg) Debug(DEBUG_WARNING, "Include server sent email to %s", basics.DCC_EMAILLOG_WHOM_TO_BLAME) s.close() except: Debug(DEBUG_WARNING, basics.CANT_SEND_MESSAGE) traceback.print_exc() def MaybeSendEmail(self, fd, force=False, never=False): """Print warning and maybe send email; the contents is from file object. Arguments: fd: a file object that will be closed. force: send the mail even if number of emails sent exceed basics.opt_email_bound """ fd.seek(0, 0) Debug(DEBUG_WARNING, "%s", fd.read()) self.TryToSend(fd, force, never) fd.close() NEWLINE_RE = re.compile(r"\n", re.MULTILINE) BACKSLASH_NEWLINE_RE = re.compile(r"\\\n", re.MULTILINE) def ExactDependencies(cmd, realpath_map, systemdir_prefix_cache, translation_unit): """The dependencies as calculated by CPP, the C Preprocessor. Arguments: cmd: the compilation command, a string realpath_map: map from filesystem paths (no symlink) to idx systemdir_prefix_cache: says whether realpath starts with a systemdir translation_unit: string Returns: the set of realpath indices of the include dependencies. Raises: NotCoveredError """ # Safely get a couple of temporary files. (fd_o, name_o) = tempfile.mkstemp("distcc-pump") (fd_d, name_d) = tempfile.mkstemp("distcc-pump") def _delete_temp_files(): os.close(fd_d) os.close(fd_o) os.unlink(name_o) os.unlink(name_d) # Remove -o option and call with -E, -M, and -MF flags. preprocessing_command = ( (re.sub(r"\s-o[ ]?(\w|[./+-])+", " ", cmd) # delete -o option + " -o %(name_o)s" # add it back, but to temp file, + " -E" # macro processing only + " -M -MF %(name_d)s") % # output .d file {'name_o':name_o, 'name_d':name_d}) ret = os.system(preprocessing_command) if ret: _delete_temp_files() raise NotCoveredError("Could not execute '%s'" % preprocessing_command, translation_unit) # Using the primitive fd_d file descriptor for reading is cumbersome, so open # normally as well. fd_d_ = open(name_d, "rb", encoding='latin-1') # Massage the contents of fd_d_ dotd = re.sub("^.*:", # remove Makefile target "", NEWLINE_RE.sub( "", # remove newlines BACKSLASH_NEWLINE_RE.sub("", # remove backslashes fd_d_.read()))) fd_d_.close() _delete_temp_files() # The sets of dependencies is a set the of realpath indices of the # absolute filenames corresponding to files in the dotd file. deps = set([ rp_idx for filepath in dotd.split() for rp_idx in [ realpath_map.Index(os.path.join(os.getcwd(), filepath)) ] if not systemdir_prefix_cache.StartsWithSystemdir(rp_idx, realpath_map) ]) statistics.len_exact_closure = len(deps) return deps def WriteDependencies(deps, result_file, realpath_map): """Write the list of deps to result_file. Arguments: deps: a list of realpath indices result_file: a filepath realpath_map: map from filesystem paths (no symlink) to idx """ try: fd = open(result_file, "w") fd.write("\n".join([realpath_map.string[d] for d in deps])) fd.write("\n") fd.close() except (IOError, OSError) as why: raise NotCoveredError("Could not write to '%s': %s" % (result_file, why)) def VerifyExactDependencies(include_closure, exact_no_system_header_dependency_set, realpath_map, translation_unit): """Compare computed and real include closures, ignoring system header files (such as those in /usr/include). Arguments: include_closure: a dictionary whose keys are realpath indices exact_no_system_header_dependency_set: set of realpath indices realpath_map: map from filesystem paths (no symlink) to idx translation_unit: string Raises: NotCoveredError """ diff = exact_no_system_header_dependency_set - set(include_closure) statistics.len_surplus_nonsys = ( len(set(include_closure) - exact_no_system_header_dependency_set)) if diff != set([]): # Pick one bad dependency. bad_dep = diff.pop() raise NotCoveredError( ("Calculated include closure does not contain: '%s'.\n" + "There %s %d such missing %s.") % (realpath_map.string[bad_dep], len(diff) == 0 and "is" or "are", len(diff) + 1, len(diff) == 0 and "dependency" or "dependencies"), translation_unit) # A SOCKET SERVER class Queuingsocketserver(socketserver.UnixStreamServer): """A socket server whose request queue have size REQUEST_QUEUE_SIZE.""" request_queue_size = REQUEST_QUEUE_SIZE def handle_error(self, _, client_address): """Re-raise current exception; overrides socketserver.handle_error. """ raise # HANDLER FOR SOCKETSERVER def DistccIncludeHandlerGenerator(include_analyzer): """Wrap a socketserver based on the include_analyzer object inside a new type that is a class named IncludeHandler.""" # TODO(klarlund): Can we do this without dynamic type generation? class IncludeHandler(socketserver.StreamRequestHandler): """Define a handle() method that invokes the include closure algorithm .""" def handle(self): """Using distcc protocol, read command and return include closure. Do the following: - Read from the socket, using the RPC protocol of distcc: - the current directory, and - the compilation command, already broken down into an argv vector. - Parse the command to find options like -I, -iquote,... - Invoke the include server's closure algorithm to yield a set of files and set of symbolic links --- both sets of files under client_root, which duplicates the part of the file system that CPP will need. - Transmit the file and link names on the socket using the RPC protocol. """ statistics.StartTiming() currdir = distcc_pump_c_extensions.RCwd(self.rfile.fileno()) cmd = distcc_pump_c_extensions.RArgv(self.rfile.fileno()) try: try: # We do timeout the include_analyzer using the crude mechanism of # SIGALRM. This signal is problematic if raised while Python is doing # I/O in the C extensions and during use of the subprocess # module. # # TODO(klarlund) The Python library manual states: "When a signal # arrives during an I/O operation, it is possible that the I/O # operation raises an exception after the signal handler returns. This # is dependent on the underlying Unix system's semantics regarding # interrupted system calls." We must clarify this. Currently, there # is I/O during DoCompilationCommand: # # - when a link is created in mirror_path.py # - module compress_files is used # # TODO(klarlund): Modify mirror_path so that is accumulates symbolic # link operations instead of actually executing them on the spot. The # accumulated operations can be executed after DoCompilationCommand # when the timer has been cancelled. include_analyzer.timer = basics.IncludeAnalyzerTimer() files_and_links = ( include_analyzer. DoCompilationCommand(cmd, currdir, include_analyzer.client_root_keeper)) finally: # The timer should normally be cancelled during normal execution # flow. Still, we want to make sure that this is indeed the case in # all circumstances. include_analyzer.timer.Cancel() except NotCoveredError as inst: # Warn user. The 'Preprocessing locally' message is meant to # assure the user that the build process is otherwise intact. fd = tempfile.TemporaryFile(mode='w+') print(("Preprocessing locally. Include server not covering: %s for " + "translation unit '%s'") % ( (inst.args and inst.args[0] or "unknown reason", include_analyzer.translation_unit)), file=fd, end=' ') # We don't include a stack trace here. include_analyzer.email_sender.MaybeSendEmail(fd, never=not inst.send_email) # The empty argv list denotes failure. Communicate this # information back to the distcc client, so that it can fall # back to preprocessing on the client. distcc_pump_c_extensions.XArgv(self.wfile.fileno(), []) if isinstance(inst, NotCoveredTimeOutError): Debug(DEBUG_TRACE, "Clearing caches because of include server timeout.") include_analyzer.ClearStatCaches() except SignalSIGTERM: # Normally, we will get this exception when the include server is no # longer needed. But we also handle it here, during the servicing of a # request. See basics.RaiseSignalSIGTERM. Debug(DEBUG_TRACE, "SIGTERM received while handling request.") raise except KeyboardInterrupt: # Propagate to the last-chance exception handler in Main. raise except SystemExit as inst: # When handler tries to exit (by invoking sys.exit, which in turn raises # SystemExit), something is really wrong. Terminate the include # server. But, print out an informative message first. fd = tempfile.TemporaryFile(mode='w+') print(("Preprocessing locally. Include server fatal error: '%s' for " + "translation unit '%s'") % ( (inst.args, include_analyzer.translation_unit)), file=fd, end=' ') _PrintStackTrace(fd) include_analyzer.email_sender.MaybeSendEmail(fd, force=True) distcc_pump_c_extensions.XArgv(self.wfile.fileno(), []) sys.exit("Now terminating include server.") # All other exceptions are trapped here. except Exception as inst: # Internal error. Better be safe than sorry: terminate include # server. But show error to user on stderr. We hope this message will be # reported. fd = tempfile.TemporaryFile(mode='w+') print(("Preprocessing locally. Include server internal error: '%s: %s'" + " for translation unit '%s'") % ( (inst.__class__, inst.args, include_analyzer.translation_unit)), file=fd) _PrintStackTrace(fd) # # Force this email through (if basics.opt_send_email is True), because # # this is the last one and this is an important case to report. include_analyzer.email_sender.MaybeSendEmail(fd, force=True) distcc_pump_c_extensions.XArgv(self.wfile.fileno(), []) raise SignalSIGTERM # to be caught in Main with no further stack trace else: # No exception raised, include closure can be trusted. distcc_pump_c_extensions.XArgv(self.wfile.fileno(), files_and_links) # Print out observed paths. if basics.opt_path_observation_re: include_analyzer.build_stat_cache.WarnAboutPathObservations( include_analyzer.translation_unit) # Finally, stop the clock and report statistics if needed. statistics.EndTiming() if basics.opt_statistics: statistics.PrintStatistics(include_analyzer) return IncludeHandler def _ParseCommandLineOptions(): """Parse arguments and options for the include server command. Returns: (include_server_port, pid_file), where include_server_port is a string and pid_file is a string or None Modifies: option variables in module basics """ try: opts, args = getopt.getopt(sys.argv[1:], "d:estvwx", ["port=", "pid_file=", "debug_pattern=", "email", "no-email", "email_bound=", "exact_analysis", "path_observation_re=", "stat_reset_triggers=", "simple_algorithm", "statistics", "time", "unsafe_absolute_includes", "no_force_dirs", "verify", "write_include_closure"]) except getopt.GetoptError: # Print help information and exit. Usage() sys.exit(1) pid_file = None include_server_port = None for opt, arg in opts: try: if opt in ("-d", "--debug_pattern"): basics.opt_debug_pattern = int(arg) if opt in ("--port", ): include_server_port = arg if opt in ("--pid_file",): pid_file = arg if opt in ("-e", "--email"): basics.opt_send_email = True if opt in ("--no-email",): basics.opt_send_email = False if opt in ("--email_bound",): basics.opt_email_bound = int(arg) if opt in ("--path_observation_re",): basics.opt_path_observation_re = re.compile(arg) if opt in ("--stat_reset_triggers",): basics.opt_stat_reset_triggers = ( dict([ (glob_expr, dict ([ (path, basics.Stamp(path)) for path in glob.glob(glob_expr) ])) for glob_expr in arg.split(':') ])) if opt in ("--simple_algorithm",): basics.opt_simple_algorithm = True sys.exit("Not implemented") if opt in ("--unsafe_absolute_includes",): basics.opt_unsafe_absolute_includes = True if opt in ("--no_force_dirs",): basics.opt_no_force_dirs = True if opt in ("-s", "--statistics"): basics.opt_statistics = True if opt in ("-t", "--time"): basics.opt_print_times = True if opt in ("-v", "--verify"): basics.opt_verify = True if opt in ("-w", "--write_include_closure"): basics.opt_write_include_closure = True if opt in ("-x", "--exact_analysis"): basics.opt_exact_include_analysis = True except ValueError: Usage() sys.exit(1) # We must have a port! if not include_server_port: print("INCLUDE_SERVER_PORT not provided. Aborting.", file=sys.stderr) print("-------------------------------------------", "\n", file=sys.stderr) Usage() sys.exit(1) return (include_server_port, pid_file) def _PrintTimes(times_at_start, times_at_fork, times_child): """Print elapsed, user, system, and user + system times.""" # The os.times format stores user time in positions 0 and 2 (for parent and # children, resp.) Similarly, system time is stored in positions 1 and # 3. Elapsed time is in position 4. Elapsed time is measured relative to some # epoch whereas user and system time are 0 at the time of process creation. total_u = (times_at_fork[0] + times_at_fork[2] + times_child[0] + times_child[2]) total_s = (times_at_fork[1] + times_at_fork[3] + times_child[1] + times_child[1]) total_cpu = total_u + total_s total_e = times_child[4] - times_at_start[4] print("Include server timing. ", sys.stderr) print("Elapsed: %3.1fs User: %3.1fs System: %3.1fs User + System: %3.1fs" % (total_e, total_u, total_s, total_cpu), file=sys.stderr) class _IncludeServerPortReady(object): """A simple semaphore for forked processes. The implementation uses an unnamed pipe.""" def __init__(self): """Constructor. Should be called before fork. """ (self.read_fd, self.write_fd) = os.pipe() def Acquire(self): """Acquire the semaphore after fork; blocks until a call of Release.""" if os.read(self.read_fd, 1) != b'\n': sys.exit("Include server: _IncludeServerPortReady.Acquire failed.") def Release(self): """Release the semaphore after fork.""" if os.write(self.write_fd, b'\n') != 1: sys.exit("Include server: _IncludeServerPortReady.Release failed.") def _SetUp(include_server_port): """Setup include_analyzer and socket server. Returns: (include_analyzer, server)""" try: os.unlink(include_server_port) except (IOError, OSError): pass # this would be expected, the port provided should not exist if os.sep != '/': sys.exit("Expected '/' as separator in filepaths.") client_root_keeper = basics.ClientRootKeeper() # Clean out any junk left over from prior runs. client_root_keeper.CleanOutOthers() Debug(DEBUG_TRACE, "Starting socketserver %s" % include_server_port) # Create the analyser. include_analyzer = ( include_analyzer_memoizing_node.IncludeAnalyzerMemoizingNode( client_root_keeper, basics.opt_stat_reset_triggers)) include_analyzer.email_sender = _EmailSender() # Wrap it inside a handler that is a part of a UnixStreamServer. server = Queuingsocketserver( include_server_port, # Now, produce a StreamRequestHandler subclass whose new objects has # a handler which calls the include_analyzer just made. DistccIncludeHandlerGenerator(include_analyzer)) return (include_analyzer, server) def _CleanOut(include_analyzer, include_server_port): """Prepare shutdown by cleaning out files and unlinking port.""" if include_analyzer and include_analyzer.client_root_keeper: include_analyzer.client_root_keeper.CleanOutClientRoots() try: os.unlink(include_server_port) except OSError: pass def Main(): """Parse command line, fork, and start stream request handler.""" # Remember the time spent in the parent. times_at_start = os.times() include_server_port, pid_file = _ParseCommandLineOptions() # Get locking mechanism. include_server_port_ready = _IncludeServerPortReady() # Now spawn child so that parent can exit immediately after writing # the process id of child to the pid file. times_at_fork = os.times() pid = os.fork() if pid != 0: # In parent. # if pid_file: pid_file_fd = open(pid_file, "w") print(pid, file=pid_file_fd) pid_file_fd.close() # Just run to completion now -- after making sure that child is ready. include_server_port_ready.Acquire() # concerned. else: # In child. # # We call _Setup only now, because the process id, used in naming the client # root, must be that of this process, not that of the parent process. See # _CleanOutOthers for the importance of the process id. (include_analyzer, server) = _SetUp(include_server_port) include_server_port_ready.Release() try: try: gc.set_threshold(basics.GC_THRESHOLD) # Use commented-out line below to have a message printed for each # collection. # gc.set_debug(gc.DEBUG_STATS + gc.DEBUG_COLLECTABLE) server.serve_forever() except KeyboardInterrupt: print("Include server: keyboard interrupt, quitting after cleaning up.", file=sys.stderr) _CleanOut(include_analyzer, include_server_port) except SignalSIGTERM: Debug(DEBUG_TRACE, "Include server shutting down.") _CleanOut(include_analyzer, include_server_port) except: print("Include server: exception occurred, quitting after cleaning up.", file=sys.stderr) _PrintStackTrace(sys.stderr) _CleanOut(include_analyzer, include_server_port) raise # reraise exception finally: if basics.opt_print_times: _PrintTimes(times_at_start, times_at_fork, os.times()) if __name__ == "__main__": # Treat SIGTERM (the default of kill) as Ctrl-C. signal.signal(signal.SIGTERM, basics.RaiseSignalSIGTERM) Main() distcc-3.4/include_server/include_server_test.py000077500000000000000000000136171404653710500223040ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Exercise include server handler with respect to exceptions and email. To do this, we mock out socket servers, c_extensions, email handling, and even ultimately the notion of an AssertionError. """ __author__ = "Nils Klarlund" import os import sys import traceback import unittest import basics import cache_basics import parse_command import statistics import include_analyzer_memoizing_node import include_server import distcc_pump_c_extensions NotCoveredError = basics.NotCoveredError class IncludeServerTest(unittest.TestCase): def setUp(self): statistics.StartTiming() basics.opt_print_statistics = False basics.opt_debug_pattern = 1 def tearDown(self): if basics.opt_print_statistics: statistics.EndTiming() statistics.PrintStatistics(self.include_analyzer) def CanonicalPaths(self, dirs): return set([ self.canonical_path.Canonicalize(f) for f in dirs ]) def RetrieveCanonicalPaths(self, files): return set([ self.include_analyzer.realpath_map.string[f] for f in files ]) def test_IncludeHandler_handle(self): self_test = self client_root_keeper = basics.ClientRootKeeper() old_RWcd = distcc_pump_c_extensions.RCwd distcc_pump_c_extensions.RCwd = None # to be set below old_RArgv = distcc_pump_c_extensions.RArgv distcc_pump_c_extensions.RArgv = None # to be set below old_XArgv = distcc_pump_c_extensions.XArgv distcc_pump_c_extensions.XArgv = lambda _, __: None old_StreamRequestHandler = ( include_server.socketserver.StreamRequestHandler) class Mock_StreamRequestHandler(object): def __init__(self): self.rfile = lambda: None self.rfile.fileno = lambda: 27 self.wfile = lambda: None self.wfile.fileno = lambda: 27 include_server.socketserver.StreamRequestHandler = ( Mock_StreamRequestHandler) include_analyzer = ( include_analyzer_memoizing_node. IncludeAnalyzerMemoizingNode(client_root_keeper)) class Mock_EmailSender(object): def __init(self): self.expect = lambda: None def MaybeSendEmail(self, fd, force=False, never=False): fd.seek(0) text = fd.read() self.expect(text, force, never) fd.close() raise mock_email_sender = include_analyzer.email_sender = Mock_EmailSender() include_handler = ( include_server.DistccIncludeHandlerGenerator(include_analyzer)()) # Wow, that was a lot of set-up. Now exercise the include server and # analyzer with an emphasis on triggering exceptions. # Exercise 1: non-existent translation unit. distcc_pump_c_extensions.RArgv = lambda self: [ "gcc", "parse.c" ] distcc_pump_c_extensions.RCwd = lambda self: os.getcwd() def Expect1(txt, force, never): self_test.assertTrue( "Include server not covering: " + "Could not find translation unit 'parse.c'" in txt, txt) self_test.assertEqual(never, True) mock_email_sender.expect = Expect1 try: include_handler.handle() except NotCoveredError: pass else: raise AssertionError # Exercise 2: provoke assertion error in cache_basics by providing an # entirely false value of current directory as provided in RCwd. distcc_pump_c_extensions.RArgv = lambda self: [ "gcc", "parse.c" ] distcc_pump_c_extensions.RCwd = lambda self: "/" # The cwd will be changed because of false value. oldcwd = os.getcwd() # We must distinguish between provoked and erroneous exceptions. So, we # mock out, in a sense, the provoked assertion exception that we # expect. The variable got_here allows us to filter the provoked exception # away from unexpected ones. got_here = [] def Expect2(txt, force, never): got_here.append(True) self_test.assertTrue("Include server internal error" in txt, txt) self_test.assertTrue("exceptions.AssertionError" in txt, txt) self_test.assertTrue("for translation unit 'parse.c'" in txt, txt) # This email should be sent. self_test.assertEqual(never, False) mock_email_sender.expect = Expect2 try: include_handler.handle() except AssertionError: os.chdir(oldcwd) # Make sure that we're catching the induced AssertionError, not one # produced in Except2. self.assertTrue(got_here) else: raise AssertionError # Exercise 3: provoke a NotCoveredError due to an absolute #include. distcc_pump_c_extensions.RArgv = lambda self: [ "gcc", "test_data/contains_abs_include.c" ] distcc_pump_c_extensions.RCwd = lambda self: os.getcwd() def Expect3(txt, force, never): self_test.assertTrue( "Filepath must be relative but isn't: '/love/of/my/life'." in txt, txt) # Now check that this email is scheduled to not be sent. self_test.assertEqual(never, True) mock_email_sender.expect = Expect3 try: include_handler.handle() except NotCoveredError: pass distcc_pump_c_extensions.RWcd = old_RWcd distcc_pump_c_extensions.RArgv = old_RArgv distcc_pump_c_extensions.XArgv = old_XArgv include_server.socketserver.StreamRequestHandler = ( old_StreamRequestHandler) unittest.main() distcc-3.4/include_server/macro_eval.py000077500000000000000000000366701404653710500203500ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Evaluation of macros acccording to an overapproximation semantics. This module generally follows CPP semantics for the evaluation of macros. But we treat every define as a possible one, because we don't know whether it is actually executed when a file is really preprocessed. Our semantics is thus multi-valued: an expression (that is, a string) is evaluated to the set of poosible values it can have according to arbitrary choices of #defines in effect among those encountered in the program text. An example explains the general idea. If we have: #define A x #define A y #define B 1 #define B 2 Then the expression A.B evaluates to one of the following: x.1 y.1 x.2 y.2 The set {"x.1", "y.1", "x.2", "y.2"} is the value of EvalExpr("A.B", symbol_table), where symbol_table is the dictionary in which we have stored the four #define's. Currently, we will be satisfied with A A evaluating to x x x y y x y y although a sharper semantic modelling would yield only: x x y y How to Read This Code --------------------- An understanding of the C preprocessor is necessary. See "The GNU C Preprocessor Internals" (http://gcc.gnu.org/onlinedocs/cppinternals). Especially the section "Macro Expansion Algorithm" is informative. Whitespace Insertion and Other Deficiencies ------------------------------------------- CPP inserts whitespaces and sometimes doesn't according to very complicated rules. We do not insert whitespaces. Also, we retokenize each intermediate expansion. For actual arguments of macros, we also we do not do the right thing for parentheses inside single quotes, which is to ignore them. There are probably several more deviations from CPP semantics. These deviations should not matter for most common included computes. What If the Include Processor is Wrong -------------------------------------- Assume that we have #include very_complicated_call(anfhis,fifj) If the include processor produces spurious expansions like: "whatda.c" 2 + 2 "5 * 3" then file whada.c if found in search directory becomes part of the include closure. So does the file "5 * 3". But 2 + 2 does not have the shape of an a filepath in an include: the filepath must be in quotes or angle brackets. These spurious files are not harmful to preprocessing on the server. If the include server omits calculating the expansion "right_file.h" then the compilation on the server will fail. The client, according to the logic of dcc_build_somewhere, will then perform a local compilation. Symbol Table ------------ The symbol table is a dictionary, whose entries are of the form symbol: definition_list Each definition in definition_list is either - a string, denoting the expansion of an object-like macro, or - a pair ([param_1,...,param_n], rhs), which denotes a function-like macro, whose formal parameters are param_1,.., param_n and whose expansion is rhs, before the substitution of formal parameters for actual parameters. """ __author__ = "Nils Klarlund" import re import basics import parse_file import statistics Debug = basics.Debug DEBUG_TRACE = basics.DEBUG_TRACE DEBUG_TRACE1 = basics.DEBUG_TRACE1 DEBUG_TRACE2 = basics.DEBUG_TRACE2 NotCoveredError = basics.NotCoveredError # REGULAR EXPRESSIONS SINGLE_POUND_RE = re.compile(r"\B#\s*(\S*)") # \B = here: not at end of word DOUBLE_POUND_RE = re.compile(r"##") SYMBOL_RE = re.compile(r"\b\w+\b") # \b = word boundary \w = word constituent # HELPER FUNCTIONS def _BigUnion(list_of_sets): """Return the set that is the union of the sets or lists in list_of_sets.""" result = [] for s in list_of_sets: result.extend(list(s)) return set(result) def _PrependToSet(expr, expr_set): """Return the set consisting of expr + element with element in expr_set.""" return set([ expr + expr_ for expr_ in expr_set ]) def _SubstituteSymbolInString(x, y, str): """Return the string that results from substituting x for y in str.""" Debug(DEBUG_TRACE2, """_SubstituteSymbolInString: x: "%s", y: "%s", str:"%s" """, x, y, str) result = re.sub(r"\b%s\b" % re.escape(x), y.replace('\\', '\\\\'), str) Debug(DEBUG_TRACE2, """_SubstituteSymbolInString (result): "%s" """, result) return result def _ParseArgs(string, pos): """Split stuff according to commas at outer level in parenthesized string. If string[pos:] does not start with '(', return (None, pos). If string[pos:] starts with '(' and there is a balanced parenthesis structure ending at pos_end, then return (args, pos_end), where args is string[pos:pos_end] hacked into segments between commas at outer level. So "(a,m(c, n(d)), c)...." results in (["a", "m(c, n(d))", " c"], 17) being returned. """ # TODO(klarlund): we ignore ignoring parentheses inside single quotes. Such # occurrences are deemed unlikely at this moment. Fix that so that parentheses # inside single quotes are ignored. open_parens = 0 if not pos < len(string) or string[pos] != '(': return (None, pos) # Prepare a list of comma and extremal positions. The '(' at the left is the # first extremal position. commas = [pos] pos_end = None inside_quotes = False for i in range(pos, len(string)): if inside_quotes: if string[i] == '"' and string[i-1] != r'\\': inside_quotes = False continue if string[i]==',' and open_parens==1: commas.append(i) elif string[i]=='(': open_parens += 1 elif string[i]==')': open_parens -= 1 if open_parens == 0: pos_end = i break elif string[i] == '"' and string[i-1] != r'\\': inside_quotes = True if not pos_end: return (None, pos) commas.append(pos_end) # the other extremal position args_list = [] for i in range(len(commas) - 1): args_list.append(string[commas[i] + 1 : commas[i + 1]]) return (args_list, pos_end + 1) def _MassageAccordingToPoundSigns(string): """Perform 'stringification (#) and concatenation (##).""" return SINGLE_POUND_RE.sub(r'"\1"', DOUBLE_POUND_RE.sub("", string)) # EVALUATION def _EvalExprHelper(expr, symbol_table, disabled): if __debug__: Debug(DEBUG_TRACE2, "EvalExprHelper: expr: %s", expr) """Evaluate according to an overapproximation macro substitution semantics. Arguments: expr: a string symbol_table: { symbol: [rhs, ..., ([param_1,...,param_n], rhs), ...], ... }, where rhs and param_i are strings disabled: set of disabled symbols (see "The GNU C Preprocessor Internals") Returns: [ expr_1, expr_2, ...], which is a non-empy list of strings, namely the expansions of expr. """ def _ReEvalRecursivelyForExpansion(expansion, after): """Reevaluate the expansion that is the result of finding a match for a macro. Arguments: symbol (outer scope): the name of the matched macro that resulted in expansion; it is the same as match.group() match (outer scope): the match data for the symbol expansion: the expansion we are substituting for the match after: the string after the expansion Modifies: value_set: the set of all possible expansions of expr The value set is updated according to recursive evaluations of the string that results from inserting expansion between expr[:match.start()] and expr[match.end():] (for symbol-like macro) or expr[args_end:] (for function-like macro). The idea is to form a set of strings from a cross product of two string sets describing all possibly expansions before and after the match. There are two recursions involved. First, we evaluate after to find all possible values of what follows the match. This recursion does not involve a larger disabled set. Each resulting string is named after_eval_expr. Second, we evaluate expansion concatenated with each after_eval_expr value. In these evaluations, symbol is added to the disabled set. """ if __debug__: Debug(DEBUG_TRACE2, ("_ReEvalRecursivelyForExpansion: expr: %s\n" + " before: %s\n expansion: %s\n after: %s") % (expr, expr[:match.start()], expansion, after)) value_set.update( _PrependToSet(expr[:match.start()], _BigUnion([ _EvalExprHelper(expansion + after_expansion, symbol_table, disabled | set([symbol])) for after_expansion in _EvalExprHelper(after, symbol_table, disabled) ]))) def _EvalMacro(definition, disabled): """Evaluate symbol according to definition. Here definition is either object-like or function-like. """ # Consider that this symbol goes unevaluated. value_set.update( _PrependToSet(expr[:match.end()], _EvalExprHelper(expr[match.end():], symbol_table, disabled))) if isinstance(definition, str): # The expansion is the definition. _ReEvalRecursivelyForExpansion(definition, expr[match.end():]) elif isinstance(definition, tuple): # We have an invocation a function-like macro. Find the possible # values of the function symbol, according to object-like # expansions, before substituting. (lhs, rhs) = definition # lhs = formal parameters, rhs = # expansion before substitution # Verify that the number of formal parameters match the # number of actual parameters; otherwise skip. if not args_list or len(lhs) != len(args_list): return # Expand arguments recursively. args_expand = [ _EvalExprHelper(arg, symbol_table, disabled) for arg in args_list ] # Do the substitutions. Again, we'll need to piece together # strings from a cross product. In this the fragments come from # the expansions of the arguments. expansions = [rhs] for i in range(len(args_expand)): expansions = [ _SubstituteSymbolInString(lhs[i], arg, expansion) for expansion in expansions for arg in args_expand[i] ] for expansion in expansions: real_expansion = _MassageAccordingToPoundSigns(expansion) _ReEvalRecursivelyForExpansion(real_expansion, expr[args_end:]) else: assert False, "Definition '%s' is unexpected." % definition # Look for a symbol. match = SYMBOL_RE.search(expr) if not match: # No symbol found. return set([expr]) else: # Let's break down the string into segments according to the # symbol found. This is non-standard: the real CPP only tokenizes # once. symbol = match.group() (args_list, args_end) = _ParseArgs(expr, match.end()) Debug(DEBUG_TRACE2, "EvalExprHelper (inside): expr: %s\n" + " symbol: %s\n args_list: %s\n" + " before: %s\n", expr, symbol, args_list, expr[:match.start()]) if symbol not in symbol_table: # Process rest of string recursively. return _PrependToSet(expr[:match.end()], _EvalExprHelper(expr[match.end():], symbol_table, disabled)) else: # Now consider the set of meanings of this symbol. But first # note that the string remaining unexpanded is always a # possibility, because we are doing a "forall" analysis. value_set = set([expr]) # Now carry out substitution on expr[match.start():match.end()], # the whole stretch of expr that consists of symbol and possibly # args with parentheses. if symbol not in disabled: defs = symbol_table[symbol] for definition in defs: _EvalMacro(definition, disabled) return value_set def EvalExpression(expr, symbol_table): """Calculate sets of possibly values of expr given symbol_table. Arguments: expr: any string to be macro expanded symbol_table: { symbol: {rhs, ..}, ,..., symbol:{((param_1,...,param_n), rhs), ... } Returns: [ expr_1, expr_2, ...], a list of strings: the possible expansions of expr. """ if __debug__: Debug(DEBUG_TRACE, "EvalExpression: expr: %s", expr) r = set(_EvalExprHelper(expr, symbol_table, set([]))) if __debug__: Debug(DEBUG_TRACE, "EvalExpression: return: %s", r) return r def ResolveExpr(includepath_map_index, resolve, expr, currdir_idx, searchdir_idx, quote_dirs, angle_dirs, symbol_table): """Evaluate and resolve possible values for expr using symbol table. Determine all possible values of expr. Those that are of the form "filepath" or are resolved against (file_dir_idx, quote_dirs) or angle_dirs, respectively. The set of resolvants is returned along with a list of all symbols that occurs in possible evaluations of expr. Arguments: includepath_map_index: the Index function of an includepath map resolve: a Resolve method of a BuildStatCache object expr: any string to be macro expanded currdir_idx: a directory index searchdir_idx: a directory index (used for resolving quote-includes) quote_dirs: a directory index list angle_dirs: a directory index list symbol_table: as described in module macro_expr Returns: a pair(files, symbols), where files is a list of (filepath pair, realpath index), namely those files that are successful resolutions of possible double-quoted and angle-quoted values of expr, and symbols is the set of all identifiers occurring in expression or its possible expansions Raises: NotCoveredError """ if __debug__: Debug(DEBUG_TRACE, "ResolveExpr: %s, %s, %s", expr, searchdir_idx, angle_dirs) resolved_files = [] symbols = [] statistics.resolve_expr_counter += 1 for val in EvalExpression(expr, symbol_table): match_result = parse_file.INCLUDE_STRING_RE.match(val) if match_result: if match_result.group('quote'): resolved = resolve(includepath_map_index(match_result.group('quote')),currdir_idx, searchdir_idx, quote_dirs) resolved_files.append(resolved) elif match_result.group('angle'): resolved = resolve(includepath_map_index(match_result.group('angle')), currdir_idx, None, angle_dirs) resolved_files.append(resolved) else: symbols.extend(SYMBOL_RE.findall(val)) if __debug__: Debug(DEBUG_TRACE, "ResolveExpr: return: %s", resolved_files) return (resolved_files, set(symbols)) distcc-3.4/include_server/macro_eval_test.py000077500000000000000000000167321404653710500214040ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. __author__ = "Nils Klarlund" # See also tests in include_server_test.py. import os import basics import parse_file import cache_basics import macro_eval import shutil import tempfile import unittest NotCoveredError = basics.NotCoveredError class MacroEvalTest(unittest.TestCase): def setUp(self): basics.opt_debug_pattern = 1 self.tmp = tempfile.mkdtemp() caches = cache_basics.SetUpCaches(self.tmp) self.includepath_map = caches.includepath_map self.canonical_path = caches.canonical_path self.directory_map = caches.directory_map self.realpath_map = caches.realpath_map def tearDown(self): shutil.rmtree(self.tmp) def test__SubstituteSymbolInString(self): self.assertEqual( macro_eval._SubstituteSymbolInString("X", "f(y)", "X+(X, X##Y)"), "f(y)+(f(y), f(y)##Y)") self.assertEqual( macro_eval._SubstituteSymbolInString("a", "b", "c(a, aa)"), "c(b, aa)") def test_MassageAccordingToPoundSigns(self): self.assertEqual(macro_eval._MassageAccordingToPoundSigns('#aa##bb'), '"aabb"') self.assertEqual(macro_eval._MassageAccordingToPoundSigns('# a(.)'), '"a(.)"') def test__ParseArgs(self): self.assertEqual(macro_eval._ParseArgs("(a,m(c, n(d)), c)", 0), (["a", "m(c, n(d))", " c"], 17)) self.assertEqual(macro_eval._ParseArgs("""(a","m(c, n(d)), c)""", 0), (["""a","m(c, n(d))""", " c"], 19)) def test__PrependToSet(self): self.assertEqual( macro_eval._PrependToSet("x", set(["y", "z"])), set(["xy", "xz"])) def test__BigUnion(self): self.assertEqual(macro_eval._BigUnion([set([]), set([1,2]), set([3])]), set([1,2,3])) def test_EvalExprDirs(self): self.assertEqual( macro_eval.EvalExpression("A", { 'A': ['b'] }), set(['A', 'b'])) self.assertEqual( macro_eval.EvalExpression("A", { 'A': ['B'], 'B': ['A'] }), set(['A', 'B'])) self.assertEqual( macro_eval.EvalExpression("A", { 'A': ['B'], 'B': ['c'] }), set(['A', 'B', 'c'])) self.assertEqual( macro_eval.EvalExpression("max(2, 4)", { 'max': [ ( ['x', 'y'], "x < y? y: x") ] }), set(['max(2, 4)', '2 < 4? 4: 2'])) self.assertEqual( macro_eval.EvalExpression("F(2, 4)", { 'F': ['max'], 'max': [ ( ['x', 'y'], "x < y? y: x") ] }), set(['max(2, 4)', 'F(2, 4)', '2 < 4? 4: 2'])) self.assertEqual( macro_eval.EvalExpression("max(max(1,2), 3)", { 'max': [ ( ['x', 'y'], "(x < y? y: x)") ] }), set(['((1 < 2? 2: 1) < 3? 3: (1 < 2? 2: 1))', 'max(max(1,2), 3)', '(max(1,2) < 3? 3: max(1,2))', 'max((1 < 2? 2: 1), 3)'])) self.assertEqual( macro_eval.EvalExpression("A", { 'A': ['"a.c"'] }), set(['A', '"a.c"'])) # The ## operator only works in rhs of function-like macros. Check # that it doesn't work stand-alone. self.assertEqual( macro_eval.EvalExpression("A##A", { 'A': ['a.c'] }), set(['A##A', 'a.c##A', 'A##a.c', 'a.c##a.c'])) self.assertEqual( macro_eval.EvalExpression("A(y)A(z)", { 'A': [(['x'], 'x##a.c')] }), set(['A(y)A(z)', 'A(y)za.c', 'ya.cza.c', 'ya.cA(z)'])) self.assertEqual( macro_eval.EvalExpression("m(abc)", { 'm': [( ['a'], "" )] }), set(['m(abc)', ''])) self.assertEqual( macro_eval.EvalExpression("myfile(hello)", { 'myfile': [(['x'], "myquote(myplace/x)")], 'myquote': [(['y'], """#y""")] }), set(['myfile(hello)', '"myplace/hello"', 'myquote(myplace/hello)'])) def test_FromCPPInternals(self): # This little example works. # # #define foo(x) bar x # # foo(foo) (2) == bar foo (2) # # Let us check that. self.assertEqual( macro_eval.EvalExpression("foo(foo) (2)", {'foo':[(['x'], "bar x")]}), set(['bar foo (2)', 'foo(foo) (2)'])) # The next one does not work, because we are not inserting spaces. # # From : # http://gcc.gnu.org/onlinedocs/cppinternals/Token-Spacing.html#Token-Spacing # # #define PLUS + # #define EMPTY # #define f(x) =x= # # +PLUS -EMPTY- PLUS+ f(=) # ==> + + - - + + = = = # # We do not insert spaces as CPP does. But we generate a lot of # combinations! self.assertEqual( macro_eval.EvalExpression("+PLUS -EMPTY- PLUS+ f(=)", { 'PLUS':['+'], 'EMPTY':[""], 'f':[(['x'], '=x=')] }), set(['++ -EMPTY- ++ ===', '++ -EMPTY- PLUS+ ===', '+PLUS -- ++ f(=)', '+PLUS -EMPTY- ++ ===', '++ -EMPTY- PLUS+ f(=)', '+PLUS -EMPTY- PLUS+ f(=)', '+PLUS -- ++ ===', '++ -EMPTY- ++ f(=)', '+PLUS -- PLUS+ ===', '+PLUS -- PLUS+ f(=)', '++ -- PLUS+ ===', '++ -- ++ ===', '+PLUS -EMPTY- PLUS+ ===', '++ -- PLUS+ f(=)', '+PLUS -EMPTY- ++ f(=)', '++ -- ++ f(=)'])) def test_ResolveExpr(self): # Erect the edifice of caches. caches = cache_basics.SetUpCaches(self.tmp) parse_file_obj = parse_file.ParseFile(caches.includepath_map) symbol_table = {} # Set up symbol_table by parsing test_data/more_macros.c. self.assertEqual(parse_file_obj.Parse( "test_data/more_macros.c", symbol_table), ([], [], ['TEMPLATE_VARNAME(foo)'], [])) # Check what we got in symbol_table. self.assertEqual( macro_eval.EvalExpression("TEMPLATE_VARNAME(foo)", symbol_table), set(['TEMPLATE_VARNAME(foo)', '"maps/foo.tpl.varnames.h"', 'AS_STRING(maps/foo.tpl.varnames.h)', 'AS_STRING_INTERNAL(maps/foo.tpl.varnames.h)'])) # Verify that resolving this expression yields one actual file (which we # have placed in test_data/map). [((d, ip), rp)], symbols = macro_eval.ResolveExpr( caches.includepath_map.Index, caches.build_stat_cache.Resolve, 'TEMPLATE_VARNAME(foo)', caches.directory_map.Index(os.getcwd()), # current dir caches.directory_map.Index(""), # file directory [caches.directory_map.Index("test_data")], # search directory [], symbol_table) self.assertEqual(caches.directory_map.string[d], "test_data/") self.assertEqual(caches.includepath_map.string[ip], "maps/foo.tpl.varnames.h") self.assertEqual(symbols, set(['TEMPLATE_VARNAME', 'maps', 'AS_STRING', 'AS_STRING_INTERNAL', 'tpl', 'varnames', 'h', 'foo'])) unittest.main() distcc-3.4/include_server/mirror_path.py000077500000000000000000000135011404653710500205520ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # """Memoizing, piecemeal mirroring of directory and link structure.""" __author__ = "Nils Klarlund" import os import os.path import cache_basics class MirrorPath(object): """Make a caching structure for copying all parts of the paths that method DoPath is called with. This includes replication of symbolic links. But the targets of symbolic links are absolutized: they are replaced by the realpath of the original target, whether this target was relative or absolute. Also, remember all directories that had to be followed to find out what paths mean. This is of particular importance to the '..' operator, which may involve temporary excursions into directories that otherwise contain no files of relevance to the build. But the directories must still be replicated on the server for the semantics of '..' to work. These are called must_exist_dirs. """ def __init__(self, simple_build_stat, canonical_path, realpath_map, systemdir_prefix_cache): """Constructor. Arguments: simple_build_stat: object of type SimpleBuildStat canonical_path: function of type CanonicalPath realpath_map: a CanonicalMapToIndex; see cache_basics.py systemdir_prefix_cache: a SystemdirPrefixCache; see cache_basics.py. """ assert isinstance(simple_build_stat, cache_basics.SimpleBuildStat) assert isinstance(canonical_path, cache_basics.CanonicalPath) # All links encountered so far. self.links = [] # We cache tuples (filepath, current_dir_idx) for which we've already fixed # up the symbolic links. self.link_stat = set([]) # Usual abbreviations. self.simple_build_stat = simple_build_stat self.canonical_path = canonical_path self.must_exist_dirs = [] self.realpath_map = realpath_map self.systemdir_prefix_cache = systemdir_prefix_cache def Links(self): """Return the list of symbolic links created.""" return self.links def MustExistDirs(self): return self.must_exist_dirs def DoPath(self, filepath, current_dir_idx, root): """Mirror the parts of filepath not yet created under root. Arguments: filepath: a string, which is relative or absolute filename current_dir_idx: a directory index root: a string denoting an absolute path for an existing directory """ assert isinstance(filepath, str) assert isinstance(current_dir_idx, int) assert isinstance(root, str) assert root[0] == '/' and root[-1] != '/' assert os.path.isdir(root), root link_stat = self.link_stat lookup = self.simple_build_stat.Lookup # Working from the end (in the hope that a cache lookup will reveal # the futility of further work), make sure that intermediate # destinations exist, and replicate symbolic links where necessary. while filepath and filepath != '/': if (filepath, current_dir_idx) in link_stat: # Filepath is already mirrored return link_stat.add((filepath, current_dir_idx)) # Process suffix of filepath by # - making sure that the mirrored real path of the prefix exists, # - and that the suffix if a symbolic link # is replicated as a symbolic link. assert filepath[-1] != '/', filepath # Now identify the potential symbolic link at the end of filepath (prefix_filepath, suffix) = os.path.split(filepath) # Calculate the real position of the destination of the prefix prefix_real = self.canonical_path.Canonicalize(prefix_filepath) if prefix_real == '/': prefix_real = '' # And, its counterpart under root root_prefix_real = root + prefix_real # Make sure that the parent, root_prefix_real, is there if not lookup(root_prefix_real): # We have not been in this real location before. if not os.path.isdir(root_prefix_real): # Now check that the parent of the link is not under a default system # dir. If it is, then we assume that the parent and indeed the # link itself exist on the server as well, and thus, don't need to # be mirrored. realpath_map = self.realpath_map realpath_idx = realpath_map.Index(prefix_real) if not self.systemdir_prefix_cache.StartsWithSystemdir(realpath_idx, realpath_map): # Not under default system dir. Mark this directory as one that # must always be created on the server. self.must_exist_dirs.append(root_prefix_real) # Create parent path in mirror directory. os.makedirs(root_prefix_real) else: break self.simple_build_stat.cache[root_prefix_real] = True assert os.path.isdir(root_prefix_real) # Create the mirrored symbolic link if applicable. if os.path.islink(filepath): link_name = root_prefix_real + '/' + suffix if not os.path.exists(link_name): os.symlink(self.canonical_path.Canonicalize(filepath), link_name) self.links.append(link_name) filepath = prefix_filepath distcc-3.4/include_server/mirror_path_test.py000077500000000000000000000117531404653710500216200ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. __author__ = "Nils Klarlund" import os import os.path import basics import cache_basics import mirror_path import shutil import tempfile import unittest NotCoveredError = basics.NotCoveredError class MirrorPathTest(unittest.TestCase): """We construct a mock-up world of a file system in order to unittest the DoPath function of mirror_path.""" def setUp(self): basics.debug_pattern = 3 self.tmp = tempfile.mkdtemp() caches = cache_basics.SetUpCaches(self.tmp) self.canonical_path = caches.canonical_path self.simple_build_stat = caches.simple_build_stat self.mirror_path = mirror_path.MirrorPath(self.simple_build_stat, self.canonical_path, caches.realpath_map, caches.systemdir_prefix_cache) self.directories = ['/', '/a', '/link', '/a/link', '/a/b', '/link/link', '/root'] self.links = ['/a/link', '/link', '/link/link'] self.exists = self.directories + self.links self.realpaths = {'/' :'/', '/a' :'/a', '/a/link' :'/a/b', '/link' :'/a', '/link/link':'/a/b'} def tearDown(self): shutil.rmtree(self.tmp) def test_MirrorPath(self): try: def isdir(path): return path in self.directories def exists(path): return path in self.exists def islink(path): return path in self.links def realpath(path): if path.startswith('/root'): self.fail("Not expected that '%s' started with '/root'." % path) return self.realpaths[path] def makedirs(path): if path == '/root/a': self.directories.extend(['/root/a']) self.exists.extend(['/root/a']) else: self.fail("makedirs %s" % path) def symlink(src, dest): if not (src, dest) in [ ('/a', '/root/link'), ('/a/b', '/root/a/link') ]: self.fail("symlink %s %s" % (src, dest)) self.links.append(dest) self.exists.append(dest) # Overwrite the canonicalization function that MirrorPath uses. self.mirror_path.canonical_path.Canonicalize = realpath # Overwrite various system functions that MirrorPath uses. isdir_ = os.path.isdir os.path.isdir = isdir exists_ = os.path.exists os.path.exists = exists islink_ = os.path.islink os.path.islink = islink makedirs_ = os.makedirs os.makedirs = makedirs symlink_ = os.symlink os.symlink = symlink # Mirror the link /a/link. self.mirror_path.DoPath('/a/link', 117, '/root') self.assertEqual(self.mirror_path.Links(), ['/root/a/link']) self.assertTrue(self.simple_build_stat.Lookup('/root/a')) # Check that symlink function is not called again, by verifying # that mirror_path.Links() doesn't grow. self.mirror_path.DoPath('/a/link', 117, '/root') self.assertEqual(self.mirror_path.Links(), ['/root/a/link']) # Now mirror /link/link. self.mirror_path.DoPath('/link/link', 117, '/root') self.assertEqual(self.mirror_path.Links(), ['/root/a/link', '/root/link']) self.assertEqual( [ d for d in self.directories if d.startswith('/root') ], [ '/root', '/root/a' ]) self.assertEqual( [ d for d in self.links if d.startswith('/root') ], [ '/root/a/link', '/root/link' ]) # Now mirror /a/b. Since b is a file and /a already is mirrored, # there is no effect. self.mirror_path.DoPath('/a/b', 117, '/root') self.assertEqual(self.mirror_path.Links(), ['/root/a/link', '/root/link']) self.assertEqual( [ d for d in self.directories if d.startswith('/root') ], [ '/root', '/root/a' ]) self.assertEqual( [ d for d in self.links if d.startswith('/root') ], [ '/root/a/link', '/root/link' ]) finally: try: # Don't propagate another exception. os.path.isdir = isdir_ os.path.exists = exists_ os.path.islink = islink_ os.makedirs = makedirs_ os.symlink = symlink_ except NameError: pass unittest.main() distcc-3.4/include_server/parse_command.py000077500000000000000000000500751404653710500210430ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Parsing of C and C++ commands and extraction of search paths.""" __author__ = "opensource@google.com (Craig Silverstein, Nils Klarlund)" import re import os import sys import glob import basics import cache_basics Debug = basics.Debug DEBUG_TRACE = basics.DEBUG_TRACE NotCoveredError = basics.NotCoveredError # TODO(klarlund): Make mechanism for handling -U, -undef options, along with # default symbols. class ParseState: """Everything we figure out during parsing. This is accessed a lot and needs to be fast, so you should access and set the data members directly. Mutator functions are provided for the non-list elements, but solely because this way you can set these elements from within a lambda. """ def __init__(self): self.nostdinc = False self.file_names = [] self.quote_dirs = [] self.include_files = [] self.i_dirs = [] self.before_system_dirs = [] self.after_system_dirs = [] self.language = 'none' # equivalent to commandline of '-x none' self.isysroot = "" self.sysroot = "" self.output_file = None self.iprefix = "" self.Dopts = [] def set_nostdinc(self): self.nostdinc = True def set_language(self, x): self.language = x def set_isysroot(self, x): self.isysroot = x def set_sysroot(self, x): self.sysroot = x def set_outputfile(self, x): self.output_file = x def set_iprefix(self, x): self.iprefix = x def include_sysroot(self): return self.isysroot if self.isysroot else self.sysroot def _SplitMacroArg(arg): """Split an arg as found in -Darg Argument: arg: argument Returns: [arg] if there is no '=' in arg, otherwise [symb, val], where symb is what is to the left of '=' and val is what is to the right. """ pos = arg.find("=") if pos > 0: return [arg[:pos], arg[pos + 1:]] else: return [arg] def _RaiseNotImplemented(name, comment=''): raise NotCoveredError('%s is not implemented. %s' % (name, comment)) # These are the cpp options that a) are more than one letter long, # b) always take an argument, and c) may either have that argument # as a separate word in argv, or may have the argument concatenated # after the option-name (eg, either "-include foo" or "-includefoo"). # These are taken from # http://gcc.gnu.org/onlinedocs/cpp/Invocation.html#Invocation # and, more completely, from the gnu gcc info pages. # Each option takes as a value, the function to run on the opt's argument. # Below, ps is a ParseState object. # TODO(csilvers): check for arg[0] == '=' for iquote, isystem CPP_OPTIONS_MAYBE_TWO_WORDS = { '-MF': lambda ps, arg: None, '-MT': lambda ps, arg: None, '-MQ': lambda ps, arg: None, '-arch': lambda ps, arg: None, '-target': lambda ps, arg: None, '-include': lambda ps, arg: ps.include_files.append(arg), '-imacros': lambda ps, arg: ps.include_files.append(arg), '-idirafter': lambda ps, arg: ps.after_system_dirs.append(arg), '-iprefix': lambda ps, arg: ps.set_iprefix(arg), '-iwithprefix': lambda ps, arg: ps.after_system_dirs.append( os.path.join(ps.iprefix, arg)), '-iwithprefixbefore': lambda ps, arg: ps.i_dirs.append( os.path.join(ps.iprefix, arg)), '-isysroot': lambda ps, arg: ps.set_isysroot(arg), '-imultilib': lambda ps, arg: _RaiseNotImplemented('-imultilib'), '-isystem': lambda ps, arg: ps.before_system_dirs.append(arg), '-iquote': lambda ps, arg: ps.quote_dirs.append(arg), } CPP_OPTIONS_MAYBE_TWO_WORDS_FIRST_LETTERS = ('M', 'i', '-', 'a', 't') # A "compile-time" check to make sure the first-letter list is up-to-date for key in CPP_OPTIONS_MAYBE_TWO_WORDS.keys(): assert key[1] in CPP_OPTIONS_MAYBE_TWO_WORDS_FIRST_LETTERS PATH_EXPR='[/a-zA-Z_0-9.]+' # regular expression for a partial file path # These are the cpp options that require regular expressions, m is Match. CPP_OPTIONS_REGULAR_EXPRESSIONS = { '-Wa,(%s\.s)' % PATH_EXPR: lambda ps, m: ps.include_files.append(m.group(1)), '-Wa,\[(%s\.s)\]' % PATH_EXPR: lambda ps, m: ps.include_files.append(m.group(1)), } CPP_OPTIONS_REGULAR_EXPRESSIONS_STARTS_WITH = '-Wa,' for key in CPP_OPTIONS_REGULAR_EXPRESSIONS.keys(): assert key.startswith(CPP_OPTIONS_REGULAR_EXPRESSIONS_STARTS_WITH) CPP_OPTIONS_REGULAR_EXPRESSIONS_COMPILED = {} for key in CPP_OPTIONS_REGULAR_EXPRESSIONS.keys(): CPP_OPTIONS_REGULAR_EXPRESSIONS_COMPILED[key] = re.compile(key) # These are the cpp options that a) are more than one letter long, # b) always take an argument, and c) must have that argument as a # separate word in argv. CPP_OPTIONS_ALWAYS_TWO_WORDS = { '-Xpreprocessor': lambda ps, arg: _RaiseNotImplemented('-Xpreprocessor'), # In order to parse correctly, this data structure needs to include # *all* two-word arguments that gcc accepts (we don't want to see # "gcc -aux-info foo" and think that foo is an output filename...) # This list is taken from the complete list from the gcc info page: # "Option Summary". These aren't preprocessor-related, so are noops. '-aux-info': lambda ps, arg: None, '--param': lambda ps, arg: None, '-Xassembler': lambda ps, arg: None, '-Xlinker': lambda ps, arg: None, '-Xclang': lambda ps, arg: None, } # For efficiency, it's helpful to be able to combine the two above CPP_OPTIONS_TWO_WORDS = {} CPP_OPTIONS_TWO_WORDS.update(CPP_OPTIONS_MAYBE_TWO_WORDS) CPP_OPTIONS_TWO_WORDS.update(CPP_OPTIONS_ALWAYS_TWO_WORDS) # These are the cpp options that a) are more than one letter long, # b) always take an argument, and c) have that argument separated from # the option by '='. CPP_OPTIONS_APPEARING_AS_ASSIGNMENTS = { '--sysroot': lambda ps, arg: ps.set_sysroot(arg) } # These are the cpp options that do not take an argument. # (Note, most cpp options do not take an argument, but do not pertain to # preprocessing, so we can ignore them. Those are dealt in the default # case in our processing loop. This is only for no-argument options # that we actually care about for preprocessing.) CPP_OPTIONS_ONE_WORD = { # '-undef': lambda ps, arg: _RaiseNotImplemented('-undef') '-undef': lambda ps, arg: None, '-nostdinc': lambda ps: ps.set_nostdinc(), # TODO(csilvers): deal with -nostdinc++ as well? } # These are the cpp options that are one letter long, and take an # argument. In all such cases, the argument may either be the next # word, or may be appended right after the letter. CPP_OPTIONS_ONE_LETTER = { 'D': lambda ps, arg: ps.Dopts.append(arg.split('=')), 'I': lambda ps, arg: ps.i_dirs.append(arg), # 'U': lambda ps, arg: _RaiseNotImplemented('-U') # affects computed includes 'U': lambda ps, arg: None, 'o': lambda ps, arg: ps.set_outputfile(arg), 'x': lambda ps, arg: ps.set_language(arg), # In order to parse correctly, this data structure needs to include # *all* two-word arguments that gcc accepts (we don't want to see # "gcc -L foo" and think that foo is an output filename...) Since # most one-letter args can go as either '-Lfoo' or '-L foo', we need # to include (almost) all one-letter args in our list, even when we # don't care about them. This list is taken from the complete list # from the gcc info page: "Option Summary". Since these aren't # preprocessor-related, they are all noops. 'A': lambda ps, arg: None, 'l': lambda ps, arg: None, 'F': lambda ps, arg: ps.i_dirs.extend(glob.glob(os.path.join(arg,'*', 'Headers'))), 'u': lambda ps, arg: None, 'L': lambda ps, arg: None, 'B': lambda ps, arg: None, 'V': lambda ps, arg: None, 'b': lambda ps, arg: None, } ### DREADFUL PARSER + OPTIMIZED PARSER # This parser was written after a *much* simpler parser using regular # expression turned out to be too slow, two orders of magnitude slower # than str.split. The parser below is faster than the one based on # regular expression and more complete, so that's the one we keep. NONSPACE_RE = re.compile(r'\S') # don't use \S|$, which introduces backtracking SPACE_RE = re.compile(r'\s') NONESC_QUOTE_RE = re.compile(r'[^\\]"|^"') # inefficient QUOTE_RE = re.compile(r'(? unesc_q end = m_unesc_q.end() if end == len(line): args.append(ESC_QUOTE_RE.sub( '"', QUOTE_RE.sub( '', line[start:end]))) return args # We found the counterpart before the end of the line. The argument may # still not be finished. But before continuing, look for the next quote. m_unesc_q = NONESC_QUOTE_RE.search(line, end) if m_unesc_q: unesc_q = m_unesc_q.end() - 1 else: unesc_q = sys.maxsize def ParseCommandLine(line): """Parse line as it were issued in a shell (optimized). """ # It turns out that str.split() for large string (size 500) is almost two # orders of magnitude faster than ParseCommandLineSlowly. Usually, when # there is a '"' this quote is near the beginning of the line (as in dX="some # thing"). We use this observation to apply split() to the suffix following # the last quote. In that way, only the prefix up to somewhere around the last # quote needs to be parsed by more sophisticated means. quote_pos = line.rfind('"') if quote_pos == -1: return line.split() else: # Walk forward to a space; the quote could be an escaped one in # the middle of non-space characters. good_pos = line.find(' ', quote_pos) if good_pos != -1: return (ParseCommandLineSlowly(line[0:good_pos]) + line[good_pos:].split()) else: # give up return ParseCommandLineSlowly(line) # Make a regular expression that matches suffixes of strings ending in # a period followed by a string in the domain of TRANSLATION_UNIT_MAP. TRANSLATION_UNIT_FILEPATH_RE = ( re.compile(r".*[.](?P%s)$" % '|'.join([re.escape(ext) for ext in basics.TRANSLATION_UNIT_MAP.keys()]))) def ParseCommandArgs(args, current_dir, includepath_map, dir_map, compiler_defaults, timer=None): """Parse arguments like -I to make include directory lists. Arguments: args: list of arguments (strings) current_dir: string includepath_map: a MapToIndex object dir_map: a DirectoryMapToIndex object compiler_defaults: a CompilerDefaults object timer: a basics.IncludeAnalyzerTimer object Returns: (quote_dirs, angle_dirs, files, source_file, source_file_prefix, dopts) where: quote_dirs: a list of dir_map-indexed directories angle_dirs: a list of dir_map-indexed directories files: a list of includepath_map-indexed files source_file_prefix: the source file name with extension stripped dopts: a list of items as returned by _SplitMacroArg Modifies: compiler_defaults """ if __debug__: Debug(DEBUG_TRACE, "ParseCommand %s" % args) assert isinstance(dir_map, cache_basics.DirectoryMapToIndex) assert isinstance(includepath_map, cache_basics.MapToIndex) parse_state = ParseState() if len(args) < 2: raise NotCoveredError("Command line: too few arguments.") compiler = args[0] i = 1 while i < len(args): # First, deal with everything that's not a flag-option if args[i][0] != '-' or args[i] == '-': # - is the stdin file if args[i].startswith('"-'): pass # TODO(csilvers): parse arg inside quotes? else: parse_state.file_names.append(args[i]) # if not a flag, it's a file i += 1 continue # Deal with the one-letter options -- the kind most commonly seen. # We need to figure out whether the option-argument is glommed on to # the end of the option ("-Dfoo"), or is a separate word ("-D foo"). action = CPP_OPTIONS_ONE_LETTER.get(args[i][1]) # letter after the - if action: arg = args[i][2:] if arg: # the glommed-onto-end case action(parse_state, arg) i += 1 else: # the separate-word case try: action(parse_state, args[i+1]) i += 2 except IndexError: raise NotCoveredError("No argument found for option '%s'" % args[i]) continue # Deal with the have-arg options with the arg as the 2nd word ("-MF foo"). action = CPP_OPTIONS_TWO_WORDS.get(args[i]) if action: try: action(parse_state, args[i+1]) i += 2 except IndexError: raise NotCoveredError("No argument found for option '%s'" % args[i]) continue # Deal with the have-arg options that appear as if assignments # ("--sysroot=/mumble"). if '=' in args[i]: arg, value = args[i].split('=', 1) action = CPP_OPTIONS_APPEARING_AS_ASSIGNMENTS.get(arg) if action: action(parse_state, value) i += 1 continue # Deal with the options that take no arguments ("-nostdinc"). action = CPP_OPTIONS_ONE_WORD.get(args[i]) if action: action(parse_state) i += 1 continue # Deal with the have-arg options with the arg concatenated to the word. # ("-MFfoo"). We do this last because it's slowest. if args[i][1] in CPP_OPTIONS_MAYBE_TWO_WORDS_FIRST_LETTERS: # filter found_action = False for (option, action) in CPP_OPTIONS_MAYBE_TWO_WORDS.items(): if action and args[i].startswith(option): action(parse_state, args[i][len(option):]) i += 1 found_action = True break if found_action: # what we really need here is a goto! continue # Deal with the complex options requiring regular expressions last. if args[i].startswith(CPP_OPTIONS_REGULAR_EXPRESSIONS_STARTS_WITH): found_action = False for (option, action) in CPP_OPTIONS_REGULAR_EXPRESSIONS.items(): r = CPP_OPTIONS_REGULAR_EXPRESSIONS_COMPILED[option] m = r.match(args[i]) if action and m is not None: action(parse_state, m) i += 1 found_action = True break if found_action: continue # Whatever is left must be a one-word option (that is, an option # without an arg) that it's safe to ignore. i += 1 continue # Done parsing arguments! # Sanity-checking on arguments # -I- is a special form of the -I command. if "-" in parse_state.i_dirs: _RaiseNotImplemented('-I-', '(Use -iquote instead.)') if len(parse_state.file_names) != 1: raise NotCoveredError( "Could not locate name of translation unit: %s." % parse_state.file_names, send_email=False) source_file = parse_state.file_names[0] if parse_state.output_file: # Use output_file to create prefix source_file_prefix = re.sub("[.]o$", "", parse_state.output_file) else: # Remove suffix from source file source_file_prefix = re.sub("[.](%s)$" % "|".join(basics.TRANSLATION_UNIT_MAP.keys()), "", source_file) source_file_prefix = os.path.join(current_dir, source_file_prefix) if parse_state.language == 'none': # no explicit -x flag, or -x none language_match = TRANSLATION_UNIT_FILEPATH_RE.match(source_file) if not language_match: raise NotCoveredError( "For source file '%s': unrecognized filename extension" % source_file) suffix = language_match.group('suffix') parse_state.language = basics.TRANSLATION_UNIT_MAP[suffix] assert parse_state.language in basics.LANGUAGES sysroot = parse_state.include_sysroot() compiler_defaults.SetSystemDirsDefaults(compiler, sysroot, parse_state.language, timer) def IndexDirs(dir_list): """Normalize directory names and index. Remove leading "./" and trailing "/"'s from directory paths in dir_list before indexing them according to dir_map. """ S = basics.SafeNormPath I = dir_map.Index return [I(S(d)) for d in dir_list] # Now string the directory lists together according to CPP semantics. angle_dirs = IndexDirs(parse_state.i_dirs) angle_dirs.extend(IndexDirs(parse_state.before_system_dirs)) if not parse_state.nostdinc: sysroot = parse_state.include_sysroot() angle_dirs.extend( IndexDirs(compiler_defaults.system_dirs_default [compiler][sysroot][parse_state.language])) angle_dirs.extend(IndexDirs(parse_state.after_system_dirs)) quote_dirs = IndexDirs(parse_state.quote_dirs) quote_dirs.extend(angle_dirs) angle_dirs = tuple(angle_dirs) quote_dirs = tuple(quote_dirs) # Include files are meant to be sent to the server. They do not pose the # danger of absolute includes, which includepath_map is designed to avoid. include_files = tuple( [includepath_map.Index(basics.SafeNormPath(f), ignore_absolute_path_warning=True) for f in parse_state.include_files]) if __debug__: Debug(DEBUG_TRACE, ("ParseCommand result: %s %s %s %s %s %s" % (quote_dirs, angle_dirs, include_files, source_file, source_file_prefix, parse_state.Dopts))) return (quote_dirs, angle_dirs, include_files, source_file, source_file_prefix, parse_state.Dopts) distcc-3.4/include_server/parse_command_test.py000077500000000000000000000163121404653710500220760ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Parsing of C and C++ commands and extraction of search paths.""" __author__ = "Nils Klarlund" import os import time import basics import cache_basics import parse_command import shutil import tempfile import unittest NotCoveredError = basics.NotCoveredError class ParseCommandUnitTest(unittest.TestCase): def setUp(self): basics.opt_debug_pattern = 1 self.tmp = tempfile.mkdtemp() caches = cache_basics.SetUpCaches(self.tmp) self.includepath_map = caches.includepath_map self.canonical_path = caches.canonical_path self.directory_map = caches.directory_map self.realpath_map = caches.realpath_map self.systemdir_prefix_cache = caches.systemdir_prefix_cache mock_compiler = '/usr/crosstool/v8/gcc-4.1.0-glibc-2.2.2/blah/gcc' self.mock_compiler = mock_compiler mock_sysroot = '/usr/local/fake/sysroot' self.mock_sysroot = mock_sysroot def Mock_SetSystemDirsDefaults(compiler, sysroot, language, timer=None): if compiler != mock_compiler: raise Exception("compiler: %s, mock_compiler: %s" % ( compiler, mock_compiler)) if sysroot != mock_sysroot: raise Exception("sysroot: %s, mock_sysroot: %s" % ( sysroot, mock_sysroot)) self.compiler_defaults = lambda x: x self.compiler_defaults.SetSystemDirsDefaults = Mock_SetSystemDirsDefaults self.compiler_defaults.system_dirs_default_all = [] self.compiler_defaults.system_dirs_default = {} system_dirs_default = self.compiler_defaults.system_dirs_default system_dirs_default[mock_compiler] = {} system_dirs_default[mock_compiler][mock_sysroot] = {} system_dirs_default[mock_compiler][mock_sysroot]['c'] = [] system_dirs_default[mock_compiler][mock_sysroot]['c++'] = [] def tearDown(self): shutil.rmtree(self.tmp) def test__SplitMacroArg(self): self.assertEqual(parse_command._SplitMacroArg("="), ["="]) self.assertEqual(parse_command._SplitMacroArg("A="), ["A", ""]) self.assertEqual(parse_command._SplitMacroArg("A=B=C"), ["A", "B=C"]) def _RetrieveDirectoriesExceptSys(self, directory_idxs): return cache_basics.RetrieveDirectoriesExceptSys( self.directory_map, self.realpath_map, self.systemdir_prefix_cache, directory_idxs) def test_ParseCommandLine(self): self.assertEqual(parse_command.ParseCommandLine( """ "a"b"\\"c" "a"\n"b" a b\\"c"""), ['ab"c', 'a', 'b', 'a', 'b"c']) self.assertEqual(parse_command.ParseCommandLine( """this is a test"""), ['this', 'is', 'a', 'test']) self.assertEqual(parse_command.ParseCommandLine( """ this is a test"""), ['this', 'is', 'a', 'test']) self.assertEqual(parse_command.ParseCommandLine( """this is a test """), ['this', 'is', 'a', 'test']) self.assertEqual(parse_command.ParseCommandLine( 'this " is" a"test" '), ['this', ' is', 'atest']) self.assertEqual(parse_command.ParseCommandLine( r'this " \"is" a"test" '), ['this', ' "is', 'atest']) self.assertEqual(parse_command.ParseCommandLine( 'this " is" a"test"'), ['this', ' is', 'atest']) self.assertRaises(NotCoveredError, parse_command.ParseCommandLine, """this is" a"test" """) self.assertRaises(NotCoveredError, parse_command.ParseCommandLine, 'this is" a"test"') def test_ParseCommandArgs(self): quote_dirs, angle_dirs, include_files, filepath, _incl_clos_f, _d_opts = ( parse_command.ParseCommandArgs( parse_command.ParseCommandLine( self.mock_compiler + " --sysroot=" + self.mock_sysroot + " -isystem system -Imice -iquote/and -I/men a.c " + " -include included_A.h " + " -includeincluded_B.h " + " -Wa,macros_A.s " + " -Wa,[macros_B.s] " + " -Wa,arch/x86/kernel/macros.s -Wa,- " + " -Wa,other_directive " + "-Xlinker W,l -L /ignored_by_us -o a.o"), os.getcwd(), self.includepath_map, self.directory_map, self.compiler_defaults)) self.assertEqual( (self._RetrieveDirectoriesExceptSys(quote_dirs), self._RetrieveDirectoriesExceptSys(angle_dirs), [self.includepath_map.String(i) for i in include_files], filepath), (('/and', 'mice', '/men', 'system'), ('mice', '/men', 'system'), ["included_A.h", "included_B.h", "macros_A.s", "macros_B.s", "arch/x86/kernel/macros.s"], 'a.c')) self.assertRaises(NotCoveredError, parse_command.ParseCommandArgs, parse_command.ParseCommandLine( self.mock_compiler + " --sysroot=" + self.mock_sysroot + " -I- -iquote a.c"), os.getcwd(), self.includepath_map, self.directory_map, self.compiler_defaults) quote_dirs, angle_dirs, include_files, filepath, _incl_cls_file, _d_opts = ( parse_command.ParseCommandArgs(parse_command.ParseCommandLine( "/usr/crosstool/v8/gcc-4.1.0-glibc-2.2.2/blah/gcc" + " --sysroot=/usr/local/fake/sysroot" + " -fno-exceptions -funsigned-char -D__STDC_FORMAT_MACROS -g0" + " -D_REENTRANT -DCOMPILER_GCC3 -DCOMPILER_GCC4 -DARCH_PIII -DOS_LINUX" + " -fmessage-length=0 -fno-strict-aliasing -fno-tree-vrp -D_REENTRANT" + " -DHAS_vsnprintf" + " -Iobj/gcc-4.1.0-glibc-2.2.2-piii-linux-g0-dbg/genfiles/third_party/libxml/third_party/libxml" + " -Ithird_party/zlib -iquote . -fno-strict-aliasing -c -o" + " obj/gcc-4.1.0-glibc-2.2.2-piii-linux-g0-dbg/bin/third_party/libxml/threads.c.o" + " third_party/libxml/threads.c"), os.getcwd(), self.includepath_map, self.directory_map, self.compiler_defaults)) self.assertEqual( (self._RetrieveDirectoriesExceptSys(quote_dirs), self._RetrieveDirectoriesExceptSys(angle_dirs), filepath), (('', 'obj/gcc-4.1.0-glibc-2.2.2-piii-linux-g0-dbg/genfiles/third_party/libxml/third_party/libxml', 'third_party/zlib'), ('obj/gcc-4.1.0-glibc-2.2.2-piii-linux-g0-dbg/genfiles/third_party/libxml/third_party/libxml', 'third_party/zlib'), 'third_party/libxml/threads.c')) unittest.main() distcc-3.4/include_server/parse_file.py000077500000000000000000000303441404653710500203410ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """A very fast directives-only parser for C and C++ source code. We parse only the following directives: #include (the standard C/C++ inclusion mechanism) #include_next (a GNU C/C++ extension) #import (an Objective-C feature, similar to #include) #define (because #defines can affect the results of '#include MACRO') """ __author__ = 'Nils Klarlund' import re import time import basics import cache_basics import statistics Debug = basics.Debug DEBUG_TRACE = basics.DEBUG_TRACE DEBUG_TRACE2 = basics.DEBUG_TRACE2 NotCoveredError = basics.NotCoveredError # For coarse and fast scanning RE_INCLUDE_DEFINE = re.compile("include|define|import") # For fine-grained, but slow backtracking, parsing POUND_SIGN_RE = re.compile(r""" ^ # start of line [ \t]* # space(s) ([*][/])? # a possible ..*/ ending block comment [ \t]* # space(s) ([/][*] [^\n]* [*][/])* # initial block comment(s) /*...*/ [ \t]* # space(s) (?P # group('directive') -- what we're after [#] # the pound sign [ \t]* # space(s) (define|include_next|include|import)\b # the directive ((?!\\\n).)* # the rest on this line: zero or more # characters, each not a backslash that # is followed by \n (\\\n((?!\\\n).)*)* # (backslash + \n + rest of line)* ) """, re.VERBOSE + re.MULTILINE) NOT_COMMA_OR_PARENS = "([^(),])" # For parsing macro expressions of the form: # symbol # symbol (something, ..., something), where something is not ',', '(', or ')' MACRO_EXPR = r""" (?P\w+) # the symbol, named 'symbol' ( \s* [(] \s* # beginning parenthesis (?P # a parenthesized expression (with no # containing expressions -- a limitation) # named 'args' %(NOT_COMMA_OR_PARENS)s* # the first argument (if it exists) ([,]%(NOT_COMMA_OR_PARENS)s*)* # subsequent arguments ) [)] # ending parenthesis )?""" % {'NOT_COMMA_OR_PARENS': NOT_COMMA_OR_PARENS} MACRO_EXPR_RE = re.compile(MACRO_EXPR, re.VERBOSE) # Nice little parser of certain directive lines (after backslash-ended # line continuations and comments are removed) DIRECTIVE_RE = re.compile(r""" ^[ \t]* [#] [ \t]* ( ((?P include_next | include | import) \s* ( "(?P (\w|[_/.,+-])*)" | # "bar/foo.h" <(?P (\w|[_/.,+-])*)> | # (?P .*?)) # expr, match . minimally ) | (?P define \s+ (?P %s) # insert MACRO_EXPR here \s* (?P .*?)) # match . minimally before # trailing white space ) \s* # trailing whitespace ((/[*]|//).*)? # optional trailing comment start $ """ % MACRO_EXPR, re.VERBOSE) # INCLUDE_STRING_RE = re.compile(r""" ^ \s* ( "\s*(?P (\w|[\\_/.,+-])*)\s*" | <\s*(?P (\w|[\\_/.,+-])*)\s*> ) \s* $ """, re.VERBOSE) # For ridding lines of backslash BACKSLASH_RE = re.compile(r"\\\n", re.MULTILINE) # For matching non-comment prefix of line. COMMENT_RE = re.compile(r"((?!/[*]|//).)*") # FOR SEARCHING AFTER /* .. */. PAIRED_COMMENT_RE = re.compile(r"(/[*].*?[*]/)") def InsertMacroDefInTable(lhs, rhs, symbol_table, callback_function): """Insert the definition of a pair (lhs, rhs) into symbol table. Arguments: lhs: a string, of the form "symbol" or "symbol(param1, ..., paramN)" rhs: a string symbol_table: where the definition will be inserted callback_function: a function called with value "symbol" """ m_expr = MACRO_EXPR_RE.match(lhs) if m_expr.end(0) != len(lhs): raise NotCoveredError( "Unexpected macro definition with LHS: '%s'." % lhs) # Calculate the definition df, either # - a pair ([arg_1, .., arg_n], rhs) where arg_i is the # i'th formal parameter (function-like macro definition), or # - just a symbol (object-like macro definition) if m_expr.group('args') != None: # perhaps '' # A function-like macro definition. # Construct pair (list of formal parameters, rhs). args = m_expr.group('args').split(',') df = args, rhs # lhs is adjusted to be just the 'function' name lhs = m_expr.group('symbol') else: # m_expr.group('args') # An object-like macro definition assert m_expr.group('symbol') == lhs df = rhs if lhs not in symbol_table: symbol_table[lhs] = [df] else: symbol_table[lhs].append(df) callback_function(lhs) class ParseFile(object): """Parser class for syntax understood by CPP, the C and C++ preprocessor. An instance of this class defines the Parse method.""" def __init__(self, includepath_map): """Constructor. Make a parser. Arguments: includepath_map: string-to-index map for includepaths """ assert isinstance(includepath_map, cache_basics.MapToIndex) self.includepath_map = includepath_map self.define_callback = lambda x: None def SetDefineCallback(self, callback_function): """Set a callback function, which is invoked for '#define's. The function is called as callback_function(symbol), whenever a '#define' of symbol is parsed. The callback allows an include processor to adjust its notion of which expressions are still current. If we (the include processor) already met #define A B and later meet #define B whether this is the first definition of B or not, then the possible meanings of A have changed. We set up a callback to identify such situations.""" self.define_callback = callback_function def _ParseFine(self, poundsign_match, includepath_map_index, file_contents, symbol_table, quote_includes, angle_includes, expr_includes, next_includes): """Helper function for ParseFile.""" Debug(DEBUG_TRACE2, "_ParseFine %s", file_contents[poundsign_match.start('directive'): poundsign_match.end('directive')]) m = DIRECTIVE_RE.match( # parse the directive PAIRED_COMMENT_RE.sub( # remove possible paired comments "", BACKSLASH_RE.sub( # get rid of lines ending in backslash "", file_contents[poundsign_match.start('directive'): poundsign_match.end('directive')]))) if m: try: groupdict = m.groupdict() if groupdict['include'] == 'include' or \ groupdict['include'] == 'import': if groupdict['quote']: quote_includes.append(includepath_map_index(m.group('quote'))) elif groupdict['angle']: angle_includes.append(includepath_map_index(m.group('angle'))) elif groupdict['expr']: expr_includes.append(m.group('expr').rstrip()) else: assert False elif groupdict['include'] == 'include_next': # We do not, in fact, distinguish between the two kinds of # include_next's, because we conservatively assume that they are of # the quote variety. if groupdict['quote']: next_includes.append(includepath_map_index(m.group('quote'))) elif groupdict['angle']: next_includes.append(includepath_map_index(m.group('angle'))) # The following restriction would not be too hard to remove. elif groupdict['expr']: NotCoveredError( "For include_next: cannot deal with computed include here.") else: assert False raise NotCoveredError("include_next not parsed") elif groupdict['define']: if not groupdict['lhs']: raise NotCoveredError("Unexpected macro definition with no LHS.") else: lhs = m.group('lhs') rhs = groupdict['rhs'] and groupdict['rhs'] or None InsertMacroDefInTable(lhs, rhs, symbol_table, self.define_callback) except NotCoveredError as inst: # Decorate this exception with the filename, by recreating it # appropriately. if not inst.source_file: raise NotCoveredError(inst.args[0], self.filepath, send_email = inst.send_email) else: raise def Parse(self, filepath, symbol_table): """Parse filepath for preprocessor directives and update symbol table. Arguments: filepath: a string symbol_table: a dictionary, see module macro_expr Returns: (quote_includes, angle_includes, expr_includes, next_includes), where all are lists of filepath indices, except for expr_includes, which is a list of expressions. """ Debug(DEBUG_TRACE, "ParseFile %s", filepath) assert isinstance(filepath, str) self.filepath = filepath parse_file_start_time = time.perf_counter() statistics.parse_file_counter += 1 includepath_map_index = self.includepath_map.Index try: fd = open(filepath, "r", encoding='latin-1') except IOError as msg: # This normally does not happen because the file should be known to # exists. Still there might be, say, a permissions issue that prevents it # from being read. raise NotCoveredError("Parse file: '%s': %s" % (filepath, msg), send_email=False) file_contents = fd.read() fd.close() quote_includes, angle_includes, expr_includes, next_includes = ( [], [], [], []) i = 0 line_start_last = None while True: # Scan coarsely to find something of interest mfast = RE_INCLUDE_DEFINE.search(file_contents, i + 1) if not mfast: break i = mfast.end() # Identify the line of interest by scanning backwards to \n line_start = file_contents.rfind("\n", 0, i) + 1 # to beginning of line # Now, line_start is -1 if \n was not found. ### TODO(klarlund) continue going back if line continuation preceeding # Is this really a new line? if line_start == line_start_last: continue line_start_last = line_start # Here we should really skip back over lines to see whether a totally # pathological situation involving '\'-terminated lines like: # # #include # # Start of pathological situation involving line continuations: # # \ # \ # \ # \ # include "nidgaard.h" # # occurs, where the first # on each line is just Python syntax and should # not be considered as part of the C/C++ example. This code defines a # valid directive to include "nidgaard.h". We will not handle such # situations correctly -- the include will be missed. # Parse the line of interest according to fine-grained parser poundsign_match = POUND_SIGN_RE.match(file_contents, line_start) if not poundsign_match: continue self._ParseFine(poundsign_match, includepath_map_index, file_contents, symbol_table, quote_includes, angle_includes, expr_includes, next_includes) statistics.parse_file_total_time += time.perf_counter() - parse_file_start_time return (quote_includes, angle_includes, expr_includes, next_includes) distcc-3.4/include_server/parse_file_test.py000077500000000000000000000122371404653710500214010ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Tests for parse_file.""" __author__ = "opensource@google.com" import unittest import basics import cache_basics import parse_file import include_server import include_analyzer class parse_file_Test(unittest.TestCase): def setUp(self): include_server.print_statistics = False client_root_keeper = basics.ClientRootKeeper() include_server.write_include_closure_file = True self.include_analyzer = include_analyzer.IncludeAnalyzer(client_root_keeper) def tearDown(self): pass def test_RegularExpressions(self): self.assertEqual(parse_file.POUND_SIGN_RE.match( """ #\tinclude blah. blah.""" ).group(0), " #\tinclude blah. blah.") self.assertEqual(parse_file.POUND_SIGN_RE.match( """ # gggg include blah. blah.""" ), None) self.assertEqual(parse_file.POUND_SIGN_RE.match( """ */ /**/ /* a */ # include blah. blah.""" ).group(0), ' */ /**/ /* a */ # \tinclude blah. blah.') self.assertEqual( parse_file.MACRO_EXPR_RE.search("m(a, b) + c + n(d)").groupdict(), {'args': 'a, b', 'symbol': 'm'}) # The expression we recognize do not include nested parenthesis self.assertEqual( parse_file.MACRO_EXPR_RE.search("m(a, (b)) + c + n(d)").groupdict(), {'args': None, 'symbol': 'm'}) self.assertEqual(parse_file.MACRO_EXPR_RE.match("random()").group('symbol'), "random") self.assertTrue(parse_file.DIRECTIVE_RE.match( """ # include """).group('angle') == 'a.c') self.assertTrue(parse_file.DIRECTIVE_RE.match( """ # include mac(a.c, mic)""").group('expr') == 'mac(a.c, mic)') self.assertTrue(parse_file.DIRECTIVE_RE.match( """ # include "a.c" """).group('quote') == 'a.c') self.assertTrue(parse_file.DIRECTIVE_RE.match( """ #include "a.c" """).group('quote') == 'a.c') self.assertTrue(parse_file.DIRECTIVE_RE.match( """ #include"a.c" """).group('quote') == 'a.c') self.assertEqual(parse_file.DIRECTIVE_RE.match( """ #define m(a) """).group('rhs'), '') self.assertEqual( parse_file.DIRECTIVE_RE.match("#define xmlRealloc(ptr, size)" + " xmlReallocLoc((ptr), (size)," + " __FILE__, __LINE__)").group('lhs'), "xmlRealloc(ptr, size)") self.assertEqual( parse_file.DIRECTIVE_RE.match("#define random() rand()").group('lhs'), "random()") self.assertEqual( parse_file.DIRECTIVE_RE.match("#define ABBA ").group('lhs'), "ABBA") self.assertEqual( parse_file.DIRECTIVE_RE.match("#define ABBA").group('lhs'), "ABBA") self.assertEqual(parse_file.BACKSLASH_RE.sub("", """a\ b\ c\ d"""), "abcd") self.assertEqual(parse_file.BACKSLASH_RE.sub("", """a b """), """a b """) self.assertEqual(parse_file.PAIRED_COMMENT_RE.sub("", "ab/*./*..*/cd"), "abcd") self.assertEqual(parse_file.PAIRED_COMMENT_RE.sub("", "ab/*/cd"), "ab/*/cd") self.assertEqual(parse_file.COMMENT_RE.match("ab/*cd").group(), "ab") self.assertEqual(parse_file.COMMENT_RE.match("ab//cd").group(), "ab") self.assertEqual(parse_file.COMMENT_RE.match("ab/cd").group(), "ab/cd") self.assertEqual(parse_file. INCLUDE_STRING_RE.match(""" < ab.c>""").group('angle'), "ab.c") def test_ParseFile(self): includepath_map = cache_basics.MapToIndex() canonical_path = cache_basics.CanonicalPath() parse_file_obj = parse_file.ParseFile(includepath_map) symbol_table = {} self.assertEqual(parse_file_obj.Parse( "test_data/more_macros.c", symbol_table), ([], [], ['TEMPLATE_VARNAME(foo)'], [])) symbol_table_keys = list(symbol_table.keys()) symbol_table_keys.sort() self.assertEqual(symbol_table_keys, ['AS_STRING', 'AS_STRING_INTERNAL', 'ILLFORMED', 'TEMPLATE_VARNAME']) [([arg], val)] = symbol_table['TEMPLATE_VARNAME'] self.assertEqual(arg, '_filename_') self.assertEqual(val, 'AS_STRING(maps/_filename_.tpl.varnames.h)') self.assertEqual(parse_file_obj.Parse( "test_data/computed_includes.c", symbol_table), ([], [], [ 'A' , 'm(abc)' ], [])) self.assertEqual(symbol_table['A'], ['"p1.h"']) [val] = symbol_table['ILLFORMED'] self.assertEqual(val, "(_filename_,(x)) " + "AS_STRING(maps/_filename_.tpl.varnames.h, " + "NOTHANDLED(_filename_))") unittest.main() distcc-3.4/include_server/run.py000077500000000000000000000067741404653710500170460ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Run with PYTHONPATH including appropriate place for extension module.""" __author__ = "opensource@google.com" import os import sys import glob USAGE="""Usage: run.py [--install] CMD [ARG...] Option: --run_in_install: find extension module under lib of installation directory Locate a Python extension module in some directory D under the c_extensions/build subdirectory of the directory that contains the present command. With --run_in_install, assume that this script resides in an installed version; this means that the directory structure is different and D is located as ../../lib. Then run CMD [ARG...] with environment variable PYTHONPATH augmented with D. Normally, print out a message where the extension module is found. But, with --run_in_install this message is suppressed. Examples: From anywhere: # Start include server. /home/distcc/include_server/run.py include_server.py In the include_server directory: # Run include_server tests. ./run.py include_server_test.py # Pycheck include_server. ./run.py `which pychecker` include_server.py In installed distcc-pump: # See 'pump' script. $include_server_location/run.py --run_in_install include_server.py .. """ def usage(): print(USAGE) sys.exit(1) DEFAULT_PATH = "c_extensions/build/lib.*/*" cmd = sys.argv[0] if len(sys.argv) < 2: usage() dirname = os.path.dirname(cmd) directory = os.path.abspath(os.path.join(os.getcwd(), dirname)) # Define lib_directory, the directory of the .so, one way or another. if sys.argv[1]== '--run_in_install': del sys.argv[1] if len(sys.argv) < 2: usage() # We are in share/python. lib_directory = os.path.join(dirname, "../../lib") else: # We're in the source directory, not in installation. place_to_look = directory + '/' + DEFAULT_PATH potential_libs = glob.glob(place_to_look) # Now potential_libs is supposed to contain the filepaths of dynamically # loaded libraries. We expect exactly one such filepath. if len(potential_libs) == 0: sys.exit("No extension modules of the form '%s' found." % place_to_look) if len(potential_libs) > 1: sys.exit("More than one extension module found. " + " Cannot determine which one to use.") lib_directory = os.path.dirname(potential_libs[0]) print("__________Using Python extension in %s" % lib_directory) # Now, the all important change to PYTHONPATH. Note that we obliterate any # environmental setting setting as well. This improves performance in # installations with unneeded Python resources on network disks. os.environ['PYTHONPATH'] = lib_directory try: os.execv(os.path.join(directory, sys.argv[1]), sys.argv[1:]) except OSError: print("Could not run: '%s' with arguments: %s" % (os.path.join(directory, sys.argv[1]), sys.argv[1:]), file=sys.stderr) distcc-3.4/include_server/setup.py000077500000000000000000000141371404653710500173720ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Build the include server module. The version number should be passed to this script through the environment variable DISTCC_VERSION. Also, the CPPFLAGS of the Makefile must be passed through the environment. This is how we figure out the locations of include directories. SRCDIR must be passed as well; it explains where to find the C sources and the include_server directory of Python source files and C extensions. Because SRCDIR is appended to build location and we don't want to end up outside this location through a relative SRCDIR path with '..'s, SRCDIR is absolutized. """ __author__ = 'Manos Renieris and Nils Klarlund' import distutils.core import distutils.extension import doctest import os import shlex import sys OPTIONS_NOT_ALLOWED = ['-Iquote', '-Isystem', '-I-'] # We include a partial command line parser instead of using the more the more # complicated one in parse_command.py. This cuts down on dependencies in the # build system itself. def GetIncludes(flags): """Parse a flags string for includes of the form -I

. Args: flags: a string in shell syntax denoting compiler options Returns: a list of s of the includes Raises: ValueError: In the doctests below, note that a single quoted backslash takes four backslashes to represent if it is inside a single quoted string inside this present triple-quoted string. >>> GetIncludes('-I x -X -I"y" -Y') ['x', 'y'] >>> GetIncludes('-Ix -Dfoo -Iy') ['x', 'y'] >>> GetIncludes(r'-Ix -I"y\\z" -I"y\\\\z" -Y') ['x', 'y\\\\z', 'y\\\\z'] >>> GetIncludes('-DX -Iquote Y') Traceback (most recent call last): ... ValueError: These options are not allowed: -Iquote, -Isystem, -I-. >>> GetIncludes('-DX -I x -I') Traceback (most recent call last): ... ValueError: Argument expected after '-I'. """ flags = shlex.split(flags) if set(OPTIONS_NOT_ALLOWED) & set(flags): raise ValueError('These options are not allowed: %s.' % ', '.join(OPTIONS_NOT_ALLOWED)) # Fish out the directories of '-I' options. i = 0 inc_dirs = [] while i < len(flags): if flags[i].startswith('-I'): inc_dir = flags[i][len('-I'):] if inc_dir: # "-Idir" inc_dirs.append(inc_dir) i += 1 continue else: # "-I dir" if i == len(flags) - 1: raise ValueError("Argument expected after '-I'.") inc_dirs.append(flags[i+1]) i += 2 else: i += 1 return inc_dirs cpp_flags_env = os.getenv('CPPFLAGS', '') if not cpp_flags_env: # Don't quit; perhaps the user is asking for help using '--help'. # CPPFLAGS checking. print('setup.py: CPPFLAGS must be defined.', sys.stderr) # CPPFLAGS is passed to us as it's used in the Makefile: a string that the shell # will interpret. GetInclude uses shlex to do the same kind of interpretation # in order to identify the include directory options. cpp_flags_includes = GetIncludes(cpp_flags_env) # SRCDIR checking. if not os.getenv('SRCDIR'): # Don't quit; perhaps the user is asking for help using '--help'. print('setup.py: SRCDIR must be defined.', sys.stderr) srcdir = 'UNDEFINED' srcdir_include_server = 'UNDEFINED' else: # The distutils build system appends the source location to the build # location, and so to avoid that relative source paths with '..' make built # files end up outside the build location, the location is changed to an # absolute path. srcdir = os.path.abspath(os.getenv('SRCDIR')) if not os.path.isdir(srcdir): sys.exit("""Could not cd to SRCDIR '%s'.""" % srcdir) srcdir_include_server = os.path.join(srcdir, 'include_server') # Specify extension. ext = distutils.extension.Extension( name='include_server.distcc_pump_c_extensions', sources=[os.path.join(srcdir, source) for source in ['src/clirpc.c', 'src/clinet.c', 'src/state.c', 'src/srvrpc.c', 'src/pump.c', 'src/rpc.c', 'src/io.c', 'src/include_server_if.c', 'src/trace.c', 'src/snprintf.c', 'src/util.c', 'src/tempfile.c', 'src/filename.c', 'src/bulk.c', 'src/sendfile.c', 'src/compress.c', 'src/argutil.c', 'src/cleanup.c', 'src/emaillog.c', 'src/timeval.c', 'src/netutil.c', 'lzo/minilzo.c', 'include_server/c_extensions/distcc_pump_c_extensions_module.c', ]], include_dirs=cpp_flags_includes, define_macros=[('_GNU_SOURCE', 1)], library_dirs=[], libraries=[], runtime_library_dirs=[], extra_objects=[], extra_compile_args=[] ) args = { 'name': 'include_server', # The 'include_server' package is in the srcdir_include_server. 'package_dir': {'include_server': srcdir_include_server}, 'version': os.getenv('DISTCC_VERSION') or 'unknown', 'description': """Include server for distcc's pump-mode""", 'author': 'Nils Klarlund', 'author_email': 'opensource@google.com', 'url': 'http://code.google.com/p/distcc', 'long_description': 'The include server is part of distcc.', 'packages': ['include_server'], 'ext_modules': [ext], } # First, do a little self-testing. doctest.testmod() # Second, do the setup. distutils.core.setup(**args) distcc-3.4/include_server/statistics.py000077500000000000000000000121621404653710500204200ustar00rootroot00000000000000#! /usr/bin/env python3 # # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # """Statistics gathering for the distcc-pump include server.""" __author__ = "Nils Klarlund" import time resolve_expr_counter = 0 # number of computed includes master_hit_counter = 0 # summary node hits master_miss_counter = 0 # summary node misses resolve_counter = 0 # calls of Resolve method search_counter = 0 # number of probes in directory lists build_stat_counter = 0 # number of stats in build_stat_cache sys_stat_counter = 0 # number of calls to OS stat translation_unit_counter = 0 # number of translation units start_time = None translation_unit_time = None min_time = float('Inf') max_time = 0.0 total_time = 0.0 parse_file_total_time = 0.0 parse_file_counter = 0 # number of files parsed parse_file_counter_last = 0 # the number of files parsed after previous # translation unit quote_path_total = 0 # total length of quote directory lists angle_path_total = 0 # total length of angle directory lists len_calculated_closure = 0 # number of all included files len_calculated_closure_nonsys = 0 # same, but excluding system files # known to compiler len_exact_closure = 0 # number of all files in CPP-calculated closure len_surplus_nonsys = 0 # the difference between # len_calculated_closure and number of files # in exact closure that are not known to compiler find_node_counter = 0 # number of times FindNode is called def StartTiming(): global start_time, translation_unit_counter """Mark the start of a request to find an include closure.""" translation_unit_counter += 1 start_time = time.perf_counter() def EndTiming(): """Mark the end of an include closure calculation.""" global translation_unit_time, min_time, max_time, total_time translation_unit_time = time.perf_counter() - start_time min_time = min(translation_unit_time, min_time) max_time = max(translation_unit_time, max_time) total_time += translation_unit_time def PrintStatistics(include_analyzer): # Avoid division by zero in non-interesting case. if translation_unit_counter == 0: return print("TRANSLATION_UNIT: %s" % include_analyzer.translation_unit) print (("TIME: last %-2.3fs, min %-2.3fs, " "max %-2.3fs, average %-2.3fs, #: %5d, total: %5.1fs") % (translation_unit_time, min_time, max_time, total_time/translation_unit_counter, translation_unit_counter, total_time)) print ("PARSING: total %-5.3fs, total count: %4d, new files: %-5d" % (parse_file_total_time, parse_file_counter, parse_file_counter - parse_file_counter_last)) print("COUNTER: resolve_expr_counter: %8d" % resolve_expr_counter) print("COUNTER: master_hit_counter: %8d" % master_hit_counter) print("COUNTER: master_miss_counter: %8d" % master_miss_counter) print("SIZE: master_cache %8d" % ( len(include_analyzer.master_cache))) print("COUNTER: sys_stat_counter: %10d" % sys_stat_counter) print("COUNTER: build_stat_counter: %10d" % build_stat_counter) if resolve_counter != 0: print("COUNTER: search_counter (average): %4.1f" % ( float(search_counter)/resolve_counter)) print("SIZE: include_dir_pairs: %8d" % ( len(include_analyzer.include_dir_pairs))) if 'quote_dirs' in include_analyzer.__dict__: print("SIZE: quote_path %8d" % ( len(include_analyzer.quote_dirs))) if 'angle_dirs' in include_analyzer.__dict__: print("SIZE: angle_path %8d" % ( len(include_analyzer.angle_dirs))) print("SIZE: quote_path (average) %4.1f" % ( float(quote_path_total)/translation_unit_counter)) print("SIZE: angle_path (average) %4.1f" % ( float(angle_path_total)/translation_unit_counter)) print("SIZE: quote_dirs_set %8d" % ( len(include_analyzer.quote_dirs_set))) print("SIZE: angle_dirs_set: %8d" % ( len(include_analyzer.angle_dirs_set))) print() print("SIZE: calculated_closure: %8d" % len_calculated_closure) print("SIZE: calculated_closure_nonsys: %8d" % ( len_calculated_closure_nonsys)) print("SIZE: exact_closure %8d" % len_exact_closure) print("SIZE: surplus_nonsys %8d" % len_surplus_nonsys) print() distcc-3.4/include_server/test_data/000077500000000000000000000000001404653710500176175ustar00rootroot00000000000000distcc-3.4/include_server/test_data/abc_post.c000077500000000000000000000000421404653710500215540ustar00rootroot00000000000000/* Used by computed_includes.c */ distcc-3.4/include_server/test_data/abc_pre.c000077500000000000000000000000431404653710500213560ustar00rootroot00000000000000/* Used by computed_includes.c */ distcc-3.4/include_server/test_data/computed_includes.c000077500000000000000000000002141404653710500234710ustar00rootroot00000000000000#define A "p1.h" #include A #ifdef C #define m(a) #else #define m(a) #endif #include m(abc) // distcc-3.4/include_server/test_data/contains_abs_include.c000066400000000000000000000000341404653710500241260ustar00rootroot00000000000000#include "/love/of/my/life" distcc-3.4/include_server/test_data/dbar/000077500000000000000000000000001404653710500205275ustar00rootroot00000000000000distcc-3.4/include_server/test_data/dbar/dbar1/000077500000000000000000000000001404653710500215205ustar00rootroot00000000000000distcc-3.4/include_server/test_data/dbar/dbar1/bar.h000066400000000000000000000000321404653710500224300ustar00rootroot00000000000000#define dbar_dbar1_bar_h distcc-3.4/include_server/test_data/dbar/foo.h000077500000000000000000000000221404653710500214600ustar00rootroot00000000000000#include "foo2.h" distcc-3.4/include_server/test_data/dfoo/000077500000000000000000000000001404653710500205465ustar00rootroot00000000000000distcc-3.4/include_server/test_data/dfoo/foo.h000077500000000000000000000000611404653710500215020ustar00rootroot00000000000000#include "foo2.h" #include "../dbar/dbar1/bar.h" distcc-3.4/include_server/test_data/dfoo/foo2.h000066400000000000000000000001551404653710500215650ustar00rootroot00000000000000#define dfoo_foo2_h // The include below is not valid syntax and should be ignored. #include ../dbar/foo.h distcc-3.4/include_server/test_data/dfoo/i_am_perhaps_a_directory.h000066400000000000000000000000001404653710500257200ustar00rootroot00000000000000distcc-3.4/include_server/test_data/dfoo/include_dotdot_foo000066400000000000000000000000221404653710500243260ustar00rootroot00000000000000#include "../foo" distcc-3.4/include_server/test_data/dfoo/include_next_foo.h000077500000000000000000000000261404653710500242440ustar00rootroot00000000000000#include_next distcc-3.4/include_server/test_data/dfoo/stat_triggers.h000066400000000000000000000000001404653710500235660ustar00rootroot00000000000000distcc-3.4/include_server/test_data/distcc/000077500000000000000000000000001404653710500210705ustar00rootroot00000000000000distcc-3.4/include_server/test_data/distcc/README000066400000000000000000000000701404653710500217450ustar00rootroot00000000000000This is just part of the distcc code, used for testing. distcc-3.4/include_server/test_data/distcc/src/000077500000000000000000000000001404653710500216575ustar00rootroot00000000000000distcc-3.4/include_server/test_data/distcc/src/bulk.h000066400000000000000000000035751404653710500227770ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78; -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ int dcc_r_file(int ifd, const char *filename, unsigned, enum dcc_compress); int dcc_r_fifo(int ifd, const char *fifo_name, size_t len); int dcc_x_file(int ofd, const char *fname, const char *token, enum dcc_compress compression, off_t *); int dcc_r_file_timed(int ifd, const char *fname, unsigned size, enum dcc_compress); int dcc_r_token_file(int ifd, const char *token, const char *fname, enum dcc_compress compr); int dcc_open_read(const char *fname, int *ifd, off_t *fsize); int dcc_copy_file_to_fd(const char *in_fname, int out_fd); /* clirpc.c */ int dcc_x_many_files(int ofd, unsigned int n_files, char **fnames); /* srvrpc.c */ int dcc_r_many_files(int in_fd, const char *dirname, enum dcc_compress compr); distcc-3.4/include_server/test_data/distcc/src/compile.h000066400000000000000000000027421404653710500234650ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /* remote.c */ int dcc_compile_remote(char **argv, char *input_fname, char *cpp_fname, char **file_names, char *output_fname, char *deps_fname, char *server_stderr_fname, pid_t cpp_pid, int local_cpu_lock_fd, struct dcc_hostdef *host, int *status); int dcc_build_somewhere_timed(char *argv[], int sg_level, int *status); distcc-3.4/include_server/test_data/distcc/src/config.h000066400000000000000000000157221404653710500233040ustar00rootroot00000000000000/* src/config.h. Generated by configure. */ /* src/config.h.in. Generated from configure.ac by autoheader. */ /* Use getaddrinfo(), getnameinfo(), etc */ /* #undef ENABLE_RFC2553 */ /* Your gnu-style host triple */ #define GNU_HOST "x86_64-unknown-linux-gnu" /* Define to 1 if you have the header file. */ #define HAVE_ALLOCA_H 1 /* Define to 1 if you have the header file. */ #define HAVE_ARPA_NAMESER_H 1 /* Define to 1 if you have the `asprintf' function. */ #define HAVE_ASPRINTF 1 /* define if vsnprintf is C99 compliant */ #define HAVE_C99_VSNPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_CTYPE_H 1 /* Define to 1 if you have the declaration of `asprintf', and to 0 if you don't. */ #define HAVE_DECL_ASPRINTF 1 /* Define to 1 if you have the declaration of `snprintf', and to 0 if you don't. */ #define HAVE_DECL_SNPRINTF 1 /* Define to 1 if you have the declaration of `strndup', and to 0 if you don't. */ #define HAVE_DECL_STRNDUP 1 /* Define to 1 if you have the declaration of `vasprintf', and to 0 if you don't. */ #define HAVE_DECL_VASPRINTF 1 /* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you don't. */ #define HAVE_DECL_VSNPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_FLOAT_H 1 /* Define to 1 if you have the `flock' function. */ #define HAVE_FLOCK 1 /* Define to 1 if you have the `getaddrinfo' function. */ #define HAVE_GETADDRINFO 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `geteuid' function. */ #define HAVE_GETEUID 1 /* Define to 1 if you have the `getloadavg' function. */ #define HAVE_GETLOADAVG 1 /* Define to 1 if you have the `getnameinfo' function. */ #define HAVE_GETNAMEINFO 1 /* Define to 1 if you have the `getrusage' function. */ #define HAVE_GETRUSAGE 1 /* Define to 1 if you have the `gettimeofday' function. */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the `getuid' function. */ #define HAVE_GETUID 1 /* Define to 1 if you have the `getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define to 1 if you have the `getwd' function. */ #define HAVE_GETWD 1 /* Define to 1 if you have the `hstrerror' function. */ #define HAVE_HSTRERROR 1 /* Define to 1 if you have the `inet_ntoa' function. */ #define HAVE_INET_NTOA 1 /* Define to 1 if you have the `inet_ntop' function. */ #define HAVE_INET_NTOP 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if the system has the type `in_addr_t'. */ #define HAVE_IN_ADDR_T 1 /* Define to 1 if the system has the type `in_port_t'. */ #define HAVE_IN_PORT_T 1 /* Define to 1 if you have the `lockf' function. */ #define HAVE_LOCKF 1 /* Define to 1 if you have the `mcheck' function. */ #define HAVE_MCHECK 1 /* Define to 1 if you have the header file. */ #define HAVE_MCHECK_H 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mmap' function. */ #define HAVE_MMAP 1 /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_RESOLV_H 1 /* Define to 1 if you have the `sendfile' function. */ #define HAVE_SENDFILE 1 /* Define to 1 if you have the `setgroups' function. */ #define HAVE_SETGROUPS 1 /* Define to 1 if you have the `setreuid' function. */ #define HAVE_SETREUID 1 /* Define to 1 if you have the `setsid' function. */ #define HAVE_SETSID 1 /* Define to 1 if you have the `setuid' function. */ #define HAVE_SETUID 1 /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 /* define if you have struct sockaddr_storage */ #define HAVE_SOCKADDR_STORAGE 1 /* define if you have a working socketpair */ #define HAVE_SOCKETPAIR 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcpy' function. */ /* #undef HAVE_STRLCPY */ /* Define to 1 if you have the `strndup' function. */ #define HAVE_STRNDUP 1 /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_LOADAVG_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_MMAN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SELECT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SENDFILE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SIGNAL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SOCKET_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define if your cpp has vararg macros */ #define HAVE_VARARG_MACROS /* Define to 1 if you have the `vasprintf' function. */ #define HAVE_VASPRINTF 1 /* Whether __va_copy() is available */ #define HAVE_VA_COPY 1 /* Define to 1 if you have the `vsnprintf' function. */ #define HAVE_VSNPRINTF 1 /* Define to 1 if you have the `wait3' function. */ #define HAVE_WAIT3 1 /* Define to 1 if you have the `wait4' function. */ #define HAVE_WAIT4 1 /* Define to 1 if you have the `waitpid' function. */ #define HAVE_WAITPID 1 /* Define if MAP_FAILED constant not available */ #define MAP_FAILED (void *)-1L /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "distcc-pump@google.com" /* Define to the full name of this package. */ #define PACKAGE_NAME "distcc" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "distcc 2.18.3-17gg-pump6" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "distcc" /* Define to the version of this package. */ #define PACKAGE_VERSION "2.18.3-17gg-pump6" /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Use GNOME */ /* #undef WITH_GNOME */ /* Use GTK+ */ /* #undef WITH_GTK */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* type to use in place of socklen_t if not defined */ /* #undef socklen_t */ distcc-3.4/include_server/test_data/distcc/src/distcc.c000066400000000000000000000146131404653710500233010ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /* 4: The noise of a multitude in the * mountains, like as of a great people; a * tumultuous noise of the kingdoms of nations * gathered together: the LORD of hosts * mustereth the host of the battle. * -- Isaiah 13 */ #include "config.h" #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "hosts.h" #include "bulk.h" #include "implicit.h" #include "compile.h" #include "emaillog.h" /* Name of this program, for trace.c */ const char *rs_program_name = "distcc"; /** * @file * * Entry point for the distcc client. * * There are three methods of use for distcc: explicit (distcc gcc -c * foo.c), implicit (distcc -c foo.c) and masqueraded (gcc -c foo.c, * where gcc is really a link to distcc). * * Detecting these is relatively easy by examining the first one or * two words of the command. We also need to make sure that when we * go to run the compiler, we run the one intended by the user. * * In particular, for masqueraded mode, we want to make sure that we * don't invoke distcc recursively. **/ static void dcc_show_usage(void) { dcc_show_version("distcc"); printf( "Usage:\n" " distcc [COMPILER] [compile options] -o OBJECT -c SOURCE\n" " distcc --help\n" "\n" "Options:\n" " COMPILER defaults to \"cc\"\n" " --help explain usage and exit\n" " --version show version and exit\n" "\n" "Environment variables:\n" " See the manual page for a complete list.\n" " DISTCC_VERBOSE=1 give debug messages\n" " DISTCC_LOG send messages to file, not stderr\n" " DISTCC_SSH command to run to open SSH connections\n" " DISTCC_DIR directory for host list and locks\n" "\n" "Server specification:\n" "A list of servers is taken from the environment variable $DISTCC_HOSTS, or\n" "$DISTCC_DIR/hosts, or ~/.distcc/hosts, or %s/distcc/hosts.\n" "Each host can be given in any of these forms, see the manual for details:\n" "\n" " localhost run in place\n" " HOST TCP connection, port %d\n" " HOST:PORT TCP connection, specified port\n" " @HOST SSH connection\n" " USER@HOST SSH connection to specified host\n" " --randomize Randomize the server list before execution\n" "\n" "distcc distributes compilation jobs across volunteer machines running\n" "distccd. Jobs that cannot be distributed, such as linking or \n" "preprocessing are run locally. distcc should be used with make's -jN\n" "option to execute in parallel on several machines.\n", SYSCONFDIR, DISTCC_DEFAULT_PORT); } static RETSIGTYPE dcc_client_signalled (int whichsig) { signal(whichsig, SIG_DFL); #ifdef HAVE_STRSIGNAL rs_log_info("%s", strsignal(whichsig)); #else rs_log_info("terminated by signal %d", whichsig); #endif dcc_cleanup_tempfiles_from_signal_handler(); raise(whichsig); } static void dcc_client_catch_signals(void) { signal(SIGTERM, &dcc_client_signalled); signal(SIGINT, &dcc_client_signalled); signal(SIGHUP, &dcc_client_signalled); } /** * distcc client entry point. * * This is typically called by make in place of the real compiler. * * Performs basic setup and checks for distcc arguments, and then kicks off * dcc_build_somewhere(). **/ int main(int argc, char **argv) { int status, sg_level, tweaked_path = 0; char **compiler_args; char *compiler_name; int ret; dcc_client_catch_signals(); atexit(dcc_cleanup_tempfiles); atexit(dcc_remove_state_file); dcc_set_trace_from_env(); dcc_setup_log_email(); dcc_trace_version(); compiler_name = (char *) dcc_find_basename(argv[0]); /* Ignore SIGPIPE; we consistently check error codes and will * see the EPIPE. */ dcc_ignore_sigpipe(1); sg_level = dcc_recursion_safeguard(); rs_trace("compiler name is \"%s\"", compiler_name); if (strstr(compiler_name, "distcc") != NULL) { /* Either "distcc -c hello.c" or "distcc gcc -c hello.c" */ if (argc <= 1 || !strcmp(argv[1], "--help")) { dcc_show_usage(); ret = 0; goto out; } if (!strcmp(argv[1], "--version")) { dcc_show_version("distcc"); ret = 0; goto out; } dcc_find_compiler(argv, &compiler_args); /* compiler_args is now respectively either "cc -c hello.c" or * "gcc -c hello.c" */ #if 0 /* I don't think we need to call this: if we reached this * line, our invocation name is something like 'distcc', and * that's never a problem for masquerading loops. */ if ((ret = dcc_trim_path(compiler_name)) != 0) goto out; #endif } else { /* Invoked as "cc -c hello.c", with masqueraded path */ if ((ret = dcc_support_masquerade(argv, compiler_name, &tweaked_path)) != 0) goto out; dcc_copy_argv(argv, &compiler_args, 0); compiler_args[0] = compiler_name; } if (sg_level - tweaked_path > 0) { rs_log_crit("distcc seems to have invoked itself recursively!"); ret = EXIT_RECURSION; goto out; } ret = dcc_build_somewhere_timed(compiler_args, sg_level, &status); out: dcc_maybe_send_email(); dcc_exit(ret); } distcc-3.4/include_server/test_data/distcc/src/distcc.h000066400000000000000000000217231404653710500233060ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /* distcc.h -- common internal-use header file */ #include #ifdef NORETURN /* nothing */ #elif defined(__GNUC__) # define NORETURN __attribute__((noreturn)) #elif defined(__LCLINT__) # define NORETURN /*@noreturn@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define NORETURN #endif /* !__GNUC__ && !__LCLINT__ */ #ifdef UNUSED /* nothing */ #elif defined(__GNUC__) # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) #elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define UNUSED(x) x #endif /* !__GNUC__ && !__LCLINT__ */ #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) /* This works on Gentoo's (patched?) gcc 3.3.3 but not 3.2.3, and not Debian's * 3.3.4. It should be standard on 3.4. */ # define WARN_UNUSED __attribute__((warn_unused_result)) #else # define WARN_UNUSED #endif #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif struct dcc_hostdef; #include "state.h" enum dcc_compress { /* weird values to catch errors */ DCC_COMPRESS_NONE = 69, DCC_COMPRESS_LZO1X }; enum dcc_cpp_where { /* weird values to catch errors */ DCC_CPP_ON_CLIENT = 42, DCC_CPP_ON_SERVER }; enum dcc_protover { DCC_VER_1 = 1, /**< vanilla */ DCC_VER_2 = 2, /**< LZO sprinkles */ DCC_VER_3 = 3 /**< server-side cpp */ }; int str_endswith(const char *tail, const char *tiger); /* A macro so that we get the right __FUNCTION__ in the trace message. * * We condition on rs_trace_enabled so that we don't do the to-string * conversion unless the user will actually see the result, because it's a * little expensive. */ #define dcc_trace_argv(_message, _argv) \ if (rs_trace_enabled()) { \ char *_astr; \ _astr = dcc_argv_tostr(_argv); \ rs_trace("%s: %s", _message, _astr); \ free(_astr); \ } else {} /* help.c */ int dcc_trace_version(void); int dcc_show_version(const char *prog); /* hosts.c */ int dcc_parse_hosts_env(struct dcc_hostdef **ret_list, int *ret_nhosts); int dcc_parse_hosts(const char *where, const char *source_name, struct dcc_hostdef **ret_list, int *ret_nhosts); /* ncpu.c */ int dcc_ncpus(int *); /* ssh.c */ int dcc_ssh_connect(char *ssh_cmd, char *user, char *machine, char *path, int *f_in, int *f_out, pid_t *ssh_pid); /* safeguard.c */ int dcc_increment_safeguard(void); int dcc_recursion_safeguard(void); /* clirpc.c */ int dcc_x_req_header(int fd, enum dcc_protover protover); int dcc_x_argv(int fd, char **argv); int dcc_x_cwd(int fd); /* srvrpc.c */ int dcc_r_cwd(int ifd, char **cwd); /* remote.c */ int dcc_send_job_corked(int net_fd, char **argv, pid_t cpp_pid, int *status, const char *, const char *cpp_fname, struct dcc_hostdef *); int dcc_retrieve_results(int net_fd, int *status, const char *output_fname, const char *deps_fname, const char *server_stderr_fname, struct dcc_hostdef *); /* climasq.c */ int dcc_support_masquerade(char *argv[], char *progname, int *); /* backoff.c */ int dcc_enjoyed_host(const struct dcc_hostdef *host); int dcc_disliked_host(const struct dcc_hostdef *host); int dcc_remove_disliked(struct dcc_hostdef **hostlist); #define DISTCC_DEFAULT_PORT 3632 #define DISTCC_DEFAULT_STATS_ENABLED 0 #define DISTCC_DEFAULT_STATS_PORT 3633 #ifndef WAIT_ANY # define WAIT_ANY (-1) #endif /* If --enable-rfc2553 was given, then we will try to enable compile-time IPv6 * support. This means we must have a sockaddr_storage large enough to hold * IPv6 addresses. If not, we'll just use a plain sockaddr, which is more * likely to compile correctly. */ #ifdef ENABLE_RFC2553 # ifndef HAVE_SOCKADDR_STORAGE # error You can't use RFC2553 because you don't have a sockaddr_storage type # endif /* HAVE_SOCKADDR_STORAGE */ # define dcc_sockaddr_storage sockaddr_storage #else /* !ENABLE_RFC2553 */ # define dcc_sockaddr_storage sockaddr #endif /* !ENABLE_RFC2553 */ #ifndef O_BINARY # define O_BINARY 0 #endif void dcc_set_trace_from_env(void); /* compress.c */ int dcc_r_bulk_lzo1x(int outf_fd, int in_fd, unsigned in_len); int dcc_compress_file_lzo1x(int in_fd, size_t in_len, char **out_buf, size_t *out_len); int dcc_compress_lzo1x_alloc(const char *in_buf, size_t in_len, char **out_buf_ret, size_t *out_len_ret); /* bulk.h */ void dcc_calc_rate(off_t size_out, struct timeval *before, struct timeval *after, double *secs, double *rate); /* arg.c */ int dcc_set_action_opt(char **, const char *); int dcc_set_output(char **, char *); int dcc_set_input(char **, char *); int dcc_scan_args(char *argv[], /*@out@*/ /*@relnull@*/ char **orig_o, char **orig_i, char ***ret_newargv); /* argutil.c */ unsigned int dcc_argv_len(char **a); int dcc_argv_search(char **a, const char *); int dcc_copy_argv(char **argv, char ***out_argv, int extra_args); int dcc_argv_append(char **argv, char *toadd); char *dcc_argv_tostr(char **a); void dcc_free_argv(char **argv); /* tempfile.c */ int dcc_get_tempdir(const char **); int dcc_make_tmpnam(const char *, const char *suffix, char **); int dcc_get_new_tmpdir(char **tmpdir); int dcc_mk_tmpdir(const char *path); int dcc_mkdir(const char *path); int dcc_get_lock_dir(char **path_ret) WARN_UNUSED; int dcc_get_state_dir(char **path_ret) WARN_UNUSED; int dcc_get_top_dir(char **path_ret) WARN_UNUSED; int dcc_get_tmp_top(const char **p_ret) WARN_UNUSED; int dcc_mk_tmp_ancestor_dirs(const char* file); /* cleanup.c */ void dcc_cleanup_tempfiles(void); void dcc_cleanup_tempfiles_from_signal_handler(void); int dcc_add_cleanup(const char *filename) WARN_UNUSED; /* strip.c */ int dcc_strip_local_args(char **from, char ***out_argv); int dcc_strip_dasho(char **from, char ***out_argv); /* cpp.c */ int dcc_cpp_maybe(char **argv, char *input_fname, char **cpp_fname, pid_t *cpp_pid); /* filename.c */ int dcc_is_source(const char *sfile); int dcc_is_preprocessed(const char *sfile); int dcc_is_object(const char *filename); int dcc_source_needs_local(const char *); char * dcc_find_extension(char *sfile); int dcc_output_from_source(const char *sfile, const char *out_extn, char **ofile); const char * dcc_preproc_exten(const char *e); const char * dcc_find_basename(const char *sfile); void dcc_truncate_to_dirname(char *file); /* io.c */ int dcc_writex(int fd, const void *buf, size_t len); int dcc_r_token(int ifd, char *token); int dcc_readx(int fd, void *buf, size_t len); int dcc_pump_sendfile(int ofd, int ifd, size_t n); int dcc_r_str_alloc(int fd, unsigned len, char **buf); int tcp_cork_sock(int fd, int corked); int dcc_close(int fd); int dcc_want_mmap(void); int dcc_select_for_write(int fd, int timeout); int dcc_select_for_read(int fd, int timeout); /* loadfile.c */ int dcc_load_file_string(const char *filename, char **retbuf); extern const int dcc_connect_timeout, dcc_io_timeout; /* pump.c */ int dcc_r_bulk(int ofd, int ifd, unsigned f_size, enum dcc_compress compression); int dcc_pump_readwrite(int ofd, int ifd, size_t n); /* mapfile.c */ int dcc_map_input_file(int in_fd, off_t in_size, char **buf_ret); /* XXX: Kind of kludgy, we should do dynamic allocation. But this will do for * now. */ #ifndef MAXPATHLEN #define MAXPATHLEN 4096 #endif #ifndef WCOREDUMP # define WCOREDUMP(status) 0 #endif distcc-3.4/include_server/test_data/distcc/src/emaillog.h000066400000000000000000000004711404653710500236230ustar00rootroot00000000000000#ifndef DCC_EMAILLOG_H #define DCC_EMAILLOG_H #define DCC_EMAILLOG_WHOM_TO_BLAME "distcc-pump-errors@google.com" void dcc_please_send_email(void); void dcc_setup_log_email(void); void dcc_maybe_send_email(void); int dcc_add_file_to_log_email(const char *description, const char *fname); #endif /* EMAILLOG_H */ distcc-3.4/include_server/test_data/distcc/src/exitcode.h000066400000000000000000000042401404653710500236340ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #ifndef _DISTCC_EXITCODE_H #define _DISTCC_EXITCODE_H /** * @file * * Common exit codes. **/ /** * Common exit codes for both client and server. * * These need to be in [1,255] so that they can be used as exit() * codes. **/ enum dcc_exitcode { EXIT_DISTCC_FAILED = 100, /**< General failure */ EXIT_BAD_ARGUMENTS = 101, EXIT_BIND_FAILED = 102, EXIT_CONNECT_FAILED = 103, EXIT_COMPILER_CRASHED = 104, EXIT_OUT_OF_MEMORY = 105, EXIT_BAD_HOSTSPEC = 106, EXIT_IO_ERROR = 107, EXIT_TRUNCATED = 108, EXIT_PROTOCOL_ERROR = 109, EXIT_COMPILER_MISSING = 110, /**< Compiler executable not found */ EXIT_RECURSION = 111, /**< distcc called itself */ EXIT_SETUID_FAILED = 112, /**< Failed to discard privileges */ EXIT_ACCESS_DENIED = 113, /**< Network access denied */ EXIT_BUSY = 114, /**< In use by another process. */ EXIT_NO_SUCH_FILE = 115, EXIT_NO_HOSTS = 116, EXIT_GONE = 117, /**< No longer relevant */ EXIT_TIMEOUT = 118 }; #endif /* _DISTCC_EXITCODE_H */ distcc-3.4/include_server/test_data/distcc/src/hosts.h000066400000000000000000000050761404653710500232000ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /** * @file * * Declarations for distcc host selection stuff. **/ /** * A simple linked list of host definitions. All strings are mallocd. **/ struct dcc_hostdef { enum { DCC_MODE_TCP = 1, DCC_MODE_SSH, DCC_MODE_LOCAL } mode; char * user; char * hostname; int port; char * ssh_command; /** Mark the host as up == 1, by default, or down == 0, if !hostname */ int is_up; /** Number of tasks that can be dispatched concurrently to this machine. */ int n_slots; /** The full name of this host, taken verbatim from the host * definition. **/ char * hostdef_string; enum dcc_protover protover; /** The kind of compression to use for this host */ enum dcc_compress compr; /** Where are we doing preprocessing? */ enum dcc_cpp_where cpp_where; struct dcc_hostdef *next; }; /** Static definition of localhost **/ extern struct dcc_hostdef *dcc_hostdef_local; extern struct dcc_hostdef *dcc_hostdef_local_cpp; /* hosts.c */ int dcc_get_hostlist(struct dcc_hostdef **ret_list, int *ret_nhosts); int dcc_free_hostdef(struct dcc_hostdef *host); int dcc_get_features_from_protover(enum dcc_protover protover, enum dcc_compress *compr, enum dcc_cpp_where *cpp_where); int dcc_get_protover_from_features(enum dcc_compress compr, enum dcc_cpp_where cpp_where, enum dcc_protover *protover); /* hostfile.c */ int dcc_parse_hosts_file(const char *fname, struct dcc_hostdef **ret_list, int *ret_nhosts); distcc-3.4/include_server/test_data/distcc/src/implicit.h000066400000000000000000000017701404653710500236470ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/implicit.h,v 1.3 2002/09/18 06:57:45 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ int dcc_find_compiler(char **argv, char ***); distcc-3.4/include_server/test_data/distcc/src/include_me.h000066400000000000000000000000001404653710500241220ustar00rootroot00000000000000distcc-3.4/include_server/test_data/distcc/src/state.h000066400000000000000000000047531404653710500231610ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #ifndef _DISTCC_STATE_H #define _DISTCC_STATE_H #ifdef __cplusplus extern "C" { #endif int dcc_get_state_dir (char **p); int dcc_open_state_file (int *p_fd); /* Note that these must be in the order in which they are encountered * for the state file to work properly. It's OK if some are skipped * though. */ enum dcc_phase { DCC_PHASE_STARTUP, DCC_PHASE_BLOCKED, DCC_PHASE_CONNECT, DCC_PHASE_CPP, DCC_PHASE_SEND, DCC_PHASE_COMPILE, /**< or unknown */ DCC_PHASE_RECEIVE, DCC_PHASE_DONE /**< MUST be last */ }; int dcc_note_state (enum dcc_phase state, const char *file, const char *host); void dcc_remove_state_file (void); extern const char *dcc_state_prefix; #define DCC_STATE_MAGIC 0x44494800 /* DIH\0 */ /** * State and history of a distcc process. Used in memory and also in native * format for binary state files. * * This should be <4kB, so that it will normally be written out * atomically. **/ struct dcc_task_state { size_t struct_size; unsigned long magic; unsigned long cpid; /**< Client pid */ char file[128]; /**< Input filename */ char host[128]; /**< Destination host description */ int slot; /**< Which CPU slot for this host */ enum dcc_phase curr_phase; /** In memory, point to the next in a list of all tasks. In the * file, undefined. */ struct dcc_task_state *next; }; const char *dcc_get_phase_name(enum dcc_phase); void dcc_note_state_slot(int slot); #ifdef __cplusplus } #endif #endif /* _DISTCC_STATE_H */ distcc-3.4/include_server/test_data/distcc/src/trace.h000066400000000000000000000161421404653710500231320ustar00rootroot00000000000000/*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- * * librsync -- generate and apply network deltas * * Copyright (C) 2000, 2001, 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** * @file * * Reusable trace library. * * @todo A function like perror that includes strerror output. Apache * does this by adding flags as well as the severity level which say * whether such information should be included. * * @todo Also check in configure for the C9X predefined identifier `_function', or * whatever it's called. **/ /* Provide simple macro statement wrappers (adapted from glib, and originally from Perl): * RS_STMT_START { statements; } RS_STMT_END; * can be used as a single statement, as in * if (x) RS_STMT_START { ... } RS_STMT_END; else ... * * For gcc we will wrap the statements within `({' and `})' braces. * For SunOS they will be wrapped within `if (1)' and `else (void) 0', * and otherwise within `do' and `while (0)'. */ #if !(defined (RS_STMT_START) && defined (RS_STMT_END)) # if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) # define RS_STMT_START (void)( # define RS_STMT_END ) # else # if (defined (sun) || defined (__sun__)) # define RS_STMT_START if (1) # define RS_STMT_END else (void)0 # else # define RS_STMT_START do # define RS_STMT_END while (0) # endif # endif #endif #include /* unconditionally on */ #define DO_RS_TRACE /** * Log severity levels. * * These have the same numeric values as the levels for syslog, at * least in glibc. * * Trace may be turned off. * * Error is always on, but you can return and continue in some way. */ typedef enum { RS_LOG_EMERG = 0, /**< System is unusable */ RS_LOG_ALERT = 1, /**< Action must be taken immediately */ RS_LOG_CRIT = 2, /**< Critical conditions */ RS_LOG_ERR = 3, /**< Error conditions */ RS_LOG_WARNING = 4, /**< Warning conditions */ RS_LOG_NOTICE = 5, /**< Normal but significant condition */ RS_LOG_INFO = 6, /**< Informational */ RS_LOG_DEBUG = 7 /**< Debug-level messages */ } rs_loglevel; int rs_loglevel_from_name(const char *name); enum { RS_LOG_PRIMASK = 7, /**< Mask to extract priority part. \internal */ RS_LOG_NONAME = 8, /**< \b Don't show function name in message. */ RS_LOG_NO_PROGRAM = 16, RS_LOG_NO_PID = 32 }; /** * \typedef rs_logger_fn * \brief Callback to write out log messages. * \param level a syslog level. * \param msg message to be logged. * * \param private Opaque data passed in when logger was added. For * example, pointer to file descriptor. */ typedef void rs_logger_fn(int flags, const char *fn, char const *msg, va_list, void *private_ptr, int private_int); void rs_format_msg(char *buf, size_t, int, const char *, const char *fmt, va_list); void rs_trace_set_level(rs_loglevel level); void rs_add_logger(rs_logger_fn *, int level, void *, int); void rs_remove_logger(rs_logger_fn *, int level, void *, int); void rs_remove_all_loggers(void); void rs_logger_file(int level, const char *fn, char const *fmt, va_list va, void *, int); void rs_logger_syslog(int level, const char *fn, char const *fmt, va_list va, void *, int); /** Check whether the library was compiled with debugging trace support. */ int rs_supports_trace(void); void rs_log0(int level, char const *fn, char const *fmt, ...) #if defined(__GNUC__) __attribute__ ((format(printf, 3, 4))) #endif /* __GNUC__ */ ; /* TODO: Check for the __FUNCTION__ thing, rather than gnuc */ #if defined(HAVE_VARARG_MACROS) && defined(__GNUC__) #if 1 || defined(DO_RS_TRACE) # define rs_trace(fmt, arg...) \ do { rs_log0(RS_LOG_DEBUG, __FUNCTION__, fmt , ##arg); \ } while (0) #else # define rs_trace(s, str...) #endif /* !DO_RS_TRACE */ #define rs_log(l, s, str...) do { \ rs_log0((l), __FUNCTION__, (s) , ##str); \ } while (0) #define rs_log_crit(s, str...) do { \ rs_log0(RS_LOG_CRIT, __FUNCTION__, (s) , ##str); \ } while (0) #define rs_log_error(s, str...) do { \ rs_log0(RS_LOG_ERR, __FUNCTION__, (s) , ##str); \ } while (0) #define rs_log_notice(s, str...) do { \ rs_log0(RS_LOG_NOTICE, __FUNCTION__, (s) , ##str); \ } while (0) #define rs_log_warning(s, str...) do { \ rs_log0(RS_LOG_WARNING, __FUNCTION__, (s) , ##str); \ } while (0) #define rs_log_info(s, str...) do { \ rs_log0(RS_LOG_INFO, __FUNCTION__, (s) , ##str); \ } while (0) #else /* not defined HAVE_VARARG_MACROS */ /* If we don't have gcc vararg macros, then we fall back to making the * log routines just plain functions. On platforms without gcc (boo * hiss!) this means at least you get some messages, but not the nice * function names etc. */ #define rs_log rs_log0_nofn #define rs_trace rs_log_trace_nofn #define rs_log_info rs_log_info_nofn #define rs_log_notice rs_log_notice_nofn #define rs_log_warning rs_log_warning_nofn #define rs_log_error rs_log_error_nofn #define rs_log_crit rs_log_critical_nofn #endif /* HAVE_VARARG_MACROS */ void rs_log_trace_nofn(char const *s, ...); void rs_log_info_nofn(char const *, ...); void rs_log_notice_nofn(char const *, ...); void rs_log_warning_nofn(char const *s, ...); void rs_log_error_nofn(char const *s, ...); void rs_log_critical_nofn(char const *, ...); void rs_log0_nofn(int level, char const *fmt, ...); /** * \macro rs_trace_enabled() * * Call this before putting too much effort into generating trace * messages. */ extern int rs_trace_level; #ifdef DO_RS_TRACE # define rs_trace_enabled() ((rs_trace_level & RS_LOG_PRIMASK) >= RS_LOG_DEBUG) #else # define rs_trace_enabled() 0 #endif /** * Name of the program, to be included in log messages. * * @note This must be defined exactly once in each program that links to * trace.c **/ extern const char *rs_program_name; void dcc_job_summary_clear(void); void dcc_job_summary(void); void dcc_job_summary_append(const char *s); distcc-3.4/include_server/test_data/distcc/src/util.h000066400000000000000000000036621404653710500230140ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include /* util.c */ int dcc_getcurrentload(void); void dcc_getloadavg(double loadavg[3]); int argv_contains(char **argv, const char *s); int dcc_redirect_fd(int, const char *fname, int); int str_startswith(const char *head, const char *worm); char *dcc_gethostname(void); void dcc_exit(int exitcode) NORETURN; int dcc_getenv_bool(const char *name, int def_value); int set_cloexec_flag (int desc, int value); int dcc_ignore_sigpipe(int val); int dcc_remove_if_exists(const char *fname); int dcc_trim_path(const char *compiler_name); int dcc_set_path(const char *newpath); char *dcc_abspath(const char *path, int path_len); int dcc_get_dns_domain(const char **domain_name); #define str_equal(a, b) (!strcmp((a), (b))) void dcc_get_proc_stats(int *num_D, int *max_RSS, char **max_RSS_name); void dcc_get_disk_io_stats(int *n_reads, int *n_writes); int dcc_dup_part(const char **psrc, char **pdst, const char *sep); #ifndef HAVE_STRLCPY size_t strlcpy(char *d, const char *s, size_t bufsize); #endif int dcc_tokenize_string(const char *in, char ***argv_ptr); distcc-3.4/include_server/test_data/func_macro.c000066400000000000000000000000311404653710500220710ustar00rootroot00000000000000#include FINCLUDE(foo.h) distcc-3.4/include_server/test_data/i_am_perhaps_a_directory.h/000077500000000000000000000000001404653710500250605ustar00rootroot00000000000000distcc-3.4/include_server/test_data/i_am_perhaps_a_directory.h/empty_file000066400000000000000000000000001404653710500271260ustar00rootroot00000000000000distcc-3.4/include_server/test_data/include_include_next_foo.h000077500000000000000000000000361404653710500250210ustar00rootroot00000000000000#include "include_next_foo.h" distcc-3.4/include_server/test_data/maps/000077500000000000000000000000001404653710500205575ustar00rootroot00000000000000distcc-3.4/include_server/test_data/maps/foo.tpl.varnames.h000066400000000000000000000000011404653710500241130ustar00rootroot00000000000000 distcc-3.4/include_server/test_data/more_macros.c000066400000000000000000000005231404653710500222710ustar00rootroot00000000000000 #define TEMPLATE_VARNAME(_filename_) \ AS_STRING\ (maps/_filename_.tpl.varnames.h) #define ILLFORMED(_filename_,(x)) \ AS_STRING(maps/_filename_.tpl.varnames.h, NOTHANDLED(_filename_)) // #define BEHINDCOMMENT(x) x + x #define AS_STRING(x) AS_STRING_INTERNAL(x) #define AS_STRING_INTERNAL(x) #x #include TEMPLATE_VARNAME(foo) distcc-3.4/include_server/test_data/p1.h000077500000000000000000000000011404653710500203020ustar00rootroot00000000000000 distcc-3.4/include_server/test_data/parse.c000066400000000000000000000002101404653710500210660ustar00rootroot00000000000000#includenext "incnext.h" #include #include "quote.c" # include \ /* comment */ "quote1\ .c" #include "foo.h" // in dfoo distcc-3.4/include_server/test_data/stat_triggers.c000066400000000000000000000000331404653710500226400ustar00rootroot00000000000000#include "stat_triggers.h" distcc-3.4/include_server/test_data/stat_triggers.h000066400000000000000000000000001404653710500226370ustar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/000077500000000000000000000000001404653710500223125ustar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/abc_post.c000077700000000000000000000000001404653710500264142../abc_post.custar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/abc_pre.c000077700000000000000000000000001404653710500260162../abc_pre.custar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/computed_includes.c000077700000000000000000000000001404653710500322442../computed_includes.custar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/dbar000077700000000000000000000000001404653710500242062../dbarustar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/dfoo000077700000000000000000000000001404653710500242442../dfooustar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/foo000066400000000000000000000000721404653710500230170ustar00rootroot00000000000000#include "sub_farm/link_to_dd_dd_dfoo_include_dotdot_foo" distcc-3.4/include_server/test_data/symlink_farm/p1.h000077700000000000000000000000001404653710500237022../p1.hustar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/parse.c000077700000000000000000000000001404653710500252542../parse.custar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/sub_farm/000077500000000000000000000000001404653710500241105ustar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/sub_farm/link_to_dd_dd_dfoo_include_dotdot_foo000077700000000000000000000000001404653710500407002../../dfoo/include_dotdot_fooustar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/test_directory_probing.c000077700000000000000000000000001404653710500343762../test_directory_probing.custar00rootroot00000000000000distcc-3.4/include_server/test_data/symlink_farm/test_include_next000077700000000000000000000000001404653710500316262../test_include_nextustar00rootroot00000000000000distcc-3.4/include_server/test_data/test_computed_includes/000077500000000000000000000000001404653710500243645ustar00rootroot00000000000000distcc-3.4/include_server/test_data/test_computed_includes/helper.c000066400000000000000000000000161404653710500260040ustar00rootroot00000000000000#include INCL distcc-3.4/include_server/test_data/test_computed_includes/incl.h000066400000000000000000000000241404653710500254560ustar00rootroot00000000000000#define MSG "hello" distcc-3.4/include_server/test_data/test_computed_includes/inclA.h000066400000000000000000000000261404653710500255610ustar00rootroot00000000000000#define MSG "hello A" distcc-3.4/include_server/test_data/test_computed_includes/src.c000066400000000000000000000001671404653710500253230ustar00rootroot00000000000000#define INCL "incl.h" #include "helper.c" #include int main() { printf(MSG); printf("\n"); return 0; } distcc-3.4/include_server/test_data/test_computed_includes/srcA.c000066400000000000000000000001711404653710500254170ustar00rootroot00000000000000#define INCL "inclA.h" #include "helper.c" #include int main() { printf(MSG); printf("\n"); return 0; } distcc-3.4/include_server/test_data/test_directory_probing.c000066400000000000000000000002511404653710500245440ustar00rootroot00000000000000// For the include: should not be distracted by the directory // i_am_perhaps_a_directory.h in the present directory (test_data). #include "i_am_perhaps_a_directory.h" distcc-3.4/include_server/test_data/test_include_next/000077500000000000000000000000001404653710500233375ustar00rootroot00000000000000distcc-3.4/include_server/test_data/test_include_next/bar/000077500000000000000000000000001404653710500241035ustar00rootroot00000000000000distcc-3.4/include_server/test_data/test_include_next/bar/x.h000077500000000000000000000000411404653710500245210ustar00rootroot00000000000000Now bar/x.h #include_next "x.h" distcc-3.4/include_server/test_data/test_include_next/bar/y.h000077500000000000000000000000411404653710500245220ustar00rootroot00000000000000Now bar/y.h #include_next "y.h" distcc-3.4/include_server/test_data/test_include_next/baz/000077500000000000000000000000001404653710500241135ustar00rootroot00000000000000distcc-3.4/include_server/test_data/test_include_next/baz/start_x.c000077500000000000000000000000411404653710500257410ustar00rootroot00000000000000Now baz/start_x.h #include "x.h" distcc-3.4/include_server/test_data/test_include_next/baz/start_y.c000077500000000000000000000000501404653710500257420ustar00rootroot00000000000000Now baz/start_y.h #include "../foo/y.h" distcc-3.4/include_server/test_data/test_include_next/baz/x.h000077500000000000000000000000441404653710500245340ustar00rootroot00000000000000Now in baz/x.h #include_next "x.h" distcc-3.4/include_server/test_data/test_include_next/baz/y.h000077500000000000000000000001051404653710500245330ustar00rootroot00000000000000Now baz/y.h #ifndef baz_y_h #define baz_y_h #include y.h #endif distcc-3.4/include_server/test_data/test_include_next/biz/000077500000000000000000000000001404653710500241235ustar00rootroot00000000000000distcc-3.4/include_server/test_data/test_include_next/biz/x.h000077500000000000000000000000141404653710500245410ustar00rootroot00000000000000Now biz/x.h distcc-3.4/include_server/test_data/test_include_next/foo/000077500000000000000000000000001404653710500241225ustar00rootroot00000000000000distcc-3.4/include_server/test_data/test_include_next/foo/x.h000077500000000000000000000000411404653710500245400ustar00rootroot00000000000000Now: foo/x.h #include_next "x.h" distcc-3.4/include_server/test_data/test_include_next/foo/y.h000077500000000000000000000000411404653710500245410ustar00rootroot00000000000000Now: foo/y.h #include_next "y.h" distcc-3.4/install-sh000077500000000000000000000127361404653710500146530ustar00rootroot00000000000000#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 distcc-3.4/lzo/000077500000000000000000000000001404653710500134425ustar00rootroot00000000000000distcc-3.4/lzo/.stamp-conf.in000066400000000000000000000000721404653710500161160ustar00rootroot00000000000000## Force lzo directory to be created in build directory. distcc-3.4/lzo/COPYING000066400000000000000000000432541404653710500145050ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. distcc-3.4/lzo/README.LZO000066400000000000000000000076431404653710500147770ustar00rootroot00000000000000 ============================================================================ miniLZO -- mini subset of the LZO real-time data compression library ============================================================================ Author : Markus Franz Xaver Johannes Oberhumer http://www.oberhumer.com/opensource/lzo/ Version : 2.10 Date : 01 Mar 2017 I've created miniLZO for projects where it is inconvenient to include (or require) the full LZO source code just because you want to add a little bit of data compression to your application. miniLZO implements the LZO1X-1 compressor and both the standard and safe LZO1X decompressor. Apart from fast compression it also useful for situations where you want to use pre-compressed data files (which must have been compressed with LZO1X-999). miniLZO consists of one C source file and three header files: minilzo.c minilzo.h, lzoconf.h, lzodefs.h To use miniLZO just copy these files into your source directory, add minilzo.c to your Makefile and #include minilzo.h from your program. Note: you also must distribute this file ('README.LZO') with your project. minilzo.o compiles to about 6 KiB (using gcc or Visual C on an i386), and the sources are about 30 KiB when packed with zip - so there's no more excuse that your application doesn't support data compression :-) For more information, documentation, example programs and other support files (like Makefiles and build scripts) please download the full LZO package from http://www.oberhumer.com/opensource/lzo/ Have fun, Markus P.S. minilzo.c is generated automatically from the LZO sources and therefore functionality is completely identical Appendix A: building miniLZO ---------------------------- miniLZO is written such a way that it should compile and run out-of-the-box on most machines. If you are running on a very unusual architecture and lzo_init() fails then you should first recompile with '-DLZO_DEBUG' to see what causes the failure. The most probable case is something like 'sizeof(void *) != sizeof(size_t)'. After identifying the problem you can compile by adding some defines like '-DSIZEOF_VOID_P=8' to your Makefile. The best solution is (of course) using Autoconf - if your project uses Autoconf anyway just add '-DMINILZO_HAVE_CONFIG_H' to your compiler flags when compiling minilzo.c. See the LZO distribution for an example how to set up configure.ac. Appendix B: list of public functions available in miniLZO --------------------------------------------------------- Library initialization lzo_init() Compression lzo1x_1_compress() Decompression lzo1x_decompress() lzo1x_decompress_safe() Checksum functions lzo_adler32() Version functions lzo_version() lzo_version_string() lzo_version_date() Portable (but slow) string functions lzo_memcmp() lzo_memcpy() lzo_memmove() lzo_memset() Appendix C: suggested macros for 'configure.ac' when using Autoconf ------------------------------------------------------------------- Checks for typedefs and structures AC_CHECK_TYPE(ptrdiff_t,long) AC_TYPE_SIZE_T AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long long) AC_CHECK_SIZEOF(__int64) AC_CHECK_SIZEOF(void *) AC_CHECK_SIZEOF(size_t) AC_CHECK_SIZEOF(ptrdiff_t) Checks for compiler characteristics AC_C_CONST Checks for library functions AC_CHECK_FUNCS(memcmp memcpy memmove memset) Appendix D: Copyright --------------------- LZO and miniLZO are Copyright (C) 1996-2017 Markus Franz Xaver Oberhumer All Rights Reserved. LZO and miniLZO are distributed under the terms of the GNU General Public License (GPL). See the file COPYING. Special licenses for commercial and other applications which are not willing to accept the GNU General Public License are available by contacting the author. distcc-3.4/lzo/lzoconf.h000066400000000000000000000372061404653710500152750ustar00rootroot00000000000000/* lzoconf.h -- configuration of the LZO data compression library This file is part of the LZO real-time data compression library. Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ */ #ifndef __LZOCONF_H_INCLUDED #define __LZOCONF_H_INCLUDED 1 #define LZO_VERSION 0x20a0 /* 2.10 */ #define LZO_VERSION_STRING "2.10" #define LZO_VERSION_DATE "Mar 01 2017" /* internal Autoconf configuration file - only used when building LZO */ #if defined(LZO_HAVE_CONFIG_H) # include #endif #include #include /*********************************************************************** // LZO requires a conforming ************************************************************************/ #if !defined(CHAR_BIT) || (CHAR_BIT != 8) # error "invalid CHAR_BIT" #endif #if !defined(UCHAR_MAX) || !defined(USHRT_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) # error "check your compiler installation" #endif #if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) # error "your limits.h macros are broken" #endif /* get OS and architecture defines */ #ifndef __LZODEFS_H_INCLUDED #include #endif #ifdef __cplusplus extern "C" { #endif /*********************************************************************** // some core defines ************************************************************************/ /* memory checkers */ #if !defined(__LZO_CHECKER) # if defined(__BOUNDS_CHECKING_ON) # define __LZO_CHECKER 1 # elif defined(__CHECKER__) # define __LZO_CHECKER 1 # elif defined(__INSURE__) # define __LZO_CHECKER 1 # elif defined(__PURIFY__) # define __LZO_CHECKER 1 # endif #endif /*********************************************************************** // integral and pointer types ************************************************************************/ /* lzo_uint must match size_t */ #if !defined(LZO_UINT_MAX) # if (LZO_ABI_LLP64) # if (LZO_OS_WIN64) typedef unsigned __int64 lzo_uint; typedef __int64 lzo_int; # define LZO_TYPEOF_LZO_INT LZO_TYPEOF___INT64 # else typedef lzo_ullong_t lzo_uint; typedef lzo_llong_t lzo_int; # define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG_LONG # endif # define LZO_SIZEOF_LZO_INT 8 # define LZO_UINT_MAX 0xffffffffffffffffull # define LZO_INT_MAX 9223372036854775807LL # define LZO_INT_MIN (-1LL - LZO_INT_MAX) # elif (LZO_ABI_IP32L64) /* MIPS R5900 */ typedef unsigned int lzo_uint; typedef int lzo_int; # define LZO_SIZEOF_LZO_INT LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INT LZO_TYPEOF_INT # define LZO_UINT_MAX UINT_MAX # define LZO_INT_MAX INT_MAX # define LZO_INT_MIN INT_MIN # elif (ULONG_MAX >= LZO_0xffffffffL) typedef unsigned long lzo_uint; typedef long lzo_int; # define LZO_SIZEOF_LZO_INT LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG # define LZO_UINT_MAX ULONG_MAX # define LZO_INT_MAX LONG_MAX # define LZO_INT_MIN LONG_MIN # else # error "lzo_uint" # endif #endif /* The larger type of lzo_uint and lzo_uint32_t. */ #if (LZO_SIZEOF_LZO_INT >= 4) # define lzo_xint lzo_uint #else # define lzo_xint lzo_uint32_t #endif typedef int lzo_bool; /* sanity checks */ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int) == LZO_SIZEOF_LZO_INT) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_INT) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t)) #ifndef __LZO_MMODEL #define __LZO_MMODEL /*empty*/ #endif /* no typedef here because of const-pointer issues */ #define lzo_bytep unsigned char __LZO_MMODEL * #define lzo_charp char __LZO_MMODEL * #define lzo_voidp void __LZO_MMODEL * #define lzo_shortp short __LZO_MMODEL * #define lzo_ushortp unsigned short __LZO_MMODEL * #define lzo_intp lzo_int __LZO_MMODEL * #define lzo_uintp lzo_uint __LZO_MMODEL * #define lzo_xintp lzo_xint __LZO_MMODEL * #define lzo_voidpp lzo_voidp __LZO_MMODEL * #define lzo_bytepp lzo_bytep __LZO_MMODEL * #define lzo_int8_tp lzo_int8_t __LZO_MMODEL * #define lzo_uint8_tp lzo_uint8_t __LZO_MMODEL * #define lzo_int16_tp lzo_int16_t __LZO_MMODEL * #define lzo_uint16_tp lzo_uint16_t __LZO_MMODEL * #define lzo_int32_tp lzo_int32_t __LZO_MMODEL * #define lzo_uint32_tp lzo_uint32_t __LZO_MMODEL * #if defined(lzo_int64_t) #define lzo_int64_tp lzo_int64_t __LZO_MMODEL * #define lzo_uint64_tp lzo_uint64_t __LZO_MMODEL * #endif /* Older LZO versions used to support ancient systems and memory models * such as 16-bit MSDOS with __huge pointers or Cray PVP, but these * obsolete configurations are not supported any longer. */ #if defined(__LZO_MMODEL_HUGE) #error "__LZO_MMODEL_HUGE memory model is unsupported" #endif #if (LZO_MM_PVP) #error "LZO_MM_PVP memory model is unsupported" #endif #if (LZO_SIZEOF_INT < 4) #error "LZO_SIZEOF_INT < 4 is unsupported" #endif #if (__LZO_UINTPTR_T_IS_POINTER) #error "__LZO_UINTPTR_T_IS_POINTER is unsupported" #endif LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) >= 4) /* Strange configurations where sizeof(lzo_uint) != sizeof(size_t) should * work but have not received much testing lately, so be strict here. */ LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(size_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(ptrdiff_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(lzo_uintptr_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_uintptr_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_uintptr_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long *) == sizeof(lzo_uintptr_t)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_voidp)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep)) /*********************************************************************** // function types ************************************************************************/ /* name mangling */ #if !defined(__LZO_EXTERN_C) # ifdef __cplusplus # define __LZO_EXTERN_C extern "C" # else # define __LZO_EXTERN_C extern # endif #endif /* calling convention */ #if !defined(__LZO_CDECL) # define __LZO_CDECL __lzo_cdecl #endif /* DLL export information */ #if !defined(__LZO_EXPORT1) # define __LZO_EXPORT1 /*empty*/ #endif #if !defined(__LZO_EXPORT2) # define __LZO_EXPORT2 /*empty*/ #endif /* __cdecl calling convention for public C and assembly functions */ #if !defined(LZO_PUBLIC) # define LZO_PUBLIC(r) __LZO_EXPORT1 r __LZO_EXPORT2 __LZO_CDECL #endif #if !defined(LZO_EXTERN) # define LZO_EXTERN(r) __LZO_EXTERN_C LZO_PUBLIC(r) #endif #if !defined(LZO_PRIVATE) # define LZO_PRIVATE(r) static r __LZO_CDECL #endif /* function types */ typedef int (__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem ); typedef int (__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem ); typedef int (__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem ); typedef int (__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem, const lzo_bytep dict, lzo_uint dict_len ); typedef int (__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem, const lzo_bytep dict, lzo_uint dict_len ); /* Callback interface. Currently only the progress indicator ("nprogress") * is used, but this may change in a future release. */ struct lzo_callback_t; typedef struct lzo_callback_t lzo_callback_t; #define lzo_callback_p lzo_callback_t __LZO_MMODEL * /* malloc & free function types */ typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) (lzo_callback_p self, lzo_uint items, lzo_uint size); typedef void (__LZO_CDECL *lzo_free_func_t) (lzo_callback_p self, lzo_voidp ptr); /* a progress indicator callback function */ typedef void (__LZO_CDECL *lzo_progress_func_t) (lzo_callback_p, lzo_uint, lzo_uint, int); struct lzo_callback_t { /* custom allocators (set to 0 to disable) */ lzo_alloc_func_t nalloc; /* [not used right now] */ lzo_free_func_t nfree; /* [not used right now] */ /* a progress indicator callback function (set to 0 to disable) */ lzo_progress_func_t nprogress; /* INFO: the first parameter "self" of the nalloc/nfree/nprogress * callbacks points back to this struct, so you are free to store * some extra info in the following variables. */ lzo_voidp user1; lzo_xint user2; lzo_xint user3; }; /*********************************************************************** // error codes and prototypes ************************************************************************/ /* Error codes for the compression/decompression functions. Negative * values are errors, positive values will be used for special but * normal events. */ #define LZO_E_OK 0 #define LZO_E_ERROR (-1) #define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */ #define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ #define LZO_E_INPUT_OVERRUN (-4) #define LZO_E_OUTPUT_OVERRUN (-5) #define LZO_E_LOOKBEHIND_OVERRUN (-6) #define LZO_E_EOF_NOT_FOUND (-7) #define LZO_E_INPUT_NOT_CONSUMED (-8) #define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ #define LZO_E_INVALID_ARGUMENT (-10) #define LZO_E_INVALID_ALIGNMENT (-11) /* pointer argument is not properly aligned */ #define LZO_E_OUTPUT_NOT_CONSUMED (-12) #define LZO_E_INTERNAL_ERROR (-99) #ifndef lzo_sizeof_dict_t # define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) #endif /* lzo_init() should be the first function you call. * Check the return code ! * * lzo_init() is a macro to allow checking that the library and the * compiler's view of various types are consistent. */ #define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ (int)sizeof(long),(int)sizeof(lzo_uint32_t),(int)sizeof(lzo_uint),\ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ (int)sizeof(lzo_callback_t)) LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); /* version functions (useful for shared libraries) */ LZO_EXTERN(unsigned) lzo_version(void); LZO_EXTERN(const char *) lzo_version_string(void); LZO_EXTERN(const char *) lzo_version_date(void); LZO_EXTERN(const lzo_charp) _lzo_version_string(void); LZO_EXTERN(const lzo_charp) _lzo_version_date(void); /* string functions */ LZO_EXTERN(int) lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len); LZO_EXTERN(lzo_voidp) lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len); LZO_EXTERN(lzo_voidp) lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len); LZO_EXTERN(lzo_voidp) lzo_memset(lzo_voidp buf, int c, lzo_uint len); /* checksum functions */ LZO_EXTERN(lzo_uint32_t) lzo_adler32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); LZO_EXTERN(lzo_uint32_t) lzo_crc32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); LZO_EXTERN(const lzo_uint32_tp) lzo_get_crc32_table(void); /* misc. */ LZO_EXTERN(int) _lzo_config_check(void); typedef union { lzo_voidp a00; lzo_bytep a01; lzo_uint a02; lzo_xint a03; lzo_uintptr_t a04; void *a05; unsigned char *a06; unsigned long a07; size_t a08; ptrdiff_t a09; #if defined(lzo_int64_t) lzo_uint64_t a10; #endif } lzo_align_t; /* align a char pointer on a boundary that is a multiple of 'size' */ LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size); #define LZO_PTR_ALIGN_UP(p,size) \ ((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size))) /*********************************************************************** // deprecated macros - only for backward compatibility ************************************************************************/ /* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */ #define lzo_byte unsigned char /* deprecated type names */ #define lzo_int32 lzo_int32_t #define lzo_uint32 lzo_uint32_t #define lzo_int32p lzo_int32_t __LZO_MMODEL * #define lzo_uint32p lzo_uint32_t __LZO_MMODEL * #define LZO_INT32_MAX LZO_INT32_C(2147483647) #define LZO_UINT32_MAX LZO_UINT32_C(4294967295) #if defined(lzo_int64_t) #define lzo_int64 lzo_int64_t #define lzo_uint64 lzo_uint64_t #define lzo_int64p lzo_int64_t __LZO_MMODEL * #define lzo_uint64p lzo_uint64_t __LZO_MMODEL * #define LZO_INT64_MAX LZO_INT64_C(9223372036854775807) #define LZO_UINT64_MAX LZO_UINT64_C(18446744073709551615) #endif /* deprecated types */ typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u; typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u; /* deprecated defines */ #if !defined(LZO_SIZEOF_LZO_UINT) # define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LZO_INT #endif #if defined(LZO_CFG_COMPAT) #define __LZOCONF_H 1 #if defined(LZO_ARCH_I086) # define __LZO_i386 1 #elif defined(LZO_ARCH_I386) # define __LZO_i386 1 #endif #if defined(LZO_OS_DOS16) # define __LZO_DOS 1 # define __LZO_DOS16 1 #elif defined(LZO_OS_DOS32) # define __LZO_DOS 1 #elif defined(LZO_OS_WIN16) # define __LZO_WIN 1 # define __LZO_WIN16 1 #elif defined(LZO_OS_WIN32) # define __LZO_WIN 1 #endif #define __LZO_CMODEL /*empty*/ #define __LZO_DMODEL /*empty*/ #define __LZO_ENTRY __LZO_CDECL #define LZO_EXTERN_CDECL LZO_EXTERN #define LZO_ALIGN LZO_PTR_ALIGN_UP #define lzo_compress_asm_t lzo_compress_t #define lzo_decompress_asm_t lzo_decompress_t #endif /* LZO_CFG_COMPAT */ #ifdef __cplusplus } /* extern "C" */ #endif #endif /* already included */ /* vim:set ts=4 sw=4 et: */ distcc-3.4/lzo/lzodefs.h000066400000000000000000003704711404653710500152750ustar00rootroot00000000000000/* lzodefs.h -- architecture, OS and compiler specific defines This file is part of the LZO real-time data compression library. Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ */ #ifndef __LZODEFS_H_INCLUDED #define __LZODEFS_H_INCLUDED 1 #if defined(__CYGWIN32__) && !defined(__CYGWIN__) # define __CYGWIN__ __CYGWIN32__ #endif #if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) # define _ALL_SOURCE 1 #endif #if defined(__mips__) && defined(__R5900__) # if !defined(__LONG_MAX__) # define __LONG_MAX__ 9223372036854775807L # endif #endif #if 0 #elif !defined(__LZO_LANG_OVERRIDE) #if (defined(__clang__) || defined(__GNUC__)) && defined(__ASSEMBLER__) # if (__ASSEMBLER__+0) <= 0 # error "__ASSEMBLER__" # else # define LZO_LANG_ASSEMBLER 1 # endif #elif defined(__cplusplus) # if (__cplusplus+0) <= 0 # error "__cplusplus" # elif (__cplusplus < 199711L) # define LZO_LANG_CXX 1 # elif defined(_MSC_VER) && defined(_MSVC_LANG) && (_MSVC_LANG+0 >= 201402L) && 1 # define LZO_LANG_CXX _MSVC_LANG # else # define LZO_LANG_CXX __cplusplus # endif # define LZO_LANG_CPLUSPLUS LZO_LANG_CXX #else # if defined(__STDC_VERSION__) && (__STDC_VERSION__+0 >= 199409L) # define LZO_LANG_C __STDC_VERSION__ # else # define LZO_LANG_C 1 # endif #endif #endif #if !defined(LZO_CFG_NO_DISABLE_WUNDEF) #if defined(__ARMCC_VERSION) # pragma diag_suppress 193 #elif defined(__clang__) && defined(__clang_minor__) # pragma clang diagnostic ignored "-Wundef" #elif defined(__INTEL_COMPILER) # pragma warning(disable: 193) #elif defined(__KEIL__) && defined(__C166__) # pragma warning disable = 322 #elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) # if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) # pragma GCC diagnostic ignored "-Wundef" # endif #elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) # if ((_MSC_VER-0) >= 1300) # pragma warning(disable: 4668) # endif #endif #endif #if 0 && defined(__POCC__) && defined(_WIN32) # if (__POCC__ >= 400) # pragma warn(disable: 2216) # endif #endif #if 0 && defined(__WATCOMC__) # if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) # pragma warning 203 9 # endif #endif #if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) # pragma option -h #endif #if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) #ifndef _CRT_NONSTDC_NO_DEPRECATE #define _CRT_NONSTDC_NO_DEPRECATE 1 #endif #ifndef _CRT_NONSTDC_NO_WARNINGS #define _CRT_NONSTDC_NO_WARNINGS 1 #endif #ifndef _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE 1 #endif #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS 1 #endif #endif #if 0 #define LZO_0xffffUL 0xfffful #define LZO_0xffffffffUL 0xfffffffful #else #define LZO_0xffffUL 65535ul #define LZO_0xffffffffUL 4294967295ul #endif #define LZO_0xffffL LZO_0xffffUL #define LZO_0xffffffffL LZO_0xffffffffUL #if (LZO_0xffffL == LZO_0xffffffffL) # error "your preprocessor is broken 1" #endif #if (16ul * 16384ul != 262144ul) # error "your preprocessor is broken 2" #endif #if 0 #if (32767 >= 4294967295ul) # error "your preprocessor is broken 3" #endif #if (65535u >= 4294967295ul) # error "your preprocessor is broken 4" #endif #endif #if defined(__COUNTER__) # ifndef LZO_CFG_USE_COUNTER # define LZO_CFG_USE_COUNTER 1 # endif #else # undef LZO_CFG_USE_COUNTER #endif #if (UINT_MAX == LZO_0xffffL) #if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) # if !defined(MSDOS) # define MSDOS 1 # endif # if !defined(_MSDOS) # define _MSDOS 1 # endif #elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) # if (__VERSION == 520) && (MB_LEN_MAX == 1) # if !defined(__AZTEC_C__) # define __AZTEC_C__ __VERSION # endif # if !defined(__DOS__) # define __DOS__ 1 # endif # endif #endif #endif #if (UINT_MAX == LZO_0xffffL) #if defined(_MSC_VER) && defined(M_I86HM) # define ptrdiff_t long # define _PTRDIFF_T_DEFINED 1 #endif #endif #if (UINT_MAX == LZO_0xffffL) # undef __LZO_RENAME_A # undef __LZO_RENAME_B # if defined(__AZTEC_C__) && defined(__DOS__) # define __LZO_RENAME_A 1 # elif defined(_MSC_VER) && defined(MSDOS) # if (_MSC_VER < 600) # define __LZO_RENAME_A 1 # elif (_MSC_VER < 700) # define __LZO_RENAME_B 1 # endif # elif defined(__TSC__) && defined(__OS2__) # define __LZO_RENAME_A 1 # elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) # define __LZO_RENAME_A 1 # elif defined(__PACIFIC__) && defined(DOS) # if !defined(__far) # define __far far # endif # if !defined(__near) # define __near near # endif # endif # if defined(__LZO_RENAME_A) # if !defined(__cdecl) # define __cdecl cdecl # endif # if !defined(__far) # define __far far # endif # if !defined(__huge) # define __huge huge # endif # if !defined(__near) # define __near near # endif # if !defined(__pascal) # define __pascal pascal # endif # if !defined(__huge) # define __huge huge # endif # elif defined(__LZO_RENAME_B) # if !defined(__cdecl) # define __cdecl _cdecl # endif # if !defined(__far) # define __far _far # endif # if !defined(__huge) # define __huge _huge # endif # if !defined(__near) # define __near _near # endif # if !defined(__pascal) # define __pascal _pascal # endif # elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) # if !defined(__cdecl) # define __cdecl cdecl # endif # if !defined(__pascal) # define __pascal pascal # endif # endif # undef __LZO_RENAME_A # undef __LZO_RENAME_B #endif #if (UINT_MAX == LZO_0xffffL) #if defined(__AZTEC_C__) && defined(__DOS__) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 #elif defined(_MSC_VER) && defined(MSDOS) # if (_MSC_VER < 600) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 # endif # if (_MSC_VER < 700) # define LZO_BROKEN_INTEGRAL_PROMOTION 1 # define LZO_BROKEN_SIZEOF 1 # endif #elif defined(__PACIFIC__) && defined(DOS) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 #elif defined(__TURBOC__) && defined(__MSDOS__) # if (__TURBOC__ < 0x0150) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 # define LZO_BROKEN_INTEGRAL_PROMOTION 1 # endif # if (__TURBOC__ < 0x0200) # define LZO_BROKEN_SIZEOF 1 # endif # if (__TURBOC__ < 0x0400) && defined(__cplusplus) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # endif #elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # define LZO_BROKEN_SIZEOF 1 #endif #endif #if defined(__WATCOMC__) && (__WATCOMC__ < 900) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 #endif #if defined(_CRAY) && defined(_CRAY1) # define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 #endif #define LZO_PP_STRINGIZE(x) #x #define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) #define LZO_PP_CONCAT0() /*empty*/ #define LZO_PP_CONCAT1(a) a #define LZO_PP_CONCAT2(a,b) a ## b #define LZO_PP_CONCAT3(a,b,c) a ## b ## c #define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e #define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f #define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g #define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() #define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) #define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) #define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) #define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) #define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) #define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) #define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) #define LZO_PP_EMPTY /*empty*/ #define LZO_PP_EMPTY0() /*empty*/ #define LZO_PP_EMPTY1(a) /*empty*/ #define LZO_PP_EMPTY2(a,b) /*empty*/ #define LZO_PP_EMPTY3(a,b,c) /*empty*/ #define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ #define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ #define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ #define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ #if 1 #define LZO_CPP_STRINGIZE(x) #x #define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) #define LZO_CPP_CONCAT2(a,b) a ## b #define LZO_CPP_CONCAT3(a,b,c) a ## b ## c #define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e #define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f #define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g #define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) #define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) #define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) #define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) #define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) #define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) #endif #define __LZO_MASK_GEN(o,b) (((((o) << ((b)-((b)!=0))) - (o)) << 1) + (o)*((b)!=0)) #if 1 && defined(__cplusplus) # if !defined(__STDC_CONSTANT_MACROS) # define __STDC_CONSTANT_MACROS 1 # endif # if !defined(__STDC_LIMIT_MACROS) # define __STDC_LIMIT_MACROS 1 # endif #endif #if defined(__cplusplus) # define LZO_EXTERN_C extern "C" # define LZO_EXTERN_C_BEGIN extern "C" { # define LZO_EXTERN_C_END } #else # define LZO_EXTERN_C extern # define LZO_EXTERN_C_BEGIN /*empty*/ # define LZO_EXTERN_C_END /*empty*/ #endif #if !defined(__LZO_OS_OVERRIDE) #if (LZO_OS_FREESTANDING) # define LZO_INFO_OS "freestanding" #elif (LZO_OS_EMBEDDED) # define LZO_INFO_OS "embedded" #elif 1 && defined(__IAR_SYSTEMS_ICC__) # define LZO_OS_EMBEDDED 1 # define LZO_INFO_OS "embedded" #elif defined(__CYGWIN__) && defined(__GNUC__) # define LZO_OS_CYGWIN 1 # define LZO_INFO_OS "cygwin" #elif defined(__EMX__) && defined(__GNUC__) # define LZO_OS_EMX 1 # define LZO_INFO_OS "emx" #elif defined(__BEOS__) # define LZO_OS_BEOS 1 # define LZO_INFO_OS "beos" #elif defined(__Lynx__) # define LZO_OS_LYNXOS 1 # define LZO_INFO_OS "lynxos" #elif defined(__OS400__) # define LZO_OS_OS400 1 # define LZO_INFO_OS "os400" #elif defined(__QNX__) # define LZO_OS_QNX 1 # define LZO_INFO_OS "qnx" #elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" #elif defined(__BORLANDC__) && defined(__DPMI16__) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" #elif defined(__ZTC__) && defined(DOS386) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" #elif defined(__OS2__) || defined(__OS2V2__) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_OS216 1 # define LZO_INFO_OS "os216" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_OS2 1 # define LZO_INFO_OS "os2" # else # error "check your limits.h header" # endif #elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) # define LZO_OS_WIN64 1 # define LZO_INFO_OS "win64" #elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" #elif defined(__MWERKS__) && defined(__INTEL__) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" #elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_WIN16 1 # define LZO_INFO_OS "win16" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" # else # error "check your limits.h header" # endif #elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" # else # error "check your limits.h header" # endif #elif defined(__WATCOMC__) # if defined(__NT__) && (UINT_MAX == LZO_0xffffL) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" # elif defined(__NT__) && (__WATCOMC__ < 1100) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" # elif defined(__linux__) || defined(__LINUX__) # define LZO_OS_POSIX 1 # define LZO_INFO_OS "posix" # else # error "please specify a target using the -bt compiler option" # endif #elif defined(__palmos__) # define LZO_OS_PALMOS 1 # define LZO_INFO_OS "palmos" #elif defined(__TOS__) || defined(__atarist__) # define LZO_OS_TOS 1 # define LZO_INFO_OS "tos" #elif defined(macintosh) && !defined(__arm__) && !defined(__i386__) && !defined(__ppc__) && !defined(__x64_64__) # define LZO_OS_MACCLASSIC 1 # define LZO_INFO_OS "macclassic" #elif defined(__VMS) # define LZO_OS_VMS 1 # define LZO_INFO_OS "vms" #elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PS2 1 # define LZO_INFO_OS "console" # define LZO_INFO_OS_CONSOLE "ps2" #elif defined(__mips__) && defined(__psp__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PSP 1 # define LZO_INFO_OS "console" # define LZO_INFO_OS_CONSOLE "psp" #else # define LZO_OS_POSIX 1 # define LZO_INFO_OS "posix" #endif #if (LZO_OS_POSIX) # if defined(_AIX) || defined(__AIX__) || defined(__aix__) # define LZO_OS_POSIX_AIX 1 # define LZO_INFO_OS_POSIX "aix" # elif defined(__FreeBSD__) # define LZO_OS_POSIX_FREEBSD 1 # define LZO_INFO_OS_POSIX "freebsd" # elif defined(__hpux__) || defined(__hpux) # define LZO_OS_POSIX_HPUX 1 # define LZO_INFO_OS_POSIX "hpux" # elif defined(__INTERIX) # define LZO_OS_POSIX_INTERIX 1 # define LZO_INFO_OS_POSIX "interix" # elif defined(__IRIX__) || defined(__irix__) # define LZO_OS_POSIX_IRIX 1 # define LZO_INFO_OS_POSIX "irix" # elif defined(__linux__) || defined(__linux) || defined(__LINUX__) # define LZO_OS_POSIX_LINUX 1 # define LZO_INFO_OS_POSIX "linux" # elif defined(__APPLE__) && defined(__MACH__) # if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) # define LZO_OS_POSIX_DARWIN 1040 # define LZO_INFO_OS_POSIX "darwin_iphone" # elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) # define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ # define LZO_INFO_OS_POSIX "darwin" # else # define LZO_OS_POSIX_DARWIN 1 # define LZO_INFO_OS_POSIX "darwin" # endif # define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN # elif defined(__minix__) || defined(__minix) # define LZO_OS_POSIX_MINIX 1 # define LZO_INFO_OS_POSIX "minix" # elif defined(__NetBSD__) # define LZO_OS_POSIX_NETBSD 1 # define LZO_INFO_OS_POSIX "netbsd" # elif defined(__OpenBSD__) # define LZO_OS_POSIX_OPENBSD 1 # define LZO_INFO_OS_POSIX "openbsd" # elif defined(__osf__) # define LZO_OS_POSIX_OSF 1 # define LZO_INFO_OS_POSIX "osf" # elif defined(__solaris__) || defined(__sun) # if defined(__SVR4) || defined(__svr4__) # define LZO_OS_POSIX_SOLARIS 1 # define LZO_INFO_OS_POSIX "solaris" # else # define LZO_OS_POSIX_SUNOS 1 # define LZO_INFO_OS_POSIX "sunos" # endif # elif defined(__ultrix__) || defined(__ultrix) # define LZO_OS_POSIX_ULTRIX 1 # define LZO_INFO_OS_POSIX "ultrix" # elif defined(_UNICOS) # define LZO_OS_POSIX_UNICOS 1 # define LZO_INFO_OS_POSIX "unicos" # else # define LZO_OS_POSIX_UNKNOWN 1 # define LZO_INFO_OS_POSIX "unknown" # endif #endif #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) # if (UINT_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) # define LZO_CC_CILLY 1 # define LZO_INFO_CC "Cilly" # if defined(__CILLY__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) # else # define LZO_INFO_CCVER "unknown" # endif #elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) # define LZO_CC_SDCC 1 # define LZO_INFO_CC "sdcc" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) #elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) # define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) # define LZO_INFO_CC "Pathscale C" # define LZO_INFO_CCVER __PATHSCALE__ # if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) # define LZO_CC_INTELC __INTEL_COMPILER # define LZO_INFO_CC "Intel C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_INTELC_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__POCC__) && defined(_WIN32) # define LZO_CC_PELLESC 1 # define LZO_INFO_CC "Pelles C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) #elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) # define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else # define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif # define LZO_CC_ARMCC __ARMCC_VERSION # define LZO_INFO_CC "ARM C Compiler" # define LZO_INFO_CCVER __VERSION__ #elif defined(__clang__) && defined(__c2__) && defined(__c2_version__) && defined(_MSC_VER) # define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) # define LZO_CC_CLANG_C2 _MSC_VER # define LZO_CC_CLANG_VENDOR_MICROSOFT 1 # define LZO_INFO_CC "clang/c2" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__c2_version__) #elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) # if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) # define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) # else # define LZO_CC_CLANG 0x010000L # endif # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_CLANG_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif # if defined(__APPLE_CC__) # define LZO_CC_CLANG_VENDOR_APPLE 1 # define LZO_INFO_CC "clang/apple" # else # define LZO_CC_CLANG_VENDOR_LLVM 1 # define LZO_INFO_CC "clang" # endif # if defined(__clang_version__) # define LZO_INFO_CCVER __clang_version__ # else # define LZO_INFO_CCVER __VERSION__ # endif #elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) # define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else # define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif # define LZO_CC_LLVM LZO_CC_LLVM_GNUC # define LZO_INFO_CC "llvm-gcc" # define LZO_INFO_CCVER __VERSION__ #elif defined(__ACK__) && defined(_ACK) # define LZO_CC_ACK 1 # define LZO_INFO_CC "Amsterdam Compiler Kit C" # define LZO_INFO_CCVER "unknown" #elif defined(__ARMCC_VERSION) && !defined(__GNUC__) # define LZO_CC_ARMCC __ARMCC_VERSION # define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION # define LZO_INFO_CC "ARM C Compiler" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) #elif defined(__AZTEC_C__) # define LZO_CC_AZTECC 1 # define LZO_INFO_CC "Aztec C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) #elif defined(__CODEGEARC__) # define LZO_CC_CODEGEARC 1 # define LZO_INFO_CC "CodeGear C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) #elif defined(__BORLANDC__) # define LZO_CC_BORLANDC 1 # define LZO_INFO_CC "Borland C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) #elif defined(_CRAYC) && defined(_RELEASE) # define LZO_CC_CRAYC 1 # define LZO_INFO_CC "Cray C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) #elif defined(__DMC__) && defined(__SC__) # define LZO_CC_DMC 1 # define LZO_INFO_CC "Digital Mars C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) #elif defined(__DECC) # define LZO_CC_DECC 1 # define LZO_INFO_CC "DEC C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) #elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) # define LZO_CC_GHS 1 # define LZO_INFO_CC "Green Hills C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_GHS_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__HIGHC__) # define LZO_CC_HIGHC 1 # define LZO_INFO_CC "MetaWare High C" # define LZO_INFO_CCVER "unknown" #elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) # define LZO_CC_HPACC __HP_aCC # define LZO_INFO_CC "HP aCC" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) #elif defined(__IAR_SYSTEMS_ICC__) # define LZO_CC_IARC 1 # define LZO_INFO_CC "IAR C" # if defined(__VER__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) # else # define LZO_INFO_CCVER "unknown" # endif #elif defined(__IBMC__) && ((__IBMC__-0) > 0) # define LZO_CC_IBMC __IBMC__ # define LZO_INFO_CC "IBM C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) #elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) # define LZO_CC_IBMC __IBMCPP__ # define LZO_INFO_CC "IBM C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) #elif defined(__KEIL__) && defined(__C166__) # define LZO_CC_KEILC 1 # define LZO_INFO_CC "Keil C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) #elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) # define LZO_CC_LCCWIN32 1 # define LZO_INFO_CC "lcc-win32" # define LZO_INFO_CCVER "unknown" #elif defined(__LCC__) # define LZO_CC_LCC 1 # define LZO_INFO_CC "lcc" # if defined(__LCC_VERSION__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) # else # define LZO_INFO_CCVER "unknown" # endif #elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) # define LZO_CC_MWERKS __MWERKS__ # define LZO_INFO_CC "Metrowerks C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) #elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) # define LZO_CC_NDPC 1 # define LZO_INFO_CC "Microway NDP C" # define LZO_INFO_CCVER "unknown" #elif defined(__PACIFIC__) # define LZO_CC_PACIFICC 1 # define LZO_INFO_CC "Pacific C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) #elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) # if defined(__PGIC_PATCHLEVEL__) # define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) # else # define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" # endif # define LZO_INFO_CC "Portland Group PGI C" #elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) # define LZO_CC_PGI 1 # define LZO_INFO_CC "Portland Group PGI C" # define LZO_INFO_CCVER "unknown" #elif defined(__PUREC__) && defined(__TOS__) # define LZO_CC_PUREC 1 # define LZO_INFO_CC "Pure C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) #elif defined(__SC__) && defined(__ZTC__) # define LZO_CC_SYMANTECC 1 # define LZO_INFO_CC "Symantec C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) #elif defined(__SUNPRO_C) # define LZO_INFO_CC "SunPro C" # if ((__SUNPRO_C-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_C # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) # else # define LZO_CC_SUNPROC 1 # define LZO_INFO_CCVER "unknown" # endif #elif defined(__SUNPRO_CC) # define LZO_INFO_CC "SunPro C" # if ((__SUNPRO_CC-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_CC # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) # else # define LZO_CC_SUNPROC 1 # define LZO_INFO_CCVER "unknown" # endif #elif defined(__TINYC__) # define LZO_CC_TINYC 1 # define LZO_INFO_CC "Tiny C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) #elif defined(__TSC__) # define LZO_CC_TOPSPEEDC 1 # define LZO_INFO_CC "TopSpeed C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) #elif defined(__WATCOMC__) # define LZO_CC_WATCOMC 1 # define LZO_INFO_CC "Watcom C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) #elif defined(__TURBOC__) # define LZO_CC_TURBOC 1 # define LZO_INFO_CC "Turbo C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) #elif defined(__ZTC__) # define LZO_CC_ZORTECHC 1 # define LZO_INFO_CC "Zortech C" # if ((__ZTC__-0) == 0x310) # define LZO_INFO_CCVER "0x310" # else # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) # endif #elif defined(__GNUC__) && defined(__VERSION__) # if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) # define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # elif defined(__GNUC_MINOR__) # define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # else # define LZO_CC_GNUC (__GNUC__ * 0x10000L) # endif # define LZO_INFO_CC "gcc" # define LZO_INFO_CCVER __VERSION__ #elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_MSC _MSC_VER # define LZO_INFO_CC "Microsoft C" # if defined(_MSC_FULL_VER) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) # else # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) # endif #else # define LZO_CC_UNKNOWN 1 # define LZO_INFO_CC "unknown" # define LZO_INFO_CCVER "unknown" #endif #if (LZO_CC_GNUC) && defined(__OPEN64__) # if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) # define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) # define LZO_CC_OPEN64_GNUC LZO_CC_GNUC # endif #endif #if (LZO_CC_GNUC) && defined(__PCC__) # if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) # define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) # define LZO_CC_PCC_GNUC LZO_CC_GNUC # endif #endif #if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) # error "LZO_CC_MSC: _MSC_FULL_VER is not defined" #endif #if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) # if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) # if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) # define LZO_ARCH_CRAY_MPP 1 # elif defined(_CRAY1) # define LZO_ARCH_CRAY_PVP 1 # endif # endif #endif #if !defined(__LZO_ARCH_OVERRIDE) #if (LZO_ARCH_GENERIC) # define LZO_INFO_ARCH "generic" #elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086 1 # define LZO_INFO_ARCH "i086" #elif defined(__aarch64__) || defined(_M_ARM64) # define LZO_ARCH_ARM64 1 # define LZO_INFO_ARCH "arm64" #elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) # define LZO_ARCH_ALPHA 1 # define LZO_INFO_ARCH "alpha" #elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) # define LZO_ARCH_ALPHA 1 # define LZO_INFO_ARCH "alpha" #elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) # define LZO_ARCH_AMD64 1 # define LZO_INFO_ARCH "amd64" #elif defined(__arm__) || defined(_M_ARM) # define LZO_ARCH_ARM 1 # define LZO_INFO_ARCH "arm" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) # define LZO_ARCH_ARM 1 # define LZO_INFO_ARCH "arm" #elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) # define LZO_ARCH_AVR 1 # define LZO_INFO_ARCH "avr" #elif defined(__avr32__) || defined(__AVR32__) # define LZO_ARCH_AVR32 1 # define LZO_INFO_ARCH "avr32" #elif defined(__bfin__) # define LZO_ARCH_BLACKFIN 1 # define LZO_INFO_ARCH "blackfin" #elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) # define LZO_ARCH_C166 1 # define LZO_INFO_ARCH "c166" #elif defined(__cris__) # define LZO_ARCH_CRIS 1 # define LZO_INFO_ARCH "cris" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) # define LZO_ARCH_EZ80 1 # define LZO_INFO_ARCH "ez80" #elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) # define LZO_ARCH_H8300 1 # define LZO_INFO_ARCH "h8300" #elif defined(__hppa__) || defined(__hppa) # define LZO_ARCH_HPPA 1 # define LZO_INFO_ARCH "hppa" #elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif (LZO_CC_ZORTECHC && defined(__I86__)) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) # define LZO_ARCH_IA64 1 # define LZO_INFO_ARCH "ia64" #elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) # define LZO_ARCH_M16C 1 # define LZO_INFO_ARCH "m16c" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) # define LZO_ARCH_M16C 1 # define LZO_INFO_ARCH "m16c" #elif defined(__m32r__) # define LZO_ARCH_M32R 1 # define LZO_INFO_ARCH "m32r" #elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) # define LZO_ARCH_M68K 1 # define LZO_INFO_ARCH "m68k" #elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) # define LZO_ARCH_MCS251 1 # define LZO_INFO_ARCH "mcs251" #elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) # define LZO_ARCH_MCS51 1 # define LZO_INFO_ARCH "mcs51" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) # define LZO_ARCH_MCS51 1 # define LZO_INFO_ARCH "mcs51" #elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) # define LZO_ARCH_MIPS 1 # define LZO_INFO_ARCH "mips" #elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) # define LZO_ARCH_MSP430 1 # define LZO_INFO_ARCH "msp430" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) # define LZO_ARCH_MSP430 1 # define LZO_INFO_ARCH "msp430" #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__powerpc64__) || defined(__powerpc64) || defined(__ppc64__) || defined(__PPC64__) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__powerpc64le__) || defined(__powerpc64le) || defined(__ppc64le__) || defined(__PPC64LE__) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__riscv) # define LZO_ARCH_RISCV 1 # define LZO_INFO_ARCH "riscv" #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) # define LZO_ARCH_S390 1 # define LZO_INFO_ARCH "s390" #elif defined(__sh__) || defined(_M_SH) # define LZO_ARCH_SH 1 # define LZO_INFO_ARCH "sh" #elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) # define LZO_ARCH_SPARC 1 # define LZO_INFO_ARCH "sparc" #elif defined(__SPU__) # define LZO_ARCH_SPU 1 # define LZO_INFO_ARCH "spu" #elif (UINT_MAX == LZO_0xffffL) && defined(__z80) # define LZO_ARCH_Z80 1 # define LZO_INFO_ARCH "z80" #elif (LZO_ARCH_CRAY_PVP) # if defined(_CRAYSV1) # define LZO_ARCH_CRAY_SV1 1 # define LZO_INFO_ARCH "cray_sv1" # elif (_ADDR64) # define LZO_ARCH_CRAY_T90 1 # define LZO_INFO_ARCH "cray_t90" # elif (_ADDR32) # define LZO_ARCH_CRAY_YMP 1 # define LZO_INFO_ARCH "cray_ymp" # else # define LZO_ARCH_CRAY_XMP 1 # define LZO_INFO_ARCH "cray_xmp" # endif #else # define LZO_ARCH_UNKNOWN 1 # define LZO_INFO_ARCH "unknown" #endif #endif #if !defined(LZO_ARCH_ARM_THUMB2) #if (LZO_ARCH_ARM) # if defined(__thumb__) || defined(__thumb) || defined(_M_THUMB) # if defined(__thumb2__) # define LZO_ARCH_ARM_THUMB2 1 # elif 1 && defined(__TARGET_ARCH_THUMB) && ((__TARGET_ARCH_THUMB)+0 >= 4) # define LZO_ARCH_ARM_THUMB2 1 # elif 1 && defined(_MSC_VER) && defined(_M_THUMB) && ((_M_THUMB)+0 >= 7) # define LZO_ARCH_ARM_THUMB2 1 # endif # endif #endif #endif #if (LZO_ARCH_ARM_THUMB2) # undef LZO_INFO_ARCH # define LZO_INFO_ARCH "arm_thumb2" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) # error "FIXME - missing define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) # error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) # error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" #endif #if (LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && defined(BLX286)) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) # define LZO_ARCH_I086PM 1 #endif #if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) # define LZO_ARCH_X64 1 #elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_AMD64 1 #endif #if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) # define LZO_ARCH_AARCH64 1 #elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_ARM64 1 #endif #if (LZO_ARCH_I386 && !LZO_ARCH_X86) # define LZO_ARCH_X86 1 #elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_I386 1 #endif #if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I086PM && !LZO_ARCH_I086) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I086) # if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_ARCH_I386) # if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) # error "unexpected configuration - check your compiler defines" # endif # if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_ARCH_AMD64 || LZO_ARCH_I386) # if !defined(LZO_TARGET_FEATURE_SSE2) # if defined(__SSE2__) # define LZO_TARGET_FEATURE_SSE2 1 # elif defined(_MSC_VER) && (defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) # define LZO_TARGET_FEATURE_SSE2 1 # elif (LZO_CC_INTELC_MSC || LZO_CC_MSC) && defined(_M_AMD64) # define LZO_TARGET_FEATURE_SSE2 1 # endif # endif # if !defined(LZO_TARGET_FEATURE_SSSE3) # if (LZO_TARGET_FEATURE_SSE2) # if defined(__SSSE3__) # define LZO_TARGET_FEATURE_SSSE3 1 # elif defined(_MSC_VER) && defined(__AVX__) # define LZO_TARGET_FEATURE_SSSE3 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_SSE4_2) # if (LZO_TARGET_FEATURE_SSSE3) # if defined(__SSE4_2__) # define LZO_TARGET_FEATURE_SSE4_2 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_AVX) # if (LZO_TARGET_FEATURE_SSSE3) # if defined(__AVX__) # define LZO_TARGET_FEATURE_AVX 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_AVX2) # if (LZO_TARGET_FEATURE_AVX) # if defined(__AVX2__) # define LZO_TARGET_FEATURE_AVX2 1 # endif # endif # endif #endif #if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM) # if !defined(LZO_TARGET_FEATURE_NEON) # if defined(__ARM_NEON) && ((__ARM_NEON)+0) # define LZO_TARGET_FEATURE_NEON 1 # elif 1 && defined(__ARM_NEON__) && ((__ARM_NEON__)+0) # define LZO_TARGET_FEATURE_NEON 1 # elif 1 && defined(__TARGET_FEATURE_NEON) && ((__TARGET_FEATURE_NEON)+0) # define LZO_TARGET_FEATURE_NEON 1 # endif # endif #elif (LZO_ARCH_ARM64) # if !defined(LZO_TARGET_FEATURE_NEON) # if 1 # define LZO_TARGET_FEATURE_NEON 1 # endif # endif #endif #if 0 #elif !defined(__LZO_MM_OVERRIDE) #if (LZO_ARCH_I086) #if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" #endif #if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) # define LZO_MM_TINY 1 #elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) # define LZO_MM_HUGE 1 #elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) # define LZO_MM_SMALL 1 #elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) # define LZO_MM_MEDIUM 1 #elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) # define LZO_MM_COMPACT 1 #elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) # define LZO_MM_LARGE 1 #elif (LZO_CC_AZTECC) # if defined(_LARGE_CODE) && defined(_LARGE_DATA) # define LZO_MM_LARGE 1 # elif defined(_LARGE_CODE) # define LZO_MM_MEDIUM 1 # elif defined(_LARGE_DATA) # define LZO_MM_COMPACT 1 # else # define LZO_MM_SMALL 1 # endif #elif (LZO_CC_ZORTECHC && defined(__VCM__)) # define LZO_MM_LARGE 1 #else # error "unknown LZO_ARCH_I086 memory model" #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) #define LZO_HAVE_MM_HUGE_PTR 1 #define LZO_HAVE_MM_HUGE_ARRAY 1 #if (LZO_MM_TINY) # undef LZO_HAVE_MM_HUGE_ARRAY #endif #if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) # undef LZO_HAVE_MM_HUGE_PTR # undef LZO_HAVE_MM_HUGE_ARRAY #elif (LZO_CC_DMC || LZO_CC_SYMANTECC) # undef LZO_HAVE_MM_HUGE_ARRAY #elif (LZO_CC_MSC && defined(_QC)) # undef LZO_HAVE_MM_HUGE_ARRAY # if (_MSC_VER < 600) # undef LZO_HAVE_MM_HUGE_PTR # endif #elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) # undef LZO_HAVE_MM_HUGE_ARRAY #endif #if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) # if (LZO_OS_DOS16) # error "unexpected configuration - check your compiler defines" # elif (LZO_CC_ZORTECHC) # else # error "unexpected configuration - check your compiler defines" # endif #endif #if defined(__cplusplus) extern "C" { #endif #if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) # define LZO_MM_AHSHIFT 12 #elif (LZO_CC_WATCOMC) extern unsigned char _HShift; # define LZO_MM_AHSHIFT ((unsigned) _HShift) #else # error "FIXME - implement LZO_MM_AHSHIFT" #endif #if defined(__cplusplus) } #endif #endif #elif (LZO_ARCH_C166) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_C166 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 1) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_C166 __MODEL__" #endif #elif (LZO_ARCH_MCS251) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_MCS251 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_MCS251 __MODEL__" #endif #elif (LZO_ARCH_MCS51) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_MCS51 __MODEL__" #elif ((__MODEL__) == 1) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_MCS51 __MODEL__" #endif #elif (LZO_ARCH_CRAY_PVP) # define LZO_MM_PVP 1 #else # define LZO_MM_FLAT 1 #endif #if (LZO_MM_COMPACT) # define LZO_INFO_MM "compact" #elif (LZO_MM_FLAT) # define LZO_INFO_MM "flat" #elif (LZO_MM_HUGE) # define LZO_INFO_MM "huge" #elif (LZO_MM_LARGE) # define LZO_INFO_MM "large" #elif (LZO_MM_MEDIUM) # define LZO_INFO_MM "medium" #elif (LZO_MM_PVP) # define LZO_INFO_MM "pvp" #elif (LZO_MM_SMALL) # define LZO_INFO_MM "small" #elif (LZO_MM_TINY) # define LZO_INFO_MM "tiny" #else # error "unknown memory model" #endif #endif #if !defined(__lzo_gnuc_extension__) #if (LZO_CC_GNUC >= 0x020800ul) # define __lzo_gnuc_extension__ __extension__ #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_gnuc_extension__ __extension__ #elif (LZO_CC_IBMC >= 600) # define __lzo_gnuc_extension__ __extension__ #endif #endif #if !defined(__lzo_gnuc_extension__) # define __lzo_gnuc_extension__ /*empty*/ #endif #if !defined(lzo_has_builtin) #if (LZO_CC_CLANG) && defined(__has_builtin) # define lzo_has_builtin __has_builtin #endif #endif #if !defined(lzo_has_builtin) # define lzo_has_builtin(x) 0 #endif #if !defined(lzo_has_attribute) #if (LZO_CC_CLANG) && defined(__has_attribute) # define lzo_has_attribute __has_attribute #endif #endif #if !defined(lzo_has_attribute) # define lzo_has_attribute(x) 0 #endif #if !defined(lzo_has_declspec_attribute) #if (LZO_CC_CLANG) && defined(__has_declspec_attribute) # define lzo_has_declspec_attribute __has_declspec_attribute #endif #endif #if !defined(lzo_has_declspec_attribute) # define lzo_has_declspec_attribute(x) 0 #endif #if !defined(lzo_has_feature) #if (LZO_CC_CLANG) && defined(__has_feature) # define lzo_has_feature __has_feature #endif #endif #if !defined(lzo_has_feature) # define lzo_has_feature(x) 0 #endif #if !defined(lzo_has_extension) #if (LZO_CC_CLANG) && defined(__has_extension) # define lzo_has_extension __has_extension #elif (LZO_CC_CLANG) && defined(__has_feature) # define lzo_has_extension __has_feature #endif #endif #if !defined(lzo_has_extension) # define lzo_has_extension(x) 0 #endif #if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 # elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 # else # define LZO_CFG_USE_NEW_STYLE_CASTS 1 # endif #endif #if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 #endif #if !defined(__cplusplus) # if defined(LZO_CFG_USE_NEW_STYLE_CASTS) # undef LZO_CFG_USE_NEW_STYLE_CASTS # endif # define LZO_CFG_USE_NEW_STYLE_CASTS 0 #endif #if !defined(LZO_REINTERPRET_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast (e)) # endif #endif #if !defined(LZO_REINTERPRET_CAST) # define LZO_REINTERPRET_CAST(t,e) ((t) (e)) #endif #if !defined(LZO_STATIC_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_STATIC_CAST(t,e) (static_cast (e)) # endif #endif #if !defined(LZO_STATIC_CAST) # define LZO_STATIC_CAST(t,e) ((t) (e)) #endif #if !defined(LZO_STATIC_CAST2) # define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) #endif #if !defined(LZO_UNCONST_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNCONST_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNCONST_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) # endif #endif #if !defined(LZO_UNCONST_CAST) # define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) #endif #if !defined(LZO_UNCONST_VOLATILE_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) # endif #endif #if !defined(LZO_UNCONST_VOLATILE_CAST) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) #endif #if !defined(LZO_UNVOLATILE_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNVOLATILE_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) # endif #endif #if !defined(LZO_UNVOLATILE_CAST) # define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) #endif #if !defined(LZO_UNVOLATILE_CONST_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) # endif #endif #if !defined(LZO_UNVOLATILE_CONST_CAST) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) #endif #if !defined(LZO_PCAST) # if (LZO_HAVE_MM_HUGE_PTR) # define LZO_PCAST(t,e) ((t) (e)) # endif #endif #if !defined(LZO_PCAST) # define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) #endif #if !defined(LZO_CCAST) # if (LZO_HAVE_MM_HUGE_PTR) # define LZO_CCAST(t,e) ((t) (e)) # endif #endif #if !defined(LZO_CCAST) # define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) #endif #if !defined(LZO_ICONV) # define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(LZO_ICAST) # define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(LZO_ITRUNC) # define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(__lzo_cte) # if (LZO_CC_MSC || LZO_CC_WATCOMC) # define __lzo_cte(e) ((void)0,(e)) # elif 1 # define __lzo_cte(e) ((void)0,(e)) # endif #endif #if !defined(__lzo_cte) # define __lzo_cte(e) (e) #endif #if !defined(LZO_BLOCK_BEGIN) # define LZO_BLOCK_BEGIN do { # define LZO_BLOCK_END } while __lzo_cte(0) #endif #if !defined(LZO_UNUSED) # if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) # define LZO_UNUSED(var) ((void) &var) # elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) # define LZO_UNUSED(var) if (&var) ; else # elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) # define LZO_UNUSED(var) ((void) &var) # elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNUSED(var) ((void) var) # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_UNUSED(var) if (&var) ; else # elif (LZO_CC_KEILC) # define LZO_UNUSED(var) {extern int lzo_unused__[1-2*!(sizeof(var)>0)]; (void)lzo_unused__;} # elif (LZO_CC_PACIFICC) # define LZO_UNUSED(var) ((void) sizeof(var)) # elif (LZO_CC_WATCOMC) && defined(__cplusplus) # define LZO_UNUSED(var) ((void) var) # else # define LZO_UNUSED(var) ((void) &var) # endif #endif #if !defined(LZO_UNUSED_RESULT) # define LZO_UNUSED_RESULT(var) LZO_UNUSED(var) #endif #if !defined(LZO_UNUSED_FUNC) # if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) # define LZO_UNUSED_FUNC(func) ((void) func) # elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) # define LZO_UNUSED_FUNC(func) if (func) ; else # elif (LZO_CC_CLANG || LZO_CC_LLVM) # define LZO_UNUSED_FUNC(func) ((void) &func) # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_UNUSED_FUNC(func) if (func) ; else # elif (LZO_CC_MSC) # define LZO_UNUSED_FUNC(func) ((void) &func) # elif (LZO_CC_KEILC || LZO_CC_PELLESC) # define LZO_UNUSED_FUNC(func) {extern int lzo_unused__[1-2*!(sizeof((int)func)>0)]; (void)lzo_unused__;} # else # define LZO_UNUSED_FUNC(func) ((void) func) # endif #endif #if !defined(LZO_UNUSED_LABEL) # if (LZO_CC_CLANG >= 0x020800ul) # define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) # elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) # define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l # else # define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l # endif #endif #if !defined(LZO_DEFINE_UNINITIALIZED_VAR) # if 0 # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var # elif 0 && (LZO_CC_GNUC) # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var # else # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init # endif #endif #if !defined(__lzo_inline) #if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) #elif defined(__cplusplus) # define __lzo_inline inline #elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) # define __lzo_inline inline #elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) # define __lzo_inline __inline #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define __lzo_inline __inline__ #elif (LZO_CC_DMC) # define __lzo_inline __inline #elif (LZO_CC_GHS) # define __lzo_inline __inline__ #elif (LZO_CC_IBMC >= 600) # define __lzo_inline __inline__ #elif (LZO_CC_INTELC) # define __lzo_inline __inline #elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) # define __lzo_inline __inline #elif (LZO_CC_MSC && (_MSC_VER >= 900)) # define __lzo_inline __inline #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_inline __inline__ #endif #endif #if defined(__lzo_inline) # ifndef __lzo_HAVE_inline # define __lzo_HAVE_inline 1 # endif #else # define __lzo_inline /*empty*/ #endif #if !defined(__lzo_forceinline) #if (LZO_CC_GNUC >= 0x030200ul) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) # define __lzo_forceinline __forceinline #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) # define __lzo_forceinline __forceinline #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #endif #endif #if defined(__lzo_forceinline) # ifndef __lzo_HAVE_forceinline # define __lzo_HAVE_forceinline 1 # endif #else # define __lzo_forceinline __lzo_inline #endif #if !defined(__lzo_noinline) #if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) # define __lzo_noinline __attribute__((__noinline__,__used__)) #elif (LZO_CC_GNUC >= 0x030200ul) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) # define __lzo_noinline __declspec(noinline) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_noinline __declspec(noinline) #elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) # if defined(__cplusplus) # else # define __lzo_noinline __declspec(noinline) # endif #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_noinline __attribute__((__noinline__)) #endif #endif #if defined(__lzo_noinline) # ifndef __lzo_HAVE_noinline # define __lzo_HAVE_noinline 1 # endif #else # define __lzo_noinline /*empty*/ #endif #if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) # error "unexpected configuration - check your compiler defines" #endif #if !defined(__lzo_static_inline) #if (LZO_CC_IBMC) # define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline #endif #endif #if !defined(__lzo_static_inline) # define __lzo_static_inline static __lzo_inline #endif #if !defined(__lzo_static_forceinline) #if (LZO_CC_IBMC) # define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline #endif #endif #if !defined(__lzo_static_forceinline) # define __lzo_static_forceinline static __lzo_forceinline #endif #if !defined(__lzo_static_noinline) #if (LZO_CC_IBMC) # define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline #endif #endif #if !defined(__lzo_static_noinline) # define __lzo_static_noinline static __lzo_noinline #endif #if !defined(__lzo_c99_extern_inline) #if defined(__GNUC_GNU_INLINE__) # define __lzo_c99_extern_inline __lzo_inline #elif defined(__GNUC_STDC_INLINE__) # define __lzo_c99_extern_inline extern __lzo_inline #elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) # define __lzo_c99_extern_inline extern __lzo_inline #endif #if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) # define __lzo_c99_extern_inline __lzo_inline #endif #endif #if defined(__lzo_c99_extern_inline) # ifndef __lzo_HAVE_c99_extern_inline # define __lzo_HAVE_c99_extern_inline 1 # endif #else # define __lzo_c99_extern_inline /*empty*/ #endif #if !defined(__lzo_may_alias) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_CLANG >= 0x020900ul) # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 # define __lzo_may_alias __attribute__((__may_alias__)) #endif #endif #if defined(__lzo_may_alias) # ifndef __lzo_HAVE_may_alias # define __lzo_HAVE_may_alias 1 # endif #else # define __lzo_may_alias /*empty*/ #endif #if !defined(__lzo_noreturn) #if (LZO_CC_GNUC >= 0x020700ul) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) # define __lzo_noreturn __declspec(noreturn) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) # define __lzo_noreturn __declspec(noreturn) #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_noreturn __attribute__((__noreturn__)) #endif #endif #if defined(__lzo_noreturn) # ifndef __lzo_HAVE_noreturn # define __lzo_HAVE_noreturn 1 # endif #else # define __lzo_noreturn /*empty*/ #endif #if !defined(__lzo_nothrow) #if (LZO_CC_GNUC >= 0x030300ul) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) # define __lzo_nothrow __declspec(nothrow) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) # define __lzo_nothrow __declspec(nothrow) #endif #endif #if defined(__lzo_nothrow) # ifndef __lzo_HAVE_nothrow # define __lzo_HAVE_nothrow 1 # endif #else # define __lzo_nothrow /*empty*/ #endif #if !defined(__lzo_restrict) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_restrict __restrict__ #elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) # define __lzo_restrict __restrict__ #elif (LZO_CC_IBMC >= 1210) # define __lzo_restrict __restrict__ #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) # define __lzo_restrict __restrict__ #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) # define __lzo_restrict __restrict__ #elif (LZO_CC_MSC && (_MSC_VER >= 1400)) # define __lzo_restrict __restrict #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_restrict __restrict__ #endif #endif #if defined(__lzo_restrict) # ifndef __lzo_HAVE_restrict # define __lzo_HAVE_restrict 1 # endif #else # define __lzo_restrict /*empty*/ #endif #if !defined(__lzo_alignof) #if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_GHS) && !defined(__cplusplus) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_IBMC >= 600) # define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) #elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_alignof(e) __alignof(e) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_alignof(e) __alignof__(e) #endif #endif #if defined(__lzo_alignof) # ifndef __lzo_HAVE_alignof # define __lzo_HAVE_alignof 1 # endif #endif #if !defined(__lzo_struct_packed) #if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) #elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) #elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) # define __lzo_struct_packed(s) struct s { # define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_struct_packed(s) struct s { # define __lzo_struct_packed_end() } __attribute__((__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_IBMC >= 700) # define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { # define __lzo_struct_packed_end() } __attribute__((__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { # define __lzo_struct_packed_end() } __pragma(pack(pop)); #elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) # define __lzo_struct_packed(s) _Packed struct s { # define __lzo_struct_packed_end() }; #endif #endif #if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) # define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) #endif #if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) # define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() #endif #if !defined(__lzo_byte_struct) #if defined(__lzo_struct_packed) # define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() # define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() #elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); # define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); #endif #endif #if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) # define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) #endif #if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) #if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) #elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_CILLY || LZO_CC_PCC) #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_struct_align16(s) struct __declspec(align(16)) s { # define __lzo_struct_align16_end() }; # define __lzo_struct_align32(s) struct __declspec(align(32)) s { # define __lzo_struct_align32_end() }; # define __lzo_struct_align64(s) struct __declspec(align(64)) s { # define __lzo_struct_align64_end() }; #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_struct_align16(s) struct s { # define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); # define __lzo_struct_align32(s) struct s { # define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); # define __lzo_struct_align64(s) struct s { # define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); #endif #endif #if !defined(__lzo_union_um) #if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) #elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) #elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_union_am(s) union s { # define __lzo_union_am_end() } __lzo_may_alias; # define __lzo_union_um(s) union s { # define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_IBMC >= 700) # define __lzo_union_am(s) __lzo_gnuc_extension__ union s { # define __lzo_union_am_end() } __lzo_may_alias; # define __lzo_union_um(s) __lzo_gnuc_extension__ union s { # define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_union_um(s) __pragma(pack(push,1)) union s { # define __lzo_union_um_end() } __pragma(pack(pop)); #elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) # define __lzo_union_um(s) _Packed union s { # define __lzo_union_um_end() }; #endif #endif #if !defined(__lzo_union_am) # define __lzo_union_am(s) union s { # define __lzo_union_am_end() }; #endif #if !defined(__lzo_constructor) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_constructor __attribute__((__constructor__,__used__)) #elif (LZO_CC_GNUC >= 0x020700ul) # define __lzo_constructor __attribute__((__constructor__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_constructor __attribute__((__constructor__,__used__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_constructor __attribute__((__constructor__)) #endif #endif #if defined(__lzo_constructor) # ifndef __lzo_HAVE_constructor # define __lzo_HAVE_constructor 1 # endif #endif #if !defined(__lzo_destructor) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_destructor __attribute__((__destructor__,__used__)) #elif (LZO_CC_GNUC >= 0x020700ul) # define __lzo_destructor __attribute__((__destructor__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_destructor __attribute__((__destructor__,__used__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_destructor __attribute__((__destructor__)) #endif #endif #if defined(__lzo_destructor) # ifndef __lzo_HAVE_destructor # define __lzo_HAVE_destructor 1 # endif #endif #if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) # error "unexpected configuration - check your compiler defines" #endif #if !defined(__lzo_likely) && !defined(__lzo_unlikely) #if (LZO_CC_GNUC >= 0x030200ul) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_IBMC >= 1010) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_CLANG && LZO_CC_CLANG_C2) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #endif #endif #if defined(__lzo_likely) # ifndef __lzo_HAVE_likely # define __lzo_HAVE_likely 1 # endif #else # define __lzo_likely(e) (e) #endif #if defined(__lzo_very_likely) # ifndef __lzo_HAVE_very_likely # define __lzo_HAVE_very_likely 1 # endif #else # define __lzo_very_likely(e) __lzo_likely(e) #endif #if defined(__lzo_unlikely) # ifndef __lzo_HAVE_unlikely # define __lzo_HAVE_unlikely 1 # endif #else # define __lzo_unlikely(e) (e) #endif #if defined(__lzo_very_unlikely) # ifndef __lzo_HAVE_very_unlikely # define __lzo_HAVE_very_unlikely 1 # endif #else # define __lzo_very_unlikely(e) __lzo_unlikely(e) #endif #if !defined(__lzo_loop_forever) # if (LZO_CC_IBMC) # define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END # else # define __lzo_loop_forever() do { ; } while __lzo_cte(1) # endif #endif #if !defined(__lzo_unreachable) #if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) && lzo_has_builtin(__builtin_unreachable) # define __lzo_unreachable() __builtin_unreachable(); #elif (LZO_CC_GNUC >= 0x040500ul) # define __lzo_unreachable() __builtin_unreachable(); #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 # define __lzo_unreachable() __builtin_unreachable(); #endif #endif #if defined(__lzo_unreachable) # ifndef __lzo_HAVE_unreachable # define __lzo_HAVE_unreachable 1 # endif #else # if 0 # define __lzo_unreachable() ((void)0); # else # define __lzo_unreachable() __lzo_loop_forever(); # endif #endif #if !defined(lzo_unused_funcs_impl) # if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define lzo_unused_funcs_impl(r,f) static r __attribute__((__unused__)) f # elif 1 && (LZO_CC_BORLANDC || LZO_CC_GNUC) # define lzo_unused_funcs_impl(r,f) static r f # else # define lzo_unused_funcs_impl(r,f) __lzo_static_forceinline r f # endif #endif #ifndef __LZO_CTA_NAME #if (LZO_CFG_USE_COUNTER) # define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) #else # define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) #endif #endif #if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) # if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_DMC || LZO_CC_SYMANTECC) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END # elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END # else # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END # endif #endif #if !defined(LZO_COMPILE_TIME_ASSERT) # if (LZO_CC_AZTECC) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} # elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030000ul)) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} # elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) # define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} # elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) # define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} # elif (LZO_CC_GNUC >= 0x040700ul) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # else # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} # endif #endif #if (LZO_LANG_ASSEMBLER) # undef LZO_COMPILE_TIME_ASSERT_HEADER # define LZO_COMPILE_TIME_ASSERT_HEADER(e) /*empty*/ #else LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) #if defined(__cplusplus) extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } #endif LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) #endif #if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) # if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) # elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) # define __lzo_cdecl __cdecl # define __lzo_cdecl_atexit /*empty*/ # define __lzo_cdecl_main __cdecl # if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) # define __lzo_cdecl_qsort __pascal # elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) # define __lzo_cdecl_qsort _stdcall # else # define __lzo_cdecl_qsort __cdecl # endif # elif (LZO_CC_WATCOMC) # define __lzo_cdecl __cdecl # else # define __lzo_cdecl __cdecl # define __lzo_cdecl_atexit __cdecl # define __lzo_cdecl_main __cdecl # define __lzo_cdecl_qsort __cdecl # endif # if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) # elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) # define __lzo_cdecl_sighandler __pascal # elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) # define __lzo_cdecl_sighandler _stdcall # elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) # define __lzo_cdecl_sighandler __clrcall # elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) # if defined(_DLL) # define __lzo_cdecl_sighandler _far _cdecl _loadds # elif defined(_MT) # define __lzo_cdecl_sighandler _far _cdecl # else # define __lzo_cdecl_sighandler _cdecl # endif # else # define __lzo_cdecl_sighandler __cdecl # endif #elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) # define __lzo_cdecl __cdecl #elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) # define __lzo_cdecl cdecl #endif #if !defined(__lzo_cdecl) # define __lzo_cdecl /*empty*/ #endif #if !defined(__lzo_cdecl_atexit) # define __lzo_cdecl_atexit /*empty*/ #endif #if !defined(__lzo_cdecl_main) # define __lzo_cdecl_main /*empty*/ #endif #if !defined(__lzo_cdecl_qsort) # define __lzo_cdecl_qsort /*empty*/ #endif #if !defined(__lzo_cdecl_sighandler) # define __lzo_cdecl_sighandler /*empty*/ #endif #if !defined(__lzo_cdecl_va) # define __lzo_cdecl_va __lzo_cdecl #endif #if !(LZO_CFG_NO_WINDOWS_H) #if !defined(LZO_HAVE_WINDOWS_H) #if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) # if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) # elif ((LZO_OS_WIN32 && defined(__PW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul))) # elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) # else # define LZO_HAVE_WINDOWS_H 1 # endif #endif #endif #endif #define LZO_SIZEOF_CHAR 1 #ifndef LZO_SIZEOF_SHORT #if defined(SIZEOF_SHORT) # define LZO_SIZEOF_SHORT (SIZEOF_SHORT) #elif defined(__SIZEOF_SHORT__) # define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) #endif #endif #ifndef LZO_SIZEOF_INT #if defined(SIZEOF_INT) # define LZO_SIZEOF_INT (SIZEOF_INT) #elif defined(__SIZEOF_INT__) # define LZO_SIZEOF_INT (__SIZEOF_INT__) #endif #endif #ifndef LZO_SIZEOF_LONG #if defined(SIZEOF_LONG) # define LZO_SIZEOF_LONG (SIZEOF_LONG) #elif defined(__SIZEOF_LONG__) # define LZO_SIZEOF_LONG (__SIZEOF_LONG__) #endif #endif #ifndef LZO_SIZEOF_LONG_LONG #if defined(SIZEOF_LONG_LONG) # define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) #elif defined(__SIZEOF_LONG_LONG__) # define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) #endif #endif #ifndef LZO_SIZEOF___INT16 #if defined(SIZEOF___INT16) # define LZO_SIZEOF___INT16 (SIZEOF___INT16) #endif #endif #ifndef LZO_SIZEOF___INT32 #if defined(SIZEOF___INT32) # define LZO_SIZEOF___INT32 (SIZEOF___INT32) #endif #endif #ifndef LZO_SIZEOF___INT64 #if defined(SIZEOF___INT64) # define LZO_SIZEOF___INT64 (SIZEOF___INT64) #endif #endif #ifndef LZO_SIZEOF_VOID_P #if defined(SIZEOF_VOID_P) # define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) #elif defined(__SIZEOF_POINTER__) # define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) #endif #endif #ifndef LZO_SIZEOF_SIZE_T #if defined(SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) #elif defined(__SIZEOF_SIZE_T__) # define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) #endif #endif #ifndef LZO_SIZEOF_PTRDIFF_T #if defined(SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) #elif defined(__SIZEOF_PTRDIFF_T__) # define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) #endif #endif #define __LZO_LSR(x,b) (((x)+0ul) >> (b)) #if !defined(LZO_SIZEOF_SHORT) # if (LZO_ARCH_CRAY_PVP) # define LZO_SIZEOF_SHORT 8 # elif (USHRT_MAX == LZO_0xffffL) # define LZO_SIZEOF_SHORT 2 # elif (__LZO_LSR(USHRT_MAX,7) == 1) # define LZO_SIZEOF_SHORT 1 # elif (__LZO_LSR(USHRT_MAX,15) == 1) # define LZO_SIZEOF_SHORT 2 # elif (__LZO_LSR(USHRT_MAX,31) == 1) # define LZO_SIZEOF_SHORT 4 # elif (__LZO_LSR(USHRT_MAX,63) == 1) # define LZO_SIZEOF_SHORT 8 # elif (__LZO_LSR(USHRT_MAX,127) == 1) # define LZO_SIZEOF_SHORT 16 # else # error "LZO_SIZEOF_SHORT" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) #if !defined(LZO_SIZEOF_INT) # if (LZO_ARCH_CRAY_PVP) # define LZO_SIZEOF_INT 8 # elif (UINT_MAX == LZO_0xffffL) # define LZO_SIZEOF_INT 2 # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_SIZEOF_INT 4 # elif (__LZO_LSR(UINT_MAX,7) == 1) # define LZO_SIZEOF_INT 1 # elif (__LZO_LSR(UINT_MAX,15) == 1) # define LZO_SIZEOF_INT 2 # elif (__LZO_LSR(UINT_MAX,31) == 1) # define LZO_SIZEOF_INT 4 # elif (__LZO_LSR(UINT_MAX,63) == 1) # define LZO_SIZEOF_INT 8 # elif (__LZO_LSR(UINT_MAX,127) == 1) # define LZO_SIZEOF_INT 16 # else # error "LZO_SIZEOF_INT" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) #if !defined(LZO_SIZEOF_LONG) # if (ULONG_MAX == LZO_0xffffffffL) # define LZO_SIZEOF_LONG 4 # elif (__LZO_LSR(ULONG_MAX,7) == 1) # define LZO_SIZEOF_LONG 1 # elif (__LZO_LSR(ULONG_MAX,15) == 1) # define LZO_SIZEOF_LONG 2 # elif (__LZO_LSR(ULONG_MAX,31) == 1) # define LZO_SIZEOF_LONG 4 # elif (__LZO_LSR(ULONG_MAX,39) == 1) # define LZO_SIZEOF_LONG 5 # elif (__LZO_LSR(ULONG_MAX,63) == 1) # define LZO_SIZEOF_LONG 8 # elif (__LZO_LSR(ULONG_MAX,127) == 1) # define LZO_SIZEOF_LONG 16 # else # error "LZO_SIZEOF_LONG" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) #if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) #if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) # if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) # if (LZO_CC_GNUC >= 0x030300ul) # if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) # define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG # elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) # define LZO_SIZEOF_LONG_LONG 4 # endif # endif # endif #endif #endif #if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) #if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) #if (LZO_ARCH_I086 && LZO_CC_DMC) #elif (LZO_CC_CILLY) && defined(__GNUC__) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_SIZEOF_LONG_LONG 8 #elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_OS_WIN64 || defined(_WIN64)) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_DMC)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) # define LZO_SIZEOF___INT64 8 #elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) # define LZO_SIZEOF___INT64 8 #elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) # define LZO_SIZEOF___INT64 8 #elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) # define LZO_SIZEOF_LONG_LONG 8 #elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) #elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define LZO_SIZEOF_LONG_LONG 8 #endif #endif #endif #if defined(__cplusplus) && (LZO_CC_GNUC) # if (LZO_CC_GNUC < 0x020800ul) # undef LZO_SIZEOF_LONG_LONG # endif #endif #if (LZO_CFG_NO_LONG_LONG) # undef LZO_SIZEOF_LONG_LONG #elif defined(__NO_LONG_LONG) # undef LZO_SIZEOF_LONG_LONG #elif defined(_NO_LONGLONG) # undef LZO_SIZEOF_LONG_LONG #endif #if !defined(LZO_WORDSIZE) #if (LZO_ARCH_ALPHA) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_AMD64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_ARM64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_AVR) # define LZO_WORDSIZE 1 #elif (LZO_ARCH_H8300) # if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) # define LZO_WORDSIZE 4 # else # define LZO_WORDSIZE 2 # endif #elif (LZO_ARCH_I086) # define LZO_WORDSIZE 2 #elif (LZO_ARCH_IA64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_M16C) # define LZO_WORDSIZE 2 #elif (LZO_ARCH_SPU) # define LZO_WORDSIZE 4 #elif (LZO_ARCH_Z80) # define LZO_WORDSIZE 1 #elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) # define LZO_WORDSIZE 8 #elif (LZO_OS_OS400 || defined(__OS400__)) # define LZO_WORDSIZE 8 #elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) # define LZO_WORDSIZE 8 #endif #endif #if !defined(LZO_SIZEOF_VOID_P) #if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) # define LZO_SIZEOF_VOID_P 4 #elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) # define LZO_SIZEOF_VOID_P 8 #elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) # define LZO_SIZEOF_VOID_P 8 #elif defined(__LP64__) || defined(__LP64) || defined(_LP64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) # define LZO_SIZEOF_VOID_P 8 #elif (LZO_ARCH_AVR) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_H8300) # if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 4) # if defined(__NORMAL_MODE__) # define LZO_SIZEOF_VOID_P 2 # else # define LZO_SIZEOF_VOID_P 4 # endif # else LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 2) # define LZO_SIZEOF_VOID_P 2 # endif # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT # endif #elif (LZO_ARCH_I086) # if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) # define LZO_SIZEOF_VOID_P 2 # elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) # define LZO_SIZEOF_VOID_P 4 # else # error "invalid LZO_ARCH_I086 memory model" # endif #elif (LZO_ARCH_M16C) # if defined(__m32c_cpu__) || defined(__m32cm_cpu__) # define LZO_SIZEOF_VOID_P 4 # else # define LZO_SIZEOF_VOID_P 2 # endif #elif (LZO_ARCH_SPU) # define LZO_SIZEOF_VOID_P 4 #elif (LZO_ARCH_Z80) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) # define LZO_SIZEOF_VOID_P 4 #elif (LZO_OS_OS400 || defined(__OS400__)) # if defined(__LLP64_IFC__) # define LZO_SIZEOF_VOID_P 8 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG # else # define LZO_SIZEOF_VOID_P 16 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG # endif #elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) # define LZO_SIZEOF_VOID_P 8 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG #endif #endif #if !defined(LZO_SIZEOF_VOID_P) # define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) #if !defined(LZO_SIZEOF_SIZE_T) #if (LZO_ARCH_I086 || LZO_ARCH_M16C) # define LZO_SIZEOF_SIZE_T 2 #endif #endif #if !defined(LZO_SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P #endif #if defined(offsetof) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) #endif #if !defined(LZO_SIZEOF_PTRDIFF_T) #if (LZO_ARCH_I086) # if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P # elif (LZO_MM_COMPACT || LZO_MM_LARGE) # if (LZO_CC_BORLANDC || LZO_CC_TURBOC) # define LZO_SIZEOF_PTRDIFF_T 4 # else # define LZO_SIZEOF_PTRDIFF_T 2 # endif # else # error "invalid LZO_ARCH_I086 memory model" # endif #endif #endif #if !defined(LZO_SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T #endif #if defined(offsetof) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) #endif #if !defined(LZO_WORDSIZE) # define LZO_WORDSIZE LZO_SIZEOF_VOID_P #endif #if (LZO_ABI_NEUTRAL_ENDIAN) # undef LZO_ABI_BIG_ENDIAN # undef LZO_ABI_LITTLE_ENDIAN #elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) #if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) # define LZO_ABI_BIG_ENDIAN 1 #elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) # define LZO_ABI_LITTLE_ENDIAN 1 #elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430 || LZO_ARCH_RISCV) # define LZO_ABI_LITTLE_ENDIAN 1 #elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) # if (__LITTLE_ENDIAN__ == 1) # define LZO_ABI_LITTLE_ENDIAN 1 # else # define LZO_ABI_BIG_ENDIAN 1 # endif #elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(_MSC_VER) && defined(_WIN32) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) # if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) # error "unexpected configuration - check your compiler defines" # elif defined(__BIG_ENDIAN) # define LZO_ABI_BIG_ENDIAN 1 # else # define LZO_ABI_LITTLE_ENDIAN 1 # endif # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(_MSC_VER) && defined(_WIN32) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) # define LZO_ABI_LITTLE_ENDIAN 1 #endif #endif #if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ABI_BIG_ENDIAN) # define LZO_INFO_ABI_ENDIAN "be" #elif (LZO_ABI_LITTLE_ENDIAN) # define LZO_INFO_ABI_ENDIAN "le" #elif (LZO_ABI_NEUTRAL_ENDIAN) # define LZO_INFO_ABI_ENDIAN "neutral" #endif #if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) # define LZO_ABI_I8LP16 1 # define LZO_INFO_ABI_PM "i8lp16" #elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) # define LZO_ABI_ILP16 1 # define LZO_INFO_ABI_PM "ilp16" #elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_LP32 1 # define LZO_INFO_ABI_PM "lp32" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_ILP32 1 # define LZO_INFO_ABI_PM "ilp32" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) # define LZO_ABI_LLP64 1 # define LZO_INFO_ABI_PM "llp64" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) # define LZO_ABI_LP64 1 # define LZO_INFO_ABI_PM "lp64" #elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) # define LZO_ABI_ILP64 1 # define LZO_INFO_ABI_PM "ilp64" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_IP32L64 1 # define LZO_INFO_ABI_PM "ip32l64" #endif #if (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_VOID_P == 4 && LZO_WORDSIZE == 8) # define LZO_ABI_IP32W64 1 # ifndef LZO_INFO_ABI_PM # define LZO_INFO_ABI_PM "ip32w64" # endif #endif #if 0 #elif !defined(__LZO_LIBC_OVERRIDE) #if (LZO_LIBC_NAKED) # define LZO_INFO_LIBC "naked" #elif (LZO_LIBC_FREESTANDING) # define LZO_INFO_LIBC "freestanding" #elif (LZO_LIBC_MOSTLY_FREESTANDING) # define LZO_INFO_LIBC "mfreestanding" #elif (LZO_LIBC_ISOC90) # define LZO_INFO_LIBC "isoc90" #elif (LZO_LIBC_ISOC99) # define LZO_INFO_LIBC "isoc99" #elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) # define LZO_LIBC_ISOC90 1 # define LZO_INFO_LIBC "isoc90" #elif defined(__dietlibc__) # define LZO_LIBC_DIETLIBC 1 # define LZO_INFO_LIBC "dietlibc" #elif defined(_NEWLIB_VERSION) # define LZO_LIBC_NEWLIB 1 # define LZO_INFO_LIBC "newlib" #elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) # if defined(__UCLIBC_SUBLEVEL__) # define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) # else # define LZO_LIBC_UCLIBC 0x00090bL # endif # define LZO_INFO_LIBC "uc" "libc" #elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) # define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) # define LZO_INFO_LIBC "glibc" #elif (LZO_CC_MWERKS) && defined(__MSL__) # define LZO_LIBC_MSL __MSL__ # define LZO_INFO_LIBC "msl" #elif 1 && defined(__IAR_SYSTEMS_ICC__) # define LZO_LIBC_ISOC90 1 # define LZO_INFO_LIBC "isoc90" #else # define LZO_LIBC_DEFAULT 1 # define LZO_INFO_LIBC "default" #endif #endif #if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) # define LZO_ASM_SYNTAX_MSC 1 #elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) #elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) #elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) # define LZO_ASM_SYNTAX_GNUC 1 #elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) # define LZO_ASM_SYNTAX_GNUC 1 #elif (LZO_CC_GNUC) # define LZO_ASM_SYNTAX_GNUC 1 #endif #if (LZO_ASM_SYNTAX_GNUC) #if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) # define __LZO_ASM_CLOBBER "ax" # define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) # define __LZO_ASM_CLOBBER "memory" # define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #else # define __LZO_ASM_CLOBBER "cc", "memory" # define __LZO_ASM_CLOBBER_LIST_CC : "cc" # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #endif #endif #if (LZO_ARCH_ALPHA) # define LZO_OPT_AVOID_UINT_INDEX 1 #elif (LZO_ARCH_AMD64) # define LZO_OPT_AVOID_INT_INDEX 1 # define LZO_OPT_AVOID_UINT_INDEX 1 # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif #elif (LZO_ARCH_ARM) # if defined(__ARM_FEATURE_UNALIGNED) # if ((__ARM_FEATURE_UNALIGNED)+0) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif # elif 1 && (LZO_ARCH_ARM_THUMB2) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__ARM_ARCH) && ((__ARM_ARCH)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 6) && (defined(__TARGET_PROFILE_A) || defined(__TARGET_PROFILE_R)) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(_MSC_VER) && defined(_M_ARM) && ((_M_ARM)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif #elif (LZO_ARCH_ARM64) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif #elif (LZO_ARCH_CRIS) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif #elif (LZO_ARCH_I386) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif #elif (LZO_ARCH_IA64) # define LZO_OPT_AVOID_INT_INDEX 1 # define LZO_OPT_AVOID_UINT_INDEX 1 # define LZO_OPT_PREFER_POSTINC 1 #elif (LZO_ARCH_M68K) # define LZO_OPT_PREFER_POSTINC 1 # define LZO_OPT_PREFER_PREDEC 1 # if defined(__mc68020__) && !defined(__mcoldfire__) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif #elif (LZO_ARCH_MIPS) # define LZO_OPT_AVOID_UINT_INDEX 1 #elif (LZO_ARCH_POWERPC) # define LZO_OPT_PREFER_PREINC 1 # define LZO_OPT_PREFER_PREDEC 1 # if (LZO_ABI_BIG_ENDIAN) || (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif # endif #elif (LZO_ARCH_RISCV) # define LZO_OPT_AVOID_UINT_INDEX 1 # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif #elif (LZO_ARCH_S390) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif #elif (LZO_ARCH_SH) # define LZO_OPT_PREFER_POSTINC 1 # define LZO_OPT_PREFER_PREDEC 1 #endif #ifndef LZO_CFG_NO_INLINE_ASM #if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) # define LZO_CFG_NO_INLINE_ASM 1 #elif (LZO_CC_LLVM) # define LZO_CFG_NO_INLINE_ASM 1 #endif #endif #if (LZO_CFG_NO_INLINE_ASM) # undef LZO_ASM_SYNTAX_MSC # undef LZO_ASM_SYNTAX_GNUC # undef __LZO_ASM_CLOBBER # undef __LZO_ASM_CLOBBER_LIST_CC # undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY # undef __LZO_ASM_CLOBBER_LIST_EMPTY #endif #ifndef LZO_CFG_NO_UNALIGNED #if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) # define LZO_CFG_NO_UNALIGNED 1 #endif #endif #if (LZO_CFG_NO_UNALIGNED) # undef LZO_OPT_UNALIGNED16 # undef LZO_OPT_UNALIGNED32 # undef LZO_OPT_UNALIGNED64 #endif #if defined(__LZO_INFOSTR_MM) #elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) # define __LZO_INFOSTR_MM "" #elif defined(LZO_INFO_MM) # define __LZO_INFOSTR_MM "." LZO_INFO_MM #else # define __LZO_INFOSTR_MM "" #endif #if defined(__LZO_INFOSTR_PM) #elif defined(LZO_INFO_ABI_PM) # define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM #else # define __LZO_INFOSTR_PM "" #endif #if defined(__LZO_INFOSTR_ENDIAN) #elif defined(LZO_INFO_ABI_ENDIAN) # define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN #else # define __LZO_INFOSTR_ENDIAN "" #endif #if defined(__LZO_INFOSTR_OSNAME) #elif defined(LZO_INFO_OS_CONSOLE) # define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE #elif defined(LZO_INFO_OS_POSIX) # define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX #else # define __LZO_INFOSTR_OSNAME LZO_INFO_OS #endif #if defined(__LZO_INFOSTR_LIBC) #elif defined(LZO_INFO_LIBC) # define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC #else # define __LZO_INFOSTR_LIBC "" #endif #if defined(__LZO_INFOSTR_CCVER) #elif defined(LZO_INFO_CCVER) # define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER #else # define __LZO_INFOSTR_CCVER "" #endif #define LZO_INFO_STRING \ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER #if !(LZO_CFG_SKIP_LZO_TYPES) #if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) # error "missing defines for sizes" #endif #if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) # error "missing defines for sizes" #endif #define LZO_TYPEOF_CHAR 1u #define LZO_TYPEOF_SHORT 2u #define LZO_TYPEOF_INT 3u #define LZO_TYPEOF_LONG 4u #define LZO_TYPEOF_LONG_LONG 5u #define LZO_TYPEOF___INT8 17u #define LZO_TYPEOF___INT16 18u #define LZO_TYPEOF___INT32 19u #define LZO_TYPEOF___INT64 20u #define LZO_TYPEOF___INT128 21u #define LZO_TYPEOF___INT256 22u #define LZO_TYPEOF___MODE_QI 33u #define LZO_TYPEOF___MODE_HI 34u #define LZO_TYPEOF___MODE_SI 35u #define LZO_TYPEOF___MODE_DI 36u #define LZO_TYPEOF___MODE_TI 37u #define LZO_TYPEOF_CHAR_P 129u #if !defined(lzo_llong_t) #if (LZO_SIZEOF_LONG_LONG+0 > 0) # if !(LZO_LANG_ASSEMBLER) __lzo_gnuc_extension__ typedef long long lzo_llong_t__; __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; # endif # define lzo_llong_t lzo_llong_t__ # define lzo_ullong_t lzo_ullong_t__ #endif #endif #if !defined(lzo_int16e_t) #if (LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) && (LZO_SIZEOF_SHORT != 2) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T #endif #if (LZO_SIZEOF_LONG == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) # define lzo_int16e_t long # define lzo_uint16e_t unsigned long # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_INT == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) # define lzo_int16e_t int # define lzo_uint16e_t unsigned int # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == 2) # define lzo_int16e_t short int # define lzo_uint16e_t unsigned short int # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_SHORT #elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); # endif # define lzo_int16e_t lzo_int16e_hi_t__ # define lzo_uint16e_t lzo_uint16e_hi_t__ # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___MODE_HI #elif (LZO_SIZEOF___INT16 == 2) # define lzo_int16e_t __int16 # define lzo_uint16e_t unsigned __int16 # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___INT16 #else #endif #endif #if defined(lzo_int16e_t) # define LZO_SIZEOF_LZO_INT16E_T 2 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) #endif #if !defined(lzo_int32e_t) #if (LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) && (LZO_SIZEOF_INT != 4) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T #endif #if (LZO_SIZEOF_LONG == 4) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) # define lzo_int32e_t long int # define lzo_uint32e_t unsigned long int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_INT == 4) # define lzo_int32e_t int # define lzo_uint32e_t unsigned int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == 4) # define lzo_int32e_t short int # define lzo_uint32e_t unsigned short int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_SHORT #elif (LZO_SIZEOF_LONG_LONG == 4) # define lzo_int32e_t lzo_llong_t # define lzo_uint32e_t lzo_ullong_t # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG_LONG #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); # endif # define lzo_int32e_t lzo_int32e_si_t__ # define lzo_uint32e_t lzo_uint32e_si_t__ # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); # endif # define lzo_int32e_t lzo_int32e_si_t__ # define lzo_uint32e_t lzo_uint32e_si_t__ # define LZO_INT32_C(c) (c##LL) # define LZO_UINT32_C(c) (c##ULL) # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI #elif (LZO_SIZEOF___INT32 == 4) # define lzo_int32e_t __int32 # define lzo_uint32e_t unsigned __int32 # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___INT32 #else #endif #endif #if defined(lzo_int32e_t) # define LZO_SIZEOF_LZO_INT32E_T 4 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) #endif #if !defined(lzo_int64e_t) #if (LZO_SIZEOF___INT64 == 8) # if (LZO_CC_BORLANDC) && !defined(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T) # define LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T LZO_TYPEOF___INT64 # endif #endif #if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && (LZO_SIZEOF_LONG_LONG != 8) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T #endif #if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) && (LZO_SIZEOF___INT64 != 8) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T #endif #if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_int64e_t int # define lzo_uint64e_t unsigned int # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) # define lzo_int64e_t long int # define lzo_uint64e_t unsigned long int # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) # define lzo_int64e_t lzo_llong_t # define lzo_uint64e_t lzo_ullong_t # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG_LONG # if (LZO_CC_BORLANDC) # define LZO_INT64_C(c) ((c) + 0ll) # define LZO_UINT64_C(c) ((c) + 0ull) # elif 0 # define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) # define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) # else # define LZO_INT64_C(c) (c##LL) # define LZO_UINT64_C(c) (c##ULL) # endif #elif (LZO_SIZEOF___INT64 == 8) # define lzo_int64e_t __int64 # define lzo_uint64e_t unsigned __int64 # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF___INT64 # if (LZO_CC_BORLANDC) # define LZO_INT64_C(c) ((c) + 0i64) # define LZO_UINT64_C(c) ((c) + 0ui64) # else # define LZO_INT64_C(c) (c##i64) # define LZO_UINT64_C(c) (c##ui64) # endif #else #endif #endif #if defined(lzo_int64e_t) # define LZO_SIZEOF_LZO_INT64E_T 8 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) #endif #if !defined(lzo_int32l_t) #if defined(lzo_int32e_t) # define lzo_int32l_t lzo_int32e_t # define lzo_uint32l_t lzo_uint32e_t # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T # define LZO_TYPEOF_LZO_INT32L_T LZO_TYPEOF_LZO_INT32E_T #elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_int32l_t int # define lzo_uint32l_t unsigned int # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_INT #elif (LZO_SIZEOF_LONG >= 4) # define lzo_int32l_t long int # define lzo_uint32l_t unsigned long int # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_LONG #else # error "lzo_int32l_t" #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) #endif #if !defined(lzo_int64l_t) #if defined(lzo_int64e_t) # define lzo_int64l_t lzo_int64e_t # define lzo_uint64l_t lzo_uint64e_t # define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T # define LZO_TYPEOF_LZO_INT64L_T LZO_TYPEOF_LZO_INT64E_T #else #endif #endif #if defined(lzo_int64l_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) #endif #if !defined(lzo_int32f_t) #if (LZO_SIZEOF_SIZE_T >= 8) # define lzo_int32f_t lzo_int64l_t # define lzo_uint32f_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT64L_T #else # define lzo_int32f_t lzo_int32l_t # define lzo_uint32f_t lzo_uint32l_t # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T # define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT32L_T #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) #endif #if !defined(lzo_int64f_t) #if defined(lzo_int64l_t) # define lzo_int64f_t lzo_int64l_t # define lzo_uint64f_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INT64F_T LZO_TYPEOF_LZO_INT64L_T #else #endif #endif #if defined(lzo_int64f_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) #endif #if !defined(lzo_intptr_t) #if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) # define __LZO_INTPTR_T_IS_POINTER 1 # if !(LZO_LANG_ASSEMBLER) typedef char * lzo_intptr_t; typedef char * lzo_uintptr_t; # endif # define lzo_intptr_t lzo_intptr_t # define lzo_uintptr_t lzo_uintptr_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_CHAR_P #elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) # if !(LZO_LANG_ASSEMBLER) typedef __w64 int lzo_intptr_t; typedef __w64 unsigned int lzo_uintptr_t; # endif # define lzo_intptr_t lzo_intptr_t # define lzo_uintptr_t lzo_uintptr_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) # define lzo_intptr_t short # define lzo_uintptr_t unsigned short # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_SHORT #elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_intptr_t int # define lzo_uintptr_t unsigned int # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) # define lzo_intptr_t long # define lzo_uintptr_t unsigned long # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) # define lzo_intptr_t lzo_int64l_t # define lzo_uintptr_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LZO_INT64L_T #else # error "lzo_intptr_t" #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) #endif #if !defined(lzo_word_t) #if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) #if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) # define lzo_word_t lzo_uintptr_t # define lzo_sword_t lzo_intptr_t # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LZO_INTPTR_T #elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) # define lzo_word_t unsigned long # define lzo_sword_t long # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LONG #elif (LZO_WORDSIZE == LZO_SIZEOF_INT) # define lzo_word_t unsigned int # define lzo_sword_t int # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_INT #elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) # define lzo_word_t unsigned short # define lzo_sword_t short # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_SHORT #elif (LZO_WORDSIZE == 1) # define lzo_word_t unsigned char # define lzo_sword_t signed char # define LZO_SIZEOF_LZO_WORD_T 1 # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_CHAR #elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) # define lzo_word_t lzo_uint64l_t # define lzo_sword_t lzo_int64l_t # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T #elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) #if 0 # if !(LZO_LANG_ASSEMBLER) typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); # endif # define lzo_word_t lzo_word_t # define lzo_sword_t lzo_sword_t # define LZO_SIZEOF_LZO_WORD_T 16 # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF___MODE_V16QI #endif #else # error "lzo_word_t" #endif #endif #endif #if 1 && defined(lzo_word_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) #endif #if 1 #define lzo_int8_t signed char #define lzo_uint8_t unsigned char #define LZO_SIZEOF_LZO_INT8_T 1 #define LZO_TYPEOF_LZO_INT8_T LZO_TYPEOF_CHAR LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) #endif #if defined(lzo_int16e_t) #define lzo_int16_t lzo_int16e_t #define lzo_uint16_t lzo_uint16e_t #define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T #define LZO_TYPEOF_LZO_INT16_T LZO_TYPEOF_LZO_INT16E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) #endif #if defined(lzo_int32e_t) #define lzo_int32_t lzo_int32e_t #define lzo_uint32_t lzo_uint32e_t #define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T #define LZO_TYPEOF_LZO_INT32_T LZO_TYPEOF_LZO_INT32E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) #endif #if defined(lzo_int64e_t) #define lzo_int64_t lzo_int64e_t #define lzo_uint64_t lzo_uint64e_t #define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T #define LZO_TYPEOF_LZO_INT64_T LZO_TYPEOF_LZO_INT64E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) #endif #if 1 #define lzo_int_least32_t lzo_int32l_t #define lzo_uint_least32_t lzo_uint32l_t #define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T #define LZO_TYPEOF_LZO_INT_LEAST32_T LZO_TYPEOF_LZO_INT32L_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) #endif #if defined(lzo_int64l_t) #define lzo_int_least64_t lzo_int64l_t #define lzo_uint_least64_t lzo_uint64l_t #define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T #define LZO_TYPEOF_LZO_INT_LEAST64_T LZO_TYPEOF_LZO_INT64L_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) #endif #if 1 #define lzo_int_fast32_t lzo_int32f_t #define lzo_uint_fast32_t lzo_uint32f_t #define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T #define LZO_TYPEOF_LZO_INT_FAST32_T LZO_TYPEOF_LZO_INT32F_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) #endif #if defined(lzo_int64f_t) #define lzo_int_fast64_t lzo_int64f_t #define lzo_uint_fast64_t lzo_uint64f_t #define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T #define LZO_TYPEOF_LZO_INT_FAST64_T LZO_TYPEOF_LZO_INT64F_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) #endif #if !defined(LZO_INT16_C) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) # define LZO_INT16_C(c) ((c) + 0) # define LZO_UINT16_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) # define LZO_INT16_C(c) ((c) + 0L) # define LZO_UINT16_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 2) # define LZO_INT16_C(c) (c) # define LZO_UINT16_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 2) # define LZO_INT16_C(c) (c##L) # define LZO_UINT16_C(c) (c##UL) # else # error "LZO_INT16_C" # endif #endif #if !defined(LZO_INT32_C) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) # define LZO_INT32_C(c) ((c) + 0) # define LZO_UINT32_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) # define LZO_INT32_C(c) ((c) + 0L) # define LZO_UINT32_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 4) # define LZO_INT32_C(c) (c) # define LZO_UINT32_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 4) # define LZO_INT32_C(c) (c##L) # define LZO_UINT32_C(c) (c##UL) # elif (LZO_SIZEOF_LONG_LONG >= 4) # define LZO_INT32_C(c) (c##LL) # define LZO_UINT32_C(c) (c##ULL) # else # error "LZO_INT32_C" # endif #endif #if !defined(LZO_INT64_C) && defined(lzo_int64l_t) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) # define LZO_INT64_C(c) ((c) + 0) # define LZO_UINT64_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) # define LZO_INT64_C(c) ((c) + 0L) # define LZO_UINT64_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 8) # define LZO_INT64_C(c) (c) # define LZO_UINT64_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 8) # define LZO_INT64_C(c) (c##L) # define LZO_UINT64_C(c) (c##UL) # else # error "LZO_INT64_C" # endif #endif #endif #endif /* already included */ /* vim:set ts=4 sw=4 et: */ distcc-3.4/lzo/minilzo.c000066400000000000000000006412521404653710500153010ustar00rootroot00000000000000/* minilzo.c -- mini subset of the LZO real-time data compression library This file is part of the LZO real-time data compression library. Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ */ /* * NOTE: * the full LZO package can be found at * http://www.oberhumer.com/opensource/lzo/ */ #define __LZO_IN_MINILZO 1 #if defined(LZO_CFG_FREESTANDING) # undef MINILZO_HAVE_CONFIG_H # define LZO_LIBC_FREESTANDING 1 # define LZO_OS_FREESTANDING 1 #endif #ifdef MINILZO_HAVE_CONFIG_H # include #endif #include #include #if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) #ifndef __LZODEFS_H_INCLUDED #define __LZODEFS_H_INCLUDED 1 #if defined(__CYGWIN32__) && !defined(__CYGWIN__) # define __CYGWIN__ __CYGWIN32__ #endif #if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) # define _ALL_SOURCE 1 #endif #if defined(__mips__) && defined(__R5900__) # if !defined(__LONG_MAX__) # define __LONG_MAX__ 9223372036854775807L # endif #endif #if 0 #elif !defined(__LZO_LANG_OVERRIDE) #if (defined(__clang__) || defined(__GNUC__)) && defined(__ASSEMBLER__) # if (__ASSEMBLER__+0) <= 0 # error "__ASSEMBLER__" # else # define LZO_LANG_ASSEMBLER 1 # endif #elif defined(__cplusplus) # if (__cplusplus+0) <= 0 # error "__cplusplus" # elif (__cplusplus < 199711L) # define LZO_LANG_CXX 1 # elif defined(_MSC_VER) && defined(_MSVC_LANG) && (_MSVC_LANG+0 >= 201402L) && 1 # define LZO_LANG_CXX _MSVC_LANG # else # define LZO_LANG_CXX __cplusplus # endif # define LZO_LANG_CPLUSPLUS LZO_LANG_CXX #else # if defined(__STDC_VERSION__) && (__STDC_VERSION__+0 >= 199409L) # define LZO_LANG_C __STDC_VERSION__ # else # define LZO_LANG_C 1 # endif #endif #endif #if !defined(LZO_CFG_NO_DISABLE_WUNDEF) #if defined(__ARMCC_VERSION) # pragma diag_suppress 193 #elif defined(__clang__) && defined(__clang_minor__) # pragma clang diagnostic ignored "-Wundef" #elif defined(__INTEL_COMPILER) # pragma warning(disable: 193) #elif defined(__KEIL__) && defined(__C166__) # pragma warning disable = 322 #elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) # if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) # pragma GCC diagnostic ignored "-Wundef" # endif #elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) # if ((_MSC_VER-0) >= 1300) # pragma warning(disable: 4668) # endif #endif #endif #if 0 && defined(__POCC__) && defined(_WIN32) # if (__POCC__ >= 400) # pragma warn(disable: 2216) # endif #endif #if 0 && defined(__WATCOMC__) # if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) # pragma warning 203 9 # endif #endif #if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) # pragma option -h #endif #if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) #ifndef _CRT_NONSTDC_NO_DEPRECATE #define _CRT_NONSTDC_NO_DEPRECATE 1 #endif #ifndef _CRT_NONSTDC_NO_WARNINGS #define _CRT_NONSTDC_NO_WARNINGS 1 #endif #ifndef _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE 1 #endif #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS 1 #endif #endif #if 0 #define LZO_0xffffUL 0xfffful #define LZO_0xffffffffUL 0xfffffffful #else #define LZO_0xffffUL 65535ul #define LZO_0xffffffffUL 4294967295ul #endif #define LZO_0xffffL LZO_0xffffUL #define LZO_0xffffffffL LZO_0xffffffffUL #if (LZO_0xffffL == LZO_0xffffffffL) # error "your preprocessor is broken 1" #endif #if (16ul * 16384ul != 262144ul) # error "your preprocessor is broken 2" #endif #if 0 #if (32767 >= 4294967295ul) # error "your preprocessor is broken 3" #endif #if (65535u >= 4294967295ul) # error "your preprocessor is broken 4" #endif #endif #if defined(__COUNTER__) # ifndef LZO_CFG_USE_COUNTER # define LZO_CFG_USE_COUNTER 1 # endif #else # undef LZO_CFG_USE_COUNTER #endif #if (UINT_MAX == LZO_0xffffL) #if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) # if !defined(MSDOS) # define MSDOS 1 # endif # if !defined(_MSDOS) # define _MSDOS 1 # endif #elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) # if (__VERSION == 520) && (MB_LEN_MAX == 1) # if !defined(__AZTEC_C__) # define __AZTEC_C__ __VERSION # endif # if !defined(__DOS__) # define __DOS__ 1 # endif # endif #endif #endif #if (UINT_MAX == LZO_0xffffL) #if defined(_MSC_VER) && defined(M_I86HM) # define ptrdiff_t long # define _PTRDIFF_T_DEFINED 1 #endif #endif #if (UINT_MAX == LZO_0xffffL) # undef __LZO_RENAME_A # undef __LZO_RENAME_B # if defined(__AZTEC_C__) && defined(__DOS__) # define __LZO_RENAME_A 1 # elif defined(_MSC_VER) && defined(MSDOS) # if (_MSC_VER < 600) # define __LZO_RENAME_A 1 # elif (_MSC_VER < 700) # define __LZO_RENAME_B 1 # endif # elif defined(__TSC__) && defined(__OS2__) # define __LZO_RENAME_A 1 # elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) # define __LZO_RENAME_A 1 # elif defined(__PACIFIC__) && defined(DOS) # if !defined(__far) # define __far far # endif # if !defined(__near) # define __near near # endif # endif # if defined(__LZO_RENAME_A) # if !defined(__cdecl) # define __cdecl cdecl # endif # if !defined(__far) # define __far far # endif # if !defined(__huge) # define __huge huge # endif # if !defined(__near) # define __near near # endif # if !defined(__pascal) # define __pascal pascal # endif # if !defined(__huge) # define __huge huge # endif # elif defined(__LZO_RENAME_B) # if !defined(__cdecl) # define __cdecl _cdecl # endif # if !defined(__far) # define __far _far # endif # if !defined(__huge) # define __huge _huge # endif # if !defined(__near) # define __near _near # endif # if !defined(__pascal) # define __pascal _pascal # endif # elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) # if !defined(__cdecl) # define __cdecl cdecl # endif # if !defined(__pascal) # define __pascal pascal # endif # endif # undef __LZO_RENAME_A # undef __LZO_RENAME_B #endif #if (UINT_MAX == LZO_0xffffL) #if defined(__AZTEC_C__) && defined(__DOS__) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 #elif defined(_MSC_VER) && defined(MSDOS) # if (_MSC_VER < 600) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 # endif # if (_MSC_VER < 700) # define LZO_BROKEN_INTEGRAL_PROMOTION 1 # define LZO_BROKEN_SIZEOF 1 # endif #elif defined(__PACIFIC__) && defined(DOS) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 #elif defined(__TURBOC__) && defined(__MSDOS__) # if (__TURBOC__ < 0x0150) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 # define LZO_BROKEN_INTEGRAL_PROMOTION 1 # endif # if (__TURBOC__ < 0x0200) # define LZO_BROKEN_SIZEOF 1 # endif # if (__TURBOC__ < 0x0400) && defined(__cplusplus) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # endif #elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) # define LZO_BROKEN_CDECL_ALT_SYNTAX 1 # define LZO_BROKEN_SIZEOF 1 #endif #endif #if defined(__WATCOMC__) && (__WATCOMC__ < 900) # define LZO_BROKEN_INTEGRAL_CONSTANTS 1 #endif #if defined(_CRAY) && defined(_CRAY1) # define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 #endif #define LZO_PP_STRINGIZE(x) #x #define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) #define LZO_PP_CONCAT0() /*empty*/ #define LZO_PP_CONCAT1(a) a #define LZO_PP_CONCAT2(a,b) a ## b #define LZO_PP_CONCAT3(a,b,c) a ## b ## c #define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e #define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f #define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g #define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() #define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) #define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) #define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) #define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) #define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) #define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) #define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) #define LZO_PP_EMPTY /*empty*/ #define LZO_PP_EMPTY0() /*empty*/ #define LZO_PP_EMPTY1(a) /*empty*/ #define LZO_PP_EMPTY2(a,b) /*empty*/ #define LZO_PP_EMPTY3(a,b,c) /*empty*/ #define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ #define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ #define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ #define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ #if 1 #define LZO_CPP_STRINGIZE(x) #x #define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) #define LZO_CPP_CONCAT2(a,b) a ## b #define LZO_CPP_CONCAT3(a,b,c) a ## b ## c #define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d #define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e #define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f #define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g #define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) #define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) #define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) #define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) #define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) #define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) #endif #define __LZO_MASK_GEN(o,b) (((((o) << ((b)-((b)!=0))) - (o)) << 1) + (o)*((b)!=0)) #if 1 && defined(__cplusplus) # if !defined(__STDC_CONSTANT_MACROS) # define __STDC_CONSTANT_MACROS 1 # endif # if !defined(__STDC_LIMIT_MACROS) # define __STDC_LIMIT_MACROS 1 # endif #endif #if defined(__cplusplus) # define LZO_EXTERN_C extern "C" # define LZO_EXTERN_C_BEGIN extern "C" { # define LZO_EXTERN_C_END } #else # define LZO_EXTERN_C extern # define LZO_EXTERN_C_BEGIN /*empty*/ # define LZO_EXTERN_C_END /*empty*/ #endif #if !defined(__LZO_OS_OVERRIDE) #if (LZO_OS_FREESTANDING) # define LZO_INFO_OS "freestanding" #elif (LZO_OS_EMBEDDED) # define LZO_INFO_OS "embedded" #elif 1 && defined(__IAR_SYSTEMS_ICC__) # define LZO_OS_EMBEDDED 1 # define LZO_INFO_OS "embedded" #elif defined(__CYGWIN__) && defined(__GNUC__) # define LZO_OS_CYGWIN 1 # define LZO_INFO_OS "cygwin" #elif defined(__EMX__) && defined(__GNUC__) # define LZO_OS_EMX 1 # define LZO_INFO_OS "emx" #elif defined(__BEOS__) # define LZO_OS_BEOS 1 # define LZO_INFO_OS "beos" #elif defined(__Lynx__) # define LZO_OS_LYNXOS 1 # define LZO_INFO_OS "lynxos" #elif defined(__OS400__) # define LZO_OS_OS400 1 # define LZO_INFO_OS "os400" #elif defined(__QNX__) # define LZO_OS_QNX 1 # define LZO_INFO_OS "qnx" #elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" #elif defined(__BORLANDC__) && defined(__DPMI16__) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" #elif defined(__ZTC__) && defined(DOS386) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" #elif defined(__OS2__) || defined(__OS2V2__) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_OS216 1 # define LZO_INFO_OS "os216" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_OS2 1 # define LZO_INFO_OS "os2" # else # error "check your limits.h header" # endif #elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) # define LZO_OS_WIN64 1 # define LZO_INFO_OS "win64" #elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" #elif defined(__MWERKS__) && defined(__INTEL__) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" #elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_WIN16 1 # define LZO_INFO_OS "win16" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" # else # error "check your limits.h header" # endif #elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) # if (UINT_MAX == LZO_0xffffL) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_OS_DOS32 1 # define LZO_INFO_OS "dos32" # else # error "check your limits.h header" # endif #elif defined(__WATCOMC__) # if defined(__NT__) && (UINT_MAX == LZO_0xffffL) # define LZO_OS_DOS16 1 # define LZO_INFO_OS "dos16" # elif defined(__NT__) && (__WATCOMC__ < 1100) # define LZO_OS_WIN32 1 # define LZO_INFO_OS "win32" # elif defined(__linux__) || defined(__LINUX__) # define LZO_OS_POSIX 1 # define LZO_INFO_OS "posix" # else # error "please specify a target using the -bt compiler option" # endif #elif defined(__palmos__) # define LZO_OS_PALMOS 1 # define LZO_INFO_OS "palmos" #elif defined(__TOS__) || defined(__atarist__) # define LZO_OS_TOS 1 # define LZO_INFO_OS "tos" #elif defined(macintosh) && !defined(__arm__) && !defined(__i386__) && !defined(__ppc__) && !defined(__x64_64__) # define LZO_OS_MACCLASSIC 1 # define LZO_INFO_OS "macclassic" #elif defined(__VMS) # define LZO_OS_VMS 1 # define LZO_INFO_OS "vms" #elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PS2 1 # define LZO_INFO_OS "console" # define LZO_INFO_OS_CONSOLE "ps2" #elif defined(__mips__) && defined(__psp__) # define LZO_OS_CONSOLE 1 # define LZO_OS_CONSOLE_PSP 1 # define LZO_INFO_OS "console" # define LZO_INFO_OS_CONSOLE "psp" #else # define LZO_OS_POSIX 1 # define LZO_INFO_OS "posix" #endif #if (LZO_OS_POSIX) # if defined(_AIX) || defined(__AIX__) || defined(__aix__) # define LZO_OS_POSIX_AIX 1 # define LZO_INFO_OS_POSIX "aix" # elif defined(__FreeBSD__) # define LZO_OS_POSIX_FREEBSD 1 # define LZO_INFO_OS_POSIX "freebsd" # elif defined(__hpux__) || defined(__hpux) # define LZO_OS_POSIX_HPUX 1 # define LZO_INFO_OS_POSIX "hpux" # elif defined(__INTERIX) # define LZO_OS_POSIX_INTERIX 1 # define LZO_INFO_OS_POSIX "interix" # elif defined(__IRIX__) || defined(__irix__) # define LZO_OS_POSIX_IRIX 1 # define LZO_INFO_OS_POSIX "irix" # elif defined(__linux__) || defined(__linux) || defined(__LINUX__) # define LZO_OS_POSIX_LINUX 1 # define LZO_INFO_OS_POSIX "linux" # elif defined(__APPLE__) && defined(__MACH__) # if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) # define LZO_OS_POSIX_DARWIN 1040 # define LZO_INFO_OS_POSIX "darwin_iphone" # elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) # define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ # define LZO_INFO_OS_POSIX "darwin" # else # define LZO_OS_POSIX_DARWIN 1 # define LZO_INFO_OS_POSIX "darwin" # endif # define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN # elif defined(__minix__) || defined(__minix) # define LZO_OS_POSIX_MINIX 1 # define LZO_INFO_OS_POSIX "minix" # elif defined(__NetBSD__) # define LZO_OS_POSIX_NETBSD 1 # define LZO_INFO_OS_POSIX "netbsd" # elif defined(__OpenBSD__) # define LZO_OS_POSIX_OPENBSD 1 # define LZO_INFO_OS_POSIX "openbsd" # elif defined(__osf__) # define LZO_OS_POSIX_OSF 1 # define LZO_INFO_OS_POSIX "osf" # elif defined(__solaris__) || defined(__sun) # if defined(__SVR4) || defined(__svr4__) # define LZO_OS_POSIX_SOLARIS 1 # define LZO_INFO_OS_POSIX "solaris" # else # define LZO_OS_POSIX_SUNOS 1 # define LZO_INFO_OS_POSIX "sunos" # endif # elif defined(__ultrix__) || defined(__ultrix) # define LZO_OS_POSIX_ULTRIX 1 # define LZO_INFO_OS_POSIX "ultrix" # elif defined(_UNICOS) # define LZO_OS_POSIX_UNICOS 1 # define LZO_INFO_OS_POSIX "unicos" # else # define LZO_OS_POSIX_UNKNOWN 1 # define LZO_INFO_OS_POSIX "unknown" # endif #endif #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) # if (UINT_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) # define LZO_CC_CILLY 1 # define LZO_INFO_CC "Cilly" # if defined(__CILLY__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) # else # define LZO_INFO_CCVER "unknown" # endif #elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) # define LZO_CC_SDCC 1 # define LZO_INFO_CC "sdcc" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) #elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) # define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) # define LZO_INFO_CC "Pathscale C" # define LZO_INFO_CCVER __PATHSCALE__ # if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) # define LZO_CC_INTELC __INTEL_COMPILER # define LZO_INFO_CC "Intel C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_INTELC_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__POCC__) && defined(_WIN32) # define LZO_CC_PELLESC 1 # define LZO_INFO_CC "Pelles C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) #elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) # define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else # define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif # define LZO_CC_ARMCC __ARMCC_VERSION # define LZO_INFO_CC "ARM C Compiler" # define LZO_INFO_CCVER __VERSION__ #elif defined(__clang__) && defined(__c2__) && defined(__c2_version__) && defined(_MSC_VER) # define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) # define LZO_CC_CLANG_C2 _MSC_VER # define LZO_CC_CLANG_VENDOR_MICROSOFT 1 # define LZO_INFO_CC "clang/c2" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__c2_version__) #elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) # if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) # define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) # else # define LZO_CC_CLANG 0x010000L # endif # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_CLANG_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif # if defined(__APPLE_CC__) # define LZO_CC_CLANG_VENDOR_APPLE 1 # define LZO_INFO_CC "clang/apple" # else # define LZO_CC_CLANG_VENDOR_LLVM 1 # define LZO_INFO_CC "clang" # endif # if defined(__clang_version__) # define LZO_INFO_CCVER __clang_version__ # else # define LZO_INFO_CCVER __VERSION__ # endif #elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # if defined(__GNUC_PATCHLEVEL__) # define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # else # define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # endif # define LZO_CC_LLVM LZO_CC_LLVM_GNUC # define LZO_INFO_CC "llvm-gcc" # define LZO_INFO_CCVER __VERSION__ #elif defined(__ACK__) && defined(_ACK) # define LZO_CC_ACK 1 # define LZO_INFO_CC "Amsterdam Compiler Kit C" # define LZO_INFO_CCVER "unknown" #elif defined(__ARMCC_VERSION) && !defined(__GNUC__) # define LZO_CC_ARMCC __ARMCC_VERSION # define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION # define LZO_INFO_CC "ARM C Compiler" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) #elif defined(__AZTEC_C__) # define LZO_CC_AZTECC 1 # define LZO_INFO_CC "Aztec C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) #elif defined(__CODEGEARC__) # define LZO_CC_CODEGEARC 1 # define LZO_INFO_CC "CodeGear C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) #elif defined(__BORLANDC__) # define LZO_CC_BORLANDC 1 # define LZO_INFO_CC "Borland C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) #elif defined(_CRAYC) && defined(_RELEASE) # define LZO_CC_CRAYC 1 # define LZO_INFO_CC "Cray C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) #elif defined(__DMC__) && defined(__SC__) # define LZO_CC_DMC 1 # define LZO_INFO_CC "Digital Mars C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) #elif defined(__DECC) # define LZO_CC_DECC 1 # define LZO_INFO_CC "DEC C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) #elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) # define LZO_CC_GHS 1 # define LZO_INFO_CC "Green Hills C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) # if defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_GHS_MSC _MSC_VER # elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) # define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # endif #elif defined(__HIGHC__) # define LZO_CC_HIGHC 1 # define LZO_INFO_CC "MetaWare High C" # define LZO_INFO_CCVER "unknown" #elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) # define LZO_CC_HPACC __HP_aCC # define LZO_INFO_CC "HP aCC" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) #elif defined(__IAR_SYSTEMS_ICC__) # define LZO_CC_IARC 1 # define LZO_INFO_CC "IAR C" # if defined(__VER__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) # else # define LZO_INFO_CCVER "unknown" # endif #elif defined(__IBMC__) && ((__IBMC__-0) > 0) # define LZO_CC_IBMC __IBMC__ # define LZO_INFO_CC "IBM C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) #elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) # define LZO_CC_IBMC __IBMCPP__ # define LZO_INFO_CC "IBM C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) #elif defined(__KEIL__) && defined(__C166__) # define LZO_CC_KEILC 1 # define LZO_INFO_CC "Keil C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) #elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) # define LZO_CC_LCCWIN32 1 # define LZO_INFO_CC "lcc-win32" # define LZO_INFO_CCVER "unknown" #elif defined(__LCC__) # define LZO_CC_LCC 1 # define LZO_INFO_CC "lcc" # if defined(__LCC_VERSION__) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) # else # define LZO_INFO_CCVER "unknown" # endif #elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) # define LZO_CC_MWERKS __MWERKS__ # define LZO_INFO_CC "Metrowerks C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) #elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) # define LZO_CC_NDPC 1 # define LZO_INFO_CC "Microway NDP C" # define LZO_INFO_CCVER "unknown" #elif defined(__PACIFIC__) # define LZO_CC_PACIFICC 1 # define LZO_INFO_CC "Pacific C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) #elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) # if defined(__PGIC_PATCHLEVEL__) # define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) # else # define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" # endif # define LZO_INFO_CC "Portland Group PGI C" #elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) # define LZO_CC_PGI 1 # define LZO_INFO_CC "Portland Group PGI C" # define LZO_INFO_CCVER "unknown" #elif defined(__PUREC__) && defined(__TOS__) # define LZO_CC_PUREC 1 # define LZO_INFO_CC "Pure C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) #elif defined(__SC__) && defined(__ZTC__) # define LZO_CC_SYMANTECC 1 # define LZO_INFO_CC "Symantec C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) #elif defined(__SUNPRO_C) # define LZO_INFO_CC "SunPro C" # if ((__SUNPRO_C-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_C # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) # else # define LZO_CC_SUNPROC 1 # define LZO_INFO_CCVER "unknown" # endif #elif defined(__SUNPRO_CC) # define LZO_INFO_CC "SunPro C" # if ((__SUNPRO_CC-0) > 0) # define LZO_CC_SUNPROC __SUNPRO_CC # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) # else # define LZO_CC_SUNPROC 1 # define LZO_INFO_CCVER "unknown" # endif #elif defined(__TINYC__) # define LZO_CC_TINYC 1 # define LZO_INFO_CC "Tiny C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) #elif defined(__TSC__) # define LZO_CC_TOPSPEEDC 1 # define LZO_INFO_CC "TopSpeed C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) #elif defined(__WATCOMC__) # define LZO_CC_WATCOMC 1 # define LZO_INFO_CC "Watcom C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) #elif defined(__TURBOC__) # define LZO_CC_TURBOC 1 # define LZO_INFO_CC "Turbo C" # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) #elif defined(__ZTC__) # define LZO_CC_ZORTECHC 1 # define LZO_INFO_CC "Zortech C" # if ((__ZTC__-0) == 0x310) # define LZO_INFO_CCVER "0x310" # else # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) # endif #elif defined(__GNUC__) && defined(__VERSION__) # if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) # define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) # elif defined(__GNUC_MINOR__) # define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) # else # define LZO_CC_GNUC (__GNUC__ * 0x10000L) # endif # define LZO_INFO_CC "gcc" # define LZO_INFO_CCVER __VERSION__ #elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) # define LZO_CC_MSC _MSC_VER # define LZO_INFO_CC "Microsoft C" # if defined(_MSC_FULL_VER) # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) # else # define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) # endif #else # define LZO_CC_UNKNOWN 1 # define LZO_INFO_CC "unknown" # define LZO_INFO_CCVER "unknown" #endif #if (LZO_CC_GNUC) && defined(__OPEN64__) # if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) # define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) # define LZO_CC_OPEN64_GNUC LZO_CC_GNUC # endif #endif #if (LZO_CC_GNUC) && defined(__PCC__) # if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) # define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) # define LZO_CC_PCC_GNUC LZO_CC_GNUC # endif #endif #if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) # error "LZO_CC_MSC: _MSC_FULL_VER is not defined" #endif #if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) # if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) # if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) # define LZO_ARCH_CRAY_MPP 1 # elif defined(_CRAY1) # define LZO_ARCH_CRAY_PVP 1 # endif # endif #endif #if !defined(__LZO_ARCH_OVERRIDE) #if (LZO_ARCH_GENERIC) # define LZO_INFO_ARCH "generic" #elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086 1 # define LZO_INFO_ARCH "i086" #elif defined(__aarch64__) || defined(_M_ARM64) # define LZO_ARCH_ARM64 1 # define LZO_INFO_ARCH "arm64" #elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) # define LZO_ARCH_ALPHA 1 # define LZO_INFO_ARCH "alpha" #elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) # define LZO_ARCH_ALPHA 1 # define LZO_INFO_ARCH "alpha" #elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) # define LZO_ARCH_AMD64 1 # define LZO_INFO_ARCH "amd64" #elif defined(__arm__) || defined(_M_ARM) # define LZO_ARCH_ARM 1 # define LZO_INFO_ARCH "arm" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) # define LZO_ARCH_ARM 1 # define LZO_INFO_ARCH "arm" #elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) # define LZO_ARCH_AVR 1 # define LZO_INFO_ARCH "avr" #elif defined(__avr32__) || defined(__AVR32__) # define LZO_ARCH_AVR32 1 # define LZO_INFO_ARCH "avr32" #elif defined(__bfin__) # define LZO_ARCH_BLACKFIN 1 # define LZO_INFO_ARCH "blackfin" #elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) # define LZO_ARCH_C166 1 # define LZO_INFO_ARCH "c166" #elif defined(__cris__) # define LZO_ARCH_CRIS 1 # define LZO_INFO_ARCH "cris" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) # define LZO_ARCH_EZ80 1 # define LZO_INFO_ARCH "ez80" #elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) # define LZO_ARCH_H8300 1 # define LZO_INFO_ARCH "h8300" #elif defined(__hppa__) || defined(__hppa) # define LZO_ARCH_HPPA 1 # define LZO_INFO_ARCH "hppa" #elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif (LZO_CC_ZORTECHC && defined(__I86__)) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) # define LZO_ARCH_I386 1 # define LZO_ARCH_IA32 1 # define LZO_INFO_ARCH "i386" #elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) # define LZO_ARCH_IA64 1 # define LZO_INFO_ARCH "ia64" #elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) # define LZO_ARCH_M16C 1 # define LZO_INFO_ARCH "m16c" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) # define LZO_ARCH_M16C 1 # define LZO_INFO_ARCH "m16c" #elif defined(__m32r__) # define LZO_ARCH_M32R 1 # define LZO_INFO_ARCH "m32r" #elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) # define LZO_ARCH_M68K 1 # define LZO_INFO_ARCH "m68k" #elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) # define LZO_ARCH_MCS251 1 # define LZO_INFO_ARCH "mcs251" #elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) # define LZO_ARCH_MCS51 1 # define LZO_INFO_ARCH "mcs51" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) # define LZO_ARCH_MCS51 1 # define LZO_INFO_ARCH "mcs51" #elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) # define LZO_ARCH_MIPS 1 # define LZO_INFO_ARCH "mips" #elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) # define LZO_ARCH_MSP430 1 # define LZO_INFO_ARCH "msp430" #elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) # define LZO_ARCH_MSP430 1 # define LZO_INFO_ARCH "msp430" #elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__powerpc64__) || defined(__powerpc64) || defined(__ppc64__) || defined(__PPC64__) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__powerpc64le__) || defined(__powerpc64le) || defined(__ppc64le__) || defined(__PPC64LE__) # define LZO_ARCH_POWERPC 1 # define LZO_INFO_ARCH "powerpc" #elif defined(__riscv) # define LZO_ARCH_RISCV 1 # define LZO_INFO_ARCH "riscv" #elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) # define LZO_ARCH_S390 1 # define LZO_INFO_ARCH "s390" #elif defined(__sh__) || defined(_M_SH) # define LZO_ARCH_SH 1 # define LZO_INFO_ARCH "sh" #elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) # define LZO_ARCH_SPARC 1 # define LZO_INFO_ARCH "sparc" #elif defined(__SPU__) # define LZO_ARCH_SPU 1 # define LZO_INFO_ARCH "spu" #elif (UINT_MAX == LZO_0xffffL) && defined(__z80) # define LZO_ARCH_Z80 1 # define LZO_INFO_ARCH "z80" #elif (LZO_ARCH_CRAY_PVP) # if defined(_CRAYSV1) # define LZO_ARCH_CRAY_SV1 1 # define LZO_INFO_ARCH "cray_sv1" # elif (_ADDR64) # define LZO_ARCH_CRAY_T90 1 # define LZO_INFO_ARCH "cray_t90" # elif (_ADDR32) # define LZO_ARCH_CRAY_YMP 1 # define LZO_INFO_ARCH "cray_ymp" # else # define LZO_ARCH_CRAY_XMP 1 # define LZO_INFO_ARCH "cray_xmp" # endif #else # define LZO_ARCH_UNKNOWN 1 # define LZO_INFO_ARCH "unknown" #endif #endif #if !defined(LZO_ARCH_ARM_THUMB2) #if (LZO_ARCH_ARM) # if defined(__thumb__) || defined(__thumb) || defined(_M_THUMB) # if defined(__thumb2__) # define LZO_ARCH_ARM_THUMB2 1 # elif 1 && defined(__TARGET_ARCH_THUMB) && ((__TARGET_ARCH_THUMB)+0 >= 4) # define LZO_ARCH_ARM_THUMB2 1 # elif 1 && defined(_MSC_VER) && defined(_M_THUMB) && ((_M_THUMB)+0 >= 7) # define LZO_ARCH_ARM_THUMB2 1 # endif # endif #endif #endif #if (LZO_ARCH_ARM_THUMB2) # undef LZO_INFO_ARCH # define LZO_INFO_ARCH "arm_thumb2" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) # error "FIXME - missing define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) # error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" #endif #if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) # error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" #endif #if (LZO_OS_OS216 || LZO_OS_WIN16) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && defined(BLX286)) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) # define LZO_ARCH_I086PM 1 #elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) # define LZO_ARCH_I086PM 1 #endif #if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) # define LZO_ARCH_X64 1 #elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_AMD64 1 #endif #if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) # define LZO_ARCH_AARCH64 1 #elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_ARM64 1 #endif #if (LZO_ARCH_I386 && !LZO_ARCH_X86) # define LZO_ARCH_X86 1 #elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) # define LZO_ARCH_I386 1 #endif #if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I086PM && !LZO_ARCH_I086) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_I086) # if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_ARCH_I386) # if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) # error "unexpected configuration - check your compiler defines" # endif # if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) # error "unexpected configuration - check your compiler defines" # endif # if (ULONG_MAX != LZO_0xffffffffL) # error "unexpected configuration - check your compiler defines" # endif #endif #if (LZO_ARCH_AMD64 || LZO_ARCH_I386) # if !defined(LZO_TARGET_FEATURE_SSE2) # if defined(__SSE2__) # define LZO_TARGET_FEATURE_SSE2 1 # elif defined(_MSC_VER) && (defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) # define LZO_TARGET_FEATURE_SSE2 1 # elif (LZO_CC_INTELC_MSC || LZO_CC_MSC) && defined(_M_AMD64) # define LZO_TARGET_FEATURE_SSE2 1 # endif # endif # if !defined(LZO_TARGET_FEATURE_SSSE3) # if (LZO_TARGET_FEATURE_SSE2) # if defined(__SSSE3__) # define LZO_TARGET_FEATURE_SSSE3 1 # elif defined(_MSC_VER) && defined(__AVX__) # define LZO_TARGET_FEATURE_SSSE3 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_SSE4_2) # if (LZO_TARGET_FEATURE_SSSE3) # if defined(__SSE4_2__) # define LZO_TARGET_FEATURE_SSE4_2 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_AVX) # if (LZO_TARGET_FEATURE_SSSE3) # if defined(__AVX__) # define LZO_TARGET_FEATURE_AVX 1 # endif # endif # endif # if !defined(LZO_TARGET_FEATURE_AVX2) # if (LZO_TARGET_FEATURE_AVX) # if defined(__AVX2__) # define LZO_TARGET_FEATURE_AVX2 1 # endif # endif # endif #endif #if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ARCH_ARM) # if !defined(LZO_TARGET_FEATURE_NEON) # if defined(__ARM_NEON) && ((__ARM_NEON)+0) # define LZO_TARGET_FEATURE_NEON 1 # elif 1 && defined(__ARM_NEON__) && ((__ARM_NEON__)+0) # define LZO_TARGET_FEATURE_NEON 1 # elif 1 && defined(__TARGET_FEATURE_NEON) && ((__TARGET_FEATURE_NEON)+0) # define LZO_TARGET_FEATURE_NEON 1 # endif # endif #elif (LZO_ARCH_ARM64) # if !defined(LZO_TARGET_FEATURE_NEON) # if 1 # define LZO_TARGET_FEATURE_NEON 1 # endif # endif #endif #if 0 #elif !defined(__LZO_MM_OVERRIDE) #if (LZO_ARCH_I086) #if (UINT_MAX != LZO_0xffffL) # error "unexpected configuration - check your compiler defines" #endif #if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) # define LZO_MM_TINY 1 #elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) # define LZO_MM_HUGE 1 #elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) # define LZO_MM_SMALL 1 #elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) # define LZO_MM_MEDIUM 1 #elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) # define LZO_MM_COMPACT 1 #elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) # define LZO_MM_LARGE 1 #elif (LZO_CC_AZTECC) # if defined(_LARGE_CODE) && defined(_LARGE_DATA) # define LZO_MM_LARGE 1 # elif defined(_LARGE_CODE) # define LZO_MM_MEDIUM 1 # elif defined(_LARGE_DATA) # define LZO_MM_COMPACT 1 # else # define LZO_MM_SMALL 1 # endif #elif (LZO_CC_ZORTECHC && defined(__VCM__)) # define LZO_MM_LARGE 1 #else # error "unknown LZO_ARCH_I086 memory model" #endif #if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) #define LZO_HAVE_MM_HUGE_PTR 1 #define LZO_HAVE_MM_HUGE_ARRAY 1 #if (LZO_MM_TINY) # undef LZO_HAVE_MM_HUGE_ARRAY #endif #if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) # undef LZO_HAVE_MM_HUGE_PTR # undef LZO_HAVE_MM_HUGE_ARRAY #elif (LZO_CC_DMC || LZO_CC_SYMANTECC) # undef LZO_HAVE_MM_HUGE_ARRAY #elif (LZO_CC_MSC && defined(_QC)) # undef LZO_HAVE_MM_HUGE_ARRAY # if (_MSC_VER < 600) # undef LZO_HAVE_MM_HUGE_PTR # endif #elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) # undef LZO_HAVE_MM_HUGE_ARRAY #endif #if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) # if (LZO_OS_DOS16) # error "unexpected configuration - check your compiler defines" # elif (LZO_CC_ZORTECHC) # else # error "unexpected configuration - check your compiler defines" # endif #endif #if defined(__cplusplus) extern "C" { #endif #if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) extern void __near __cdecl _AHSHIFT(void); # define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) #elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) # define LZO_MM_AHSHIFT 12 #elif (LZO_CC_WATCOMC) extern unsigned char _HShift; # define LZO_MM_AHSHIFT ((unsigned) _HShift) #else # error "FIXME - implement LZO_MM_AHSHIFT" #endif #if defined(__cplusplus) } #endif #endif #elif (LZO_ARCH_C166) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_C166 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 1) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_C166 __MODEL__" #endif #elif (LZO_ARCH_MCS251) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_MCS251 __MODEL__" #elif ((__MODEL__) == 0) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_MCS251 __MODEL__" #endif #elif (LZO_ARCH_MCS51) #if !defined(__MODEL__) # error "FIXME - LZO_ARCH_MCS51 __MODEL__" #elif ((__MODEL__) == 1) # define LZO_MM_SMALL 1 #elif ((__MODEL__) == 2) # define LZO_MM_LARGE 1 #elif ((__MODEL__) == 3) # define LZO_MM_TINY 1 #elif ((__MODEL__) == 4) # define LZO_MM_XTINY 1 #elif ((__MODEL__) == 5) # define LZO_MM_XSMALL 1 #else # error "FIXME - LZO_ARCH_MCS51 __MODEL__" #endif #elif (LZO_ARCH_CRAY_PVP) # define LZO_MM_PVP 1 #else # define LZO_MM_FLAT 1 #endif #if (LZO_MM_COMPACT) # define LZO_INFO_MM "compact" #elif (LZO_MM_FLAT) # define LZO_INFO_MM "flat" #elif (LZO_MM_HUGE) # define LZO_INFO_MM "huge" #elif (LZO_MM_LARGE) # define LZO_INFO_MM "large" #elif (LZO_MM_MEDIUM) # define LZO_INFO_MM "medium" #elif (LZO_MM_PVP) # define LZO_INFO_MM "pvp" #elif (LZO_MM_SMALL) # define LZO_INFO_MM "small" #elif (LZO_MM_TINY) # define LZO_INFO_MM "tiny" #else # error "unknown memory model" #endif #endif #if !defined(__lzo_gnuc_extension__) #if (LZO_CC_GNUC >= 0x020800ul) # define __lzo_gnuc_extension__ __extension__ #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_gnuc_extension__ __extension__ #elif (LZO_CC_IBMC >= 600) # define __lzo_gnuc_extension__ __extension__ #endif #endif #if !defined(__lzo_gnuc_extension__) # define __lzo_gnuc_extension__ /*empty*/ #endif #if !defined(lzo_has_builtin) #if (LZO_CC_CLANG) && defined(__has_builtin) # define lzo_has_builtin __has_builtin #endif #endif #if !defined(lzo_has_builtin) # define lzo_has_builtin(x) 0 #endif #if !defined(lzo_has_attribute) #if (LZO_CC_CLANG) && defined(__has_attribute) # define lzo_has_attribute __has_attribute #endif #endif #if !defined(lzo_has_attribute) # define lzo_has_attribute(x) 0 #endif #if !defined(lzo_has_declspec_attribute) #if (LZO_CC_CLANG) && defined(__has_declspec_attribute) # define lzo_has_declspec_attribute __has_declspec_attribute #endif #endif #if !defined(lzo_has_declspec_attribute) # define lzo_has_declspec_attribute(x) 0 #endif #if !defined(lzo_has_feature) #if (LZO_CC_CLANG) && defined(__has_feature) # define lzo_has_feature __has_feature #endif #endif #if !defined(lzo_has_feature) # define lzo_has_feature(x) 0 #endif #if !defined(lzo_has_extension) #if (LZO_CC_CLANG) && defined(__has_extension) # define lzo_has_extension __has_extension #elif (LZO_CC_CLANG) && defined(__has_feature) # define lzo_has_extension __has_feature #endif #endif #if !defined(lzo_has_extension) # define lzo_has_extension(x) 0 #endif #if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 # elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 # else # define LZO_CFG_USE_NEW_STYLE_CASTS 1 # endif #endif #if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_CFG_USE_NEW_STYLE_CASTS 0 #endif #if !defined(__cplusplus) # if defined(LZO_CFG_USE_NEW_STYLE_CASTS) # undef LZO_CFG_USE_NEW_STYLE_CASTS # endif # define LZO_CFG_USE_NEW_STYLE_CASTS 0 #endif #if !defined(LZO_REINTERPRET_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast (e)) # endif #endif #if !defined(LZO_REINTERPRET_CAST) # define LZO_REINTERPRET_CAST(t,e) ((t) (e)) #endif #if !defined(LZO_STATIC_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_STATIC_CAST(t,e) (static_cast (e)) # endif #endif #if !defined(LZO_STATIC_CAST) # define LZO_STATIC_CAST(t,e) ((t) (e)) #endif #if !defined(LZO_STATIC_CAST2) # define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) #endif #if !defined(LZO_UNCONST_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNCONST_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNCONST_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) # endif #endif #if !defined(LZO_UNCONST_CAST) # define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) #endif #if !defined(LZO_UNCONST_VOLATILE_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) # endif #endif #if !defined(LZO_UNCONST_VOLATILE_CAST) # define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) #endif #if !defined(LZO_UNVOLATILE_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNVOLATILE_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) # endif #endif #if !defined(LZO_UNVOLATILE_CAST) # define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) #endif #if !defined(LZO_UNVOLATILE_CONST_CAST) # if (LZO_CFG_USE_NEW_STYLE_CASTS) # define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast (e)) # elif (LZO_HAVE_MM_HUGE_PTR) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) # elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) # endif #endif #if !defined(LZO_UNVOLATILE_CONST_CAST) # define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) #endif #if !defined(LZO_PCAST) # if (LZO_HAVE_MM_HUGE_PTR) # define LZO_PCAST(t,e) ((t) (e)) # endif #endif #if !defined(LZO_PCAST) # define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) #endif #if !defined(LZO_CCAST) # if (LZO_HAVE_MM_HUGE_PTR) # define LZO_CCAST(t,e) ((t) (e)) # endif #endif #if !defined(LZO_CCAST) # define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) #endif #if !defined(LZO_ICONV) # define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(LZO_ICAST) # define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(LZO_ITRUNC) # define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) #endif #if !defined(__lzo_cte) # if (LZO_CC_MSC || LZO_CC_WATCOMC) # define __lzo_cte(e) ((void)0,(e)) # elif 1 # define __lzo_cte(e) ((void)0,(e)) # endif #endif #if !defined(__lzo_cte) # define __lzo_cte(e) (e) #endif #if !defined(LZO_BLOCK_BEGIN) # define LZO_BLOCK_BEGIN do { # define LZO_BLOCK_END } while __lzo_cte(0) #endif #if !defined(LZO_UNUSED) # if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) # define LZO_UNUSED(var) ((void) &var) # elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) # define LZO_UNUSED(var) if (&var) ; else # elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) # define LZO_UNUSED(var) ((void) &var) # elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_UNUSED(var) ((void) var) # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_UNUSED(var) if (&var) ; else # elif (LZO_CC_KEILC) # define LZO_UNUSED(var) {extern int lzo_unused__[1-2*!(sizeof(var)>0)]; (void)lzo_unused__;} # elif (LZO_CC_PACIFICC) # define LZO_UNUSED(var) ((void) sizeof(var)) # elif (LZO_CC_WATCOMC) && defined(__cplusplus) # define LZO_UNUSED(var) ((void) var) # else # define LZO_UNUSED(var) ((void) &var) # endif #endif #if !defined(LZO_UNUSED_RESULT) # define LZO_UNUSED_RESULT(var) LZO_UNUSED(var) #endif #if !defined(LZO_UNUSED_FUNC) # if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) # define LZO_UNUSED_FUNC(func) ((void) func) # elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) # define LZO_UNUSED_FUNC(func) if (func) ; else # elif (LZO_CC_CLANG || LZO_CC_LLVM) # define LZO_UNUSED_FUNC(func) ((void) &func) # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_UNUSED_FUNC(func) if (func) ; else # elif (LZO_CC_MSC) # define LZO_UNUSED_FUNC(func) ((void) &func) # elif (LZO_CC_KEILC || LZO_CC_PELLESC) # define LZO_UNUSED_FUNC(func) {extern int lzo_unused__[1-2*!(sizeof((int)func)>0)]; (void)lzo_unused__;} # else # define LZO_UNUSED_FUNC(func) ((void) func) # endif #endif #if !defined(LZO_UNUSED_LABEL) # if (LZO_CC_CLANG >= 0x020800ul) # define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) # elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) # define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l # else # define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l # endif #endif #if !defined(LZO_DEFINE_UNINITIALIZED_VAR) # if 0 # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var # elif 0 && (LZO_CC_GNUC) # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var # else # define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init # endif #endif #if !defined(__lzo_inline) #if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) #elif defined(__cplusplus) # define __lzo_inline inline #elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) # define __lzo_inline inline #elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) # define __lzo_inline __inline #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define __lzo_inline __inline__ #elif (LZO_CC_DMC) # define __lzo_inline __inline #elif (LZO_CC_GHS) # define __lzo_inline __inline__ #elif (LZO_CC_IBMC >= 600) # define __lzo_inline __inline__ #elif (LZO_CC_INTELC) # define __lzo_inline __inline #elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) # define __lzo_inline __inline #elif (LZO_CC_MSC && (_MSC_VER >= 900)) # define __lzo_inline __inline #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_inline __inline__ #endif #endif #if defined(__lzo_inline) # ifndef __lzo_HAVE_inline # define __lzo_HAVE_inline 1 # endif #else # define __lzo_inline /*empty*/ #endif #if !defined(__lzo_forceinline) #if (LZO_CC_GNUC >= 0x030200ul) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) # define __lzo_forceinline __forceinline #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) # define __lzo_forceinline __forceinline #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_forceinline __inline__ __attribute__((__always_inline__)) #endif #endif #if defined(__lzo_forceinline) # ifndef __lzo_HAVE_forceinline # define __lzo_HAVE_forceinline 1 # endif #else # define __lzo_forceinline __lzo_inline #endif #if !defined(__lzo_noinline) #if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) # define __lzo_noinline __attribute__((__noinline__,__used__)) #elif (LZO_CC_GNUC >= 0x030200ul) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) # define __lzo_noinline __declspec(noinline) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_noinline __declspec(noinline) #elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) # if defined(__cplusplus) # else # define __lzo_noinline __declspec(noinline) # endif #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_noinline __attribute__((__noinline__)) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_noinline __attribute__((__noinline__)) #endif #endif #if defined(__lzo_noinline) # ifndef __lzo_HAVE_noinline # define __lzo_HAVE_noinline 1 # endif #else # define __lzo_noinline /*empty*/ #endif #if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) # error "unexpected configuration - check your compiler defines" #endif #if !defined(__lzo_static_inline) #if (LZO_CC_IBMC) # define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline #endif #endif #if !defined(__lzo_static_inline) # define __lzo_static_inline static __lzo_inline #endif #if !defined(__lzo_static_forceinline) #if (LZO_CC_IBMC) # define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline #endif #endif #if !defined(__lzo_static_forceinline) # define __lzo_static_forceinline static __lzo_forceinline #endif #if !defined(__lzo_static_noinline) #if (LZO_CC_IBMC) # define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline #endif #endif #if !defined(__lzo_static_noinline) # define __lzo_static_noinline static __lzo_noinline #endif #if !defined(__lzo_c99_extern_inline) #if defined(__GNUC_GNU_INLINE__) # define __lzo_c99_extern_inline __lzo_inline #elif defined(__GNUC_STDC_INLINE__) # define __lzo_c99_extern_inline extern __lzo_inline #elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) # define __lzo_c99_extern_inline extern __lzo_inline #endif #if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) # define __lzo_c99_extern_inline __lzo_inline #endif #endif #if defined(__lzo_c99_extern_inline) # ifndef __lzo_HAVE_c99_extern_inline # define __lzo_HAVE_c99_extern_inline 1 # endif #else # define __lzo_c99_extern_inline /*empty*/ #endif #if !defined(__lzo_may_alias) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_CLANG >= 0x020900ul) # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 # define __lzo_may_alias __attribute__((__may_alias__)) #elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 # define __lzo_may_alias __attribute__((__may_alias__)) #endif #endif #if defined(__lzo_may_alias) # ifndef __lzo_HAVE_may_alias # define __lzo_HAVE_may_alias 1 # endif #else # define __lzo_may_alias /*empty*/ #endif #if !defined(__lzo_noreturn) #if (LZO_CC_GNUC >= 0x020700ul) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_IBMC >= 700) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) # define __lzo_noreturn __declspec(noreturn) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_noreturn __attribute__((__noreturn__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) # define __lzo_noreturn __declspec(noreturn) #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_noreturn __attribute__((__noreturn__)) #endif #endif #if defined(__lzo_noreturn) # ifndef __lzo_HAVE_noreturn # define __lzo_HAVE_noreturn 1 # endif #else # define __lzo_noreturn /*empty*/ #endif #if !defined(__lzo_nothrow) #if (LZO_CC_GNUC >= 0x030300ul) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) # define __lzo_nothrow __declspec(nothrow) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_nothrow __attribute__((__nothrow__)) #elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) # define __lzo_nothrow __declspec(nothrow) #endif #endif #if defined(__lzo_nothrow) # ifndef __lzo_HAVE_nothrow # define __lzo_HAVE_nothrow 1 # endif #else # define __lzo_nothrow /*empty*/ #endif #if !defined(__lzo_restrict) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_restrict __restrict__ #elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) # define __lzo_restrict __restrict__ #elif (LZO_CC_IBMC >= 1210) # define __lzo_restrict __restrict__ #elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) # define __lzo_restrict __restrict__ #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) # define __lzo_restrict __restrict__ #elif (LZO_CC_MSC && (_MSC_VER >= 1400)) # define __lzo_restrict __restrict #elif (LZO_CC_PGI >= 0x0d0a00ul) # define __lzo_restrict __restrict__ #endif #endif #if defined(__lzo_restrict) # ifndef __lzo_HAVE_restrict # define __lzo_HAVE_restrict 1 # endif #else # define __lzo_restrict /*empty*/ #endif #if !defined(__lzo_alignof) #if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_GHS) && !defined(__cplusplus) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_IBMC >= 600) # define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) #elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) # define __lzo_alignof(e) __alignof__(e) #elif (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_alignof(e) __alignof(e) #elif (LZO_CC_SUNPROC >= 0x5100) # define __lzo_alignof(e) __alignof__(e) #endif #endif #if defined(__lzo_alignof) # ifndef __lzo_HAVE_alignof # define __lzo_HAVE_alignof 1 # endif #endif #if !defined(__lzo_struct_packed) #if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) #elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) #elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) # define __lzo_struct_packed(s) struct s { # define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_struct_packed(s) struct s { # define __lzo_struct_packed_end() } __attribute__((__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_IBMC >= 700) # define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { # define __lzo_struct_packed_end() } __attribute__((__packed__)); # define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { # define __lzo_struct_packed_end() } __pragma(pack(pop)); #elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) # define __lzo_struct_packed(s) _Packed struct s { # define __lzo_struct_packed_end() }; #endif #endif #if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) # define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) #endif #if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) # define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() #endif #if !defined(__lzo_byte_struct) #if defined(__lzo_struct_packed) # define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() # define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() #elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); # define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); #endif #endif #if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) # define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) #endif #if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) #if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) #elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_CILLY || LZO_CC_PCC) #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_struct_align16(s) struct __declspec(align(16)) s { # define __lzo_struct_align16_end() }; # define __lzo_struct_align32(s) struct __declspec(align(32)) s { # define __lzo_struct_align32_end() }; # define __lzo_struct_align64(s) struct __declspec(align(64)) s { # define __lzo_struct_align64_end() }; #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_struct_align16(s) struct s { # define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); # define __lzo_struct_align32(s) struct s { # define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); # define __lzo_struct_align64(s) struct s { # define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); #endif #endif #if !defined(__lzo_union_um) #if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) #elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) #elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) #elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) #elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) # define __lzo_union_am(s) union s { # define __lzo_union_am_end() } __lzo_may_alias; # define __lzo_union_um(s) union s { # define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_IBMC >= 700) # define __lzo_union_am(s) __lzo_gnuc_extension__ union s { # define __lzo_union_am_end() } __lzo_may_alias; # define __lzo_union_um(s) __lzo_gnuc_extension__ union s { # define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); #elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) # define __lzo_union_um(s) __pragma(pack(push,1)) union s { # define __lzo_union_um_end() } __pragma(pack(pop)); #elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) # define __lzo_union_um(s) _Packed union s { # define __lzo_union_um_end() }; #endif #endif #if !defined(__lzo_union_am) # define __lzo_union_am(s) union s { # define __lzo_union_am_end() }; #endif #if !defined(__lzo_constructor) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_constructor __attribute__((__constructor__,__used__)) #elif (LZO_CC_GNUC >= 0x020700ul) # define __lzo_constructor __attribute__((__constructor__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_constructor __attribute__((__constructor__,__used__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_constructor __attribute__((__constructor__)) #endif #endif #if defined(__lzo_constructor) # ifndef __lzo_HAVE_constructor # define __lzo_HAVE_constructor 1 # endif #endif #if !defined(__lzo_destructor) #if (LZO_CC_GNUC >= 0x030400ul) # define __lzo_destructor __attribute__((__destructor__,__used__)) #elif (LZO_CC_GNUC >= 0x020700ul) # define __lzo_destructor __attribute__((__destructor__)) #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) # define __lzo_destructor __attribute__((__destructor__,__used__)) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_destructor __attribute__((__destructor__)) #endif #endif #if defined(__lzo_destructor) # ifndef __lzo_HAVE_destructor # define __lzo_HAVE_destructor 1 # endif #endif #if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) # error "unexpected configuration - check your compiler defines" #endif #if !defined(__lzo_likely) && !defined(__lzo_unlikely) #if (LZO_CC_GNUC >= 0x030200ul) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_IBMC >= 1010) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #elif (LZO_CC_CLANG && LZO_CC_CLANG_C2) #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define __lzo_likely(e) (__builtin_expect(!!(e),1)) # define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) #endif #endif #if defined(__lzo_likely) # ifndef __lzo_HAVE_likely # define __lzo_HAVE_likely 1 # endif #else # define __lzo_likely(e) (e) #endif #if defined(__lzo_very_likely) # ifndef __lzo_HAVE_very_likely # define __lzo_HAVE_very_likely 1 # endif #else # define __lzo_very_likely(e) __lzo_likely(e) #endif #if defined(__lzo_unlikely) # ifndef __lzo_HAVE_unlikely # define __lzo_HAVE_unlikely 1 # endif #else # define __lzo_unlikely(e) (e) #endif #if defined(__lzo_very_unlikely) # ifndef __lzo_HAVE_very_unlikely # define __lzo_HAVE_very_unlikely 1 # endif #else # define __lzo_very_unlikely(e) __lzo_unlikely(e) #endif #if !defined(__lzo_loop_forever) # if (LZO_CC_IBMC) # define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END # else # define __lzo_loop_forever() do { ; } while __lzo_cte(1) # endif #endif #if !defined(__lzo_unreachable) #if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) && lzo_has_builtin(__builtin_unreachable) # define __lzo_unreachable() __builtin_unreachable(); #elif (LZO_CC_GNUC >= 0x040500ul) # define __lzo_unreachable() __builtin_unreachable(); #elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 # define __lzo_unreachable() __builtin_unreachable(); #endif #endif #if defined(__lzo_unreachable) # ifndef __lzo_HAVE_unreachable # define __lzo_HAVE_unreachable 1 # endif #else # if 0 # define __lzo_unreachable() ((void)0); # else # define __lzo_unreachable() __lzo_loop_forever(); # endif #endif #if !defined(lzo_unused_funcs_impl) # if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) # define lzo_unused_funcs_impl(r,f) static r __attribute__((__unused__)) f # elif 1 && (LZO_CC_BORLANDC || LZO_CC_GNUC) # define lzo_unused_funcs_impl(r,f) static r f # else # define lzo_unused_funcs_impl(r,f) __lzo_static_forceinline r f # endif #endif #ifndef __LZO_CTA_NAME #if (LZO_CFG_USE_COUNTER) # define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) #else # define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) #endif #endif #if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) # if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_DMC || LZO_CC_SYMANTECC) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END # elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END # elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END # else # define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END # endif #endif #if !defined(LZO_COMPILE_TIME_ASSERT) # if (LZO_CC_AZTECC) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} # elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030000ul)) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} # elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) # define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} # elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) # define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} # elif (LZO_CC_GNUC >= 0x040700ul) # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} # elif (LZO_CC_MSC && (_MSC_VER < 900)) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) # define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; # else # define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} # endif #endif #if (LZO_LANG_ASSEMBLER) # undef LZO_COMPILE_TIME_ASSERT_HEADER # define LZO_COMPILE_TIME_ASSERT_HEADER(e) /*empty*/ #else LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) #if defined(__cplusplus) extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } #endif LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) #endif #if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) # if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) # elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) # define __lzo_cdecl __cdecl # define __lzo_cdecl_atexit /*empty*/ # define __lzo_cdecl_main __cdecl # if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) # define __lzo_cdecl_qsort __pascal # elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) # define __lzo_cdecl_qsort _stdcall # else # define __lzo_cdecl_qsort __cdecl # endif # elif (LZO_CC_WATCOMC) # define __lzo_cdecl __cdecl # else # define __lzo_cdecl __cdecl # define __lzo_cdecl_atexit __cdecl # define __lzo_cdecl_main __cdecl # define __lzo_cdecl_qsort __cdecl # endif # if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) # elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) # define __lzo_cdecl_sighandler __pascal # elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) # define __lzo_cdecl_sighandler _stdcall # elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) # define __lzo_cdecl_sighandler __clrcall # elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) # if defined(_DLL) # define __lzo_cdecl_sighandler _far _cdecl _loadds # elif defined(_MT) # define __lzo_cdecl_sighandler _far _cdecl # else # define __lzo_cdecl_sighandler _cdecl # endif # else # define __lzo_cdecl_sighandler __cdecl # endif #elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) # define __lzo_cdecl __cdecl #elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) # define __lzo_cdecl cdecl #endif #if !defined(__lzo_cdecl) # define __lzo_cdecl /*empty*/ #endif #if !defined(__lzo_cdecl_atexit) # define __lzo_cdecl_atexit /*empty*/ #endif #if !defined(__lzo_cdecl_main) # define __lzo_cdecl_main /*empty*/ #endif #if !defined(__lzo_cdecl_qsort) # define __lzo_cdecl_qsort /*empty*/ #endif #if !defined(__lzo_cdecl_sighandler) # define __lzo_cdecl_sighandler /*empty*/ #endif #if !defined(__lzo_cdecl_va) # define __lzo_cdecl_va __lzo_cdecl #endif #if !(LZO_CFG_NO_WINDOWS_H) #if !defined(LZO_HAVE_WINDOWS_H) #if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) # if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) # elif ((LZO_OS_WIN32 && defined(__PW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul))) # elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) # else # define LZO_HAVE_WINDOWS_H 1 # endif #endif #endif #endif #define LZO_SIZEOF_CHAR 1 #ifndef LZO_SIZEOF_SHORT #if defined(SIZEOF_SHORT) # define LZO_SIZEOF_SHORT (SIZEOF_SHORT) #elif defined(__SIZEOF_SHORT__) # define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) #endif #endif #ifndef LZO_SIZEOF_INT #if defined(SIZEOF_INT) # define LZO_SIZEOF_INT (SIZEOF_INT) #elif defined(__SIZEOF_INT__) # define LZO_SIZEOF_INT (__SIZEOF_INT__) #endif #endif #ifndef LZO_SIZEOF_LONG #if defined(SIZEOF_LONG) # define LZO_SIZEOF_LONG (SIZEOF_LONG) #elif defined(__SIZEOF_LONG__) # define LZO_SIZEOF_LONG (__SIZEOF_LONG__) #endif #endif #ifndef LZO_SIZEOF_LONG_LONG #if defined(SIZEOF_LONG_LONG) # define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) #elif defined(__SIZEOF_LONG_LONG__) # define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) #endif #endif #ifndef LZO_SIZEOF___INT16 #if defined(SIZEOF___INT16) # define LZO_SIZEOF___INT16 (SIZEOF___INT16) #endif #endif #ifndef LZO_SIZEOF___INT32 #if defined(SIZEOF___INT32) # define LZO_SIZEOF___INT32 (SIZEOF___INT32) #endif #endif #ifndef LZO_SIZEOF___INT64 #if defined(SIZEOF___INT64) # define LZO_SIZEOF___INT64 (SIZEOF___INT64) #endif #endif #ifndef LZO_SIZEOF_VOID_P #if defined(SIZEOF_VOID_P) # define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) #elif defined(__SIZEOF_POINTER__) # define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) #endif #endif #ifndef LZO_SIZEOF_SIZE_T #if defined(SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) #elif defined(__SIZEOF_SIZE_T__) # define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) #endif #endif #ifndef LZO_SIZEOF_PTRDIFF_T #if defined(SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) #elif defined(__SIZEOF_PTRDIFF_T__) # define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) #endif #endif #define __LZO_LSR(x,b) (((x)+0ul) >> (b)) #if !defined(LZO_SIZEOF_SHORT) # if (LZO_ARCH_CRAY_PVP) # define LZO_SIZEOF_SHORT 8 # elif (USHRT_MAX == LZO_0xffffL) # define LZO_SIZEOF_SHORT 2 # elif (__LZO_LSR(USHRT_MAX,7) == 1) # define LZO_SIZEOF_SHORT 1 # elif (__LZO_LSR(USHRT_MAX,15) == 1) # define LZO_SIZEOF_SHORT 2 # elif (__LZO_LSR(USHRT_MAX,31) == 1) # define LZO_SIZEOF_SHORT 4 # elif (__LZO_LSR(USHRT_MAX,63) == 1) # define LZO_SIZEOF_SHORT 8 # elif (__LZO_LSR(USHRT_MAX,127) == 1) # define LZO_SIZEOF_SHORT 16 # else # error "LZO_SIZEOF_SHORT" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) #if !defined(LZO_SIZEOF_INT) # if (LZO_ARCH_CRAY_PVP) # define LZO_SIZEOF_INT 8 # elif (UINT_MAX == LZO_0xffffL) # define LZO_SIZEOF_INT 2 # elif (UINT_MAX == LZO_0xffffffffL) # define LZO_SIZEOF_INT 4 # elif (__LZO_LSR(UINT_MAX,7) == 1) # define LZO_SIZEOF_INT 1 # elif (__LZO_LSR(UINT_MAX,15) == 1) # define LZO_SIZEOF_INT 2 # elif (__LZO_LSR(UINT_MAX,31) == 1) # define LZO_SIZEOF_INT 4 # elif (__LZO_LSR(UINT_MAX,63) == 1) # define LZO_SIZEOF_INT 8 # elif (__LZO_LSR(UINT_MAX,127) == 1) # define LZO_SIZEOF_INT 16 # else # error "LZO_SIZEOF_INT" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) #if !defined(LZO_SIZEOF_LONG) # if (ULONG_MAX == LZO_0xffffffffL) # define LZO_SIZEOF_LONG 4 # elif (__LZO_LSR(ULONG_MAX,7) == 1) # define LZO_SIZEOF_LONG 1 # elif (__LZO_LSR(ULONG_MAX,15) == 1) # define LZO_SIZEOF_LONG 2 # elif (__LZO_LSR(ULONG_MAX,31) == 1) # define LZO_SIZEOF_LONG 4 # elif (__LZO_LSR(ULONG_MAX,39) == 1) # define LZO_SIZEOF_LONG 5 # elif (__LZO_LSR(ULONG_MAX,63) == 1) # define LZO_SIZEOF_LONG 8 # elif (__LZO_LSR(ULONG_MAX,127) == 1) # define LZO_SIZEOF_LONG 16 # else # error "LZO_SIZEOF_LONG" # endif #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) #if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) #if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) # if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) # if (LZO_CC_GNUC >= 0x030300ul) # if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) # define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG # elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) # define LZO_SIZEOF_LONG_LONG 4 # endif # endif # endif #endif #endif #if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) #if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) #if (LZO_ARCH_I086 && LZO_CC_DMC) #elif (LZO_CC_CILLY) && defined(__GNUC__) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) # define LZO_SIZEOF_LONG_LONG 8 #elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_OS_WIN64 || defined(_WIN64)) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_DMC)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) # define LZO_SIZEOF___INT64 8 #elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) # define LZO_SIZEOF___INT64 8 #elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) # define LZO_SIZEOF___INT64 8 #elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) # define LZO_SIZEOF___INT64 8 #elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) # define LZO_SIZEOF_LONG_LONG 8 #elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) # define LZO_SIZEOF_LONG_LONG 8 #elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) #elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # define LZO_SIZEOF_LONG_LONG 8 #endif #endif #endif #if defined(__cplusplus) && (LZO_CC_GNUC) # if (LZO_CC_GNUC < 0x020800ul) # undef LZO_SIZEOF_LONG_LONG # endif #endif #if (LZO_CFG_NO_LONG_LONG) # undef LZO_SIZEOF_LONG_LONG #elif defined(__NO_LONG_LONG) # undef LZO_SIZEOF_LONG_LONG #elif defined(_NO_LONGLONG) # undef LZO_SIZEOF_LONG_LONG #endif #if !defined(LZO_WORDSIZE) #if (LZO_ARCH_ALPHA) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_AMD64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_ARM64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_AVR) # define LZO_WORDSIZE 1 #elif (LZO_ARCH_H8300) # if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) # define LZO_WORDSIZE 4 # else # define LZO_WORDSIZE 2 # endif #elif (LZO_ARCH_I086) # define LZO_WORDSIZE 2 #elif (LZO_ARCH_IA64) # define LZO_WORDSIZE 8 #elif (LZO_ARCH_M16C) # define LZO_WORDSIZE 2 #elif (LZO_ARCH_SPU) # define LZO_WORDSIZE 4 #elif (LZO_ARCH_Z80) # define LZO_WORDSIZE 1 #elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) # define LZO_WORDSIZE 8 #elif (LZO_OS_OS400 || defined(__OS400__)) # define LZO_WORDSIZE 8 #elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) # define LZO_WORDSIZE 8 #endif #endif #if !defined(LZO_SIZEOF_VOID_P) #if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) # define LZO_SIZEOF_VOID_P 4 #elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) # define LZO_SIZEOF_VOID_P 8 #elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) # define LZO_SIZEOF_VOID_P 8 #elif defined(__LP64__) || defined(__LP64) || defined(_LP64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) # define LZO_SIZEOF_VOID_P 8 #elif (LZO_ARCH_AVR) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_ARCH_H8300) # if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 4) # if defined(__NORMAL_MODE__) # define LZO_SIZEOF_VOID_P 2 # else # define LZO_SIZEOF_VOID_P 4 # endif # else LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 2) # define LZO_SIZEOF_VOID_P 2 # endif # if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT # endif #elif (LZO_ARCH_I086) # if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) # define LZO_SIZEOF_VOID_P 2 # elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) # define LZO_SIZEOF_VOID_P 4 # else # error "invalid LZO_ARCH_I086 memory model" # endif #elif (LZO_ARCH_M16C) # if defined(__m32c_cpu__) || defined(__m32cm_cpu__) # define LZO_SIZEOF_VOID_P 4 # else # define LZO_SIZEOF_VOID_P 2 # endif #elif (LZO_ARCH_SPU) # define LZO_SIZEOF_VOID_P 4 #elif (LZO_ARCH_Z80) # define LZO_SIZEOF_VOID_P 2 #elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) # define LZO_SIZEOF_VOID_P 4 #elif (LZO_OS_OS400 || defined(__OS400__)) # if defined(__LLP64_IFC__) # define LZO_SIZEOF_VOID_P 8 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG # else # define LZO_SIZEOF_VOID_P 16 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG # endif #elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) # define LZO_SIZEOF_VOID_P 8 # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG #endif #endif #if !defined(LZO_SIZEOF_VOID_P) # define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG #endif LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) #if !defined(LZO_SIZEOF_SIZE_T) #if (LZO_ARCH_I086 || LZO_ARCH_M16C) # define LZO_SIZEOF_SIZE_T 2 #endif #endif #if !defined(LZO_SIZEOF_SIZE_T) # define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P #endif #if defined(offsetof) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) #endif #if !defined(LZO_SIZEOF_PTRDIFF_T) #if (LZO_ARCH_I086) # if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P # elif (LZO_MM_COMPACT || LZO_MM_LARGE) # if (LZO_CC_BORLANDC || LZO_CC_TURBOC) # define LZO_SIZEOF_PTRDIFF_T 4 # else # define LZO_SIZEOF_PTRDIFF_T 2 # endif # else # error "invalid LZO_ARCH_I086 memory model" # endif #endif #endif #if !defined(LZO_SIZEOF_PTRDIFF_T) # define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T #endif #if defined(offsetof) LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) #endif #if !defined(LZO_WORDSIZE) # define LZO_WORDSIZE LZO_SIZEOF_VOID_P #endif #if (LZO_ABI_NEUTRAL_ENDIAN) # undef LZO_ABI_BIG_ENDIAN # undef LZO_ABI_LITTLE_ENDIAN #elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) #if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) # define LZO_ABI_BIG_ENDIAN 1 #elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) # define LZO_ABI_LITTLE_ENDIAN 1 #elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430 || LZO_ARCH_RISCV) # define LZO_ABI_LITTLE_ENDIAN 1 #elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) # if (__LITTLE_ENDIAN__ == 1) # define LZO_ABI_LITTLE_ENDIAN 1 # else # define LZO_ABI_BIG_ENDIAN 1 # endif #elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM) && defined(_MSC_VER) && defined(_WIN32) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) # if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) # error "unexpected configuration - check your compiler defines" # elif defined(__BIG_ENDIAN) # define LZO_ABI_BIG_ENDIAN 1 # else # define LZO_ABI_LITTLE_ENDIAN 1 # endif # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_ARM64) && defined(_MSC_VER) && defined(_WIN32) # define LZO_ABI_LITTLE_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) # define LZO_ABI_BIG_ENDIAN 1 #elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) # define LZO_ABI_LITTLE_ENDIAN 1 #endif #endif #if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) # error "unexpected configuration - check your compiler defines" #endif #if (LZO_ABI_BIG_ENDIAN) # define LZO_INFO_ABI_ENDIAN "be" #elif (LZO_ABI_LITTLE_ENDIAN) # define LZO_INFO_ABI_ENDIAN "le" #elif (LZO_ABI_NEUTRAL_ENDIAN) # define LZO_INFO_ABI_ENDIAN "neutral" #endif #if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) # define LZO_ABI_I8LP16 1 # define LZO_INFO_ABI_PM "i8lp16" #elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) # define LZO_ABI_ILP16 1 # define LZO_INFO_ABI_PM "ilp16" #elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_LP32 1 # define LZO_INFO_ABI_PM "lp32" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_ILP32 1 # define LZO_INFO_ABI_PM "ilp32" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) # define LZO_ABI_LLP64 1 # define LZO_INFO_ABI_PM "llp64" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) # define LZO_ABI_LP64 1 # define LZO_INFO_ABI_PM "lp64" #elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) # define LZO_ABI_ILP64 1 # define LZO_INFO_ABI_PM "ilp64" #elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) # define LZO_ABI_IP32L64 1 # define LZO_INFO_ABI_PM "ip32l64" #endif #if (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_VOID_P == 4 && LZO_WORDSIZE == 8) # define LZO_ABI_IP32W64 1 # ifndef LZO_INFO_ABI_PM # define LZO_INFO_ABI_PM "ip32w64" # endif #endif #if 0 #elif !defined(__LZO_LIBC_OVERRIDE) #if (LZO_LIBC_NAKED) # define LZO_INFO_LIBC "naked" #elif (LZO_LIBC_FREESTANDING) # define LZO_INFO_LIBC "freestanding" #elif (LZO_LIBC_MOSTLY_FREESTANDING) # define LZO_INFO_LIBC "mfreestanding" #elif (LZO_LIBC_ISOC90) # define LZO_INFO_LIBC "isoc90" #elif (LZO_LIBC_ISOC99) # define LZO_INFO_LIBC "isoc99" #elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) # define LZO_LIBC_ISOC90 1 # define LZO_INFO_LIBC "isoc90" #elif defined(__dietlibc__) # define LZO_LIBC_DIETLIBC 1 # define LZO_INFO_LIBC "dietlibc" #elif defined(_NEWLIB_VERSION) # define LZO_LIBC_NEWLIB 1 # define LZO_INFO_LIBC "newlib" #elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) # if defined(__UCLIBC_SUBLEVEL__) # define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) # else # define LZO_LIBC_UCLIBC 0x00090bL # endif # define LZO_INFO_LIBC "uc" "libc" #elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) # define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) # define LZO_INFO_LIBC "glibc" #elif (LZO_CC_MWERKS) && defined(__MSL__) # define LZO_LIBC_MSL __MSL__ # define LZO_INFO_LIBC "msl" #elif 1 && defined(__IAR_SYSTEMS_ICC__) # define LZO_LIBC_ISOC90 1 # define LZO_INFO_LIBC "isoc90" #else # define LZO_LIBC_DEFAULT 1 # define LZO_INFO_LIBC "default" #endif #endif #if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) # define LZO_ASM_SYNTAX_MSC 1 #elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) #elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) #elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) # define LZO_ASM_SYNTAX_GNUC 1 #elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) # define LZO_ASM_SYNTAX_GNUC 1 #elif (LZO_CC_GNUC) # define LZO_ASM_SYNTAX_GNUC 1 #endif #if (LZO_ASM_SYNTAX_GNUC) #if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) # define __LZO_ASM_CLOBBER "ax" # define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) # define __LZO_ASM_CLOBBER "memory" # define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #else # define __LZO_ASM_CLOBBER "cc", "memory" # define __LZO_ASM_CLOBBER_LIST_CC : "cc" # define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" # define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ #endif #endif #if (LZO_ARCH_ALPHA) # define LZO_OPT_AVOID_UINT_INDEX 1 #elif (LZO_ARCH_AMD64) # define LZO_OPT_AVOID_INT_INDEX 1 # define LZO_OPT_AVOID_UINT_INDEX 1 # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif #elif (LZO_ARCH_ARM) # if defined(__ARM_FEATURE_UNALIGNED) # if ((__ARM_FEATURE_UNALIGNED)+0) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif # elif 1 && (LZO_ARCH_ARM_THUMB2) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__ARM_ARCH) && ((__ARM_ARCH)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 6) && (defined(__TARGET_PROFILE_A) || defined(__TARGET_PROFILE_R)) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # elif 1 && defined(_MSC_VER) && defined(_M_ARM) && ((_M_ARM)+0 >= 7) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif #elif (LZO_ARCH_ARM64) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif #elif (LZO_ARCH_CRIS) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif #elif (LZO_ARCH_I386) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif #elif (LZO_ARCH_IA64) # define LZO_OPT_AVOID_INT_INDEX 1 # define LZO_OPT_AVOID_UINT_INDEX 1 # define LZO_OPT_PREFER_POSTINC 1 #elif (LZO_ARCH_M68K) # define LZO_OPT_PREFER_POSTINC 1 # define LZO_OPT_PREFER_PREDEC 1 # if defined(__mc68020__) && !defined(__mcoldfire__) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # endif #elif (LZO_ARCH_MIPS) # define LZO_OPT_AVOID_UINT_INDEX 1 #elif (LZO_ARCH_POWERPC) # define LZO_OPT_PREFER_PREINC 1 # define LZO_OPT_PREFER_PREDEC 1 # if (LZO_ABI_BIG_ENDIAN) || (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif # endif #elif (LZO_ARCH_RISCV) # define LZO_OPT_AVOID_UINT_INDEX 1 # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif #elif (LZO_ARCH_S390) # ifndef LZO_OPT_UNALIGNED16 # define LZO_OPT_UNALIGNED16 1 # endif # ifndef LZO_OPT_UNALIGNED32 # define LZO_OPT_UNALIGNED32 1 # endif # if (LZO_WORDSIZE == 8) # ifndef LZO_OPT_UNALIGNED64 # define LZO_OPT_UNALIGNED64 1 # endif # endif #elif (LZO_ARCH_SH) # define LZO_OPT_PREFER_POSTINC 1 # define LZO_OPT_PREFER_PREDEC 1 #endif #ifndef LZO_CFG_NO_INLINE_ASM #if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) # define LZO_CFG_NO_INLINE_ASM 1 #elif (LZO_CC_LLVM) # define LZO_CFG_NO_INLINE_ASM 1 #endif #endif #if (LZO_CFG_NO_INLINE_ASM) # undef LZO_ASM_SYNTAX_MSC # undef LZO_ASM_SYNTAX_GNUC # undef __LZO_ASM_CLOBBER # undef __LZO_ASM_CLOBBER_LIST_CC # undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY # undef __LZO_ASM_CLOBBER_LIST_EMPTY #endif #ifndef LZO_CFG_NO_UNALIGNED #if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) # define LZO_CFG_NO_UNALIGNED 1 #endif #endif #if (LZO_CFG_NO_UNALIGNED) # undef LZO_OPT_UNALIGNED16 # undef LZO_OPT_UNALIGNED32 # undef LZO_OPT_UNALIGNED64 #endif #if defined(__LZO_INFOSTR_MM) #elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) # define __LZO_INFOSTR_MM "" #elif defined(LZO_INFO_MM) # define __LZO_INFOSTR_MM "." LZO_INFO_MM #else # define __LZO_INFOSTR_MM "" #endif #if defined(__LZO_INFOSTR_PM) #elif defined(LZO_INFO_ABI_PM) # define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM #else # define __LZO_INFOSTR_PM "" #endif #if defined(__LZO_INFOSTR_ENDIAN) #elif defined(LZO_INFO_ABI_ENDIAN) # define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN #else # define __LZO_INFOSTR_ENDIAN "" #endif #if defined(__LZO_INFOSTR_OSNAME) #elif defined(LZO_INFO_OS_CONSOLE) # define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE #elif defined(LZO_INFO_OS_POSIX) # define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX #else # define __LZO_INFOSTR_OSNAME LZO_INFO_OS #endif #if defined(__LZO_INFOSTR_LIBC) #elif defined(LZO_INFO_LIBC) # define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC #else # define __LZO_INFOSTR_LIBC "" #endif #if defined(__LZO_INFOSTR_CCVER) #elif defined(LZO_INFO_CCVER) # define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER #else # define __LZO_INFOSTR_CCVER "" #endif #define LZO_INFO_STRING \ LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER #if !(LZO_CFG_SKIP_LZO_TYPES) #if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) # error "missing defines for sizes" #endif #if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) # error "missing defines for sizes" #endif #define LZO_TYPEOF_CHAR 1u #define LZO_TYPEOF_SHORT 2u #define LZO_TYPEOF_INT 3u #define LZO_TYPEOF_LONG 4u #define LZO_TYPEOF_LONG_LONG 5u #define LZO_TYPEOF___INT8 17u #define LZO_TYPEOF___INT16 18u #define LZO_TYPEOF___INT32 19u #define LZO_TYPEOF___INT64 20u #define LZO_TYPEOF___INT128 21u #define LZO_TYPEOF___INT256 22u #define LZO_TYPEOF___MODE_QI 33u #define LZO_TYPEOF___MODE_HI 34u #define LZO_TYPEOF___MODE_SI 35u #define LZO_TYPEOF___MODE_DI 36u #define LZO_TYPEOF___MODE_TI 37u #define LZO_TYPEOF_CHAR_P 129u #if !defined(lzo_llong_t) #if (LZO_SIZEOF_LONG_LONG+0 > 0) # if !(LZO_LANG_ASSEMBLER) __lzo_gnuc_extension__ typedef long long lzo_llong_t__; __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; # endif # define lzo_llong_t lzo_llong_t__ # define lzo_ullong_t lzo_ullong_t__ #endif #endif #if !defined(lzo_int16e_t) #if (LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) && (LZO_SIZEOF_SHORT != 2) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T #endif #if (LZO_SIZEOF_LONG == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) # define lzo_int16e_t long # define lzo_uint16e_t unsigned long # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_INT == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) # define lzo_int16e_t int # define lzo_uint16e_t unsigned int # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == 2) # define lzo_int16e_t short int # define lzo_uint16e_t unsigned short int # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_SHORT #elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); # endif # define lzo_int16e_t lzo_int16e_hi_t__ # define lzo_uint16e_t lzo_uint16e_hi_t__ # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___MODE_HI #elif (LZO_SIZEOF___INT16 == 2) # define lzo_int16e_t __int16 # define lzo_uint16e_t unsigned __int16 # define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___INT16 #else #endif #endif #if defined(lzo_int16e_t) # define LZO_SIZEOF_LZO_INT16E_T 2 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) #endif #if !defined(lzo_int32e_t) #if (LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) && (LZO_SIZEOF_INT != 4) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T #endif #if (LZO_SIZEOF_LONG == 4) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) # define lzo_int32e_t long int # define lzo_uint32e_t unsigned long int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_INT == 4) # define lzo_int32e_t int # define lzo_uint32e_t unsigned int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == 4) # define lzo_int32e_t short int # define lzo_uint32e_t unsigned short int # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_SHORT #elif (LZO_SIZEOF_LONG_LONG == 4) # define lzo_int32e_t lzo_llong_t # define lzo_uint32e_t lzo_ullong_t # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG_LONG #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); # endif # define lzo_int32e_t lzo_int32e_si_t__ # define lzo_uint32e_t lzo_uint32e_si_t__ # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI #elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) # if !(LZO_LANG_ASSEMBLER) typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); # endif # define lzo_int32e_t lzo_int32e_si_t__ # define lzo_uint32e_t lzo_uint32e_si_t__ # define LZO_INT32_C(c) (c##LL) # define LZO_UINT32_C(c) (c##ULL) # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI #elif (LZO_SIZEOF___INT32 == 4) # define lzo_int32e_t __int32 # define lzo_uint32e_t unsigned __int32 # define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___INT32 #else #endif #endif #if defined(lzo_int32e_t) # define LZO_SIZEOF_LZO_INT32E_T 4 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) #endif #if !defined(lzo_int64e_t) #if (LZO_SIZEOF___INT64 == 8) # if (LZO_CC_BORLANDC) && !defined(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T) # define LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T LZO_TYPEOF___INT64 # endif #endif #if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && (LZO_SIZEOF_LONG_LONG != 8) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T #endif #if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) && (LZO_SIZEOF___INT64 != 8) # undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T #endif #if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_int64e_t int # define lzo_uint64e_t unsigned int # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) # define lzo_int64e_t long int # define lzo_uint64e_t unsigned long int # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) # define lzo_int64e_t lzo_llong_t # define lzo_uint64e_t lzo_ullong_t # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG_LONG # if (LZO_CC_BORLANDC) # define LZO_INT64_C(c) ((c) + 0ll) # define LZO_UINT64_C(c) ((c) + 0ull) # elif 0 # define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) # define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) # else # define LZO_INT64_C(c) (c##LL) # define LZO_UINT64_C(c) (c##ULL) # endif #elif (LZO_SIZEOF___INT64 == 8) # define lzo_int64e_t __int64 # define lzo_uint64e_t unsigned __int64 # define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF___INT64 # if (LZO_CC_BORLANDC) # define LZO_INT64_C(c) ((c) + 0i64) # define LZO_UINT64_C(c) ((c) + 0ui64) # else # define LZO_INT64_C(c) (c##i64) # define LZO_UINT64_C(c) (c##ui64) # endif #else #endif #endif #if defined(lzo_int64e_t) # define LZO_SIZEOF_LZO_INT64E_T 8 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) #endif #if !defined(lzo_int32l_t) #if defined(lzo_int32e_t) # define lzo_int32l_t lzo_int32e_t # define lzo_uint32l_t lzo_uint32e_t # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T # define LZO_TYPEOF_LZO_INT32L_T LZO_TYPEOF_LZO_INT32E_T #elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_int32l_t int # define lzo_uint32l_t unsigned int # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_INT #elif (LZO_SIZEOF_LONG >= 4) # define lzo_int32l_t long int # define lzo_uint32l_t unsigned long int # define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_LONG #else # error "lzo_int32l_t" #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) #endif #if !defined(lzo_int64l_t) #if defined(lzo_int64e_t) # define lzo_int64l_t lzo_int64e_t # define lzo_uint64l_t lzo_uint64e_t # define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T # define LZO_TYPEOF_LZO_INT64L_T LZO_TYPEOF_LZO_INT64E_T #else #endif #endif #if defined(lzo_int64l_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) #endif #if !defined(lzo_int32f_t) #if (LZO_SIZEOF_SIZE_T >= 8) # define lzo_int32f_t lzo_int64l_t # define lzo_uint32f_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT64L_T #else # define lzo_int32f_t lzo_int32l_t # define lzo_uint32f_t lzo_uint32l_t # define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T # define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT32L_T #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) #endif #if !defined(lzo_int64f_t) #if defined(lzo_int64l_t) # define lzo_int64f_t lzo_int64l_t # define lzo_uint64f_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INT64F_T LZO_TYPEOF_LZO_INT64L_T #else #endif #endif #if defined(lzo_int64f_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) #endif #if !defined(lzo_intptr_t) #if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) # define __LZO_INTPTR_T_IS_POINTER 1 # if !(LZO_LANG_ASSEMBLER) typedef char * lzo_intptr_t; typedef char * lzo_uintptr_t; # endif # define lzo_intptr_t lzo_intptr_t # define lzo_uintptr_t lzo_uintptr_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_CHAR_P #elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) # if !(LZO_LANG_ASSEMBLER) typedef __w64 int lzo_intptr_t; typedef __w64 unsigned int lzo_uintptr_t; # endif # define lzo_intptr_t lzo_intptr_t # define lzo_uintptr_t lzo_uintptr_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) # define lzo_intptr_t short # define lzo_uintptr_t unsigned short # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_SHORT #elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) # define lzo_intptr_t int # define lzo_uintptr_t unsigned int # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT #elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) # define lzo_intptr_t long # define lzo_uintptr_t unsigned long # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LONG #elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) # define lzo_intptr_t lzo_int64l_t # define lzo_uintptr_t lzo_uint64l_t # define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LZO_INT64L_T #else # error "lzo_intptr_t" #endif #endif #if 1 LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) #endif #if !defined(lzo_word_t) #if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) #if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) # define lzo_word_t lzo_uintptr_t # define lzo_sword_t lzo_intptr_t # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LZO_INTPTR_T #elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) # define lzo_word_t unsigned long # define lzo_sword_t long # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LONG #elif (LZO_WORDSIZE == LZO_SIZEOF_INT) # define lzo_word_t unsigned int # define lzo_sword_t int # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_INT #elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) # define lzo_word_t unsigned short # define lzo_sword_t short # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_SHORT #elif (LZO_WORDSIZE == 1) # define lzo_word_t unsigned char # define lzo_sword_t signed char # define LZO_SIZEOF_LZO_WORD_T 1 # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_CHAR #elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) # define lzo_word_t lzo_uint64l_t # define lzo_sword_t lzo_int64l_t # define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T # define LZO_TYPEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T #elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) #if 0 # if !(LZO_LANG_ASSEMBLER) typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); # endif # define lzo_word_t lzo_word_t # define lzo_sword_t lzo_sword_t # define LZO_SIZEOF_LZO_WORD_T 16 # define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF___MODE_V16QI #endif #else # error "lzo_word_t" #endif #endif #endif #if 1 && defined(lzo_word_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) #endif #if 1 #define lzo_int8_t signed char #define lzo_uint8_t unsigned char #define LZO_SIZEOF_LZO_INT8_T 1 #define LZO_TYPEOF_LZO_INT8_T LZO_TYPEOF_CHAR LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) #endif #if defined(lzo_int16e_t) #define lzo_int16_t lzo_int16e_t #define lzo_uint16_t lzo_uint16e_t #define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T #define LZO_TYPEOF_LZO_INT16_T LZO_TYPEOF_LZO_INT16E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) #endif #if defined(lzo_int32e_t) #define lzo_int32_t lzo_int32e_t #define lzo_uint32_t lzo_uint32e_t #define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T #define LZO_TYPEOF_LZO_INT32_T LZO_TYPEOF_LZO_INT32E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) #endif #if defined(lzo_int64e_t) #define lzo_int64_t lzo_int64e_t #define lzo_uint64_t lzo_uint64e_t #define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T #define LZO_TYPEOF_LZO_INT64_T LZO_TYPEOF_LZO_INT64E_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) #endif #if 1 #define lzo_int_least32_t lzo_int32l_t #define lzo_uint_least32_t lzo_uint32l_t #define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T #define LZO_TYPEOF_LZO_INT_LEAST32_T LZO_TYPEOF_LZO_INT32L_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) #endif #if defined(lzo_int64l_t) #define lzo_int_least64_t lzo_int64l_t #define lzo_uint_least64_t lzo_uint64l_t #define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T #define LZO_TYPEOF_LZO_INT_LEAST64_T LZO_TYPEOF_LZO_INT64L_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) #endif #if 1 #define lzo_int_fast32_t lzo_int32f_t #define lzo_uint_fast32_t lzo_uint32f_t #define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T #define LZO_TYPEOF_LZO_INT_FAST32_T LZO_TYPEOF_LZO_INT32F_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) #endif #if defined(lzo_int64f_t) #define lzo_int_fast64_t lzo_int64f_t #define lzo_uint_fast64_t lzo_uint64f_t #define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T #define LZO_TYPEOF_LZO_INT_FAST64_T LZO_TYPEOF_LZO_INT64F_T LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) #endif #if !defined(LZO_INT16_C) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) # define LZO_INT16_C(c) ((c) + 0) # define LZO_UINT16_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) # define LZO_INT16_C(c) ((c) + 0L) # define LZO_UINT16_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 2) # define LZO_INT16_C(c) (c) # define LZO_UINT16_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 2) # define LZO_INT16_C(c) (c##L) # define LZO_UINT16_C(c) (c##UL) # else # error "LZO_INT16_C" # endif #endif #if !defined(LZO_INT32_C) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) # define LZO_INT32_C(c) ((c) + 0) # define LZO_UINT32_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) # define LZO_INT32_C(c) ((c) + 0L) # define LZO_UINT32_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 4) # define LZO_INT32_C(c) (c) # define LZO_UINT32_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 4) # define LZO_INT32_C(c) (c##L) # define LZO_UINT32_C(c) (c##UL) # elif (LZO_SIZEOF_LONG_LONG >= 4) # define LZO_INT32_C(c) (c##LL) # define LZO_UINT32_C(c) (c##ULL) # else # error "LZO_INT32_C" # endif #endif #if !defined(LZO_INT64_C) && defined(lzo_int64l_t) # if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) # define LZO_INT64_C(c) ((c) + 0) # define LZO_UINT64_C(c) ((c) + 0U) # elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) # define LZO_INT64_C(c) ((c) + 0L) # define LZO_UINT64_C(c) ((c) + 0UL) # elif (LZO_SIZEOF_INT >= 8) # define LZO_INT64_C(c) (c) # define LZO_UINT64_C(c) (c##U) # elif (LZO_SIZEOF_LONG >= 8) # define LZO_INT64_C(c) (c##L) # define LZO_UINT64_C(c) (c##UL) # else # error "LZO_INT64_C" # endif #endif #endif #endif #endif #undef LZO_HAVE_CONFIG_H #include "minilzo.h" #if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x20a0) # error "version mismatch in miniLZO source files" #endif #ifdef MINILZO_HAVE_CONFIG_H # define LZO_HAVE_CONFIG_H 1 #endif #ifndef __LZO_CONF_H #define __LZO_CONF_H 1 #if !defined(__LZO_IN_MINILZO) #if defined(LZO_CFG_FREESTANDING) && (LZO_CFG_FREESTANDING) # define LZO_LIBC_FREESTANDING 1 # define LZO_OS_FREESTANDING 1 #endif #if defined(LZO_CFG_EXTRA_CONFIG_HEADER) # include LZO_CFG_EXTRA_CONFIG_HEADER #endif #if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) # error "include this file first" #endif #if defined(LZO_CFG_BUILD_DLL) && (LZO_CFG_BUILD_DLL+0) && !defined(__LZO_EXPORT1) && !defined(__LZO_EXPORT2) && 0 #ifndef __LZODEFS_H_INCLUDED #if defined(LZO_HAVE_CONFIG_H) # include #endif #include #include #include #endif #endif #include #if defined(LZO_CFG_EXTRA_CONFIG_HEADER2) # include LZO_CFG_EXTRA_CONFIG_HEADER2 #endif #endif #if !defined(__LZOCONF_H_INCLUDED) || (LZO_VERSION+0 != 0x20a0) # error "version mismatch" #endif #if (LZO_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1100)) # pragma warning(disable: 4702) #endif #if (LZO_CC_MSC && (_MSC_VER >= 1000)) # pragma warning(disable: 4127 4701) # pragma warning(disable: 4514 4710 4711) #endif #if (LZO_CC_MSC && (_MSC_VER >= 1300)) # pragma warning(disable: 4820) #endif #if (LZO_CC_MSC && (_MSC_VER >= 1800)) # pragma warning(disable: 4746) #endif #if (LZO_CC_INTELC && (__INTEL_COMPILER >= 900)) # pragma warning(disable: 1684) #endif #if (LZO_CC_SUNPROC) #if !defined(__cplusplus) # pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED) # pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP) # pragma error_messages(off,E_STATEMENT_NOT_REACHED) #endif #endif #if !defined(__LZO_NOEXPORT1) # define __LZO_NOEXPORT1 /*empty*/ #endif #if !defined(__LZO_NOEXPORT2) # define __LZO_NOEXPORT2 /*empty*/ #endif #if 1 # define LZO_PUBLIC_DECL(r) LZO_EXTERN(r) #endif #if 1 # define LZO_PUBLIC_IMPL(r) LZO_PUBLIC(r) #endif #if !defined(LZO_LOCAL_DECL) # define LZO_LOCAL_DECL(r) __LZO_EXTERN_C LZO_LOCAL_IMPL(r) #endif #if !defined(LZO_LOCAL_IMPL) # define LZO_LOCAL_IMPL(r) __LZO_NOEXPORT1 r __LZO_NOEXPORT2 __LZO_CDECL #endif #if 1 # define LZO_STATIC_DECL(r) LZO_PRIVATE(r) #endif #if 1 # define LZO_STATIC_IMPL(r) LZO_PRIVATE(r) #endif #if defined(__LZO_IN_MINILZO) || (LZO_CFG_FREESTANDING) #elif 1 # include #else # define LZO_WANT_ACC_INCD_H 1 #endif #if defined(LZO_HAVE_CONFIG_H) # define LZO_CFG_NO_CONFIG_HEADER 1 #endif #if 1 && !defined(LZO_CFG_FREESTANDING) #if 1 && !defined(HAVE_STRING_H) #define HAVE_STRING_H 1 #endif #if 1 && !defined(HAVE_MEMCMP) #define HAVE_MEMCMP 1 #endif #if 1 && !defined(HAVE_MEMCPY) #define HAVE_MEMCPY 1 #endif #if 1 && !defined(HAVE_MEMMOVE) #define HAVE_MEMMOVE 1 #endif #if 1 && !defined(HAVE_MEMSET) #define HAVE_MEMSET 1 #endif #endif #if 1 && defined(HAVE_STRING_H) #include #endif #if 1 || defined(lzo_int8_t) || defined(lzo_uint8_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint8_t) == 1) #endif #if 1 || defined(lzo_int16_t) || defined(lzo_uint16_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint16_t) == 2) #endif #if 1 || defined(lzo_int32_t) || defined(lzo_uint32_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32_t) == 4) #endif #if defined(lzo_int64_t) || defined(lzo_uint64_t) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64_t) == 8) #endif #if (LZO_CFG_FREESTANDING) # undef HAVE_MEMCMP # undef HAVE_MEMCPY # undef HAVE_MEMMOVE # undef HAVE_MEMSET #endif #if !(HAVE_MEMCMP) # undef memcmp # define memcmp(a,b,c) lzo_memcmp(a,b,c) #else # undef lzo_memcmp # define lzo_memcmp(a,b,c) memcmp(a,b,c) #endif #if !(HAVE_MEMCPY) # undef memcpy # define memcpy(a,b,c) lzo_memcpy(a,b,c) #else # undef lzo_memcpy # define lzo_memcpy(a,b,c) memcpy(a,b,c) #endif #if !(HAVE_MEMMOVE) # undef memmove # define memmove(a,b,c) lzo_memmove(a,b,c) #else # undef lzo_memmove # define lzo_memmove(a,b,c) memmove(a,b,c) #endif #if !(HAVE_MEMSET) # undef memset # define memset(a,b,c) lzo_memset(a,b,c) #else # undef lzo_memset # define lzo_memset(a,b,c) memset(a,b,c) #endif #undef NDEBUG #if (LZO_CFG_FREESTANDING) # undef LZO_DEBUG # define NDEBUG 1 # undef assert # define assert(e) ((void)0) #else # if !defined(LZO_DEBUG) # define NDEBUG 1 # endif # include #endif #if 0 && defined(__BOUNDS_CHECKING_ON) # include #else # define BOUNDS_CHECKING_OFF_DURING(stmt) stmt # define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) #endif #if (LZO_CFG_PGO) # undef __lzo_likely # undef __lzo_unlikely # define __lzo_likely(e) (e) # define __lzo_unlikely(e) (e) #endif #undef _ #undef __ #undef ___ #undef ____ #undef _p0 #undef _p1 #undef _p2 #undef _p3 #undef _p4 #undef _s0 #undef _s1 #undef _s2 #undef _s3 #undef _s4 #undef _ww #if 1 # define LZO_BYTE(x) ((unsigned char) (x)) #else # define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) #endif #define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) #define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) #define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) #define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) #define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) #define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) #define LZO_SIZE(bits) (1u << (bits)) #define LZO_MASK(bits) (LZO_SIZE(bits) - 1) #define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) #define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) #if !defined(DMUL) #if 0 # define DMUL(a,b) ((lzo_xint) ((lzo_uint32_t)(a) * (lzo_uint32_t)(b))) #else # define DMUL(a,b) ((lzo_xint) ((a) * (b))) #endif #endif #ifndef __LZO_FUNC_H #define __LZO_FUNC_H 1 #if !defined(LZO_BITOPS_USE_ASM_BITSCAN) && !defined(LZO_BITOPS_USE_GNUC_BITSCAN) && !defined(LZO_BITOPS_USE_MSC_BITSCAN) #if 1 && (LZO_ARCH_AMD64) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_ASM_SYNTAX_GNUC) #define LZO_BITOPS_USE_ASM_BITSCAN 1 #elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul)))) #define LZO_BITOPS_USE_GNUC_BITSCAN 1 #elif (LZO_OS_WIN32 || LZO_OS_WIN64) && ((LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 1010)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) #define LZO_BITOPS_USE_MSC_BITSCAN 1 #if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) #include #endif #if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) #pragma intrinsic(_BitScanReverse) #pragma intrinsic(_BitScanForward) #endif #if (LZO_CC_MSC) && (LZO_ARCH_AMD64) #pragma intrinsic(_BitScanReverse64) #pragma intrinsic(_BitScanForward64) #endif #endif #endif __lzo_static_forceinline unsigned lzo_bitops_ctlz32_func(lzo_uint32_t v) { #if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) unsigned long r; (void) _BitScanReverse(&r, v); return (unsigned) r ^ 31; #define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) #elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) lzo_uint32_t r; __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); return (unsigned) r ^ 31; #define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT == 4) unsigned r; r = (unsigned) __builtin_clz(v); return r; #define lzo_bitops_ctlz32(v) ((unsigned) __builtin_clz(v)) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8) unsigned r; r = (unsigned) __builtin_clzl(v); return r ^ 32; #define lzo_bitops_ctlz32(v) (((unsigned) __builtin_clzl(v)) ^ 32) #else LZO_UNUSED(v); return 0; #endif } #if defined(lzo_uint64_t) __lzo_static_forceinline unsigned lzo_bitops_ctlz64_func(lzo_uint64_t v) { #if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) unsigned long r; (void) _BitScanReverse64(&r, v); return (unsigned) r ^ 63; #define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) #elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) lzo_uint64_t r; __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); return (unsigned) r ^ 63; #define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8) unsigned r; r = (unsigned) __builtin_clzl(v); return r; #define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzl(v)) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG == 8) && (LZO_WORDSIZE >= 8) unsigned r; r = (unsigned) __builtin_clzll(v); return r; #define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzll(v)) #else LZO_UNUSED(v); return 0; #endif } #endif __lzo_static_forceinline unsigned lzo_bitops_cttz32_func(lzo_uint32_t v) { #if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) unsigned long r; (void) _BitScanForward(&r, v); return (unsigned) r; #define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) #elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) lzo_uint32_t r; __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); return (unsigned) r; #define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT >= 4) unsigned r; r = (unsigned) __builtin_ctz(v); return r; #define lzo_bitops_cttz32(v) ((unsigned) __builtin_ctz(v)) #else LZO_UNUSED(v); return 0; #endif } #if defined(lzo_uint64_t) __lzo_static_forceinline unsigned lzo_bitops_cttz64_func(lzo_uint64_t v) { #if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) unsigned long r; (void) _BitScanForward64(&r, v); return (unsigned) r; #define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) #elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) lzo_uint64_t r; __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); return (unsigned) r; #define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG >= 8) && (LZO_WORDSIZE >= 8) unsigned r; r = (unsigned) __builtin_ctzl(v); return r; #define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzl(v)) #elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG >= 8) && (LZO_WORDSIZE >= 8) unsigned r; r = (unsigned) __builtin_ctzll(v); return r; #define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzll(v)) #else LZO_UNUSED(v); return 0; #endif } #endif lzo_unused_funcs_impl(void, lzo_bitops_unused_funcs)(void) { LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); LZO_UNUSED_FUNC(lzo_bitops_ctlz32_func); LZO_UNUSED_FUNC(lzo_bitops_cttz32_func); #if defined(lzo_uint64_t) LZO_UNUSED_FUNC(lzo_bitops_ctlz64_func); LZO_UNUSED_FUNC(lzo_bitops_cttz64_func); #endif } #if defined(__lzo_alignof) && !(LZO_CFG_NO_UNALIGNED) #if !defined(lzo_memops_tcheck__) && 0 #define lzo_memops_tcheck__(t,a,b) ((void)0, sizeof(t) == (a) && __lzo_alignof(t) == (b)) #endif #endif #ifndef lzo_memops_TU0p #define lzo_memops_TU0p void __LZO_MMODEL * #endif #ifndef lzo_memops_TU1p #define lzo_memops_TU1p unsigned char __LZO_MMODEL * #endif #ifndef lzo_memops_TU2p #if (LZO_OPT_UNALIGNED16) typedef lzo_uint16_t __lzo_may_alias lzo_memops_TU2; #define lzo_memops_TU2p volatile lzo_memops_TU2 * #elif defined(__lzo_byte_struct) __lzo_byte_struct(lzo_memops_TU2_struct,2) typedef struct lzo_memops_TU2_struct lzo_memops_TU2; #else struct lzo_memops_TU2_struct { unsigned char a[2]; } __lzo_may_alias; typedef struct lzo_memops_TU2_struct lzo_memops_TU2; #endif #ifndef lzo_memops_TU2p #define lzo_memops_TU2p lzo_memops_TU2 * #endif #endif #ifndef lzo_memops_TU4p #if (LZO_OPT_UNALIGNED32) typedef lzo_uint32_t __lzo_may_alias lzo_memops_TU4; #define lzo_memops_TU4p volatile lzo_memops_TU4 __LZO_MMODEL * #elif defined(__lzo_byte_struct) __lzo_byte_struct(lzo_memops_TU4_struct,4) typedef struct lzo_memops_TU4_struct lzo_memops_TU4; #else struct lzo_memops_TU4_struct { unsigned char a[4]; } __lzo_may_alias; typedef struct lzo_memops_TU4_struct lzo_memops_TU4; #endif #ifndef lzo_memops_TU4p #define lzo_memops_TU4p lzo_memops_TU4 __LZO_MMODEL * #endif #endif #ifndef lzo_memops_TU8p #if (LZO_OPT_UNALIGNED64) typedef lzo_uint64_t __lzo_may_alias lzo_memops_TU8; #define lzo_memops_TU8p volatile lzo_memops_TU8 __LZO_MMODEL * #elif defined(__lzo_byte_struct) __lzo_byte_struct(lzo_memops_TU8_struct,8) typedef struct lzo_memops_TU8_struct lzo_memops_TU8; #else struct lzo_memops_TU8_struct { unsigned char a[8]; } __lzo_may_alias; typedef struct lzo_memops_TU8_struct lzo_memops_TU8; #endif #ifndef lzo_memops_TU8p #define lzo_memops_TU8p lzo_memops_TU8 __LZO_MMODEL * #endif #endif #ifndef lzo_memops_set_TU1p #define lzo_memops_set_TU1p volatile lzo_memops_TU1p #endif #ifndef lzo_memops_move_TU1p #define lzo_memops_move_TU1p lzo_memops_TU1p #endif #define LZO_MEMOPS_SET1(dd,cc) \ LZO_BLOCK_BEGIN \ lzo_memops_set_TU1p d__1 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ d__1[0] = LZO_BYTE(cc); \ LZO_BLOCK_END #define LZO_MEMOPS_SET2(dd,cc) \ LZO_BLOCK_BEGIN \ lzo_memops_set_TU1p d__2 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ d__2[0] = LZO_BYTE(cc); d__2[1] = LZO_BYTE(cc); \ LZO_BLOCK_END #define LZO_MEMOPS_SET3(dd,cc) \ LZO_BLOCK_BEGIN \ lzo_memops_set_TU1p d__3 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ d__3[0] = LZO_BYTE(cc); d__3[1] = LZO_BYTE(cc); d__3[2] = LZO_BYTE(cc); \ LZO_BLOCK_END #define LZO_MEMOPS_SET4(dd,cc) \ LZO_BLOCK_BEGIN \ lzo_memops_set_TU1p d__4 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ d__4[0] = LZO_BYTE(cc); d__4[1] = LZO_BYTE(cc); d__4[2] = LZO_BYTE(cc); d__4[3] = LZO_BYTE(cc); \ LZO_BLOCK_END #define LZO_MEMOPS_MOVE1(dd,ss) \ LZO_BLOCK_BEGIN \ lzo_memops_move_TU1p d__1 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_move_TU1p s__1 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ d__1[0] = s__1[0]; \ LZO_BLOCK_END #define LZO_MEMOPS_MOVE2(dd,ss) \ LZO_BLOCK_BEGIN \ lzo_memops_move_TU1p d__2 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_move_TU1p s__2 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ d__2[0] = s__2[0]; d__2[1] = s__2[1]; \ LZO_BLOCK_END #define LZO_MEMOPS_MOVE3(dd,ss) \ LZO_BLOCK_BEGIN \ lzo_memops_move_TU1p d__3 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_move_TU1p s__3 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ d__3[0] = s__3[0]; d__3[1] = s__3[1]; d__3[2] = s__3[2]; \ LZO_BLOCK_END #define LZO_MEMOPS_MOVE4(dd,ss) \ LZO_BLOCK_BEGIN \ lzo_memops_move_TU1p d__4 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_move_TU1p s__4 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ d__4[0] = s__4[0]; d__4[1] = s__4[1]; d__4[2] = s__4[2]; d__4[3] = s__4[3]; \ LZO_BLOCK_END #define LZO_MEMOPS_MOVE8(dd,ss) \ LZO_BLOCK_BEGIN \ lzo_memops_move_TU1p d__8 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_move_TU1p s__8 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ d__8[0] = s__8[0]; d__8[1] = s__8[1]; d__8[2] = s__8[2]; d__8[3] = s__8[3]; \ d__8[4] = s__8[4]; d__8[5] = s__8[5]; d__8[6] = s__8[6]; d__8[7] = s__8[7]; \ LZO_BLOCK_END LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU1p)0)==1) #define LZO_MEMOPS_COPY1(dd,ss) LZO_MEMOPS_MOVE1(dd,ss) #if (LZO_OPT_UNALIGNED16) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2) #define LZO_MEMOPS_COPY2(dd,ss) \ * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss) #elif defined(lzo_memops_tcheck__) #define LZO_MEMOPS_COPY2(dd,ss) \ LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU2,2,1)) { \ * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss); \ } else { LZO_MEMOPS_MOVE2(dd,ss); } LZO_BLOCK_END #else #define LZO_MEMOPS_COPY2(dd,ss) LZO_MEMOPS_MOVE2(dd,ss) #endif #if (LZO_OPT_UNALIGNED32) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4) #define LZO_MEMOPS_COPY4(dd,ss) \ * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss) #elif defined(lzo_memops_tcheck__) #define LZO_MEMOPS_COPY4(dd,ss) \ LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU4,4,1)) { \ * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss); \ } else { LZO_MEMOPS_MOVE4(dd,ss); } LZO_BLOCK_END #else #define LZO_MEMOPS_COPY4(dd,ss) LZO_MEMOPS_MOVE4(dd,ss) #endif #if (LZO_WORDSIZE != 8) #define LZO_MEMOPS_COPY8(dd,ss) \ LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END #else #if (LZO_OPT_UNALIGNED64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8) #define LZO_MEMOPS_COPY8(dd,ss) \ * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss) #elif (LZO_OPT_UNALIGNED32) #define LZO_MEMOPS_COPY8(dd,ss) \ LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END #elif defined(lzo_memops_tcheck__) #define LZO_MEMOPS_COPY8(dd,ss) \ LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU8,8,1)) { \ * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss); \ } else { LZO_MEMOPS_MOVE8(dd,ss); } LZO_BLOCK_END #else #define LZO_MEMOPS_COPY8(dd,ss) LZO_MEMOPS_MOVE8(dd,ss) #endif #endif #define LZO_MEMOPS_COPYN(dd,ss,nn) \ LZO_BLOCK_BEGIN \ lzo_memops_TU1p d__n = (lzo_memops_TU1p) (lzo_memops_TU0p) (dd); \ const lzo_memops_TU1p s__n = (const lzo_memops_TU1p) (const lzo_memops_TU0p) (ss); \ lzo_uint n__n = (nn); \ while ((void)0, n__n >= 8) { LZO_MEMOPS_COPY8(d__n, s__n); d__n += 8; s__n += 8; n__n -= 8; } \ if ((void)0, n__n >= 4) { LZO_MEMOPS_COPY4(d__n, s__n); d__n += 4; s__n += 4; n__n -= 4; } \ if ((void)0, n__n > 0) do { *d__n++ = *s__n++; } while (--n__n > 0); \ LZO_BLOCK_END __lzo_static_forceinline lzo_uint16_t lzo_memops_get_le16(const lzo_voidp ss) { lzo_uint16_t v; #if (LZO_ABI_LITTLE_ENDIAN) LZO_MEMOPS_COPY2(&v, ss); #elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) const lzo_memops_TU2p s = (const lzo_memops_TU2p) ss; unsigned long vv; __asm__("lhbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); v = (lzo_uint16_t) vv; #else const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; v = (lzo_uint16_t) (((lzo_uint16_t)s[0]) | ((lzo_uint16_t)s[1] << 8)); #endif return v; } #if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) #define LZO_MEMOPS_GET_LE16(ss) (* (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)) #else #define LZO_MEMOPS_GET_LE16(ss) lzo_memops_get_le16(ss) #endif __lzo_static_forceinline lzo_uint32_t lzo_memops_get_le32(const lzo_voidp ss) { lzo_uint32_t v; #if (LZO_ABI_LITTLE_ENDIAN) LZO_MEMOPS_COPY4(&v, ss); #elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) const lzo_memops_TU4p s = (const lzo_memops_TU4p) ss; unsigned long vv; __asm__("lwbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); v = (lzo_uint32_t) vv; #else const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; v = (lzo_uint32_t) (((lzo_uint32_t)s[0]) | ((lzo_uint32_t)s[1] << 8) | ((lzo_uint32_t)s[2] << 16) | ((lzo_uint32_t)s[3] << 24)); #endif return v; } #if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) #define LZO_MEMOPS_GET_LE32(ss) (* (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)) #else #define LZO_MEMOPS_GET_LE32(ss) lzo_memops_get_le32(ss) #endif #if (LZO_OPT_UNALIGNED64) && (LZO_ABI_LITTLE_ENDIAN) #define LZO_MEMOPS_GET_LE64(ss) (* (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)) #endif __lzo_static_forceinline lzo_uint16_t lzo_memops_get_ne16(const lzo_voidp ss) { lzo_uint16_t v; LZO_MEMOPS_COPY2(&v, ss); return v; } #if (LZO_OPT_UNALIGNED16) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2) #define LZO_MEMOPS_GET_NE16(ss) (* (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)) #else #define LZO_MEMOPS_GET_NE16(ss) lzo_memops_get_ne16(ss) #endif __lzo_static_forceinline lzo_uint32_t lzo_memops_get_ne32(const lzo_voidp ss) { lzo_uint32_t v; LZO_MEMOPS_COPY4(&v, ss); return v; } #if (LZO_OPT_UNALIGNED32) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4) #define LZO_MEMOPS_GET_NE32(ss) (* (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)) #else #define LZO_MEMOPS_GET_NE32(ss) lzo_memops_get_ne32(ss) #endif #if (LZO_OPT_UNALIGNED64) LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8) #define LZO_MEMOPS_GET_NE64(ss) (* (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)) #endif __lzo_static_forceinline void lzo_memops_put_le16(lzo_voidp dd, lzo_uint16_t vv) { #if (LZO_ABI_LITTLE_ENDIAN) LZO_MEMOPS_COPY2(dd, &vv); #elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) lzo_memops_TU2p d = (lzo_memops_TU2p) dd; unsigned long v = vv; __asm__("sthbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); #else lzo_memops_TU1p d = (lzo_memops_TU1p) dd; d[0] = LZO_BYTE((vv ) & 0xff); d[1] = LZO_BYTE((vv >> 8) & 0xff); #endif } #if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) #define LZO_MEMOPS_PUT_LE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) #else #define LZO_MEMOPS_PUT_LE16(dd,vv) lzo_memops_put_le16(dd,vv) #endif __lzo_static_forceinline void lzo_memops_put_le32(lzo_voidp dd, lzo_uint32_t vv) { #if (LZO_ABI_LITTLE_ENDIAN) LZO_MEMOPS_COPY4(dd, &vv); #elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) lzo_memops_TU4p d = (lzo_memops_TU4p) dd; unsigned long v = vv; __asm__("stwbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); #else lzo_memops_TU1p d = (lzo_memops_TU1p) dd; d[0] = LZO_BYTE((vv ) & 0xff); d[1] = LZO_BYTE((vv >> 8) & 0xff); d[2] = LZO_BYTE((vv >> 16) & 0xff); d[3] = LZO_BYTE((vv >> 24) & 0xff); #endif } #if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) #define LZO_MEMOPS_PUT_LE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) #else #define LZO_MEMOPS_PUT_LE32(dd,vv) lzo_memops_put_le32(dd,vv) #endif __lzo_static_forceinline void lzo_memops_put_ne16(lzo_voidp dd, lzo_uint16_t vv) { LZO_MEMOPS_COPY2(dd, &vv); } #if (LZO_OPT_UNALIGNED16) #define LZO_MEMOPS_PUT_NE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) #else #define LZO_MEMOPS_PUT_NE16(dd,vv) lzo_memops_put_ne16(dd,vv) #endif __lzo_static_forceinline void lzo_memops_put_ne32(lzo_voidp dd, lzo_uint32_t vv) { LZO_MEMOPS_COPY4(dd, &vv); } #if (LZO_OPT_UNALIGNED32) #define LZO_MEMOPS_PUT_NE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) #else #define LZO_MEMOPS_PUT_NE32(dd,vv) lzo_memops_put_ne32(dd,vv) #endif lzo_unused_funcs_impl(void, lzo_memops_unused_funcs)(void) { LZO_UNUSED_FUNC(lzo_memops_unused_funcs); LZO_UNUSED_FUNC(lzo_memops_get_le16); LZO_UNUSED_FUNC(lzo_memops_get_le32); LZO_UNUSED_FUNC(lzo_memops_get_ne16); LZO_UNUSED_FUNC(lzo_memops_get_ne32); LZO_UNUSED_FUNC(lzo_memops_put_le16); LZO_UNUSED_FUNC(lzo_memops_put_le32); LZO_UNUSED_FUNC(lzo_memops_put_ne16); LZO_UNUSED_FUNC(lzo_memops_put_ne32); } #endif #ifndef UA_SET1 #define UA_SET1 LZO_MEMOPS_SET1 #endif #ifndef UA_SET2 #define UA_SET2 LZO_MEMOPS_SET2 #endif #ifndef UA_SET3 #define UA_SET3 LZO_MEMOPS_SET3 #endif #ifndef UA_SET4 #define UA_SET4 LZO_MEMOPS_SET4 #endif #ifndef UA_MOVE1 #define UA_MOVE1 LZO_MEMOPS_MOVE1 #endif #ifndef UA_MOVE2 #define UA_MOVE2 LZO_MEMOPS_MOVE2 #endif #ifndef UA_MOVE3 #define UA_MOVE3 LZO_MEMOPS_MOVE3 #endif #ifndef UA_MOVE4 #define UA_MOVE4 LZO_MEMOPS_MOVE4 #endif #ifndef UA_MOVE8 #define UA_MOVE8 LZO_MEMOPS_MOVE8 #endif #ifndef UA_COPY1 #define UA_COPY1 LZO_MEMOPS_COPY1 #endif #ifndef UA_COPY2 #define UA_COPY2 LZO_MEMOPS_COPY2 #endif #ifndef UA_COPY3 #define UA_COPY3 LZO_MEMOPS_COPY3 #endif #ifndef UA_COPY4 #define UA_COPY4 LZO_MEMOPS_COPY4 #endif #ifndef UA_COPY8 #define UA_COPY8 LZO_MEMOPS_COPY8 #endif #ifndef UA_COPYN #define UA_COPYN LZO_MEMOPS_COPYN #endif #ifndef UA_COPYN_X #define UA_COPYN_X LZO_MEMOPS_COPYN #endif #ifndef UA_GET_LE16 #define UA_GET_LE16 LZO_MEMOPS_GET_LE16 #endif #ifndef UA_GET_LE32 #define UA_GET_LE32 LZO_MEMOPS_GET_LE32 #endif #ifdef LZO_MEMOPS_GET_LE64 #ifndef UA_GET_LE64 #define UA_GET_LE64 LZO_MEMOPS_GET_LE64 #endif #endif #ifndef UA_GET_NE16 #define UA_GET_NE16 LZO_MEMOPS_GET_NE16 #endif #ifndef UA_GET_NE32 #define UA_GET_NE32 LZO_MEMOPS_GET_NE32 #endif #ifdef LZO_MEMOPS_GET_NE64 #ifndef UA_GET_NE64 #define UA_GET_NE64 LZO_MEMOPS_GET_NE64 #endif #endif #ifndef UA_PUT_LE16 #define UA_PUT_LE16 LZO_MEMOPS_PUT_LE16 #endif #ifndef UA_PUT_LE32 #define UA_PUT_LE32 LZO_MEMOPS_PUT_LE32 #endif #ifndef UA_PUT_NE16 #define UA_PUT_NE16 LZO_MEMOPS_PUT_NE16 #endif #ifndef UA_PUT_NE32 #define UA_PUT_NE32 LZO_MEMOPS_PUT_NE32 #endif #define MEMCPY8_DS(dest,src,len) \ lzo_memcpy(dest,src,len); dest += len; src += len #define BZERO8_PTR(s,l,n) \ lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) #define MEMCPY_DS(dest,src,len) \ do *dest++ = *src++; while (--len > 0) LZO_EXTERN(const lzo_bytep) lzo_copyright(void); #ifndef __LZO_PTR_H #define __LZO_PTR_H 1 #ifdef __cplusplus extern "C" { #endif #if (LZO_ARCH_I086) #error "LZO_ARCH_I086 is unsupported" #elif (LZO_MM_PVP) #error "LZO_MM_PVP is unsupported" #else #define PTR(a) ((lzo_uintptr_t) (a)) #define PTR_LINEAR(a) PTR(a) #define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) #define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) #define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) #define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) #endif #define PTR_LT(a,b) (PTR(a) < PTR(b)) #define PTR_GE(a,b) (PTR(a) >= PTR(b)) #define PTR_DIFF(a,b) (PTR(a) - PTR(b)) #define pd(a,b) ((lzo_uint) ((a)-(b))) LZO_EXTERN(lzo_uintptr_t) __lzo_ptr_linear(const lzo_voidp ptr); typedef union { char a_char; unsigned char a_uchar; short a_short; unsigned short a_ushort; int a_int; unsigned int a_uint; long a_long; unsigned long a_ulong; lzo_int a_lzo_int; lzo_uint a_lzo_uint; lzo_xint a_lzo_xint; lzo_int16_t a_lzo_int16_t; lzo_uint16_t a_lzo_uint16_t; lzo_int32_t a_lzo_int32_t; lzo_uint32_t a_lzo_uint32_t; #if defined(lzo_uint64_t) lzo_int64_t a_lzo_int64_t; lzo_uint64_t a_lzo_uint64_t; #endif size_t a_size_t; ptrdiff_t a_ptrdiff_t; lzo_uintptr_t a_lzo_uintptr_t; void * a_void_p; char * a_char_p; unsigned char * a_uchar_p; const void * a_c_void_p; const char * a_c_char_p; const unsigned char * a_c_uchar_p; lzo_voidp a_lzo_voidp; lzo_bytep a_lzo_bytep; const lzo_voidp a_c_lzo_voidp; const lzo_bytep a_c_lzo_bytep; } lzo_full_align_t; #ifdef __cplusplus } #endif #endif #ifndef LZO_DETERMINISTIC #define LZO_DETERMINISTIC 1 #endif #ifndef LZO_DICT_USE_PTR #define LZO_DICT_USE_PTR 1 #endif #if (LZO_DICT_USE_PTR) # define lzo_dict_t const lzo_bytep # define lzo_dict_p lzo_dict_t * #else # define lzo_dict_t lzo_uint # define lzo_dict_p lzo_dict_t * #endif #endif #if !defined(MINILZO_CFG_SKIP_LZO_PTR) LZO_PUBLIC(lzo_uintptr_t) __lzo_ptr_linear(const lzo_voidp ptr) { lzo_uintptr_t p; #if (LZO_ARCH_I086) #error "LZO_ARCH_I086 is unsupported" #elif (LZO_MM_PVP) #error "LZO_MM_PVP is unsupported" #else p = (lzo_uintptr_t) PTR_LINEAR(ptr); #endif return p; } LZO_PUBLIC(unsigned) __lzo_align_gap(const lzo_voidp ptr, lzo_uint size) { #if (__LZO_UINTPTR_T_IS_POINTER) #error "__LZO_UINTPTR_T_IS_POINTER is unsupported" #else lzo_uintptr_t p, n; if (size < 2) return 0; p = __lzo_ptr_linear(ptr); #if 0 n = (((p + size - 1) / size) * size) - p; #else if ((size & (size - 1)) != 0) return 0; n = size; n = ((p + n - 1) & ~(n - 1)) - p; #endif #endif assert((long)n >= 0); assert(n <= size); return (unsigned)n; } #endif #if !defined(MINILZO_CFG_SKIP_LZO_UTIL) /* If you use the LZO library in a product, I would appreciate that you * keep this copyright string in the executable of your product. */ static const char lzo_copyright_[] = #if !defined(__LZO_IN_MINLZO) LZO_VERSION_STRING; #else "\r\n\n" "LZO data compression library.\n" "$Copyright: LZO Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer\n" "\n" "http://www.oberhumer.com $\n\n" "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" "$Info: " LZO_INFO_STRING " $\n"; #endif static const char lzo_version_string_[] = LZO_VERSION_STRING; static const char lzo_version_date_[] = LZO_VERSION_DATE; LZO_PUBLIC(const lzo_bytep) lzo_copyright(void) { return (const lzo_bytep) lzo_copyright_; } LZO_PUBLIC(unsigned) lzo_version(void) { return LZO_VERSION; } LZO_PUBLIC(const char *) lzo_version_string(void) { return lzo_version_string_; } LZO_PUBLIC(const char *) lzo_version_date(void) { return lzo_version_date_; } LZO_PUBLIC(const lzo_charp) _lzo_version_string(void) { return lzo_version_string_; } LZO_PUBLIC(const lzo_charp) _lzo_version_date(void) { return lzo_version_date_; } #define LZO_BASE 65521u #define LZO_NMAX 5552 #define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 #define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1) #define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2) #define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4) #define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8) LZO_PUBLIC(lzo_uint32_t) lzo_adler32(lzo_uint32_t adler, const lzo_bytep buf, lzo_uint len) { lzo_uint32_t s1 = adler & 0xffff; lzo_uint32_t s2 = (adler >> 16) & 0xffff; unsigned k; if (buf == NULL) return 1; while (len > 0) { k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; len -= k; if (k >= 16) do { LZO_DO16(buf,0); buf += 16; k -= 16; } while (k >= 16); if (k != 0) do { s1 += *buf++; s2 += s1; } while (--k > 0); s1 %= LZO_BASE; s2 %= LZO_BASE; } return (s2 << 16) | s1; } #undef LZO_DO1 #undef LZO_DO2 #undef LZO_DO4 #undef LZO_DO8 #undef LZO_DO16 #endif #if !defined(MINILZO_CFG_SKIP_LZO_STRING) #undef lzo_memcmp #undef lzo_memcpy #undef lzo_memmove #undef lzo_memset #if !defined(__LZO_MMODEL_HUGE) # undef LZO_HAVE_MM_HUGE_PTR #endif #define lzo_hsize_t lzo_uint #define lzo_hvoid_p lzo_voidp #define lzo_hbyte_p lzo_bytep #define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f #define lzo_hmemcmp lzo_memcmp #define lzo_hmemcpy lzo_memcpy #define lzo_hmemmove lzo_memmove #define lzo_hmemset lzo_memset #define __LZOLIB_HMEMCPY_CH_INCLUDED 1 #if !defined(LZOLIB_PUBLIC) # define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) #endif LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP) const lzo_hbyte_p p1 = LZO_STATIC_CAST(const lzo_hbyte_p, s1); const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, s2); if __lzo_likely(len > 0) do { int d = *p1 - *p2; if (d != 0) return d; p1++; p2++; } while __lzo_likely(--len > 0); return 0; #else return memcmp(s1, s2, len); #endif } LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY) lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); if (!(len > 0) || p1 == p2) return dest; do *p1++ = *p2++; while __lzo_likely(--len > 0); return dest; #else return memcpy(dest, src, len); #endif } LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE) lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); if (!(len > 0) || p1 == p2) return dest; if (p1 < p2) { do *p1++ = *p2++; while __lzo_likely(--len > 0); } else { p1 += len; p2 += len; do *--p1 = *--p2; while __lzo_likely(--len > 0); } return dest; #else return memmove(dest, src, len); #endif } LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int cc, lzo_hsize_t len) { #if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET) lzo_hbyte_p p = LZO_STATIC_CAST(lzo_hbyte_p, s); unsigned char c = LZO_ITRUNC(unsigned char, cc); if __lzo_likely(len > 0) do *p++ = c; while __lzo_likely(--len > 0); return s; #else return memset(s, cc, len); #endif } #undef LZOLIB_PUBLIC #endif #if !defined(MINILZO_CFG_SKIP_LZO_INIT) #if !defined(__LZO_IN_MINILZO) #define LZO_WANT_ACC_CHK_CH 1 #undef LZOCHK_ASSERT LZOCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) LZOCHK_ASSERT_IS_SIGNED_T(lzo_int) LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) #if !(__LZO_UINTPTR_T_IS_POINTER) LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) #endif LZOCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) #endif #undef LZOCHK_ASSERT union lzo_config_check_union { lzo_uint a[2]; unsigned char b[2*LZO_MAX(8,sizeof(lzo_uint))]; #if defined(lzo_uint64_t) lzo_uint64_t c[2]; #endif }; #if 0 #define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off))) #else static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off) { return (lzo_voidp) ((lzo_bytep) ptr + off); } #endif LZO_PUBLIC(int) _lzo_config_check(void) { #if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030100ul && LZO_CC_CLANG < 0x030300ul)) # if 0 volatile # endif #endif union lzo_config_check_union u; lzo_voidp p; unsigned r = 1; u.a[0] = u.a[1] = 0; p = u2p(&u, 0); r &= ((* (lzo_bytep) p) == 0); #if !(LZO_CFG_NO_CONFIG_CHECK) #if (LZO_ABI_BIG_ENDIAN) u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128; p = u2p(&u, 0); r &= ((* (lzo_uintp) p) == 128); #endif #if (LZO_ABI_LITTLE_ENDIAN) u.a[0] = u.a[1] = 0; u.b[0] = 128; p = u2p(&u, 0); r &= ((* (lzo_uintp) p) == 128); #endif u.a[0] = u.a[1] = 0; u.b[0] = 1; u.b[3] = 2; p = u2p(&u, 1); r &= UA_GET_NE16(p) == 0; r &= UA_GET_LE16(p) == 0; u.b[1] = 128; r &= UA_GET_LE16(p) == 128; u.b[2] = 129; r &= UA_GET_LE16(p) == LZO_UINT16_C(0x8180); #if (LZO_ABI_BIG_ENDIAN) r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8081); #endif #if (LZO_ABI_LITTLE_ENDIAN) r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8180); #endif u.a[0] = u.a[1] = 0; u.b[0] = 3; u.b[5] = 4; p = u2p(&u, 1); r &= UA_GET_NE32(p) == 0; r &= UA_GET_LE32(p) == 0; u.b[1] = 128; r &= UA_GET_LE32(p) == 128; u.b[2] = 129; u.b[3] = 130; u.b[4] = 131; r &= UA_GET_LE32(p) == LZO_UINT32_C(0x83828180); #if (LZO_ABI_BIG_ENDIAN) r &= UA_GET_NE32(p) == LZO_UINT32_C(0x80818283); #endif #if (LZO_ABI_LITTLE_ENDIAN) r &= UA_GET_NE32(p) == LZO_UINT32_C(0x83828180); #endif #if defined(UA_GET_NE64) u.c[0] = u.c[1] = 0; u.b[0] = 5; u.b[9] = 6; p = u2p(&u, 1); u.c[0] = u.c[1] = 0; r &= UA_GET_NE64(p) == 0; #if defined(UA_GET_LE64) r &= UA_GET_LE64(p) == 0; u.b[1] = 128; r &= UA_GET_LE64(p) == 128; #endif #endif #if defined(lzo_bitops_ctlz32) { unsigned i = 0; lzo_uint32_t v; for (v = 1; v != 0 && r == 1; v <<= 1, i++) { r &= lzo_bitops_ctlz32(v) == 31 - i; r &= lzo_bitops_ctlz32_func(v) == 31 - i; }} #endif #if defined(lzo_bitops_ctlz64) { unsigned i = 0; lzo_uint64_t v; for (v = 1; v != 0 && r == 1; v <<= 1, i++) { r &= lzo_bitops_ctlz64(v) == 63 - i; r &= lzo_bitops_ctlz64_func(v) == 63 - i; }} #endif #if defined(lzo_bitops_cttz32) { unsigned i = 0; lzo_uint32_t v; for (v = 1; v != 0 && r == 1; v <<= 1, i++) { r &= lzo_bitops_cttz32(v) == i; r &= lzo_bitops_cttz32_func(v) == i; }} #endif #if defined(lzo_bitops_cttz64) { unsigned i = 0; lzo_uint64_t v; for (v = 1; v != 0 && r == 1; v <<= 1, i++) { r &= lzo_bitops_cttz64(v) == i; r &= lzo_bitops_cttz64_func(v) == i; }} #endif #endif LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); return r == 1 ? LZO_E_OK : LZO_E_ERROR; } LZO_PUBLIC(int) __lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, int s6, int s7, int s8, int s9) { int r; #if defined(__LZO_IN_MINILZO) #elif (LZO_CC_MSC && ((_MSC_VER) < 700)) #else #define LZO_WANT_ACC_CHK_CH 1 #undef LZOCHK_ASSERT #define LZOCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) #endif #undef LZOCHK_ASSERT if (v == 0) return LZO_E_ERROR; r = (s1 == -1 || s1 == (int) sizeof(short)) && (s2 == -1 || s2 == (int) sizeof(int)) && (s3 == -1 || s3 == (int) sizeof(long)) && (s4 == -1 || s4 == (int) sizeof(lzo_uint32_t)) && (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && (s7 == -1 || s7 == (int) sizeof(char *)) && (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); if (!r) return LZO_E_ERROR; r = _lzo_config_check(); if (r != LZO_E_OK) return r; return r; } #if !defined(__LZO_IN_MINILZO) #if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) #if 0 BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, WORD wHeapSize, LPSTR lpszCmdLine ) #else int __far __pascal LibMain ( int a, short b, short c, long d ) #endif { LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); return 1; } #endif #endif #endif #define LZO1X 1 #define LZO_EOF_CODE 1 #define M2_MAX_OFFSET 0x0800 #if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) #if 1 && defined(UA_GET_LE32) #undef LZO_DICT_USE_PTR #define LZO_DICT_USE_PTR 0 #undef lzo_dict_t #define lzo_dict_t lzo_uint16_t #endif #define LZO_NEED_DICT_H 1 #ifndef D_BITS #define D_BITS 14 #endif #define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) #define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) #if 1 #define DINDEX(dv,p) DM(((DMUL(0x1824429d,dv)) >> (32-D_BITS))) #else #define DINDEX(dv,p) DM((dv) + ((dv) >> (32-D_BITS))) #endif #ifndef __LZO_CONFIG1X_H #define __LZO_CONFIG1X_H 1 #if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) # define LZO1X 1 #endif #if !defined(__LZO_IN_MINILZO) #include #endif #ifndef LZO_EOF_CODE #define LZO_EOF_CODE 1 #endif #undef LZO_DETERMINISTIC #define M1_MAX_OFFSET 0x0400 #ifndef M2_MAX_OFFSET #define M2_MAX_OFFSET 0x0800 #endif #define M3_MAX_OFFSET 0x4000 #define M4_MAX_OFFSET 0xbfff #define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) #define M1_MIN_LEN 2 #define M1_MAX_LEN 2 #define M2_MIN_LEN 3 #ifndef M2_MAX_LEN #define M2_MAX_LEN 8 #endif #define M3_MIN_LEN 3 #define M3_MAX_LEN 33 #define M4_MIN_LEN 3 #define M4_MAX_LEN 9 #define M1_MARKER 0 #define M2_MARKER 64 #define M3_MARKER 32 #define M4_MARKER 16 #ifndef MIN_LOOKAHEAD #define MIN_LOOKAHEAD (M2_MAX_LEN + 1) #endif #if defined(LZO_NEED_DICT_H) #ifndef LZO_HASH #define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B #endif #define DL_MIN_LEN M2_MIN_LEN #ifndef __LZO_DICT_H #define __LZO_DICT_H 1 #ifdef __cplusplus extern "C" { #endif #if !defined(D_BITS) && defined(DBITS) # define D_BITS DBITS #endif #if !defined(D_BITS) # error "D_BITS is not defined" #endif #if (D_BITS < 16) # define D_SIZE LZO_SIZE(D_BITS) # define D_MASK LZO_MASK(D_BITS) #else # define D_SIZE LZO_USIZE(D_BITS) # define D_MASK LZO_UMASK(D_BITS) #endif #define D_HIGH ((D_MASK >> 1) + 1) #if !defined(DD_BITS) # define DD_BITS 0 #endif #define DD_SIZE LZO_SIZE(DD_BITS) #define DD_MASK LZO_MASK(DD_BITS) #if !defined(DL_BITS) # define DL_BITS (D_BITS - DD_BITS) #endif #if (DL_BITS < 16) # define DL_SIZE LZO_SIZE(DL_BITS) # define DL_MASK LZO_MASK(DL_BITS) #else # define DL_SIZE LZO_USIZE(DL_BITS) # define DL_MASK LZO_UMASK(DL_BITS) #endif #if (D_BITS != DL_BITS + DD_BITS) # error "D_BITS does not match" #endif #if (D_BITS < 6 || D_BITS > 18) # error "invalid D_BITS" #endif #if (DL_BITS < 6 || DL_BITS > 20) # error "invalid DL_BITS" #endif #if (DD_BITS < 0 || DD_BITS > 6) # error "invalid DD_BITS" #endif #if !defined(DL_MIN_LEN) # define DL_MIN_LEN 3 #endif #if !defined(DL_SHIFT) # define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) #endif #define LZO_HASH_GZIP 1 #define LZO_HASH_GZIP_INCREMENTAL 2 #define LZO_HASH_LZO_INCREMENTAL_A 3 #define LZO_HASH_LZO_INCREMENTAL_B 4 #if !defined(LZO_HASH) # error "choose a hashing strategy" #endif #undef DM #undef DX #if (DL_MIN_LEN == 3) # define _DV2_A(p,shift1,shift2) \ (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) # define _DV2_B(p,shift1,shift2) \ (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) # define _DV3_B(p,shift1,shift2,shift3) \ ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) #elif (DL_MIN_LEN == 2) # define _DV2_A(p,shift1,shift2) \ (( (lzo_xint)(p[0]) << shift1) ^ p[1]) # define _DV2_B(p,shift1,shift2) \ (( (lzo_xint)(p[1]) << shift1) ^ p[2]) #else # error "invalid DL_MIN_LEN" #endif #define _DV_A(p,shift) _DV2_A(p,shift,shift) #define _DV_B(p,shift) _DV2_B(p,shift,shift) #define DA2(p,s1,s2) \ (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) #define DS2(p,s1,s2) \ (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) #define DX2(p,s1,s2) \ (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) #define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) #define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) #define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) #define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) #define DM(v) DMS(v,0) #if (LZO_HASH == LZO_HASH_GZIP) # define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) #elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) # define __LZO_HASH_INCREMENTAL 1 # define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) # define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) # define _DINDEX(dv,p) (dv) # define DVAL_LOOKAHEAD DL_MIN_LEN #elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) # define __LZO_HASH_INCREMENTAL 1 # define DVAL_FIRST(dv,p) dv = _DV_A((p),5) # define DVAL_NEXT(dv,p) \ dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) # define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) # define DVAL_LOOKAHEAD DL_MIN_LEN #elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) # define __LZO_HASH_INCREMENTAL 1 # define DVAL_FIRST(dv,p) dv = _DV_B((p),5) # define DVAL_NEXT(dv,p) \ dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) # define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) # define DVAL_LOOKAHEAD DL_MIN_LEN #else # error "choose a hashing strategy" #endif #ifndef DINDEX #define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) #endif #if !defined(DINDEX1) && defined(D_INDEX1) #define DINDEX1 D_INDEX1 #endif #if !defined(DINDEX2) && defined(D_INDEX2) #define DINDEX2 D_INDEX2 #endif #if !defined(__LZO_HASH_INCREMENTAL) # define DVAL_FIRST(dv,p) ((void) 0) # define DVAL_NEXT(dv,p) ((void) 0) # define DVAL_LOOKAHEAD 0 #endif #if !defined(DVAL_ASSERT) #if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) #if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) static void __attribute__((__unused__)) #else static void #endif DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) { lzo_xint df; DVAL_FIRST(df,(p)); assert(DINDEX(dv,p) == DINDEX(df,p)); } #else # define DVAL_ASSERT(dv,p) ((void) 0) #endif #endif #if (LZO_DICT_USE_PTR) # define DENTRY(p,in) (p) # define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] #else # define DENTRY(p,in) ((lzo_dict_t) pd(p, in)) # define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] #endif #if (DD_BITS == 0) # define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) # define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) # define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) #else # define UPDATE_D(dict,drun,dv,p,in) \ dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK # define UPDATE_I(dict,drun,index,p,in) \ dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK # define UPDATE_P(ptr,drun,p,in) \ (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK #endif #if (LZO_DICT_USE_PTR) #define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) #define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ (BOUNDS_CHECKING_OFF_IN_EXPR(( \ m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ PTR_LT(m_pos,in) || \ (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) == 0 || \ m_off > max_offset ))) #else #define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ (m_off == 0 || \ ((m_off = pd(ip, in) - m_off) > max_offset) || \ (m_pos = (ip) - (m_off), 0) ) #define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ (pd(ip, in) <= m_off || \ ((m_off = pd(ip, in) - m_off) > max_offset) || \ (m_pos = (ip) - (m_off), 0) ) #endif #if (LZO_DETERMINISTIC) # define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET #else # define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET #endif #ifdef __cplusplus } #endif #endif #endif #endif #define LZO_DETERMINISTIC !(LZO_DICT_USE_PTR) #ifndef DO_COMPRESS #define DO_COMPRESS lzo1x_1_compress #endif #if 1 && defined(DO_COMPRESS) && !defined(do_compress) # define do_compress LZO_PP_ECONCAT2(DO_COMPRESS,_core) #endif static __lzo_noinline lzo_uint do_compress ( const lzo_bytep in , lzo_uint in_len, lzo_bytep out, lzo_uintp out_len, lzo_uint ti, lzo_voidp wrkmem) { const lzo_bytep ip; lzo_bytep op; const lzo_bytep const in_end = in + in_len; const lzo_bytep const ip_end = in + in_len - 20; const lzo_bytep ii; lzo_dict_p const dict = (lzo_dict_p) wrkmem; op = out; ip = in; ii = ip; ip += ti < 4 ? 4 - ti : 0; for (;;) { const lzo_bytep m_pos; #if !(LZO_DETERMINISTIC) LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0); lzo_uint m_len; lzo_uint dindex; next: if __lzo_unlikely(ip >= ip_end) break; DINDEX1(dindex,ip); GINDEX(m_pos,m_off,dict,dindex,in); if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) goto literal; #if 1 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) goto try_match; DINDEX2(dindex,ip); #endif GINDEX(m_pos,m_off,dict,dindex,in); if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) goto literal; if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) goto try_match; goto literal; try_match: #if (LZO_OPT_UNALIGNED32) if (UA_GET_NE32(m_pos) != UA_GET_NE32(ip)) #else if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3]) #endif { literal: UPDATE_I(dict,0,dindex,ip,in); ip += 1 + ((ip - ii) >> 5); continue; } UPDATE_I(dict,0,dindex,ip,in); #else lzo_uint m_off; lzo_uint m_len; { lzo_uint32_t dv; lzo_uint dindex; literal: ip += 1 + ((ip - ii) >> 5); next: if __lzo_unlikely(ip >= ip_end) break; dv = UA_GET_LE32(ip); dindex = DINDEX(dv,ip); GINDEX(m_off,m_pos,in+dict,dindex,in); UPDATE_I(dict,0,dindex,ip,in); if __lzo_unlikely(dv != UA_GET_LE32(m_pos)) goto literal; } #endif ii -= ti; ti = 0; { lzo_uint t = pd(ip,ii); if (t != 0) { if (t <= 3) { op[-2] = LZO_BYTE(op[-2] | t); #if (LZO_OPT_UNALIGNED32) UA_COPY4(op, ii); op += t; #else { do *op++ = *ii++; while (--t > 0); } #endif } #if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) else if (t <= 16) { *op++ = LZO_BYTE(t - 3); UA_COPY8(op, ii); UA_COPY8(op+8, ii+8); op += t; } #endif else { if (t <= 18) *op++ = LZO_BYTE(t - 3); else { lzo_uint tt = t - 18; *op++ = 0; while __lzo_unlikely(tt > 255) { tt -= 255; UA_SET1(op, 0); op++; } assert(tt > 0); *op++ = LZO_BYTE(tt); } #if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) do { UA_COPY8(op, ii); UA_COPY8(op+8, ii+8); op += 16; ii += 16; t -= 16; } while (t >= 16); if (t > 0) #endif { do *op++ = *ii++; while (--t > 0); } } } } m_len = 4; { #if (LZO_OPT_UNALIGNED64) lzo_uint64_t v; v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); if __lzo_unlikely(v == 0) { do { m_len += 8; v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); if __lzo_unlikely(ip + m_len >= ip_end) goto m_len_done; } while (v == 0); } #if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz64) m_len += lzo_bitops_ctlz64(v) / CHAR_BIT; #elif (LZO_ABI_BIG_ENDIAN) if ((v >> (64 - CHAR_BIT)) == 0) do { v <<= CHAR_BIT; m_len += 1; } while ((v >> (64 - CHAR_BIT)) == 0); #elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz64) m_len += lzo_bitops_cttz64(v) / CHAR_BIT; #elif (LZO_ABI_LITTLE_ENDIAN) if ((v & UCHAR_MAX) == 0) do { v >>= CHAR_BIT; m_len += 1; } while ((v & UCHAR_MAX) == 0); #else if (ip[m_len] == m_pos[m_len]) do { m_len += 1; } while (ip[m_len] == m_pos[m_len]); #endif #elif (LZO_OPT_UNALIGNED32) lzo_uint32_t v; v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); if __lzo_unlikely(v == 0) { do { m_len += 4; v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); if (v != 0) break; m_len += 4; v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); if __lzo_unlikely(ip + m_len >= ip_end) goto m_len_done; } while (v == 0); } #if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz32) m_len += lzo_bitops_ctlz32(v) / CHAR_BIT; #elif (LZO_ABI_BIG_ENDIAN) if ((v >> (32 - CHAR_BIT)) == 0) do { v <<= CHAR_BIT; m_len += 1; } while ((v >> (32 - CHAR_BIT)) == 0); #elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz32) m_len += lzo_bitops_cttz32(v) / CHAR_BIT; #elif (LZO_ABI_LITTLE_ENDIAN) if ((v & UCHAR_MAX) == 0) do { v >>= CHAR_BIT; m_len += 1; } while ((v & UCHAR_MAX) == 0); #else if (ip[m_len] == m_pos[m_len]) do { m_len += 1; } while (ip[m_len] == m_pos[m_len]); #endif #else if __lzo_unlikely(ip[m_len] == m_pos[m_len]) { do { m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if (ip[m_len] != m_pos[m_len]) break; m_len += 1; if __lzo_unlikely(ip + m_len >= ip_end) goto m_len_done; } while (ip[m_len] == m_pos[m_len]); } #endif } m_len_done: m_off = pd(ip,m_pos); ip += m_len; ii = ip; if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) { m_off -= 1; #if defined(LZO1X) *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); *op++ = LZO_BYTE(m_off >> 3); #elif defined(LZO1Y) *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); *op++ = LZO_BYTE(m_off >> 2); #endif } else if (m_off <= M3_MAX_OFFSET) { m_off -= 1; if (m_len <= M3_MAX_LEN) *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); else { m_len -= M3_MAX_LEN; *op++ = M3_MARKER | 0; while __lzo_unlikely(m_len > 255) { m_len -= 255; UA_SET1(op, 0); op++; } *op++ = LZO_BYTE(m_len); } *op++ = LZO_BYTE(m_off << 2); *op++ = LZO_BYTE(m_off >> 6); } else { m_off -= 0x4000; if (m_len <= M4_MAX_LEN) *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2)); else { m_len -= M4_MAX_LEN; *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8)); while __lzo_unlikely(m_len > 255) { m_len -= 255; UA_SET1(op, 0); op++; } *op++ = LZO_BYTE(m_len); } *op++ = LZO_BYTE(m_off << 2); *op++ = LZO_BYTE(m_off >> 6); } goto next; } *out_len = pd(op, out); return pd(in_end,ii-ti); } LZO_PUBLIC(int) DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, lzo_bytep out, lzo_uintp out_len, lzo_voidp wrkmem ) { const lzo_bytep ip = in; lzo_bytep op = out; lzo_uint l = in_len; lzo_uint t = 0; while (l > 20) { lzo_uint ll = l; lzo_uintptr_t ll_end; #if 0 || (LZO_DETERMINISTIC) ll = LZO_MIN(ll, 49152); #endif ll_end = (lzo_uintptr_t)ip + ll; if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll) break; #if (LZO_DETERMINISTIC) lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t)); #endif t = do_compress(ip,ll,op,out_len,t,wrkmem); ip += ll; op += *out_len; l -= ll; } t += l; if (t > 0) { const lzo_bytep ii = in + in_len - t; if (op == out && t <= 238) *op++ = LZO_BYTE(17 + t); else if (t <= 3) op[-2] = LZO_BYTE(op[-2] | t); else if (t <= 18) *op++ = LZO_BYTE(t - 3); else { lzo_uint tt = t - 18; *op++ = 0; while (tt > 255) { tt -= 255; UA_SET1(op, 0); op++; } assert(tt > 0); *op++ = LZO_BYTE(tt); } UA_COPYN(op, ii, t); op += t; } *op++ = M4_MARKER | 1; *op++ = 0; *op++ = 0; *out_len = pd(op, out); return LZO_E_OK; } #endif #undef do_compress #undef DO_COMPRESS #undef LZO_HASH #undef LZO_TEST_OVERRUN #undef DO_DECOMPRESS #define DO_DECOMPRESS lzo1x_decompress #if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) #if defined(LZO_TEST_OVERRUN) # if !defined(LZO_TEST_OVERRUN_INPUT) # define LZO_TEST_OVERRUN_INPUT 2 # endif # if !defined(LZO_TEST_OVERRUN_OUTPUT) # define LZO_TEST_OVERRUN_OUTPUT 2 # endif # if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) # define LZO_TEST_OVERRUN_LOOKBEHIND 1 # endif #endif #undef TEST_IP #undef TEST_OP #undef TEST_IP_AND_TEST_OP #undef TEST_LB #undef TEST_LBO #undef NEED_IP #undef NEED_OP #undef TEST_IV #undef TEST_OV #undef HAVE_TEST_IP #undef HAVE_TEST_OP #undef HAVE_NEED_IP #undef HAVE_NEED_OP #undef HAVE_ANY_IP #undef HAVE_ANY_OP #if defined(LZO_TEST_OVERRUN_INPUT) # if (LZO_TEST_OVERRUN_INPUT >= 1) # define TEST_IP (ip < ip_end) # endif # if (LZO_TEST_OVERRUN_INPUT >= 2) # define NEED_IP(x) \ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun # define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun # endif #endif #if defined(LZO_TEST_OVERRUN_OUTPUT) # if (LZO_TEST_OVERRUN_OUTPUT >= 1) # define TEST_OP (op <= op_end) # endif # if (LZO_TEST_OVERRUN_OUTPUT >= 2) # undef TEST_OP # define NEED_OP(x) \ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun # define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun # endif #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) # define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun # define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun #else # define TEST_LB(m_pos) ((void) 0) # define TEST_LBO(m_pos,o) ((void) 0) #endif #if !defined(LZO_EOF_CODE) && !defined(TEST_IP) # define TEST_IP (ip < ip_end) #endif #if defined(TEST_IP) # define HAVE_TEST_IP 1 #else # define TEST_IP 1 #endif #if defined(TEST_OP) # define HAVE_TEST_OP 1 #else # define TEST_OP 1 #endif #if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) # define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) #elif defined(HAVE_TEST_IP) # define TEST_IP_AND_TEST_OP TEST_IP #elif defined(HAVE_TEST_OP) # define TEST_IP_AND_TEST_OP TEST_OP #else # define TEST_IP_AND_TEST_OP 1 #endif #if defined(NEED_IP) # define HAVE_NEED_IP 1 #else # define NEED_IP(x) ((void) 0) # define TEST_IV(x) ((void) 0) #endif #if defined(NEED_OP) # define HAVE_NEED_OP 1 #else # define NEED_OP(x) ((void) 0) # define TEST_OV(x) ((void) 0) #endif #if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) # define HAVE_ANY_IP 1 #endif #if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) # define HAVE_ANY_OP 1 #endif #if defined(DO_DECOMPRESS) LZO_PUBLIC(int) DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, lzo_bytep out, lzo_uintp out_len, lzo_voidp wrkmem ) #endif { lzo_bytep op; const lzo_bytep ip; lzo_uint t; #if defined(COPY_DICT) lzo_uint m_off; const lzo_bytep dict_end; #else const lzo_bytep m_pos; #endif const lzo_bytep const ip_end = in + in_len; #if defined(HAVE_ANY_OP) lzo_bytep const op_end = out + *out_len; #endif #if defined(LZO1Z) lzo_uint last_m_off = 0; #endif LZO_UNUSED(wrkmem); #if defined(COPY_DICT) if (dict) { if (dict_len > M4_MAX_OFFSET) { dict += dict_len - M4_MAX_OFFSET; dict_len = M4_MAX_OFFSET; } dict_end = dict + dict_len; } else { dict_len = 0; dict_end = NULL; } #endif *out_len = 0; op = out; ip = in; NEED_IP(1); if (*ip > 17) { t = *ip++ - 17; if (t < 4) goto match_next; assert(t > 0); NEED_OP(t); NEED_IP(t+3); do *op++ = *ip++; while (--t > 0); goto first_literal_run; } for (;;) { NEED_IP(3); t = *ip++; if (t >= 16) goto match; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_IV(t); NEED_IP(1); } t += 15 + *ip++; } assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); #if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) t += 3; if (t >= 8) do { UA_COPY8(op,ip); op += 8; ip += 8; t -= 8; } while (t >= 8); if (t >= 4) { UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } if (t > 0) { *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } } #elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) #if !(LZO_OPT_UNALIGNED32) if (PTR_ALIGNED2_4(op,ip)) { #endif UA_COPY4(op,ip); op += 4; ip += 4; if (--t > 0) { if (t >= 4) { do { UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *ip++; while (--t > 0); } else do *op++ = *ip++; while (--t > 0); } #if !(LZO_OPT_UNALIGNED32) } else #endif #endif #if !(LZO_OPT_UNALIGNED32) { *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; do *op++ = *ip++; while (--t > 0); } #endif first_literal_run: t = *ip++; if (t >= 16) goto match; #if defined(COPY_DICT) #if defined(LZO1Z) m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); #endif NEED_OP(3); t = 3; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - (1 + M2_MAX_OFFSET); m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LB(m_pos); NEED_OP(3); *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; for (;;) { match: if (t >= 64) { #if defined(COPY_DICT) #if defined(LZO1X) m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); t = (t >> 5) - 1; #elif defined(LZO1Y) m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); t = (t >> 4) - 3; #elif defined(LZO1Z) m_off = t & 0x1f; if (m_off >= 0x1c) m_off = last_m_off; else { m_off = 1 + (m_off << 6) + (*ip++ >> 2); last_m_off = m_off; } t = (t >> 5) - 1; #endif #else #if defined(LZO1X) m_pos = op - 1; m_pos -= (t >> 2) & 7; m_pos -= *ip++ << 3; t = (t >> 5) - 1; #elif defined(LZO1Y) m_pos = op - 1; m_pos -= (t >> 2) & 3; m_pos -= *ip++ << 2; t = (t >> 4) - 3; #elif defined(LZO1Z) { lzo_uint off = t & 0x1f; m_pos = op; if (off >= 0x1c) { assert(last_m_off > 0); m_pos -= last_m_off; } else { off = 1 + (off << 6) + (*ip++ >> 2); m_pos -= off; last_m_off = off; } } t = (t >> 5) - 1; #endif TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); goto copy_match; #endif } else if (t >= 32) { t &= 31; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_OV(t); NEED_IP(1); } t += 31 + *ip++; NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); last_m_off = m_off; #else m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); #endif #else #if defined(LZO1Z) { lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); m_pos = op - off; last_m_off = off; } #elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) m_pos = op - 1; m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos = op - 1; m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif #endif ip += 2; } else if (t >= 16) { #if defined(COPY_DICT) m_off = (t & 8) << 11; #else m_pos = op; m_pos -= (t & 8) << 11; #endif t &= 7; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_OV(t); NEED_IP(1); } t += 7 + *ip++; NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) m_off += (ip[0] << 6) + (ip[1] >> 2); #else m_off += (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_off == 0) goto eof_found; m_off += 0x4000; #if defined(LZO1Z) last_m_off = m_off; #endif #else #if defined(LZO1Z) m_pos -= (ip[0] << 6) + (ip[1] >> 2); #elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_pos == op) goto eof_found; m_pos -= 0x4000; #if defined(LZO1Z) last_m_off = pd((const lzo_bytep)op, m_pos); #endif #endif } else { #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = 1 + (t >> 2) + (*ip++ << 2); #endif NEED_OP(2); t = 2; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = 1 + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - 1; m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LB(m_pos); NEED_OP(2); *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; } #if defined(COPY_DICT) NEED_OP(t+3-1); t += 3-1; COPY_DICT(t,m_off) #else TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); #if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) if (op - m_pos >= 8) { t += (3 - 1); if (t >= 8) do { UA_COPY8(op,m_pos); op += 8; m_pos += 8; t -= 8; } while (t >= 8); if (t >= 4) { UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } if (t > 0) { *op++ = m_pos[0]; if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } } } else #elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) #if !(LZO_OPT_UNALIGNED32) if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) { assert((op - m_pos) >= 4); #else if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { #endif UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4 - (3 - 1); do { UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *m_pos++; while (--t > 0); } else #endif { copy_match: *op++ = *m_pos++; *op++ = *m_pos++; do *op++ = *m_pos++; while (--t > 0); } #endif match_done: #if defined(LZO1Z) t = ip[-1] & 3; #else t = ip[-2] & 3; #endif if (t == 0) break; match_next: assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); #if 0 do *op++ = *ip++; while (--t > 0); #else *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } #endif t = *ip++; } } eof_found: *out_len = pd(op, out); return (ip == ip_end ? LZO_E_OK : (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); #if defined(HAVE_NEED_IP) input_overrun: *out_len = pd(op, out); return LZO_E_INPUT_OVERRUN; #endif #if defined(HAVE_NEED_OP) output_overrun: *out_len = pd(op, out); return LZO_E_OUTPUT_OVERRUN; #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) lookbehind_overrun: *out_len = pd(op, out); return LZO_E_LOOKBEHIND_OVERRUN; #endif } #endif #define LZO_TEST_OVERRUN 1 #undef DO_DECOMPRESS #define DO_DECOMPRESS lzo1x_decompress_safe #if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) #if defined(LZO_TEST_OVERRUN) # if !defined(LZO_TEST_OVERRUN_INPUT) # define LZO_TEST_OVERRUN_INPUT 2 # endif # if !defined(LZO_TEST_OVERRUN_OUTPUT) # define LZO_TEST_OVERRUN_OUTPUT 2 # endif # if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) # define LZO_TEST_OVERRUN_LOOKBEHIND 1 # endif #endif #undef TEST_IP #undef TEST_OP #undef TEST_IP_AND_TEST_OP #undef TEST_LB #undef TEST_LBO #undef NEED_IP #undef NEED_OP #undef TEST_IV #undef TEST_OV #undef HAVE_TEST_IP #undef HAVE_TEST_OP #undef HAVE_NEED_IP #undef HAVE_NEED_OP #undef HAVE_ANY_IP #undef HAVE_ANY_OP #if defined(LZO_TEST_OVERRUN_INPUT) # if (LZO_TEST_OVERRUN_INPUT >= 1) # define TEST_IP (ip < ip_end) # endif # if (LZO_TEST_OVERRUN_INPUT >= 2) # define NEED_IP(x) \ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun # define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun # endif #endif #if defined(LZO_TEST_OVERRUN_OUTPUT) # if (LZO_TEST_OVERRUN_OUTPUT >= 1) # define TEST_OP (op <= op_end) # endif # if (LZO_TEST_OVERRUN_OUTPUT >= 2) # undef TEST_OP # define NEED_OP(x) \ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun # define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun # endif #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) # define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun # define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun #else # define TEST_LB(m_pos) ((void) 0) # define TEST_LBO(m_pos,o) ((void) 0) #endif #if !defined(LZO_EOF_CODE) && !defined(TEST_IP) # define TEST_IP (ip < ip_end) #endif #if defined(TEST_IP) # define HAVE_TEST_IP 1 #else # define TEST_IP 1 #endif #if defined(TEST_OP) # define HAVE_TEST_OP 1 #else # define TEST_OP 1 #endif #if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) # define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) #elif defined(HAVE_TEST_IP) # define TEST_IP_AND_TEST_OP TEST_IP #elif defined(HAVE_TEST_OP) # define TEST_IP_AND_TEST_OP TEST_OP #else # define TEST_IP_AND_TEST_OP 1 #endif #if defined(NEED_IP) # define HAVE_NEED_IP 1 #else # define NEED_IP(x) ((void) 0) # define TEST_IV(x) ((void) 0) #endif #if defined(NEED_OP) # define HAVE_NEED_OP 1 #else # define NEED_OP(x) ((void) 0) # define TEST_OV(x) ((void) 0) #endif #if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) # define HAVE_ANY_IP 1 #endif #if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) # define HAVE_ANY_OP 1 #endif #if defined(DO_DECOMPRESS) LZO_PUBLIC(int) DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, lzo_bytep out, lzo_uintp out_len, lzo_voidp wrkmem ) #endif { lzo_bytep op; const lzo_bytep ip; lzo_uint t; #if defined(COPY_DICT) lzo_uint m_off; const lzo_bytep dict_end; #else const lzo_bytep m_pos; #endif const lzo_bytep const ip_end = in + in_len; #if defined(HAVE_ANY_OP) lzo_bytep const op_end = out + *out_len; #endif #if defined(LZO1Z) lzo_uint last_m_off = 0; #endif LZO_UNUSED(wrkmem); #if defined(COPY_DICT) if (dict) { if (dict_len > M4_MAX_OFFSET) { dict += dict_len - M4_MAX_OFFSET; dict_len = M4_MAX_OFFSET; } dict_end = dict + dict_len; } else { dict_len = 0; dict_end = NULL; } #endif *out_len = 0; op = out; ip = in; NEED_IP(1); if (*ip > 17) { t = *ip++ - 17; if (t < 4) goto match_next; assert(t > 0); NEED_OP(t); NEED_IP(t+3); do *op++ = *ip++; while (--t > 0); goto first_literal_run; } for (;;) { NEED_IP(3); t = *ip++; if (t >= 16) goto match; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_IV(t); NEED_IP(1); } t += 15 + *ip++; } assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); #if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) t += 3; if (t >= 8) do { UA_COPY8(op,ip); op += 8; ip += 8; t -= 8; } while (t >= 8); if (t >= 4) { UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } if (t > 0) { *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } } #elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) #if !(LZO_OPT_UNALIGNED32) if (PTR_ALIGNED2_4(op,ip)) { #endif UA_COPY4(op,ip); op += 4; ip += 4; if (--t > 0) { if (t >= 4) { do { UA_COPY4(op,ip); op += 4; ip += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *ip++; while (--t > 0); } else do *op++ = *ip++; while (--t > 0); } #if !(LZO_OPT_UNALIGNED32) } else #endif #endif #if !(LZO_OPT_UNALIGNED32) { *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; do *op++ = *ip++; while (--t > 0); } #endif first_literal_run: t = *ip++; if (t >= 16) goto match; #if defined(COPY_DICT) #if defined(LZO1Z) m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); #endif NEED_OP(3); t = 3; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - (1 + M2_MAX_OFFSET); m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LB(m_pos); NEED_OP(3); *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; for (;;) { match: if (t >= 64) { #if defined(COPY_DICT) #if defined(LZO1X) m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); t = (t >> 5) - 1; #elif defined(LZO1Y) m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); t = (t >> 4) - 3; #elif defined(LZO1Z) m_off = t & 0x1f; if (m_off >= 0x1c) m_off = last_m_off; else { m_off = 1 + (m_off << 6) + (*ip++ >> 2); last_m_off = m_off; } t = (t >> 5) - 1; #endif #else #if defined(LZO1X) m_pos = op - 1; m_pos -= (t >> 2) & 7; m_pos -= *ip++ << 3; t = (t >> 5) - 1; #elif defined(LZO1Y) m_pos = op - 1; m_pos -= (t >> 2) & 3; m_pos -= *ip++ << 2; t = (t >> 4) - 3; #elif defined(LZO1Z) { lzo_uint off = t & 0x1f; m_pos = op; if (off >= 0x1c) { assert(last_m_off > 0); m_pos -= last_m_off; } else { off = 1 + (off << 6) + (*ip++ >> 2); m_pos -= off; last_m_off = off; } } t = (t >> 5) - 1; #endif TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); goto copy_match; #endif } else if (t >= 32) { t &= 31; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_OV(t); NEED_IP(1); } t += 31 + *ip++; NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); last_m_off = m_off; #else m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); #endif #else #if defined(LZO1Z) { lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); m_pos = op - off; last_m_off = off; } #elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) m_pos = op - 1; m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos = op - 1; m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif #endif ip += 2; } else if (t >= 16) { #if defined(COPY_DICT) m_off = (t & 8) << 11; #else m_pos = op; m_pos -= (t & 8) << 11; #endif t &= 7; if (t == 0) { while (*ip == 0) { t += 255; ip++; TEST_OV(t); NEED_IP(1); } t += 7 + *ip++; NEED_IP(2); } #if defined(COPY_DICT) #if defined(LZO1Z) m_off += (ip[0] << 6) + (ip[1] >> 2); #else m_off += (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_off == 0) goto eof_found; m_off += 0x4000; #if defined(LZO1Z) last_m_off = m_off; #endif #else #if defined(LZO1Z) m_pos -= (ip[0] << 6) + (ip[1] >> 2); #elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) m_pos -= UA_GET_LE16(ip) >> 2; #else m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif ip += 2; if (m_pos == op) goto eof_found; m_pos -= 0x4000; #if defined(LZO1Z) last_m_off = pd((const lzo_bytep)op, m_pos); #endif #endif } else { #if defined(COPY_DICT) #if defined(LZO1Z) m_off = 1 + (t << 6) + (*ip++ >> 2); last_m_off = m_off; #else m_off = 1 + (t >> 2) + (*ip++ << 2); #endif NEED_OP(2); t = 2; COPY_DICT(t,m_off) #else #if defined(LZO1Z) t = 1 + (t << 6) + (*ip++ >> 2); m_pos = op - t; last_m_off = t; #else m_pos = op - 1; m_pos -= t >> 2; m_pos -= *ip++ << 2; #endif TEST_LB(m_pos); NEED_OP(2); *op++ = *m_pos++; *op++ = *m_pos; #endif goto match_done; } #if defined(COPY_DICT) NEED_OP(t+3-1); t += 3-1; COPY_DICT(t,m_off) #else TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); #if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) if (op - m_pos >= 8) { t += (3 - 1); if (t >= 8) do { UA_COPY8(op,m_pos); op += 8; m_pos += 8; t -= 8; } while (t >= 8); if (t >= 4) { UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } if (t > 0) { *op++ = m_pos[0]; if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } } } else #elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) #if !(LZO_OPT_UNALIGNED32) if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) { assert((op - m_pos) >= 4); #else if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { #endif UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4 - (3 - 1); do { UA_COPY4(op,m_pos); op += 4; m_pos += 4; t -= 4; } while (t >= 4); if (t > 0) do *op++ = *m_pos++; while (--t > 0); } else #endif { copy_match: *op++ = *m_pos++; *op++ = *m_pos++; do *op++ = *m_pos++; while (--t > 0); } #endif match_done: #if defined(LZO1Z) t = ip[-1] & 3; #else t = ip[-2] & 3; #endif if (t == 0) break; match_next: assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); #if 0 do *op++ = *ip++; while (--t > 0); #else *op++ = *ip++; if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } #endif t = *ip++; } } eof_found: *out_len = pd(op, out); return (ip == ip_end ? LZO_E_OK : (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); #if defined(HAVE_NEED_IP) input_overrun: *out_len = pd(op, out); return LZO_E_INPUT_OVERRUN; #endif #if defined(HAVE_NEED_OP) output_overrun: *out_len = pd(op, out); return LZO_E_OUTPUT_OVERRUN; #endif #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) lookbehind_overrun: *out_len = pd(op, out); return LZO_E_LOOKBEHIND_OVERRUN; #endif } #endif /***** End of minilzo.c *****/ distcc-3.4/lzo/minilzo.h000066400000000000000000000060211404653710500152730ustar00rootroot00000000000000/* minilzo.h -- mini subset of the LZO real-time data compression library This file is part of the LZO real-time data compression library. Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ */ /* * NOTE: * the full LZO package can be found at * http://www.oberhumer.com/opensource/lzo/ */ #ifndef __MINILZO_H_INCLUDED #define __MINILZO_H_INCLUDED 1 #define MINILZO_VERSION 0x20a0 /* 2.10 */ #if defined(__LZOCONF_H_INCLUDED) # error "you cannot use both LZO and miniLZO" #endif /* internal Autoconf configuration file - only used when building miniLZO */ #ifdef MINILZO_HAVE_CONFIG_H # include #endif #include #include #ifndef __LZODEFS_H_INCLUDED #include "lzodefs.h" #endif #undef LZO_HAVE_CONFIG_H #include "lzoconf.h" #if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) # error "version mismatch in header files" #endif #ifdef __cplusplus extern "C" { #endif /*********************************************************************** // ************************************************************************/ /* Memory required for the wrkmem parameter. * When the required size is 0, you can also pass a NULL pointer. */ #define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS #define LZO1X_1_MEM_COMPRESS ((lzo_uint32_t) (16384L * lzo_sizeof_dict_t)) #define LZO1X_MEM_DECOMPRESS (0) /* compression */ LZO_EXTERN(int) lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem ); /* decompression */ LZO_EXTERN(int) lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem /* NOT USED */ ); /* safe decompression with overrun testing */ LZO_EXTERN(int) lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem /* NOT USED */ ); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* already included */ /* vim:set ts=4 sw=4 et: */ distcc-3.4/lzo/testmini.c000066400000000000000000000111031404653710500154360ustar00rootroot00000000000000/* testmini.c -- very simple test program for the miniLZO library This file is part of the LZO real-time data compression library. Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer All Rights Reserved. The LZO library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The LZO library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the LZO library; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ */ #include #include /************************************************************************* // This program shows the basic usage of the LZO library. // We will compress a block of data and decompress again. // // For more information, documentation, example programs and other support // files (like Makefiles and build scripts) please download the full LZO // package from // http://www.oberhumer.com/opensource/lzo/ **************************************************************************/ /* First let's include "minizo.h". */ #include "minilzo.h" /* We want to compress the data block at 'in' with length 'IN_LEN' to * the block at 'out'. Because the input block may be incompressible, * we must provide a little more output space in case that compression * is not possible. */ #define IN_LEN (128*1024ul) #define OUT_LEN (IN_LEN + IN_LEN / 16 + 64 + 3) static unsigned char __LZO_MMODEL in [ IN_LEN ]; static unsigned char __LZO_MMODEL out [ OUT_LEN ]; /* Work-memory needed for compression. Allocate memory in units * of 'lzo_align_t' (instead of 'char') to make sure it is properly aligned. */ #define HEAP_ALLOC(var,size) \ lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); /************************************************************************* // **************************************************************************/ int main(int argc, char *argv[]) { int r; lzo_uint in_len; lzo_uint out_len; lzo_uint new_len; if (argc < 0 && argv == NULL) /* avoid warning about unused args */ return 0; printf("\nLZO real-time data compression library (v%s, %s).\n", lzo_version_string(), lzo_version_date()); printf("Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer\nAll Rights Reserved.\n\n"); /* * Step 1: initialize the LZO library */ if (lzo_init() != LZO_E_OK) { printf("internal error - lzo_init() failed !!!\n"); printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n"); return 3; } /* * Step 2: prepare the input block that will get compressed. * We just fill it with zeros in this example program, * but you would use your real-world data here. */ in_len = IN_LEN; lzo_memset(in,0,in_len); /* * Step 3: compress from 'in' to 'out' with LZO1X-1 */ r = lzo1x_1_compress(in,in_len,out,&out_len,wrkmem); if (r == LZO_E_OK) printf("compressed %lu bytes into %lu bytes\n", (unsigned long) in_len, (unsigned long) out_len); else { /* this should NEVER happen */ printf("internal error - compression failed: %d\n", r); return 2; } /* check for an incompressible block */ if (out_len >= in_len) { printf("This block contains incompressible data.\n"); return 0; } /* * Step 4: decompress again, now going from 'out' to 'in' */ new_len = in_len; r = lzo1x_decompress(out,out_len,in,&new_len,NULL); if (r == LZO_E_OK && new_len == in_len) printf("decompressed %lu bytes back into %lu bytes\n", (unsigned long) out_len, (unsigned long) in_len); else { /* this should NEVER happen */ printf("internal error - decompression failed: %d\n", r); return 1; } printf("\nminiLZO simple compression test passed.\n"); return 0; } /* vim:set ts=4 sw=4 et: */ distcc-3.4/m4/000077500000000000000000000000001404653710500131565ustar00rootroot00000000000000distcc-3.4/m4/ax_pthread.m4000066400000000000000000000506131404653710500155440ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to # that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with # PTHREAD_CFLAGS. # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # Updated for Autoconf 2.68 by Daniel Richard G. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 25 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then ax_pthread_save_CC="$CC" ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) AC_MSG_RESULT([$ax_pthread_ok]) if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi CC="$ax_pthread_save_CC" CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 # (Note: HP C rejects this with "bad form for `-t' option") # -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads and # -D_REENTRANT too), HP C (must be checked before -lpthread, which # is present but should not be used directly; and before -mthreads, # because the compiler interprets this as "-mt" + "-hreads") # -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case $host_os in freebsd*) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) ax_pthread_flags="-kthread lthread $ax_pthread_flags" ;; hpux*) # From the cc(1) man page: "[-mt] Sets various -D flags to enable # multi-threading and also sets -lpthread." ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" ;; openedition*) # IBM z/OS requires a feature-test macro to be defined in order to # enable POSIX threads at all, so give the user a hint if this is # not set. (We don't define these ourselves, as they can affect # other portions of the system API in unpredictable ways.) AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], [ # if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) AX_PTHREAD_ZOS_MISSING # endif ], [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) ;; solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (N.B.: The stubs are missing # pthread_cleanup_push, or rather a function called by this macro, # so we could check for that, but who knows whether they'll stub # that too in a future libc.) So we'll check first for the # standard Solaris way of linking pthreads (-mt -lpthread). ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" ;; esac # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) AS_IF([test "x$GCC" = "xyes"], [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) # The presence of a feature test macro requesting re-entrant function # definitions is, on some systems, a strong hint that pthreads support is # correctly enabled case $host_os in darwin* | hpux* | linux* | osf* | solaris*) ax_pthread_check_macro="_REENTRANT" ;; aix*) ax_pthread_check_macro="_THREAD_SAFE" ;; *) ax_pthread_check_macro="--" ;; esac AS_IF([test "x$ax_pthread_check_macro" = "x--"], [ax_pthread_check_cond=0], [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) # Are we compiling with Clang? AC_CACHE_CHECK([whether $CC is Clang], [ax_cv_PTHREAD_CLANG], [ax_cv_PTHREAD_CLANG=no # Note that Autoconf sets GCC=yes for Clang as well as GCC if test "x$GCC" = "xyes"; then AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ # if defined(__clang__) && defined(__llvm__) AX_PTHREAD_CC_IS_CLANG # endif ], [ax_cv_PTHREAD_CLANG=yes]) fi ]) ax_pthread_clang="$ax_cv_PTHREAD_CLANG" ax_pthread_clang_warning=no # Clang needs special handling, because older versions handle the -pthread # option in a rather... idiosyncratic way if test "x$ax_pthread_clang" = "xyes"; then # Clang takes -pthread; it has never supported any other flag # (Note 1: This will need to be revisited if a system that Clang # supports has POSIX threads in a separate library. This tends not # to be the way of modern systems, but it's conceivable.) # (Note 2: On some systems, notably Darwin, -pthread is not needed # to get POSIX threads support; the API is always present and # active. We could reasonably leave PTHREAD_CFLAGS empty. But # -pthread does define _REENTRANT, and while the Darwin headers # ignore this macro, third-party headers might not.) PTHREAD_CFLAGS="-pthread" PTHREAD_LIBS= ax_pthread_ok=yes # However, older versions of Clang make a point of warning the user # that, in an invocation where only linking and no compilation is # taking place, the -pthread option has no effect ("argument unused # during compilation"). They expect -pthread to be passed in only # when source code is being compiled. # # Problem is, this is at odds with the way Automake and most other # C build frameworks function, which is that the same flags used in # compilation (CFLAGS) are also used in linking. Many systems # supported by AX_PTHREAD require exactly this for POSIX threads # support, and in fact it is often not straightforward to specify a # flag that is used only in the compilation phase and not in # linking. Such a scenario is extremely rare in practice. # # Even though use of the -pthread flag in linking would only print # a warning, this can be a nuisance for well-run software projects # that build with -Werror. So if the active version of Clang has # this misfeature, we search for an option to squash it. AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown # Create an alternate version of $ac_link that compiles and # links in two steps (.c -> .o, .o -> exe) instead of one # (.c -> exe), because the warning occurs only in the second # step ax_pthread_save_ac_link="$ac_link" ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" ax_pthread_save_CFLAGS="$CFLAGS" for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" ac_link="$ax_pthread_save_ac_link" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], [ac_link="$ax_pthread_2step_ac_link" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], [break]) ]) done ac_link="$ax_pthread_save_ac_link" CFLAGS="$ax_pthread_save_CFLAGS" AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" ]) case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in no | unknown) ;; *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; esac fi # $ax_pthread_clang = yes if test "x$ax_pthread_ok" = "xno"; then for ax_pthread_try_flag in $ax_pthread_flags; do case $ax_pthread_try_flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -mt,pthread) AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) PTHREAD_CFLAGS="-mt" PTHREAD_LIBS="-lpthread" ;; -*) AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include # if $ax_pthread_check_cond # error "$ax_pthread_check_macro must be defined" # endif static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], [ax_pthread_ok=yes], []) CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" AC_MSG_RESULT([$ax_pthread_ok]) AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = "xyes"; then ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_CACHE_CHECK([for joinable pthread attribute], [ax_cv_PTHREAD_JOINABLE_ATTR], [ax_cv_PTHREAD_JOINABLE_ATTR=unknown for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [int attr = $ax_pthread_attr; return attr /* ; */])], [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], []) done ]) AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ test "x$ax_pthread_joinable_attr_defined" != "xyes"], [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$ax_cv_PTHREAD_JOINABLE_ATTR], [Define to necessary symbol if this constant uses a non-standard name on your system.]) ax_pthread_joinable_attr_defined=yes ]) AC_CACHE_CHECK([whether more special flags are required for pthreads], [ax_cv_PTHREAD_SPECIAL_FLAGS], [ax_cv_PTHREAD_SPECIAL_FLAGS=no case $host_os in solaris*) ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" ;; esac ]) AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ test "x$ax_pthread_special_flags_added" != "xyes"], [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" ax_pthread_special_flags_added=yes]) AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], [ax_cv_PTHREAD_PRIO_INHERIT], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT; return i;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ test "x$ax_pthread_prio_inherit_defined" != "xyes"], [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) ax_pthread_prio_inherit_defined=yes ]) CFLAGS="$ax_pthread_save_CFLAGS" LIBS="$ax_pthread_save_LIBS" # More AIX lossage: compile with *_r variant if test "x$GCC" != "xyes"; then case $host_os in aix*) AS_CASE(["x/$CC"], [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], [#handle absolute path differently from PATH based program lookup AS_CASE(["x$CC"], [x/*], [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" AC_SUBST([PTHREAD_LIBS]) AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test "x$ax_pthread_ok" = "xyes"; then ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_POP ])dnl AX_PTHREAD distcc-3.4/m4/pkg.m4000066400000000000000000000131231404653710500142010ustar00rootroot00000000000000# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # # Similar to PKG_CHECK_MODULES, make sure that the first instance of # this or PKG_CHECK_MODULES is called, or make sure to call # PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_ifval([$2], [$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$PKG_CONFIG"; then if test -n "$$1"; then pkg_cv_[]$1="$$1" else PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], [pkg_failed=yes]) fi else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` else $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD ifelse([$4], , [AC_MSG_ERROR(dnl [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT ])], [$4]) elif test $pkg_failed = untried; then ifelse([$4], , [AC_MSG_FAILURE(dnl [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])], [$4]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) ifelse([$3], , :, [$3]) fi[]dnl ])# PKG_CHECK_MODULES distcc-3.4/man/000077500000000000000000000000001404653710500134115ustar00rootroot00000000000000distcc-3.4/man/distcc.1000066400000000000000000001102101404653710500147370ustar00rootroot00000000000000.TH distcc 1 "9 June 2008" .SH "NAME" distcc \- distributed C/C++/ObjC compiler with distcc-pump extensions .SH "SYNOPSIS" .B distcc .I [COMPILER OPTIONS] .PP .B distcc .I [COMPILER OPTIONS] .PP .B .I [COMPILER OPTIONS] .PP .B distcc .I [DISTCC OPTIONS] .SH "DESCRIPTION" .P distcc distributes compilation of C code across several machines on a network. distcc should always generate the same results as a local compile, it is simple to install and use, and it is often much faster than a local compile. .PP This version incorporates plain distcc as well as an enhancement called pump mode or distcc-pump. .PP For each job, distcc in plain mode sends the complete preprocessed source code and compiler arguments across the network from the client to a compilation server. In pump mode, distcc sends the source code and recursively included header files (excluding those from the default system header directories), so that both preprocessing and compilation can take place on the compilation servers. This speeds up the delivery of compilations by up to an order of magnitude over plain distcc. .PP Compilation is driven by a client machine, which is typically the developer's workstation or laptop. The distcc client runs on this machine, as does make, the preprocessor (if distcc's pump mode is not used), the linker, and other stages of the build process. Any number of volunteer machines act as compilation servers and help the client to build the program, by running the .B distccd(1) daemon, C compiler and assembler as required. .PP distcc can run across either TCP sockets (on port 3632 by default), or through a tunnel command such as ssh(1). For TCP connections the volunteers must run the distccd(1) daemon either directly or from inetd. For SSH connections distccd must be installed but should .B not be listening for connections. .PP TCP connections should only be used on secure networks because there is no user authentication or protection of source or object code. SSH connections are slower. .PP distcc is intended to be used with GNU Make's .B -j option, which runs several compiler processes concurrently. distcc spreads the jobs across both local and remote CPUs. Because distcc is able to distribute most of the work across the network, a higher concurrency level can be used than for local builds. As a rule of thumb, the .B -j value should be set to about twice the total number of available server CPUs but subject to client limitations. This setting allows for maximal interleaving of tasks being blocked waiting for disk or network IO. Note that distcc can also work with other build control tools, such as SCons, where similar concurrency settings must be adjusted. .PP The .B -j setting, especially for large values of .B -j, must take into account the CPU load on the client. Additional measures may be needed to curtail the client load. For example, concurrent linking should be severely curtailed using auxiliary locks. The effect of other build activity, such as Java compilation when building mixed code, should be considered. The .B --localslots_cpp parameter is by default set to 8. This limits the number of concurrent processes that do preprocessing in plain distcc (non-pump) mode. Therefore, larger .B -j values than 8 may be used without overloading a single-CPU client due to preprocessing. Such large values may speed up parts of the build that do not involve C compilations, but they may not be useful to distcc efficiency in plain mode. .PP In contrast, using pump mode and say 40 servers, a setting of .B -j80 or larger may be appropriate even for single-CPU clients. .PP It is strongly recommended that you install the same compiler version on all machines participating in a build. Incompatible compilers may cause mysterious compile or link failures. .SH "QUICKSTART" .TP 1 For each machine, download distcc, unpack, and install. .TP 2 On each of the servers, run .B distccd --daemon with .B --allow options to restrict access. .TP 3 Put the names of the servers in your environment: .RS $ export DISTCC_HOSTS='localhost red green blue' .RE .TP 4 Build! .RS $ make -j8 CC=distcc .RE .SH "QUICKSTART FOR DISTCC-PUMP MODE" Proceed as above, but in Step 3, specify that the remote hosts are to carry the burden of preprocessing and that the files sent over the network should be compressed: .RS $ export DISTCC_HOSTS='--randomize localhost red,cpp,lzo green,cpp,lzo blue,cpp,lzo' .RE The .B --randomize option enforces a uniform usage of compile servers. While you will get some benefit from distcc's pump mode with only a few servers, you get increasing benefit with more server CPUs (up to the hundreds!). Wrap your build inside the pump command, here assuming 10 servers: .RS $ pump make -j20 CC=distcc .RE .SH "QUICKSTART FOR DISTCC-GSSAPI MODE" Proceed as per the .B QUICKSTART but in Step 3, specify that the remote hosts are to mutually authenticate with the client: .RS $ export DISTCC_HOSTS='--randomize localhost red,auth green,auth blue,auth' .RE If distccd runs under a specific principal name then execute the following command prior to step 4: .RS export DISTCC_PRINICIPAL= .RE .SH "HOW PLAIN (NON-PUMP) DISTCC WORKS" distcc only ever runs the compiler and assembler remotely. With plain distcc, the preprocessor must always run locally because it needs to access various header files on the local machine which may not be present, or may not be the same, on the volunteer. The linker similarly needs to examine libraries and object files, and so must run locally. .PP The compiler and assembler take only a single input file (the preprocessed source) and produce a single output (the object file). distcc ships these two files across the network and can therefore run the compiler/assembler remotely. .PP Fortunately, for most programs running the preprocessor is relatively cheap, and the linker is called relatively infrequent, so most of the work can be distributed. .PP distcc examines its command line to determine which of these phases are being invoked, and whether the job can be distributed. .SH "HOW DISTCC-PUMP MODE WORKS" In pump mode, distcc runs the preprocessor remotely too. To do so, the preprocessor must have access to all the files that it would have accessed if had been running locally. In pump mode, therefore, distcc gathers all of the recursively included headers, except the ones that are default system headers, and sends them along with the source file to the compilation server. .PP In distcc-pump mode, the server unpacks the set of all source files in a temporary directory, which contains a directory tree that mirrors the part of the file system that is relevant to preprocessing, including symbolic links. .PP The compiler is then run from the path in the temporary directory that corresponds to the current working directory on the client. To find and transmit the many hundreds of files that are often part of a single compilation, pump mode uses an incremental include analysis algorithm. The include server is a Python program that implements this algorithm. The pump command starts the include server so that throughout the build it can answer include queries by distcc commands. .PP The include server uses static analysis of the macro language to deal with conditional compilation and computed includes. It uses the property that when a given header file has already been analyzed for includes, it is not necessary to do so again if all the include options (-I's) are unchanged (along with other conditions). .PP For large builds, header files are included, on average, hundreds of times each. With distcc-pump mode each such file is analyzed only a few times, perhaps just once, instead of being preprocessed hundreds of times. Also, each source or header file is now compressed only once, because the include server memoizes the compressed files. As a result, the time used for preparing compilations may drop by up to an order of magnitude over the preprocessing of plain distcc. .PP Because distcc in pump mode is able to push out files up to about ten times faster, build speed may increase 3X or more for large builds compared to plain distcc mode. .SH "RESTRICTIONS FOR PUMP MODE" Using pump mode requires both client and servers to use release 3.0 or later of distcc and distccd (respectively). .PP The incremental include analysis of distc-pump mode rests on the fundamental assumption that source and header files do not change during the build process. A few complex build systems, such as that for Linux kernel 2.6, do not quite satisfy this requirement. To overcome such issues, and other corner cases such as absolute filepaths in includes, see the .BR include_server(1) man page. .PP Another important assumption is that the include configuration of all machines must be identical. Thus the headers under the default system path must be the same on all servers and all clients. If a standard GNU compiler installation is used, then this requirement applies to all libraries whose header files are installed under /usr/include or /usr/local/include/. Note that installing software packages often lead to additional headers files being placed in subdirectories of either. .PP If this assumption does not hold, then it is possible to break builds with distcc-pump mode, or worse, to get wrong results without warning. Presently this condition is not verified, and it is on our TODO list to address this issue. .PP An easy way to guarantee that the include configurations are identical is to use a cross-compiler that defines a default system search path restricted to directories of the compiler installation. .PP See the \fBinclude_server\fR(1) manual for more information on symptoms and causes of violations of distcc-pump mode assumptions. .SH "HOW DISTCC-GSSAPI MODE WORKS" In this mode distcc will use the GSS-API framework to access the currently configured security mechanism and perform mutual authentication with the daemon. .SH "OPTION SUMMARY" Most options passed to distcc are interpreted as compiler options. The following options are understood by distcc itself. If any of these options are specified, distcc will not invoke the compiler. .TP .B --help Displays summary instructions. .PP .TP .B --version Displays the distcc client version. .PP .TP .B --show-hosts Displays the host list that distcc would use. See the Host Specifications section. .PP .TP .B --scan-includes Displays the list of files that distcc would send to the remote machine, as computed by the include server. This is a conservative (over-)approximation of the files that would be read by the C compiler. This option only works in pump mode. See the "How Distcc-pump Mode Works" section for details on how this is computed. .RS .P The list output by \fBdistcc --scan-includes\fR will contain one entry per line. Each line contains a category followed by a path. The category is one of FILE, SYMLINK, DIRECTORY, or SYSTEMDIR: .IP .B FILE indicates a source file or header file that would be sent to the distcc server host. .IP .B SYMLINK indicates a symbolic link that would be sent to the distcc server host. .IP .B DIRECTORY indicates a directory that may be needed in order to compile the source file. For example, a directory "foo" may be needed because of an include of the form #include "foo/../bar.h". Such directories would be created on the distcc server host. .IP .B SYSTEMDIR indicates a system include directory, i.e. a directory which is on the compiler's default include path, such as "/usr/include"; such directories are assumed to be present on the distcc server host, and so would not be sent to the distcc server host. .RE .TP .B -j Displays distcc's concurrency level, as calculated from the host list; it is the maximum number of outstanding jobs issued by this client to all servers. By default this will be four times the number of hosts in the host list, unless the /LIMIT option was used in the host list. See the Host Specifications section. .PP .TP .B --show-principal Displays the name of the distccd security principal extracted from the environment. .B This option is only available if distcc was compiled with .B the --with-auth configure option. .SH "INSTALLING DISTCC" There are three different ways to call distcc, to suit different circumstances: .RS .PP distcc can be installed under the name of the real compiler, to intercept calls to it and run them remotely. This "masqueraded" compiler has the widest compatibility with existing source trees, and is convenient when you want to use distcc for all compilation. The fact that distcc is being used is transparent to the makefiles. .PP distcc can be prepended to compiler command lines, such as "distcc cc -c hello.c" or CC="distcc gcc". This is convenient when you want to use distcc for only some compilations or to try it out, but can cause trouble with some makefiles or versions of libtool that assume $CC does not contain a space. .PP Finally, distcc can be used directly as a compiler. "cc" is always used as the name of the real compiler in this "implicit" mode. This can be convenient for interactive use when "explicit" mode does not work but is not really recommended for new use. .RE .PP Remember that you should not use two methods for calling distcc at the same time. If you are using a masquerade directory, don't change CC and/or CXX, just put the directory early on your PATH. If you're not using a masquerade directory, you'll need to either change CC and/or CXX, or modify the makefile(s) to call distcc explicitly. .SH "MASQUERADING" The basic idea is to create a "masquerade directory" which contains links from the name of the real compiler to the distcc binary. This directory is inserted early on the PATH, so that calls to the compiler are intercepted and distcc is run instead. distcc then removes itself from the PATH to find the real compiler. .PP For example: .PP .RS .nf # mkdir /usr/lib/distcc/bin # cd /usr/lib/distcc/bin # ln -s ../../../bin/distcc gcc # ln -s ../../../bin/distcc cc # ln -s ../../../bin/distcc g++ # ln -s ../../../bin/distcc c++ .fi .RE .PP Then, to use distcc, a user just needs to put the directory /usr/lib/distcc/bin early in the PATH, and have set a host list in DISTCC_HOSTS or a file. distcc will handle the rest. .PP To automatically discover compilers and create masquerade links run the provided .BR update-distcc-symlinks script. .PP Note that this masquerade directory must occur on the PATH earlier than the directory that contains the actual compilers of the same names, and that any auxiliary programs that these compilers call (such as as or ld) must also be found on the PATH in a directory after the masquerade directory since distcc calls out to the real compiler with a PATH value that has all directory up to and including the masquerade directory trimmed off. .PP It is possible to get a "recursion error" in masquerade mode, which means that distcc is somehow finding itself again, not the real compiler. This can indicate that you have two masquerade directories on the PATH, possibly because of having two distcc installations in different locations. It can also indicate that you're trying to mix "masqueraded" and "explicit" operation. .PP Recursion errors can be avoided by using shell scripts instead of links. For example, in /usr/lib/distcc/bin create a file cc which contains: .PP .RS .nf #!/bin/sh distcc /usr/bin/gcc "$@" .fi .RE .PP In this way, we are not dependent on distcc having to locate the real gcc by investigating the PATH variable. Instead, the compiler location is explicitly provided. .SH "USING DISTCC WITH CCACHE" ccache is a program that speeds software builds by caching the results of compilations. ccache is normally called before distcc, so that results are retrieved from a normal cache. Some experimentation may be required for idiosyncratic makefiles to make everything work together. .PP The most reliable method is to set .IP .B CCACHE_PREFIX="distcc" .PP This tells ccache to run distcc as a wrapper around the real compiler. ccache still uses the real compiler to detect compiler upgrades. .PP ccache can then be run using either a masquerade directory .I or by setting .IP .B CC="ccache gcc" .PP As of version 2.2, ccache does not cache compilation from preprocessed source and so will never get a cache hit if it is run from distccd or distcc. It must be run only on the client side and before distcc to be any use. distcc's pump mode is not compatible with ccache. .SH "HOST SPECIFICATIONS" A "host list" tells distcc which machines to use for compilation. In order, distcc looks in the .B $DISTCC_HOSTS environment variable, the user's .B $DISTCC_DIR/hosts file, and the system-wide host file. If no host list can be found, distcc emits a warning and compiles locally. .PP The host list is a simple whitespace separated list of host specifications. The simplest and most common form is a host names, such as .PP .RS .B localhost red green blue .RE .PP distcc prefers hosts towards the start of the list, so machines should be listed in descending order of speed. In particular, when only a single compilation can be run (such as from a configure script), the first machine listed is used (but see .I --randomize below). .PP Placing .I localhost at the right point in the list is important to getting good performance. Because overhead for running jobs locally is low, localhost should normally be first. However, it is important that the client have enough cycles free to run the local jobs and the distcc client. If the client is slower than the volunteers, or if there are many volunteers, then the client should be put later in the list or not at all. As a general rule, if the aggregate CPU speed of the client is less than one fifth of the total, then the client should be left out of the list. .PP If you have a large shared build cluster and a single shared hosts file, the above rules would cause the first few machines in the hosts file to be tried first even though they are likely to be busier than machines later in the list. To avoid this, place the keyword .I --randomize into the host list. This will cause the host list to be randomized, which should improve performance slightly for large build clusters. .PP There are two special host names .B --localslots and .B --localslots_cpp which are useful for adjusting load on the local machine. The .B --localslots host specifies how many jobs that cannot be run remotely that can be run concurrently on the local machine, while .B --localslots_cpp controls how many preprocessors will run in parallel on the local machine. Tuning these values can improve performance. Linking on large projects can take large amounts of memory. Running parallel linkers, which cannot be executed remotely, may force the machine to swap, which reduces performance over just running the jobs in sequence without swapping. Getting the number of parallel preprocessors just right allows you to use larger parallel factors with make, since the local machine now has some mechanism for measuring local resource usage. .PP Finally there is the host entry .PP Performance depends on the details of the source and makefiles used for the project, and the machine and network speeds. Experimenting with different settings for the host list and .B -j factor may improve performance. .PP The syntax is .PP .nf DISTCC_HOSTS = HOSTSPEC ... HOSTSPEC = LOCAL_HOST | SSH_HOST | TCP_HOST | OLDSTYLE_TCP_HOST | GLOBAL_OPTION | ZEROCONF LOCAL_HOST = localhost[/LIMIT] | --localslots= | --localslots_cpp= SSH_HOST = [USER]@HOSTID[/LIMIT][:COMMAND][OPTIONS] TCP_HOST = HOSTID[:PORT][/LIMIT][OPTIONS] OLDSTYLE_TCP_HOST = HOSTID[/LIMIT][:PORT][OPTIONS] HOSTID = HOSTNAME | IPV4 | IPV6 OPTIONS = ,OPTION[OPTIONS] OPTION = lzo | cpp | auth[=AUTH_NAME] GLOBAL_OPTION = --randomize ZEROCONF = +zeroconf .fi .PP Here are some individual examples of the syntax: .TP .B localhost The literal word "localhost" is interpreted specially to cause compilations to be directly executed, rather than passed to a daemon on the local machine. If you do want to connect to a daemon on the local machine for testing, then give the machine's IP address or real hostname. (This will be slower.) .TP .B IPV6 A literal IPv6 address enclosed in square brackets, such as .B [::1] .TP .B IPV4 A literal IPv4 address, such as .B 10.0.0.1 .TP .B HOSTNAME A hostname to be looked up using the resolver. .TP .B :PORT Connect to a specified decimal port number, rather than the default of 3632. .TP .B @HOSTID Connect to the host over SSH, rather than TCP. Options for the SSH connection can be set in .B ~/.ssh/config .TP .B USER@ Connect to the host over SSH as a specified username. .TP .B :COMMAND Connect over SSH, and use a specified path to find the distccd server. This is normally only needed if for some reason you can't install distccd into a directory on the default PATH for SSH connections. Use this if you get errors like "distccd: command not found" in SSH mode. .TP .B /LIMIT A decimal limit can be added to any host specification to restrict the number of jobs that this client will send to the machine. The limit defaults to four per host (two for localhost), but may be further restricted by the server. You should only need to increase this for servers with more than two processors. .TP .B ,lzo Enables LZO compression for this TCP or SSH host. .TP .B ,cpp Enables distcc-pump mode for this host. Note: the build command must be wrapped in the pump script in order to start the include server. .TP .B ,auth Enables GSSAPI-based mutual authentication for this host. .TP .B AUTH_NAME The "canonical" name to use for the service principal name instead of HOSTNAME (or its corresponding fqdn). This option is useful in case of accessing an authenticated server via ssh port forwarding, in which case the HOSTNAME is 127.0.0.1. .TP .B --randomize Randomize the order of the host list before execution. .TP .B +zeroconf .B This option is only available if distcc was compiled with Avahi support enabled at configure time. When this special entry is present in the hosts list, distcc will use Avahi Zeroconf DNS Service Discovery (DNS-SD) to locate any available distccd servers on the local network. This avoids the need to explicitly list the host names or IP addresses of the distcc server machines. The distccd servers must have been started with the "--zeroconf" option to distccd. An important caveat is that in the current implementation, pump mode (",cpp") and compression (",lzo") will never be used for hosts located via zeroconf. .PP Here is an example demonstrating some possibilities: .PP .RS .nf .B localhost/2 @bigman/16:/opt/bin/distccd oldmachine:4200/1 .B # cartman is down .B distant/3,lzo .fi .RE .PP Comments are allowed in host specifications. Comments start with a hash/pound sign (\fB#\fP) and run to the end of the line. .PP If a host in the list is not reachable distcc will emit a warning and ignore that host for about one minute. .SH "COMPRESSION" The .B lzo host option specifies that LZO compression should be used for data transfer, including preprocessed source, object code and error messages. Compression is usually economical on networks slower than 100Mbps, but results may vary depending on the network, processors and source tree. .PP Enabling compression makes the distcc client and server use more CPU time, but less network traffic. The added CPU time is insignificant for pump mode. The compression ratio is typically 4:1 for source and 2:1 for object code. .PP Using compression requires both client and server to use at least release 2.9 of distcc. No server configuration is required: the server always responds with compressed replies to compressed requests. .PP Pump mode requires the servers to have the lzo host option on. .SH "SEARCH PATHS" .PP If the compiler name is an absolute path, it is passed verbatim to the server and the compiler is run from that directory. For example: .PP .RS .B distcc /usr/local/bin/gcc-3.1415 -c hello.c .RE .PP If the compiler name is not absolute, or not fully qualified, distccd's PATH is searched. When distcc is run from a masquerade directory, only the base name of the compiler is used. The client's PATH is used only to run the preprocessor and has no effect on the server's path. .SH "TIMEOUTS" .PP Both the distcc client and server impose timeouts on transfer of data across the network. This is intended to detect hosts which are down or unreachable, and to prevent compiles hanging indefinitely if a server is disconnected while in use. If a client-side timeout expires, the job will be re-run locally. .PP The transfer timeout is not configurable at present. The timeout that detects stale distributed job is configurable via DISTCC_IO_TIMEOUT environment variable. .SH "DIAGNOSTICS" Error messages or warnings from local or remote compilers are passed through to diagnostic output on the client. .PP distcc can supply extensive debugging information when the verbose option is used. This is controlled by the .B DISTCC_VERBOSE environment variable on the client, and the .B --verbose option on the server. For troubleshooting, examine both the client and server error messages. .SH "EXIT CODES" The exit code of distcc is normally that of the compiler: zero for successful compilation and non-zero otherwise. .PP distcc distinguishes between "genuine" errors such as a syntax error in the source, and "accidental" errors such as a networking problem connecting to a volunteer. In the case of accidental errors, distcc will retry the compilation locally unless the DISTCC_FALLBACK option has been disabled. .PP If the compiler exits with a signal, distcc returns an exit code of 128 plus the signal number. .PP distcc internal errors cause an exit code between 100 and 127. In particular .TP 100 General distcc failure. .TP 101 Bad arguments. .TP 102 Bind failed. .TP 103 Connect failed. .TP 104 Compiler crashed. .TP 105 Out of memory. .TP 106 Bad Host SPEC .TP 107 I/O Error .TP 108 Truncated. .TP 109 Protocol Error. .TP 110 The given compiler was not found on the remote host. Check that $CC is set appropriately and that it's installed in a directory on the search path for distccd. .TP 111 Recursive call to distcc. .TP 112 Failed to discard privileges. .TP 113 Network access denied. .TP 114 In use by another process. .TP 115 No such file. .TP 116 No hosts defined and fallbacks disabled. .TP 118 Timeout. .TP 119 GSS-API - Catchall error code for GSS-API related errors. .TP 120 Called for preprocessing, which needs to be done locally. .SH "FILES" If $DISTCC_HOSTS is not set, distcc reads a host list from either .B $DISTCC_DIR/hosts or a system-wide configuration file set at compile time. The file locations are shown in the output from .B distcc --help .PP distcc creates a number of temporary and lock files underneath the temporary directory. .SH "ENVIRONMENT VARIABLES" distcc's behaviour is controlled by a number of environment variables. For most cases nothing need be set if the host list is stored in a file. .TP .B "DISTCC_HOSTS" Space-separated list of volunteer host specifications. .TP .B "DISTCC_VERBOSE" If set to 1, distcc produces explanatory messages on the standard error stream or in the log file. This can be helpful in debugging problems. Bug reports should include verbose output. .TP .B "DISTCC_LOG" Log file to receive messages from distcc itself, rather than stderr. .TP .B "DISTCC_FALLBACK" By default distcc will compile locally if it fails to distribute a job to the intended machine, or if no host list can be found. If this variable is set to 0 then fallbacks are disabled and those compilations will simply fail. Note that this does not affect jobs which must always be local such as linking. .TP .B "DISTCC_NO_CROSS_REWRITE" By default distcc will rewrite calls gcc to use fully qualified names (like x86_64-linux-gnu-gcc), and clang to use the -target option. Setting this turns that off. .TP .B "DISTCC_BACKOFF_PERIOD" Specifies how long (in seconds) distcc will avoid trying to use a particular compilation server after that server yields a compile failure. By default set to 60 seconds. To disable the backoff behavior altogether, set this to 0. .TP .B "DISTCC_IO_TIMEOUT" Specifies how long (in seconds) distcc will wait before deciding a distributed job has timed out. If a distributed job is expected to takes a long time, consider increasing this value so the job does not time out and fallback to a local compile. By default set to 300 seconds. .TP .B "DISTCC_PAUSE_TIME_MSEC" Specifies how long (in milliseconds) distcc will pause when all compilation servers are in use. By default set to 1000 milliseconds (1 second). Setting this to a smaller value (e.g. 10 milliconds) may improve throughput for some configurations, at the expense of increased CPU load on the distcc client machine. .TP .B "DISTCC_SAVE_TEMPS" If set to 1, temporary files are not deleted after use. Good for debugging, or if your disks are too empty. .TP .B "DISTCC_TCP_CORK" If set to 0, disable use of "TCP corks", even if they're present on this system. Using corks normally helps pack requests into fewer packets and aids performance. This should normally be left enabled. .TP .B DISTCC_SSH Specifies the command used for opening SSH connections. Defaults to "ssh" but may be set to a different connection command such as "lsh" or "tsocks-ssh" that accepts a similar command line. The command is not split into words and is not executed through the shell. .TP .B DISTCC_SKIP_LOCAL_RETRY If set, when a remote compile fails, distcc will no longer try to recompile that file locally. .TP .B "DISTCC_DIR" Per-user configuration directory to store lock files and state files. By default .B ~/.distcc/ is used. .TP .B "TMPDIR" Directory for temporary files such as preprocessor output. By default /tmp/ is used. .TP .B "UNCACHED_ERR_FD" If set and if DISTCC_LOG is not set, distcc errors are written to the file descriptor identified by this variable. This variable is intended mainly for automatic use by ccache, which sets it to avoid caching transient errors such as network problems. .TP .B "DISTCC_ENABLE_DISCREPANCY_EMAIL" If set, distcc sends an email when a compilation failed remotely, but succeeded locally. Built-in heuristics prevent some such discrepancy email from being sent if the problem is that a local file changed between the failing remote compilation and the succeeding local compilation. .TP .B "DISTCC_MAX_DISCREPANCY" The maximum number of remote compilation failures allowed in pump mode before distcc switches to plain distcc mode. By default set to 1. .TP .B "DCC_EMAILLOG_WHOM_TO_BLAME" The email address for discrepancy email; the default is "distcc-pump-errors". .TP .B "DISTCC_PRINCIPAL" If set, specifies the name of the principal that distccd runs under, and is used to authenticate the server to the client. .B This environment variable is only used if distcc was compiled with .B the --with-auth configure option and the ",auth" per host option is specified. .SH "CROSS COMPILING" Cross compilation means building programs to run on a machine with a different processor, architecture, or operating system to where they were compiled. distcc supports cross compilation, including teams of mixed-architecture machines, although some changes to the compilation commands may be required. .PP The compilation command passed to distcc must be one that will execute properly on every volunteer machine to produce an object file of the appropriate type. If the machines have different processors, then simply using .B distcc cc will probably not work, because that will normally invoke the volunteer's native compiler. .PP Machines with the same CPU but different operating systems may not necessarily generate compatible .o files. .PP Several different gcc configurations can be installed side-by-side on any machine. If you build gcc from source, you should use the .B --program-suffix configuration options to cause it to be installed with a name that encodes the gcc version and the target platform. .PP The recommended convention for the gcc name is .I TARGET-gcc-VERSION such as .B i686-linux-gcc-3.2 \&. GCC 3.3 will install itself under this name, in addition to .I TARGET-gcc and, if it's native, .I gcc-VERSION and .I gcc \&. .PP The compiler must be installed under the same name on the client and on every volunteer machine. .SH "BUGS" If you think you have found a distcc bug, please see the file .I reporting-bugs.txt in the documentation directory for information on how to report it. .PP Some makefiles have missing or extra dependencies that cause incorrect or slow parallel builds. Recursive make is inefficient and can leave processors unnecessarily idle for long periods. (See .I Recursive Make Considered Harmful by Peter Miller.) Makefile bugs are the most common cause of trees failing to build under distcc. Alternatives to Make such as .I SCons can give much faster builds for some projects. .PP Using different versions of gcc can cause confusing build problems because the header files and binary interfaces have changed over time, and some distributors have included incompatible patches without changing the version number. distcc does not protect against using incompatible versions. Compiler errors about link problems or declarations in system header files are usually due to mismatched or incorrectly installed compilers. .PP gcc's .B -MD option can produce output in the wrong directory if the source and object files are in different directories and the .B -MF option is not used. There is no perfect solution because of incompatible changes between gcc versions. Explicitly specifying the dependency output file with .B -MF will fix the problem. .PP TCP mode connections should only be used on trusted networks. .PP Including slow machines in the list of volunteer hosts can slow the build down. .PP When distcc or ccache is used on NFS, the filesystem must be exported with the .B no_subtree_check option to allow reliable renames between directories. .PP The compiler can be invoked with a command line .B gcc hello.c to both compile and link. distcc doesn't split this into separate parts, but rather runs the whole thing locally. .PP distcc-pump mode reverts to plain distcc mode for source files that contain includes with absolute paths (either directly or in an included file). .PP Due to limitations in gcc, gdb may not be able to automatically find the source files for programs built using distcc in some circumstances. The gdb .B directory command can be used. For distcc's plain (non-pump) mode, this is fixed in gcc 3.4 and later. For pump mode, the fix in gcc 3.4 does not suffice; we've worked around the gcc limitation by rewriting the object files that gcc produces, but this is only done for ELF object files, but not for other object file formats. .PP The .o files produced by discc in pump mode will be different from those produced locally: for non-ELF files, the debug information will specify compile directories of the server. The code itself should be identical. .PP For the ELF-format, distcc rewrites the .o files to correct compile directory path information. While the resulting .o files are not bytewise identical to what would have been produced by compiling on the local client (due to different padding, etc), they should be functionally identical. .PP In distcc-pump mode, the include server is unable to handle certain very complicated computed includes as found in parts of the Boost library. The include server will time out and distcc will revert to plain mode. .PP In distcc-pump mode, certain assumptions are made that source and header files do not change during the build. See discussion in section DISTCC DISCREPANCY SYMPTOMS of \fBinclude_server\fR(1(). Other known bugs may be documented on .I http://code.google.com/p/distcc/ .SH "AUTHOR" distcc was written by Martin Pool , with the co-operation of many scholars including Wayne Davison, Frerich Raabe, Dimitri Papadopoulos and others noted in the NEWS file. Please report bugs to . See \fBpump\fR(1) for the authors of pump mode. .SH "LICENCE" You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warrany. A copy of the GPL is included in the file COPYING. .SH "SEE ALSO" \fBdistccd\fR(1), \fBpump\fR(1), \fBinclude_server\fR(1), \fBgcc\fR(1), \fBmake\fR(1), and \fBccache\fR(1). .I http://code.google.com/p/distcc/ .I https://ccache.dev/ distcc-3.4/man/distccd.1000066400000000000000000000306751404653710500151230ustar00rootroot00000000000000.TH distccd 1 "9 June 2008" .SH "NAME" distccd \- distributed C/C++ compiler server .SH "SYNOPSIS" .B distccd --daemon .I [OPTIONS] .SH "DESCRIPTION" .I distccd is the server for the distcc(1) distributed compiler. It accepts and runs compilation jobs for network clients. .PP distcc can run over either TCP or a connection command such as ssh(1). TCP connections are fast but relatively insecure. SSH connections are secure but slower. .PP For SSH connections, distccd must be installed on the volunteer but should not run as a daemon -- it will be started over SSH as needed. SSH connections have several advantages: neither the client nor server listens on any new ports; compilations run with the privileges of the user that requested them; unauthorized users cannot access the server; and source and output is protected in transit. .PP For TCP connections, distccd can run either from an inetd-style program, or as a standalone server. Standalone mode is recommended because it is slightly more efficient and allows distccd to regulate the number of incoming jobs. The .B --listen and .B --allow options can be used for simple IP-based access control. .PP distcc may be started either by root or any other user. If run by root, it gives away privileges and changes to the user specified by the .B --user option, or the user called "distcc", or the user called "nobody". .PP distccd does not have a configuration file; it's behaviour is controlled only by command-line options and requests from clients. .SH "STANDALONE SERVER" The recommended method for running distccd is as a standalone server. distccd will listen for network connections and fork several child processes to serve them. .PP If you installed distcc using a packaged version you may be able to start the server using the standard mechanism for your operating system, such as .RS .PP # service distcc start .RE .PP To start distccd as a standalone service, run a command like this either as root or an ordinary user: .RS .PP # distccd --daemon .RE .SH "RUNNING FROM INIT" distccd may be run as a standalone daemon under the control of another program like init(8) or daemontools. The super-server starts distccd when the system boots, and whenever it exits. .PP distccd should be started just as for a standalone server, except that the .B --no-detach option should be used so that the super-server can monitor it. .PP For example, to add distccd as a process to Linux sysvinit, add this line to .I /etc/inittab .RS .PP dscc:2345:respawn:/usr/local/bin/distccd --verbose --no-detach --daemon .RE .SH "RUNNING FROM INETD" distccd may be started from a network super-server such as inetd or xinetd. In this case inetd listens for network connections and invokes distccd when one arrives. .PP This is slightly less efficient than running a standalone distccd daemon. distccd is not able to regulate the number of concurrent jobs accepted, but there may be an option in your inetd configuration to do so. .PP For traditional Unix inetd, a line like this can be added to /etc/inetd.conf: .RS .PP distcc stream tcp nowait.6000 root /usr/local/bin/distccd distccd --inetd .RE .PP inetd imposes a limit on the rate of connections to a service to protect against accidental or intentional overuse. The default in Linux NetKit inetd is 40 per minute, which is far too low for distccd. The \.6000 option raises the limit to 6000 per minute. .SH "TERMINATING DISTCCD" To shut down a standalone server, send a SIGTERM signal to the parent process. The most reliable way to do this from a script is to use the .I --pid-file option to record its process ID. Shutting down the server in this way should allow any jobs currently in progress to complete. .SH "OPTIONS" .TP .B --help Display summary usage information. .TP .B --version Shows the daemon version and exits. .TP .B -j, --jobs JOBS Sets a limit on the number of jobs that can be accepted at any time. By default this is set to two greater than the number of CPUs on the machine, to allow for some processes being blocked on network IO. (Daemon mode only.) .TP .B -N, --nice NICENESS Makes the daemon more nice about giving up the CPU to other tasks on the machine. NICENESS is an increment to the current priority of the process. The range of priorities depends on the operating system but is typically 0 to 20. By default the niceness is increased by 5. .TP .B -p, --port PORT Set the TCP port to listen on, rather than the default of 3632. (Daemon mode only.) .TP .B --listen ADDRESS Instructs the distccd daemon to listen on the IP address ADDRESS. This can be useful for access control on dual-homed hosts. (Daemon mode only.) .TP .B -P, --pid-file FILE Save daemon process id to file FILE. (Daemon mode only.) .TP .B --user USER If distccd gets executed as root, change to user USER. .TP .B -a, --allow IPADDR[/MASK] Instructs distccd to accept connections from the IP address IPADDR. A CIDR mask length can be supplied optionally after a trailing slash, e.g. 192.168.0.0/24, in which case addresses that match in the most significant MASK bits will be allowed. If no --allow options are specified, distccd will exit immediately! Unauthorized connections are rejected by closing the TCP connection immediately. A warning is logged on the server but nothing is sent to the client. .TP .B --allow-private Allow private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, and 127.0.0.0/8). .TP .B --job-lifetime SECONDS Kills a distccd job if it runs for more than SECONDS seconds. This prevents denial of service from clients that don't properly disconnect and compilers that fail to terminate. By default this is turned off. .TP .B --no-detach Do not detach from the shell that started the daemon. .TP .B --no-fork Don't fork children for each connection, to allow attaching gdb. Don't use this if you don't understand it! .TP .B --log-file FILE Send messages to file FILE instead of syslog. Logging directly to a file is significantly faster than going via syslog and is recommended. .TP .B --log-level LEVEL Set the minimum severity of error that will be included in the log file. Useful if you only want to see error messages rather than an entry for each connection. LEVEL can be any of the standard syslog levels, and in particular .I critical, error, warning, notice, info, or .I debug. .TP .B --log-stderr Send log messages to stderr, rather than to a file or syslog. This is mainly intended for use in debugging. Do not use in inetd mode. .TP .B --verbose Include debug messages in log. Equivalent to .B --log-level=debug .TP .B --wizard Turn on all options appropriate for starting distccd under gdb: run as a daemon, log verbosely to stderr, and do not detach or fork. For wizards only. .TP .B --stats Turn on the statistics HTTP server. By default it is off. (Daemon mode only.) .TP .B --stats-port PORT Set the TCP port to listen on for HTTP requests, rather than the default of 3633. (Daemon mode only.) .TP .B --inetd Serve a client connected to stdin/stdout. As the name suggests, this option should be used when distccd is run from within a super-server like inetd. distccd assumes inetd mode when stdin is a socket. .TP .B --daemon Bind and listen on a socket, rather than running from inetd. This is used for standalone mode. distccd assumes daemon mode at startup if stdin is a tty, so --daemon should be explicitly specified when starting distccd from a script or in a non-interactive ssh connection. .TP .B --enable-tcp-insecure By default (since Distcc 3.3) distcc will only execute binaries that are masqueraded to distcc in /usr/lib/distcc. This turns that off, and opens distcc up to executing arbitrary code. This feature is mainly for distcc's test suite. See MASQUERADING of .BR distcc (1). .TP .B --zeroconf Register the availability of this distccd server using Avahi Zeroconf DNS Service Discovery (DNS-SD). This allows distcc clients on the local network to access this distccd server without explicitly listing its host name or IP address in their distcc host list: the distcc clients can just use "+zeroconf" in their distcc host lists. Can optionally use -j parameter to specify the maximum number of jobs that this server can process concurrently. .B This option is only available if distccd was compiled with .B Avahi support enabled. .TP .B --auth Perform GSS-API based mutual authentication. .B This option is only available if distccd was compiled with .B the --with-auth configure option. .TP .B --show-principal Displays the name of the distccd security principal extracted from the environment. .B This option is only available if distccd was compiled with .B the --with-auth configure option. .TP .B --blacklist=FILE Instruct distccd to reject connections from users whose principal names are listed in FILE. .B This option is only available if distccd was compiled with .B the --with-auth configure option and if distccd is run with the .B --auth option. .TP .B --whitelist=FILE Instruct distccd to accept connections only from users whose principal names are listed in FILE. .B This option is only available if distccd was compiled with .B the --with-auth configure option and if distccd is run with the .B --auth option. .SH "SEARCH PATHS" .PP distcc can pass either a relative or an absolute name for the compiler to distccd. If distcc is given an explicit absolute compiler filename, that name is used verbatim on both the client and server. If the compiler name is not an absolute path, or if the client is used in masquerade mode, then the server's PATH is searched. .PP distccd inherits its search path from its parent process. By default distccd tries to remove directories that seem to contain distccd masquerade links, to guard against inadvertent recursion. The .B DISTCCD_PATH environment variable may be used to set the path. .PP The search path is logged when --verbose is given. In case of confusion, check the logs. .PP When distccd is run over ssh, the .I $HOME/.ssh/environment file may be useful in setting the path. See .B ssh(1). .SH "DIAGNOSTICS" distccd logs messages to syslog's .I daemon facility by default, which normally writes to .I /var/log/daemon or .I /var/log/messages. Log messages can be sent to a different file using the .B --log-file option. .SH "ENVIRONMENT VARIABLES" .TP .B "DISTCC_CMDLIST" If the environment variable DISTCC_CMDLIST is set, load a list of supported commands from the file named by DISTCC_CMDLIST, and refuse to serve any command whose last DISTCC_CMDLIST_MATCHWORDS last words do not match those of a command in that list. See the comments in src/serve.c. .TP .B "DISTCC_CMDLIST_NUMWORDS" The number of words, from the end of the command, to match. The default is 1. .TP .B "DISTCCD_PATH" When starting distccd, if this value is set it will be used unaltered for the command-execution PATH. The code that normally tries to remove masquerade directories from the path is skipped. .TP .B "DISTCC_SAVE_TEMPS" If set to 1, temporary files are not deleted after use. .PP Note that .B "DISTCC_LOG" does not affect the log destination for the server. .TP .B "DISTCC_TCP_DEFER_ACCEPT" On Linux, turn on the TCP_DEFER_ACCEPT socket option. Defaults to on. .TP .B "TMPDIR" Directory for temporary files such as preprocessor output. By default /tmp/ is used. .TP .B "DISTCCD_PRINCIPAL" If set, specifies the name of the principal that distccd runs under, and is used to authenticate with the client. .B This environment variable is only used if distccd was compiled with .B the --with-auth configure option and if distccd is run with the --auth option. .SH "SEE ALSO" \fBdistcc\fR(1), \fBpump\fR(1), \fBinclude_server\fR(1), \fBgcc\fR(1), \fBmake\fR(1), and \fBccache\fR(1) .I http://code.google.com/p/distcc/ .SH "BUGS" IP-based access control is not secure against attackers able to spoof TCP connections, and cannot discriminate different users on a client. .PP TCP connections are not secure against attackers able to observe or modify network traffic. .PP Because ccache does not cache compilation from .B .i files, it is not useful to call it from distccd. .SH "LICENCE" You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warrany. A copy of the GPL is included in the file COPYING. .SH "AUTHOR" distcc was written by Martin Pool , with the co-operation of many scholars including Wayne Davison, Frerich Raabe, Dimitri Papadopoulos and others noted in the NEWS file. See \fBpump\fR(1) for the authors of pump mode. Please report bugs to . distcc-3.4/man/distccmon-text.1000066400000000000000000000031111404653710500164340ustar00rootroot00000000000000.TH distccmon-text 1 "2 October 2004" .SH "NAME" .LP distccmon\-text \- Displays current compilation jobs in text form. .SH "SYNTAX" .LP distccmon-text [DELAY] .SH "DESCRIPTION" .LP Displays current compilation jobs in text form. distccmon-text must be run on the client machine, with the same setting for .I DISTCC_DIR (or home directory) as the user running the distcc client. .SH "OPTIONS" .LP .TP \fBDELAY\fR repeatedly updates after \fIdelay\fP (fractional) seconds. .SH "OUTPUT FORMAT" .LP The output of distccmon-text contains one line for each job currently being compiled. Each line contains the following columns: .TP .I PID ID of the distcc client process. .TP .I STATE Identifies the phase of operation. In order these may be "Startup", "Blocked", "Connected", "Preprocess", "Conect", "Send", "Receive" and "Done". .TP .I FILE The input filename, if known. .TP .I HOST[SLOT] The compile hostname. May be followed in square brackets by the slot index for that host. .LP When a delay is specified, each block of output is terminated by a blank line. .SH "EXAMPLES" .LP To display currently active jobs (updated every second): .IP distccmon\-text 1 .LP To display the status once: .IP distccmon\-text .SH "AUTHORS" .LP distcc was written by Martin Pool , with the co\-operation of many scholars including Wayne Davison, Frerich Raabe, Dimitri Papadopoulos and others noted in the NEWS file. Please report bugs to . .SH "SEE ALSO" .LP d distccd(1), ccache(1), gcc(1), make(1) http://code.google.com/p/distcc/ https://ccache.dev/ distcc-3.4/man/include_server.1000066400000000000000000000332521404653710500165110ustar00rootroot00000000000000.TH include_server 1 "9 June 2008" .SH "NAME" include_server.py \- conservative approximation of include dependencies for C/C++ .SH "SYNOPSIS" .B include_server --port .I INCLUDE_SERVER_PORT [OPTIONS] .SH "DESCRIPTION" .P include_server.py starts an include server process. This process answers queries from \fBdistcc\fR(1) clients about what files to include in C/C++ compilations. The include_server.py command itself terminates as soon as the include server has been spawned. .PP The INCLUDE_SERVER_PORT argument is the name of a socket used for all communication between distcc clients and the include server. The \fBpump\fR(1) command is responsible for creating the socket location, for passing it to this script, and for passing it to all distcc clients via the environment variable named INCLUDE_SERVER_PORT. .PP The protocol used by the include server uses distcc's RPC implementation. Each distcc request consists of (1) the current directory and (2) the list of arguments of the compilation command. .PP If the include server is able to process the request, then it answers the distcc client by sending a list of filepaths. The filepaths are those of the compressed source and header files found to be necessary for compilation through include analysis. The list also comprises symbolic links and even dummy files needed for the compilation server to construct an accurate replica of the parts of the filesystem needed for compilation. In this way, a needed header file like /path/foo.h is compressed, renamed, and stored in a temporary location, such as /dev/shm/tmpiAvfGv.include_server-9368-1/path/foo.h.lzo. The distcc client will pass these files on to a compilation server, where they will be uncompressed and mounted temporarily. .PP If the include server is not able to process the request, then it returns the empty list to the distcc client. .PP There are two kinds of failures that relate to the include server. The include server may fail to compute the includes or fail in other ways, see section \fBINCLUDE SERVER SYMPTOMS\fR. Also, the compilation on the remove server may fail due to inadequacy of the calculated include closure, but then succeed when locally retried, see section \fBDISTCC DISCREPANCY SYMPTOMS\fR. .SH "OPTION SUMMARY" The following options are understood by include_server.py. .TP .B -dPAT, --debug_pattern=PAT Bit vector for turning on warnings and debugging 1 = warnings 2 = trace some functions other powers of two: see include_server/basics.py. .TP .B -e, --email Send email to 'distcc-pump-errors' or if defined, the value of environment variable DISTCC_EMAILLOG_WHOM_TO_BLAME, when include server gets in trouble. The default is to not send email. .TP .B --email_bound NUMBER Maximal number of emails to send (in addition to a final email). Default: 3. .TP .B --no-email Do not send email. This is the default. .TP .B --path_observation_re=RE Issue warning message whenever a filename is resolved to a realpath that is matched by RE, which is a regular expression in Python syntax. This is useful for finding out where files included actually come from. Use RE="" to find them all. Note: warnings must be enabled with at least -d1. .TP .B --pid_file FILEPATH The pid of the include server is written to file FILEPATH. This allows a script such a \fBpump\fR to tear down the include server. .TP .B -s, --statistics Print information to stdout about include analysis. .TP .B --stat_reset_triggers=LIST Flush stat caches when the timestamp of any filepath in LIST changes or the filepath comes in or out of existence. LIST is a colon separated string of filepaths, possibly containing simple globs (as allowed by Python's glob module). Print a warning whenever such a change happens (if warnings are enabled). This option allows limited exceptions to distcc_pump's normal assumption that source files are not modified during the build. .TP .B -t, --time Print elapsed, user, and system time to stderr. .TP .B --unsafe_absolute_includes Do preprocessing on the compilation server even if includes of absolute filepaths are encountered. Normally the include-server will fall back on local preprocessing if it detects any absolute includes. Thus, this flag is useful for preventing such fallbacks when the absolute includes are a false alarm, either because the absolute include is discarded during preprocessing or because the absolutely included file exists on the compilation servers. .IP More precisely, with --unsafe_absolute_includes absolute includes are ignored for the purposes of gathering the include closure. Using this option may lead to incorrect results because (1) the header may actually be included on the compilation server and it may not be the same as on the client, (2) the include directives of the header are not further analyzed. .IP The option is useful for compiling code that has such hardcoded absolute locations of header files inside conditional directives (e.g. "#ifdef") that render the includes irrelevant. More precisely, these includes must be eliminated during preprocessing for the actual configuration. Then the question of existence of the header file is moot and the remote compilation is sound. This is often the case if such includes are meant for unusual configurations different from the actual configuration. .TP .B --no_force_dirs Do not force the creation of all directories used in an include path. May improve performance for some cases, but will break builds which use include structures like "" without including other files in foo/. .TP .B -v, --verify Verify that files in CPP closure are contained in closure calculated by include processor. .TP .B -w, --write_include_closure Write a .d_approx file which lists all the included files calculated by the include server; with -x, additionally write the included files as calculated by CPP to a .d_exact file. .TP .B -x, --exact_analysis Use CPP instead, do not omit system headers files. .SH "INCLUDE SERVER SYMPTOMS AND ISSUES" The most likely messages and warnings to come from the include processor are listed below. .PP .TP .B "Preprocessing locally. Include server not covering: Couldn't determine default system include directories" To determine the default system header directories, the include server runs the compiler once for each language needed during its session. This message indicates that the compiler specified to distcc is not present on the client. .PP .TP .B Preprocessing locally. Include server not covering: Bailing out because include server spent more than ...s user time handling request In uncommon situations, the include server fails to analyze very complicated macro expressions. The distcc client will use plain distcc mode. .PP .TP .B Warning: Filepath must be relative but isn't The include server does not accept absolute filepaths, such as /usr/include/stdio.h, in include directives, because there is no guarantee that this header on the compilation server machine will be the same as that on the client. The include server gives up analyzing the include closure. The distcc client cannot use pump-mode. .IP To overcome this problem in a not always reliable way, set the environment variable INCLUDE_SERVER_ARGS='--unsafe_absolute_includes' when invoking the pump script to pass the --unsafe_absolute_includes option to the include server. .PP .TP .B Warning: Absolute filepath ... was IGNORED The --unsafe_absolute_includes is in use. This situation happens under the same circumstances as when "Filepath must be relative but isn't" is issued, but in this case the include will provide an answer to the distcc client. .PP .TP .B Warning: Path '/PATH/FILE' changed/came into existence/no longer exists These warnings are issued when using stat reset triggers. Because /PATH/FILE changed, the include server clears its caches; the new version of the file (or the lack of it) renders the include analysis invalid. This message can usually be ignored; it does signify a somewhat precarious use of files by the build system. It is recommended to fix the build system so that files are not rewritten. .PP .TP .B Warning: For translation unit ..., lookup of file ... resolved to ... whose realpath is ... This warning occurs with --path_observation_re when a new realpath matching a source or header file is observed. .SH "DISTCC DISCREPANCY SYMPTOMS" The interactions between the build system, distcc, and the include server is somewhat complex. When a distcc commands receives a failing compilation from the remote server it retries the compilation locally. This section discusses the causes of discrepancies between remote and local compilation. These are flagged by the demotion message: .PP .B __________Warning: ... pump-mode compilation(s) failed on server, .B but succeeded locally. .br .B __________Distcc-pump was demoted to plain mode. .B See the Distcc Discrepancy Symptoms section in the include_server(1) man .B page. .PP The pump script issues this message at the end of the build. This means that for at least one distcc invocation a local compilation succeeded after the remote compilation failed. Each distcc invocation for which such a discrepancy occurred in turn also issues a message such as: .PP .B Warning: remote compilation of '...' failed, .B retried locally and got a different result. .PP The demotion makes subsequent distcc invocations use plain distcc mode. Thus preprocessing will take place on the local machine for the remainder of the build. This technique prevents very slow builds where all compilations end up on the local machine after failing remotely. .PP Of course, if the local compilations fails after the remote failures, then the distcc invocation exits with the non-zero status of the local compilation. The error messages printed are also those of the local compilation. .PP The fallback behavior for distcc-pump mode to local compilation can be disabled by setting the environment variable DISTCC_FALLBACK to 0, which makes the distcc command fail as soon as the remote compilation has failed. This setting is very useful for debugging why the remote compilation went wrong, because now the output from the server will be printed. .PP Next we discuss the possible causes of discrepancies. .PP .TP .B The user changed a source or header file during the build. This yields inconsistent results of course. .PP .TP .B A source or header file changed during the build. The build system rewrites a file. For Linux kernel 2.6, this happens for 'include/linux/compile.h' and 'include/asm/asm-offsets.h'. This condition is fixed by letting the include server know that it must reset its caches when a stat of any of the files changes. Practically, this is done by gathering the files in a colon-separated list and then setting the INCLUDE_SERVER_ARGS environment variable when invoking the pump script, so that it passes the .B --stat_reset_triggers option; for example, INCLUDE_SERVER_ARGS="--stat_reset_triggers=include/linux/compile.h:include/asm/asm-offsets.h" .PP .TP .B A header file is potentially included, but does not exist, and is then later included. This occurs when some header foo.h includes another header file trick.h, but the trick.h file has not yet been generated and the inclusion is actually ignored because of preprocessing directives. The include server will probe for the existence of trick.h, because it overapproximates all possible ways directives actually evaluate. The file trick.h is determined not to exist. If it is later generated, and then really included, then the include server will falsely believe that the file still does not exist. The solution to this problem is to make the build system generate trick.h before the first time any header file is included that makes a syntactic reference to trick.h .PP .TP .B The include server was started with \fB--unsafe_absolute_includes\fR. This is a problem if there are header files locally that do not exist remotely and that are actually used. Such includes are often protected by conditional directives that evaluate so that are actually used on only specific and often uncommon platforms. If you are not compiling for such a platform, then it may be correct to use \fB--unsafe_absolute_include\fR. .PP .TP .B The include server has calculated the wrong includes. We do not know of such a situation. .SH "EXIT CODES" The exit code of include_server.py is usually 0. That the include server has been started properly is communicated through the existence of the pid_file. .SH "ENVIRONMENT VARIABLES" .B DISTCC_EMAILLOG_WHOM_TO_BLAME The email address to use for include server automated emails. The default is 'distcc-pump-errors' (which is an email address that probably will not exist in your domain). .PP Additionally, the invocation of the compiler may use additional environment variables. .SH "BUGS" If you think you have found a distcc bug, please see the file .I reporting-bugs.txt in the documentation directory for information on how to report it. .PP In distcc-pump mode, the include server is unable to handle certain very complicated computed includes as found in parts of the Boost library. The include server will time out and distcc will revert to plain mode. .PP Other known bugs may be documented on .I http://code.google.com/p/distcc/ .SH "AUTHOR" The include server was written by Nils Klarlund, with assistance from Fergus Henderson, Manos Renieris, and Craig Silverstein. Please report bugs to . .SH "LICENCE" You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warrany. A copy of the GPL is included in the file COPYING. .SH "SEE ALSO" \fBdistcc\fR(1), \fBdistccd\fR(1), \fBinclude_server\fR(1), and \fBgcc\fR(1). http://code.google.com/p/distcc/ https://ccache.dev/ distcc-3.4/man/lsdistcc.1000066400000000000000000000063031404653710500153050ustar00rootroot00000000000000.TH lsdistcc 1 "1 May 2012" .SH "NAME" lsdistcc \- simple distcc server discovery .SH "SYNOPSIS" .B lsdistcc [\fIOPTIONS\fR] [\fIFORMAT\fR] .PP .B lsdistcc [\fIOPTIONS\fR] .I host1 ... .SH "DESCRIPTION" .B lsdistcc autodetects listening distcc servers either by looking in DNS for hosts named according to a given .IR FORMAT , or by checking the host names given on the command line. Hosts are considered good servers based solely on whether their name fits the format and whether they are listening on the right port (and optionally whether they respond when you send them a compile job). Scans for hosts named according to .I FORMAT (default is "distcc%d"; see .BR printf (3)) and starting from 1, so hosts such as distcc1, distcc2, and so on. Stops after 7 seconds or the first host name that does not resolve. Prints the names of all such servers listening on distcc's port. If a list of host names is given in the command line, .B lsdistcc will only check those hosts. .SH "OPTIONS" .TP .B --help Displays summary instructions .TP .B -l Output latency in milliseconds after each hostname (not including DNS latency) .TP .B -n Print IP address rather than name .TP .B -x Append ,down to down hosts in host list .TP .BI -t "TIMEOUT" Set number of seconds to stop searching after [7] .TP .BI -h "HTIMEOUT" Set number of milliseconds before retrying gethostbyname [500] .TP .BI -c "CTIMEOUT" Set number of milliseconds before giving up on connect [900] (0 to inhibit connect) .TP .BI -k "KTIMEOUT" Set number of milliseconds before giving up on compile [1500] (0 to inhibit compile) .TP .BI -m "BITS" Set number of bits of address that must match first host found [0] .TP .BI -o "OVERLAP" Set number of extra DNS requests to send [1] .TP .BI -g "DNSGAP" Set number of missing DNS entries to tolerate [0] .TP .BI -r "PORT" Port to connect to [3632] .TP .BI -P "PROTOCOL" Protocol version to use (1-3) [1] .TP .BI -p "COMPILER" Name of compiler to use [none] .TP .B -d Append DNS domain name to format .TP .B -v Verbose .SH "EXAMPLES" Scan for servers named distcc1, distcc2, ... that provide a compiler named gcc-4.6 and include their latencies in the output: .RS $ lsdistcc \-l \-pgcc-4.6 .RE Scan for a compiler named gcc-4.6 on the servers hosta, somehost, hostx, and hosty: .RS $ lsdistcc \-pgcc-4.6 hosta somehost hostx hosty .RE To use the program in a build script, add the lines: .RS DISTCC_HOSTS=`lsdistcc` .br export DISTCC_HOSTS .RE before the line that invokes make. Or, in a Makefile, add the line: .RS export DISTCC_HOSTS = $(shell lsdistcc) .RE Or use .BR pump (1) which automatically invokes lsdistcc if you set DISTCC_POTENTIAL_HOSTS. .SH "EXIT STATUS" The exit status is 0 if any servers were found, and 1 otherwise. Uses 'for i=1... sprintf(format, i)' to construct names of servers, stops after 7 seconds or at second server that doesn't resolve, prints the names of all such servers listening on distcc's port. Default format is distcc%d. .SH "SEE ALSO" .BR distcc (1), .BR distccd (1), .BR pump (1), .BR printf (3) .I http://code.google.com/p/distcc/ .SH "AUTHOR" .B lsdistcc was written by Dan Kegel, Dongmin Zhang, and Manos Renieris. This manual page was written by Daniel Hartwig for the Debian project. distcc-3.4/man/pump.1000066400000000000000000000115371404653710500144630ustar00rootroot00000000000000.TH pump 1 "9 June 2008" .SH "NAME" pump \- accelerate remote compilation with distcc .SH "SYNOPSIS" .B pump .I BUILD-COMMAND [ARGS] \& ... .BR .PP eval ` .B pump --startup `; .I BUILD-COMMAND [ARGS] \& ... ; .B pump --shutdown .BR .SH "DESCRIPTION" .B pump is part of distcc. It is used for distcc's pump mode. Distcc's pump mode accelerates remote compilation with distcc by also distributing preprocessing to the servers. .PP For a detailed description of pump mode, including most notably some .B important restrictions, see the .BR distcc(1) man page, in particular the .B HOW PUMP-MODE WORKS section and the .B RESTRICTIONS ON PUMP MODE section. .PP The simplest usage is the form .RS .B pump .I COMMAND [ARG] \& ... .RE This will start an include server for distcc's "pump" mode; optionally run .B lsdistcc to compute the distcc host list; set some auxiliary environment variables; change PATH to use the distcc client in the same directory as the "pump" script; execute .I COMMAND with the specified .I ARG(s) \& ; and then shut down the include server. The .I COMMAND is typically a parallel build command, such as "make -j80", that will do many concurrent invocations of distcc. .PP An alternative way of invoking .B pump is to explicitly invoke "pump --startup" to start the include server and "pump --shutdown" to stop the include server. The "pump --startup" command will start up the include server, and will print out some environment variable settings. These environment variables are used to communicate between the pump-mode "distcc" client and the include server, and to communicate between "pump --startup" and "pump --shutdown". The caller of "pump --startup" is responsible for setting those environment variables before invoking "distcc" or "pump --shutdown". .PP For example: .RS eval `pump --startup` .br make -j80 .br pump --shutdown .RE .PP Note that distcc's pump-mode assumes that sources files will not be modified during the lifetime of the include server, so modifying source files during a build may cause inconsistent results. .SH "INVOKING LSDISTCC" When invoked in either the simple " .B pump .I COMMAND [ARG] \&... " form, or as " .B pump --startup \&", the .B pump script will invoke .B lsdistcc \& whenever DISTCC_POTENTIAL_HOSTS is set and DISTCC_HOSTS isn't. It will pass the value of DISTCC_POTENTIAL_HOSTS to .B lsdistcc and use the output of .B lsdistcc to set DISTCC_HOSTS. .SH "OPTIONS" .TP .B --help Displays summary instructions. .TP .B --startup Starts an include server, and outputs the environment variable settings needed for .BR distcc(1) or .B pump --shutdown to access it. .TP .B --shutdown Shuts down an include server started up by .B pump --startup. .SH "ENVIRONMENT VARIABLES" The following environment variables are all optional. .TP .B DISTCC_LOCATION The location of the distcc bin directory, which is normally inferred from the link-resolved dirname of argv[0]. If this location is in fact the bin directory inside an installation (as will be the case when the pump script in the installation executes), then Python executables and distcc itself will be retrieved from the parent directory of the location. .TP .B "DISTCC_MAX_DISCREPANCY" see the .BR distcc(1) man page. .TP .B DISTCC_POTENTIAL_HOSTS The distcc servers that will be queried by lsdistcc in order to produce a value for DISTCC_HOSTS. This value may be unset or null. In such cases, lsdistcc will not be invoked, and distcc will use DISTCC_HOSTS or the distcc hosts configuration file, as described in the "Host Specifications" section of .BR distcc(1). .TP .B DISTCC_HOSTS This variable is passed through to distcc but only if DISTCC_POTENTIAL_HOSTS is not set. .TP .B LSDISTCC_ARGS Extra arguments to pass to lsdistcc. See .B lsdistcc --help for more details. .TP .B INCLUDE_SERVER_ARGS Extra arguments to pass to the include server. .TP .B PYTHONOPTIMIZE If set to "", then Python optimization is disabled. .SH "EXAMPLE" .B pump make -j20 .SH "BUGS" .\" TODO: .\" Fix inconsistency between BUGS section and bug reporting instructions .\" in the AUTHORS section, both here and in distcc.1 and elsewhere. If you think you have found a distcc bug, please see the file .I reporting-bugs.txt in the documentation directory for information on how to report it. .SH "AUTHORS" The pump script and distcc's pump mode were written by Nils Klarlund, Manos Renieris, Fergus Henderson, and Craig Silverstein. Please report bugs to . .SH "LICENCE" .B pump is part of distcc. You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warranty. A copy of the GPL is included in the file COPYING. .SH "SEE ALSO" .\" TODO: add lsdistcc(1) once we have a man page for lsdistcc. \fBdistcc\fR(1), \fBdistccd\fR(1), \fBinclude_server\fR(1), \fBgcc\fR(1), and \fBmake\fR(1) distcc-3.4/mkinstalldirs000077500000000000000000000013211404653710500154410ustar00rootroot00000000000000#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.1 2002/05/28 02:43:45 mbp Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here distcc-3.4/packaging/000077500000000000000000000000001404653710500145625ustar00rootroot00000000000000distcc-3.4/packaging/RedHat/000077500000000000000000000000001404653710500157315ustar00rootroot00000000000000distcc-3.4/packaging/RedHat/conf/000077500000000000000000000000001404653710500166565ustar00rootroot00000000000000distcc-3.4/packaging/RedHat/conf/clients.allow000066400000000000000000000030561404653710500213630ustar00rootroot00000000000000# Comments start with "#" and go to end of line. Non-comment lines should # contain entries suitable for passing to the --allow option of distccd, e.g. # 192.168.1.100 # 192.168.2.0/8 # # From the distccd man page: # -a, --allow IPADDR[/MASK] # Instructs distccd to accept connections from the IP address # IPADDR. A CIDR mask length can be supplied optionally after a # trailing slash, e.g. 192.168.0.0/24, in which case addresses # that match in the most significant MASK bits will be allowed. # If no --allow options are specified, no clients are allowed! # Unauthorized connections are rejected by closing the TCP connec- # tion immediately. A warning is logged on the server but nothing # is sent to the client. # # You should only allow trusted hosts to connect to distccd in TCP mode. # You should assume that any user on the trusted hosts can (with some # effort) run arbitrary commands as the distcc user on the distccd host. # If this is not acceptable, then you should leave this config file empty # (apart from comments) and thus only allow SSH mode rather than TCP mode. # However, be aware that SSH mode has poorer performance than TCP mode. # For RedHat-like distributions using systemd, you should instead look in: # /etc/sysconfig/distccd in order to configure the trusted hosts list # See: https://bugzilla.redhat.com/show_bug.cgi?id=1187517 # Add your trusted hosts here, e.g. start by uncommented the line below. # 127.0.0.1 distcc-3.4/packaging/RedHat/conf/commands.allow.sh000066400000000000000000000033431404653710500221330ustar00rootroot00000000000000#!/bin/sh # --- /etc/site/current/distcc/commands.allow.sh ---------------------- # # This file is a shell script that gets sourced by /etc/init.d/distcc. # It's purpose is to optionally set the following environment # variables, which affect the behaviour of distccd: # # DISTCC_CMDLIST # If the environment variable DISTCC_CMDLIST is set, distccd will # load a list of supported commands from the file named by # DISTCC_CMDLIST, and will refuse to serve any command whose last # DISTCC_CMDLIST_MATCHWORDS last words do not match those of a # command in that list. See the comments in src/serve.c. # # DISTCC_CMDLIST_NUMWORDS # The number of words, from the end of the command, to match. The # default is 1. # # The interface to this script is as follows. # Input variables: # CMDLIST: this variable will hold the full path of the commands.allow file. # Side effects: # This script should write into the commands.allow file specified by # $CMDLIST. It should write the list of allowable commands, one per line. # Output variables: # DISTCC_CMDLIST and DISTCC_CMDLIST_NUMWORDS. See above. #-----------------------------------------------------------------------------# # Here are the parts that you may want to modify. numwords=1 allowed_compilers=" /usr/bin/cc /usr/bin/c++ /usr/bin/c89 /usr/bin/c99 /usr/bin/gcc /usr/bin/g++ /usr/bin/*gcc-* /usr/bin/*g++-* " # You shouldn't need to alter anything below here. [ "$CMDLIST" ] || { echo "$0: don't run this script directly!" >&2 echo "Run /etc/init.d/distcc (or equivalent) instead." >&2 exit 1 } echo $allowed_compilers | tr ' ' '\n' > $CMDLIST DISTCC_CMDLIST=$CMDLIST DISTCC_CMDLIST_NUMWORDS=$numwords distcc-3.4/packaging/RedHat/conf/hosts000066400000000000000000000003131404653710500177360ustar00rootroot00000000000000# --- /etc/distcc/hosts ----------------------- # See the "Hosts Specification" section of # "man distcc" for the format of this file. # # By default, just test that it works in loopback mode. 127.0.0.1 distcc-3.4/packaging/RedHat/default/000077500000000000000000000000001404653710500173555ustar00rootroot00000000000000distcc-3.4/packaging/RedHat/default/distcc000066400000000000000000000000211404653710500205420ustar00rootroot00000000000000STARTDISTCC=true distcc-3.4/packaging/RedHat/init.d/000077500000000000000000000000001404653710500171165ustar00rootroot00000000000000distcc-3.4/packaging/RedHat/init.d/distcc000066400000000000000000000123141404653710500203130ustar00rootroot00000000000000#!/bin/bash # # /etc/rc.d/init.d/distcc # # Starts the distccd daemon # # WARNING: Don't enable on untrusted networks # # NOTE: Allows access from all networks listed in clients.allow # clients.allow is searched for in directories # /etc/distcc/`dnsdomainname`/clients.allow # /etc/distcc/clients.allow # Format of clients.allow is # addr/size # addr/size # addr/size # etc. e.g. # 196.168.0.0/16 # 127.0.0.0/8 # # chkconfig: - 80 20 # description: Start the distcc daemon # processname: distccd # # # Determine which kind of configuration we're using # system=unknown if [ -f /etc/debian_version ]; then system=debian elif [ -f /etc/redhat-release ]; then system=redhat else echo "$0: Unknown system, please port and contact distcc-admin@google.com" 1>&2 exit 1 fi OPTIONS="--daemon --stats --job-lifetime=1200" USER=distcc PROG="distccd" PIDFILE=/var/run/$PROG.pid EXEC="/usr/bin/distccd" if [ -f /etc/sitename.install ]; then # Debian? DOMAIN=`cat /etc/sitename.install` if [ -d /etc/site/current/distcc ]; then CONFIGDIR=/etc/site/current/distcc else CONFIGDIR=/etc/distcc fi NORESTART=$CONFIGDIR/no-restart else # RedHat? DOMAIN=`/bin/dnsdomainname` CONFIGDIR=/etc/distcc NORESTART=$CONFIGDIR/no-restart fi if [ $system = redhat ]; then . /etc/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ ${NETWORKING} = "no" ] && exit 0 fi if [ $system = debian ]; then . /lib/lsb/init-functions . /etc/default/distcc thisscript="$0" if [ ! -f "$thisscript" ]; then echo "$0: Cannot find myself" 1>&2 exit 1 fi if [ "$STARTDISTCC" != "true" ] ; then echo "STARTDISTCC is set to false in /etc/default/distcc" echo "$something is not starting" exit 0 fi touch $PIDFILE chown $USER $PIDFILE fi # Tell distccd to store temp files in /var/tmp/distcc to avoid filling up / # The sysadmin may want to make /var/tmp/distcc be a symlink to a # directory on a larger partition (hence the /. on the chown) TMPDIR=/var/tmp/distcc export TMPDIR mkdir -p $TMPDIR chown $USER $TMPDIR/. rm -rf $TMPDIR/* || : chmod 700 $TMPDIR RETVAL=0 [ -x $EXEC ] || exit 0 ALLOWFILE="" if test -f $CONFIGDIR/$DOMAIN/clients.allow; then ALLOWFILE=$CONFIGDIR/$DOMAIN/clients.allow elif test -f $CONFIGDIR/clients.allow; then ALLOWFILE=$CONFIGDIR/clients.allow else echo "$0: no clients allowed" exit 1 fi if test "$ALLOWFILE"x != x; then ALLOW_OPTIONS=$(sed -e 's/#.*$//' -e '/^[ ]*$/d' -e 's/^/--allow=/' < $ALLOWFILE) OPTIONS="$OPTIONS $ALLOW_OPTIONS" fi COMMANDFILE="" if test -f $CONFIGDIR/$DOMAIN/commands.allow.sh; then COMMANDFILE=$CONFIGDIR/$DOMAIN/commands.allow.sh elif test -f $CONFIGDIR/commands.allow.sh; then COMMANDFILE=$CONFIGDIR/commands.allow.sh fi mkdir -p /var/state/distcc CMDLIST=/var/state/distcc/commands.allow rh_start() { echo -n "Starting $PROG" if [ -f $NORESTART ] then echo "failed -- $NORESTART present" return 1 fi env="TMPDIR=$TMPDIR" if [ -n "$COMMANDFILE" ]; then : > $CMDLIST . $COMMANDFILE if [ "$DISTCC_CMDLIST" ]; then env="$env DISTCC_CMDLIST=$DISTCC_CMDLIST" fi if [ "$DISTCC_CMDLIST_NUMWORDS" ]; then env="$env DISTCC_CMDLIST_NUMWORDS=$DISTCC_CMDLIST_NUMWORDS" fi fi daemon --user $USER $env $PROG $OPTIONS RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$PROG return $RETVAL } rh_stop() { echo -n "Shutting down $PROG" killproc $PROG RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$PROG return $RETVAL } redhat() { case "$1" in start) rh_start ;; stop) rh_stop ;; status) status $PROG RETVAL=$? ;; restart|reload) rh_stop rh_start RETVAL=$? ;; condrestart) if [ -f /var/lock/subsys/$PROG ]; then rh_stop rh_start RETVAL=$? fi ;; *) echo $"Usage $0 {start|stop|restart|condrestart|status}" exit 1 esac } deb_start() { log_begin_msg "Starting $PROG..." if [ -f $NORESTART ] then log_end_msg 1 echo "distcc start failed -- $NORESTART present" return 1 fi if [ -n "$COMMANDFILE" ]; then : > $CMDLIST . $COMMANDFILE export DISTCC_CMDLIST export DISTCC_CMDLIST_NUMWORDS fi export TMPDIR=$TMPDIR start-stop-daemon --start --name distccd --pidfile $PIDFILE -m --chuid $USER --exec $EXEC -- $OPTIONS RETVAL=$? log_end_msg $RETVAL return $RETVAL } deb_stop() { log_begin_msg "Shutting down $PROG..." start-stop-daemon --stop --name distccd --retry 30 RETVAL=$? [ $RETVAL -eq 0 ] || log_success_msg "$PROG not running?" log_end_msg $RETVAL [ $RETVAL -eq 0 ] && rm -f $PIDFILE return $RETVAL } debian() { case "$1" in start) deb_start ;; stop) deb_stop ;; restart|reload) deb_stop deb_start RETVAL=$? ;; condrestart) if [ -f /var/lock/subsys/$PROG ]; then deb_stop deb_start RETVAL=$? fi ;; *) echo $"Usage $0 {start|stop|restart|condrestart}" exit 1 esac } # See how we were called. RETVAL=0 if [ $system = debian ]; then debian "$@" elif [ $system = redhat ]; then redhat "$@" fi exit $RETVAL distcc-3.4/packaging/RedHat/logrotate.d/000077500000000000000000000000001404653710500201535ustar00rootroot00000000000000distcc-3.4/packaging/RedHat/logrotate.d/distcc000066400000000000000000000004631404653710500213520ustar00rootroot00000000000000# logrotate.d example configuration for distcc, contributed by Dag # Wieers. # The "copytruncate" option means distcc can keep appending to the # same filehandle. You would otherwise need to shut down and restart # distccd. /var/log/distccd.log { missingok copytruncate notifempty } distcc-3.4/packaging/RedHat/rpm.spec000066400000000000000000000230121404653710500174010ustar00rootroot00000000000000%define RELEASE 1 %define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE} %define _prefix /usr %define _bindir %{_prefix}/bin %define _datadir %{_prefix}/share #%define _docdir %{_datadir}/doc/%{name}-%{version} %define _docdir %{_datadir}/doc/%{name} %define _libdir %{_prefix}/lib %define _mandir %{_datadir}/man %define _sysconfdir /etc Name: %NAME Summary: Client side program for distributed C/C++ compilations. Version: %VERSION Release: %rel Group: Development/Languages Url: https://code.google.com/p/distcc License: GPL Packager: Google Inc. Source: http://%{NAME}.googlecode.com/files/%{NAME}-%{VERSION}.tar.gz Distribution: Redhat 7 and above. BuildRoot: %{_tmppath}/%{name}-buildroot Prefix: %_prefix Provides: distcc Obsoletes: crosstool-distcc distcc-include-server %description distcc is a program to distribute compilation of C or C++ code across several machines on a network. distcc should always generate the same results as a local compile, is simple to install and use, and is often two or more times faster than a local compile. %prep %setup %build # Work around broken sendfile in 32 bit apps on some x86_64 systems ac_cv_func_sendfile=no ac_cv_header_sys_sendfile_h=no ./configure \ --prefix=%{_prefix} \ --bindir=%{_bindir} \ --sysconfdir=%{_sysconfdir} \ --datadir=%{_datadir} \ --with-docdir=%{_docdir} \ --mandir=%{_mandir} \ --enable-rfc2553 --with-included-popt # Get the list of files installed by the python install process # by asking make to tell setup.py to put it in python_install_record make RPM_OPT_FLAGS="$RPM_OPT_FLAGS" \ PYTHON_INSTALL_RECORD=python_install_record %install rm -rf $RPM_BUILD_ROOT make DESTDIR=${RPM_BUILD_ROOT} PYTHON_INSTALL_RECORD=python_install_record install # The remaining configuration files are installed here rather than by # 'make install' because their nature and their locations are too # system-specific. mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d install -m 644 packaging/RedHat/logrotate.d/distcc $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/distcc mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d install -m 644 packaging/RedHat/xinetd.d/distcc $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d/distcc mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/init.d install -m 755 packaging/RedHat/init.d/distcc $RPM_BUILD_ROOT%{_sysconfdir}/init.d/distcc # TODO(fergus): move the next five lines to 'make install'? mkdir -p $RPM_BUILD_ROOT/%{_libdir}/distcc ln -s %{_bindir}/distcc $RPM_BUILD_ROOT/%{_libdir}/distcc/cc ln -s %{_bindir}/distcc $RPM_BUILD_ROOT/%{_libdir}/distcc/c++ ln -s %{_bindir}/distcc $RPM_BUILD_ROOT/%{_libdir}/distcc/gcc ln -s %{_bindir}/distcc $RPM_BUILD_ROOT/%{_libdir}/distcc/g++ %clean rm -rf $RPM_BUILD_ROOT %files -f python_install_record %defattr(-, root, root, 0755) %{_bindir}/distcc %{_bindir}/distccmon-text %{_bindir}/lsdistcc %{_libdir}/distcc %{_bindir}/pump %dir %{_sysconfdir}/distcc %config %{_sysconfdir}/distcc/hosts %doc %{_mandir}/man1/distcc.1.gz %doc %{_mandir}/man1/distccmon-text.1.gz %doc %{_mandir}/man1/pump.1.gz %doc %{_mandir}/man1/include_server.1.gz %doc %{_mandir}/man1/lsdistcc.1.gz %doc %{_docdir} %package server Summary: Server side program for distributed C/C++ compilations. Group: Development/Languages Provides: distccd Obsoletes: crosstool-distcc-server %description server distcc is a program to distribute compilation of C or C++ code across several machines on a network. distcc should always generate the same results as a local compile, is simple to install and use, and is often two or more times faster than a local compile. %files server %defattr(-, root, root, 0755) %{_bindir}/distccd %dir %{_sysconfdir}/logrotate.d %config %{_sysconfdir}/logrotate.d/distcc # Don't list init.d dir because on Red Hat it's a symlink owned by # chkconfig, so it causes a conflict on install. #%dir %{_sysconfdir}/init.d %config %{_sysconfdir}/init.d/distcc %dir %{_sysconfdir}/xinetd.d/ %config %{_sysconfdir}/xinetd.d/distcc %dir %{_sysconfdir}/distcc %config %{_sysconfdir}/distcc/clients.allow %config %{_sysconfdir}/distcc/commands.allow.sh %dir %{_sysconfdir}/default %config %{_sysconfdir}/default/distcc %doc %{_mandir}/man1/distccd.1.gz %pre server %post server DISTCC_USER=distcc if [ -s /etc/redhat-release ]; then # sadly, can't useradd -s /sbin/nologin on rh71, since # then starting the service as user distcc fails, # since it uses su - without overriding the shell :-( # See https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=26894 /sbin/service distcc stop &>/dev/null || : if fgrep 'nice initlog $INITLOG_ARGS -c "su - $user' /etc/init.d/functions | fgrep -v '.-s ' > /dev/null 2>&1 ; then # Kludge: for Red Hat 6.2, don't use -s /sbin/nologin /usr/sbin/useradd -d /var/run/distcc -m -r $DISTCC_USER &>/dev/null || : else # but do for everyone else /usr/sbin/useradd -d /var/run/distcc -m -r -s /sbin/nologin $DISTCC_USER &>/dev/null || : fi else echo Creating $DISTCC_USER user... if ! id $DISTCC_USER > /dev/null 2>&1 ; then if ! id -g $DISTCC_USER > /dev/null 2>&1 ; then addgroup --system --gid 11 $DISTCC_USER fi adduser --quiet --system --gid 11 \ --home / --no-create-home --uid 15 $DISTCC_USER fi fi DISTCC_LOGFILE=/var/log/distccd.log if [ ! -s $DISTCC_LOGFILE ]; then touch $DISTCC_LOGFILE chown ${DISTCC_USER}:adm $DISTCC_LOGFILE chmod 640 $DISTCC_LOGFILE fi if ! grep -q "3632/tcp" /etc/services; then echo -e "distcc\t\t3632/tcp\t\t\t# Distcc Distributed Compiler" >> /etc/services fi if ! grep -q "^distcc:" /etc/hosts.allow; then echo -e "distcc:\t127.0.0.1" >> /etc/hosts.allow fi # Update runlevel settings and start daemon. if [ -s /etc/redhat-release ]; then /sbin/chkconfig --add distcc /etc/init.d/distcc start || exit 0 else if [ -x "/etc/init.d/distcc" ]; then update-rc.d -f distcc remove >/dev/null update-rc.d distcc defaults 95 05 >/dev/null if [ -x /usr/sbin/invoke-rc.d ]; then start_command="invoke-rc.d distcc start" else start_command="/etc/init.d/distcc start" fi $start_command || { echo "To enable distcc's TCP mode, you should edit these files" echo " %{_sysconfdir}/distcc/clients.allow" echo " %{_sysconfdir}/distcc/commands.allow.sh" echo "and then run (as root)" echo " $start_command" echo "For more info, including alternatives to TCP mode, see" echo "%{_docdir}/INSTALL and %{_docdir}/examples/README." } fi fi %preun server # Remove hosts.allow entry. if grep -q "^distcc:" /etc/hosts.allow; then sed -e "/^distcc/d" /etc/hosts.allow > /etc/hosts.allow.new mv /etc/hosts.allow.new /etc/hosts.allow fi # Stop daemon and clear runlevel settings. if [ -s /etc/redhat-release ]; then if [ $1 -eq 0 ]; then /sbin/service distcc stop &>/dev/null || : fi # chkconfig --del must run before deleting init script. /sbin/chkconfig --del distcc else if [ -x "/etc/init.d/distcc" ]; then if [ -x /usr/sbin/invoke-rc.d ] ; then invoke-rc.d distcc stop || exit 0 else /etc/init.d/distcc stop || exit 0 fi fi fi %postun server # TODO(mtm) Should Red Hat also remove user/group? if [ -s /etc/debian_version ]; then case "$1" in purge) deluser --quiet --system distcc delgroup --quiet --system distcc ;; remove) ;; upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) ;; *) echo "postrm called with unknown argument \`$1'" >&2 exit 1 ;; esac if [ "$1" = "purge" ] ; then # update-rc.d must run after deleting init script. update-rc.d distcc remove >/dev/null || exit 0 fi fi %changelog * Sat Mar 12 2008 Craig Silverstein 3.0-1 - Updated to 3.0 - Added include-server files - useradd is run in post- rather than pre-install - distcc server is automatically started - Remove source package generation - Man pages are now unzipped - Deb packages now also built, using alien * Sat May 31 2003 Terry Griffin 2.5-2 - Updated to 2.5 * Sat May 24 2003 Terry Griffin 2.4.2-2 - Updated to 2.4.2 * Sat May 17 2003 Terry Griffin 2.3-2 - Updated to 2.3 * Sun May 04 2003 Terry Griffin 2.1-2 - Updated to 2.1 - Added symbolic links for masquerade mode * Fri Mar 28 2003 Terry Griffin 2.0.1-2 - Updated to 2.0.1 - Removed info file from document list. * Tue Feb 25 2003 Terry Griffin 1.2.1-2 - Updated to 1.2.1 * Mon Jan 27 2003 Terry Griffin 1.1-2 - Updated to 1.1 - Minor improvements to the RPM spec file * Mon Dec 16 2002 Terry Griffin 0.15-2 - Changed server user back to 'nobody' * Fri Dec 13 2002 Terry Griffin 0.15-2 - Updated to 0.15 - Changed port number in server configs to 3632 * Sat Nov 23 2002 Terry Griffin 0.14-2 - Updated to 0.14 - Major rework of the RPM spec file - Added Red Hat server config files for both xinetd and SysV init. - Change server user to daemon. * Sat Nov 09 2002 Terry Griffin 0.12-1 - Updated to 0.12 * Thu Oct 10 2002 Terry Griffin 0.11-3 - First binary packages for Red Hat 8.x - Fixed xinetd config file for location of distccd. * Mon Sep 30 2002 Terry Griffin 0.11-2 - Moved distccd back to /usr/bin from /usr/sbin. * Sat Sep 28 2002 Terry Griffin 0.11-1 - Initial build (Red Hat 7.x) - Client and server in separate binary packages - Added xinetd config file - Moved distccd to /usr/sbin - Added version number suffix to the documentation directory distcc-3.4/packaging/RedHat/xinetd.d/000077500000000000000000000000001404653710500174465ustar00rootroot00000000000000distcc-3.4/packaging/RedHat/xinetd.d/distcc000066400000000000000000000005151404653710500206430ustar00rootroot00000000000000# default: on # description: distccd serves C/C++ compilation requests from distcc clients. # WARNING: This service should ONLY be used on trusted networks. service distcc { socket_type = stream protocol = tcp port = 3632 wait = no user = nobody server = /usr/bin/distccd server_args = --inetd disable = yes } distcc-3.4/packaging/deb.sh000077500000000000000000000007721404653710500156610ustar00rootroot00000000000000#!/bin/sh -e # This takes a package name and version, # and a list of rpms to convert to .deb files. # It puts them all under a debian-* directory under the current directory. # # Run this from the 'packaging' directory, just under rootdir PACKAGE="$1"; VERSION="$2"; shift; shift; # Clean out any old .deb files from a previous build. rm -f "$PACKAGE"*[-._]"$VERSION".deb for file in "$@"; do fakeroot alien -c -k -v "$file" done echo echo "The Debian package files are located in $PWD:" ls *.deb distcc-3.4/packaging/googlecode_upload.py000077500000000000000000000357161404653710500206260ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright 2006, 2007 Google Inc. All Rights Reserved. # Author: danderson@google.com (David Anderson) # # Modifications for distcc Copyright 2008 Google Inc. # Author: Craig Silverstein. # # Script for uploading files to a Google Code project. # # This is intended to be both a useful script for people who want to # streamline project uploads and a reference implementation for # uploading files to Google Code projects. # # To upload a file to Google Code, you need to provide a path to the # file on your local machine, a small summary of what the file is, a # project name, and a valid account that is a member or owner of that # project. You can optionally provide a list of labels that apply to # the file. The file will be uploaded under the same name that it has # in your local filesystem (that is, the "basename" or last path # component). Run the script with '--help' to get the exact syntax # and available options. # # Note that the upload script requests that you enter your # googlecode.com password. This is NOT your Gmail account password! # This is the password you use on googlecode.com for committing to # Subversion and uploading files. You can find your password by going # to http://code.google.com/hosting/settings when logged in with your # Gmail account. If you have already committed to your project's # Subversion repository, the script will automatically retrieve your # credentials from there (unless disabled, see the output of '--help' # for details). # # If you are looking at this script as a reference for implementing # your own Google Code file uploader, then you should take a look at # the upload() function, which is the meat of the uploader. You # basically need to build a multipart/form-data POST request with the # right fields and send it to https://PROJECT.googlecode.com/files . # Authenticate the request using HTTP Basic authentication, as is # shown below. # # Licensed under the terms of the Apache Software License 2.0: # http://www.apache.org/licenses/LICENSE-2.0 # # Questions, comments, feature requests and patches are most welcome. # Please direct all of these to the Google Code users group: # http://groups.google.com/group/google-code-hosting """Google Code file uploader script. """ __author__ = 'danderson@google.com (David Anderson)' import httplib import os.path import optparse import getpass import base64 import sys import re def extract_version(project, file_paths): """Given a list of filenames belonging to a given Google Code project, derive from that the version number. Do this by looking for a .tar.gz, .tgz. .tar.bz2, or .zip file, and assume those are named -.. Verify by making sure and are substrings in all given files. Returns version, or empty string if couldn't figure it out. """ for file_path in file_paths: m = re.match(r'%s-([0-9]+\.[0-9]+.*)\.(tar\.gz|tgz|tar\.bz2|zip)' % project, os.path.basename(file_path), re.I) if m: version = m.group(1) break else: # for ended without finding anything return '' # Now verify the project and version are everywhere for file_path in file_paths: if file_path.find(version) == -1: return '' return version def derive_summary_and_labels(file_path, package, version): """Derive a summary associated with a file given some file information. Returns (summary, list_of_labels). Raises ValueError if there was a problem figuring out the summary. Given a filename like google_perftools-0.94.rpm, this function would derive * summary = "RPM for google_perftools 0.94" * labels = ["Type-Package", "OpSys-Linux"] """ if file_path.find('distcc-server') != -1: project = 'Distcc server (distccd)' elif file_path.find('distcc') != -1: if file_path.find('.tar') != -1: # The source distribution has both client and server project = 'Distcc (both client and server)' else: project = 'Distcc client (distcc)' else: raise ValueError("Unknown project name for '%s'" % file_path) if (file_path.endswith('.tar.gz') or file_path.endswith('.tgz') or file_path.endswith('.tar.bz2')): return ('Tarball for %s %s' % (project, version), ('Type-Source', 'OpSys-All')) if file_path.endswith('.zip'): return ('Zip file for %s %s' % (project, version), ('Type-Source', 'OpSys-Windows')) if file_path.endswith('.deb') and file_path.find('-dev_') != -1: return ('Development deb for %s %s' % (project, version), ('Type-Package', 'OpSys-Linux')) if file_path.endswith('.deb'): return ('Deb for %s %s' % (project, version), ('Type-Package', 'OpSys-Linux')) if file_path.endswith('.src.rpm') and file_path.find('-devel-') != -1: return ('Source-code RPM for %s %s' % (project, version), ('Type-Package', 'OpSys-Linux')) if file_path.endswith('.rpm') and file_path.find('-devel-') != -1: return ('Development RPM for %s %s' % (project, version), ('Type-Package', 'OpSys-Linux')) if file_path.endswith('.rpm'): return ('RPM for %s %s' % (project, version), ('Type-Package', 'OpSys-Linux')) raise ValueError("Unknown file extension for '%s'" % file_path) def get_svn_config_dir(): """Return user's Subversion configuration directory.""" try: from win32com.shell.shell import SHGetFolderPath import win32com.shell.shellcon except ImportError: # If we can't import the win32api, just use ~; this is right on unix, and # returns not entirely unreasonable results on Windows. return os.path.expanduser('~/.subversion') # We're on Windows with win32api; use APPDATA. return os.path.join(SHGetFolderPath(0, win32com.shell.shellcon.CSIDL_APPDATA, 0, 0).encode('utf-8'), 'Subversion') def get_svn_auth(project_name, config_dir): """Return (username, password) for project_name in config_dir.""" # Default to returning nothing. result = (None, None) try: from svn.core import SVN_AUTH_CRED_SIMPLE, svn_config_read_auth_data from svn.core import SubversionException except ImportError: return result realm = (' Google Code Subversion Repository' % project_name) # auth may be none even if no exception is raised, e.g. if config_dir does # not exist, or exists but has no entry for realm. try: auth = svn_config_read_auth_data(SVN_AUTH_CRED_SIMPLE, realm, config_dir) except SubversionException: auth = None if auth is not None: try: result = (auth['username'], auth['password']) except KeyError: # Missing the keys, so return nothing. pass return result def upload(file, project_name, user_name, password, summary, labels=None): """Upload a file to a Google Code project's file server. Args: file: The local path to the file. project_name: The name of your project on Google Code. user_name: Your Google account name. password: The googlecode.com password for your account. Note that this is NOT your global Google Account password! summary: A small description for the file. labels: an optional list of label strings with which to tag the file. Returns: a tuple: http_status: 201 if the upload succeeded, something else if an error occurred. http_reason: The human-readable string associated with http_status file_url: If the upload succeeded, the URL of the file on Google Code, None otherwise. """ # The login is the user part of user@gmail.com. If the login provided # is in the full user@domain form, strip it down. if '@' in user_name: user_name = user_name[:user_name.index('@')] form_fields = [('summary', summary)] if labels is not None: form_fields.extend([('label', l.strip()) for l in labels]) content_type, body = encode_upload_request(form_fields, file) upload_host = '%s.googlecode.com' % project_name upload_uri = '/files' auth_token = base64.b64encode('%s:%s'% (user_name, password)) headers = { 'Authorization': 'Basic %s' % auth_token, 'User-Agent': 'Googlecode.com uploader v0.9.4', 'Content-Type': content_type, } server = httplib.HTTPSConnection(upload_host) server.request('POST', upload_uri, body, headers) resp = server.getresponse() server.close() if resp.status == 201: location = resp.getheader('Location', None) else: location = None return resp.status, resp.reason, location def encode_upload_request(fields, file_path): """Encode the given fields and file into a multipart form body. fields is a sequence of (name, value) pairs. file is the path of the file to upload. The file will be uploaded to Google Code with the same file name. Returns: (content_type, body) ready for httplib.HTTP instance """ BOUNDARY = '----------Googlecode_boundary_reindeer_flotilla' CRLF = '\r\n' body = [] # Add the metadata about the upload first for key, value in fields: body.extend( ['--' + BOUNDARY, 'Content-Disposition: form-data; name="%s"' % key, '', value, ]) # Now add the file itself file_name = os.path.basename(file_path) f = open(file_path, 'rb') file_content = f.read() f.close() body.extend( ['--' + BOUNDARY, 'Content-Disposition: form-data; name="filename"; filename="%s"' % file_name, # The upload server determines the mime-type, no need to set it. 'Content-Type: application/octet-stream', '', file_content, ]) # Finalize the form body body.extend(['--' + BOUNDARY + '--', '']) return 'multipart/form-data; boundary=%s' % BOUNDARY, CRLF.join(body) def upload_find_auth(file_path, project_name, summary, labels=None, config_dir=None, user_name=None, tries=3): """Find credentials and upload a file to a Google Code project's file server. file_path, project_name, summary, and labels are passed as-is to upload. If config_dir is None, try get_svn_config_dir(); if it is 'none', skip trying the Subversion configuration entirely. If user_name is not None, use it for the first attempt; prompt for subsequent attempts. Args: file_path: The local path to the file. project_name: The name of your project on Google Code. summary: A small description for the file. labels: an optional list of label strings with which to tag the file. config_dir: Path to Subversion configuration directory, 'none', or None. user_name: Your Google account name. tries: How many attempts to make. """ if config_dir != 'none': # Try to load username/password from svn config for first try. if config_dir is None: config_dir = get_svn_config_dir() (svn_username, password) = get_svn_auth(project_name, config_dir) if user_name is None: # If username was not supplied by caller, use svn config. user_name = svn_username else: # Just initialize password for the first try. password = None while tries > 0: if user_name is None: # Read username if not specified or loaded from svn config, or on # subsequent tries. sys.stdout.write('Please enter your googlecode.com username: ') sys.stdout.flush() user_name = sys.stdin.readline().rstrip() if password is None: # Read password if not loaded from svn config, or on subsequent tries. print 'Please enter your googlecode.com password.' print '** Note that this is NOT your Gmail account password! **' print 'It is the password you use to access Subversion repositories.' prompt = 'Password (listed at http://code.google.com/hosting/settings): ' password = getpass.getpass(prompt) status, reason, url = upload(file_path, project_name, user_name, password, summary, labels) # Returns 403 Forbidden instead of 401 Unauthorized for bad # credentials as of 2007-07-17. if status in [httplib.FORBIDDEN, httplib.UNAUTHORIZED]: # Rest for another try. user_name = password = None tries = tries - 1 else: # We're done. break return status, reason, url def main(): parser = optparse.OptionParser(usage='googlecode-upload.py -s SUMMARY ' '-p PROJECT [options] FILE [FILE] ...') parser.add_option('--config-dir', dest='config_dir', metavar='DIR', help='read svn auth data from DIR' ' ("none" means not to use svn auth data)') parser.add_option('-s', '--summary', dest='summary', help='Short description of the file' ' (if not set, description will derive from filename)') parser.add_option('-u', '--user', dest='user', help='Your Google Code username' ' (if not set, the program will prompt you)') parser.add_option('-l', '--labels', dest='labels', help='An optional list of labels to attach to the file' ' (if not set, labels will derive from filename)') options, args = parser.parse_args() if not args: parser.error('File(s) to upload not provided.') project = 'distcc' # We hard-code that. :-) if options.labels: user_labels = options.labels.split(',') else: user_labels = None default_user = os.environ.get('USER', 'unknown') if options.user: user = options.user else: print 'Enter username ( takes the default of "%s"):' % default_user, user = raw_input() or default_user prompt = 'Password (listed at http://code.google.com/hosting/settings): ' password = getpass.getpass(prompt) version = extract_version(project, args) successes = 0 failures = 0 for file_path in args: # If the user did not specify the summary or labels, derive these # from the filename. try: (derived_summary, derived_labels) = \ derive_summary_and_labels(file_path, project, version) except ValueError, why: print "%s" % why failures += 1 continue summary = options.summary or derived_summary labels = user_labels or derived_labels # The find_auth functionality is currently broken; see # http://code.google.com/p/support/issues/detail?id=558 # This is why we asked for the password/username above. ## status, reason, url = upload_find_auth(file_path, options.project, ## options.summary, labels, ## options.config_dir, options.user) status, reason, url = upload(file_path, project, user, password, summary, labels) if url: print '%s was uploaded successfully.' % file_path print 'URL: %s' % url print successes += 1 else: print 'An error occurred. %s was not uploaded.' % file_path print 'Google Code upload server said: %s (%s)' % (reason, status) print failures += 1 print "Upload status: %d successes, %d failures." % (successes, failures) return failures if __name__ == '__main__': sys.exit(main()) distcc-3.4/packaging/rpm.sh000077500000000000000000000052551404653710500157260ustar00rootroot00000000000000#!/bin/sh -e # Run this from the 'packaging' directory, just under rootdir # We can only build rpm packages, if the rpm build tools are installed if [ \! -x /usr/bin/rpmbuild ] then echo "Cannot find /usr/bin/rpmbuild. Not building an rpm." 1>&2 exit 0 fi # Check if we have a bad kernel + RPM combination; that is, a kernel # that does not support vdso, and a find-requires script that doesn't # notice that and special-case linux-gate as a result. # Background: # Versions of RPM prior to 4.4.1 incorrectly add a dependency on # 'linux-gate.so.1', which is a virtual dso in 2.6+ Linux # kernels. Since this is not a real lib provided by any package, the # resulting RPMs won't install due to failed dependency checks. # For the curious, more linux-gate details are documented at: # http://www.trilithium.com/johan/2005/08/linux-gate/ if ! cat /proc/self/maps | grep -q vdso; then if ! grep -q 'linux-gate' /usr/lib/rpm/find-requires; then echo 'ERROR: Your combination of RPM and kernel is buggy.' echo 'Upgrade to RPM 4.4.1-5 or later, or patch /usr/lib/rpm/find-requires' echo 'to special-case the "linux-gate" dependency.' echo 'see also http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=338515' exit 1 fi fi # Check the commandline flags PACKAGE="$1" VERSION="$2" fullname="${PACKAGE}-${VERSION}" archive=../$fullname.tar.gz if [ -z "$1" -o -z "$2" ] then echo "Usage: $0 " 1>&2 exit 0 fi # Double-check we're in the packages directory, just under rootdir if [ \! -r ../Makefile -a \! -r ../INSTALL ] then echo "Must run $0 in the 'packaging' directory, under the root directory." 1>&2 echo "Also, you must run \"make dist\" before running this script." 1>&2 exit 0 fi if [ \! -r "$archive" ] then echo "Cannot find $archive. Run \"make dist\" first." 1>&2 exit 0 fi # Create the directory where the input lives, and where the output should live RPM_SOURCE_DIR="/tmp/rpmsource-$fullname" RPM_BUILD_DIR="/tmp/rpmbuild-$fullname" trap 'rm -rf $RPM_SOURCE_DIR $RPM_BUILD_DIR; exit $?' EXIT HUP INT TERM rm -rf "$RPM_SOURCE_DIR" "$RPM_BUILD_DIR" mkdir "$RPM_SOURCE_DIR" mkdir "$RPM_BUILD_DIR" cp "$archive" "$RPM_SOURCE_DIR" rpmbuild -bb RedHat/rpm.spec \ --define "NAME $PACKAGE" \ --define "VERSION $VERSION" \ --define "_sourcedir $RPM_SOURCE_DIR" \ --define "_builddir $RPM_BUILD_DIR" \ --define "_rpmdir $RPM_SOURCE_DIR" # Clean out any existing rpms from a previous build. rm -f "$PACKAGE"*[-._]"$VERSION"[-._]*.rpm # We want to get not only the main package but devel etc, hence the middle * mv "$RPM_SOURCE_DIR"/*/"$PACKAGE"-*"$VERSION"*.rpm . echo echo "The rpm package file(s) are located in $PWD:" ls *.rpm distcc-3.4/popt/000077500000000000000000000000001404653710500136205ustar00rootroot00000000000000distcc-3.4/popt/.stamp-conf.in000066400000000000000000000000731404653710500162750ustar00rootroot00000000000000## Force popt directory to be created in build directory. distcc-3.4/popt/README.popt000066400000000000000000000010661404653710500154640ustar00rootroot00000000000000This is a perfectly ordinary copy of libpopt 1.7, except that the configure scripts have been munged to make them fit with distcc. NLS support has been removed, because distcc currently does not use it. It is only used on platforms that do not have a sufficiently up-to-date copy of their own. If you build distcc on a platform which has popt, this directory should not be used. (You can control that using the --with-included-popt configure flag.) popt has no apparent home page, but the source can be retrieved from ftp://ftp.rpm.org/pub/rpm/dist/rpm-4.1.xdistcc-3.4/popt/findme.c000066400000000000000000000022141404653710500152250ustar00rootroot00000000000000/** \ingroup popt * \file popt/findme.c */ /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #include "system.h" #include "findme.h" const char * findProgramPath(const char * argv0) { char * path = getenv("PATH"); char * pathbuf; char * start, * chptr; char * buf; if (argv0 == NULL) return NULL; /* XXX can't happen */ /* If there is a / in the argv[0], it has to be an absolute path */ if (strchr(argv0, '/')) return xstrdup(argv0); if (path == NULL) return NULL; start = pathbuf = alloca(strlen(path) + 1); buf = malloc(strlen(path) + strlen(argv0) + sizeof("/")); if (buf == NULL) return NULL; /* XXX can't happen */ strcpy(pathbuf, path); chptr = NULL; /*@-branchstate@*/ do { if ((chptr = strchr(start, ':'))) *chptr = '\0'; sprintf(buf, "%s/%s", start, argv0); if (!access(buf, X_OK)) return buf; if (chptr) start = chptr + 1; else start = NULL; } while (start && *start); /*@=branchstate@*/ free(buf); return NULL; } distcc-3.4/popt/findme.h000066400000000000000000000007701404653710500152370ustar00rootroot00000000000000/** \ingroup popt * \file popt/findme.h */ /* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #ifndef H_FINDME #define H_FINDME /** * Return absolute path to executable by searching PATH. * @param argv0 name of executable * @return (malloc'd) absolute path to executable (or NULL) */ /*@null@*/ const char * findProgramPath(/*@null@*/ const char * argv0) /*@*/; #endif distcc-3.4/popt/popt.c000066400000000000000000001023051404653710500147470ustar00rootroot00000000000000/** \ingroup popt * \file popt/popt.c */ /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist */ #undef MYDEBUG #include "system.h" #if HAVE_FLOAT_H #include #endif #include #include "findme.h" #include "poptint.h" #ifdef MYDEBUG /*@unchecked@*/ int _popt_debug = 0; #endif #ifndef HAVE_STRERROR static char * strerror(int errno) { extern int sys_nerr; extern char * sys_errlist[]; if ((0 <= errno) && (errno < sys_nerr)) return sys_errlist[errno]; else return POPT_("unknown errno"); } #endif #ifdef MYDEBUG /*@unused@*/ static void prtcon(const char *msg, poptContext con) { if (msg) fprintf(stderr, "%s", msg); fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n", con, con->os, (con->os->nextCharArg ? con->os->nextCharArg : ""), (con->os->nextArg ? con->os->nextArg : ""), con->os->next, (con->os->argv && con->os->argv[con->os->next] ? con->os->argv[con->os->next] : "")); } #endif void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) { con->execPath = _free(con->execPath); con->execPath = xstrdup(path); con->execAbsolute = allowAbsolute; /*@-nullstate@*/ /* LCL: con->execPath can be NULL? */ return; /*@=nullstate@*/ } static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt) /*@globals internalState@*/ /*@modifies internalState@*/ { if (opt != NULL) for (; opt->longName || opt->shortName || opt->arg; opt++) { if (opt->arg == NULL) continue; /* XXX program error. */ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { /* Recurse on included sub-tables. */ invokeCallbacksPRE(con, opt->arg); } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && (opt->argInfo & POPT_CBFLAG_PRE)) { /*@-castfcnptr@*/ poptCallbackType cb = (poptCallbackType)opt->arg; /*@=castfcnptr@*/ /* Perform callback. */ /*@-moduncon -noeffectuncon @*/ cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip); /*@=moduncon =noeffectuncon @*/ } } } static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt) /*@globals internalState@*/ /*@modifies internalState@*/ { if (opt != NULL) for (; opt->longName || opt->shortName || opt->arg; opt++) { if (opt->arg == NULL) continue; /* XXX program error. */ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { /* Recurse on included sub-tables. */ invokeCallbacksPOST(con, opt->arg); } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && (opt->argInfo & POPT_CBFLAG_POST)) { /*@-castfcnptr@*/ poptCallbackType cb = (poptCallbackType)opt->arg; /*@=castfcnptr@*/ /* Perform callback. */ /*@-moduncon -noeffectuncon @*/ cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip); /*@=moduncon =noeffectuncon @*/ } } } static void invokeCallbacksOPTION(poptContext con, const struct poptOption * opt, const struct poptOption * myOpt, /*@null@*/ const void * myData, int shorty) /*@globals internalState@*/ /*@modifies internalState@*/ { const struct poptOption * cbopt = NULL; if (opt != NULL) for (; opt->longName || opt->shortName || opt->arg; opt++) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { /* Recurse on included sub-tables. */ if (opt->arg != NULL) /* XXX program error */ invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty); } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && !(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) { /* Save callback info. */ cbopt = opt; } else if (cbopt != NULL && ((myOpt->shortName && opt->shortName && shorty && myOpt->shortName == opt->shortName) || (myOpt->longName && opt->longName && /*@-nullpass@*/ /* LCL: opt->longName != NULL */ !strcmp(myOpt->longName, opt->longName))) /*@=nullpass@*/ ) { /*@-castfcnptr@*/ poptCallbackType cb = (poptCallbackType)cbopt->arg; /*@=castfcnptr@*/ const void * cbData = (cbopt->descrip ? cbopt->descrip : myData); /* Perform callback. */ if (cb != NULL) { /* XXX program error */ /*@-moduncon -noeffectuncon @*/ cb(con, POPT_CALLBACK_REASON_OPTION, myOpt, con->os->nextArg, cbData); /*@=moduncon =noeffectuncon @*/ } /* Terminate (unless explcitly continuing). */ if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE)) return; } } } poptContext poptGetContext(const char * name, int argc, const char ** argv, const struct poptOption * options, int flags) { poptContext con = malloc(sizeof(*con)); if (con == NULL) return NULL; /* XXX can't happen */ memset(con, 0, sizeof(*con)); con->os = con->optionStack; con->os->argc = argc; /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */ con->os->argv = argv; /*@=dependenttrans =assignexpose@*/ con->os->argb = NULL; if (!(flags & POPT_CONTEXT_KEEP_FIRST)) con->os->next = 1; /* skip argv[0] */ con->leftovers = calloc( (argc + 1), sizeof(*con->leftovers) ); /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */ con->options = options; /*@=dependenttrans =assignexpose@*/ con->aliases = NULL; con->numAliases = 0; con->flags = flags; con->execs = NULL; con->numExecs = 0; con->finalArgvAlloced = argc * 2; con->finalArgv = calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) ); con->execAbsolute = 1; con->arg_strip = NULL; if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER")) con->flags |= POPT_CONTEXT_POSIXMEHARDER; if (name) { char * t = malloc(strlen(name) + 1); if (t) con->appName = strcpy(t, name); } /*@-internalglobs@*/ invokeCallbacksPRE(con, con->options); /*@=internalglobs@*/ return con; } static void cleanOSE(/*@special@*/ struct optionStackEntry *os) /*@uses os @*/ /*@releases os->nextArg, os->argv, os->argb @*/ /*@modifies os @*/ { os->nextArg = _free(os->nextArg); os->argv = _free(os->argv); os->argb = PBM_FREE(os->argb); } /*@-boundswrite@*/ void poptResetContext(poptContext con) { int i; if (con == NULL) return; while (con->os > con->optionStack) { cleanOSE(con->os--); } con->os->argb = PBM_FREE(con->os->argb); con->os->currAlias = NULL; con->os->nextCharArg = NULL; con->os->nextArg = NULL; con->os->next = 1; /* skip argv[0] */ con->numLeftovers = 0; con->nextLeftover = 0; con->restLeftover = 0; con->doExec = NULL; if (con->finalArgv != NULL) for (i = 0; i < con->finalArgvCount; i++) { /*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */ con->finalArgv[i] = _free(con->finalArgv[i]); /*@=unqualifiedtrans@*/ } con->finalArgvCount = 0; con->arg_strip = PBM_FREE(con->arg_strip); /*@-nullstate@*/ /* FIX: con->finalArgv != NULL */ return; /*@=nullstate@*/ } /*@=boundswrite@*/ /* Only one of longName, shortName should be set, not both. */ /*@-boundswrite@*/ static int handleExec(/*@special@*/ poptContext con, /*@null@*/ const char * longName, char shortName) /*@uses con->execs, con->numExecs, con->flags, con->doExec, con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/ /*@modifies con @*/ { poptItem item; int i; if (con->execs == NULL || con->numExecs <= 0) /* XXX can't happen */ return 0; for (i = con->numExecs - 1; i >= 0; i--) { item = con->execs + i; if (longName && !(item->option.longName && !strcmp(longName, item->option.longName))) continue; else if (shortName != item->option.shortName) continue; break; } if (i < 0) return 0; if (con->flags & POPT_CONTEXT_NO_EXEC) return 1; if (con->doExec == NULL) { con->doExec = con->execs + i; return 1; } /* We already have an exec to do; remember this option for next time 'round */ if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) { con->finalArgvAlloced += 10; con->finalArgv = realloc(con->finalArgv, sizeof(*con->finalArgv) * con->finalArgvAlloced); } i = con->finalArgvCount++; if (con->finalArgv != NULL) /* XXX can't happen */ { char *s = malloc((longName ? strlen(longName) : 0) + 3); if (s != NULL) { /* XXX can't happen */ if (longName) sprintf(s, "--%s", longName); else sprintf(s, "-%c", shortName); con->finalArgv[i] = s; } else con->finalArgv[i] = NULL; } /*@-nullstate@*/ /* FIX: con->finalArgv[] == NULL */ return 1; /*@=nullstate@*/ } /*@=boundswrite@*/ /* Only one of longName, shortName may be set at a time */ static int handleAlias(/*@special@*/ poptContext con, /*@null@*/ const char * longName, char shortName, /*@exposed@*/ /*@null@*/ const char * nextCharArg) /*@uses con->aliases, con->numAliases, con->optionStack, con->os, con->os->currAlias, con->os->currAlias->option.longName @*/ /*@modifies con @*/ { poptItem item = con->os->currAlias; int rc; int i; if (item) { if (longName && (item->option.longName && !strcmp(longName, item->option.longName))) return 0; if (shortName && shortName == item->option.shortName) return 0; } if (con->aliases == NULL || con->numAliases <= 0) /* XXX can't happen */ return 0; for (i = con->numAliases - 1; i >= 0; i--) { item = con->aliases + i; if (longName && !(item->option.longName && !strcmp(longName, item->option.longName))) continue; else if (shortName != item->option.shortName) continue; break; } if (i < 0) return 0; if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH) return POPT_ERROR_OPTSTOODEEP; /*@-boundsread@*/ if (nextCharArg && *nextCharArg) con->os->nextCharArg = nextCharArg; /*@=boundsread@*/ con->os++; con->os->next = 0; con->os->stuffed = 0; con->os->nextArg = NULL; con->os->nextCharArg = NULL; con->os->currAlias = con->aliases + i; rc = poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv, &con->os->argc, &con->os->argv); con->os->argb = NULL; return (rc ? rc : 1); } /*@-bounds -boundswrite @*/ static int execCommand(poptContext con) /*@globals internalState @*/ /*@modifies internalState @*/ { poptItem item = con->doExec; const char ** argv; int argc = 0; int rc; if (item == NULL) /*XXX can't happen*/ return POPT_ERROR_NOARG; if (item->argv == NULL || item->argc < 1 || (!con->execAbsolute && strchr(item->argv[0], '/'))) return POPT_ERROR_NOARG; argv = malloc(sizeof(*argv) * (6 + item->argc + con->numLeftovers + con->finalArgvCount)); if (argv == NULL) return POPT_ERROR_MALLOC; /* XXX can't happen */ if (!strchr(item->argv[0], '/') && con->execPath) { char *s = alloca(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/")); sprintf(s, "%s/%s", con->execPath, item->argv[0]); argv[argc] = s; } else { argv[argc] = findProgramPath(item->argv[0]); } if (argv[argc++] == NULL) return POPT_ERROR_NOARG; if (item->argc > 1) { memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1)); argc += (item->argc - 1); } if (con->finalArgv != NULL && con->finalArgvCount > 0) { memcpy(argv + argc, con->finalArgv, sizeof(*argv) * con->finalArgvCount); argc += con->finalArgvCount; } if (con->leftovers != NULL && con->numLeftovers > 0) { #if 0 argv[argc++] = "--"; #endif memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers); argc += con->numLeftovers; } argv[argc] = NULL; #ifdef __hpux rc = setresuid(getuid(), getuid(),-1); if (rc) return POPT_ERROR_ERRNO; #else /* * XXX " ... on BSD systems setuid() should be preferred over setreuid()" * XXX sez' Timur Bakeyev * XXX from Norbert Warmuth */ #if defined(HAVE_SETUID) rc = setuid(getuid()); if (rc) return POPT_ERROR_ERRNO; #elif defined (HAVE_SETREUID) rc = setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */ if (rc) return POPT_ERROR_ERRNO; #else ; /* Can't drop privileges */ #endif #endif if (argv[0] == NULL) return POPT_ERROR_NOARG; #ifdef MYDEBUG if (_popt_debug) { const char ** avp; fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc); for (avp = argv; *avp; avp++) fprintf(stderr, " '%s'", *avp); fprintf(stderr, "\n"); } #endif rc = execvp(argv[0], (char *const *)argv); return POPT_ERROR_ERRNO; } /*@=bounds =boundswrite @*/ /*@-boundswrite@*/ /*@observer@*/ /*@null@*/ static const struct poptOption * findOption(const struct poptOption * opt, /*@null@*/ const char * longName, char shortName, /*@null@*/ /*@out@*/ poptCallbackType * callback, /*@null@*/ /*@out@*/ const void ** callbackData, int singleDash) /*@modifies *callback, *callbackData */ { const struct poptOption * cb = NULL; /* This happens when a single - is given */ if (singleDash && !shortName && (longName && *longName == '\0')) shortName = '-'; for (; opt->longName || opt->shortName || opt->arg; opt++) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { const struct poptOption * opt2; /* Recurse on included sub-tables. */ if (opt->arg == NULL) continue; /* XXX program error */ opt2 = findOption(opt->arg, longName, shortName, callback, callbackData, singleDash); if (opt2 == NULL) continue; /* Sub-table data will be inheirited if no data yet. */ if (!(callback && *callback)) return opt2; if (!(callbackData && *callbackData == NULL)) return opt2; /*@-observertrans -dependenttrans @*/ *callbackData = opt->descrip; /*@=observertrans =dependenttrans @*/ return opt2; } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) { cb = opt; } else if (longName && opt->longName && (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) && /*@-nullpass@*/ /* LCL: opt->longName != NULL */ !strcmp(longName, opt->longName)) /*@=nullpass@*/ { break; } else if (shortName && shortName == opt->shortName) { break; } } if (!opt->longName && !opt->shortName) return NULL; /*@-modobserver -mods @*/ if (callback) *callback = NULL; if (callbackData) *callbackData = NULL; if (cb) { if (callback) /*@-castfcnptr@*/ *callback = (poptCallbackType)cb->arg; /*@=castfcnptr@*/ if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) { if (callbackData) /*@-observertrans@*/ /* FIX: typedef double indirection. */ *callbackData = cb->descrip; /*@=observertrans@*/ } } /*@=modobserver =mods @*/ return opt; } /*@=boundswrite@*/ static const char * findNextArg(/*@special@*/ poptContext con, unsigned argx, int delete_arg) /*@uses con->optionStack, con->os, con->os->next, con->os->argb, con->os->argc, con->os->argv @*/ /*@modifies con @*/ { struct optionStackEntry * os = con->os; const char * arg; do { int i; arg = NULL; while (os->next == os->argc && os > con->optionStack) os--; if (os->next == os->argc && os == con->optionStack) break; if (os->argv != NULL) for (i = os->next; i < os->argc; i++) { /*@-sizeoftype@*/ if (os->argb && PBM_ISSET(i, os->argb)) /*@innercontinue@*/ continue; if (*os->argv[i] == '-') /*@innercontinue@*/ continue; if (--argx > 0) /*@innercontinue@*/ continue; arg = os->argv[i]; if (delete_arg) { if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc); if (os->argb != NULL) /* XXX can't happen */ PBM_SET(i, os->argb); } /*@innerbreak@*/ break; /*@=sizeoftype@*/ } if (os > con->optionStack) os--; } while (arg == NULL); return arg; } /*@-boundswrite@*/ static /*@only@*/ /*@null@*/ const char * expandNextArg(/*@special@*/ poptContext con, const char * s) /*@uses con->optionStack, con->os, con->os->next, con->os->argb, con->os->argc, con->os->argv @*/ /*@modifies con @*/ { const char * a = NULL; size_t alen; char *t, *te; size_t tn = strlen(s) + 1; char c; te = t = malloc(tn);; if (t == NULL) return NULL; /* XXX can't happen */ while ((c = *s++) != '\0') { switch (c) { #if 0 /* XXX can't do this */ case '\\': /* escape */ c = *s++; /*@switchbreak@*/ break; #endif case '!': if (!(s[0] == '#' && s[1] == ':' && s[2] == '+')) /*@switchbreak@*/ break; /* XXX Make sure that findNextArg deletes only next arg. */ if (a == NULL) { if ((a = findNextArg(con, 1, 1)) == NULL) /*@switchbreak@*/ break; } s += 3; alen = strlen(a); tn += alen; *te = '\0'; t = realloc(t, tn); te = t + strlen(t); memcpy(te, a, alen); te += alen; continue; /*@notreached@*/ /*@switchbreak@*/ break; default: /*@switchbreak@*/ break; } *te++ = c; } *te = '\0'; t = realloc(t, strlen(t) + 1); /* XXX memory leak, hard to plug */ return t; } /*@=boundswrite@*/ static void poptStripArg(/*@special@*/ poptContext con, int which) /*@uses con->arg_strip, con->optionStack @*/ /*@defines con->arg_strip @*/ /*@modifies con @*/ { /*@-sizeoftype@*/ if (con->arg_strip == NULL) con->arg_strip = PBM_ALLOC(con->optionStack[0].argc); if (con->arg_strip != NULL) /* XXX can't happen */ PBM_SET(which, con->arg_strip); /*@=sizeoftype@*/ /*@-compdef@*/ /* LCL: con->arg_strip udefined? */ return; /*@=compdef@*/ } int poptSaveLong(long * arg, int argInfo, long aLong) { /* XXX Check alignment, may fail on funky platforms. */ if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1))) return POPT_ERROR_NULLARG; if (argInfo & POPT_ARGFLAG_NOT) aLong = ~aLong; switch (argInfo & POPT_ARGFLAG_LOGICALOPS) { case 0: *arg = aLong; break; case POPT_ARGFLAG_OR: *arg |= aLong; break; case POPT_ARGFLAG_AND: *arg &= aLong; break; case POPT_ARGFLAG_XOR: *arg ^= aLong; break; default: return POPT_ERROR_BADOPERATION; /*@notreached@*/ break; } return 0; } int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong) { /* XXX Check alignment, may fail on funky platforms. */ if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1))) return POPT_ERROR_NULLARG; if (argInfo & POPT_ARGFLAG_NOT) aLong = ~aLong; switch (argInfo & POPT_ARGFLAG_LOGICALOPS) { case 0: *arg = aLong; break; case POPT_ARGFLAG_OR: *arg |= aLong; break; case POPT_ARGFLAG_AND: *arg &= aLong; break; case POPT_ARGFLAG_XOR: *arg ^= aLong; break; default: return POPT_ERROR_BADOPERATION; /*@notreached@*/ break; } return 0; } /*@-boundswrite@*/ /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ int poptGetNextOpt(poptContext con) { const struct poptOption * opt = NULL; int done = 0; if (con == NULL) return -1; while (!done) { const char * origOptString = NULL; poptCallbackType cb = NULL; const void * cbData = NULL; const char * longArg = NULL; int canstrip = 0; int shorty = 0; while (!con->os->nextCharArg && con->os->next == con->os->argc && con->os > con->optionStack) { cleanOSE(con->os--); } if (!con->os->nextCharArg && con->os->next == con->os->argc) { /*@-internalglobs@*/ invokeCallbacksPOST(con, con->options); /*@=internalglobs@*/ if (con->doExec) return execCommand(con); return -1; } /* Process next long option */ if (!con->os->nextCharArg) { char * localOptString, * optString; int thisopt; /*@-sizeoftype@*/ if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) { con->os->next++; continue; } /*@=sizeoftype@*/ thisopt = con->os->next; if (con->os->argv != NULL) /* XXX can't happen */ origOptString = con->os->argv[con->os->next++]; if (origOptString == NULL) /* XXX can't happen */ return POPT_ERROR_BADOPT; if (con->restLeftover || *origOptString != '-') { if (con->flags & POPT_CONTEXT_POSIXMEHARDER) con->restLeftover = 1; if (con->flags & POPT_CONTEXT_ARG_OPTS) { con->os->nextArg = xstrdup(origOptString); return 0; } if (con->leftovers != NULL) /* XXX can't happen */ con->leftovers[con->numLeftovers++] = origOptString; continue; } /* Make a copy we can hack at */ localOptString = optString = strcpy(alloca(strlen(origOptString) + 1), origOptString); if (optString[0] == '\0') return POPT_ERROR_BADOPT; if (optString[1] == '-' && !optString[2]) { con->restLeftover = 1; continue; } else { char *oe; int singleDash; optString++; if (*optString == '-') singleDash = 0, optString++; else singleDash = 1; /* XXX aliases with arg substitution need "--alias=arg" */ if (handleAlias(con, optString, '\0', NULL)) continue; if (handleExec(con, optString, '\0')) continue; /* Check for "--long=arg" option. */ for (oe = optString; *oe && *oe != '='; oe++) {}; if (*oe == '=') { *oe++ = '\0'; /* XXX longArg is mapped back to persistent storage. */ longArg = origOptString + (oe - localOptString); } opt = findOption(con->options, optString, '\0', &cb, &cbData, singleDash); if (!opt && !singleDash) return POPT_ERROR_BADOPT; } if (!opt) { con->os->nextCharArg = origOptString + 1; } else { if (con->os == con->optionStack && opt->argInfo & POPT_ARGFLAG_STRIP) { canstrip = 1; poptStripArg(con, thisopt); } shorty = 0; } } /* Process next short option */ /*@-branchstate@*/ /* FIX: W2DO? */ if (con->os->nextCharArg) { origOptString = con->os->nextCharArg; con->os->nextCharArg = NULL; if (handleAlias(con, NULL, *origOptString, origOptString + 1)) continue; if (handleExec(con, NULL, *origOptString)) { /* Restore rest of short options for further processing */ origOptString++; if (*origOptString != '\0') con->os->nextCharArg = origOptString; continue; } opt = findOption(con->options, NULL, *origOptString, &cb, &cbData, 0); if (!opt) return POPT_ERROR_BADOPT; shorty = 1; origOptString++; if (*origOptString != '\0') con->os->nextCharArg = origOptString; } /*@=branchstate@*/ if (opt == NULL) return POPT_ERROR_BADOPT; /* XXX can't happen */ if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) { if (poptSaveInt((int *)opt->arg, opt->argInfo, 1L)) return POPT_ERROR_BADOPERATION; } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) { if (opt->arg) { if (poptSaveInt((int *)opt->arg, opt->argInfo, (long)opt->val)) return POPT_ERROR_BADOPERATION; } } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) { con->os->nextArg = _free(con->os->nextArg); /*@-usedef@*/ /* FIX: W2DO? */ if (longArg) { /*@=usedef@*/ longArg = expandNextArg(con, longArg); con->os->nextArg = longArg; } else if (con->os->nextCharArg) { longArg = expandNextArg(con, con->os->nextCharArg); con->os->nextArg = longArg; con->os->nextCharArg = NULL; } else { while (con->os->next == con->os->argc && con->os > con->optionStack) { cleanOSE(con->os--); } if (con->os->next == con->os->argc) { if (!(opt->argInfo & POPT_ARGFLAG_OPTIONAL)) /*@-compdef@*/ /* FIX: con->os->argv not defined */ return POPT_ERROR_NOARG; /*@=compdef@*/ con->os->nextArg = NULL; } else { /* * Make sure this isn't part of a short arg or the * result of an alias expansion. */ if (con->os == con->optionStack && (opt->argInfo & POPT_ARGFLAG_STRIP) && canstrip) { poptStripArg(con, con->os->next); } if (con->os->argv != NULL) { /* XXX can't happen */ /* XXX watchout: subtle side-effects live here. */ longArg = con->os->argv[con->os->next++]; longArg = expandNextArg(con, longArg); con->os->nextArg = longArg; } } } longArg = NULL; if (opt->arg) { switch (opt->argInfo & POPT_ARG_MASK) { case POPT_ARG_STRING: /* XXX memory leak, hard to plug */ *((const char **) opt->arg) = (con->os->nextArg) ? xstrdup(con->os->nextArg) : NULL; /*@switchbreak@*/ break; case POPT_ARG_INT: case POPT_ARG_LONG: { long aLong = 0; char *end; if (con->os->nextArg) { aLong = strtol(con->os->nextArg, &end, 0); if (!(end && *end == '\0')) return POPT_ERROR_BADNUMBER; } if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) { if (aLong == LONG_MIN || aLong == LONG_MAX) return POPT_ERROR_OVERFLOW; if (poptSaveLong((long *)opt->arg, opt->argInfo, aLong)) return POPT_ERROR_BADOPERATION; } else { if (aLong > INT_MAX || aLong < INT_MIN) return POPT_ERROR_OVERFLOW; if (poptSaveInt((int *)opt->arg, opt->argInfo, aLong)) return POPT_ERROR_BADOPERATION; } } /*@switchbreak@*/ break; case POPT_ARG_FLOAT: case POPT_ARG_DOUBLE: { double aDouble = 0.0; char *end; if (con->os->nextArg) { /*@-mods@*/ int saveerrno = errno; errno = 0; aDouble = strtod(con->os->nextArg, &end); if (errno == ERANGE) return POPT_ERROR_OVERFLOW; errno = saveerrno; /*@=mods@*/ if (*end != '\0') return POPT_ERROR_BADNUMBER; } if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) { *((double *) opt->arg) = aDouble; } else { #define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a)) if ((_ABS(aDouble) - FLT_MAX) > DBL_EPSILON) return POPT_ERROR_OVERFLOW; if ((FLT_MIN - _ABS(aDouble)) > DBL_EPSILON) return POPT_ERROR_OVERFLOW; *((float *) opt->arg) = aDouble; } } /*@switchbreak@*/ break; default: fprintf(stdout, POPT_("option type (%d) not implemented in popt\n"), (opt->argInfo & POPT_ARG_MASK)); exit(EXIT_FAILURE); /*@notreached@*/ /*@switchbreak@*/ break; } } } if (cb) { /*@-internalglobs@*/ invokeCallbacksOPTION(con, con->options, opt, cbData, shorty); /*@=internalglobs@*/ } else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL)) done = 1; if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) { con->finalArgvAlloced += 10; con->finalArgv = realloc(con->finalArgv, sizeof(*con->finalArgv) * con->finalArgvAlloced); } if (con->finalArgv != NULL) { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3); if (s != NULL) { /* XXX can't happen */ if (opt->longName) sprintf(s, "%s%s", ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), opt->longName); else sprintf(s, "-%c", opt->shortName); con->finalArgv[con->finalArgvCount++] = s; } else con->finalArgv[con->finalArgvCount++] = NULL; } if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) /*@-ifempty@*/ ; /*@=ifempty@*/ else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) /*@-ifempty@*/ ; /*@=ifempty@*/ else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) { if (con->finalArgv != NULL && con->os->nextArg) con->finalArgv[con->finalArgvCount++] = /*@-nullpass@*/ /* LCL: con->os->nextArg != NULL */ xstrdup(con->os->nextArg); /*@=nullpass@*/ } } return (opt ? opt->val : -1); /* XXX can't happen */ } /*@=boundswrite@*/ const char * poptGetOptArg(poptContext con) { const char * ret = NULL; /*@-branchstate@*/ if (con) { ret = con->os->nextArg; con->os->nextArg = NULL; } /*@=branchstate@*/ return ret; } const char * poptGetArg(poptContext con) { const char * ret = NULL; if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers) ret = con->leftovers[con->nextLeftover++]; return ret; } const char * poptPeekArg(poptContext con) { const char * ret = NULL; if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers) ret = con->leftovers[con->nextLeftover]; return ret; } /*@-boundswrite@*/ const char ** poptGetArgs(poptContext con) { if (con == NULL || con->leftovers == NULL || con->numLeftovers == con->nextLeftover) return NULL; /* some apps like [like RPM ;-) ] need this NULL terminated */ con->leftovers[con->numLeftovers] = NULL; /*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */ return (con->leftovers + con->nextLeftover); /*@=nullret =nullstate @*/ } /*@=boundswrite@*/ poptContext poptFreeContext(poptContext con) { poptItem item; int i; if (con == NULL) return con; poptResetContext(con); con->os->argb = _free(con->os->argb); if (con->aliases != NULL) for (i = 0; i < con->numAliases; i++) { item = con->aliases + i; /*@-modobserver -observertrans -dependenttrans@*/ item->option.longName = _free(item->option.longName); item->option.descrip = _free(item->option.descrip); item->option.argDescrip = _free(item->option.argDescrip); /*@=modobserver =observertrans =dependenttrans@*/ item->argv = _free(item->argv); } con->aliases = _free(con->aliases); if (con->execs != NULL) for (i = 0; i < con->numExecs; i++) { item = con->execs + i; /*@-modobserver -observertrans -dependenttrans@*/ item->option.longName = _free(item->option.longName); item->option.descrip = _free(item->option.descrip); item->option.argDescrip = _free(item->option.argDescrip); /*@=modobserver =observertrans =dependenttrans@*/ item->argv = _free(item->argv); } con->execs = _free(con->execs); con->leftovers = _free(con->leftovers); con->finalArgv = _free(con->finalArgv); con->appName = _free(con->appName); con->otherHelp = _free(con->otherHelp); con->execPath = _free(con->execPath); con->arg_strip = PBM_FREE(con->arg_strip); con = _free(con); return con; } int poptAddAlias(poptContext con, struct poptAlias alias, /*@unused@*/ int flags) { poptItem item = alloca(sizeof(*item)); memset(item, 0, sizeof(*item)); item->option.longName = alias.longName; item->option.shortName = alias.shortName; item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; item->option.arg = 0; item->option.val = 0; item->option.descrip = NULL; item->option.argDescrip = NULL; item->argc = alias.argc; item->argv = alias.argv; return poptAddItem(con, item, 0); } /*@-boundswrite@*/ /*@-mustmod@*/ /* LCL: con not modified? */ int poptAddItem(poptContext con, poptItem newItem, int flags) { poptItem * items, item; int * nitems; switch (flags) { case 1: items = &con->execs; nitems = &con->numExecs; break; case 0: items = &con->aliases; nitems = &con->numAliases; break; default: return 1; /*@notreached@*/ break; } *items = realloc((*items), ((*nitems) + 1) * sizeof(**items)); if ((*items) == NULL) return 1; item = (*items) + (*nitems); item->option.longName = (newItem->option.longName ? xstrdup(newItem->option.longName) : NULL); item->option.shortName = newItem->option.shortName; item->option.argInfo = newItem->option.argInfo; item->option.arg = newItem->option.arg; item->option.val = newItem->option.val; item->option.descrip = (newItem->option.descrip ? xstrdup(newItem->option.descrip) : NULL); item->option.argDescrip = (newItem->option.argDescrip ? xstrdup(newItem->option.argDescrip) : NULL); item->argc = newItem->argc; item->argv = newItem->argv; (*nitems)++; return 0; } /*@=mustmod@*/ /*@=boundswrite@*/ const char * poptBadOption(poptContext con, int flags) { struct optionStackEntry * os = NULL; if (con != NULL) os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os; /*@-nullderef@*/ /* LCL: os->argv != NULL */ return (os && os->argv ? os->argv[os->next - 1] : NULL); /*@=nullderef@*/ } const char *poptStrerror(const int error) { switch (error) { case POPT_ERROR_NOARG: return POPT_("missing argument"); case POPT_ERROR_BADOPT: return POPT_("unknown option"); case POPT_ERROR_BADOPERATION: return POPT_("mutually exclusive logical operations requested"); case POPT_ERROR_NULLARG: return POPT_("opt->arg should not be NULL"); case POPT_ERROR_OPTSTOODEEP: return POPT_("aliases nested too deeply"); case POPT_ERROR_BADQUOTE: return POPT_("error in parameter quoting"); case POPT_ERROR_BADNUMBER: return POPT_("invalid numeric value"); case POPT_ERROR_OVERFLOW: return POPT_("number too large or too small"); case POPT_ERROR_MALLOC: return POPT_("memory allocation failed"); case POPT_ERROR_ERRNO: return strerror(errno); default: return POPT_("unknown error"); } } int poptStuffArgs(poptContext con, const char ** argv) { int argc; int rc; if ((con->os - con->optionStack) == POPT_OPTION_DEPTH) return POPT_ERROR_OPTSTOODEEP; for (argc = 0; argv[argc]; argc++) {}; con->os++; con->os->next = 0; con->os->nextArg = NULL; con->os->nextCharArg = NULL; con->os->currAlias = NULL; rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv); con->os->argb = NULL; con->os->stuffed = 1; return rc; } const char * poptGetInvocationName(poptContext con) { return (con->os->argv ? con->os->argv[0] : ""); } /*@-boundswrite@*/ int poptStrippedArgv(poptContext con, int argc, char ** argv) { int numargs = argc; int j = 1; int i; /*@-sizeoftype@*/ if (con->arg_strip) for (i = 1; i < argc; i++) { if (PBM_ISSET(i, con->arg_strip)) numargs--; } for (i = 1; i < argc; i++) { if (con->arg_strip && PBM_ISSET(i, con->arg_strip)) continue; argv[j] = (j < numargs) ? argv[i] : NULL; j++; } /*@=sizeoftype@*/ return numargs; } /*@=boundswrite@*/ distcc-3.4/popt/popt.h000066400000000000000000000371551404653710500147660ustar00rootroot00000000000000/** \file popt/popt.h * \ingroup popt */ /* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #ifndef H_POPT #define H_POPT #include /* for FILE * */ #define POPT_OPTION_DEPTH 10 /** \ingroup popt * \name Arg type identifiers */ /*@{*/ #define POPT_ARG_NONE 0 /*!< no arg */ #define POPT_ARG_STRING 1 /*!< arg will be saved as string */ #define POPT_ARG_INT 2 /*!< arg will be converted to int */ #define POPT_ARG_LONG 3 /*!< arg will be converted to long */ #define POPT_ARG_INCLUDE_TABLE 4 /*!< arg points to table */ #define POPT_ARG_CALLBACK 5 /*!< table-wide callback... must be set first in table; arg points to callback, descrip points to callback data to pass */ #define POPT_ARG_INTL_DOMAIN 6 /*!< set the translation domain for this table and any included tables; arg points to the domain string */ #define POPT_ARG_VAL 7 /*!< arg should take value val */ #define POPT_ARG_FLOAT 8 /*!< arg will be converted to float */ #define POPT_ARG_DOUBLE 9 /*!< arg will be converted to double */ #define POPT_ARG_MASK 0x0000FFFF /*@}*/ /** \ingroup popt * \name Arg modifiers */ /*@{*/ #define POPT_ARGFLAG_ONEDASH 0x80000000 /*!< allow -longoption */ #define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /*!< don't show in help/usage */ #define POPT_ARGFLAG_STRIP 0x20000000 /*!< strip this arg from argv(only applies to long args) */ #define POPT_ARGFLAG_OPTIONAL 0x10000000 /*!< arg may be missing */ #define POPT_ARGFLAG_OR 0x08000000 /*!< arg will be or'ed */ #define POPT_ARGFLAG_NOR 0x09000000 /*!< arg will be nor'ed */ #define POPT_ARGFLAG_AND 0x04000000 /*!< arg will be and'ed */ #define POPT_ARGFLAG_NAND 0x05000000 /*!< arg will be nand'ed */ #define POPT_ARGFLAG_XOR 0x02000000 /*!< arg will be xor'ed */ #define POPT_ARGFLAG_NOT 0x01000000 /*!< arg will be negated */ #define POPT_ARGFLAG_LOGICALOPS \ (POPT_ARGFLAG_OR|POPT_ARGFLAG_AND|POPT_ARGFLAG_XOR) #define POPT_BIT_SET (POPT_ARG_VAL|POPT_ARGFLAG_OR) /*!< set arg bit(s) */ #define POPT_BIT_CLR (POPT_ARG_VAL|POPT_ARGFLAG_NAND) /*!< clear arg bit(s) */ #define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000 /*!< show default value in --help */ /*@}*/ /** \ingroup popt * \name Callback modifiers */ /*@{*/ #define POPT_CBFLAG_PRE 0x80000000 /*!< call the callback before parse */ #define POPT_CBFLAG_POST 0x40000000 /*!< call the callback after parse */ #define POPT_CBFLAG_INC_DATA 0x20000000 /*!< use data from the include line, not the subtable */ #define POPT_CBFLAG_SKIPOPTION 0x10000000 /*!< don't callback with option */ #define POPT_CBFLAG_CONTINUE 0x08000000 /*!< continue callbacks with option */ /*@}*/ /** \ingroup popt * \name Error return values */ /*@{*/ #define POPT_ERROR_NOARG -10 /*!< missing argument */ #define POPT_ERROR_BADOPT -11 /*!< unknown option */ #define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */ #define POPT_ERROR_BADQUOTE -15 /*!< error in parameter quoting */ #define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */ #define POPT_ERROR_BADNUMBER -17 /*!< invalid numeric value */ #define POPT_ERROR_OVERFLOW -18 /*!< number too large or too small */ #define POPT_ERROR_BADOPERATION -19 /*!< mutually exclusive logical operations requested */ #define POPT_ERROR_NULLARG -20 /*!< opt->arg should not be NULL */ #define POPT_ERROR_MALLOC -21 /*!< memory allocation failed */ /*@}*/ /** \ingroup popt * \name poptBadOption() flags */ /*@{*/ #define POPT_BADOPTION_NOALIAS (1 << 0) /*!< don't go into an alias */ /*@}*/ /** \ingroup popt * \name poptGetContext() flags */ /*@{*/ #define POPT_CONTEXT_NO_EXEC (1 << 0) /*!< ignore exec expansions */ #define POPT_CONTEXT_KEEP_FIRST (1 << 1) /*!< pay attention to argv[0] */ #define POPT_CONTEXT_POSIXMEHARDER (1 << 2) /*!< options can't follow args */ #define POPT_CONTEXT_ARG_OPTS (1 << 4) /*!< return args as options with value 0 */ /*@}*/ /** \ingroup popt */ struct poptOption { /*@observer@*/ /*@null@*/ const char * longName; /*!< may be NULL */ char shortName; /*!< may be '\0' */ int argInfo; /*@shared@*/ /*@null@*/ void * arg; /*!< depends on argInfo */ int val; /*!< 0 means don't return, just update flag */ /*@observer@*/ /*@null@*/ const char * descrip; /*!< description for autohelp -- may be NULL */ /*@observer@*/ /*@null@*/ const char * argDescrip; /*!< argument description for autohelp */ }; /** \ingroup popt * A popt alias argument for poptAddAlias(). */ struct poptAlias { /*@owned@*/ /*@null@*/ const char * longName; /*!< may be NULL */ char shortName; /*!< may be '\0' */ int argc; /*@owned@*/ const char ** argv; /*!< must be free()able */ }; /** \ingroup popt * A popt alias or exec argument for poptAddItem(). */ /*@-exporttype@*/ typedef struct poptItem_s { struct poptOption option; /*!< alias/exec name(s) and description. */ int argc; /*!< (alias) no. of args. */ /*@owned@*/ const char ** argv; /*!< (alias) args, must be free()able. */ } * poptItem; /*@=exporttype@*/ /** \ingroup popt * \name Auto-generated help/usage */ /*@{*/ /** * Empty table marker to enable displaying popt alias/exec options. */ /*@-exportvar@*/ /*@unchecked@*/ /*@observer@*/ extern struct poptOption poptAliasOptions[]; /*@=exportvar@*/ #define POPT_AUTOALIAS { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptAliasOptions, \ 0, "Options implemented via popt alias/exec:", NULL }, /** * Auto help table options. */ /*@-exportvar@*/ /*@unchecked@*/ /*@observer@*/ extern struct poptOption poptHelpOptions[]; /*@=exportvar@*/ #define POPT_AUTOHELP { NULL, '\0', POPT_ARG_INCLUDE_TABLE, poptHelpOptions, \ 0, "Help options:", NULL }, #define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL } /*@}*/ /** \ingroup popt */ /*@-exporttype@*/ typedef /*@abstract@*/ struct poptContext_s * poptContext; /*@=exporttype@*/ /** \ingroup popt */ #ifndef __cplusplus /*@-exporttype -typeuse@*/ typedef struct poptOption * poptOption; /*@=exporttype =typeuse@*/ #endif /*@-exportconst@*/ enum poptCallbackReason { POPT_CALLBACK_REASON_PRE = 0, POPT_CALLBACK_REASON_POST = 1, POPT_CALLBACK_REASON_OPTION = 2 }; /*@=exportconst@*/ #ifdef __cplusplus extern "C" { #endif /*@-type@*/ /** \ingroup popt * Table callback prototype. * @param con context * @param reason reason for callback * @param opt option that triggered callback * @param arg @todo Document. * @param data @todo Document. */ typedef void (*poptCallbackType) (poptContext con, enum poptCallbackReason reason, /*@null@*/ const struct poptOption * opt, /*@null@*/ const char * arg, /*@null@*/ const void * data) /*@*/; /** \ingroup popt * Initialize popt context. * @param name * @param argc no. of arguments * @param argv argument array * @param options address of popt option table * @param flags or'd POPT_CONTEXT_* bits * @return initialized popt context */ /*@only@*/ /*@null@*/ poptContext poptGetContext( /*@dependent@*/ /*@keep@*/ const char * name, int argc, /*@dependent@*/ /*@keep@*/ const char ** argv, /*@dependent@*/ /*@keep@*/ const struct poptOption * options, int flags) /*@*/; /** \ingroup popt * Reinitialize popt context. * @param con context */ /*@-exportlocal@*/ void poptResetContext(/*@null@*/poptContext con) /*@modifies con @*/; /*@=exportlocal@*/ /** \ingroup popt * Return value of next option found. * @param con context * @return next option val, -1 on last item, POPT_ERROR_* on error */ int poptGetNextOpt(/*@null@*/poptContext con) /*@globals fileSystem, internalState @*/ /*@modifies con, fileSystem, internalState @*/; /*@-redecl@*/ /** \ingroup popt * Return next option argument (if any). * @param con context * @return option argument, NULL if no more options are available */ /*@observer@*/ /*@null@*/ const char * poptGetOptArg(/*@null@*/poptContext con) /*@modifies con @*/; /** \ingroup popt * Return current option's argument. * @param con context * @return option argument, NULL if no more options are available */ /*@observer@*/ /*@null@*/ const char * poptGetArg(/*@null@*/poptContext con) /*@modifies con @*/; /** \ingroup popt * Peek at current option's argument. * @param con context * @return option argument */ /*@observer@*/ /*@null@*/ const char * poptPeekArg(/*@null@*/poptContext con) /*@*/; /** \ingroup popt * Return remaining arguments. * @param con context * @return argument array, terminated with NULL */ /*@observer@*/ /*@null@*/ const char ** poptGetArgs(/*@null@*/poptContext con) /*@modifies con @*/; /** \ingroup popt * Return the option which caused the most recent error. * @param con context * @param flags * @return offending option */ /*@observer@*/ const char * poptBadOption(/*@null@*/poptContext con, int flags) /*@*/; /*@=redecl@*/ /** \ingroup popt * Destroy context. * @param con context * @return NULL always */ /*@null@*/ poptContext poptFreeContext( /*@only@*/ /*@null@*/ poptContext con) /*@modifies con @*/; /** \ingroup popt * Add arguments to context. * @param con context * @param argv argument array, NULL terminated * @return 0 on success, POPT_ERROR_OPTSTOODEEP on failure */ int poptStuffArgs(poptContext con, /*@keep@*/ const char ** argv) /*@modifies con @*/; /** \ingroup popt * Add alias to context. * @todo Pass alias by reference, not value. * @deprecated Use poptAddItem instead. * @param con context * @param alias alias to add * @param flags (unused) * @return 0 on success */ /*@unused@*/ int poptAddAlias(poptContext con, struct poptAlias alias, int flags) /*@modifies con @*/; /** \ingroup popt * Add alias/exec item to context. * @param con context * @param newItem alias/exec item to add * @param flags 0 for alias, 1 for exec * @return 0 on success */ int poptAddItem(poptContext con, poptItem newItem, int flags) /*@modifies con @*/; /** \ingroup popt * Read configuration file. * @param con context * @param fn file name to read * @return 0 on success, POPT_ERROR_ERRNO on failure */ int poptReadConfigFile(poptContext con, const char * fn) /*@globals fileSystem, internalState @*/ /*@modifies con->execs, con->numExecs, fileSystem, internalState @*/; /** \ingroup popt * Read default configuration from /etc/popt and $HOME/.popt. * @param con context * @param useEnv (unused) * @return 0 on success, POPT_ERROR_ERRNO on failure */ int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) /*@globals fileSystem, internalState @*/ /*@modifies con->execs, con->numExecs, fileSystem, internalState @*/; /** \ingroup popt * Duplicate an argument array. * @note: The argument array is malloc'd as a single area, so only argv must * be free'd. * * @param argc no. of arguments * @param argv argument array * @retval argcPtr address of returned no. of arguments * @retval argvPtr address of returned argument array * @return 0 on success, POPT_ERROR_NOARG on failure */ int poptDupArgv(int argc, /*@null@*/ const char **argv, /*@null@*/ /*@out@*/ int * argcPtr, /*@null@*/ /*@out@*/ const char *** argvPtr) /*@modifies *argcPtr, *argvPtr @*/; /** \ingroup popt * Parse a string into an argument array. * The parse allows ', ", and \ quoting, but ' is treated the same as " and * both may include \ quotes. * @note: The argument array is malloc'd as a single area, so only argv must * be free'd. * * @param s string to parse * @retval argcPtr address of returned no. of arguments * @retval argvPtr address of returned argument array */ int poptParseArgvString(const char * s, /*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr) /*@modifies *argcPtr, *argvPtr @*/; /** \ingroup popt * Parses an input configuration file and returns an string that is a * command line. For use with popt. You must free the return value when done. * * Given the file: \verbatim # this line is ignored # this one too aaa bbb ccc bla=bla this_is = fdsafdas bad_line= really bad line really bad line = again 5555= 55555 test = with lots of spaces \endverbatim * * The result is: \verbatim --aaa --bbb --ccc --bla="bla" --this_is="fdsafdas" --5555="55555" --test="with lots of spaces" \endverbatim * * Passing this to poptParseArgvString() yields an argv of: \verbatim '--aaa' '--bbb' '--ccc' '--bla=bla' '--this_is=fdsafdas' '--5555=55555' '--test=with lots of spaces' \endverbatim * * @bug NULL is returned if file line is too long. * @bug Silently ignores invalid lines. * * @param fp file handle to read * @param *argstrp return string of options (malloc'd) * @param flags unused * @return 0 on success * @see poptParseArgvString */ /*@-fcnuse@*/ int poptConfigFileToString(FILE *fp, /*@out@*/ char ** argstrp, int flags) /*@globals fileSystem @*/ /*@modifies *fp, *argstrp, fileSystem @*/; /*@=fcnuse@*/ /** \ingroup popt * Return formatted error string for popt failure. * @param error popt error * @return error string */ /*@-redecl@*/ /*@observer@*/ const char *poptStrerror(const int error) /*@*/; /*@=redecl@*/ /** \ingroup popt * Limit search for executables. * @param con context * @param path single path to search for executables * @param allowAbsolute absolute paths only? */ void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) /*@modifies con @*/; /** \ingroup popt * Print detailed description of options. * @param con context * @param fp output file handle * @param flags (unused) */ void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/; /** \ingroup popt * Print terse description of options. * @param con context * @param fp output file handle * @param flags (unused) */ void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/; /** \ingroup popt * Provide text to replace default "[OPTION...]" in help/usage output. * @param con context * @param text replacement text */ /*@-fcnuse@*/ void poptSetOtherOptionHelp(poptContext con, const char * text) /*@modifies con @*/; /*@=fcnuse@*/ /** \ingroup popt * Return argv[0] from context. * @param con context * @return argv[0] */ /*@-redecl -fcnuse@*/ /*@observer@*/ const char * poptGetInvocationName(poptContext con) /*@*/; /*@=redecl =fcnuse@*/ /** \ingroup popt * Shuffle argv pointers to remove stripped args, returns new argc. * @param con context * @param argc no. of args * @param argv arg vector * @return new argc */ /*@-fcnuse@*/ int poptStrippedArgv(poptContext con, int argc, char ** argv) /*@modifies *argv @*/; /*@=fcnuse@*/ /** * Save a long, performing logical operation with value. * @warning Alignment check may be too strict on certain platorms. * @param arg integer pointer, aligned on int boundary. * @param argInfo logical operation (see POPT_ARGFLAG_*) * @param aLong value to use * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION */ /*@-incondefs@*/ int poptSaveLong(/*@null@*/ long * arg, int argInfo, long aLong) /*@modifies *arg @*/ /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/; /*@=incondefs@*/ /** * Save an integer, performing logical operation with value. * @warning Alignment check may be too strict on certain platorms. * @param arg integer pointer, aligned on int boundary. * @param argInfo logical operation (see POPT_ARGFLAG_*) * @param aLong value to use * @return 0 on success, POPT_ERROR_NULLARG/POPT_ERROR_BADOPERATION */ /*@-incondefs@*/ int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong) /*@modifies *arg @*/ /*@requires maxSet(arg) >= 0 /\ maxRead(arg) == 0 @*/; /*@=incondefs@*/ /*@=type@*/ #ifdef __cplusplus } #endif #endif distcc-3.4/popt/poptconfig.c000066400000000000000000000112261404653710500161360ustar00rootroot00000000000000/** \ingroup popt * \file popt/poptconfig.c */ /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #include #include "system.h" #include "poptint.h" /*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */ static void configLine(poptContext con, char * line) /*@modifies con @*/ { /*@-type@*/ int nameLength = strlen(con->appName); /*@=type@*/ const char * entryType; const char * opt; poptItem item = alloca(sizeof(*item)); int i, j; /*@-boundswrite@*/ memset(item, 0, sizeof(*item)); /*@-type@*/ if (strncmp(line, con->appName, nameLength)) return; /*@=type@*/ line += nameLength; if (*line == '\0' || !isspace((uint8_t)*line)) return; while (*line != '\0' && isspace((uint8_t)*line)) line++; entryType = line; while (*line == '\0' || !isspace((uint8_t)*line)) line++; *line++ = '\0'; while (*line != '\0' && isspace((uint8_t)*line)) line++; if (*line == '\0') return; opt = line; while (*line == '\0' || !isspace((uint8_t)*line)) line++; *line++ = '\0'; while (*line != '\0' && isspace((uint8_t)*line)) line++; if (*line == '\0') return; /*@-temptrans@*/ /* FIX: line alias is saved */ if (opt[0] == '-' && opt[1] == '-') item->option.longName = opt + 2; else if (opt[0] == '-' && opt[2] == '\0') item->option.shortName = opt[1]; /*@=temptrans@*/ if (poptParseArgvString(line, &item->argc, &item->argv)) return; /*@-modobserver@*/ item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN; for (i = 0, j = 0; i < item->argc; i++, j++) { const char * f; if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) { f = item->argv[i] + sizeof("--POPTdesc="); if (f[0] == '$' && f[1] == '"') f++; item->option.descrip = f; item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; j--; } else if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) { f = item->argv[i] + sizeof("--POPTargs="); if (f[0] == '$' && f[1] == '"') f++; item->option.argDescrip = f; item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN; item->option.argInfo |= POPT_ARG_STRING; j--; } else if (j != i) item->argv[j] = item->argv[i]; } if (j != i) { item->argv[j] = NULL; item->argc = j; } /*@=modobserver@*/ /*@=boundswrite@*/ /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */ if (!strcmp(entryType, "alias")) (void) poptAddItem(con, item, 0); else if (!strcmp(entryType, "exec")) (void) poptAddItem(con, item, 1); /*@=nullstate@*/ } /*@=compmempass@*/ int poptReadConfigFile(poptContext con, const char * fn) { const char * file, * chptr, * end; char * buf; /*@dependent@*/ char * dst; int fd, rc; off_t fileLength; fd = open(fn, O_RDONLY); if (fd < 0) return (errno == ENOENT ? 0 : POPT_ERROR_ERRNO); fileLength = lseek(fd, 0, SEEK_END); if (fileLength == -1 || lseek(fd, 0, 0) == -1) { rc = errno; (void) close(fd); /*@-mods@*/ errno = rc; /*@=mods@*/ return POPT_ERROR_ERRNO; } file = alloca(fileLength + 1); if (read(fd, (char *)file, fileLength) != fileLength) { rc = errno; (void) close(fd); /*@-mods@*/ errno = rc; /*@=mods@*/ return POPT_ERROR_ERRNO; } if (close(fd) == -1) return POPT_ERROR_ERRNO; /*@-boundswrite@*/ dst = buf = alloca(fileLength + 1); chptr = file; end = (file + fileLength); /*@-infloops@*/ /* LCL: can't detect chptr++ */ while (chptr < end) { switch (*chptr) { case '\n': *dst = '\0'; dst = buf; while (*dst && isspace((uint8_t)*dst)) dst++; if (*dst && *dst != '#') configLine(con, dst); chptr++; /*@switchbreak@*/ break; case '\\': *dst++ = *chptr++; if (chptr < end) { if (*chptr == '\n') dst--, chptr++; /* \ at the end of a line does not insert a \n */ else *dst++ = *chptr++; } /*@switchbreak@*/ break; default: *dst++ = *chptr++; /*@switchbreak@*/ break; } } /*@=infloops@*/ /*@=boundswrite@*/ return 0; } int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) { char * fn, * home; int rc; /*@-type@*/ if (!con->appName) return 0; /*@=type@*/ rc = poptReadConfigFile(con, "/etc/popt"); if (rc) return rc; #if defined(HAVE_GETUID) && defined(HAVE_GETEUID) if (getuid() != geteuid()) return 0; #endif if ((home = getenv("HOME"))) { fn = alloca(strlen(home) + 20); strcpy(fn, home); strcat(fn, "/.popt"); rc = poptReadConfigFile(con, fn); if (rc) return rc; } return 0; } distcc-3.4/popt/popthelp.c000066400000000000000000000464451404653710500156340ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /*@-type@*/ /** \ingroup popt * \file popt/popthelp.c */ /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #include #include "system.h" #include "poptint.h" /** * Display arguments. * @param con context * @param foo (unused) * @param key option(s) * @param arg (unused) * @param data (unused) */ static void displayArgs(poptContext con, /*@unused@*/ enum poptCallbackReason foo, struct poptOption * key, /*@unused@*/ const char * arg, /*@unused@*/ void * data) /*@globals fileSystem@*/ /*@modifies fileSystem@*/ { if (key->shortName == '?') poptPrintHelp(con, stdout, 0); else poptPrintUsage(con, stdout, 0); exit(0); } #ifdef NOTYET /*@unchecked@*/ static int show_option_defaults = 0; #endif /** * Empty table marker to enable displaying popt alias/exec options. */ /*@observer@*/ /*@unchecked@*/ struct poptOption poptAliasOptions[] = { POPT_TABLEEND }; /** * Auto help table options. */ /*@-castfcnptr@*/ /*@observer@*/ /*@unchecked@*/ struct poptOption poptHelpOptions[] = { { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL }, { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL }, { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL }, #ifdef NOTYET { "defaults", '\0', POPT_ARG_NONE, &show_option_defaults, 0, N_("Display option defaults in message"), NULL }, #endif POPT_TABLEEND } ; /*@=castfcnptr@*/ /** * @param table option(s) */ /*@observer@*/ /*@null@*/ static const char * getTableTranslationDomain(/*@null@*/ const struct poptOption *table) /*@*/ { const struct poptOption *opt; if (table != NULL) for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) { if (opt->argInfo == POPT_ARG_INTL_DOMAIN) return opt->arg; } return NULL; } /** * @param opt option(s) * @param translation_domain translation domain */ /*@observer@*/ /*@null@*/ static const char * getArgDescrip(const struct poptOption * opt, /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */ /*@null@*/ const char * translation_domain) /*@=paramuse@*/ /*@*/ { if (!(opt->argInfo & POPT_ARG_MASK)) return NULL; if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2)) if (opt->argDescrip) return POPT_(opt->argDescrip); if (opt->argDescrip) return D_(translation_domain, opt->argDescrip); switch (opt->argInfo & POPT_ARG_MASK) { case POPT_ARG_NONE: return POPT_("NONE"); #ifdef DYING case POPT_ARG_VAL: return POPT_("VAL"); #else case POPT_ARG_VAL: return NULL; #endif case POPT_ARG_INT: return POPT_("INT"); case POPT_ARG_LONG: return POPT_("LONG"); case POPT_ARG_STRING: return POPT_("STRING"); case POPT_ARG_FLOAT: return POPT_("FLOAT"); case POPT_ARG_DOUBLE: return POPT_("DOUBLE"); default: return POPT_("ARG"); } } /** * Display default value for an option. * @param lineLength * @param opt option(s) * @param translation_domain translation domain * @return */ static /*@only@*/ /*@null@*/ char * singleOptionDefaultValue(int lineLength, const struct poptOption * opt, /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */ /*@null@*/ const char * translation_domain) /*@=paramuse@*/ /*@*/ { const char * defstr = D_(translation_domain, "default"); char * le = malloc(4*lineLength + 1); char * l = le; if (le == NULL) return NULL; /* XXX can't happen */ /*@-boundswrite@*/ *le = '\0'; *le++ = '('; strcpy(le, defstr); le += strlen(le); *le++ = ':'; *le++ = ' '; if (opt->arg) /* XXX programmer error */ switch (opt->argInfo & POPT_ARG_MASK) { case POPT_ARG_VAL: case POPT_ARG_INT: { long aLong = *((int *)opt->arg); le += sprintf(le, "%ld", aLong); } break; case POPT_ARG_LONG: { long aLong = *((long *)opt->arg); le += sprintf(le, "%ld", aLong); } break; case POPT_ARG_FLOAT: { double aDouble = *((float *)opt->arg); le += sprintf(le, "%g", aDouble); } break; case POPT_ARG_DOUBLE: { double aDouble = *((double *)opt->arg); le += sprintf(le, "%g", aDouble); } break; case POPT_ARG_STRING: { const char * s = *(const char **)opt->arg; if (s == NULL) { strcpy(le, "null"); le += strlen(le); } else { size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")"); *le++ = '"'; strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le); if (slen < strlen(s)) { strcpy(le, "..."); le += strlen(le); } *le++ = '"'; } } break; case POPT_ARG_NONE: default: l = _free(l); return NULL; /*@notreached@*/ break; } *le++ = ')'; *le = '\0'; /*@=boundswrite@*/ return l; } /** * Display help text for an option. * @param fp output file handle * @param maxLeftCol * @param opt option(s) * @param translation_domain translation domain */ static void singleOptionHelp(FILE * fp, int maxLeftCol, const struct poptOption * opt, /*@null@*/ const char * translation_domain) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { int indentLength = maxLeftCol + 5; int lineLength = 79 - indentLength; const char * help = D_(translation_domain, opt->descrip); const char * argDescrip = getArgDescrip(opt, translation_domain); int helpLength; char * defs = NULL; char * left; int nb = maxLeftCol + 1; /* Make sure there's more than enough room in target buffer. */ if (opt->longName) nb += strlen(opt->longName); if (argDescrip) nb += strlen(argDescrip); /*@-boundswrite@*/ left = malloc(nb); if (left == NULL) return; /* XXX can't happen */ left[0] = '\0'; left[maxLeftCol] = '\0'; if (opt->longName && opt->shortName) sprintf(left, "-%c, %s%s", opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), opt->longName); else if (opt->shortName != '\0') sprintf(left, "-%c", opt->shortName); else if (opt->longName) sprintf(left, "%s%s", ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), opt->longName); if (!*left) goto out; if (argDescrip) { char * le = left + strlen(left); if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) *le++ = '['; /* Choose type of output */ /*@-branchstate@*/ if (opt->argInfo & POPT_ARGFLAG_SHOW_DEFAULT) { defs = singleOptionDefaultValue(lineLength, opt, translation_domain); if (defs) { char * t = malloc((help ? strlen(help) : 0) + strlen(defs) + sizeof(" ")); if (t) { char * te = t; *te = '\0'; if (help) { strcpy(te, help); te += strlen(te); } *te++ = ' '; strcpy(te, defs); defs = _free(defs); } defs = t; } } /*@=branchstate@*/ if (opt->argDescrip == NULL) { switch (opt->argInfo & POPT_ARG_MASK) { case POPT_ARG_NONE: break; case POPT_ARG_VAL: #ifdef NOTNOW /* XXX pug ugly nerdy output */ { long aLong = opt->val; int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS); int negate = (opt->argInfo & POPT_ARGFLAG_NOT); /* Don't bother displaying typical values */ if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L)) break; *le++ = '['; switch (ops) { case POPT_ARGFLAG_OR: *le++ = '|'; /*@innerbreak@*/ break; case POPT_ARGFLAG_AND: *le++ = '&'; /*@innerbreak@*/ break; case POPT_ARGFLAG_XOR: *le++ = '^'; /*@innerbreak@*/ break; default: /*@innerbreak@*/ break; } *le++ = '='; if (negate) *le++ = '~'; /*@-formatconst@*/ le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong); /*@=formatconst@*/ *le++ = ']'; } #endif break; case POPT_ARG_INT: case POPT_ARG_LONG: case POPT_ARG_FLOAT: case POPT_ARG_DOUBLE: case POPT_ARG_STRING: *le++ = '='; strcpy(le, argDescrip); le += strlen(le); break; default: break; } } else { *le++ = '='; strcpy(le, argDescrip); le += strlen(le); } if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) *le++ = ']'; *le = '\0'; } /*@=boundswrite@*/ if (help) fprintf(fp," %-*s ", maxLeftCol, left); else { fprintf(fp," %s\n", left); goto out; } left = _free(left); if (defs) { help = defs; defs = NULL; } helpLength = strlen(help); /*@-boundsread@*/ while (helpLength > lineLength) { const char * ch; char format[30]; ch = help + lineLength - 1; while (ch > help && !isspace((uint8_t)*ch)) ch--; if (ch == help) break; /* give up */ while (ch > (help + 1) && isspace((uint8_t)*ch)) ch--; ch++; sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength); /*@-formatconst@*/ fprintf(fp, format, help, " "); /*@=formatconst@*/ help = ch; while (isspace((uint8_t)*help) && *help) help++; helpLength = strlen(help); } /*@=boundsread@*/ if (helpLength) fprintf(fp, "%s\n", help); out: /*@-dependenttrans@*/ defs = _free(defs); /*@=dependenttrans@*/ left = _free(left); } /** * @param opt option(s) * @param translation_domain translation domain */ static int maxArgWidth(const struct poptOption * opt, /*@null@*/ const char * translation_domain) /*@*/ { int max = 0; int len = 0; const char * s; if (opt != NULL) while (opt->longName || opt->shortName || opt->arg) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { if (opt->arg) /* XXX program error */ len = maxArgWidth(opt->arg, translation_domain); if (len > max) max = len; } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { len = sizeof(" ")-1; if (opt->shortName != '\0') len += sizeof("-X")-1; if (opt->shortName != '\0' && opt->longName) len += sizeof(", ")-1; if (opt->longName) { len += ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? sizeof("-")-1 : sizeof("--")-1); len += strlen(opt->longName); } s = getArgDescrip(opt, translation_domain); if (s) len += sizeof("=")-1 + strlen(s); if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1; if (len > max) max = len; } opt++; } return max; } /** * Display popt alias and exec help. * @param fp output file handle * @param items alias/exec array * @param nitems no. of alias/exec entries * @param left * @param translation_domain translation domain */ static void itemHelp(FILE * fp, /*@null@*/ poptItem items, int nitems, int left, /*@null@*/ const char * translation_domain) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { poptItem item; int i; if (items != NULL) for (i = 0, item = items; i < nitems; i++, item++) { const struct poptOption * opt; opt = &item->option; if ((opt->longName || opt->shortName) && !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) singleOptionHelp(fp, left, opt, translation_domain); } } /** * Display help text for a table of options. * @param con context * @param fp output file handle * @param table option(s) * @param left * @param translation_domain translation domain */ static void singleTableHelp(poptContext con, FILE * fp, /*@null@*/ const struct poptOption * table, int left, /*@null@*/ const char * translation_domain) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { const struct poptOption * opt; const char *sub_transdom; if (table == poptAliasOptions) { itemHelp(fp, con->aliases, con->numAliases, left, NULL); itemHelp(fp, con->execs, con->numExecs, left, NULL); return; } if (table != NULL) for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) { if ((opt->longName || opt->shortName) && !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) singleOptionHelp(fp, left, opt, translation_domain); } if (table != NULL) for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) { if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_INCLUDE_TABLE) continue; sub_transdom = getTableTranslationDomain(opt->arg); if (sub_transdom == NULL) sub_transdom = translation_domain; if (opt->descrip) fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip)); singleTableHelp(con, fp, opt->arg, left, sub_transdom); } } /** * @param con context * @param fp output file handle */ static int showHelpIntro(poptContext con, FILE * fp) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { int len = 6; const char * fn; fprintf(fp, POPT_("Usage:")); if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) { /*@-boundsread@*/ /*@-nullderef@*/ /* LCL: wazzup? */ fn = con->optionStack->argv[0]; /*@=nullderef@*/ /*@=boundsread@*/ if (fn == NULL) return len; if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1; fprintf(fp, " %s", fn); len += strlen(fn) + 1; } return len; } void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags) { int leftColWidth; (void) showHelpIntro(con, fp); if (con->otherHelp) fprintf(fp, " %s\n", con->otherHelp); else fprintf(fp, " %s\n", POPT_("[OPTION...]")); leftColWidth = maxArgWidth(con->options, NULL); singleTableHelp(con, fp, con->options, leftColWidth, NULL); } /** * @param fp output file handle * @param cursor * @param opt option(s) * @param translation_domain translation domain */ static int singleOptionUsage(FILE * fp, int cursor, const struct poptOption * opt, /*@null@*/ const char *translation_domain) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { int len = 4; char shortStr[2] = { '\0', '\0' }; const char * item = shortStr; const char * argDescrip = getArgDescrip(opt, translation_domain); if (opt->shortName != '\0' && opt->longName != NULL) { len += 2; if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++; len += strlen(opt->longName); } else if (opt->shortName != '\0') { len++; shortStr[0] = opt->shortName; shortStr[1] = '\0'; } else if (opt->longName) { len += strlen(opt->longName); if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++; item = opt->longName; } if (len == 4) return cursor; if (argDescrip) len += strlen(argDescrip) + 1; if ((cursor + len) > 79) { fprintf(fp, "\n "); cursor = 7; } if (opt->longName && opt->shortName) { fprintf(fp, " [-%c|-%s%s%s%s]", opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "" : "-"), opt->longName, (argDescrip ? " " : ""), (argDescrip ? argDescrip : "")); } else { fprintf(fp, " [-%s%s%s%s]", ((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"), item, (argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""), (argDescrip ? argDescrip : "")); } return cursor + len + 1; } /** * Display popt alias and exec usage. * @param fp output file handle * @param cursor * @param item alias/exec array * @param nitems no. of ara/exec entries * @param translation_domain translation domain */ static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems, /*@null@*/ const char * translation_domain) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { int i; /*@-branchstate@*/ /* FIX: W2DO? */ if (item != NULL) for (i = 0; i < nitems; i++, item++) { const struct poptOption * opt; opt = &item->option; if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) { translation_domain = (const char *)opt->arg; } else if ((opt->longName || opt->shortName) && !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { cursor = singleOptionUsage(fp, cursor, opt, translation_domain); } } /*@=branchstate@*/ return cursor; } /** * Keep track of option tables already processed. */ typedef struct poptDone_s { int nopts; int maxopts; const void ** opts; } * poptDone; /** * Display usage text for a table of options. * @param con context * @param fp output file handle * @param cursor * @param opt option(s) * @param translation_domain translation domain * @param done tables already processed * @return */ static int singleTableUsage(poptContext con, FILE * fp, int cursor, /*@null@*/ const struct poptOption * opt, /*@null@*/ const char * translation_domain, /*@null@*/ poptDone done) /*@globals fileSystem @*/ /*@modifies *fp, done, fileSystem @*/ { /*@-branchstate@*/ /* FIX: W2DO? */ if (opt != NULL) for (; (opt->longName || opt->shortName || opt->arg) ; opt++) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) { translation_domain = (const char *)opt->arg; } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { if (done) { int i = 0; for (i = 0; i < done->nopts; i++) { /*@-boundsread@*/ const void * that = done->opts[i]; /*@=boundsread@*/ if (that == NULL || that != opt->arg) /*@innercontinue@*/ continue; /*@innerbreak@*/ break; } /* Skip if this table has already been processed. */ if (opt->arg == NULL || i < done->nopts) continue; /*@-boundswrite@*/ if (done->nopts < done->maxopts) done->opts[done->nopts++] = (const void *) opt->arg; /*@=boundswrite@*/ } cursor = singleTableUsage(con, fp, cursor, opt->arg, translation_domain, done); } else if ((opt->longName || opt->shortName) && !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { cursor = singleOptionUsage(fp, cursor, opt, translation_domain); } } /*@=branchstate@*/ return cursor; } /** * Return concatenated short options for display. * @todo Sub-tables should be recursed. * @param opt option(s) * @param fp output file handle * @retval str concatenation of short options * @return length of display string */ static int showShortOptions(const struct poptOption * opt, FILE * fp, /*@null@*/ char * str) /*@globals fileSystem @*/ /*@modifies *str, *fp, fileSystem @*/ { size_t size = 300; /* larger then the ascii set */ char * s = alloca(size); s[0] = '\0'; /*@-branchstate@*/ /* FIX: W2DO? */ if (str == NULL) { memset(s, 0, size); str = s; } /*@=branchstate@*/ /*@-boundswrite@*/ if (opt != NULL) for (; (opt->longName || opt->shortName || opt->arg); opt++) { if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK)) str[strlen(str)] = opt->shortName; else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) if (opt->arg) /* XXX program error */ (void) showShortOptions(opt->arg, fp, str); } /*@=boundswrite@*/ if (s != str || *s != '\0') return 0; fprintf(fp, " [-%s]", s); return strlen(s) + 4; } void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags) { poptDone done = memset(alloca(sizeof(*done)), 0, sizeof(*done)); int cursor; done->nopts = 0; done->maxopts = 64; cursor = done->maxopts * sizeof(*done->opts); /*@-boundswrite@*/ done->opts = memset(alloca(cursor), 0, cursor); done->opts[done->nopts++] = (const void *) con->options; /*@=boundswrite@*/ cursor = showHelpIntro(con, fp); cursor += showShortOptions(con->options, fp, NULL); cursor = singleTableUsage(con, fp, cursor, con->options, NULL, done); cursor = itemUsage(fp, cursor, con->aliases, con->numAliases, NULL); cursor = itemUsage(fp, cursor, con->execs, con->numExecs, NULL); if (con->otherHelp) { cursor += strlen(con->otherHelp) + 1; if (cursor > 79) fprintf(fp, "\n "); fprintf(fp, " %s", con->otherHelp); } fprintf(fp, "\n"); } void poptSetOtherOptionHelp(poptContext con, const char * text) { con->otherHelp = _free(con->otherHelp); con->otherHelp = xstrdup(text); } /*@=type@*/ distcc-3.4/popt/poptint.h000066400000000000000000000053271404653710500154750ustar00rootroot00000000000000/** \ingroup popt * \file popt/poptint.h */ /* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #ifndef H_POPTINT #define H_POPTINT /** * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL. * @param p memory to free * @retval NULL always */ /*@unused@*/ static inline /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * p) /*@modifies p @*/ { if (p != NULL) free((void *)p); return NULL; } /* Bit mask macros. */ /*@-exporttype -redef @*/ typedef unsigned int __pbm_bits; /*@=exporttype =redef @*/ #define __PBM_NBITS (8 * sizeof (__pbm_bits)) #define __PBM_IX(d) ((d) / __PBM_NBITS) #define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS)) /*@-exporttype -redef @*/ typedef struct { __pbm_bits bits[1]; } pbm_set; /*@=exporttype =redef @*/ #define __PBM_BITS(set) ((set)->bits) #define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits)) #define PBM_FREE(s) _free(s); #define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d)) #define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d)) #define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0) struct optionStackEntry { int argc; /*@only@*/ /*@null@*/ const char ** argv; /*@only@*/ /*@null@*/ pbm_set * argb; int next; /*@only@*/ /*@null@*/ const char * nextArg; /*@observer@*/ /*@null@*/ const char * nextCharArg; /*@dependent@*/ /*@null@*/ poptItem currAlias; int stuffed; }; struct poptContext_s { struct optionStackEntry optionStack[POPT_OPTION_DEPTH]; /*@dependent@*/ struct optionStackEntry * os; /*@owned@*/ /*@null@*/ const char ** leftovers; int numLeftovers; int nextLeftover; /*@keep@*/ const struct poptOption * options; int restLeftover; /*@only@*/ /*@null@*/ const char * appName; /*@only@*/ /*@null@*/ poptItem aliases; int numAliases; int flags; /*@owned@*/ /*@null@*/ poptItem execs; int numExecs; /*@only@*/ /*@null@*/ const char ** finalArgv; int finalArgvCount; int finalArgvAlloced; /*@dependent@*/ /*@null@*/ poptItem doExec; /*@only@*/ const char * execPath; int execAbsolute; /*@only@*/ const char * otherHelp; /*@null@*/ pbm_set * arg_strip; }; #ifdef HAVE_LIBINTL_H #include #endif #if defined(HAVE_GETTEXT) && !defined(__LCLINT__) #define _(foo) gettext(foo) #else #define _(foo) foo #endif #if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__) #define D_(dom, str) dgettext(dom, str) #define POPT_(foo) D_("popt", foo) #else #define D_(dom, str) str #define POPT_(foo) foo #endif #define N_(foo) foo #endif distcc-3.4/popt/poptparse.c000066400000000000000000000122501404653710500160010ustar00rootroot00000000000000/** \ingroup popt * \file popt/poptparse.c */ /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #include #include "system.h" #define POPT_ARGV_ARRAY_GROW_DELTA 5 /*@-boundswrite@*/ int poptDupArgv(int argc, const char **argv, int * argcPtr, const char *** argvPtr) { size_t nb = (argc + 1) * sizeof(*argv); const char ** argv2; char * dst; int i; if (argc <= 0 || argv == NULL) /* XXX can't happen */ return POPT_ERROR_NOARG; for (i = 0; i < argc; i++) { if (argv[i] == NULL) return POPT_ERROR_NOARG; nb += strlen(argv[i]) + 1; } dst = malloc(nb); if (dst == NULL) /* XXX can't happen */ return POPT_ERROR_MALLOC; argv2 = (void *) dst; dst += (argc + 1) * sizeof(*argv); /*@-branchstate@*/ for (i = 0; i < argc; i++) { argv2[i] = dst; dst += strlen(strcpy(dst, argv[i])) + 1; } /*@=branchstate@*/ argv2[argc] = NULL; if (argvPtr) { *argvPtr = argv2; } else { free(argv2); argv2 = NULL; } if (argcPtr) *argcPtr = argc; return 0; } /*@=boundswrite@*/ /*@-bounds@*/ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) { const char * src; char quote = '\0'; int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; const char ** argv = malloc(sizeof(*argv) * argvAlloced); int argc = 0; int buflen = strlen(s) + 1; char * buf = memset(alloca(buflen), 0, buflen); int rc = POPT_ERROR_MALLOC; if (argv == NULL) return rc; argv[argc] = buf; for (src = s; *src != '\0'; src++) { if (quote == *src) { quote = '\0'; } else if (quote != '\0') { if (*src == '\\') { src++; if (!*src) { rc = POPT_ERROR_BADQUOTE; goto exit; } if (*src != quote) *buf++ = '\\'; } *buf++ = *src; } else if (isspace((uint8_t)*src)) { if (*argv[argc] != '\0') { buf++, argc++; if (argc == argvAlloced) { argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; argv = realloc(argv, sizeof(*argv) * argvAlloced); if (argv == NULL) goto exit; } argv[argc] = buf; } } else switch (*src) { case '"': case '\'': quote = *src; /*@switchbreak@*/ break; case '\\': src++; if (!*src) { rc = POPT_ERROR_BADQUOTE; goto exit; } /*@fallthrough@*/ default: *buf++ = *src; /*@switchbreak@*/ break; } } if (strlen(argv[argc])) { argc++, buf++; } rc = poptDupArgv(argc, argv, argcPtr, argvPtr); exit: if (argv) free(argv); return rc; } /*@=bounds@*/ /* still in the dev stage. * return values, perhaps 1== file error * 2== line to long * 3== umm.... more? */ int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ int flags) { char line[999]; char * argstr; char * p; char * q; char * x; int t; int argvlen = 0; size_t maxlinelen = sizeof(line); size_t linelen; int maxargvlen = 480; int linenum = 0; *argstrp = NULL; /* | this_is = our_line * p q x */ if (fp == NULL) return POPT_ERROR_NULLARG; argstr = calloc(maxargvlen, sizeof(*argstr)); if (argstr == NULL) return POPT_ERROR_MALLOC; while (fgets(line, (int)maxlinelen, fp) != NULL) { linenum++; p = line; /* loop until first non-space char or EOL */ while( *p != '\0' && isspace((uint8_t)*p) ) p++; linelen = strlen(p); if (linelen >= maxlinelen-1) return POPT_ERROR_OVERFLOW; /* XXX line too long */ if (*p == '\0' || *p == '\n') continue; /* line is empty */ if (*p == '#') continue; /* comment line */ q = p; while (*q != '\0' && (!isspace((uint8_t)*q)) && *q != '=') q++; if (isspace((uint8_t)*q)) { /* a space after the name, find next non space */ *q++='\0'; while( *q != '\0' && isspace((int)*q) ) q++; } if (*q == '\0') { /* single command line option (ie, no name=val, just name) */ q[-1] = '\0'; /* kill off newline from fgets() call */ argvlen += (t = q - p) + (sizeof(" --")-1); if (argvlen >= maxargvlen) { maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2; argstr = realloc(argstr, maxargvlen); if (argstr == NULL) return POPT_ERROR_MALLOC; } strcat(argstr, " --"); strcat(argstr, p); continue; } if (*q != '=') continue; /* XXX for now, silently ignore bogus line */ /* *q is an equal sign. */ *q++ = '\0'; /* find next non-space letter of value */ while (*q != '\0' && isspace((uint8_t)*q)) q++; if (*q == '\0') continue; /* XXX silently ignore missing value */ /* now, loop and strip all ending whitespace */ x = p + linelen; while (isspace((uint8_t)*--x)) *x = 0; /* null out last char if space (including fgets() NL) */ /* rest of line accept */ t = x - p; argvlen += t + (sizeof("' --='")-1); if (argvlen >= maxargvlen) { maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2; argstr = realloc(argstr, maxargvlen); if (argstr == NULL) return POPT_ERROR_MALLOC; } strcat(argstr, " --"); strcat(argstr, p); strcat(argstr, "=\""); strcat(argstr, q); strcat(argstr, "\""); } *argstrp = argstr; return 0; } distcc-3.4/popt/system.h000066400000000000000000000031671404653710500153240ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H #include #endif #if defined (__GLIBC__) && defined(__LCLINT__) /*@-declundef@*/ /*@unchecked@*/ extern __const __int32_t *__ctype_tolower; /*@unchecked@*/ extern __const __int32_t *__ctype_toupper; /*@=declundef@*/ #endif #include #include #include #include #if HAVE_MCHECK_H #include #endif #include #include #include #if HAVE_UNISTD_H #include #endif #ifdef __NeXT /* access macros are not declared in non posix mode in unistd.h - don't try to use posix on NeXTstep 3.3 ! */ #include #endif #if defined(__LCLINT__) /*@-declundef -incondefs -redecl@*/ /* LCL: missing annotation */ /*@only@*/ void * alloca (size_t __size) /*@ensures MaxSet(result) == (__size - 1) @*/ /*@*/; /*@=declundef =incondefs =redecl@*/ #endif /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #elif defined(__GNUC__) && defined(__STRICT_ANSI__) #define alloca __builtin_alloca #endif /*@-redecl -redef@*/ /*@mayexit@*/ /*@only@*/ char * xstrdup (const char *str) /*@*/; /*@=redecl =redef@*/ #if HAVE_MCHECK_H && defined(__GNUC__) #define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL) #define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str))) #else #define xstrdup(_str) strdup(_str) #endif /* HAVE_MCHECK_H && defined(__GNUC__) */ #include "popt.h" distcc-3.4/pump.in000077500000000000000000000464601404653710500141640ustar00rootroot00000000000000#!/bin/sh # # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # # Authors: Nils Klarlund, Fergus Henderson # # 'pump': a script for using distcc-pump with build commands. # This file is processed by configure, which substitutes in the right # value for @PYTHON@, @prefix@, etc. # NOTE: do we need to do the expansion of these variables by using sed # in Makefile.in rather than by having configure process this file? # The autoconf manual suggests that we do. Right now it doesn't seem # to be needed in practice, though. PYTHON=@PYTHON@ prefix=@prefix@ exec_prefix=@exec_prefix@ sysconfdir=@sysconfdir@ srcdir=@srcdir@ # This is where include_server.py lives. It's set to the empty string # before pump is installed into its final location. At install-time, # the 'make install' command will rewrite this line of pump to point # to the installed include_server.py. # NOTE: DO NOT CHANGE THE LINE BELOW WITHOUT CHANGING THE SED IN # Makefile.in:install-include-server. include_server='' CheckUsage() { if [ "$1" = "" -o "$1" = '-h' -o "$1" = '--help' ]; then cat <<'EOF' Usage: pump COMMAND [ARG...] or pump --startup pump --shutdown Description: Pump, also known as distcc-pump, accelerates remote compilation with distcc by also distributing preprocessing to the servers. The simplest usage is the form "pump COMMAND [ARG...]". This will start an include server for distcc-pump; set some environment variables; change PATH to use the distcc-pump "distcc" client; execute COMMAND with the specified ARG(s); and then shutdown the include server. The COMMAND is typically a parallel build command, such as "make -j80", that will do many concurrent invocations of distcc. An alternative way of invoking pump is to explicitly invoke "pump --startup" to start the include server and "pump --shutdown" to stop the include server. The "pump --startup" command will start up the include server, and will print out some environment variable settings. These environment variables are used to communicate between the distcc-pump "distcc" client and the include server, and to communicate between "pump --startup" and "pump --shutdown". The caller of "pump --startup" is responsible for setting those environment variables before invoking "distcc" or "pump --shutdown". For example: eval `pump --startup` make -j80 pump --shutdown Note that distcc-pump assumes that sources files will not be modified during the lifetime of the include server, so modifying source files during a build may cause inconsistent results. Environment variables (all optional): DISTCC_LOCATION Either the distcc 'bin' install directory (when the pump script in the installation executes) or the build directory (when the pump script is run during development). This location is normally inferred from the dirname of argv[0]. It is resolved with respect to links. If this location is the bin directory inside an installation, then Python executables and distcc itself will be retrieved from the parent directory of the location. If this location is the build directory, then Python sources are retrieved from the source directory. DISTCC_POTENTIAL_HOSTS The distcc servers that will be queried by lsdistcc in order to produce a value for DISTCC_HOSTS. This value may be unset or null. In such cases, use DISTCC_HOSTS. DISTCC_HOSTS This variable is passed through to distcc but only if DISTCC_POTENTIAL_HOSTS is not set. LSDISTCC_ARGS Extra arguments to lsdistcc. INCLUDE_SERVER_ARGS Extra arguments to the include server. PYTHONOPTIMIZE If set to "", then Python optimization is disabled. Example: pump make EOF exit 0 fi } # Get the directory of a command. The argument is $0 as received from # argv[0]. If $0 is of the form /path/symlink and symlink points to # another directory than /path, then `basename $0` does not return # the directory where the executable lives. We fix this here. GetScriptDir() { if [ -h "$0" ]; then dir=`dirname "$0"` link=`readlink "$0"` linkdir=`dirname "$link"` case $linkdir in /*) echo "$linkdir" ;; *) echo "$dir/$linkdir" ;; esac else dirname "$0" fi } # Constants used by this process. # The default value must be the same as that in src/compile.c. See # comment there. max_discrepancies_before_demotion=1 if [ -n "$DISTCC_MAX_DISCREPANCY" ] ; then if [ "$DISTCC_MAX_DISCREPANCY" -le 0 ] ; then echo "$0:" \ "Bad DISTCC_MAX_DISCREPANCY value: \"$DISTCC_MAX_DISCREPANCY\"." \ "Needs to be 1 or greater." \ 1>&2 exit 1 fi max_discrepancies_before_demotion="$DISTCC_MAX_DISCREPANCY" fi # Variables inherited from the environment of the caller. if [ -z "$DISTCC_LOCATION" ]; then # Set the default for location of 'pump' script'. DISTCC_LOCATION=`GetScriptDir "$0"` fi # Variables used by this process. program_name="$0" socket_dir='' # Temporary directory created by this process. tmp_pid_file='' # Temporary file created by this process. available_hosts_file='' # Temporary file for newline separated list of hosts. socket='' # Temporary socket file, inside $socket_dir. include_server_stdout='' # Temporary file, inside $socket_dir. include_server_stderr='' # Temporary file, inside $socket_dir. include_server_pid='' include_server_relative='' # Set by Initialize(). This path is relative to # the 'bin' directory of a distcc-pump installation. distcc_location='' # Set by Initialize(). The directory of the distcc binary. DISTCC='distcc' # the name of the distcc binary verbose=1 # Print progress messages to stdout? (1 means yes.) redirect_io=0 # Redirect include server's I/O streams? (1 means yes.) # Make temp file using distinguishing prefix $1. Use optional argument # $2="-d" to make a directory. The name of the created temp file or # directory is written to stdout. MakeTmpFile() { if mktemp $2 "${TMPDIR-/tmp}/$1.XXXXXX"; then : # mktemp prints the output we want; no need to do more else echo "$program_name: Could not make temp \"$1\"" 1>&2 exit 1 fi } Initialize() { # We know the value of $PYTHON when this function is executed. The value is # set when the 'pump' script is made from 'pump.in'. Use this value in the # formation of the relative path that takes us from the 'bin' directory of an # installation to the 'include_server' directory. include_server_relative="../$PYTHON_RELATIVE_LIB/include_server" distcc_location="$DISTCC_LOCATION" # Check that we're getting exactly the distcc client we want: the # one that is part of this build. if [ ! -x "$distcc_location/$DISTCC" ]; then echo "$0: error: can't find distcc (looked in $distcc_location)" 1>&2 exit 1 fi } PrintIncludeServerStatusMessage() { include_server_status=$1 if [ "$verbose" = 1 ]; then if [ "$include_server_status" = 0 ]; then echo '__________Started distcc-pump include server' else echo '__________Could not start distcc-pump include server' 1>&2 fi fi } Announce() { echo "__________Using distcc-pump from $DISTCC_LOCATION" } # Starts up the include server. Sets $socket, $socket_dir, and # $include_server_pid. If successful (with exit status 0), sets exported # variable $INCLUDE_SERVER_PORT to the socket file ($socket), to tell the distcc # clients where to find the include server. StartIncludeServer() { # If include_server already exists, that means we're a # installed pump (in /usr/local/bin somewhere or something), and # include_server points to the installed include_server.py. if [ -n "$include_server" ]; then pythonpath=`dirname "$include_server"` else # We assume this script is run from the build directory. We pick up .py # files from the include_server directory in the source tree, and we pick up # the .so file from the include_server/build/libXXX/include_server # directory. # # Calculate the location of the source directory. distcc_srcdir=`cd "$DISTCC_LOCATION"; cd "$srcdir"; pwd` # The source tree location must be passed. include_server="$distcc_srcdir/include_server/include_server.py" # Now locate the single directory containing the .so file from the build # directory. Possibly there may be more than one such file; first identify # them all. so_dir=`"$distcc_srcdir/find_c_extension.sh" "$DISTCC_LOCATION"` pythonpath="$so_dir" fi # Create a temporary directory $socket_dir. socket_dir=`MakeTmpFile "distcc-pump" -d` || exit 1 # The socket file on which the include server accepts connections. socket="$socket_dir/socket" # Files for the include server's stdout/stderr. # When a build tool invokes 'pump --startup', stdout/stderr may be # pipes, in which case the invocation may hang unless the include # server process closes them. So to avoid this, we need to redirect # the include server's output to temporary files. # We print these files during shutdown; better late than never! include_server_stdout="$socket_dir/stdout" include_server_stderr="$socket_dir/stderr" # File for the include server process id. tmp_pid_file=`MakeTmpFile "distcc-pump-pid"` || exit 1 # Start include server in optimized mode (no assertions) and with # debug level 1 for tracing warnings. # The include server will fork off # a background process to handle the requests; # the main process will exit only when the background # process is ready to accept connections. ( # Optionally redirect the I/O streams for the include server. case $redirect_io in 1) exec < /dev/null \ > $include_server_stdout \ 2> $include_server_stderr ;; *) rm -f $include_server_stdout $include_server_stderr ;; esac if [ -z "$PYTHONOPTIMIZE" ]; then PYTHONOPTIMIZE=1; fi # We use 'eval' so that INCLUDE_SERVER_ARGS can use shell quoting such # as in: # # INCLUDE_SERVER_ARGS='--stat_reset_triggers="*"' # # which will pass '*' to the include server (that is, the string consisting # of one asterisk) without filename expansion. eval \ "PYTHONOPTIMIZE='$PYTHONOPTIMIZE' " \ "PYTHONPATH='$pythonpath${PYTHONPATH:+:$PYTHONPATH}' " \ "'$PYTHON'" \ "'$include_server'" \ --port "'$socket'" \ --pid_file "'$tmp_pid_file'" \ -d1 \ $INCLUDE_SERVER_ARGS ) # solaris sh's built-in test does not support -S, so we need to use # the binary. if [ -x /bin/test ]; then TEST=/bin/test elif [ -x /usr/bin/test ]; then TEST=/usr/bin/test else TEST=test fi if $TEST ! -S "$socket"; then echo "__________Expected a socket at '$socket'" 1>&2 PrintIncludeServerStatusMessage 1 return 1 fi include_server_pid=`cat $tmp_pid_file` rm "$tmp_pid_file" # Make sure $include_server_pid looks like a pid if echo "$include_server_pid" | grep '^[0-9][0-9]*$' >/dev/null; then # We got a number. Tell the distcc clients where to find it. INCLUDE_SERVER_PORT="$socket" export INCLUDE_SERVER_PORT else # We got something that's not a number. This indicates the # socket is not working. include_server_pid='' PrintIncludeServerStatusMessage 1 return 1 fi } ReportDiscrepancies() { # The discrepancy_counter file is created when a pump-mode distcc invocation # failed remotely but succeeded locally. num_discrepancies=`(cat $socket_dir/discrepancy_counter 2>/dev/null | wc -c \ || echo 0)` if [ $num_discrepancies -eq 0 ]; then return 0 fi echo "__________Warning: $num_discrepancies" \ 'pump-mode compilation(s) failed on server,' \ 'but succeeded locally.' 1>&2 if [ $num_discrepancies -ge $max_discrepancies_before_demotion ]; then echo '__________Distcc-pump was demoted to plain mode.' 1>&2 fi echo 'See the Distcc Discrepancy Symptoms section in the' \ 'include_server(1) man page.' 1>&2 } ShutDown() { ReportDiscrepancies # Always -- at exit -- shut down include_server and remove $socket_dir if [ -n "$include_server_pid" ] && \ ps -p "$include_server_pid" > /dev/null; then echo '__________Shutting down distcc-pump include server' kill $include_server_pid # Wait until it's really dead. We need to do this because the # include server may produce output after receiving SIGTERM. # Note that while 'sleep 0.01' is relying on a feature of GNU sleep, # that's OK; on systems that don't support it, it's effectively the # same as 'sleep 0', i.e. we'll just busy-wait rather than sleeping. while kill -0 $include_server_pid; do sleep 0.01; done >/dev/null 2>&1 fi if [ -f "$include_server_stdout" ]; then cat "$include_server_stdout" fi if [ -f "$include_server_stderr" ]; then cat "$include_server_stderr" >&2 fi if [ -n "$socket_dir" ]; then rm -rf "$socket_dir" fi if [ -n "$tmp_pid_file" ]; then rm -f "$tmp_pid_file" fi if [ -n "$available_hosts_file" ]; then rm -f "$available_hosts_file" fi } # Invokes lsdistcc to find the available servers. This list is # \n-separated and written to the filepath provided as $1. AvailableHosts() { available_hosts="$1" lsdistcc="$DISTCC_LOCATION/lsdistcc" if [ ! -x "$lsdistcc" ]; then echo "$0: error: can't find lsdistcc (looked in $DISTCC_LOCATION)" 1>&2 exit 1 fi # Call lsdistcc and let it wait no more than 150ms unless overridden in # LSDISTCC_ARGS. "$lsdistcc" -c150 $LSDISTCC_ARGS $DISTCC_POTENTIAL_HOSTS > "$available_hosts" } # Exports DISTCC_HOSTS as a function of the single argument and the global # variable $available_hosts_file. ExportDISTCC_HOSTS() { include_server_status="$1" opts='' if [ "$include_server_status" = 0 ]; then # The include server is up. # Make 'cpp' mode (with lzo) the default. opts=",cpp,lzo" else # The include server is not ready. # Make 'lzo' mode the default. if [ "$?" = 1 ]; then echo "__________Warning: distcc-pump include server failed;" \ "running unpumped" 1>&2 fi opts=",lzo" fi # When calculating final value of DISTCC_HOSTS, we get rid of # newlines (thanks to "`sed ...`"). export DISTCC_HOSTS="--randomize `sed s/'$'/$opts/ $available_hosts_file`" if [ "$verbose" = 1 ]; then echo "__________Found" \ "`wc -l < $available_hosts_file` available distcc servers" fi } StartIncludeServerAndDetermineHosts() { include_server_status=1 # ie, not running (yet) if [ -n "$DISTCC_POTENTIAL_HOSTS" ]; then # Probe the distcc servers. It may take up to a second. But # starting the include server takes about 150ms. Make these # activities happen in parallel. # First, the lsdistcc command goes in the background. available_hosts_file=`MakeTmpFile "distcc-pump-hosts"` || exit 1 AvailableHosts "$available_hosts_file" & # Second, the include server goes in the foreground so variables can be set. StartIncludeServer && include_server_status=0 # Await for AvailableHosts to finish. wait ExportDISTCC_HOSTS "$include_server_status" rm -f "$available_hosts_file" else if [ -z "$DISTCC_HOSTS" ] && [ -z "$DISTCC_DIR" -o ! -f "$DISTCC_DIR/hosts" ] && [ -z "$HOME" -o ! -f "$HOME/.distcc/hosts" ] && [ ! -f "$sysconfdir/distcc/hosts" ] then echo "$program_name:" \ "expected environment variables \"DISTCC_HOSTS\" or" \ "\"DISTCC_POTENTIAL_HOSTS\" to be set, or to find a" \ "distcc hosts file in \"\$DISTCC_DIR/hosts\"," \ "\"\$HOME/.distcc/hosts\", or \"$sysconfdir/distcc/hosts\"." \ 1>&2 exit 1 else hosts=`$distcc_location/distcc --show-hosts` num_hosts=`echo "$hosts" | wc -l` num_pump_hosts=`echo "$hosts" | grep ',cpp' | wc -l` if [ $num_hosts -eq 0 ]; then echo "$program_name: error: distcc hosts list is empty!" 1>&2 exit 1 elif [ $num_pump_hosts -eq 0 ]; then echo "$program_name: error: pump mode requested, but distcc" \ "hosts list does not contain any hosts with ',cpp' option" 1>&2 exit 1 else if [ "$verbose" = 1 ]; then server_word="servers" if [ $num_hosts = 1 ]; then server_word="server" fi if [ $num_hosts -eq $num_pump_hosts ]; then echo "__________Using $num_hosts distcc $server_word in pump mode" else echo "__________Using $num_hosts distcc $server_word, of which" \ "only $num_pump_hosts support(s) pump mode" fi fi fi fi StartIncludeServer && include_server_status=0 fi return "$include_server_status" } # Prints out environment variable settings, for the --startup option. DumpEnvironmentVariables() { # Variables used by "pump --shutdown" echo export INCLUDE_SERVER_PID=\'$include_server_pid\' echo export INCLUDE_SERVER_DIR=\'$socket_dir\' # Variables used by the distcc client echo export INCLUDE_SERVER_PORT=\'$INCLUDE_SERVER_PORT\' if [ -n "$DISTCC_HOSTS" ]; then echo export DISTCC_HOSTS=\'$DISTCC_HOSTS\' fi echo export PATH=\'$distcc_location:$PATH\' } Main() { CheckUsage "$@" Initialize case "$*" in --startup) # Don't put ordinary progress messages on stdout, # because they interfere with the environment variable # settings that we print out. verbose=0 # Redirect the include server's stdin/stdout/stderr redirect_io=1 trap 'ShutDown' EXIT # In case we get interrupted. StartIncludeServerAndDetermineHosts include_server_status=$? trap '' EXIT if [ "$include_server_status" = 0 ]; then DumpEnvironmentVariables exit 0 else exit 1 fi ;; --shutdown) include_server_pid="$INCLUDE_SERVER_PID" socket_dir="$INCLUDE_SERVER_DIR" include_server_stdout="$socket_dir/stdout" include_server_stderr="$socket_dir/stderr" ShutDown exit 0 ;; *) trap 'ShutDown' EXIT Announce StartIncludeServerAndDetermineHosts || exit 1 # Now execute the command that is the argument of 'pump'. PATH="$distcc_location:$PATH" \ "$@" # When we exit, the ShutDown function will be called. ;; esac } Main "$@" distcc-3.4/src/000077500000000000000000000000001404653710500134255ustar00rootroot00000000000000distcc-3.4/src/access.c000066400000000000000000000242151404653710500150360ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * They that forsake the law praise the wicked: but such * as keep the law contend with them. * -- Proverbs 28:4 */ #include #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "trace.h" #include "access.h" #include "exitcode.h" /** * @file * * IP-based access-control system */ static const uint32_t allones = 0xffffffffUL; #ifdef ENABLE_RFC2553 static const uint8_t allones8 = 0xffU; #endif /** * Split a "HOST/BITS" mask specification into HOST and BITS. * * @returns 0 on success or -1 if the program ran out of heap space **/ static int split_mask(const char *spec, char **host, const char **bits) { int value_len = strcspn(spec, "/"); if (host != NULL) { char *host_str; host_str = malloc(value_len + 1); if (host_str == NULL) { rs_log_error("could not allocate memory (%d bytes)", value_len + 1); return -1; } strncpy(host_str, spec, value_len); host_str[value_len] = '\0'; *host = host_str; } if (bits != NULL) { if (spec[value_len] && spec[value_len + 1]) *bits = spec + value_len + 1; else *bits = NULL; } return 0; } /** * Set a dcc_address_t to a full mask. **/ static void set_allones(dcc_address_t *addr) { #ifndef ENABLE_RFC2553 addr->s_addr = allones; #else memset(&addr->addr, allones8, sizeof(struct in6_addr)); #endif } /** * Set a 32-bit address, @p addr, to a mask of @p mask_size bits. **/ static inline void set_mask_inet(struct in_addr *addr, int mask_bits) { addr->s_addr = htonl(~(allones >> mask_bits)); } #ifdef ENABLE_RFC2553 /** * Set a v6 address, @p addr, to a mask of @p mask_size bits. **/ static void set_mask_inet6(struct in6_addr *addr, int mask_bits) { uint8_t *ip6_addr = addr->s6_addr; int allones_count = mask_bits / 8; int i; for (i = 0; i < allones_count; i++) ip6_addr[i] = allones8; ip6_addr[i] = ~(allones8 >> (mask_bits % 8)); i++; for (; i < 16; i++) ip6_addr[i] = 0; } #endif /* ENABLE_RFC2553 */ /** * Set a dcc_address_t to a mask of @p mask_bits bits. The family field of * the address should be set appropriately if RFC2553 is enabled. **/ static void set_mask(dcc_address_t *mask, int mask_bits) { #ifndef ENABLE_RFC2553 set_mask_inet(mask, mask_bits); #else if (mask->family == AF_INET) set_mask_inet(&mask->addr.inet, mask_bits); else set_mask_inet6(&mask->addr.inet6, mask_bits); #endif } /** * Interpret a "HOST/BITS" mask specification. Return @p value and @p mask. **/ int dcc_parse_mask(const char *spec, dcc_address_t *value, dcc_address_t *mask) { char *value_str; int ret; const char *mask_str; #ifndef ENABLE_RFC2553 struct in_addr ia; #else struct addrinfo hints; struct addrinfo *res; #endif ret = split_mask(spec, &value_str, &mask_str); if (ret == -1) return EXIT_OUT_OF_MEMORY; /* extract and parse value part */ #ifndef ENABLE_RFC2553 ret = inet_aton(value_str, &ia); if (ret == 0) { rs_log_error("can't parse internet address \"%s\"", value_str); free(value_str); return EXIT_BAD_ARGUMENTS; } *value = ia; #else /* ENABLE_RFC2553 */ memset(&hints, 0, sizeof(hints)); hints.ai_flags = 0; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; ret = getaddrinfo(value_str, NULL, &hints, &res); if (ret != 0) { rs_log_error("can't parse internet address \"%s\": %s", value_str, gai_strerror(ret)); free(value_str); return EXIT_BAD_ARGUMENTS; } value->family = res->ai_family; if (res->ai_family == AF_INET) { value->addr.inet = ((struct sockaddr_in *)res->ai_addr)->sin_addr; } else if (res->ai_family == AF_INET6) { value->addr.inet6 = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; } else { rs_log_error("unsupported address family %d for address \"%s\"", res->ai_family, value_str); freeaddrinfo(res); free(value_str); return EXIT_BAD_ARGUMENTS; } freeaddrinfo(res); #endif /* ENABLE_RFC2553 */ free(value_str); #ifdef ENABLE_RFC2553 mask->family = value->family; #endif if (mask_str != NULL) { int mask_bits; #ifndef ENABLE_RFC2553 static const int mask_max_bits = 32; #else int mask_max_bits; if (mask->family == AF_INET) mask_max_bits = 32; else mask_max_bits = 128; #endif /* find mask length as a number of bits */ mask_bits = atoi(mask_str); if (mask_bits < 0 || mask_bits > mask_max_bits) { rs_log_error("invalid mask \"%s\"", mask_str); return EXIT_BAD_ARGUMENTS; } /* Make a network-endian mask with the top mask_bits set. */ if (mask_bits == mask_max_bits) { set_allones(mask); } else { set_mask(mask, mask_bits); } } else { set_allones(mask); } return 0; } /** * Check whether two 32-bit addresses match. * * @returns 0 if they match, or EXIT_ACCESS_DENIED. **/ static int check_address_inet(const struct in_addr *client, const struct in_addr *value, const struct in_addr *mask) { if ((client->s_addr & mask->s_addr) == (value->s_addr & mask->s_addr)) { rs_trace("match client %#lx, value %#lx, mask %#lx", (long) client->s_addr, (long) value->s_addr, (long) mask->s_addr); return 0; } else { rs_trace("deny client %#lx, value %#lx, mask %#lx", (long) client->s_addr, (long) value->s_addr, (long) mask->s_addr); return EXIT_ACCESS_DENIED; } } #ifdef ENABLE_RFC2553 /** * Compare the masked components of two v6 addresses * * @returns 1 if they match, or 0. **/ static int compare_address_inet6(const struct in6_addr *client, const struct in6_addr *value, const struct in6_addr *mask) { int i; for (i = 0; i < 16; ++i) if ((client->s6_addr[i] & mask->s6_addr[i]) != (value->s6_addr[i] & mask->s6_addr[i])) return 0; return 1; } /** * Check whether two v6 addresses match. * * @returns 0 if they match, or EXIT_ACCESS_DENIED. **/ static int check_address_inet6(const struct in6_addr *client, const struct in6_addr *value, const struct in6_addr *mask) { if (compare_address_inet6(client, value, mask)) { rs_trace("match v6 client"); //rs_trace("match client %#lx, value %#lx, mask %#lx", //(long) *client, (long) *value, (long) *mask); return 0; } else { rs_trace("deny v6 client"); //rs_trace("deny client %#lx, value %#lx, mask %#lx", //(long) *client, (long) *value, (long) *mask); return EXIT_ACCESS_DENIED; } } /** * Extract the lower 32-bits of a v6 address. **/ static uint32_t inet_from_inet6(const struct in6_addr *addr) { uint32_t dest = 0; int i; for (i = 0; i < 4; ++i) { uint32_t dest_byte = addr->s6_addr[12 + i]; dest |= (dest_byte << (8 * (3-i))); } return dest; } #endif /* ENABLE_RFC2553 */ /** * Check whether a client ought to be allowed. * * @returns 0 for allowed, or EXIT_ACCESS_DENIED. **/ int dcc_check_address(const struct sockaddr *client, const dcc_address_t *value, const dcc_address_t *mask) { if (client->sa_family == AF_INET) { /* The double-cast here avoids warnings from -Wcast-align. */ const struct sockaddr_in *sockaddr = (const struct sockaddr_in *) (void *) client; const struct in_addr *cli_addr = &sockaddr->sin_addr; #ifndef ENABLE_RFC2553 return check_address_inet(cli_addr, value, mask); #else if (value->family == AF_INET) return check_address_inet(cli_addr, &value->addr.inet, &mask->addr.inet); else return EXIT_ACCESS_DENIED; } else if (client->sa_family == AF_INET6) { const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *)client; const struct in6_addr *a6 = &sa6->sin6_addr; if (value->family == AF_INET) { if (IN6_IS_ADDR_V4MAPPED(a6) || IN6_IS_ADDR_V4COMPAT(a6)) { struct in_addr a4; a4.s_addr = inet_from_inet6(a6); return check_address_inet(&a4, &value->addr.inet, &mask->addr.inet); } else return EXIT_ACCESS_DENIED; } else return check_address_inet6(a6, &value->addr.inet6, &mask->addr.inet6); #endif } else { rs_log_notice("access denied from unsupported address family %d", client->sa_family); return EXIT_ACCESS_DENIED; } } distcc-3.4/src/access.h000066400000000000000000000030461404653710500150420ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #pragma once #include /* access.c */ #ifndef ENABLE_RFC2553 typedef struct in_addr dcc_address_t; #else typedef struct dcc_address { sa_family_t family; union { struct in_addr inet; struct in6_addr inet6; } addr; } dcc_address_t; #endif int dcc_parse_mask(const char *mask_spec, dcc_address_t *value, dcc_address_t *mask); int dcc_check_address(const struct sockaddr *client, const dcc_address_t *value, const dcc_address_t *mask); struct dcc_allow_list { dcc_address_t addr, mask; struct dcc_allow_list *next; }; distcc-3.4/src/arg.c000066400000000000000000000465761404653710500143640ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "I have a bone to pick, and a few to break." */ /** * @file * * Functions for understanding and manipulating argument vectors. * * The few options explicitly handled by the client are processed in its * main(). At the moment, this is just --help and --version, so this function * never has to worry about them. * * We recognize two basic forms "distcc gcc ..." and "distcc ...", with no * explicit compiler name. This second one is used if you have a Makefile * that can't manage two-word values for $CC; eventually it might support * putting a link to distcc on your path as 'gcc'. We call this second one an * implicit compiler. * * We need to distinguish the two by working out whether the first argument * "looks like" a compiler name or not. I think the two cases in which we * should assume it's implicit are "distcc -c hello.c" (starts with a hyphen), * and "distcc hello.c" (starts with a source filename.) * * In the case of implicit compilation "distcc --help" will always give you * distcc's help, not gcc's, and similarly for --version. I don't see much * that we can do about that. * * @todo We don't need to run the full argument scanner on the server, only * something simple to recognize input and output files. That would perhaps * make the function simpler, and also mean that if argument recognizer bugs * are fixed in the future, they only need to be fixed on the client, not on * the server. An even better solution is to have the client tell the server * where to put the input and output files. * * @todo Perhaps make the argument parser driven by a data table. (Would that * actually be clearer?) Perhaps use regexps to recognize strings. * * @todo We could also detect options like "-x cpp-output" or "-x * assembler-with-cpp", because they should override language detection based * on extension. I haven't seen anyone use them yet though. In fact, since * we don't assemble remotely it is moot for the only reported case, the * Darwin C library. We would also need to update the option when passing it * to the server. * * @todo Perhaps assume that assembly code will not use both #include and * .include, and therefore if we preprocess locally we can distribute the * compilation? Assembling is so cheap that it's not necessarily worth * distributing. **/ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "snprintf.h" int dcc_argv_append(char **argv, char *toadd) { int l = dcc_argv_len(argv); argv[l] = toadd; argv[l+1] = NULL; /* just make sure */ return 0; } static void dcc_note_compiled(const char *input_file, const char *output_file) { const char *input_base, *output_base; input_base = dcc_find_basename(input_file); output_base = dcc_find_basename(output_file); rs_log(RS_LOG_INFO|RS_LOG_NONAME, "compile from %s to %s", input_base, output_base); } /** * Parse arguments, extract ones we care about, and also work out * whether it will be possible to distribute this invocation remotely. * * This is a little hard because the cc argument rules are pretty complex, but * the function still ought to be simpler than it already is. * * This code is called on both the client and the server, though they use the * results differently. * * This function makes a copy of the arguments, modified to ensure that * the arguments include '-o '. This is returned in *ret_newargv. * The copy is dynamically allocated and the caller is responsible for * deallocating it. * * @returns 0 if it's ok to distribute this compilation, or an error code. **/ int dcc_scan_args(char *argv[], char **input_file, char **output_file, char ***ret_newargv) { int seen_opt_c = 0, seen_opt_s = 0; int i; char *a; int ret; /* allow for -o foo.o */ if ((ret = dcc_copy_argv(argv, ret_newargv, 4)) != 0) return ret; argv = *ret_newargv; /* FIXME: new copy of argv is leaked */ dcc_trace_argv("scanning arguments", argv); /* Things like "distcc -c hello.c" with an implied compiler are * handled earlier on by inserting a compiler name. At this * point, argv[0] should always be a compiler name. */ if (argv[0][0] == '-') { rs_log_error("unrecognized distcc option: %s", argv[0]); exit(EXIT_BAD_ARGUMENTS); } *input_file = *output_file = NULL; for (i = 0; (a = argv[i]); i++) { if (a[0] == '-') { if (!strcmp(a, "-E")) { rs_trace("-E call for cpp must be local"); return EXIT_LOCAL_CPP; } else if (!strcmp(a, "-MD") || !strcmp(a, "-MMD")) { /* These two generate dependencies as a side effect. They * should work with the way we call cpp. */ } else if (!strcmp(a, "-MG") || !strcmp(a, "-MP")) { /* These just modify the behaviour of other -M* options and do * nothing by themselves. */ } else if (!strcmp(a, "-MF") || !strcmp(a, "-MT") || !strcmp(a, "-MQ")) { /* As above but with extra argument. */ i++; } else if (!strncmp(a, "-MF", 3) || !strncmp(a, "-MT", 3) || !strncmp(a, "-MQ", 3)) { /* As above, without extra argument. */ } else if (a[1] == 'M') { /* -M(anything else) causes the preprocessor to produce a list of make-style dependencies on header files, either to stdout or to a local file. It implies -E, so only the preprocessor is run, not the compiler. There would be no point trying to distribute it even if we could. */ rs_trace("%s implies -E (maybe) and must be local", a); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-march=native")) { rs_trace("-march=native generates code for local machine; " "must be local"); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-mtune=native")) { rs_trace("-mtune=native optimizes for local machine; " "must be local"); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-flto")) { rs_trace("LTO cc invocations are not worth distributing"); return EXIT_DISTCC_FAILED; } else if (str_startswith("-Wa,", a)) { /* Look for assembler options that would produce output * files and must be local. * * Writing listings to stdout could be supported but it might * be hard to parse reliably. */ if (strstr(a, ",-a") || strstr(a, "--MD")) { rs_trace("%s must be local", a); return EXIT_DISTCC_FAILED; } } else if (str_startswith("-specs=", a)) { rs_trace("%s must be local", a); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-S")) { seen_opt_s = 1; } else if (!strcmp(a, "-fprofile-arcs") || !strcmp(a, "-ftest-coverage") || !strcmp(a, "--coverage") || !strncmp(a, "-fprofile-generate", 18) /* it also has an -fprofile-generate= form */ || !strncmp(a, "-fprofile-use", 13) || !strncmp(a, "-fauto-profile", 14) || !strcmp(a, "-fprofile-correction")) { rs_log_info("compiler will emit/use profile info; must be local"); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-frepo")) { rs_log_info("compiler will emit .rpo files; must be local"); return EXIT_DISTCC_FAILED; } else if (str_startswith("-x", a) && argv[i+1] && !str_startswith("c", argv[i+1]) && !str_startswith("c++", argv[i+1]) && !str_startswith("objective-c", argv[i+1]) && !str_startswith("objective-c++", argv[i+1]) && !str_startswith("go", argv[i+1]) ) { rs_log_info("gcc's -x handling is complex; running locally for %s", argv[i+1] ? argv[i+1] : "empty"); return EXIT_DISTCC_FAILED; } else if (str_startswith("-dr", a)) { rs_log_info("gcc's debug option %s may write extra files; " "running locally", a); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-c")) { seen_opt_c = 1; } else if (!strcmp(a, "-o")) { /* Whatever follows must be the output */ a = argv[++i]; goto GOT_OUTPUT; } else if (str_startswith("-o", a)) { a += 2; /* skip "-o" */ goto GOT_OUTPUT; } } else { if (dcc_is_source(a)) { rs_trace("found input file \"%s\"", a); if (*input_file) { rs_log_info("do we have two inputs? i give up"); return EXIT_DISTCC_FAILED; } *input_file = a; } else if (str_endswith(".o", a)) { GOT_OUTPUT: rs_trace("found object/output file \"%s\"", a); if (*output_file) { rs_log_info("called for link? i give up"); return EXIT_DISTCC_FAILED; } *output_file = a; } } } /* TODO: ccache has the heuristic of ignoring arguments that are not * extant files when looking for the input file; that's possibly * worthwhile. Of course we can't do that on the server. */ if (!seen_opt_c && !seen_opt_s) { rs_log_info("compiler apparently called not for compile"); return EXIT_DISTCC_FAILED; } if (!*input_file) { rs_log_info("no visible input file"); return EXIT_DISTCC_FAILED; } if (dcc_source_needs_local(*input_file)) return EXIT_DISTCC_FAILED; if (!*output_file) { /* This is a commandline like "gcc -c hello.c". They want * hello.o, but they don't say so. For example, the Ethereal * makefile does this. * * Note: this doesn't handle a.out, the other implied * filename, but that doesn't matter because it would already * be excluded by not having -c or -S. */ char *ofile; /* -S takes precedence over -c, because it means "stop after * preprocessing" rather than "stop after compilation." */ if (seen_opt_s) { if (dcc_output_from_source(*input_file, ".s", &ofile)) return EXIT_DISTCC_FAILED; } else if (seen_opt_c) { if (dcc_output_from_source(*input_file, ".o", &ofile)) return EXIT_DISTCC_FAILED; } else { rs_log_crit("this can't be happening(%d)!", __LINE__); return EXIT_DISTCC_FAILED; } rs_log_info("no visible output file, going to add \"-o %s\" at end", ofile); dcc_argv_append(argv, strdup("-o")); dcc_argv_append(argv, ofile); *output_file = ofile; } dcc_note_compiled(*input_file, *output_file); if (strcmp(*output_file, "-") == 0) { /* Different compilers may treat "-o -" as either "write to * stdout", or "write to a file called '-'". We can't know, * so we just always run it locally. Hopefully this is a * pretty rare case. */ rs_log_info("output to stdout? running locally"); return EXIT_DISTCC_FAILED; } return 0; } /** * Used to change "-c" or "-S" to "-E", so that we get preprocessed * source. **/ int dcc_set_action_opt(char **a, const char *new_c) { int gotone = 0; for (; *a; a++) if (!strcmp(*a, "-c") || !strcmp(*a, "-S")) { *a = strdup(new_c); if (*a == NULL) { rs_log_error("strdup failed"); exit(EXIT_OUT_OF_MEMORY); } gotone = 1; /* keep going; it's not impossible they wrote "gcc -c -c * -c hello.c" */ } if (!gotone) { rs_log_error("failed to find -c or -S"); return EXIT_DISTCC_FAILED; } else { return 0; } } /** * Change object file or suffix of -o to @p ofname * Frees the old value, if it exists. * * It's crucially important that in every case where an output file is * detected by dcc_scan_args(), it's also correctly identified here. * It might be better to make the code shared. **/ int dcc_set_output(char **a, char *ofname) { int i; for (i = 0; a[i]; i++) if (0 == strcmp(a[i], "-o") && a[i+1] != NULL) { rs_trace("changed output from \"%s\" to \"%s\"", a[i+1], ofname); free(a[i+1]); a[i+1] = strdup(ofname); if (a[i+1] == NULL) { rs_log_crit("failed to allocate space for output parameter"); return EXIT_OUT_OF_MEMORY; } dcc_trace_argv("command after", a); return 0; } else if (0 == strncmp(a[i], "-o", 2)) { char *newptr; rs_trace("changed output from \"%s\" to \"%s\"", a[i]+2, ofname); free(a[i]); if (asprintf(&newptr, "-o%s", ofname) == -1) { rs_log_crit("failed to allocate space for output parameter"); return EXIT_OUT_OF_MEMORY; } a[i] = newptr; dcc_trace_argv("command after", a); return 0; } rs_log_error("failed to find \"-o\""); return EXIT_DISTCC_FAILED; } /** * Change input file to a copy of @p ifname; called on compiler. * Frees the old value. * * @todo Unify this with dcc_scan_args * * @todo Test this by making sure that when the modified arguments are * run through scan_args, the new ifname is identified as the input. **/ int dcc_set_input(char **a, char *ifname) { int i; for (i =0; a[i]; i++) if (dcc_is_source(a[i])) { rs_trace("changed input from \"%s\" to \"%s\"", a[i], ifname); free(a[i]); a[i] = strdup(ifname); if (a[i] == NULL) { rs_log_crit("failed to allocate space for input parameter"); return EXIT_OUT_OF_MEMORY; } dcc_trace_argv("command after", a); return 0; } rs_log_error("failed to find input file"); return EXIT_DISTCC_FAILED; } /* Subroutine of dcc_expand_preprocessor_options(). * Calculate how many extra arguments we'll need to convert * a "-Wp,..." option into regular gcc options. * Returns the number of extra arguments needed. */ static int count_extra_args(char *dash_Wp_option) { int extra_args = 0; char *comma = dash_Wp_option + strlen("-Wp"); while (comma != NULL) { char *opt = comma + 1; comma = strchr(opt, ','); if (str_startswith("-MD,", opt) || str_startswith("-MMD,", opt)) { char *filename = comma + 1; comma = strchr(filename, ','); extra_args += 3; /* "-MD", "-MF", filename. */ } else { extra_args++; } } return extra_args; } /* Subroutine of dcc_expand_preprocessor_options(). * Convert a "-Wp,..." option into one or more regular gcc options. * Copy the resulting gcc options to dest_argv, which should be * pre-allocated by the caller. * Destructively modifies dash_Wp_option as it goes. * Returns 0 on success, nonzero for error (out of memory). */ static int copy_extra_args(char **dest_argv, char *dash_Wp_option, int extra_args) { int i = 0; char *comma = dash_Wp_option + strlen("-Wp"); while (comma != NULL) { char *opt = comma + 1; comma = strchr(opt, ','); if (comma) *comma = '\0'; dest_argv[i] = strdup(opt); if (!dest_argv[i]) return EXIT_OUT_OF_MEMORY; i++; if (strcmp(opt, "-MD") == 0 || strcmp(opt, "-MMD") == 0) { char *filename; if (!comma) { rs_log_warning("'-Wp,-MD' or '-Wp,-MMD' option is missing " "filename argument"); break; } filename = comma + 1; comma = strchr(filename, ','); if (comma) *comma = '\0'; dest_argv[i] = strdup("-MF"); if (!dest_argv[i]) return EXIT_OUT_OF_MEMORY; i++; dest_argv[i] = strdup(filename); if (!dest_argv[i]) return EXIT_OUT_OF_MEMORY; i++; } } assert(i == extra_args); return 0; } /* * Convert any "-Wp," options into regular gcc options. * We do this because it simplifies the command-line * option handling elsewhere; this is the only place * that needs to parse "-Wp," options. * Returns 0 on success, nonzero for error (out of memory). * * The argv array pointed to by argv_ptr when this function * is called must have been dynamically allocated. It remains * the caller's responsibility to deallocate it. */ int dcc_expand_preprocessor_options(char ***argv_ptr) { int i, j, ret; char **argv = *argv_ptr; char **new_argv; int argc = dcc_argv_len(argv); for (i = 0; argv[i]; i++) { if (str_startswith("-Wp,", argv[i])) { /* First, calculate how many extra arguments we'll need. */ int extra_args = count_extra_args(argv[i]); assert(extra_args >= 1); new_argv = calloc(argc + extra_args, sizeof(char *)); if (!new_argv) { return EXIT_OUT_OF_MEMORY; } for (j = 0; j < i; j++) { new_argv[j] = argv[j]; } if ((ret = copy_extra_args(new_argv + i, argv[i], extra_args)) != 0) { free(new_argv); return ret; } for (j = i + 1; j <= argc; j++) { new_argv[j + extra_args - 1] = argv[j]; } free(argv); *argv_ptr = argv = new_argv; i += extra_args - 1; argc += extra_args - 1; } } return 0; } distcc-3.4/src/argutil.c000066400000000000000000000076761404653710500152600ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * Utilities for dealing with argv[]-style strings. * * These rules might not yet be consistently applied in distcc, but they * should be in the future: * * For simplicity in managing memory we try to keep all argv structures * malloc'd, without any shared structure. It is then possible to just free * the whole thing whenever we're finished with it. * * One exception is of course the argv used to invoke the program, which is * treated as read-only. */ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** * Return true if argv contains needle as an argument. **/ int dcc_argv_search(char **a, const char *needle) { for (; *a; a++) if (!strcmp(*a, needle)) return 1; return 0; } unsigned int dcc_argv_len(char **a) { unsigned int i; for (i = 0; a[i]; i++) ; return i; } /* Free a malloc'd argv structure. Only safe when the array and all its * components were malloc'd. */ void dcc_free_argv(char **argv) { char **a; for (a = argv; *a != NULL; a++) free(*a); free(argv); } /* Copy an argv array, adding extra NULL elements to the end to allow for * adding more arguments later. */ int dcc_copy_argv(char **from, char ***out, int delta) { char **b; int l, i, k; l = dcc_argv_len(from); b = malloc((l+1+delta) * (sizeof from[0])); if (b == NULL) { rs_log_error("failed to allocate copy of argv"); return EXIT_OUT_OF_MEMORY; } for (i = 0; i < l; i++) { if ((b[i] = strdup(from[i])) == NULL) { rs_log_error("failed to duplicate element %d", i); for(k = 0; k < i; k++) free(b[k]); free(b); return EXIT_OUT_OF_MEMORY; } } b[l] = NULL; *out = b; return 0; } /** * Convert an argv array to printable form for debugging output. * * @note The result is not necessarily properly quoted for passing to * shells. * * @return newly-allocated string containing representation of * arguments. **/ char *dcc_argv_tostr(char **a) { int l, i; char *s, *ss; /* calculate total length */ for (l = 0, i = 0; a[i]; i++) { l += strlen(a[i]) + 3; /* two quotes and space */ } ss = s = malloc((size_t) l + 1); if (!s) { rs_log_crit("failed to allocate %d bytes", l+1); exit(EXIT_OUT_OF_MEMORY); } for (i = 0; a[i]; i++) { /* kind of half-assed quoting; won't handle strings containing * quotes properly, but good enough for debug messages for the * moment. */ int needs_quotes = !*a[i] || (strpbrk(a[i], " \t\n\"\';") != NULL); if (i) *ss++ = ' '; if (needs_quotes) *ss++ = '"'; strcpy(ss, a[i]); ss += strlen(a[i]); if (needs_quotes) *ss++ = '"'; } *ss = '\0'; return s; } distcc-3.4/src/auth.h000066400000000000000000000033341404653710500145420ustar00rootroot00000000000000/* Copyright (C) 2008 CERN * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Ian Baker */ #include /* Handshake exchange character. */ #define HANDSHAKE '*' /* Notification of server access. */ #define ACCESS 'y' /* Notification of server access denied. */ #define NO_ACCESS 'n' struct dcc_hostdef; int dcc_gssapi_acquire_credentials(void); void dcc_gssapi_release_credentials(void); int dcc_gssapi_obtain_list(int mode); void dcc_gssapi_free_list(void); int dcc_gssapi_check_client(int to_net_fd, int from_net_fd); int dcc_gssapi_perform_requested_security(const struct dcc_hostdef *host, int to_net_fd, int from_net_fd); void dcc_gssapi_status_to_log(OM_uint32 status_code, int status_type); void dcc_gssapi_cleanup(gss_buffer_desc *input_tok, gss_buffer_desc *output_tok, gss_name_t *name); int dcc_gssapi_compare_flags(OM_uint32 req_flags, OM_uint32 ret_flags); void dcc_gssapi_delete_ctx(gss_ctx_id_t *ctx_handle); int send_token(int sd, gss_buffer_t token); int recv_token(int sd, gss_buffer_t token); distcc-3.4/src/auth_common.c000066400000000000000000000146621404653710500161130ustar00rootroot00000000000000/* Copyright (C) 2008 CERN * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Ian Baker */ #include #ifdef HAVE_GSSAPI #include #endif #include #include #include #include #include "auth.h" #include "distcc.h" #include "exitcode.h" #include "netutil.h" #include "rpc.h" #include "trace.h" /* * Provide a textual representation of a GSS-API or mechanism-specific * status code and write this to the log file. * * @param status_code. Status code to convert. * * @param status_type. The type of the status code, either GSS_C_GSS_CODE * for a GSS-API status code or GSS_C_MECH_CODE * for a mechanism-specific status code. */ void dcc_gssapi_status_to_log(OM_uint32 status_code, int status_type) { gss_buffer_desc status_string = GSS_C_EMPTY_BUFFER; OM_uint32 major_status, minor_status; OM_uint32 message_ctx = 0; do { major_status = gss_display_status(&minor_status, status_code, status_type, GSS_C_NULL_OID, &message_ctx, &status_string); rs_log_info("%s: %s", (status_type == GSS_C_GSS_CODE) ? "GSSAPI" : "Mech" , (char *) status_string.value); gss_release_buffer(&minor_status, &status_string); } while (message_ctx != 0); (void) major_status; (void) minor_status; } /* * Perform a cleanup on specified GSS-API internal data formats. * * @param input_tok. The input token to release. * * @param output_tok. The output token to release. * * @param name. The name to release. */ void dcc_gssapi_cleanup(gss_buffer_desc *input_tok, gss_buffer_desc *output_tok, gss_name_t *name) { OM_uint32 major_status, minor_status; if (input_tok != NULL) { if ((major_status = gss_release_buffer(&minor_status, input_tok)) != GSS_S_COMPLETE) { rs_log_error("Failed to release buffer."); } } if (output_tok != NULL) { if ((major_status = gss_release_buffer(&minor_status, output_tok)) != GSS_S_COMPLETE) { rs_log_error("Failed to release buffer."); } } if (name != NULL) { if ((major_status = gss_release_name(&minor_status, name)) != GSS_S_COMPLETE) { rs_log_error("Failed to release name."); } } (void) major_status; (void) minor_status; } /* * Perform a comparison of two sets of flags representing security * services. At the moment we only check for mutual authentication, * replay and out of sequence detection, but this function could be * extended to include others. * * @param req_flags. The first set of flags to be compared and * represents what is required by the client * or server. * * @param ret_flags. The second set of flags to be compared and * what is provided/returned by the peer. * * Returns 0 on success, otherwise error. */ int dcc_gssapi_compare_flags(OM_uint32 req_flags, OM_uint32 ret_flags) { if (req_flags & GSS_C_MUTUAL_FLAG) { if (ret_flags & GSS_C_MUTUAL_FLAG) { rs_log_info("Mutual authentication requested and granted."); } else { rs_log_crit("Requested security services don't match those returned."); return EXIT_GSSAPI_FAILED; } } if (req_flags & GSS_C_REPLAY_FLAG) { if (ret_flags & GSS_C_REPLAY_FLAG) { rs_log_info("Replay detection requested and granted."); } else { rs_log_crit("Requested security services don't match those returned."); return EXIT_GSSAPI_FAILED; } } if (req_flags & GSS_C_SEQUENCE_FLAG) { if (ret_flags & GSS_C_SEQUENCE_FLAG) { rs_log_info("Out of sequence detection requested and granted."); } else { rs_log_crit("Requested security services don't match those returned."); return EXIT_GSSAPI_FAILED; } } return 0; } /* * Delete a specified secure context from the current process. * The output buffer token is not used as we do not notify the * peer. * * @param ctx_handle. The secure context to delete. */ void dcc_gssapi_delete_ctx(gss_ctx_id_t *ctx_handle) { OM_uint32 major_status, minor_status; if (ctx_handle != NULL) { if (*ctx_handle != GSS_C_NO_CONTEXT) { if ((major_status = gss_delete_sec_context(&minor_status, ctx_handle, GSS_C_NO_BUFFER)) != GSS_S_COMPLETE) { rs_log_error("Failed to delete context."); } } } } /* * Send the specified token. First we transmit the token length, * then the token itself. * * @param token. The token to be sent. * * Returns 0 on success, otherwise error. */ int send_token(int sd, gss_buffer_t token) { int ret; if ((ret = dcc_x_token_int(sd, "TLEN", token->length)) != 0) { return ret; } if ((ret = dcc_writex(sd, token->value, token->length)) != 0) { return ret; } return 0; } /* * Receive a token. First we receive the token length, * then the token itself. * * @param token. The token to be received. * * Returns 0 on success, otherwise error. */ int recv_token(int sd, gss_buffer_t token) { int ret; unsigned length; if ((ret = dcc_r_token_int(sd, "TLEN", &length)) != 0) { return ret; } if (length > INT_MAX || length == 0) { rs_log_error("Malformed token length."); return EXIT_IO_ERROR; } token->length = length; token->value = malloc(length); if (token->value == NULL && length != 0) { rs_log_error("malloc failed : %lu bytes: out of memory.", (unsigned long) length); return EXIT_OUT_OF_MEMORY; } if ((ret = dcc_readx(sd, token->value, token->length)) != 0) { return ret; } return 0; } distcc-3.4/src/auth_distcc.c000066400000000000000000000246011404653710500160660ustar00rootroot00000000000000/* Copyright (C) 2008 CERN * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Ian Baker */ #include #ifdef HAVE_GSSAPI #include #include #endif #include #include #include #include #include "auth.h" #include "distcc.h" #include "exitcode.h" #include "hosts.h" #include "netutil.h" #include "trace.h" static int dcc_gssapi_establish_secure_context(const struct dcc_hostdef *host, int to_net_sd, int from_net_sd, OM_uint32 req_flags, OM_uint32 *ret_flags); static int dcc_gssapi_send_handshake(int to_net_sd, int from_net_sd); static int dcc_gssapi_recv_notification(int sd); /** * Global security context in case other services are implemented in the * future. */ gss_ctx_id_t distcc_ctx_handle = GSS_C_NO_CONTEXT; /* * Perform any requested security. Message replay and out of sequence * detection are given in addition to mutual authentication. * * @param to_net_sd. Socket to write to. * * @param from_net_sd. Socket to read from. * * Returns 0 on success, otherwise error. */ int dcc_gssapi_perform_requested_security(const struct dcc_hostdef *host, int to_net_sd, int from_net_sd) { int ret; OM_uint32 req_flags, ret_flags; req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; if ((ret = dcc_gssapi_establish_secure_context(host, to_net_sd, from_net_sd, req_flags, &ret_flags)) != 0) { return ret; } if ((ret = dcc_gssapi_compare_flags(req_flags, ret_flags)) != 0) { dcc_gssapi_delete_ctx(&distcc_ctx_handle); return ret; } if ((ret = dcc_gssapi_recv_notification(from_net_sd)) != 0) { dcc_gssapi_delete_ctx(&distcc_ctx_handle); return ret; } rs_log_info("Authentication complete - happy compiling!"); return 0; } /* * Establish a secure context using the GSS-API. A handshake is attempted in * order to detect a non-authenticating server. The server IP address is obtained * from the socket and is used to perform an fqdn lookup in case a DNS alias is * used as a host spec, this ensures we authenticate against the correct server. * We attempt to extract the server principal name, a service, from the * environment, if it is not specified we use "host/" as a default. * * @pram to_net_sd. Socket to write to. * * @pram from_net_sd. Socket to read from. * * @param req_flags. A representation of the security services to * be requested. * * @param ret_flags. A representation of the security services * provided/supported by the underlying mechanism * to be returned to the invoking function. * * Returns 0 on success, otherwise error. */ static int dcc_gssapi_establish_secure_context(const struct dcc_hostdef *host, int to_net_sd, int from_net_sd, OM_uint32 req_flags, OM_uint32 *ret_flags) { char *ext_princ_name = NULL; char *full_name = NULL; char *princ_env_val = NULL; gss_buffer_desc input_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc name_buffer = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_tok = GSS_C_EMPTY_BUFFER; gss_name_t int_serv_name; gss_OID name_type; int ret; OM_uint32 major_status, minor_status, return_status; socklen_t addr_len; struct hostent *hp; struct sockaddr_in addr; if (!host->auth_name) { addr_len = sizeof(addr); if ((ret = getpeername(to_net_sd, (struct sockaddr *)&addr, &addr_len)) != 0) { rs_log_error("Failed to look up peer address using socket \"%d\": %s.", to_net_sd, hstrerror(h_errno)); return EXIT_CONNECT_FAILED; } rs_log_info("Successfully looked up IP address %s using socket %d.", inet_ntoa(addr.sin_addr), to_net_sd); if ((hp = gethostbyaddr((char *) &addr.sin_addr, sizeof(addr.sin_addr), AF_INET)) == NULL) { rs_log_error("Failed to look up host by address \"%s\": %s.", inet_ntoa(addr.sin_addr), hstrerror(h_errno)); return EXIT_CONNECT_FAILED; } rs_log_info("Successfully looked up host %s using IP address %s.", hp->h_name, inet_ntoa(addr.sin_addr)); full_name = hp->h_name; } else { full_name = host->auth_name; } if ((princ_env_val = getenv("DISTCC_PRINCIPAL"))) { if (asprintf(&ext_princ_name, "%s@%s", princ_env_val, full_name) < 0) { rs_log_error("Failed to allocate memory for asprintf."); return EXIT_OUT_OF_MEMORY; } name_type = GSS_C_NT_HOSTBASED_SERVICE; } else { if (asprintf(&ext_princ_name, "host/%s", full_name) < 0) { rs_log_error("Failed to allocate memory for asprintf."); return EXIT_OUT_OF_MEMORY; } name_type = GSS_C_NT_USER_NAME; } name_buffer.value = ext_princ_name; name_buffer.length = strlen(ext_princ_name); if ((major_status = gss_import_name(&minor_status, &name_buffer, name_type, &int_serv_name)) != GSS_S_COMPLETE) { rs_log_error("Failed to import service name to internal GSS-API format."); return EXIT_GSSAPI_FAILED; } input_tok.value = NULL; input_tok.length = 0; output_tok.value = NULL; output_tok.length = 0; if ((ret = dcc_gssapi_send_handshake(to_net_sd, from_net_sd)) != 0) { return ret; } do { major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, &distcc_ctx_handle, int_serv_name, GSS_C_NO_OID, req_flags, 0, GSS_C_NO_CHANNEL_BINDINGS, &input_tok, NULL, &output_tok, ret_flags, NULL); if (GSS_ERROR(major_status)) { rs_log_crit("Failed to initiate a secure context."); dcc_gssapi_status_to_log(major_status, GSS_C_GSS_CODE); dcc_gssapi_status_to_log(minor_status, GSS_C_MECH_CODE); return EXIT_GSSAPI_FAILED; } if (output_tok.length > 0) { if ((ret = send_token(to_net_sd, &output_tok)) != 0) { dcc_gssapi_cleanup(&input_tok, &output_tok, &int_serv_name); return ret; } else { if ((return_status = gss_release_buffer(&minor_status, &output_tok)) != GSS_S_COMPLETE) { rs_log_error("Failed to release buffer."); } } } if (input_tok.length > 0) { if ((return_status = gss_release_buffer(&minor_status, &input_tok)) != GSS_S_COMPLETE) { rs_log_error("Failed to release buffer."); } } if (major_status == GSS_S_CONTINUE_NEEDED) { if ((ret = recv_token(from_net_sd, &input_tok)) != 0) { dcc_gssapi_cleanup(&input_tok, &output_tok, &int_serv_name); return ret; } } } while (major_status != GSS_S_COMPLETE); rs_log_info("Successfully authenticated %s.", ext_princ_name); dcc_gssapi_cleanup(&input_tok, &output_tok, &int_serv_name); if ((major_status = gss_release_buffer(&minor_status, &name_buffer)) != GSS_S_COMPLETE) { rs_log_error("Failed to release buffer."); } return 0; } /* * Attempt handshake exchange with the server to indicate client's * desire to authentciate. * * @param to_net_sd. Socket to write to. * * @param from_net_sd. Socket to read from. * * Returns 0 on success, otherwise error. */ static int dcc_gssapi_send_handshake(int to_net_sd, int from_net_sd) { char auth = HANDSHAKE; fd_set sockets; int ret; struct timeval timeout; rs_log_info("Sending handshake."); if ((ret = dcc_writex(to_net_sd, &auth, sizeof(auth))) != 0) { return ret; } rs_log_info("Sent %c.", auth); FD_ZERO(&sockets); FD_SET(from_net_sd, &sockets); timeout.tv_sec = 1; timeout.tv_usec = 0; ret = select(from_net_sd + 1, &sockets, NULL, NULL, &timeout); if (ret < 0) { rs_log_error("select failed: %s.", strerror(errno)); return EXIT_IO_ERROR; } if (ret == 0) { rs_log_error("Timeout - does this server require authentication?"); return EXIT_TIMEOUT; } rs_log_info("Receiving handshake."); if ((ret = dcc_readx(from_net_sd, &auth, sizeof(auth))) != 0) { return ret; } rs_log_info("Received %c.", auth); if (auth != HANDSHAKE) { rs_log_crit("No server handshake."); return EXIT_GSSAPI_FAILED; } return 0; } /* * Receive notification from an authenticating server as to * whether the client has successfully gained access or not. * * @param sd. Socket to read from. * * Returns 0 on success, otherwise error. */ static int dcc_gssapi_recv_notification(int sd) { char notification; fd_set sockets; int ret; struct timeval timeout; FD_ZERO(&sockets); FD_SET(sd, &sockets); timeout.tv_sec = 1; timeout.tv_usec = 0; ret = select(sd + 1, &sockets, NULL, NULL, &timeout); if (ret < 0) { rs_log_error("select failed: %s.", strerror(errno)); return EXIT_IO_ERROR; } if (ret == 0) { rs_log_error("Timeout - error receiving notification."); return EXIT_TIMEOUT; } if ((ret = dcc_readx(sd, ¬ification, sizeof(notification))) != 0) { rs_log_crit("Failed to receive notification."); return ret; } if (notification != ACCESS) { rs_log_crit("Access denied by server."); rs_log_info("Your principal may be blacklisted or may not be whitelisted."); return EXIT_ACCESS_DENIED; } rs_log_info("Access granted by server."); return 0; } distcc-3.4/src/auth_distccd.c000066400000000000000000000411311404653710500162270ustar00rootroot00000000000000/* Copyright (C) 2008 CERN * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Ian Baker */ #include #ifdef HAVE_GSSAPI #include #endif #include #include #include #include #include "auth.h" #include "distcc.h" #include "dopt.h" #include "exitcode.h" #include "netutil.h" #include "trace.h" /*Maximum length of principal name in black/white list.*/ #define MAX_NAME_LENGTH 50 /*Key not found during binary search*/ #define KEY_NOT_FOUND -1 static int dcc_gssapi_accept_secure_context(int to_net_sd, int from_net_sd, OM_uint32 *ret_flags, char **principal); static int dcc_gssapi_recv_handshake(int from_net_sd, int to_net_sd); static int dcc_gssapi_check_list(char *principal, int sd); static int dcc_gssapi_bin_search(char *key); static int dcc_gssapi_notify_client(int sd, char status); static int dcc_gssapi_compare_strings(const void *string_one, const void *string_two); /*Global credentials so they're only required and released once*/ /*in the most suitable place.*/ gss_cred_id_t creds; /*Global security context in case other services*/ /*are implemented in the future.*/ gss_ctx_id_t distccd_ctx_handle = GSS_C_NO_CONTEXT; /*Global sorted list of principal names from either a specified*/ /*blacklist or a whitelist available to all children*/ char **list = NULL; /*Global count of the number of principal names in the sorted list.*/ int list_count = 0; /* * Perform any requested security. * * @param to_net_sd. Socket to write to. * * @param from_net_sd. Socket to read from. * * @param ret_flags. A representation of the services requested * by the client. * * @param principal. The name of the client principal. * * Returns 0 on success, otherwise error. */ int dcc_gssapi_check_client(int to_net_sd, int from_net_sd) { char *principal = NULL; int ret; OM_uint32 ret_flags; if ((ret = dcc_gssapi_accept_secure_context(to_net_sd, from_net_sd, &ret_flags, &principal)) != 0) { return ret; } if ((ret = dcc_gssapi_compare_flags(GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG, ret_flags)) != 0) { dcc_gssapi_delete_ctx(&distccd_ctx_handle); return ret; } if (opt_blacklist_enabled || opt_whitelist_enabled) { rs_log_info("Checking %s against %slist %s.", principal, (opt_blacklist_enabled) ? "black" : "white", arg_list_file); if ((ret = dcc_gssapi_check_list(principal, to_net_sd)) != 0) { dcc_gssapi_delete_ctx(&distccd_ctx_handle); free(principal); return ret; } free(principal); } else { rs_log_info("Notifying client."); if ((ret = dcc_gssapi_notify_client(to_net_sd, ACCESS)) != 0) { dcc_gssapi_delete_ctx(&distccd_ctx_handle); return ret; } } return 0; } /* * Accept a secure context using the GSS-API. A handshake is attempted * in order to detect a non-authenticating client. * * @param to_net_sd. Socket to write to. * * @param from_net_sd. Socket to read from. * * @param ret_flags. A representation of the security services * requested by the client to be returned to * the invoking function. * * @param principal. The name of the client principal to be returned * to the invoking function. * * Returns 0 on success, otherwise error. */ static int dcc_gssapi_accept_secure_context(int to_net_sd, int from_net_sd, OM_uint32 *ret_flags, char **principal) { gss_buffer_desc input_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc name_buffer = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_tok = GSS_C_EMPTY_BUFFER; gss_name_t int_client_name; gss_OID name_type; int ret; OM_uint32 major_status, minor_status, return_status; input_tok.value = NULL; input_tok.length = 0; output_tok.value = NULL; output_tok.length = 0; if ((ret = dcc_gssapi_recv_handshake(from_net_sd, to_net_sd)) != 0) { return ret; } do { if ((ret = recv_token(from_net_sd, &input_tok)) != 0) { rs_log_error("Error receiving token."); rs_log_info("(eof may indicate a client error during ctx init)."); return ret; } major_status = gss_accept_sec_context(&minor_status, &distccd_ctx_handle, creds, &input_tok, GSS_C_NO_CHANNEL_BINDINGS, &int_client_name, NULL, &output_tok, ret_flags, NULL, NULL); if (GSS_ERROR(major_status)) { rs_log_crit("Failed to accept secure context."); dcc_gssapi_status_to_log(major_status, GSS_C_GSS_CODE); dcc_gssapi_status_to_log(minor_status, GSS_C_MECH_CODE); if ((return_status = gss_release_buffer(&minor_status, &input_tok)) != GSS_S_COMPLETE) { rs_log_error("Failed to release buffer."); } return EXIT_GSSAPI_FAILED; } if (output_tok.length > 0) { if ((ret = send_token(to_net_sd, &output_tok)) != 0) { dcc_gssapi_cleanup(&input_tok, &output_tok, &int_client_name); return ret; } if ((return_status = gss_release_buffer(&minor_status, &output_tok)) != GSS_S_COMPLETE) { rs_log_error("Failed to release buffer."); } } if (input_tok.length > 0) { if ((return_status = gss_release_buffer(&minor_status, &input_tok)) != GSS_S_COMPLETE) { rs_log_error("Failed to release buffer."); } } } while (major_status != GSS_S_COMPLETE); if ((major_status = gss_display_name(&minor_status, int_client_name, &name_buffer, &name_type)) != GSS_S_COMPLETE) { rs_log_error("Failed to convert name."); } rs_log_info("Successfully authenticated %s.", (char *) name_buffer.value); if ((*principal = malloc(strlen((char *) name_buffer.value) + 1 )) == NULL) { rs_log_error("malloc failed : %ld bytes: out of memory.", (long) (strlen((char *) name_buffer.value) + 1)); return EXIT_OUT_OF_MEMORY; } strcpy(*principal, (char *) name_buffer.value); dcc_gssapi_cleanup(&input_tok, &output_tok, &int_client_name); return 0; } /* * Attempt handshake exchange with the client to indicate server's * desire to authentciate. * * @param from_net_sd. Socket to read from. * * @param to_net_sd. Socket to write to. * * Returns 0 on success, otherwise error. */ static int dcc_gssapi_recv_handshake(int from_net_sd, int to_net_sd) { char auth; int ret; rs_log_info("Receiving handshake."); if ((ret = dcc_readx(from_net_sd, &auth, sizeof(auth))) != 0) { return ret; } rs_log_info("Received %c.", auth); if (auth != HANDSHAKE) { rs_log_crit("No client handshake - did the client require authentication?"); return EXIT_GSSAPI_FAILED; } rs_log_info("Sending handshake."); if ((ret = dcc_writex(to_net_sd, &auth, sizeof(auth))) != 0) { return ret; } rs_log_info("Sent %c.", auth); return 0; } /* * Check the name of the connecting client principal against the sorted * list of principal names using a binary search to determine access * rights depending upon the type of list used. The client is then * notified of the outcome. * * @param principal. The name of the connecting client principal. * * @param sd. Socket to write notification to. * * Returns 0 on success, otherwise access deinied. */ static int dcc_gssapi_check_list(char *principal, int sd) { char *pos = NULL; int location, ret; if ((pos = strchr(principal, '@')) != NULL) { *pos = '\0'; } location = dcc_gssapi_bin_search(principal); if (opt_blacklist_enabled) { /*blacklist*/ if (location >= 0) { rs_log_info("Access denied - %s blacklisted.", principal); rs_log_info("Notifying client."); dcc_gssapi_notify_client(sd, NO_ACCESS); return EXIT_GSSAPI_FAILED; } else { rs_log_info("Access granted - %s not blacklisted.", principal); rs_log_info("Notifying client."); if ((ret = dcc_gssapi_notify_client(sd, ACCESS)) != 0) { return ret; } return 0; } } else { /*whitelist*/ if (location >= 0) { rs_log_info("Access granted - %s whitelisted.", principal); rs_log_info("Notifying client."); if ((ret = dcc_gssapi_notify_client(sd, ACCESS)) != 0) { return ret; } return 0; } else { rs_log_info("Access denied - %s not whitelisted.", principal); rs_log_info("Notifying client."); dcc_gssapi_notify_client(sd, NO_ACCESS); return EXIT_GSSAPI_FAILED; } } } /* * Perform a binary search on a sorted list for a key. * * @param key. The search key. * * Returns index if key in list, otherwise * KEY_NOT_FOUND condition. */ static int dcc_gssapi_bin_search(char *key) { int bottom = 0; int middle, res; int top = list_count - 1; while (bottom <= top) { middle = (bottom + top) / 2; res = strcmp(key, list[middle]); if (res < 0) { top = middle - 1; } else if (res > 0) { bottom = middle + 1; } else { return middle; } } return KEY_NOT_FOUND; } /* * Send notification of access/no access to client. * * @param sd. Socket to write notification to. * * @param status. Status of access request. * Either 'y' or 'n' * * Returns 0 on success, otherwise error. */ static int dcc_gssapi_notify_client(int sd, char status) { int ret; if ((ret = dcc_writex(sd, &status, sizeof(status))) != 0) { rs_log_crit("Failed to notify client."); return ret; } return 0; } /* * Acquire credentials for the distccd daemon. We attempt to extract * the server principal name from the environment and ascertain the * name type. * * Returns 0 on success, otherwise error. */ int dcc_gssapi_acquire_credentials(void) { char *princ_env_val = NULL; gss_buffer_desc name_buffer = GSS_C_EMPTY_BUFFER; gss_name_t int_princ_name; gss_OID name_type; OM_uint32 major_status, minor_status; princ_env_val = getenv("DISTCCD_PRINCIPAL"); if (princ_env_val == NULL) { rs_log_error("No principal name specified."); return EXIT_GSSAPI_FAILED; } if (strchr(princ_env_val, '@') != NULL) { name_type = GSS_C_NT_HOSTBASED_SERVICE; } else { name_type = GSS_C_NT_USER_NAME; } name_buffer.value = princ_env_val; name_buffer.length = strlen(princ_env_val); rs_log_info("Acquiring credentials."); name_buffer.length = strlen(name_buffer.value); if ((major_status = gss_import_name(&minor_status, &name_buffer, name_type, &int_princ_name)) != GSS_S_COMPLETE) { rs_log_error("Failed to import princ name (%s) to internal GSS-API format.", (char *) name_buffer.value); return EXIT_GSSAPI_FAILED; } major_status = gss_acquire_cred(&minor_status, int_princ_name, 0, GSS_C_NO_OID_SET, GSS_C_ACCEPT, &creds, NULL, NULL); if (major_status != GSS_S_COMPLETE) { rs_log_crit("Failed to acquire credentials."); dcc_gssapi_status_to_log(major_status, GSS_C_GSS_CODE); dcc_gssapi_status_to_log(minor_status, GSS_C_MECH_CODE); if ((major_status = gss_release_name(&minor_status, &int_princ_name)) != GSS_S_COMPLETE) { rs_log_error("Failed to release GSS-API buffer."); } return EXIT_GSSAPI_FAILED; } if ((major_status = gss_release_name(&minor_status, &int_princ_name)) != GSS_S_COMPLETE) { rs_log_error("Failed to release GSS-API buffer."); } rs_log_info("Credentials successfully acquired for %s.", (char *) name_buffer.value); name_buffer.value = NULL; if ((major_status = gss_release_buffer(&minor_status, &name_buffer)) != GSS_S_COMPLETE) { rs_log_error("Failed to release GSS-API buffer."); } return 0; } /* * Release acquired credentials. */ void dcc_gssapi_release_credentials(void) { OM_uint32 major_status, minor_status; if ((major_status = gss_release_cred(&minor_status, &creds)) != GSS_S_COMPLETE) { rs_log_error("Failed to release credentials."); } rs_log_info("Credentials released successfully."); } /* * Read the set of principal names from the specified file * to the list global variable and apply a qsort. If the * list file can not be opened we exit with error as a * requested security feature can not be implemented. * * @param mode. Indicates the type of the list, either * black or white. Used for the log file. * * Returns 0 on success, otherwise error. */ int dcc_gssapi_obtain_list(int mode) { char **head = NULL; char *line = NULL; char *pos = NULL; FILE *file; int ret; size_t length = 0; ssize_t read; if (!(file = fopen(arg_list_file, "r"))) { rs_log_error("Failed to open list file: %s: %s.", arg_list_file, strerror(errno)); return EXIT_GSSAPI_FAILED; } rs_log_info("Using file %s as a %slist.", arg_list_file, (mode) ? "black" : "white"); while ((read = getline(&line, &length, file)) != -1) { list_count++; } if ((ret = fseek(file, 0, SEEK_SET)) != 0) { rs_log_error("fseek failed: %s.", strerror(errno)); /* If seeking to the start of the file fails, * try achieving the same effect by closing and reopening the file. */ if ((ret = fclose(file)) != 0) { rs_log_error("fclose failed: %s.", strerror(errno)); } if (!(file = fopen(arg_list_file, "r"))) { rs_log_error("Failed to open list file: %s: %s.", arg_list_file, strerror(errno)); return EXIT_GSSAPI_FAILED; } } if ((list = malloc(list_count * sizeof(char *))) == NULL) { rs_log_error("malloc failed : %ld bytes: out of memory.", (long) (list_count * sizeof(char *))); return EXIT_OUT_OF_MEMORY; } head = list; while ((getline(&line, &length, file)) != -1) { if ((pos = strchr(line, '\n')) != NULL) { *pos = '\0'; } if ((*list = malloc(strlen(line) + 1)) == NULL) { rs_log_error("malloc failed : %ld bytes: out of memory.", (long) (strlen(line) + 1)); return EXIT_OUT_OF_MEMORY; } strcpy(*list, line); list++; } list = head; qsort(list, list_count, sizeof(char *), dcc_gssapi_compare_strings); if ((ret = fclose(file)) != 0) { rs_log_error("fclose failed: %s.", strerror(errno)); } free(line); return 0; } /* * Comparison function used by qsort, simply compares * the two specified array elements containing two * principal names. * * @param string_one. First element to be compared. * * @param string_two. Second element to be compared. * * Returns the result of the comparison. */ static int dcc_gssapi_compare_strings(const void *string_one, const void *string_two) { const char **s1 = (const char **) string_one; const char **s2 = (const char **) string_two; return strcmp(*s1, *s2); } /* * Free the dynamically allocated memory used by the * list global variable. First free the individual * strings then the array itself. */ void dcc_gssapi_free_list(void) { int i; for (i = 0; i < list_count; i++) { free(list[i]); } free(list); } distcc-3.4/src/backoff.c000066400000000000000000000063121404653710500151660ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Keep track of hosts which are, or are not, usable. **/ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "snprintf.h" #include "lock.h" #include "timefile.h" #include "hosts.h" static int dcc_backoff_period = 60; /* seconds */ /** * Remember that this host is working OK. * * For the moment this just means removing any backoff timer scored against * it. **/ int dcc_enjoyed_host(const struct dcc_hostdef *host) { char *bp; /* special-case: if DISTCC_BACKOFF_PERIOD==0, don't manage backoff files */ bp = getenv("DISTCC_BACKOFF_PERIOD"); if (bp && (atoi(bp) == 0)) return 0; return dcc_remove_timefile("backoff", host); } int dcc_disliked_host(const struct dcc_hostdef *host) { char *bp; /* special-case: if DISTCC_BACKOFF_PERIOD==0, don't manage backoff files */ bp = getenv("DISTCC_BACKOFF_PERIOD"); if (bp && (atoi(bp) == 0)) return 0; /* i hate you (but only for dcc_backoff_period seconds) */ return dcc_mark_timefile("backoff", host); } static int dcc_check_backoff(struct dcc_hostdef *host) { int ret; time_t mtime; if ((ret = dcc_check_timefile("backoff", host, &mtime))) return ret; if (difftime(time(NULL), mtime) < (double) dcc_backoff_period) { rs_trace("still in backoff period for %s", host->hostdef_string); return EXIT_BUSY; } return 0; } /** * Walk through @p hostlist and remove any hosts that are marked unavailable. **/ int dcc_remove_disliked(struct dcc_hostdef **hostlist) { struct dcc_hostdef *h; char *bp; bp = getenv("DISTCC_BACKOFF_PERIOD"); if (bp) dcc_backoff_period = atoi(bp); /* special-case: if DISTCC_BACKOFF_PERIOD==0, don't manage backoff files */ if (dcc_backoff_period == 0) return 0; while ((h = *hostlist) != NULL) { if (dcc_check_backoff(h) != 0) { rs_trace("remove %s from list", h->hostdef_string); *hostlist = h->next; free(h); } else { /* check next one */ hostlist = &h->next; } } return 0; } distcc-3.4/src/bulk.c000066400000000000000000000236121404653710500145320ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "A new contraption to capture a dandelion in one * piece has been put together by the crew." * -- Boards of Canada, "Geogaddi" */ /** * @file * * Bulk file transfer, used for sending .i, .o files etc. * * Files are always sent in the standard IO format: stream name, * length, bytes. This implies that we can deliver to a fifo (just * keep writing), but we can't send from a fifo, because we wouldn't * know how many bytes were coming. * * @note We don't time transmission of files: because the write returns when * they've just been written into the OS buffer, we don't really get * meaningful numbers except for files that are very large. **/ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "rpc.h" #include "bulk.h" #include "time.h" #include "exitcode.h" #include "timeval.h" /** * Open a file for read, and also put its size into @p fsize. * * If the file does not exist, then returns 0, but @p ifd is -1 and @p * fsize is zero. If @p fsize is zero, the caller should not try to * read from the file. * * This strange behaviour for ENOENT is useful because if there is * e.g. no output file from the compiler, we don't want to abort, but * rather just send nothing. The receiver has the corresponding * behaviour of not creating zero-length files. * * Using fstat() helps avoid a race condition -- not a security issue, * but possibly a failure. Shouldn't be very likely though. * * The caller is responsible for closing @p ifd. **/ int dcc_open_read(const char *fname, int *ifd, off_t *fsize) { struct stat buf; *ifd = open(fname, O_RDONLY|O_BINARY); if (*ifd == -1) { int save_errno = errno; if (save_errno == ENOENT) { /* that's OK, just assume it's empty */ *fsize = 0; return 0; } else { rs_log_error("failed to open %s: %s", fname, strerror(save_errno)); return EXIT_IO_ERROR; } } if (fstat(*ifd, &buf) == -1) { rs_log_error("fstat %s failed: %s", fname, strerror(errno)); dcc_close(*ifd); return EXIT_IO_ERROR; } *fsize = buf.st_size; return 0; } void dcc_calc_rate(off_t size_out, struct timeval *before, struct timeval *after, double *secs, double *rate) { struct timeval delta; /* FIXME: Protect against division by zero and other floating-point * exceptions. */ timeval_subtract(&delta, after, before); *secs = (double) delta.tv_sec + (double) delta.tv_usec / 1e6; if (*secs == 0.0) *rate = 0.0; else *rate = ((double) size_out / *secs) / 1024.0; } static int dcc_x_file_lzo1x(int out_fd, int in_fd, const char *token, unsigned in_len) { int ret; char *out_buf = NULL; size_t out_len; /* As a special case, send 0 as 0 */ if (in_len == 0) { if ((ret = dcc_x_token_int(out_fd, token, 0))) goto out; } else { if ((ret = dcc_compress_file_lzo1x(in_fd, in_len, &out_buf, &out_len))) goto out; if ((ret = dcc_x_token_int(out_fd, token, out_len))) goto out; if ((ret = dcc_writex(out_fd, out_buf, out_len))) goto out; } ret = 0; out: free(out_buf); return ret; } /** * Transmit from a local file to the network. Sends TOKEN, LENGTH, BODY, * where the length is the appropriate compressed length. * * Does compression if needed. * * @param ofd File descriptor for the network connection. * @param fname Name of the file to send. * @param token Token for this file, e.g. "DOTO". **/ int dcc_x_file(int ofd, const char *fname, const char *token, enum dcc_compress compression, off_t *f_size_out) { int ifd; int ret; off_t f_size; if (dcc_open_read(fname, &ifd, &f_size)) return EXIT_IO_ERROR; if (ifd == -1) return EXIT_IO_ERROR; if (f_size_out) *f_size_out = f_size; rs_trace("send %lu byte file %s with token %s and compression %d", (unsigned long) f_size, fname, token, compression); if (compression == DCC_COMPRESS_NONE) { if ((ret = dcc_x_token_int(ofd, token, f_size))) goto failed; /* FIXME: These could get truncated if the file was very large (>4G). * That seems pretty unlikely. */ #ifdef HAVE_SENDFILE ret = dcc_pump_sendfile(ofd, ifd, (size_t) f_size); #else ret = dcc_pump_readwrite(ofd, ifd, (size_t) f_size); #endif } else if (compression == DCC_COMPRESS_LZO1X) { ret = dcc_x_file_lzo1x(ofd, ifd, token, f_size); } else { rs_log_error("invalid compression"); return EXIT_PROTOCOL_ERROR; } if (ifd != -1) dcc_close(ifd); return 0; failed: if (ifd != -1) dcc_close(ifd); return ret; } /** * Receive a file stream from the network into a local file. * Make all necessary directories if they don't exist. * * Can handle compression. * * @param len Compressed length of the incoming file. * @param filename local filename to create. **/ int dcc_r_file(int ifd, const char *filename, unsigned len, enum dcc_compress compr) { int ofd; int ret, close_ret; struct stat s; /* This is meant to behave similarly to the output routines in bfd/cache.c * in gnu binutils, because makefiles or configure scripts may depend on * it for edge cases. * * We try to remove the output file first, if its size is not 0. That * should make the newly created file be owned by the current user; it * might also help in the dangerous case of some other process still * reading from the file. * * Checking for size 0 means that we won't unlink special files like * /dev/null or fifos. * * However, failure to remove the file does not cause a warning; we may * not have write permission on the directory, but +w for the file. */ if (dcc_mk_tmp_ancestor_dirs(filename)) { rs_log_error("failed to create path for '%s'", filename); return EXIT_IO_ERROR; } if (stat(filename, &s) == 0) { if (s.st_size != 0) { if (unlink(filename) && errno != ENOENT) { rs_trace("failed to remove %s: %s", filename, strerror(errno)); /* continue */ } } } else { if (errno != ENOENT) { rs_trace("stat %s failed: %s", filename, strerror(errno)); } /* continue */ } ofd = open(filename, O_TRUNC|O_WRONLY|O_CREAT|O_BINARY, 0666); if (ofd == -1) { rs_log_error("failed to create %s: %s", filename, strerror(errno)); return EXIT_IO_ERROR; } ret = 0; if (len > 0) { ret = dcc_r_bulk(ofd, ifd, len, compr); } close_ret = dcc_close(ofd); if (!ret && !close_ret) { rs_trace("received %d bytes to file %s", len, filename); return 0; } rs_trace("failed to receive %s, removing it", filename); if (unlink(filename)) { rs_log_error("failed to unlink %s after failed transfer: %s", filename, strerror(errno)); } return EXIT_IO_ERROR; } /** * Receive a file and print timing statistics. Only used for big files. * * Wrapper around dcc_r_file(). **/ int dcc_r_file_timed(int ifd, const char *fname, unsigned size, enum dcc_compress compr) { struct timeval before, after; int ret; if (gettimeofday(&before, NULL)) rs_log_warning("gettimeofday failed"); ret = dcc_r_file(ifd, fname, size, compr); if (gettimeofday(&after, NULL)) { rs_log_warning("gettimeofday failed"); } else { double secs, rate; dcc_calc_rate(size, &before, &after, &secs, &rate); rs_log_info("%ld bytes received in %.6fs, rate %.0fkB/s", (long) size, secs, rate); } return ret; } int dcc_r_token_file(int in_fd, const char *token, const char *fname, enum dcc_compress compr) { int ret; unsigned i_size; if ((ret = dcc_r_token_int(in_fd, token, &i_size))) return ret; if ((ret = dcc_r_file_timed(in_fd, fname, (size_t) i_size, compr))) return ret; return 0; } int dcc_copy_file_to_fd(const char *in_fname, int out_fd) { off_t len; int ifd; int ret; if ((ret = dcc_open_read(in_fname, &ifd, &len))) return ret; #ifdef HAVE_SENDFILE ret = dcc_pump_sendfile(out_fd, ifd, (size_t) len); #else ret = dcc_pump_readwrite(out_fd, ifd, (size_t) len); #endif if (ret) { close(ifd); return ret; } return 0; } distcc-3.4/src/bulk.h000066400000000000000000000035551404653710500145430ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ int dcc_r_file(int ifd, const char *filename, unsigned, enum dcc_compress); int dcc_r_fifo(int ifd, const char *fifo_name, size_t len); int dcc_x_file(int ofd, const char *fname, const char *token, enum dcc_compress compression, off_t *); int dcc_r_file_timed(int ifd, const char *fname, unsigned size, enum dcc_compress); int dcc_r_token_file(int ifd, const char *token, const char *fname, enum dcc_compress compr); int dcc_open_read(const char *fname, int *ifd, off_t *fsize); int dcc_copy_file_to_fd(const char *in_fname, int out_fd); /* clirpc.c */ int dcc_x_many_files(int ofd, unsigned int n_files, char **fnames); /* srvrpc.c */ int dcc_r_many_files(int in_fd, const char *dirname, enum dcc_compress compr); distcc-3.4/src/cleanup.c000066400000000000000000000126571404653710500152330ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "I have not come through fire and death to bandy crooked * words with a serving-man until the lightning falls!" * -- Gandalf (BBC LoTR radio play) */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "exitcode.h" #include "trace.h" #include "util.h" /** * A list of files that need to be cleaned up on exit. * * Volatile because it can be read from signal handlers. **/ char *volatile *volatile cleanups = 0; /* Dynamically allocated array. */ volatile int cleanups_size = 0; /* The length of the array. */ volatile int n_cleanups = 0; /* The number of entries used. */ static void dcc_cleanup_tempfiles_inner(int from_signal_handler); void dcc_cleanup_tempfiles(void) { dcc_cleanup_tempfiles_inner(0); } void dcc_cleanup_tempfiles_from_signal_handler(void) { dcc_cleanup_tempfiles_inner(1); } /* * You can call this at any time, or hook it into atexit(). It is * safe to call repeatedly. * * If from_signal_handler (a boolean) is non-zero, it means that * we're being called from a signal handler, so we need to be * careful not to call malloc() or free() or any other functions * that might not be async-signal-safe. * (We do call the tracing functions, which is perhaps unsafe * because they call sprintf() if DISCC_VERBOSE=1 is enabled. * But in that case it is probably worth the very small risk * of a crash to get the full tracing output.) * * If $DISTCC_SAVE_TEMPS is set to "1", then files are not actually * deleted, which can be good for debugging. However, we still need * to remove them from the list, otherwise it will eventually overflow * in prefork mode. */ static void dcc_cleanup_tempfiles_inner(int from_signal_handler) { int i; int done = 0; int save = dcc_getenv_bool("DISTCC_SAVE_TEMPS", 0); /* do the unlinks from the last to the first file. * This way, directories get deleted after their files. */ /* tempus fugit */ for (i = n_cleanups - 1; i >= 0; i--) { if (save) { rs_trace("skip cleanup of %s", cleanups[i]); } else { /* Try removing it as a directory first, and * if that fails, try removing is as a file. * Report the error from removing-as-a-file * if both fail. */ if ((rmdir(cleanups[i]) == -1) && (unlink(cleanups[i]) == -1) && (errno != ENOENT)) { rs_log_notice("cleanup %s failed: %s", cleanups[i], strerror(errno)); } done++; } n_cleanups = i; if (from_signal_handler) { /* It's not safe to call free() in this case. * Don't worry about the memory leak - we're about * to exit the process anyway. */ } else { free(cleanups[i]); } cleanups[i] = NULL; } rs_trace("deleted %d temporary files", done); } /** * Add to the list of files to delete on exit. * If it runs out of memory, it returns non-zero. */ int dcc_add_cleanup(const char *filename) { char *new_filename; int new_n_cleanups = n_cleanups + 1; /* Increase the size of the cleanups array, if needed. * We avoid using realloc() here, to ensure that 'cleanups' remains * valid at all times - we might get a signal in the middle here * that could call dcc_cleanup_tempfiles_from_signal_handler(). */ if (new_n_cleanups > cleanups_size) { char **old_cleanups; int new_cleanups_size = (cleanups_size == 0 ? 10 : cleanups_size * 3); char **new_cleanups = malloc(new_cleanups_size * sizeof(char *)); if (new_cleanups == NULL) { rs_log_crit("malloc failed - too many cleanups"); return EXIT_OUT_OF_MEMORY; } memcpy(new_cleanups, (char **)cleanups, cleanups_size * sizeof(char *)); old_cleanups = (char **)cleanups; cleanups = new_cleanups; /* Atomic assignment. */ cleanups_size = new_cleanups_size; /* Atomic assignment. */ free(old_cleanups); } new_filename = strdup(filename); if (new_filename == NULL) { rs_log_crit("strdup failed - too many cleanups"); return EXIT_OUT_OF_MEMORY; } cleanups[new_n_cleanups - 1] = new_filename; /* Atomic assignment. */ n_cleanups = new_n_cleanups; /* Atomic assignment. */ return 0; } distcc-3.4/src/climasq.c000066400000000000000000000100211404653710500152140ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * And the magicians did so with their enchantments, * and brought up frogs upon the land of Egypt. * -- Exodus 8:7 */ #include #include #include #include #include #include #include "distcc.h" #include "util.h" #include "trace.h" #include "exitcode.h" /** * For masquerade mode, change the path to remove the directory containing the * distcc mask, so that invoking the same name will find the underlying * compiler instead. * * @param progname basename under which distcc was introduced. If we reached * this point, then it's the same as the name of the real compiler, e.g. "cc". * * @param did_masquerade specifies an integer that will be set to 1 if the * path was changed. * * @return 0 or standard error. **/ int dcc_support_masquerade(char *argv[], char *progname, int *did_masquerade) { const char *envpath, *findpath, *p, *n; char *buf; size_t len; size_t findlen; if (!(envpath = getenv("PATH"))) /* strange but true*/ return 0; if (!(buf = malloc(strlen(envpath)+1+strlen(progname)+1))) { rs_log_error("failed to allocate buffer for new PATH"); return EXIT_OUT_OF_MEMORY; } /* Filter PATH to contain only the part that is past our dir. * If we were called explicitly, find the named dir on the PATH. */ if (progname != argv[0]) { findpath = dcc_abspath(argv[0], progname - argv[0] - 1); findlen = strlen(findpath); } else { findpath = NULL; findlen = 0; } for (n = p = envpath; *n; p = n) { /* Find the length of this component of the path */ n = strchr(p, ':'); if (n) len = n++ - p; else { len = strlen(p); n = p + len; } if (findpath) { /* Looking for a component in the path equal to findpath */ /* FIXME: This won't catch paths that are in fact the same, but * that are not the same string. This might happen if you have * multiple slashes, or dots, or symlinks... */ if (len != findlen || strncmp(p, findpath, findlen) != 0) continue; } else { /* Looking for a component in the path containing a file * progname. */ /* FIXME: This gets a false match if you have a subdirectory that * happens to be of the right name, e.g. /usr/bin/distcc... */ strncpy(buf, p, (size_t) len); sprintf(buf + len, "/%s", progname); if (access(buf, X_OK) != 0) continue; } /* Set p to the part of the path past our match. */ p = n; break; } if (*p != '\0') { int ret = dcc_set_path(p); if (ret) { free(buf); return ret; } *did_masquerade = 1; } else { rs_trace("not modifying PATH"); *did_masquerade = 0; } free(buf); return 0; } distcc-3.4/src/clinet.c000066400000000000000000000137071404653710500150570ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* I just wish I could get caller-IQ on my phones... -- The Purple People-Eater, NANAE */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "clinet.h" #include "util.h" #include "netutil.h" #ifndef h_errno extern int h_errno; #endif const int dcc_connect_timeout = 4; /* seconds */ /* * Client-side networking. * * These are called with an alarm set so we get a single timeout over the * whole resolution and connection process. * * TODO: In error messages, show the name of the relevant host. * Should do this even in readx(), etc. * * TODO: After connecting, perhaps try to read 0 bytes to see if there's an * error. */ /* * Connect to a host given its binary address, with a timeout. * * host and port are only here to aid printing debug messages. */ int dcc_connect_by_addr(struct sockaddr *sa, size_t salen, int *p_fd) { int fd; int ret; char *s; int failed; int connecterr; int tries = 3; dcc_sockaddr_to_string(sa, salen, &s); if (s == NULL) return EXIT_OUT_OF_MEMORY; rs_trace("started connecting to %s", s); if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == -1) { rs_log_error("failed to create socket: %s", strerror(errno)); ret = EXIT_CONNECT_FAILED; goto out_failed; } dcc_set_nonblocking(fd); /* start the nonblocking connect... */ do failed = connect(fd, sa, salen); while (failed == -1 && (errno == EINTR || (errno == EAGAIN && tries-- && poll(NULL, 0, 500) == 0))); if (failed == -1 && errno != EINPROGRESS) { rs_log(RS_LOG_ERR|RS_LOG_NONAME, "failed to connect to %s: %s", s, strerror(errno)); ret = EXIT_CONNECT_FAILED; goto out_failed; } do { socklen_t len; if ((ret = dcc_select_for_write(fd, dcc_connect_timeout))) { rs_log(RS_LOG_ERR|RS_LOG_NONAME, "timeout while connecting to %s", s); goto out_failed; } connecterr = -1; len = sizeof(connecterr); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&connecterr, &len) < 0) { rs_log_error("getsockopt SO_ERROR failed?!"); ret = EXIT_CONNECT_FAILED; goto out_failed; } /* looping is unlikely, but I believe I needed this in dkftpbench */ /* fixme: should reduce timeout on each time around this loop */ } while (connecterr == EINPROGRESS); if (connecterr) { rs_log(RS_LOG_ERR|RS_LOG_NONAME, "nonblocking connect to %s failed: %s", s, strerror(connecterr)); ret = EXIT_CONNECT_FAILED; goto out_failed; } *p_fd = fd; free(s); return 0; out_failed: free(s); return ret; } #if defined(ENABLE_RFC2553) /** * Open a socket to a tcp remote host with the specified port. **/ int dcc_connect_by_name(const char *host, int port, int *p_fd) { struct addrinfo hints; struct addrinfo *res; int error; int ret; char portname[20]; rs_trace("connecting to %s port %d", host, port); /* Unfortunately for us, getaddrinfo wants the port (service) as a string */ snprintf(portname, sizeof portname, "%d", port); memset(&hints, 0, sizeof(hints)); /* set-up hints structure */ hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(host, portname, &hints, &res); if (error) { rs_log_error("failed to resolve host %s port %d: %s", host, port, gai_strerror(error)); return EXIT_CONNECT_FAILED; } /* Try each of the hosts possible addresses. */ do { ret = dcc_connect_by_addr(res->ai_addr, res->ai_addrlen, p_fd); } while (ret != 0 && (res = res->ai_next)); return ret; } #else /* not ENABLE_RFC2553 */ /** * Open a socket to a tcp remote host with the specified port. * * @todo Don't try for too long to connect. **/ int dcc_connect_by_name(const char *host, int port, int *p_fd) { struct sockaddr_in sock_out; struct hostent *hp; /* FIXME: "warning: gethostbyname() leaks memory. Use gethostbyname_r * instead!" (or indeed perhaps use getaddrinfo?) */ hp = gethostbyname(host); if (!hp) { rs_log_error("failed to look up host \"%s\": %s", host, hstrerror(h_errno)); return EXIT_CONNECT_FAILED; } memcpy(&sock_out.sin_addr, hp->h_addr, (size_t) hp->h_length); sock_out.sin_port = htons((in_port_t) port); sock_out.sin_family = PF_INET; return dcc_connect_by_addr((struct sockaddr *) &sock_out, sizeof sock_out, p_fd); } #endif /* not ENABLE_RFC2553 */ distcc-3.4/src/clinet.h000066400000000000000000000022731404653710500150600ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ struct sockaddr; int dcc_connect_by_name(const char *host, int port, int *p_fd); int dcc_connect_by_addr(struct sockaddr *sa, size_t salen, int *p_fd); distcc-3.4/src/clirpc.c000066400000000000000000000177521404653710500150610ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exec.h" #include "rpc.h" #include "exitcode.h" #include "util.h" #include "clinet.h" #include "bulk.h" #include "hosts.h" #include "state.h" #include "include_server_if.h" #include "emaillog.h" /** * @file * * @brief Client-side RPC functions. **/ /* * Transmit header for whole request. */ int dcc_x_req_header(int fd, enum dcc_protover protover) { return dcc_x_token_int(fd, "DIST", protover); } /** * Transmit an argv-type array. **/ int dcc_x_argv(int fd, const char *argc_token, const char *argv_token, char **argv) { int i; int ret; int argc; argc = dcc_argv_len(argv); if (dcc_x_token_int(fd, argc_token, (unsigned) argc)) return EXIT_PROTOCOL_ERROR; for (i = 0; i < argc; i++) { if ((ret = dcc_x_token_string(fd, argv_token, argv[i]))) return ret; } return 0; } /** * Transmit the current working directory */ int dcc_x_cwd(int fd) { int ret; char cwd[MAXPATHLEN + 1]; char * cwd_ret; cwd_ret = getcwd(cwd, MAXPATHLEN); if (cwd_ret == NULL) { return 0; } ret = dcc_x_token_string(fd, "CDIR", cwd); return ret; } /** * Read the "DONE" token from the network that introduces a response. **/ int dcc_r_result_header(int ifd, enum dcc_protover expect_ver) { unsigned vers; int ret; if ((ret = dcc_r_token_int(ifd, "DONE", &vers))) { rs_log_error("server provided no answer. " "Is the server configured to allow access from your IP" " address? Is the server performing authentication and" " your client isn't? Does the server have the compiler" " installed? Is the server configured to access the" " compiler?"); return ret; } if (vers != expect_ver) { rs_log_error("got version %d not %d in response from server", vers, expect_ver); return EXIT_PROTOCOL_ERROR; } rs_trace("got response header"); return 0; } int dcc_r_cc_status(int ifd, int *status) { unsigned u_status; int ret; ret = dcc_r_token_int(ifd, "STAT", &u_status); *status = u_status; return ret; } /** * The second half of the client protocol: retrieve all results from the server. **/ int dcc_retrieve_results(int net_fd, int *status, const char *output_fname, const char *deps_fname, const char *server_stderr_fname, struct dcc_hostdef *host) { unsigned len; int ret; unsigned o_len; if ((ret = dcc_r_result_header(net_fd, host->protover))) return ret; /* We've started to see the response, so the server is done * compiling. */ dcc_note_state(DCC_PHASE_RECEIVE, NULL, NULL, DCC_REMOTE); if ((ret = dcc_r_cc_status(net_fd, status))) return ret; if ((ret = dcc_r_token_int(net_fd, "SERR", &len))) return ret; /* Save the server-side errors into a file. This way, we can decide later whether we want to report them to the user or not. We don't want to report them to the user if we are going to redo the compilation locally, because then the local errors are going to appear. Always put the server-side errors in the email we will send to the maintainers, though. */ if ((ret = dcc_r_file(net_fd, server_stderr_fname, len, host->compr))) return ret; if (dcc_add_file_to_log_email("server-side stderr", server_stderr_fname)) return ret; if ((ret = dcc_r_token_int(net_fd, "SOUT", &len)) || (ret = dcc_r_bulk(STDOUT_FILENO, net_fd, len, host->compr)) || (ret = dcc_r_token_int(net_fd, "DOTO", &o_len))) return ret; /* If the compiler succeeded, then we always retrieve the result, * even if it's 0 bytes. */ if (*status == 0) { if ((ret = dcc_r_file_timed(net_fd, output_fname, o_len, host->compr))) return ret; if (host->cpp_where == DCC_CPP_ON_SERVER) { if ((ret = dcc_r_token_int(net_fd, "DOTD", &len) == 0) && deps_fname != NULL) { ret = dcc_r_file_timed(net_fd, deps_fname, len, host->compr); return ret; } } } else if (o_len != 0) { rs_log_error("remote compiler failed but also returned output: " "I don't know what to do"); } return 0; } /* points_to must be at least MAXPATHLEN + 1 long */ int dcc_read_link(const char* fname, char *points_to) { int len; if ((len = readlink(fname, points_to, MAXPATHLEN)) == -1) { rs_log_error("readlink '%s' failed: %s", fname, strerror(errno)); return EXIT_IO_ERROR; } points_to[len] = '\0'; return 0; } int dcc_is_link(const char *fname, int *is_link) { struct stat buf; if (lstat(fname, &buf) == -1) { rs_log_error("stat '%s' failed: %s", fname, strerror(errno)); return EXIT_IO_ERROR; } *is_link = S_ISLNK(buf.st_mode); return 0; } /* Send to @p ofd @p n_files whose names are in @p fnames. * @fnames must be null-terminated. * The names can be coming from the include server, so * we consult dcc_get_original_fname to get the real names. * Always uses lzo compression. */ /* TODO: This code is highly specific to DCC_VER_3; it assumes lzo compression is on, and that the include server has actually compressed the files. */ int dcc_x_many_files(int ofd, unsigned int n_files, char **fnames) { int ret; char link_points_to[MAXPATHLEN + 1]; int is_link; const char *fname; char *original_fname; dcc_x_token_int(ofd, "NFIL", n_files); for (; *fnames != NULL; ++fnames) { fname = *fnames; ret = dcc_get_original_fname(fname, &original_fname); if (ret) return ret; if ((ret = dcc_is_link(fname, &is_link))) { return ret; } if (is_link) { if ((ret = dcc_read_link(fname, link_points_to)) || (ret = dcc_x_token_string(ofd, "NAME", original_fname)) || (ret = dcc_x_token_string(ofd, "LINK", link_points_to))) { return ret; } } else { ret = dcc_x_token_string(ofd, "NAME", original_fname); if (ret) return ret; /* File should be compressed already. If we ever support non-compressed server-side-cpp, we should have some checks here and then uncompress the file if it is compressed. */ ret = dcc_x_file(ofd, fname, "FILE", DCC_COMPRESS_NONE, NULL); if (ret) return ret; } } return 0; } distcc-3.4/src/compile.c000066400000000000000000001071161404653710500152270ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_FNMATCH_H #include #endif #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "hosts.h" #include "bulk.h" #include "implicit.h" #include "exec.h" #include "where.h" #include "lock.h" #include "timeval.h" #include "compile.h" #include "include_server_if.h" #include "emaillog.h" #include "dotd.h" /** * This boolean is true iff --scan-includes option is enabled. * If so, distcc will just run the source file through the include server, * and print out the list of header files that might be #included, * rather than actually compiling the sources. */ int dcc_scan_includes = 0; static const char *const include_server_port_suffix = "/socket"; static const char *const discrepancy_suffix = "/discrepancy_counter"; static void bad_host(struct dcc_hostdef *host, int *cpu_lock_fd , int *local_cpu_lock_fd) { if (host) dcc_disliked_host(host); if (*cpu_lock_fd != -1) { dcc_unlock(*cpu_lock_fd); *cpu_lock_fd = -1; } if (*local_cpu_lock_fd != -1) { dcc_unlock(*local_cpu_lock_fd); *local_cpu_lock_fd = -1; } } static int dcc_get_max_discrepancies_before_demotion(void) { /* Warning: the default setting here should have the same value as in the * pump.in script! */ static const int default_setting = 1; static int current_setting = 0; if (current_setting > 0) return current_setting; const char *user_setting = getenv("DISTCC_MAX_DISCREPANCY"); if (user_setting) { int parsed_user_setting = atoi(user_setting); if (parsed_user_setting <= 0) { rs_log_error("Bad DISTCC_MAX_DISCREPANCY value: %s", user_setting); exit(EXIT_BAD_ARGUMENTS); } current_setting = parsed_user_setting; } else { current_setting = default_setting; } return current_setting; } /** * Return in @param filename the name of the file we use as unary counter of * discrepancies (a compilation failing on the server, but succeeding * locally. This function may return NULL in @param filename if the name cannot * be determined. **/ int dcc_discrepancy_filename(char **filename) { const char *include_server_port = getenv("INCLUDE_SERVER_PORT"); *filename = NULL; if (include_server_port == NULL) { return 0; } else if (str_endswith(include_server_port_suffix, include_server_port)) { /* We're going to make a longer string from include_server_port: one * that replaces include_server_port_suffix with discrepancy_suffix. */ int delta = strlen(discrepancy_suffix) - strlen(include_server_port_suffix); assert (delta > 0); *filename = malloc(strlen(include_server_port) + 1 + delta); if (!*filename) { rs_log_error("failed to allocate space for filename"); return EXIT_OUT_OF_MEMORY; } strcpy(*filename, include_server_port); int slash_pos = strlen(include_server_port) - strlen(include_server_port_suffix); /* Because include_server_port_suffix is a suffix of include_server_port * we expect to find a '/' at slash_pos in filename. */ assert((*filename)[slash_pos] == '/'); (void) strcpy(*filename + slash_pos, discrepancy_suffix); return 0; } else return 0; } /** * Return the length of the @param discrepancy_filename in newly allocated * memory; return 0 if it's not possible to determine the length (if * e.g. @param discrepancy_filename is NULL). **/ static int dcc_read_number_discrepancies(const char *discrepancy_filename) { if (!discrepancy_filename) return 0; struct stat stat_record; if (stat(discrepancy_filename, &stat_record) == 0) { size_t size = stat_record.st_size; /* Does size fit in an 'int'? */ if ((((size_t) (int) size) == size) && ((int) size) > 0) return ((int) size); else return INT_MAX; } else return 0; } /** * Lengthen the file whose name is @param discrepancy_filename by one byte. Or, * do nothing, if @param discrepancy_filename is NULL. **/ static int dcc_note_discrepancy(const char *discrepancy_filename) { FILE *discrepancy_file; if (!discrepancy_filename) return 0; if (!(discrepancy_file = fopen(discrepancy_filename, "a"))) { rs_log_error("failed to open discrepancy_filename file: %s: %s", discrepancy_filename, strerror(errno)); return EXIT_IO_ERROR; } if (fputc('@', discrepancy_file) == EOF) { rs_log_error("failed to write to discrepancy_filename file: %s", discrepancy_filename); fclose(discrepancy_file); return EXIT_IO_ERROR; } /* The file position is a property of the stream, so we are assured that exactly one process will take the 'if' branch when max_discrepancies_before_demotion failures is reached. */ if (ftell(discrepancy_file) == (long int)dcc_get_max_discrepancies_before_demotion()) { rs_log_warning("now using plain distcc, possibly due to " "inconsistent file system changes during build"); } fclose(discrepancy_file); return 0; } /** * In some cases, it is ill-advised to preprocess on the server. Check for such * situations. If they occur, then change protocol version. **/ static void dcc_perhaps_adjust_cpp_where_and_protover( char *input_fname, struct dcc_hostdef *host, char *discrepancy_filename) { /* It's unfortunate that the variable that controls preprocessing is in the "host" datastructure. See elaborate complaint in dcc_build_somewhere. */ /* Check whether there has been too much trouble running distcc-pump during this build. */ if (dcc_read_number_discrepancies(discrepancy_filename) >= dcc_get_max_discrepancies_before_demotion()) { /* Give up on using distcc-pump */ host->cpp_where = DCC_CPP_ON_CLIENT; dcc_get_protover_from_features(host->compr, host->cpp_where, &host->protover); } /* Don't do anything silly for already preprocessed files. */ if (dcc_is_preprocessed(input_fname)) { /* Don't subject input file to include analysis. */ rs_log_warning("cannot use distcc_pump on already preprocessed file" " (such as emitted by ccache)"); host->cpp_where = DCC_CPP_ON_CLIENT; dcc_get_protover_from_features(host->compr, host->cpp_where, &host->protover); } /* Environment variables CPATH and two friends are hidden ways of passing * -I's. Beware! */ if (getenv("CPATH") || getenv("C_INCLUDE_PATH") || getenv("CPLUS_INCLUDE_PATH")) { rs_log_warning("cannot use distcc_pump with any of environment" " variables CPATH, C_INCLUDE_PATH or CPLUS_INCLUDE_PATH" " set, preprocessing locally"); host->cpp_where = DCC_CPP_ON_CLIENT; dcc_get_protover_from_features(host->compr, host->cpp_where, &host->protover); } } /** * Do a time analysis of dependencies in dotd file. First, if @param dotd_fname * is created before @param reference_time, then return NULL in result. Second, * if one of the files mentioned in the @param dotd_fname is modified after time * @param reference_time, then return non-NULL in result. Otherwise return NULL * in result. A non-NULL value in result is a pointer to a newly allocated * string describing the offending dependency. * If @param exclude_pattern is not NULL, then files matching the glob @param * exclude_pattern are not considered in the above comparison. * * This function is not declared static --- for purposes of testing. **/ int dcc_fresh_dependency_exists(const char *dotd_fname, const char *exclude_pattern, time_t reference_time, char **result) { struct stat stat_dotd; off_t dotd_fname_size = 0; FILE *fp; int c; int res; char *dep_name; *result = NULL; /* Allocate buffer for dotd contents and open it. */ res = stat(dotd_fname, &stat_dotd); if (res) { rs_trace("could not stat \"%s\": %s", dotd_fname, strerror(errno)); return 0; } if (stat_dotd.st_mtime < reference_time) { /* That .d file appears to be too old; don't trust it for this * analysis. */ rs_trace("old dotd file \"%s\"", dotd_fname); return 0; } dotd_fname_size = stat_dotd.st_size; /* Is dotd_fname_size representable as a size_t value ? */ if ((off_t) (size_t) dotd_fname_size == dotd_fname_size) { dep_name = malloc((size_t) dotd_fname_size); if (!dep_name) { rs_log_error("failed to allocate space for dotd file"); return EXIT_OUT_OF_MEMORY; } } else { /* This is exceedingly unlikely. */ rs_trace("file \"%s\" is too big", dotd_fname); return 0; } if ((fp = fopen(dotd_fname, "r")) == NULL) { rs_trace("could not open \"%s\": %s", dotd_fname, strerror(errno)); free(dep_name); return 0; } /* Find ':'. */ while ((c = getc(fp)) != EOF && c != ':'); if (c != ':') goto return_0; /* Process dependencies. */ while (c != EOF) { struct stat stat_dep; int i = 0; /* Skip whitespaces and backslashes. */ while ((c = getc(fp)) != EOF && (isspace(c) || c == '\\')); /* Now, we're at start of file name. */ ungetc(c, fp); while ((c = getc(fp)) != EOF && (!isspace(c) || c == '\\')) { if (i >= dotd_fname_size) { /* Impossible */ rs_log_error("not enough room for dependency name"); goto return_0; } if (c == '\\') { /* Skip the newline. */ if ((c = getc(fp)) != EOF) if (c != '\n') ungetc(c, fp); } else dep_name[i++] = c; } if (i != 0) { dep_name[i] = '\0'; #ifdef HAVE_FNMATCH_H if (exclude_pattern == NULL || fnmatch(exclude_pattern, dep_name, 0) == FNM_NOMATCH) { #else /* Tautology avoids compiler warning about unused variable. */ if (exclude_pattern == exclude_pattern) { #endif /* The dep_name is not excluded; now verify that it is not too * young. */ rs_log_info("Checking dependency: %s", dep_name); res = stat(dep_name, &stat_dep); if (res) goto return_0; if (stat_dep.st_ctime >= reference_time) { fclose(fp); *result = realloc(dep_name, strlen(dep_name) + 1); if (*result == NULL) { rs_log_error("realloc failed"); return EXIT_OUT_OF_MEMORY; } return 0; } } } } return_0: fclose(fp); free(dep_name); return 0; } /** * Invoke a compiler locally. This is, obviously, the alternative to * dcc_compile_remote(). * * The server does basically the same thing, but it doesn't call this * routine because it wants to overlap execution of the compiler with * copying the input from the network. * * This routine used to exec() the compiler in place of distcc. That * is slightly more efficient, because it avoids the need to create, * schedule, etc another process. The problem is that in that case we * can't clean up our temporary files, and (not so important) we can't * log our resource usage. * * This is called with a lock on localhost already held. **/ static int dcc_compile_local(char *argv[], char *input_name) { pid_t pid; int ret; int status; dcc_note_execution(dcc_hostdef_local, argv); dcc_note_state(DCC_PHASE_COMPILE, input_name, "localhost", DCC_LOCAL); /* We don't do any redirection of file descriptors when running locally, * so if for example cpp is being used in a pipeline we should be fine. */ if ((ret = dcc_spawn_child(argv, &pid, NULL, NULL, NULL)) != 0) return ret; if ((ret = dcc_collect_child("cc", pid, &status, timeout_null_fd))) return ret; return dcc_critique_status(status, "compile", input_name, dcc_hostdef_local, 1); } /* Make the decision to send email about @param input_name, but only after a * little further investgation. * * We avoid sending email if there's a fresh dependency. To find out, we need * @param deps_fname, a .d file, created during the build. We check each * dependency described there. If just one changed after the build started, * then we really don't want to hear about distcc-pump errors, because * dependencies shouldn't change. The files generated during the build are * exceptions. To disregard these, the distcc user may specify a glob pattern * in environment variable DISTCC_EXCLUDE_FRESH_FILES. * * Also, if there has been too many discrepancies (where the build has * succeeded remotely but failed locally), then we need to stop using * distcc-pump for the remainder of the build. The present function * contributes to this logic: if it is determined that email must be sent, then * the count of such situations is incremented using the file @param * discrepancy_filename. */ static int dcc_please_send_email_after_investigation( const char *input_fname, const char *deps_fname, const char *discrepancy_filename) { int ret; char *fresh_dependency; const char *include_server_port = getenv("INCLUDE_SERVER_PORT"); struct stat stat_port; rs_log_warning("remote compilation of '%s' failed, retried locally " "and got a different result.", input_fname); if ((include_server_port != NULL) && (stat(include_server_port, &stat_port)) == 0) { time_t build_start = stat_port.st_ctime; if (deps_fname) { const char *exclude_pattern = getenv("DISTCC_EXCLUDE_FRESH_FILES"); if ((ret = dcc_fresh_dependency_exists(deps_fname, exclude_pattern, build_start, &fresh_dependency))) { return ret; } if (fresh_dependency) { rs_log_warning("file '%s', a dependency of %s, " "changed during the build", fresh_dependency, input_fname); free(fresh_dependency); return dcc_note_discrepancy(discrepancy_filename); } } } dcc_please_send_email(); return dcc_note_discrepancy(discrepancy_filename); } #ifdef HAVE_FSTATAT /* Re-write "cc" to directly call gcc or clang */ static void dcc_rewrite_generic_compiler(char **argv) { char linkbuf[MAXPATHLEN + 1], *link = NULL, *t; int ret, dir; ssize_t ssz; struct stat st; bool cpp = false; assert(argv); if (strcmp(argv[0], "cc") == 0) ; else if (strcmp(argv[0], "c++") == 0) cpp = true; else return; ret = dcc_which(cpp ? "c++" : "cc", &link); if (ret < 0) return; t = strrchr(link, '/'); if (!t) return; *t = '\0'; dir = open(link, O_RDONLY); if (dir < 0) return; *t = '/'; ret = fstatat(dir, t + 1, &st, AT_SYMLINK_NOFOLLOW); if (ret < 0) return; if ((st.st_mode & S_IFMT) != S_IFLNK) /* TODO use cc -v */ return; ssz = readlinkat(dir, t + 1, linkbuf, sizeof(linkbuf) - 1); if (ssz < 0) return; linkbuf[ssz] = '\0'; fstatat(dir, linkbuf, &st, AT_SYMLINK_NOFOLLOW); if ((st.st_mode & S_IFMT) == S_IFLNK) { /* this is a Debian thing. Fedora just has /usr/bin/cc -> gcc */ if (strcmp(linkbuf, cpp ? "/etc/alternatives/c++" : "/etc/alternatives/cc") == 0) { char m[MAXPATHLEN + 1]; m[0] = '\0'; strcpy(m, linkbuf); ssz = readlinkat(dir, m, linkbuf, sizeof(linkbuf) - 1); linkbuf[ssz] = '\0'; } } ret = faccessat(dir, linkbuf, X_OK, 0); if (ret < 0) return; if ( cpp && strcmp(strrchr(linkbuf, '/') ? strrchr(linkbuf, '/') + 1 : linkbuf, "clang++") == 0) { free(argv[0]); argv[0] = strdup("clang++"); rs_trace("Rewriting '%s' to '%s'", "c++", "clang++"); } else if ( cpp && strcmp(strrchr(linkbuf, '/') ? strrchr(linkbuf, '/') + 1 : linkbuf, "g++") == 0) { free(argv[0]); argv[0] = strdup("g++"); rs_trace("Rewriting '%s' to '%s'", "c++", "g++"); } else if (!cpp && strcmp(strrchr(linkbuf, '/') ? strrchr(linkbuf, '/') + 1 : linkbuf, "clang") == 0) { free(argv[0]); argv[0] = strdup("clang"); rs_trace("Rewriting '%s' to '%s'", "cc", "clang"); } else if (!cpp && strcmp(strrchr(linkbuf, '/') ? strrchr(linkbuf, '/') + 1 : linkbuf, "gcc") == 0) { free(argv[0]); argv[0] = strdup("gcc"); rs_trace("Rewriting '%s' to '%s'", "cc", "gcc"); } else return; } #endif /* Clang is a native cross-compiler, but needs to be told to what target it is * building. * TODO: actually probe clang with clang --version, instead of trusting * autoheader. */ static void dcc_add_clang_target(char **argv) { /* defined by autoheader */ const char *target = GNU_HOST; if (strcmp(argv[0], "clang") == 0 || strncmp(argv[0], "clang-", strlen("clang-")) == 0 || strcmp(argv[0], "clang++") == 0 || strncmp(argv[0], "clang++-", strlen("clang++-")) == 0) ; else return; if (dcc_argv_search(argv, "-target")) return; rs_log_info("Adding '-target %s' to support clang cross-compilation.", target); dcc_argv_append(argv, strdup("-target")); dcc_argv_append(argv, strdup(target)); } /* * Cross compilation for gcc */ static int dcc_gcc_rewrite_fqn(char **argv) { /* defined by autoheader */ const char *target_with_vendor = GNU_HOST; char *newcmd, *t, *path; int pathlen = 0; int newcmd_len = 0; if (strcmp(argv[0], "gcc") == 0 || strncmp(argv[0], "gcc-", strlen("gcc-")) == 0 || strcmp(argv[0], "g++") == 0 || strncmp(argv[0], "g++-", strlen("g++-")) == 0) ; else return -ENOENT; newcmd_len = strlen(target_with_vendor) + 1 + strlen(argv[0] + 1); newcmd = malloc(newcmd_len); if (!newcmd) return -ENOMEM; memset(newcmd, 0, newcmd_len); if ((t = strstr(target_with_vendor, "-pc-"))) { memcpy(newcmd, target_with_vendor, t - target_with_vendor); strcat(newcmd, t + strlen("-pc")); } else strcpy(newcmd, target_with_vendor); strcat(newcmd, "-"); strcat(newcmd, argv[0]); /* TODO, is this the right PATH? */ path = getenv("PATH"); do { char binname[strlen(path) + 1 + strlen(newcmd) + 1]; int r; /* emulate strchrnul() */ t = strchr(path, ':'); if (!t) t = path + strlen(path); pathlen = t - path; if (*path == '\0') break; strncpy(binname, path, pathlen); binname[pathlen] = '\0'; strcat(binname, "/"); strcat(binname, newcmd); r = access(binname, X_OK); if (r < 0) continue; /* good!, now rewrite */ rs_log_info("Re-writing call to '%s' to '%s' to support cross-compilation.", argv[0], newcmd); free(argv[0]); argv[0] = newcmd; return 0; } while ((path += pathlen + 1)); free(newcmd); return -ENOENT; } /** * Execute the commands in argv remotely or locally as appropriate. * * We may need to run cpp locally; we can do that in the background * while trying to open a remote connection. * * This function is slightly inefficient when it falls back to running * gcc locally, because cpp may be run twice. Perhaps we could adjust * the command line to pass in the .i file. On the other hand, if * something has gone wrong, we should probably take the most * conservative course and run the command unaltered. It should not * be a big performance problem because this should occur only rarely. * * @param argv Command to execute. Does not include 0='distcc'. * Must be dynamically allocated. This routine deallocates it. * * @param status On return, contains the waitstatus of the compiler or * preprocessor. This function can succeed (in running the compiler) even if * the compiler itself fails. If either the compiler or preprocessor fails, * @p status is guaranteed to hold a failure value. * * Implementation notes: * * This code might be simpler if we would only acquire one lock * at a time. But we need to choose the server host in order * to determine whether it supports pump mode or not, * and choosing the server host requires acquiring its lock * (otherwise it might be busy when we we try to acquire it). * So if the server chosen is not localhost, we need to hold the * remote host lock while we're doing local preprocessing or include * scanning. Since local preprocessing/include scanning requires * us to acquire the local cpu lock, that means we need to hold two * locks at one time. * * TODO: make pump mode a global flag, and drop support for * building with cpp mode on some hosts and not on others. * Then change the code so that we only choose the remote * host after local preprocessing/include scanning is finished * and the local cpu lock is released. */ static int dcc_build_somewhere(char *argv[], int sg_level, int *status) { char *input_fname = NULL, *output_fname, *cpp_fname, *deps_fname = NULL; char **files; char **server_side_argv = NULL; int server_side_argv_deep_copied = 0; char *server_stderr_fname = NULL; int needs_dotd = 0; int sets_dotd_target = 0; pid_t cpp_pid = 0; int cpu_lock_fd = -1, local_cpu_lock_fd = -1; int ret; int remote_ret = 0; struct dcc_hostdef *host = NULL; char *discrepancy_filename = NULL; char **new_argv; if ((ret = dcc_expand_preprocessor_options(&argv)) != 0) goto clean_up; if ((ret = dcc_discrepancy_filename(&discrepancy_filename))) goto clean_up; if (sg_level) /* Recursive distcc - run locally, and skip all locking. */ goto run_local; /* TODO: Perhaps tidy up these gotos. */ /* FIXME: this may leak memory for argv. */ ret = dcc_scan_args(argv, &input_fname, &output_fname, &new_argv); dcc_free_argv(argv); argv = new_argv; if (!getenv("DISTCC_NO_REWRITE_CROSS")) { #ifdef HAVE_FSTATAT dcc_rewrite_generic_compiler(new_argv); #endif dcc_add_clang_target(new_argv); dcc_gcc_rewrite_fqn(new_argv); } if (ret != 0) { /* we need to scan the arguments even if we already know it's * local, so that we can pick up distcc client options. */ goto lock_local; } #if 0 /* turned off because we never spend long in this state. */ dcc_note_state(DCC_PHASE_STARTUP, input_fname, NULL); #endif if ((ret = dcc_make_tmpnam("distcc_server_stderr", ".txt", &server_stderr_fname))) { /* So we are failing locally to make a temp file to store the * server-side errors in; it's unlikely anything else will * work, but let's try the compilation locally. * FIXME: this will blame the server for a failure that is * local. However, we don't make any distrinction between * all the reasons dcc_compile_remote can fail either; * and some of those reasons are local. */ goto fallback; } /* Lock ordering invariant: always acquire the lock for the * remote host (if any) first. */ /* Choose the distcc server host (which could be either a remote * host or localhost) and acquire the lock for it. */ choose_host: if ((ret = dcc_pick_host_from_list_and_lock_it(&host, &cpu_lock_fd)) != 0) { /* Doesn't happen at the moment: all failures are masked by returning localhost. */ goto fallback; } if (host->mode == DCC_MODE_LOCAL) { /* We picked localhost and already have a lock on it so no * need to lock it now. */ goto run_local; } if (!dcc_is_preprocessed(input_fname)) { /* Lock the local CPU, since we're going to be doing preprocessing * or include scanning. */ if ((ret = dcc_lock_local_cpp(&local_cpu_lock_fd)) != 0) { goto fallback; } } if (host->cpp_where == DCC_CPP_ON_SERVER) { /* Perhaps it is not a good idea to preprocess on the server. */ dcc_perhaps_adjust_cpp_where_and_protover(input_fname, host, discrepancy_filename); } if (dcc_scan_includes) { ret = dcc_approximate_includes(host, argv); goto unlock_and_clean_up; } if (host->cpp_where == DCC_CPP_ON_SERVER) { if ((ret = dcc_talk_to_include_server(argv, &files))) { /* Fallback to doing cpp locally */ /* It's unfortunate that the variable that controls that is in the * "host" datastructure, even though in this case it's the client * that fails to support it, but "host" is what gets passed * around in the client code. We are, in essence, throwing away * the host's capability to do cpp, so if this code was to execute * again (it won't, not in the same process) we wouldn't know if * the server supports it or not. */ rs_log_warning("failed to get includes from include server, " "preprocessing locally"); if (dcc_getenv_bool("DISTCC_TESTING_INCLUDE_SERVER", 0)) dcc_exit(ret); host->cpp_where = DCC_CPP_ON_CLIENT; dcc_get_protover_from_features(host->compr, host->cpp_where, &host->protover); } else if (local_cpu_lock_fd != -1) { /* Include server succeeded. */ /* We're done with local "preprocessing" (include scanning). */ dcc_unlock(local_cpu_lock_fd); /* Don't try to unlock again in dcc_compile_remote. */ local_cpu_lock_fd = -1; } } if (host->cpp_where == DCC_CPP_ON_CLIENT) { files = NULL; if ((ret = dcc_cpp_maybe(argv, input_fname, &cpp_fname, &cpp_pid) != 0)) goto fallback; if ((ret = dcc_strip_local_args(argv, &server_side_argv))) goto fallback; } else { char *dotd_target = NULL; cpp_fname = NULL; cpp_pid = 0; dcc_get_dotd_info(argv, &deps_fname, &needs_dotd, &sets_dotd_target, &dotd_target); server_side_argv_deep_copied = 1; if ((ret = dcc_copy_argv(argv, &server_side_argv, 2))) goto fallback; if (needs_dotd && !sets_dotd_target) { dcc_argv_append(server_side_argv, strdup("-MT")); if (dotd_target == NULL) dcc_argv_append(server_side_argv, strdup(output_fname)); else dcc_argv_append(server_side_argv, strdup(dotd_target)); } } if ((ret = dcc_compile_remote(server_side_argv, input_fname, cpp_fname, files, output_fname, needs_dotd ? deps_fname : NULL, server_stderr_fname, cpp_pid, local_cpu_lock_fd, host, status)) != 0) { /* Returns zero if we successfully ran the compiler, even if * the compiler itself bombed out. */ /* dcc_compile_remote() already unlocked local_cpu_lock_fd. */ local_cpu_lock_fd = -1; bad_host(host, &cpu_lock_fd, &local_cpu_lock_fd); goto choose_host; } /* dcc_compile_remote() already unlocked local_cpu_lock_fd. */ local_cpu_lock_fd = -1; dcc_enjoyed_host(host); dcc_unlock(cpu_lock_fd); cpu_lock_fd = -1; ret = dcc_critique_status(*status, "compile", input_fname, host, 1); if (ret == 0) { /* Try to copy the server-side errors on stderr. * If that fails, even though the compilation succeeded, * we haven't managed to give these errors to the user, * so we have to try again. * FIXME: Just like in the attempt to make a temporary file, this * is unlikely to fail, if it does it's unlikely any other * operation will work, and this makes the mistake of * blaming the server for what is (clearly?) a local failure. */ if ((dcc_copy_file_to_fd(server_stderr_fname, STDERR_FILENO))) { rs_log_warning("Could not show server-side errors"); goto fallback; } /* SUCCESS! */ goto clean_up; } if (ret < 128) { /* Remote compile just failed, e.g. with syntax error. It may be that the remote compilation failed because the file has an error, or because we did something wrong (e.g. we did not send all the necessary files.) Retry locally. If the local compilation also fails, then we know it's the program that has the error, and it doesn't really matter that we recompile, because this is rare. If the local compilation succeeds, then we know it's our fault, and we should do something about it later. (Currently, we send email to an appropriate email address). */ if (getenv("DISTCC_SKIP_LOCAL_RETRY")) { /* don't retry locally. We'll treat the remote failure as if it was a local one. But if we can't get the failures then we need to retry regardless. */ if ((dcc_copy_file_to_fd(server_stderr_fname, STDERR_FILENO))) { rs_log_warning("remote compilation of '%s' failed",\ input_fname); rs_log_warning("Could not show server-side errors, retrying locally"); goto fallback; } /* Not retrying */ goto clean_up; } else { rs_log_warning("remote compilation of '%s' failed, retrying locally", input_fname); remote_ret = ret; goto fallback; } } fallback: bad_host(host, &cpu_lock_fd, &local_cpu_lock_fd); if (!dcc_getenv_bool("DISTCC_FALLBACK", 1)) { rs_log_error("failed to distribute and fallbacks are disabled"); /* Try copying any server-side error message to stderr; * If we fail the user will miss all the messages from the server; so * we pretend we failed remotely. */ if ((dcc_copy_file_to_fd(server_stderr_fname, STDERR_FILENO))) { rs_log_error("Could not print error messages from '%s'", server_stderr_fname); } goto clean_up; } /* At this point, we can abandon the remote errors. */ /* "You guys are so lazy! Do I have to do all the work myself??" */ if (host) { rs_log(RS_LOG_WARNING|RS_LOG_NONAME, "failed to distribute %s to %s, running locally instead", input_fname ? input_fname : "(unknown)", host->hostdef_string); } else { rs_log_warning("failed to distribute, running locally instead"); } lock_local: dcc_read_localslots_configuration(); if (ret == EXIT_LOCAL_CPP) { dcc_lock_local_cpp(&local_cpu_lock_fd); } else { dcc_lock_local(&cpu_lock_fd); } run_local: /* Either compile locally, after remote failure, or simply do other cc tasks as assembling, linking, etc. */ ret = dcc_compile_local(argv, input_fname); if (remote_ret != 0) { if (remote_ret != ret) { /* Oops! it seems what we did remotely is not the same as what we did locally. We normally send email in such situations (if emailing is enabled), but we attempt an a time analysis of source files in order to avoid doing so in case source files we changed during the build. */ (void) dcc_please_send_email_after_investigation( input_fname, deps_fname, discrepancy_filename); } else if (host) { /* Remote compilation failed, but we failed to compile this file too. * Don't punish that server, it's innocent. */ dcc_enjoyed_host(host); } } unlock_and_clean_up: if (cpu_lock_fd != -1) { dcc_unlock(cpu_lock_fd); cpu_lock_fd = -1; /* Not really needed, just for consistency. */ } /* For the --scan_includes case. */ if (local_cpu_lock_fd != -1) { dcc_unlock(local_cpu_lock_fd); local_cpu_lock_fd = -1; /* Not really needed, just for consistency. */ } clean_up: dcc_free_argv(argv); if (server_side_argv_deep_copied) { if (server_side_argv != NULL) { dcc_free_argv(server_side_argv); } } else { free(server_side_argv); } free(discrepancy_filename); return ret; } /* * argv must be dynamically allocated. * This routine will deallocate it. */ int dcc_build_somewhere_timed(char *argv[], int sg_level, int *status) { struct timeval before, after, delta; int ret; if (gettimeofday(&before, NULL)) rs_log_warning("gettimeofday failed"); ret = dcc_build_somewhere(argv, sg_level, status); if (gettimeofday(&after, NULL)) { rs_log_warning("gettimeofday failed"); } else { /* TODO: Show rate based on cpp size? Is that meaningful? */ timeval_subtract(&delta, &after, &before); rs_log(RS_LOG_INFO|RS_LOG_NONAME, "elapsed compilation time %lld.%06lds", (long long) delta.tv_sec, (long) delta.tv_usec); } return ret; } distcc-3.4/src/compile.h000066400000000000000000000036221404653710500152310ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* remote.c */ int dcc_compile_remote(char **argv, char *input_fname, char *cpp_fname, char **file_names, char *output_fname, char *deps_fname, char *server_stderr_fname, pid_t cpp_pid, int local_cpu_lock_fd, struct dcc_hostdef *host, int *status); /* compile.c */ extern int dcc_scan_includes; int dcc_build_somewhere_timed(char *argv[], int sg_level, int *status); /* Declared here for testing purposes. */ int dcc_fresh_dependency_exists(const char *dotd_fname, const char *exlude_pat, time_t reference_time, char **fresh_dependency); int dcc_discrepancy_filename(char **filename); distcc-3.4/src/compress.c000066400000000000000000000173521404653710500154340ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* I think that I can safely speak for the * whole troll community when I say "I like * watching train wrecks". -- AC */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_MMAN_H # include #endif #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "minilzo.h" static char work_mem[LZO1X_1_MEM_COMPRESS]; /** * @file * * Compressed bulk data transfer for distcc. * * lzo doesn't have any detectable magic at the start in the raw form. (lzop * the command-line tool adds some.) Therefore we indicate in the request * header (the protocol version) whether compression is on or off. If it is * on, all bulk data in both directions is compressed. metadata whether the * transfer is compressed or not. * * It might be nice to unify this code with that in pump.c, which deals with * uncompressed files. There are some parallels between the routines. * However the details are rather different, because with compressed files we * do not know ahead of time how big the expanded form will be. This affects * sending, where we need to make a large-enough temporary buffer to compress * into. It also affects receipt, where we need to allow extra space for data * coming in. So for the moment they remain separate. * * We used to use mmap here, but it complicated the code (and caused a bug in * 2.14) without being clearly any faster. So it's out again. * * The chunk header gives the number of compressed bytes. The number of * plaintext bytes isn't transmitted, and so for decompression we might need * to scale up the buffer. */ /* * Compress from a file to a newly malloc'd block. */ int dcc_compress_file_lzo1x(int in_fd, size_t in_len, char **out_buf, size_t *out_len) { char *in_buf = NULL; int ret; if ((in_buf = malloc(in_len)) == NULL) { rs_log_error("allocation of %ld byte buffer failed", (long) in_len); ret = EXIT_OUT_OF_MEMORY; goto out; } if ((ret = dcc_readx(in_fd, in_buf, in_len))) goto out; if ((ret = dcc_compress_lzo1x_alloc(in_buf, in_len, out_buf, out_len))) goto out; out: if (in_buf != NULL) { free(in_buf); } return ret; } /** * Send LZO-compressed bulk data. * * The most straightforward method for miniLZO is to just send everything in * one big chunk. So we just read the whole input into a buffer, build the * output in a buffer, and send it once its complete. **/ int dcc_compress_lzo1x_alloc(const char *in_buf, size_t in_len, char **out_buf_ret, size_t *out_len_ret) { int ret = 0, lzo_ret; char *out_buf = NULL; size_t out_size; lzo_uint out_len; /* NOTE: out_size is the buffer size, out_len is the amount of actual * data. */ /* In the unlikely worst case, LZO can cause the input to expand a bit. */ out_size = in_len + in_len/64 + 16 + 3; if ((out_buf = malloc(out_size)) == NULL) { rs_log_error("failed to allocate compression buffer"); return EXIT_OUT_OF_MEMORY; } out_len = out_size; lzo_ret = lzo1x_1_compress((lzo_byte*)in_buf, in_len, (lzo_byte*)out_buf, &out_len, work_mem); if (lzo_ret != LZO_E_OK) { rs_log_error("LZO1X1 compression failed: %d", lzo_ret); free(out_buf); return EXIT_IO_ERROR; } *out_buf_ret = out_buf; *out_len_ret = out_len; rs_trace("compressed %ld bytes to %ld bytes: %d%%", (long) in_len, (long) out_len, (int) (in_len ? 100*out_len / in_len : 0)); return ret; } /** * Receive @p in_len compressed bytes from @p in_fd, and write the * decompressed form to @p out_fd. * * There's no way for us to know how big the uncompressed form will be, and * there is also no way to grow the decompression buffer if it turns out to * initially be too small. So we assume a ratio of 10x. If it turns out to * be too small, we increase the buffer and try again. Typical compression of * source or object is about 2x to 4x. On modern Unix we should be able to * allocate (and not touch) many megabytes at little cost, since it will just * turn into an anonymous map. * * LZO doesn't have any way to decompress part of the input and then break to * get more output space, so our buffer needs to be big enough in the first * place or we would waste time repeatedly decompressing it. **/ int dcc_r_bulk_lzo1x(int out_fd, int in_fd, unsigned in_len) { int ret, lzo_ret; char *in_buf = NULL, *out_buf = NULL; size_t out_size = 0; lzo_uint out_len; /* NOTE: out_size is the buffer size, out_len is the amount of actual * data. */ if (in_len == 0) return 0; /* just check */ if ((in_buf = malloc(in_len)) == NULL) { rs_log_error("failed to allocate decompression input"); ret = EXIT_OUT_OF_MEMORY; goto out; } if ((ret = dcc_readx(in_fd, in_buf, in_len)) != 0) goto out; #if 0 /* Initial estimate for output buffer. This is intentionally quite low to * exercise the resizing code -- if it works OK then we can scale this * up. */ out_size = 2 * in_len; #else out_size = 8 * in_len; #endif try_again_with_a_bigger_buffer: if ((out_buf = malloc(out_size)) == NULL) { rs_log_error("failed to allocate decompression buffer"); ret = EXIT_OUT_OF_MEMORY; goto out; } out_len = out_size; lzo_ret = lzo1x_decompress_safe((lzo_byte*)in_buf, in_len, (lzo_byte*)out_buf, &out_len, work_mem); if (lzo_ret == LZO_E_OK) { rs_trace("decompressed %ld bytes to %ld bytes: %d%%", (long) in_len, (long) out_len, (int) (out_len ? 100*in_len / out_len : 0)); ret = dcc_writex(out_fd, out_buf, out_len); goto out; } else if (lzo_ret == LZO_E_OUTPUT_OVERRUN) { free(out_buf); out_buf = 0; out_size *= 2; /* FIXME: Make sure this doesn't overflow memory size? */ rs_trace("LZO_E_OUTPUT_OVERRUN, trying again with %lu byte buffer", (unsigned long) out_size); goto try_again_with_a_bigger_buffer; } else { rs_log_error("LZO1X1 decompression failed: %d", lzo_ret); ret = EXIT_IO_ERROR; goto out; } out: free(in_buf); free(out_buf); return ret; } distcc-3.4/src/cpp.c000066400000000000000000000064311404653710500143570ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Run the preprocessor. Client-side only. **/ #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "implicit.h" #include "exec.h" /** * If the input filename is a plain source file rather than a * preprocessed source file, then preprocess it to a temporary file * and return the name in @p cpp_fname. * * The preprocessor may still be running when we return; you have to * wait for @p cpp_fid to exit before the output is complete. This * allows us to overlap opening the TCP socket, which probably doesn't * use many cycles, with running the preprocessor. **/ int dcc_cpp_maybe(char **argv, char *input_fname, char **cpp_fname, pid_t *cpp_pid) { char **cpp_argv; int ret; char *input_exten; const char *output_exten; *cpp_pid = 0; if (dcc_is_preprocessed(input_fname)) { /* TODO: Perhaps also consider the option that says not to use cpp. * Would anyone do that? */ rs_trace("input is already preprocessed"); /* already preprocessed, great. */ if (!(*cpp_fname = strdup(input_fname))) { rs_log_error("couldn't duplicate string"); return EXIT_OUT_OF_MEMORY; } return 0; } input_exten = dcc_find_extension(input_fname); output_exten = dcc_preproc_exten(input_exten); if ((ret = dcc_make_tmpnam("distcc", output_exten, cpp_fname))) return ret; /* We strip the -o option and allow cpp to write to stdout, which is * caught in a file. Sun cc doesn't understand -E -o, and gcc screws up * -MD -E -o. * * There is still a problem here with -MD -E -o, gcc writes dependencies * to a file determined by the source filename. We could fix it by * generating a -MF option, but that would break compilation with older * versions of gcc. This is only a problem for people who have the source * and objects in different directories, and who don't specify -MF. They * can fix it by specifying -MF. */ if ((ret = dcc_strip_dasho(argv, &cpp_argv)) || (ret = dcc_set_action_opt(cpp_argv, "-E"))) return ret; /* FIXME: cpp_argv is leaked */ return dcc_spawn_child(cpp_argv, cpp_pid, "/dev/null", *cpp_fname, NULL); } distcc-3.4/src/daemon.c000066400000000000000000000234461404653710500150450ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "Just like distributed.net, only useful!" */ /** * @file * * distcc volunteer server. Accepts and serves requests to compile * files. * * May be run from inetd (default if stdin is a socket), or as a * daemon by itself. * * distcc has an adequate but perhaps not optimal system for deciding * where to send files. The general principle is that the server * should say how many jobs it is willing to accept, rather than the * client having to know. This is probably good in two ways: it * allows for people in the future to impose limits on how much work * their contributed machine will do, and secondly it seems better to * put this information in one place rather than on every client. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ARPA_NAMESER_H # include #endif #include #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "dopt.h" #include "srvnet.h" #include "daemon.h" #include "types.h" #ifdef HAVE_GSSAPI #include "auth.h" #endif /* for trace.c */ char const *rs_program_name = "distccd"; /* for serve.c */ char const *dcc_daemon_wd; /* The working directory for the server. */ static int dcc_inetd_server(void); static void dcc_setup_real_log(void); /** * Errors during startup (e.g. bad options) need to be reported somewhere, * although we have not yet parsed the options to work out where the user * wants them. * * In inetd mode, we can't write to stderr because that will corrupt the * stream, so if it looks like stderr is a socket we go to syslog instead. **/ static int dcc_setup_startup_log(void) { rs_trace_set_level(RS_LOG_INFO); if (!is_a_socket(STDERR_FILENO)) { rs_add_logger(rs_logger_file, RS_LOG_DEBUG, 0, STDERR_FILENO); } else { openlog("distccd", LOG_PID, LOG_DAEMON); rs_trace_syslog = TRUE; rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0); } return 0; } static int dcc_should_be_inetd(void) { /* Work out if we ought to serve stdin or be a standalone daemon */ if (opt_inetd_mode) return 1; else if (opt_daemon_mode) return 0; else if (is_a_socket(STDIN_FILENO)) { rs_log_info("stdin is socket; assuming --inetd mode"); return 1; } else if (isatty(STDIN_FILENO)) { rs_log_info("stdin is a tty; assuming --daemon mode"); return 0; } else { rs_log_info("stdin is neither a tty nor a socket; assuming --daemon mode"); return 0; } } static int dcc_setup_daemon_path(void) { int ret; const char *path; if ((path = getenv("DISTCCD_PATH")) != NULL) { if ((ret = dcc_set_path(path))) return ret; return 0; } else { path = getenv("PATH"); rs_log_info("daemon's PATH is %s", path ? path : "(NULL)"); return 0; } } static void dcc_warn_masquerade_whitelist(void) { DIR *d, *e; const char *warn = "You must see up masquerade" \ " (see distcc(1)) to list whitelisted compilers or pass" \ " --enable-tcp-insecure. To set up masquerade automatically" \ " run update-distcc-symlinks."; e = opendir("/usr/lib/distcc"); d = opendir(LIBDIR "/distcc"); if (!e && !d) { rs_log_crit(LIBDIR "/distcc not found. %s", warn); dcc_exit(EXIT_COMPILER_MISSING); } if ((!e || !readdir(e)) && (!d || !readdir(d))) { rs_log_crit(LIBDIR "/distcc empty. %s", warn); dcc_exit(EXIT_COMPILER_MISSING); } if (d) { closedir(d); } if (e) { closedir(e); } } /** * distcc daemon. May run from inetd, or standalone. Accepts * requests from clients to compile files. **/ int main(int argc, char *argv[]) { int ret; dcc_setup_startup_log(); if (distccd_parse_options(argc, (const char **) argv)) dcc_exit(EXIT_DISTCC_FAILED); /* check this before redirecting the logs, so that it's really obvious */ if (!dcc_should_be_inetd()) if (opt_allowed == NULL) { rs_log_warning("No --allow option specified. Defaulting to --allow-private." " Allowing non-Internet (globally" " routable) addresses."); opt_allow_private = 1; } if ((ret = dcc_set_lifetime()) != 0) dcc_exit(ret); /* do this before giving away root */ if (nice(opt_niceness) == -1) { rs_log_warning("nice %d failed: %s", opt_niceness, strerror(errno)); /* continue anyhow */ } if ((ret = dcc_discard_root()) != 0) dcc_exit(ret); /* Discard privileges before opening log so that if it's created, it has * the right ownership. */ dcc_setup_real_log(); /* Do everything from $TMPDIR directory. Allows start directory to be * unmounted. */ if ((ret = dcc_get_tmp_top(&dcc_daemon_wd))) goto out; if (chdir(dcc_daemon_wd) == -1) { rs_log_error("failed to chdir to %s: %s", dcc_daemon_wd, strerror(errno)); ret = EXIT_IO_ERROR; goto out; } else { rs_trace("chdir to %s", dcc_daemon_wd); } if ((ret = dcc_setup_daemon_path())) goto out; #ifdef HAVE_GSSAPI /* Obtain credentials if authentication is requested. */ if (dcc_auth_enabled) { if ((ret = dcc_gssapi_acquire_credentials()) != 0) { goto out; } /* Read contents of list file into an array and apply qsort. */ if (opt_blacklist_enabled || opt_whitelist_enabled) { if ((ret = dcc_gssapi_obtain_list((opt_blacklist_enabled) ? 1 : 0)) != 0) { goto out; } } } #endif /* Initialize the distcc io timeout value */ dcc_get_io_timeout(); if (!opt_enable_tcp_insecure) dcc_warn_masquerade_whitelist(); if (dcc_should_be_inetd()) ret = dcc_inetd_server(); else ret = dcc_standalone_server(); out: dcc_exit(ret); } /** * If a --lifetime options was specified, set up a timer that will kill the * daemon when it expires. **/ int dcc_set_lifetime(void) { if (opt_lifetime) { alarm(opt_lifetime); /* rs_trace("set alarm for %+d seconds", opt_lifetime); */ } return 0; } /** * Set log to the final destination after options have been read. **/ static void dcc_setup_real_log(void) { int fd; /* Even in inetd mode, we might want to log to stderr, because that will * work OK for ssh connections. */ if (opt_log_stderr) { rs_remove_all_loggers(); rs_add_logger(rs_logger_file, opt_log_level_num, 0, STDERR_FILENO); return; } if (arg_log_file) { /* Don't remove loggers yet, in case this fails and needs to go to the * default. */ if ((fd = open(arg_log_file, O_CREAT|O_APPEND|O_WRONLY, 0666)) == -1) { rs_log_error("failed to open %s: %s", arg_log_file, strerror(errno)); /* continue and use syslog */ } else { rs_remove_all_loggers(); rs_add_logger(rs_logger_file, opt_log_level_num, NULL, fd); return; } } rs_remove_all_loggers(); openlog("distccd", LOG_PID, LOG_DAEMON); rs_trace_syslog = TRUE; rs_add_logger(rs_logger_syslog, opt_log_level_num, NULL, 0); } int dcc_log_daemon_started(const char *role) { rs_log_info("%s started (%s %s, built %s %s)", role, PACKAGE_VERSION, GNU_HOST, __DATE__, __TIME__); return 0; } /** * Serve a single file on stdin, and then exit. **/ static int dcc_inetd_server(void) { int ret, close_ret; struct dcc_sockaddr_storage ss; struct sockaddr *psa = (struct sockaddr *) &ss; socklen_t len = sizeof ss; dcc_log_daemon_started("inetd server"); if ((getpeername(STDIN_FILENO, psa, &len) == -1)) { /* This can fail with ENOTSOCK if e.g. sshd has started us on a pipe, * not on a socket. I think it's harmless. */ rs_log_notice("failed to get peer name: %s", strerror(errno)); psa = NULL; /* make sure we don't refer to uninitialized mem */ len = 0; } ret = dcc_service_job(STDIN_FILENO, STDOUT_FILENO, psa, len); close_ret = dcc_close(STDIN_FILENO); #ifdef HAVE_GSSAPI if (dcc_auth_enabled) { dcc_gssapi_release_credentials(); if (opt_blacklist_enabled || opt_whitelist_enabled) { dcc_gssapi_free_list(); } } #endif if (ret) return ret; else return close_ret; } distcc-3.4/src/daemon.h000066400000000000000000000031101404653710500150340ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* daemon.c */ extern const char *dcc_daemon_wd; int dcc_refuse_root(void); int dcc_set_lifetime(void); int dcc_log_daemon_started(const char *role); /* dsignal.c */ void dcc_ignore_sighup(void); void dcc_daemon_catch_signals(void); /* dparent.c */ int dcc_standalone_server(void); void dcc_remove_pid(void); void dcc_reap_kids(int must_reap); /* prefork.c */ int dcc_preforking_parent(int listen_fd); /* serve.c */ struct sockaddr; int dcc_service_job(int in_fd, int out_fd, struct sockaddr *, int); /* setuid.c */ int dcc_discard_root(void); extern const char *opt_user; extern int dcc_max_kids; extern int dcc_nkids; extern volatile pid_t dcc_master_pid; distcc-3.4/src/distcc.c000066400000000000000000000245241404653710500150510ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* 4: The noise of a multitude in the * mountains, like as of a great people; a * tumultuous noise of the kingdoms of nations * gathered together: the LORD of hosts * mustereth the host of the battle. * -- Isaiah 13 */ #include #include #include #include #include #include #include #include #if HAVE_LIBIBERTY #if defined (HAVE_LIBIBERTY_H) #include #elif defined (HAVE_LIBIBERTY_LIBIBERTY_H) #include #else #error Need libiberty.h #endif #endif #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "hosts.h" #include "bulk.h" #include "implicit.h" #include "compile.h" #include "emaillog.h" /* Name of this program, for trace.c */ const char *rs_program_name = "distcc"; /** * @file * * Entry point for the distcc client. * * There are three methods of use for distcc: explicit (distcc gcc -c * foo.c), implicit (distcc -c foo.c) and masqueraded (gcc -c foo.c, * where gcc is really a link to distcc). * * Detecting these is relatively easy by examining the first one or * two words of the command. We also need to make sure that when we * go to run the compiler, we run the one intended by the user. * * In particular, for masqueraded mode, we want to make sure that we * don't invoke distcc recursively. **/ static void dcc_show_usage(void) { dcc_show_version("distcc"); printf( "Usage:\n" " distcc [--scan-includes] [COMPILER] [compile options] -o OBJECT -c SOURCE\n" " distcc [--help|--version|--show-hosts|-j]\n" "\n" "Options:\n" " COMPILER Defaults to \"cc\".\n" " --help Explain usage, and exit.\n" " --version Show version, and exit.\n" " --show-hosts Show host list, and exit.\n" " -j Show the concurrency level, as calculated from\n" " the host list, and exit.\n" " --scan-includes Show the files that distcc would send to the\n" " remote machine, and exit. (Pump mode only.)\n" #ifdef HAVE_GSSAPI " --show-principal Show current distccd GSS-API principal and exit.\n" #endif "\n" "Environment variables:\n" " See the manual page for a complete list.\n" " DISTCC_VERBOSE=1 Give debug messages.\n" " DISTCC_LOG Send messages to file, not stderr.\n" " DISTCC_SSH Command to run to open SSH connections.\n" " DISTCC_DIR Directory for host list and locks.\n" #ifdef HAVE_GSSAPI " DISTCC_PRINCIPAL The name of the server principal to connect to.\n" #endif "\n" "Server specification:\n" "A list of servers is taken from the environment variable $DISTCC_HOSTS, or\n" "$DISTCC_DIR/hosts, or ~/.distcc/hosts, or %s/distcc/hosts.\n" "Each host can be given in any of these forms, see the manual for details:\n" "\n" " localhost Run in place.\n" " HOST TCP connection, port %d.\n" " HOST:PORT TCP connection, specified port.\n" " @HOST SSH connection to specified host.\n" " USER@HOST SSH connection to specified username at host.\n" " HOSTSPEC,lzo Enable compression.\n" " HOSTSPEC,cpp,lzo Use pump mode (remote preprocessing).\n" " HOSTSPEC,auth Enable GSS-API based mutual authenticaton.\n" " --randomize Randomize the server list before execution.\n" "\n" "distcc distributes compilation jobs across volunteer machines running\n" "distccd. Jobs that cannot be distributed, such as linking, are run locally.\n" "distcc should be used with make's -jN option to execute in parallel on\n" "several machines.\n", SYSCONFDIR, DISTCC_DEFAULT_PORT); } static RETSIGTYPE dcc_client_signalled (int whichsig) { signal(whichsig, SIG_DFL); #ifdef HAVE_STRSIGNAL rs_log_info("%s", strsignal(whichsig)); #else rs_log_info("terminated by signal %d", whichsig); #endif dcc_cleanup_tempfiles_from_signal_handler(); raise(whichsig); } static void dcc_client_catch_signals(void) { signal(SIGTERM, &dcc_client_signalled); signal(SIGINT, &dcc_client_signalled); signal(SIGHUP, &dcc_client_signalled); } static void dcc_free_hostlist(struct dcc_hostdef *list) { while (list) { struct dcc_hostdef *l = list; list = list->next; dcc_free_hostdef(l); } } static void dcc_show_hosts(void) { struct dcc_hostdef *list, *l; int nhosts; if (dcc_get_hostlist(&list, &nhosts) != 0) { rs_log_crit("Failed to get host list"); return; } for (l = list; l; l = l->next) printf("%s\n", l->hostdef_string); dcc_free_hostlist(list); } static void dcc_concurrency_level(void) { struct dcc_hostdef *list, *l; int nhosts; int nslots = 0; if (dcc_get_hostlist(&list, &nhosts) != 0) { rs_log_crit("Failed to get host list"); return; } for (l = list; l; l = l->next) nslots += l->n_slots; dcc_free_hostlist(list); printf("%i\n", nslots); } #ifdef HAVE_GSSAPI /* * Print out the name of the principal. */ static void dcc_gssapi_show_principal(void) { char *princ_env_val = NULL; if((princ_env_val = getenv("DISTCC_PRINCIPAL"))) { printf("Principal is\t: %s\n", princ_env_val); } else { printf("Principal\t: Not Set.\n"); } } #endif /** * distcc client entry point. * * This is typically called by make in place of the real compiler. * * Performs basic setup and checks for distcc arguments, and then kicks off * dcc_build_somewhere(). **/ int main(int argc, char **argv) { int status, sg_level, tweaked_path = 0; char **compiler_args = NULL; /* dynamically allocated */ char *compiler_name; /* points into argv[0] */ int ret; dcc_client_catch_signals(); atexit(dcc_cleanup_tempfiles); atexit(dcc_remove_state_file); dcc_set_trace_from_env(); dcc_setup_log_email(); dcc_trace_version(); #if HAVE_LIBIBERTY /* Expand @FILE arguments. */ expandargv(&argc, &argv); #endif compiler_name = (char *) dcc_find_basename(argv[0]); /* Ignore SIGPIPE; we consistently check error codes and will * see the EPIPE. */ dcc_ignore_sigpipe(1); sg_level = dcc_recursion_safeguard(); rs_trace("compiler name is \"%s\"", compiler_name); if (strstr(compiler_name, "distcc") != NULL) { /* Either "distcc -c hello.c" or "distcc gcc -c hello.c" */ if (argc <= 1) { fprintf (stderr, "%s: missing option/operand\n" "Try `%s --help' for more information.\n", argv[0], argv[0]); ret = EXIT_BAD_ARGUMENTS; goto out; } if (!strcmp(argv[1], "--help")) { dcc_show_usage(); ret = 0; goto out; } if (!strcmp(argv[1], "--version")) { dcc_show_version("distcc"); ret = 0; goto out; } if (!strcmp(argv[1], "--show-hosts")) { dcc_show_hosts(); ret = 0; goto out; } if (!strcmp(argv[1], "-j")) { dcc_concurrency_level(); ret = 0; goto out; } if (!strcmp(argv[1], "--scan-includes")) { if (argc <= 2) { fprintf (stderr, "%s: missing operand\n" "Try `%s --help' for more information.\n", argv[0], argv[0]); ret = EXIT_BAD_ARGUMENTS; goto out; } dcc_scan_includes = 1; argv++; } #ifdef HAVE_GSSAPI if (!strcmp(argv[1], "--show-principal")) { dcc_gssapi_show_principal(); ret = 0; goto out; } #endif if ((ret = dcc_find_compiler(argv, &compiler_args)) != 0) { goto out; } /* compiler_args is now respectively either "cc -c hello.c" or * "gcc -c hello.c" */ #if 0 /* I don't think we need to call this: if we reached this * line, our invocation name is something like 'distcc', and * that's never a problem for masquerading loops. */ if ((ret = dcc_trim_path(compiler_name)) != 0) goto out; #endif } else { /* Invoked as "cc -c hello.c", with masqueraded path */ if ((ret = dcc_support_masquerade(argv, compiler_name, &tweaked_path)) != 0) goto out; if ((ret = dcc_copy_argv(argv, &compiler_args, 0)) != 0) { goto out; } free(compiler_args[0]); compiler_args[0] = strdup(compiler_name); if (!compiler_args[0]) { rs_log_error("strdup failed - out of memory?"); ret = EXIT_OUT_OF_MEMORY; goto out; } } if (sg_level - tweaked_path > 0) { rs_log_crit("distcc seems to have invoked itself recursively!"); ret = EXIT_RECURSION; goto out; } ret = dcc_build_somewhere_timed(compiler_args, sg_level, &status); compiler_args = NULL; /* dcc_build_somewhere_timed already free'd it. */ out: if (compiler_args) { dcc_free_argv(compiler_args); } dcc_maybe_send_email(); dcc_exit(ret); } distcc-3.4/src/distcc.h000066400000000000000000000240751404653710500150570ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* distcc.h -- common internal-use header file */ #include #include /* for struct timeval */ #ifdef NORETURN /* nothing */ #elif defined(__GNUC__) # define NORETURN __attribute__((noreturn)) #elif defined(__LCLINT__) # define NORETURN /*@noreturn@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define NORETURN #endif /* !__GNUC__ && !__LCLINT__ */ #ifdef UNUSED /* nothing */ #elif defined(__GNUC__) # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) #elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define UNUSED(x) x #endif /* !__GNUC__ && !__LCLINT__ */ /* According to the gcc info page, __attribute__((unused)) means "this * variable is *possibly* unused" (emphasis added). So we can use it for * POSSIBLY_UNUSED. This macro is used when a variable is used in one #ifdef * case but not another, say. */ #ifdef POSSIBLY_UNUSED /* nothing */ #elif defined(__GNUC__) # define POSSIBLY_UNUSED(x) x __attribute__((unused)) #elif defined(__LCLINT__) # define POSSIBLY_UNUSED(x) /*@unused@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define POSSIBLY_UNUSED(x) x #endif /* !__GNUC__ && !__LCLINT__ */ #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) /* This works on Gentoo's (patched?) gcc 3.3.3 but not 3.2.3, and not Debian's * 3.3.4. It should be standard on 3.4. */ # define WARN_UNUSED __attribute__((warn_unused_result)) #else # define WARN_UNUSED #endif #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif struct dcc_hostdef; #include "state.h" enum dcc_compress { /* weird values to catch errors */ DCC_COMPRESS_NONE = 69, DCC_COMPRESS_LZO1X }; enum dcc_cpp_where { /* weird values to catch errors */ DCC_CPP_ON_CLIENT = 42, DCC_CPP_ON_SERVER }; enum dcc_protover { DCC_VER_1 = 1, /**< vanilla */ DCC_VER_2 = 2, /**< LZO sprinkles */ DCC_VER_3 = 3 /**< server-side cpp */ }; int str_endswith(const char *tail, const char *tiger); /* A macro so that we get the right __FUNCTION__ in the trace message. * * We condition on rs_trace_enabled so that we don't do the to-string * conversion unless the user will actually see the result, because it's a * little expensive. */ #define dcc_trace_argv(_message, _argv) \ if (rs_trace_enabled()) { \ char *_astr; \ _astr = dcc_argv_tostr(_argv); \ rs_trace("%s: %s", _message, _astr); \ free(_astr); \ } else {} /* help.c */ int dcc_trace_version(void); int dcc_show_version(const char *prog); /* hosts.c */ int dcc_parse_hosts_env(struct dcc_hostdef **ret_list, int *ret_nhosts); int dcc_parse_hosts(const char *where, const char *source_name, struct dcc_hostdef **ret_list, int *ret_nhosts, struct dcc_hostdef **ret_prev); /* ncpu.c */ int dcc_ncpus(int *); /* ssh.c */ int dcc_ssh_connect(char *ssh_cmd, char *user, char *machine, char *path, int *f_in, int *f_out, pid_t *ssh_pid); /* safeguard.c */ int dcc_increment_safeguard(void); int dcc_recursion_safeguard(void); /* clirpc.c */ int dcc_x_req_header(int fd, enum dcc_protover protover); int dcc_x_argv(int fd, const char *argc_token, const char *argv_token, char **argv); int dcc_x_cwd(int fd); int dcc_is_link(const char *fname, int *is_link); int dcc_read_link(const char* fname, char *points_to); /* srvrpc.c */ int dcc_r_cwd(int ifd, char **cwd); /* remote.c */ int dcc_send_job_corked(int net_fd, char **argv, pid_t cpp_pid, int *status, const char *, const char *cpp_fname, struct dcc_hostdef *); int dcc_retrieve_results(int net_fd, int *status, const char *output_fname, const char *deps_fname, const char *server_stderr_fname, struct dcc_hostdef *); /* climasq.c */ int dcc_support_masquerade(char *argv[], char *progname, int *); /* backoff.c */ int dcc_enjoyed_host(const struct dcc_hostdef *host); int dcc_disliked_host(const struct dcc_hostdef *host); int dcc_remove_disliked(struct dcc_hostdef **hostlist); #define DISTCC_DEFAULT_PORT 3632 #define DISTCC_DEFAULT_STATS_ENABLED 0 #define DISTCC_DEFAULT_STATS_PORT 3633 #ifndef WAIT_ANY # define WAIT_ANY (-1) #endif /* If --enable-rfc2553 was given, then we will try to enable compile-time IPv6 * support. This means we must have a sockaddr_storage large enough to hold * IPv6 addresses. If not, we'll just use a plain sockaddr, which is more * likely to compile correctly. */ #ifdef ENABLE_RFC2553 # ifndef HAVE_SOCKADDR_STORAGE # error You can't use RFC2553 because you don't have a sockaddr_storage type # endif /* HAVE_SOCKADDR_STORAGE */ # define dcc_sockaddr_storage sockaddr_storage #else /* !ENABLE_RFC2553 */ # define dcc_sockaddr_storage sockaddr #endif /* !ENABLE_RFC2553 */ #ifndef O_BINARY # define O_BINARY 0 #endif void dcc_set_trace_from_env(void); /* compress.c */ int dcc_r_bulk_lzo1x(int outf_fd, int in_fd, unsigned in_len); int dcc_compress_file_lzo1x(int in_fd, size_t in_len, char **out_buf, size_t *out_len); int dcc_compress_lzo1x_alloc(const char *in_buf, size_t in_len, char **out_buf_ret, size_t *out_len_ret); /* bulk.c */ void dcc_calc_rate(off_t size_out, struct timeval *before, struct timeval *after, double *secs, double *rate); /* arg.c */ int dcc_set_action_opt(char **, const char *); int dcc_set_output(char **, char *); int dcc_set_input(char **, char *); int dcc_scan_args(char *argv[], /*@out@*/ /*@relnull@*/ char **orig_o, char **orig_i, char ***ret_newargv); int dcc_expand_preprocessor_options(char ***argv_ptr); /* argutil.c */ unsigned int dcc_argv_len(char **a); int dcc_argv_search(char **a, const char *); int dcc_copy_argv(char **argv, char ***out_argv, int extra_args); int dcc_argv_append(char **argv, char *toadd); char *dcc_argv_tostr(char **a); void dcc_free_argv(char **argv); /* tempfile.c */ int dcc_get_tempdir(const char **); int dcc_make_tmpnam(const char *, const char *suffix, char **); int dcc_get_new_tmpdir(char **tmpdir); int dcc_mk_tmpdir(const char *path); int dcc_mkdir(const char *path); int dcc_get_subdir(const char *name, char **path_ret) WARN_UNUSED; int dcc_get_lock_dir(char **path_ret) WARN_UNUSED; int dcc_get_state_dir(char **path_ret) WARN_UNUSED; int dcc_get_top_dir(char **path_ret) WARN_UNUSED; int dcc_get_tmp_top(const char **p_ret) WARN_UNUSED; int dcc_mk_tmp_ancestor_dirs(const char* file); /* cleanup.c */ void dcc_cleanup_tempfiles(void); void dcc_cleanup_tempfiles_from_signal_handler(void); int dcc_add_cleanup(const char *filename) WARN_UNUSED; /* strip.c */ int dcc_strip_local_args(char **from, char ***out_argv); int dcc_strip_dasho(char **from, char ***out_argv); /* cpp.c */ int dcc_cpp_maybe(char **argv, char *input_fname, char **cpp_fname, pid_t *cpp_pid); /* filename.c */ int dcc_is_source(const char *sfile); int dcc_is_preprocessed(const char *sfile); int dcc_is_object(const char *filename); int dcc_source_needs_local(const char *); char * dcc_find_extension(char *sfile); const char * dcc_find_extension_const(const char *sfile); int dcc_output_from_source(const char *sfile, const char *out_extn, char **ofile); const char * dcc_preproc_exten(const char *e); const char * dcc_find_basename(const char *sfile); void dcc_truncate_to_dirname(char *file); /* io.c */ int dcc_writex(int fd, const void *buf, size_t len); int dcc_r_token(int ifd, char *token); int dcc_readx(int fd, void *buf, size_t len); int dcc_pump_sendfile(int ofd, int ifd, size_t n); int dcc_r_str_alloc(int fd, unsigned len, char **buf); int tcp_cork_sock(int fd, int corked); int dcc_close(int fd); int dcc_get_io_timeout(void); int dcc_want_mmap(void); int dcc_select_for_write(int fd, int timeout); int dcc_select_for_read(int fd, int timeout); /* loadfile.c */ int dcc_load_file_string(const char *filename, char **retbuf); extern const int dcc_connect_timeout; /* pump.c */ int dcc_r_bulk(int ofd, int ifd, unsigned f_size, enum dcc_compress compression); int dcc_pump_readwrite(int ofd, int ifd, size_t n); /* mapfile.c */ int dcc_map_input_file(int in_fd, off_t in_size, char **buf_ret); /* XXX: Kind of kludgy, we should do dynamic allocation. But this will do for * now. */ #ifndef MAXPATHLEN #define MAXPATHLEN 4096 #endif #ifndef WCOREDUMP # define WCOREDUMP(status) 0 #endif distcc-3.4/src/dopt.c000066400000000000000000000316071404653710500145460ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* dopt.c -- Parse and apply server options. */ #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "trace.h" #include "dopt.h" #include "exitcode.h" #include "daemon.h" #include "access.h" #include "exec.h" int opt_niceness = 5; /* default */ /** * Number of children running jobs on this machine. If zero (recommended), * then dynamically set from the number of CPUs. **/ int arg_max_jobs = 0; #ifdef HAVE_GSSAPI /* If true perform GSS-API based authentication. */ int opt_auth_enabled = 0; /* Control access through a specified list file. */ int opt_blacklist_enabled = 0; int opt_whitelist_enabled = 0; const char *arg_list_file = NULL; #endif int arg_port = DISTCC_DEFAULT_PORT; int arg_stats = DISTCC_DEFAULT_STATS_ENABLED; int arg_stats_port = DISTCC_DEFAULT_STATS_PORT; /** If true, serve all requests directly from listening process without forking. Better for debugging. **/ int opt_no_fork = 0; int opt_daemon_mode = 0; int opt_inetd_mode = 0; int opt_no_fifo = 0; /** If non-NULL, listen on only this address. **/ char *opt_listen_addr = NULL; struct dcc_allow_list *opt_allowed = NULL; int opt_allow_private = 0; /** * If true, don't detach from the parent. This is probably necessary * for use with daemontools or other monitoring programs, and is also * used by the test suite. **/ int opt_no_detach = 0; int opt_log_stderr = 0; int opt_log_level_num = RS_LOG_NOTICE; /** * If true, do not check if a link to distcc exists in /usr/lib/distcc * for every program executed remotely. **/ int opt_enable_tcp_insecure = 0; /** * Daemon exits after this many seconds. Intended mainly for testing, to make * sure daemons don't persist for too long. */ int opt_lifetime = 0; const char *arg_pid_file = NULL; const char *arg_log_file = NULL; int opt_job_lifetime = 0; /* Enumeration values for options that don't have single-letter name. These * must be numerically above all the ascii letters. */ enum { opt_log_to_file = 300, opt_log_level }; #ifdef HAVE_AVAHI /* Flag for enabling/disabling Zeroconf using Avahi */ int opt_zeroconf = 0; #endif static const char *dcc_private_networks[] = {"192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12", "127.0.0.0/8", "fe80::/10", "fc00::/7", "::1/128"}; const struct poptOption options[] = { { "allow", 'a', POPT_ARG_STRING, 0, 'a', 0, 0 }, { "allow-private", 0,POPT_ARG_NONE, &opt_allow_private, 0, 0, 0 }, #ifdef HAVE_GSSAPI { "auth", 0, POPT_ARG_NONE, &opt_auth_enabled, 'A', 0, 0 }, { "blacklist", 0, POPT_ARG_STRING, &arg_list_file, 'b', 0, 0 }, #endif { "jobs", 'j', POPT_ARG_INT, &arg_max_jobs, 'j', 0, 0 }, { "daemon", 0, POPT_ARG_NONE, &opt_daemon_mode, 0, 0, 0 }, { "help", 0, POPT_ARG_NONE, 0, '?', 0, 0 }, { "inetd", 0, POPT_ARG_NONE, &opt_inetd_mode, 0, 0, 0 }, { "lifetime", 0, POPT_ARG_INT, &opt_lifetime, 0, 0, 0 }, { "listen", 0, POPT_ARG_STRING, &opt_listen_addr, 0, 0, 0 }, { "log-file", 0, POPT_ARG_STRING, &arg_log_file, 0, 0, 0 }, { "log-level", 0, POPT_ARG_STRING, 0, opt_log_level, 0, 0 }, { "log-stderr", 0, POPT_ARG_NONE, &opt_log_stderr, 0, 0, 0 }, { "job-lifetime", 0, POPT_ARG_INT, &opt_job_lifetime, 'l', 0, 0 }, { "nice", 'N', POPT_ARG_INT, &opt_niceness, 0, 0, 0 }, { "no-detach", 0, POPT_ARG_NONE, &opt_no_detach, 0, 0, 0 }, { "no-fifo", 0, POPT_ARG_NONE, &opt_no_fifo, 0, 0, 0 }, { "no-fork", 0, POPT_ARG_NONE, &opt_no_fork, 0, 0, 0 }, { "pid-file", 'P', POPT_ARG_STRING, &arg_pid_file, 0, 0, 0 }, { "port", 'p', POPT_ARG_INT, &arg_port, 0, 0, 0 }, #ifdef HAVE_GSSAPI { "show-principal", 0, POPT_ARG_NONE, 0, 'P', 0, 0 }, #endif { "user", 0, POPT_ARG_STRING, &opt_user, 'u', 0, 0 }, { "verbose", 0, POPT_ARG_NONE, 0, 'v', 0, 0 }, { "version", 0, POPT_ARG_NONE, 0, 'V', 0, 0 }, #ifdef HAVE_GSSAPI { "whitelist", 0, POPT_ARG_STRING, &arg_list_file, 'w', 0, 0 }, #endif { "wizard", 'W', POPT_ARG_NONE, 0, 'W', 0, 0 }, { "stats", 0, POPT_ARG_NONE, &arg_stats, 0, 0, 0 }, { "stats-port", 0, POPT_ARG_INT, &arg_stats_port, 0, 0, 0 }, #ifdef HAVE_AVAHI { "zeroconf", 0, POPT_ARG_NONE, &opt_zeroconf, 0, 0, 0 }, #endif { "make-me-a-botnet", 0, POPT_ARG_NONE, &opt_enable_tcp_insecure, 0, 0, 0 }, { "enable-tcp-insecure", 0, POPT_ARG_NONE, &opt_enable_tcp_insecure, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0 } }; static void distccd_show_usage(void) { dcc_show_version("distccd"); printf ( "Usage:\n" " distccd [OPTIONS]\n" "\n" "Options:\n" " --help explain usage and exit\n" " --version show version and exit\n" #ifdef HAVE_GSSAPI " --show-principal show current GSS-API principal and exit\n" #endif " -P, --pid-file FILE save daemon process id to file\n" " -N, --nice LEVEL lower priority, 20=most nice\n" " --user USER if run by root, change to this persona\n" " --jobs, -j LIMIT maximum tasks at any time\n" " --job-lifetime SECONDS maximum lifetime of a compile request\n" " Networking:\n" " -p, --port PORT TCP port to listen on\n" " --listen ADDRESS IP address to listen on\n" " -a, --allow IP[/BITS] client address access control\n" #ifdef HAVE_GSSAPI " --auth enable GSS-API based mutual authenticaton\n" " --blacklist=FILE control client access through a blacklist\n" " --whitelist=FILE control client access through a whitelist\n" #endif " --stats enable statistics reporting via HTTP server\n" " --stats-port PORT TCP port to listen on for statistics requests\n" #ifdef HAVE_AVAHI " --zeroconf register via mDNS/DNS-SD\n" #endif " Debug and trace:\n" " --log-level=LEVEL set detail level for log file\n" " levels: critical, error, warning, notice, info, debug\n" " --verbose set log level to \"debug\"\n" " --no-detach don't detach from parent (for daemontools, etc)\n" " --log-file=FILE send messages here instead of syslog\n" " --log-stderr send messages to stderr\n" " --wizard for running under gdb\n" " Mode of operation:\n" " --inetd serve client connected to stdin\n" " --daemon bind and listen on socket\n" "\n" "distccd runs either from inetd or as a standalone daemon to compile\n" "files submitted by the distcc client.\n" "\n" "distccd should only run on trusted networks.\n" ); } #ifdef HAVE_GSSAPI /* * Print out the name of the principal. */ static void dcc_gssapi_show_principal(void) { char *princ_env_val = NULL; if ((princ_env_val = getenv("DISTCCD_PRINCIPAL"))) { printf("Principal is\t: %s\n", princ_env_val); } else { printf("Principal\t: Not Set\n"); } } #endif int distccd_parse_options(int argc, const char **argv) { poptContext po; int po_err, exitcode; struct dcc_allow_list *new; po = poptGetContext("distccd", argc, argv, options, 0); while ((po_err = poptGetNextOpt(po)) != -1) { switch (po_err) { case '?': distccd_show_usage(); exitcode = 0; goto out_exit; case 'a': { /* TODO: Allow this to be a hostname, which is resolved to an address. */ /* TODO: Split this into a small function. */ new = malloc(sizeof *new); if (!new) { rs_log_crit("malloc failed"); exitcode = EXIT_OUT_OF_MEMORY; goto out_exit; } new->next = opt_allowed; opt_allowed = new; if ((exitcode = dcc_parse_mask(poptGetOptArg(po), &new->addr, &new->mask))) goto out_exit; } break; #ifdef HAVE_GSSAPI /* Set the flag to indicate that authentication is requested. */ case 'A': { if (opt_auth_enabled < 0) { opt_auth_enabled = 0; } dcc_auth_enabled = opt_auth_enabled; break; } case 'b': { if (opt_whitelist_enabled) { rs_log_error("Can't specify both --whitelist and --blacklist."); exitcode = EXIT_BAD_ARGUMENTS; goto out_exit; } else { opt_blacklist_enabled = 1; } break; } #endif case 'j': if (arg_max_jobs < 1 || arg_max_jobs > 200) { rs_log_error("--jobs argument must be between 1 and 200"); exitcode = EXIT_BAD_ARGUMENTS; goto out_exit; } break; case 'l': if (opt_job_lifetime < 0) { opt_job_lifetime = 0; } dcc_job_lifetime = opt_job_lifetime; break; #ifdef HAVE_GSSAPI case 'P': { dcc_gssapi_show_principal(); exitcode = 0; goto out_exit; } #endif case 'u': if (getuid() != 0 && geteuid() != 0) { rs_log_warning("--user is ignored when distccd is not run by root"); /* continue */ } break; case 'V': dcc_show_version("distccd"); exitcode = EXIT_SUCCESS; goto out_exit; case opt_log_level: { int level; const char *level_name; level_name = poptGetOptArg(po); level = rs_loglevel_from_name(level_name); if (level == -1) { rs_log_warning("invalid --log-level argument \"%s\"", level_name); } else { rs_trace_set_level(level); opt_log_level_num = level; } } break; case 'v': rs_trace_set_level(RS_LOG_DEBUG); opt_log_level_num = RS_LOG_DEBUG; break; #ifdef HAVE_GSSAPI case 'w': { if (opt_blacklist_enabled) { rs_log_error("Can't specify both --blacklist and --whitelist."); exitcode = EXIT_BAD_ARGUMENTS; goto out_exit; } else { opt_whitelist_enabled = 1; } break; } #endif case 'W': /* catchall for running under gdb */ opt_log_stderr = 1; opt_daemon_mode = 1; opt_no_detach = 1; opt_no_fork = 1; opt_no_fifo = 1; rs_trace_set_level(RS_LOG_DEBUG); opt_log_level_num = RS_LOG_DEBUG; break; default: /* bad? */ rs_log(RS_LOG_NONAME|RS_LOG_ERR|RS_LOG_NO_PID, "%s: %s", poptBadOption(po, POPT_BADOPTION_NOALIAS), poptStrerror(po_err)); exitcode = EXIT_BAD_ARGUMENTS; goto out_exit; } } if (opt_allow_private) { int i; for (i = 0;i<6;i++) { new = malloc(sizeof *new); if (!new) { rs_log_crit("malloc failed"); exitcode = EXIT_OUT_OF_MEMORY; goto out_exit; } new->next = opt_allowed; opt_allowed = new; if ((exitcode = dcc_parse_mask(dcc_private_networks[i], &new->addr, &new->mask))) goto out_exit; } } poptFreeContext(po); return 0; out_exit: poptFreeContext(po); exit(exitcode); } distcc-3.4/src/dopt.h000066400000000000000000000035271404653710500145530ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* dopt.c */ extern struct dcc_allow_list *opt_allowed; extern int opt_allow_private; int distccd_parse_options(int argc, const char *argv[]); extern int arg_port; extern int arg_stats; extern int arg_stats_port; extern int opt_log_level_num; extern int arg_max_jobs; extern const char *arg_pid_file; extern int opt_no_fork; extern int opt_no_prefork; extern int opt_no_detach; extern int opt_daemon_mode, opt_inetd_mode; extern int opt_enable_tcp_insecure; extern int opt_job_lifetime; extern const char *arg_log_file; extern int opt_no_fifo; extern int opt_log_stderr; extern int opt_lifetime; extern char *opt_listen_addr; extern int opt_niceness; #ifdef HAVE_AVAHI extern int opt_zeroconf; #endif #ifdef HAVE_GSSAPI extern int dcc_auth_enabled; #endif #ifdef HAVE_GSSAPI extern int dcc_auth_enabled; extern int opt_blacklist_enabled; extern int opt_whitelist_enabled; extern const char *arg_list_file; #endif distcc-3.4/src/dotd.c000066400000000000000000000214061404653710500145260ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include "distcc.h" #include "exitcode.h" #include "dotd.h" #include "snprintf.h" /* The dotd file is compiler generated, * so it should not have lines with more than * twice the length of the maximum path length. */ #define MAX_DOTD_LINE_LEN (MAXPATHLEN * 2) /* Replaces the first occurrence of needle in haystack with new_needle. haystack must be of at least hay_size, and hay_size must be large enough to hold the string after the replacement. new_needle should not overlap with the haystack. Returns 0 if all goes well, 1 otherwise. */ static int dcc_strgraft(char *haystack, size_t hay_size, const char *needle, const char *new_needle) { char *found; size_t needle_len = 0; size_t new_needle_len = 0; found = strstr(haystack, needle); if (found == NULL) return 0; needle_len = strlen(needle); new_needle_len = strlen(new_needle); if (strlen(haystack) - needle_len + new_needle_len + 1 > hay_size) return 1; /* make some room in the haystack for the new needle */ memmove(found + new_needle_len, found + needle_len, strlen(found + needle_len) + 1); memcpy(found, new_needle, new_needle_len); return 0; } /* Given the name of a dotd file, and the name of the directory * masquerading as root, write a @p new_dotd file that * contains everything in dotd, but with the "root" directory removed. * It will also substitute client_out_name for server_out_name, * rewriting the dependency target. */ int dcc_cleanup_dotd(const char *dotd_fname, char **new_dotd_fname, const char *root_dir, const char *client_out_name, const char *server_out_name) { /* When we do the substitution of server-side output name to * client-side output name, we may end up with a line that * longer than the longest line we expect from the compiler. */ char buf[2 * MAX_DOTD_LINE_LEN]; FILE *dotd, *tmp_dotd; char *found; int ret; dotd = fopen(dotd_fname, "r"); if (dotd == NULL) { return 1; } ret = dcc_make_tmpnam(dcc_find_basename(dotd_fname), ".d", new_dotd_fname); if (ret) { fclose(dotd); return ret; } tmp_dotd = fopen(*new_dotd_fname, "w"); if (tmp_dotd == NULL) { fclose(dotd); return 1; } while (fgets(buf, MAX_DOTD_LINE_LEN, dotd)) { if ((strchr(buf, '\n') == NULL) && !feof(dotd)) { /* Line length must have exceeded MAX_DOTD_LINE_LEN: bail out. */ fclose(dotd); fclose(tmp_dotd); return 1; } /* First, the dependency target substitution */ if (dcc_strgraft(buf, sizeof(buf), server_out_name, client_out_name)) { fclose(dotd); fclose(tmp_dotd); return 1; } /* Second, the trimming of the "root" directory" */ found = strstr(buf, root_dir); while (found) { char *rest_of_buf = found + strlen(root_dir); memmove(found, rest_of_buf, strlen(rest_of_buf) + 1); found = strstr(found, root_dir); } if (fprintf(tmp_dotd, "%s", buf) < 0) { fclose(dotd); fclose(tmp_dotd); return 1; } } if (ferror(dotd) || ferror(tmp_dotd)) { return 1; } fclose(dotd); if (fclose(tmp_dotd) < 0) { return 1; } return 0; } /* Go through arguments (in @p argv), and relevant environment variables, and * find out where the dependencies output should go. Return that location in a * newly allocated string in @p dotd_fname. @p needs_dotd is set to true if the * compilation command line and environment imply that a .d file must be * produced. @p sets_dotd_target is set to true if there is a -MQ or -MT * option. This is to be used on the client, so that the client knows where to * put the .d file it gets from the server. @p dotd_target is set only if * @needs_dotd is true and @sets_dotd_target is false and the target is given in * the DEPENDENCIES_OUTPUT environment variable. * * Note: -M is not handled here, because this option implies -E. * * TODO(manos): it does not support SUNPRO_DEPENDENCIES. */ int dcc_get_dotd_info(char **argv, char **dotd_fname, int *needs_dotd, int *sets_dotd_target, char **dotd_target) { char *deps_output = 0; char *input_file; char *output_file; char **new_args; /* will throw this away */ int has_dash_o = 0; char *env_var = 0; int i; char *a; *needs_dotd = 0; *sets_dotd_target = 0; *dotd_target = NULL; env_var = getenv("DEPENDENCIES_OUTPUT"); if (env_var != NULL) { *needs_dotd = 1; } for (i = 0; (a = argv[i]); i++) { if (strcmp(a, "-MT") == 0) { *sets_dotd_target = 1; ++i; continue; } if (strcmp(a, "-MQ") == 0) { *sets_dotd_target = 1; ++i; continue; } /* Catch-all for all -MD, -MMD, etc, options. * -MQ and -MT do not imply a deps file is expected. */ if (strncmp(a, "-M", 2) == 0) { *needs_dotd = 1; } if (strcmp(a, "-MF") == 0) { ++i; deps_output = argv[i]; } else if (strncmp(a, "-MF", 3) == 0) { deps_output = argv[i] + 3; } else if (strcmp(a, "-o") == 0) { has_dash_o = 1; } } /* TODO(csilvers): we also need to parse -Wp,-x,-y,-z, in the same * way we do gcc flags in the for loop above. Note that the -Wp * flags are passed to cpp, with slightly different semantics than * gcc flags (eg -Wp,-MD takes a filename argument, while -MD does * not). */ if (deps_output) { *dotd_fname = strdup(deps_output); if (*dotd_fname == NULL) { return EXIT_OUT_OF_MEMORY; } else { return 0; } } /* ok, so there is no explicit setting of the deps filename. */ deps_output = env_var; if (deps_output) { char *space; *dotd_fname = strdup(deps_output); if (*dotd_fname == NULL) { return EXIT_OUT_OF_MEMORY; } space = strchr(*dotd_fname, ' '); if (space != NULL) { *space = '\0'; *dotd_target = space + 1; } return 0; } /* and it's not set explicitly in the variable */ { /* Call dcc_scan_args to find the input/output files in order to calculate a name for the .d file.*/ char *extension; char *tmp_dotd_fname; dcc_scan_args(argv, &input_file, &output_file, &new_args); /* if .o is set, just append .d. * otherwise, take the basename of the input, and set the suffix to .d */ if (has_dash_o) tmp_dotd_fname = strdup(output_file); else tmp_dotd_fname = strdup(input_file); if (tmp_dotd_fname == NULL) return EXIT_OUT_OF_MEMORY; extension = dcc_find_extension(tmp_dotd_fname); /* Whether derived from input or output filename, we peel the extension off (if it exists). */ if (extension) { /* dcc_find_extension guarantees that there is space for 'd'. */ extension[1] = 'd'; extension[2] = '\0'; *dotd_fname = tmp_dotd_fname; } else { /* There is no extension (or name ends with a "."). */ if (tmp_dotd_fname[strlen(tmp_dotd_fname) - 1] == '.') checked_asprintf(dotd_fname, "%s%s", tmp_dotd_fname, "d"); else checked_asprintf(dotd_fname, "%s%s", tmp_dotd_fname, ".d"); if (*dotd_fname == NULL) { return EXIT_OUT_OF_MEMORY; } free(tmp_dotd_fname); } return 0; } } distcc-3.4/src/dotd.h000066400000000000000000000023321404653710500145300ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ int dcc_cleanup_dotd(const char *dotd_fname, char **new_dotd_fname, const char *root_dir, const char *client_out_name, const char *server_out_name); int dcc_get_dotd_info(char **argv, char **dotd_fname, int *needs_dotd, int *sets_dotd_target, char **dotd_target); distcc-3.4/src/dparent.c000066400000000000000000000260011404653710500152250ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Near is thy forgetfulness of all things; and near the * forgetfulness of thee by all. * -- Marcus Aurelius */ /** * @file * * Daemon parent. Accepts connections, forks, etc. * * @todo Quite soon we need load management. Basically when we think * we're "too busy" we should stop accepting connections. This could * be because of the load average, or because too many jobs are * running, or perhaps just because of a signal from the administrator * of this machine. In that case we want to do a blocking wait() to * find out when the current jobs are done, or perhaps a sleep() if * we're waiting for the load average to go back down. However, we * probably ought to always keep at least one job running so that we * can make progress through the queue. If you don't want any work * done, you should kill the daemon altogether. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "dopt.h" #include "exec.h" #include "srvnet.h" #include "types.h" #include "daemon.h" #include "netutil.h" #include "zeroconf.h" #ifdef HAVE_GSSAPI #include "auth.h" #endif static void dcc_nofork_parent(int listen_fd) NORETURN; static void dcc_detach(void); static void dcc_save_pid(pid_t); int dcc_nkids = 0; /** * In forking or prefork mode, the maximum number of connections we want to * allow at any time. **/ int dcc_max_kids = 0; /** * Be a standalone server, with responsibility for sockets and forking * children. Puts the daemon in the background and detaches from the * controlling tty. **/ int dcc_standalone_server(void) { int listen_fd; int n_cpus; int ret; #ifdef HAVE_AVAHI void *avahi = NULL; #endif if ((ret = dcc_socket_listen(arg_port, &listen_fd, opt_listen_addr)) != 0) return ret; dcc_defer_accept(listen_fd); set_cloexec_flag(listen_fd, 1); if (dcc_ncpus(&n_cpus) == 0) rs_log_info("%d CPU%s online on this server", n_cpus, n_cpus == 1 ? "" : "s"); /* By default, allow one job per CPU, plus two for the pot. The extra * ones are started to allow for a bit of extra concurrency so that the * machine is not idle waiting for disk or network IO. */ if (arg_max_jobs) dcc_max_kids = arg_max_jobs; else dcc_max_kids = 2 + n_cpus; rs_log_info("allowing up to %d active jobs", dcc_max_kids); if (!opt_no_detach) { /* Don't go into the background until we're listening and * ready. This is useful for testing -- when the daemon * detaches, we know we can go ahead and try to connect. */ dcc_detach(); } else { /* Still create a new process group, even if not detached */ rs_trace("not detaching"); if ((ret = dcc_new_pgrp()) != 0) return ret; dcc_save_pid(getpid()); } /* Don't catch signals until we've detached or created a process group. */ dcc_daemon_catch_signals(); #ifdef HAVE_AVAHI /* Zeroconf registration */ if (opt_zeroconf) { if (!(avahi = dcc_zeroconf_register((uint16_t) arg_port, n_cpus, dcc_max_kids))) return EXIT_CONNECT_FAILED; } #endif /* This is called in the master daemon, whether that is detached or * not. */ dcc_master_pid = getpid(); if (opt_no_fork) { dcc_log_daemon_started("non-forking daemon"); dcc_nofork_parent(listen_fd); ret = 0; } else { dcc_log_daemon_started("preforking daemon"); ret = dcc_preforking_parent(listen_fd); } #ifdef HAVE_AVAHI /* Remove zeroconf registration */ if (opt_zeroconf) { if (dcc_zeroconf_unregister(avahi) != 0) return EXIT_CONNECT_FAILED; } #endif return ret; } static void dcc_log_child_exited(pid_t kid, int status) { if (WIFSIGNALED(status)) { int sig = WTERMSIG(status); int severity = sig == SIGTERM ? RS_LOG_INFO : RS_LOG_ERR; rs_log(severity, "child %d: signal %d (%s)", (int) kid, sig, WCOREDUMP(status) ? "core dumped" : "no core"); } else if (WIFEXITED(status)) { rs_log_info("child %d exited: exit status %d", (int) kid, WEXITSTATUS(status)); } } /** * @sa dcc_wait_child(), which is used by a process that wants to do a blocking * wait for some task like cpp or gcc. * * @param must_reap If True, don't return until at least one child has been * collected. Used when e.g. all our process slots are full. In either case * we keep going until all outstanding zombies are collected. * * FIXME: Are blocking waits meant to collect all of them, or just one? At * the moment it waits until all children have exited. **/ void dcc_reap_kids(int must_reap) { while (1) { int status; pid_t kid; kid = waitpid(WAIT_ANY, &status, must_reap ? 0 : WNOHANG); if (kid == 0) { /* nobody has exited */ break; } else if (kid != -1) { /* child exited */ --dcc_nkids; rs_trace("down to %d children", dcc_nkids); dcc_log_child_exited(kid, status); } else if (errno == ECHILD) { /* No children left? That's ok, we'll go back to waiting * for new connections. */ break; } else if (errno == EINTR) { /* If we got a SIGTERM or something, then on the next pass * through the loop we'll find no children done, and we'll * return to the top loop at which point we'll exit. So * no special action is required here. */ continue; /* loop again */ } else { rs_log_error("wait failed: %s", strerror(errno)); /* e.g. too many open files; nothing we can do */ dcc_exit(EXIT_DISTCC_FAILED); } /* If there are more children keep looking, but don't block once we've * collected at least one. */ must_reap = FALSE; } } /** * Main loop for no-fork mode. * * Much slower and may leak. Should only be used when you want to run gdb on * distccd. **/ static void dcc_nofork_parent(int listen_fd) { while (1) { int acc_fd; struct dcc_sockaddr_storage cli_addr; socklen_t cli_len; rs_log_info("waiting to accept connection"); cli_len = sizeof cli_addr; acc_fd = accept(listen_fd, (struct sockaddr *) &cli_addr, &cli_len); if (acc_fd == -1 && errno == EINTR) { ; } else if (acc_fd == -1) { rs_log_error("accept failed: %s", strerror(errno)); #ifdef HAVE_GSSAPI if (dcc_auth_enabled) { dcc_gssapi_release_credentials(); if (opt_blacklist_enabled || opt_whitelist_enabled) { dcc_gssapi_free_list(); } } #endif dcc_exit(EXIT_CONNECT_FAILED); } else { dcc_service_job(acc_fd, acc_fd, (struct sockaddr *) &cli_addr, cli_len); dcc_close(acc_fd); } } } /** * Save the pid of the child process into the pid file, if any. * * This is called from the parent so that we have the invariant that * the pid file exists before the parent exits, hich is useful for * test harnesses. Otherwise, there is a race where the parent has * exited and they try to go ahead and read the child's pid, but it's * not there yet. **/ static void dcc_save_pid(pid_t pid) { FILE *fp; if (!arg_pid_file) return; if (!(fp = fopen(arg_pid_file, "wt"))) { rs_log_error("failed to open pid file: %s: %s", arg_pid_file, strerror(errno)); return; } fprintf(fp, "%ld\n", (long) pid); if (fclose(fp) == -1) { rs_log_error("failed to close pid file: %s: %s", arg_pid_file, strerror(errno)); return; } atexit(dcc_remove_pid); } /** * Remove our pid file on exit. * * Must be reentrant -- called from signal handler. **/ void dcc_remove_pid(void) { if (!arg_pid_file) return; /* this may be called from a signal handler, and syslog is not safe from signal handler */ if (unlink(arg_pid_file) && !rs_trace_syslog) { rs_log_warning("failed to remove pid file %s: %s", arg_pid_file, strerror(errno)); } } /** * Become a daemon, discarding the controlling terminal. * * Borrowed from rsync. * * This function returns in the child, but not in the parent. **/ static void dcc_detach(void) { int i; pid_t pid; pid_t sid; dcc_ignore_sighup(); if ((pid = fork()) == -1) { rs_log_error("fork failed: %s", strerror(errno)); exit(EXIT_DISTCC_FAILED); } else if (pid != 0) { /* In the parent. This guy is about to go away so as to * detach from the controlling process, but first save the * child's pid. */ dcc_save_pid(pid); _exit(0); } /* This is called in the detached child */ /* detach from the terminal */ #ifdef HAVE_SETSID if ((sid = setsid()) == -1) { rs_log_error("setsid failed: %s", strerror(errno)); } else { rs_trace("setsid to session %d", (int) sid); } #else /* no HAVE_SETSID */ #ifdef TIOCNOTTY i = open("/dev/tty", O_RDWR); if (i >= 0) { ioctl(i, (int) TIOCNOTTY, (char *)0); close(i); } #endif /* TIOCNOTTY */ #endif /* not HAVE_SETSID */ /* make sure that stdin, stdout an stderr don't stuff things up (library functions, for example) */ for (i=0;i<3;i++) { close(i); open("/dev/null", O_RDWR); } /* If there's a lifetime limit on this server (for testing) then it needs * to apply after detaching as well. */ dcc_set_lifetime(); } distcc-3.4/src/dsignal.c000066400000000000000000000077321404653710500152230ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * A servant will not be corrected by words: for * though he understand he will not answer. * -- Proverbs 29:19 */ /** * @file * @brief Daemon signal handling. * * Signals are handled differently in the daemon parent and its children. * * When the parent is killed, the entire process group is shut down, and the * pid file (if any) is removed. * * For both cases any temporary files created by the process are removed. **/ #include #include #include #include #include #include #include #include #include #include #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "dopt.h" #include "exec.h" #include "daemon.h" #ifdef HAVE_GSSAPI #include "auth.h" #endif /* This stores the pid of the parent daemon. It's used to make sure * that we only run the whole-group cleanup from inside the parent. * Remains 0 before parent initialization is complete and when run * from inetd. */ volatile pid_t dcc_master_pid = 0; static RETSIGTYPE dcc_daemon_terminate(int); /** * Catch all relevant termination signals. Set up in parent and also * applies to children. **/ void dcc_daemon_catch_signals(void) { /* SIGALRM is caught to allow for built-in timeouts when running test * cases. */ signal(SIGTERM, &dcc_daemon_terminate); signal(SIGINT, &dcc_daemon_terminate); signal(SIGHUP, &dcc_daemon_terminate); signal(SIGALRM, &dcc_daemon_terminate); } /** * Ignore hangup signal. * * This is only used in detached mode to make sure the daemon does not * quit when whoever started it closes their terminal. In nondetached * mode, the signal is logged and causes an exit as normal. **/ void dcc_ignore_sighup(void) { signal(SIGHUP, SIG_IGN); rs_trace("ignoring SIGHUP"); } /** * Just log, remove pidfile, and exit. * * Called when a daemon gets a fatal signal. * * Some cleanup is done only if we're the master/parent daemon. **/ static RETSIGTYPE dcc_daemon_terminate(int whichsig) { int am_parent; /* Make sure to remove handler before re-raising signal */ signal(whichsig, SIG_DFL); am_parent = getpid() == dcc_master_pid; /* syslog is not safe from a signal handler */ if (am_parent && !rs_trace_syslog) { #ifdef HAVE_STRSIGNAL rs_log_info("%s", strsignal(whichsig)); #else rs_log_info("terminated by signal %d", whichsig); #endif } dcc_cleanup_tempfiles_from_signal_handler(); if (am_parent) { dcc_remove_pid(); /* kill whole group */ kill(0, whichsig); } raise(whichsig); /* malloc() stuff not safe from a signal handler, but keep this here in case this memory non-leak is to be fixed in the future. */ /* #ifdef HAVE_GSSAPI if (dcc_auth_enabled) { dcc_gssapi_release_credentials(); if (opt_blacklist_enabled || opt_whitelist_enabled) { dcc_gssapi_free_list(); } } #endif*/ } distcc-3.4/src/emaillog.c000066400000000000000000000115651404653710500153720ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2007, 2009 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include "emaillog.h" #include "distcc.h" #include "util.h" #include "trace.h" #include "bulk.h" #include "snprintf.h" #include "exitcode.h" /* if never_send_email is true, we won't send email even if should_send_email is true */ static int should_send_email = 0; static int never_send_email = 0; static char *email_fname; static int email_fileno = -1; static int email_errno; static const char logmailer[] = "/bin/mail"; static const char email_subject[] = "distcc-pump email" ; static const char cant_send_message_format[] = "Please notify %s that distcc tried to send them email but failed"; static const char will_send_message_format[] = "Will send an email to %s"; static const char dcc_emaillog_whom_to_blame[] = DCC_EMAILLOG_WHOM_TO_BLAME; void dcc_please_send_email(void) { should_send_email = 1; } void dcc_setup_log_email(void) { never_send_email = !dcc_getenv_bool("DISTCC_ENABLE_DISCREPANCY_EMAIL", 0); if (never_send_email) return; /* email_fname lives until the program exits. The file itself will eventually get unlinked by dcc_cleanup_tempfiles(), but email_fileno survives until after we send email, so the file won't get removed until the emailing (child) process is done. */ dcc_make_tmpnam("distcc_error_log", "txt", &email_fname); email_fileno = open(email_fname, O_RDWR | O_TRUNC); if (email_fileno >= 0) { rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, email_fileno); rs_trace_set_level(RS_LOG_DEBUG); } else { email_errno = errno; } } int dcc_add_file_to_log_email(const char *description, const char *fname) { char begin[] = "\nBEGIN "; char end[] = "\nEND "; int in_fd = 0; off_t fsize; int ret; if (never_send_email) return 0; ret = dcc_open_read(fname, &in_fd, &fsize); if (ret != 0) return ret; ret = write(email_fileno, begin, strlen(begin)); if (ret != (ssize_t) strlen(begin)) return EXIT_IO_ERROR; ret = write(email_fileno, description, strlen(description)); if (ret != (ssize_t) strlen(description)) return EXIT_IO_ERROR; ret = write(email_fileno, "\n", 1); if (ret != 1) return EXIT_IO_ERROR; ret = dcc_pump_readwrite(email_fileno, in_fd, fsize); if (ret != 0) return ret; ret = write(email_fileno, end, strlen(end)); if (ret != (ssize_t) strlen(end)) return EXIT_IO_ERROR; ret = write(email_fileno, description, strlen(description)); if (ret != (ssize_t) strlen(description)) return EXIT_IO_ERROR; ret = write(email_fileno, "\n", 1); if (ret != 1) return EXIT_IO_ERROR; close(in_fd); return 0; } void dcc_maybe_send_email(void) { int child_pid = 0; const char *whom_to_blame; if ((whom_to_blame = getenv("DISTCC_EMAILLOG_WHOM_TO_BLAME")) == NULL) { whom_to_blame = dcc_emaillog_whom_to_blame; } char *cant_send_message_to; int ret; if (should_send_email == 0) return; if (never_send_email) return; rs_log_warning(will_send_message_format, whom_to_blame); ret = asprintf(&cant_send_message_to, cant_send_message_format, whom_to_blame); if (ret == -1) { fprintf(stderr, "error sending email: asprintf() failed"); return; } if (email_fileno < 0) { errno = email_errno; perror(cant_send_message_to); free(cant_send_message_to); return; } child_pid = fork(); if (child_pid == 0) { if (dup2(email_fileno, 0) == -1 || lseek(email_fileno, 0, SEEK_SET) == -1 || execl(logmailer, logmailer, "-s", email_subject, whom_to_blame, (char*)NULL) == -1) { perror(cant_send_message_to); /* The fork succeeded but we didn't get to exec, or the exec failed. We need to exit immediately, otherwise the cleanup code will get executed twice. */ _exit(1); } } else if (child_pid < 0) { perror(cant_send_message_to); } free(cant_send_message_to); } distcc-3.4/src/emaillog.h000066400000000000000000000022471404653710500153740ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef DCC_EMAILLOG_H #define DCC_EMAILLOG_H /* See also include_server/basics.py */ #define DCC_EMAILLOG_WHOM_TO_BLAME "distcc-pump-errors" void dcc_please_send_email(void); void dcc_setup_log_email(void); void dcc_maybe_send_email(void); int dcc_add_file_to_log_email(const char *description, const char *fname); #endif /* EMAILLOG_H */ distcc-3.4/src/exec.c000066400000000000000000000506121404653710500145210ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* 18 Their bows also shall dash the young men * to pieces; and they shall have no pity on * the fruit of the womb; their eyes shall not * spare children. * -- Isaiah 13 */ /** * @file * * Run compilers or preprocessors. * * The whole server is run in a separate process group and normally in a * separate session. (It is not a separate session in --no-detach debug * mode.) This allows us to cleanly kill off all children and all compilers * when the parent is terminated. * * @todo On Cygwin, fork() must be emulated and therefore will be * slow. It would be faster to just use their spawn() call, rather * than fork/exec. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __CYGWIN__ /* #define NOGDI */ #define RC_INVOKED #define NOWINRES #include #endif #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "exec.h" #include "lock.h" #include "hosts.h" #include "dopt.h" const int timeout_null_fd = -1; int dcc_job_lifetime = 0; static void dcc_inside_child(char **argv, const char *stdin_file, const char *stdout_file, const char *stderr_file) NORETURN; static void dcc_execvp(char **argv) NORETURN; void dcc_note_execution(struct dcc_hostdef *host, char **argv) { char *astr; astr = dcc_argv_tostr(argv); rs_log(RS_LOG_INFO|RS_LOG_NONAME, "exec on %s: %s", host->hostdef_string, astr); free(astr); } /** * Redirect stdin/out/err. Filenames may be NULL to leave them untouched. * * This is called when running a job remotely, but *not* when running * it locally, because people might e.g. want cpp to read from stdin. **/ int dcc_redirect_fds(const char *stdin_file, const char *stdout_file, const char *stderr_file) { int ret; if (stdin_file) if ((ret = dcc_redirect_fd(STDIN_FILENO, stdin_file, O_RDONLY))) return ret; if (stdout_file) { if ((ret = dcc_redirect_fd(STDOUT_FILENO, stdout_file, O_WRONLY | O_CREAT | O_TRUNC))) return ret; } if (stderr_file) { /* Open in append mode, because the server will dump its own error * messages into the compiler's error file. */ if ((ret = dcc_redirect_fd(STDERR_FILENO, stderr_file, O_WRONLY | O_CREAT | O_APPEND))) return ret; } return 0; } #ifdef __CYGWIN__ /* Execute a process WITHOUT console window and correctly redirect output. */ static DWORD dcc_execvp_cyg(char **argv, const char *input_file, const char *output_file, const char *error_file) { STARTUPINFO m_siStartInfo; PROCESS_INFORMATION m_piProcInfo; char cmdline[MAX_PATH+1]={0}; HANDLE stdin_hndl=INVALID_HANDLE_VALUE; HANDLE stdout_hndl=INVALID_HANDLE_VALUE; HANDLE stderr_hndl=INVALID_HANDLE_VALUE; char **ptr; DWORD exit_code; BOOL bRet=0; ZeroMemory(&m_siStartInfo, sizeof(STARTUPINFO)); ZeroMemory( &m_piProcInfo, sizeof(PROCESS_INFORMATION) ); /* Open files for IO redirection */ if (input_file && strcmp(input_file,"/dev/null")!=0) { if ((stdin_hndl = CreateFile(input_file,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_TEMPORARY,NULL)) == INVALID_HANDLE_VALUE) { exit_code = GetLastError(); goto cleanup; } } else stdin_hndl = GetStdHandle(STD_INPUT_HANDLE); if (output_file && strcmp(output_file,"/dev/null")!=0) { if ((stdout_hndl = CreateFile(output_file,GENERIC_WRITE,FILE_SHARE_READ,NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY,NULL)) == INVALID_HANDLE_VALUE) { exit_code = GetLastError(); goto cleanup; } } else stdout_hndl = GetStdHandle(STD_OUTPUT_HANDLE); if (error_file && strcmp(error_file,"/dev/null")!=0) { if ((stderr_hndl = CreateFile(error_file, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_TEMPORARY,NULL)) == INVALID_HANDLE_VALUE) { exit_code = GetLastError(); goto cleanup; } /* Seek to the end of file (ignore return code) */ SetFilePointer(stderr_hndl,0,NULL,FILE_END); } else stderr_hndl = GetStdHandle(STD_ERROR_HANDLE); /* Ensure handles can be inherited */ SetHandleInformation(stdin_hndl,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT); SetHandleInformation(stdout_hndl,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT); SetHandleInformation(stderr_hndl,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT); /*Set up members of STARTUPINFO structure.*/ m_siStartInfo.cb = sizeof(STARTUPINFO); m_siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; m_siStartInfo.wShowWindow = SW_HIDE; m_siStartInfo.hStdInput = stdin_hndl; m_siStartInfo.hStdOutput = stdout_hndl; m_siStartInfo.hStdError = stderr_hndl; /* Create command line */ for (ptr=argv;*ptr!=NULL;ptr++) { strcat(cmdline, *ptr); strcat(cmdline, " "); } /* Create the child process. */ bRet = CreateProcess(NULL, cmdline, /* application name */ NULL, /* process security attributes */ NULL, /* primary thread security attributes */ TRUE, /* handles are inherited */ CREATE_NEW_CONSOLE, /* creation flags */ NULL, /* use parent's environment */ NULL, /* use parent's current directory */ &m_siStartInfo, /* STARTUPINFO pointer */ &m_piProcInfo); /* receives PROCESS_INFORMATION */ if (!bRet) { exit_code = GetLastError(); goto cleanup; } WaitForSingleObject(m_piProcInfo.hProcess, (DWORD)(-1L)); /* return termination code and exit code*/ GetExitCodeProcess(m_piProcInfo.hProcess, &exit_code); CloseHandle(m_piProcInfo.hProcess); /* We can get here only if process creation failed */ cleanup: if (stdin_hndl != INVALID_HANDLE_VALUE) CloseHandle(stdin_hndl); if (stdout_hndl != INVALID_HANDLE_VALUE) CloseHandle(stdout_hndl); if (stderr_hndl != INVALID_HANDLE_VALUE) CloseHandle(stderr_hndl); if (bRet) ExitProcess(exit_code); /* Return cmdline's exit-code to parent process */ else return exit_code; /* Return failure reason to calling fn */ } #endif /** * Replace this program with another in the same process. * * Does not return, either execs the compiler in place, or exits with * a message. **/ static void dcc_execvp(char **argv) { char *slash; execvp(argv[0], argv); /* If we're still running, the program was not found on the path. One * thing that might have happened here is that the client sent an absolute * compiler path, but the compiler's located somewhere else on the server. * In the absence of anything better to do, we search the path for its * basename. * * Actually this code is called on both the client and server, which might * cause unintnded behaviour in contrived cases, like giving a full path * to a file that doesn't exist. I don't think that's a problem. */ slash = strrchr(argv[0], '/'); if (slash) execvp(slash + 1, argv); /* shouldn't be reached */ rs_log_error("failed to exec %s: %s", argv[0], strerror(errno)); dcc_exit(EXIT_COMPILER_MISSING); /* a generalization, i know */ } /** * Called inside the newly-spawned child process to execute a command. * Either executes it, or returns an appropriate error. * * This routine also takes a lock on localhost so that it's counted * against the process load. That lock will go away when the process * exits. * * In this current version locks are taken without regard to load limitation * on the current machine. The main impact of this is that cpp running on * localhost will cause jobs to be preferentially distributed away from * localhost, but it should never cause the machine to deadlock waiting for * localhost slots. * * @param what Type of process to be run here (cpp, cc, ...) **/ static void dcc_inside_child(char **argv, const char *stdin_file, const char *stdout_file, const char *stderr_file) { int ret; if ((ret = dcc_ignore_sigpipe(0))) goto fail; /* set handler back to default */ /* Ignore failure */ dcc_increment_safeguard(); #ifdef __CYGWIN__ /* This will execute compiler and CORRECTLY redirect output if compiler is * a native Windows application. If this never returns, it means the * compiler-execute succeeded. We use a hack to decide if it's a windows * application: if argv[0] starts with ":" or with "\\", then it's * a windows path and we try dcc_execvp_cyg. If not, we assume it's a * cygwin app and fall through to the unix-style forking, below. If we * guess wrong, dcc_execvp_cyg will probably fail with error 3 * (windows-exe for "path not found"), so again we'll fall through to the * unix-fork case. Otherwise we just fail in a generic way. * TODO(csilvers): Figure out the right way to deal with this. Running * cygwin apps via dcc_execvp_cyg segfaults (and takes a * long time to do it too), so I want to avoid that if * possible. I don't know enough about cygwin or * cygwin/windows interactions to know the right thing to * do here. Until distcc has cl.exe support, this may * all be a moot point anyway. */ if (argv[0] && ((argv[0][0] != '\0' && argv[0][1] == ':') || (argv[0][0] == '\\' && argv[0][1] == '\\'))) { DWORD status; status = dcc_execvp_cyg(argv, stdin_file, stdout_file, stderr_file); if (status != 3) { ret = EXIT_DISTCC_FAILED; goto fail; } } #endif /* do this last, so that any errors from previous operations are * visible */ if ((ret = dcc_redirect_fds(stdin_file, stdout_file, stderr_file))) goto fail; dcc_execvp(argv); ret = EXIT_DISTCC_FAILED; fail: dcc_exit(ret); } int dcc_new_pgrp(void) { /* If we're a session group leader, then we are not able to call * setpgid(). However, setsid will implicitly have put us into a new * process group, so we don't have to do anything. */ /* Does everyone have getpgrp()? It's in POSIX.1. We used to call * getpgid(0), but that is not available on BSD/OS. */ if (getpgrp() == getpid()) { rs_trace("already a process group leader"); return 0; } if (setpgid(0, 0) == 0) { rs_trace("entered process group"); return 0; } else { rs_trace("setpgid(0, 0) failed: %s", strerror(errno)); return EXIT_DISTCC_FAILED; } } /** * Run @p argv in a child asynchronously. * * stdin, stdout and stderr are redirected as shown, unless those * filenames are NULL. In that case they are left alone. * * @warning When called on the daemon, where stdin/stdout may refer to random * network sockets, all of the standard file descriptors must be redirected! **/ int dcc_spawn_child(char **argv, pid_t *pidptr, const char *stdin_file, const char *stdout_file, const char *stderr_file) { pid_t pid; dcc_trace_argv("forking to execute", argv); pid = fork(); if (pid == -1) { rs_log_error("failed to fork: %s", strerror(errno)); return EXIT_OUT_OF_MEMORY; /* probably */ } else if (pid == 0) { /* If this is a remote compile, * put the child in a new group, so we can * kill it and all its descendents without killing distccd * FIXME: if you kill distccd while it's compiling, and * the compiler has an infinite loop bug, the new group * will run forever until you kill it. */ if (stdout_file != NULL) { if (dcc_new_pgrp() != 0) rs_trace("Unable to start a new group\n"); } dcc_inside_child(argv, stdin_file, stdout_file, stderr_file); /* !! NEVER RETURN FROM HERE !! */ } else { *pidptr = pid; rs_trace("child started as pid%d", (int) pid); return 0; } } void dcc_reset_signal(int whichsig) { struct sigaction act_dfl; memset(&act_dfl, 0, sizeof act_dfl); act_dfl.sa_handler = SIG_DFL; sigaction(whichsig, &act_dfl, NULL); /* might be called from signal handler, therefore no IO to log a * message */ } static int sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) { /* Prefer use waitpid to wait4 for non-blocking wait with WNOHANG option */ #ifdef HAVE_WAITPID /* Just doing getrusage(children) is not sufficient, because other * children may have exited previously. */ memset(rusage, 0, sizeof *rusage); return waitpid(pid, status, options); #elif HAVE_WAIT4 return wait4(pid, status, options, rusage); #else #error Please port this #endif } /** * Blocking wait for a child to exit. This is used when waiting for * cpp, gcc, etc. * * This is not used by the daemon-parent; it has its own * implementation in dcc_reap_kids(). They could be unified, but the * parent only waits when it thinks a child has exited; the child * waits all the time. **/ int dcc_collect_child(const char *what, pid_t pid, int *wait_status, int in_fd) { struct rusage ru; pid_t ret_pid; int ret; int wait_timeout_sec; fd_set fds,readfds; wait_timeout_sec = dcc_job_lifetime; FD_ZERO(&readfds); if (in_fd != timeout_null_fd){ FD_SET(in_fd,&readfds); } while (!dcc_job_lifetime || wait_timeout_sec-- >= 0) { /* If we're called with a socket, break out of the loop if the socket * disconnects. To do that, we need to block in select, not in * sys_wait4. (Only waitpid uses WNOHANG to mean don't block ever, * so I've modified sys_wait4 above to preferentially call waitpid.) */ int flags = (in_fd == timeout_null_fd) ? 0 : WNOHANG; ret_pid = sys_wait4(pid, wait_status, flags, &ru); if (ret_pid == -1) { if (errno == EINTR) { rs_trace("wait4 was interrupted; retrying"); } else { rs_log_error("sys_wait4(pid=%d) borked: %s", (int) pid, strerror(errno)); return EXIT_DISTCC_FAILED; } } else if (ret_pid != 0) { /* This is not the main user-visible message; that comes from * critique_status(). */ rs_trace("%s child %ld terminated with status %#x", what, (long) ret_pid, *wait_status); rs_log_info("%s times: user %lld.%06lds, system %lld.%06lds, " "%ld minflt, %ld majflt", what, (long long) ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec, (long long) ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec, ru.ru_minflt, ru.ru_majflt); return 0; } /* check timeout */ if (in_fd != timeout_null_fd) { struct timeval timeout; /* If client disconnects, the socket will become readable, * and a read should return -1 and set errno to EPIPE. */ fds = readfds; timeout.tv_sec = 1; timeout.tv_usec = 0; ret = select(in_fd+1,&fds,NULL,NULL,&timeout); if (ret == 1) { char buf; int nread = read(in_fd, &buf, 1); if ((nread == -1) && (errno == EWOULDBLOCK)) { /* spurious wakeup, ignore */ ; } else if (nread == 0) { rs_log_error("Client fd disconnected, killing job"); /* If killpg fails, it might means the child process is not * in a new group, so, just kill the child process */ if (killpg(pid,SIGTERM)!=0) kill(pid, SIGTERM); return EXIT_IO_ERROR; } else if (nread == 1) { rs_log_error("Bug! Read from fd succeeded when checking " "whether client disconnected!"); } else { rs_log_error("Bug! nread %d, errno %d checking whether " "client disconnected!", nread, errno); } } } else { poll(NULL, 0, 1000); } } /* If timeout, also kill the child process */ if (killpg(pid, SIGTERM) != 0) kill(pid, SIGTERM); rs_log_error("Compilation takes too long, timeout."); return EXIT_TIMEOUT; } /** * Analyze and report to the user on a command's exit code. * * @param command short human-readable description of the command (perhaps * argv[0]) * * @returns 0 if the command succeeded; 128+SIGNAL if it stopped on a * signal; otherwise the command's exit code. **/ int dcc_critique_status(int status, const char *command, const char *input_fname, struct dcc_hostdef *host, int verbose) { int logmode; /* verbose mode is only used for executions that the user is likely to * particularly need to know about */ if (verbose) logmode = RS_LOG_ERR | RS_LOG_NONAME; else logmode = RS_LOG_INFO | RS_LOG_NONAME; if (input_fname == NULL) input_fname = "(null)"; if (WIFSIGNALED(status)) { #ifdef HAVE_STRSIGNAL rs_log(logmode, "%s %s on %s: %s%s", command, input_fname, host->hostdef_string, strsignal(WTERMSIG(status)), WCOREDUMP(status) ? " (core dumped)" : ""); #else rs_log(logmode, "%s %s on %s terminated by signal %d%s", command, input_fname, host->hostdef_string, WTERMSIG(status), WCOREDUMP(status) ? " (core dumped)" : ""); #endif /* Unix convention is to return 128+signal when a subprocess crashes. */ return 128 + WTERMSIG(status); } else if (WEXITSTATUS(status) == 1) { /* Normal failure gives exit code 1, so handle that specially */ rs_log(logmode, "%s %s on %s failed", command, input_fname, host->hostdef_string); return WEXITSTATUS(status); } else if (WEXITSTATUS(status)) { /* This is a tough call; we don't really want to clutter the client's * error stream, but if we don't say where the compilation failed then * people may find it hard to work things out. */ rs_log(logmode, "%s %s on %s failed with exit code %d", command, input_fname, host->hostdef_string, WEXITSTATUS(status)); return WEXITSTATUS(status); } else { rs_log(RS_LOG_INFO|RS_LOG_NONAME, "%s %s on %s completed ok", command, input_fname, host->hostdef_string); return 0; } } distcc-3.4/src/exec.h000066400000000000000000000035201404653710500145220ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* exec.c */ extern const int timeout_null_fd; extern int dcc_job_lifetime; int dcc_redirect_fds(const char *stdin_file, const char *stdout_file, const char *stderr_file); int dcc_spawn_child(char **argv, pid_t *pidptr, const char *, const char *, const char *); /* if in_fd is timeout_null_fd, means this parameter is not used */ int dcc_collect_child(const char *what, pid_t pid, int *wait_status, int in_fd); int dcc_critique_status(int s, const char *, const char *, struct dcc_hostdef *host, int verbose); void dcc_note_execution(struct dcc_hostdef *host, char **argv); int dcc_new_pgrp(void); void dcc_reset_signal(int whichsig); #ifndef W_EXITCODE # define W_EXITCODE(exit, signal) ((exit)<<8 | (signal)) #endif distcc-3.4/src/exitcode.h000066400000000000000000000050651404653710500154100ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef _DISTCC_EXITCODE_H #define _DISTCC_EXITCODE_H /** * @file * * Common exit codes. **/ /** * Common exit codes for both client and server. * * These need to be in [1,255] so that they can be used as exit() codes. They * are fairly high so that they're not confused with the real error code from * gcc. * * WARNING: ANY CHANGES HERE NEED TO BE DUPLICATED IN THE MAN PAGE * (../man/distcc.1). **/ enum dcc_exitcode { EXIT_DISTCC_FAILED = 100, /**< General failure */ EXIT_BAD_ARGUMENTS = 101, EXIT_BIND_FAILED = 102, EXIT_CONNECT_FAILED = 103, EXIT_COMPILER_CRASHED = 104, EXIT_OUT_OF_MEMORY = 105, EXIT_BAD_HOSTSPEC = 106, EXIT_IO_ERROR = 107, EXIT_TRUNCATED = 108, EXIT_PROTOCOL_ERROR = 109, EXIT_COMPILER_MISSING = 110, /**< Compiler executable not found */ EXIT_RECURSION = 111, /**< distcc called itself */ EXIT_SETUID_FAILED = 112, /**< Failed to discard privileges */ EXIT_ACCESS_DENIED = 113, /**< Network access denied */ EXIT_BUSY = 114, /**< In use by another process. */ EXIT_NO_SUCH_FILE = 115, EXIT_NO_HOSTS = 116, EXIT_GONE = 117, /**< No longer relevant */ EXIT_TIMEOUT = 118, #ifdef HAVE_GSSAPI EXIT_GSSAPI_FAILED = 119, /**< GSS-API - Catchall error code for GSS-API related errors. */ #endif EXIT_LOCAL_CPP = 120 }; #endif /* _DISTCC_EXITCODE_H */ distcc-3.4/src/filename.c000066400000000000000000000203201404653710500153460ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** * @file * * Everything we know about C filenames. * * We need to have some heuristics about input and output filenames to * understand command lines, because that's what cc does. * * @note As of 0.10, .s and .S files are never distributed, because * they might contain '.include' pseudo-operations, which are resolved * by the assembler. */ /** * Return a pointer to the extension, including the dot, or NULL. **/ char * dcc_find_extension(char *sfile) { char *dot; dot = strrchr(sfile, '.'); if (dot == NULL || dot[1] == '\0') { /* make sure there's space for one more character after the * dot */ return NULL; } return dot; } /** * Return a pointer to the extension, including the dot, or NULL. * Same as dcc_find_extension(), but the argument and return * value are both pointers to const. **/ const char * dcc_find_extension_const(const char *sfile) { #if 0 return dcc_find_extension((char *) sfile); #else /* The following intermediate variable works around a bug in gcc 4.2.3 where * for the code above gcc spuriously reports "warning: passing argument 1 * of 'dcc_find_extension' discards qualifiers from pointer target type", * despite the explicit cast. */ char *sfile_nonconst = (char *)sfile; return dcc_find_extension(sfile_nonconst); #endif } /** * Return a pointer to the basename of the file (everything after the * last slash.) If there is no slash, return the whole filename, * which is presumably in the current directory. **/ const char * dcc_find_basename(const char *sfile) { char *slash; if (!sfile) return sfile; slash = strrchr(sfile, '/'); if (slash == NULL || slash[1] == '\0') return sfile; return slash+1; } /** Truncate the filename to its dirname (everything before the last slash). * If the filename ends with a slash, just lop off the last slash. * Note: this is destructive. */ void dcc_truncate_to_dirname(char *file) { char *slash = 0; slash = strrchr(file, '/'); if (slash == NULL) { file[0] = '\0'; } else { *slash = '\0'; } } static int dcc_set_file_extension(const char *sfile, const char *new_ext, char **ofile) { char *dot, *o; o = strdup(sfile); if (!o) { rs_log_error("strdup failed (out of memory?)"); return EXIT_DISTCC_FAILED; } dot = dcc_find_extension(o); if (!dot) { rs_log_error("couldn't find extension in \"%s\"", o); return EXIT_DISTCC_FAILED; } if (strlen(dot) < strlen(new_ext)) { rs_log_error("not enough space for new extension"); return EXIT_DISTCC_FAILED; } strcpy(dot, new_ext); *ofile = o; return 0; } /* * Apple extensions: * file.mm, file.M * Objective-C++ source code which must be preprocessed. (APPLE ONLY) * * file.mii Objective-C++ source code which should not be * preprocessed. (APPLE ONLY) * * http://developer.apple.com/techpubs/macosx/DeveloperTools/gcc3/gcc/Overall-Options.html */ /** * If you preprocessed a file with extension @p e, what would you get? * * @param e original extension (e.g. ".c") * * @returns preprocessed extension, (e.g. ".i"), or NULL if * unrecognized. **/ const char * dcc_preproc_exten(const char *e) { if (e[0] != '.') return NULL; e++; if (!strcmp(e, "i") || !strcmp(e, "c")) { return ".i"; } else if (!strcmp(e, "c") || !strcmp(e, "cc") || !strcmp(e, "cpp") || !strcmp(e, "cxx") || !strcmp(e, "cp") || !strcmp(e, "c++") || !strcmp(e, "C") || !strcmp(e, "ii")) { return ".ii"; } else if(!strcmp(e,"mi") || !strcmp(e, "m")) { return ".mi"; } else if(!strcmp(e,"mii") || !strcmp(e,"mm") || !strcmp(e,"M")) { return ".mii"; } else if (!strcasecmp(e, "s")) { return ".s"; } else { return NULL; } } /** * Does the extension of this file indicate that it is already * preprocessed? **/ int dcc_is_preprocessed(const char *sfile) { const char *dot, *ext; dot = dcc_find_extension_const(sfile); if (!dot) return 0; ext = dot+1; switch (ext[0]) { #ifdef ENABLE_REMOTE_ASSEMBLE case 's': /* .S needs to be run through cpp; .s does not */ return !strcmp(ext, "s"); #endif case 'i': return !strcmp(ext, "i") || !strcmp(ext, "ii"); case 'm': return !strcmp(ext, "mi") || !strcmp(ext, "mii"); default: return 0; } } /** * Work out whether @p sfile is source based on extension **/ int dcc_is_source(const char *sfile) { const char *dot, *ext; dot = dcc_find_extension_const(sfile); if (!dot) return 0; ext = dot+1; /* you could expand this out further into a RE-like set of case * statements, but i'm not sure it's that important. */ switch (ext[0]) { case 'i': return !strcmp(ext, "i") || !strcmp(ext, "ii"); case 'c': return !strcmp(ext, "c") || !strcmp(ext, "cc") || !strcmp(ext, "cpp") || !strcmp(ext, "cxx") || !strcmp(ext, "cp") || !strcmp(ext, "c++"); case 'C': return !strcmp(ext, "C"); case 'm': return !strcmp(ext,"m") || !strcmp(ext,"mm") || !strcmp(ext,"mi") || !strcmp(ext,"mii"); case 'M': return !strcmp(ext, "M"); #ifdef ENABLE_REMOTE_ASSEMBLE case 's': return !strcmp(ext, "s"); case 'S': return !strcmp(ext, "S"); #endif default: return 0; } } /** * Decide whether @p filename is an object file, based on its * extension. **/ int dcc_is_object(const char *filename) { const char *dot; dot = dcc_find_extension_const(filename); if (!dot) return 0; return !strcmp(dot, ".o"); } /* Some files should always be built locally... */ int dcc_source_needs_local(const char *filename) { const char *p; p = dcc_find_basename(filename); if (str_startswith("conftest.", p) || str_startswith("tmp.conftest.", p)) { rs_trace("autoconf tests are run locally: %s", filename); return EXIT_DISTCC_FAILED; } return 0; } /** * Work out the default object file name the compiler would use if -o * was not specified. We don't need to worry about "a.out" because * we've already determined that -c or -S was specified. * * However, the compiler does put the output file in the current * directory even if the source file is elsewhere, so we need to strip * off all leading directories. * * @param sfile Source filename. Assumed to match one of the * recognized patterns, otherwise bad things might happen. **/ int dcc_output_from_source(const char *sfile, const char *out_extn, char **ofile) { char *slash; if ((slash = strrchr(sfile, '/'))) sfile = slash+1; if (strlen(sfile) < 3) { rs_log_error("source file %s is bogus", sfile); return EXIT_DISTCC_FAILED; } return dcc_set_file_extension(sfile, out_extn, ofile); } distcc-3.4/src/fix_debug_info.c000066400000000000000000000374561404653710500165570ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Fergus Henderson */ /* * fix_debug_info.cc: * Performs search-and-replace in the debug info section of an ELF file. */ #include #include #include #include #include #include #include #include #ifdef HAVE_ELF_H #include #endif #include #ifdef HAVE_SYS_MMAN_H #include #endif #include "trace.h" #include "fix_debug_info.h" /* XINDEX isn't defined everywhere, but where it is, it's always the * same as HIRESERVE, so I think this should be safe. */ #ifndef SHN_XINDEX #define SHN_XINDEX SHN_HIRESERVE #endif #ifdef HAVE_ELF_H /* * Search for an ELF section of the specified name and type. * Given an ELF file that has been mmapped (or read) into memory starting * at @p elf_mapped_base, find the section with the desired name and type, * and return (via the parameters) its start point and size. * Returns 1 if found, 0 otherwise. */ static int FindElfSection(const void *elf_mapped_base, off_t elf_size, const char *desired_section_name, const void **section_start, int *section_size) { const unsigned char *elf_base = (const unsigned char *) elf_mapped_base; /* The double cast below avoids warnings with -Wcast-align. */ const Elf32_Ehdr *elf32_header = (const Elf32_Ehdr *) (const void *) elf_base; unsigned int i; unsigned int num_sections; assert(elf_mapped_base); assert(section_start); assert(section_size); *section_start = NULL; *section_size = 0; /* * There are two kinds of ELF files, 32-bit and 64-bit. They have similar * but slightly different file structures. It's OK to use the elf32_header * structure at this point, prior to checking whether this file is a 32 or * 64 bit ELF file, so long as we only access the e_ident field, because * the layout of the e_ident field is the same for both kinds: it's the * first field in the struct, so its offset is zero, and its size is the * same for both 32 and 64 bit ELF files. * * The magic number which identifies an ELF file is stored in the * first few bytes of the e_ident field, which is also the first few * bytes of the file. */ if (elf_size < SELFMAG || memcmp(elf32_header, ELFMAG, SELFMAG) != 0) { rs_trace("object file is not an ELF file"); return 0; } /* * The ELF file layouts are defined using fixed-size data structures * in , so we don't need to worry about the host computer's * word size. But we do need to worry about the host computer's * enddianness, because ELF header fields use the same endianness * as the target computer. When cross-compiling to a target with * a different endianness, we would need to byte-swap all the fields * that we use. Right now we don't handle that case. * * TODO(fergus): * handle object files with different endianness than the host. */ #if WORDS_BIGENDIAN if (elf32_header->e_ident[EI_DATA] != ELFDATA2MSB) { rs_trace("sorry, not fixing debug info: " "distcc server host is big-endian, object file is not"); return 0; } #else if (elf32_header->e_ident[EI_DATA] != ELFDATA2LSB) { rs_trace("sorry, not fixing debug info: " "distcc server host is little-endian, object file is not"); return 0; } #endif /* * Warning: the following code section is duplicated: * once for 32-bit ELF files, and again for 64-bit ELF files. * Please be careful to keep them consistent! */ if (elf32_header->e_ident[EI_CLASS] == ELFCLASS32) { const Elf32_Ehdr *elf_header = elf32_header; const Elf32_Shdr *sections = /* The double cast below avoids warnings with -Wcast-align. */ (const Elf32_Shdr *) (const void *) (elf_base + elf_header->e_shoff); const Elf32_Shdr *string_section = sections + elf_header->e_shstrndx; const Elf32_Shdr *desired_section = NULL; if (elf_size < (off_t) sizeof(*elf_header)) { rs_trace("object file is too small for ELF header; maybe got truncated?"); return 0; } if (elf_header->e_shoff <= 0 || elf_header->e_shoff > elf_size - sizeof(Elf32_Shdr)) { rs_trace("invalid e_shoff value in ELF header"); return 0; } if (elf_header->e_shstrndx == SHN_UNDEF) { rs_trace("object file has no section name string table" " (e_shstrndx == SHN_UNDEF)"); return 0; } /* Special case for more sections than will fit in e_shstrndx. */ if (elf_header->e_shstrndx == SHN_XINDEX) { string_section = sections + sections[0].sh_link; } num_sections = elf_header->e_shnum; /* Special case for more sections than will fit in e_shnum. */ if (num_sections == 0) { num_sections = sections[0].sh_size; } for (i = 0; i < num_sections; ++i) { const char *section_name = (char *)(elf_base + string_section->sh_offset + sections[i].sh_name); if (!strcmp(section_name, desired_section_name)) { desired_section = §ions[i]; break; } } if (desired_section != NULL && desired_section->sh_size > 0) { int desired_section_size = desired_section->sh_size; *section_start = elf_base + desired_section->sh_offset; *section_size = desired_section_size; return 1; } else { return 0; } } else if (elf32_header->e_ident[EI_CLASS] == ELFCLASS64) { /* The double cast below avoids warnings with -Wcast-align. */ const Elf64_Ehdr *elf_header = (const Elf64_Ehdr *) (const void *) elf_base; const Elf64_Shdr *sections = (const Elf64_Shdr *) (const void *) (elf_base + elf_header->e_shoff); const Elf64_Shdr *string_section = sections + elf_header->e_shstrndx; const Elf64_Shdr *desired_section = NULL; if (elf_size < (off_t) sizeof(*elf_header)) { rs_trace("object file is too small for ELF header; maybe got truncated?"); return 0; } if (elf_header->e_shoff <= 0 || elf_header->e_shoff > (size_t) elf_size - sizeof(Elf64_Shdr)) { rs_trace("invalid e_shoff value in ELF header"); return 0; } if (elf_header->e_shstrndx == SHN_UNDEF) { rs_trace("object file has no section name string table" " (e_shstrndx == SHN_UNDEF)"); return 0; } /* Special case for more sections than will fit in e_shstrndx. */ if (elf_header->e_shstrndx == SHN_XINDEX) { string_section = sections + sections[0].sh_link; } num_sections = elf_header->e_shnum; if (num_sections == 0) { /* Special case for more sections than will fit in e_shnum. */ num_sections = sections[0].sh_size; } for (i = 0; i < num_sections; ++i) { const char *section_name = (char*)(elf_base + string_section->sh_offset + sections[i].sh_name); if (!strcmp(section_name, desired_section_name)) { desired_section = §ions[i]; break; } } if (desired_section != NULL && desired_section->sh_size > 0) { int desired_section_size = desired_section->sh_size; *section_start = elf_base + desired_section->sh_offset; *section_size = desired_section_size; return 1; } else { return 0; } } else { rs_trace("unknown ELF class - neither ELFCLASS32 nor ELFCLASS64"); return 0; } } /* * Search in a memory buffer (starting at @p base and of size @p size) * for a string (@p search), and replace @p search with @p replace * in all null-terminated strings that contain @p search. */ static int replace_string(void *base, size_t size, const char *search, const char *replace) { char *start = (char *) base; char *end = (char *) base + size; int count = 0; char *p; size_t search_len = strlen(search); size_t replace_len = strlen(replace); assert(replace_len == search_len); if (size < search_len + 1) return 0; for (p = start; p < end - search_len - 1; p++) { if (memcmp(p, search, search_len) == 0) { memcpy(p, replace, replace_len); count++; } } return count; } /* * Map the specified file into memory with MAP_SHARED. * Returns the mapped address, and stores the file descriptor in @p p_fd. * It also fstats the file and stores the results in @p st. * Logs an error message and returns NULL on failure. */ static void *mmap_file(const char *path, int *p_fd, struct stat *st) { int fd; void *base; fd = open(path, O_RDWR); if (fd < 0) { rs_log_error("error opening file '%s': %s", path, strerror(errno)); return NULL; } if (fstat(fd, st) != 0) { rs_log_error("fstat of file '%s' failed: %s", path, strerror(errno)); close(fd); return NULL; } if (st->st_size <= 0) { rs_log_error("file '%s' has invalid file type or size", path); close(fd); return NULL; } #ifdef HAVE_SYS_MMAP_H base = mmap(NULL, st->st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (base == MAP_FAILED) { rs_log_error("mmap of file '%s' failed: %s", path, strerror(errno)); close(fd); return NULL; } #else base = malloc(st->st_size); if (base == NULL) { rs_log_error("can't allocate buffer for %s: malloc failed", path); close(fd); return NULL; } errno = 0; if (read(fd, base, st->st_size) != st->st_size) { rs_log_error("can't read %ld bytes from %s: %s", (long) st->st_size, path, strerror(errno)); close(fd); return NULL; } #endif *p_fd = fd; return base; } static int munmap_file(void *base, const char *path, int fd, const struct stat *st) { int status = 0; #ifdef HAVE_SYS_MMAP_H if (munmap(base, st->st_size) != 0) { rs_log_error("munmap of file '%s' failed: %s", path, strerror(errno)); status = 1; } #else errno = 0; if (lseek(fd, 0, SEEK_SET) == -1) { rs_log_error("can't seek to start of %s: %s", path, strerror(errno)); status = 1; } else if (write(fd, base, st->st_size) != st->st_size) { rs_log_error("can't write %ld bytes to %s: %s", (long) st->st_size, path, strerror(errno)); status = 1; } #endif if (close(fd) != 0) { rs_log_error("close of file '%s' failed: %s", path, strerror(errno)); status = 1; } return status; } /* * Update the ELF file residing at @p path, replacing all occurrences * of @p search with @p replace in the section named @p desired_section_name. * The replacement string must be the same length or shorter than * the search string. */ static void update_section(const char *path, const void *base, off_t size, const char *desired_section_name, const char *search, const char *replace) { const void *desired_section = NULL; int desired_section_size = 0; if (FindElfSection(base, size, desired_section_name, &desired_section, &desired_section_size) && desired_section_size > 0) { /* The local variable below works around a bug in some versions * of gcc (4.2.1?), which issues an erroneous warning if * 'desired_section_rw' is replaced with '(void *) desired_section' * in the call below, causing compile errors with -Werror. */ void *desired_section_rw = (void *) desired_section; int count = replace_string(desired_section_rw, desired_section_size, search, replace); if (count == 0) { rs_trace("\"%s\" section of file %s has no occurrences of \"%s\"", desired_section_name, path, search); } else { rs_log_info("updated \"%s\" section of file \"%s\": " "replaced %d occurrences of \"%s\" with \"%s\"", desired_section_name, path, count, search, replace); if (count > 1) { rs_log_warning("only expected to replace one occurrence!"); } } } else { rs_trace("file %s has no \"%s\" section", path, desired_section_name); } } /* * Update the ELF file residing at @p path, replacing all occurrences * of @p search with @p replace in that file's ".debug_info" or * ".debug_str" section. * The replacement string must be the same length or shorter than * the search string. * Returns 0 on success (whether or not ".debug_info" section was * found or updated). * Returns 1 on serious error that should cause distcc to fail. */ static int update_debug_info(const char *path, const char *search, const char *replace) { struct stat st; int fd; void *base; base = mmap_file(path, &fd, &st); if (base == NULL) { return 0; } update_section(path, base, st.st_size, ".debug_info", search, replace); update_section(path, base, st.st_size, ".debug_str", search, replace); return munmap_file(base, path, fd, &st); } #endif /* HAVE_ELF_H */ /* * Edit the ELF file residing at @p path, changing all occurrences of * the path @p server_path to @p client_path in the debugging info. * * We're a bit sloppy about that; rather than properly parsing * the DWARF debug info, finding the DW_AT_comp_dir (compilation working * directory) field and the DW_AT_name (source file name) field, * we just do a search-and-replace in the ".debug_info" and ".debug_str" * sections. But this is good enough. * * Returns 0 on success (whether or not the ".debug_info" and ".debug_str" * sections were found or updated). * Returns 1 on serious error that should cause distcc to fail. */ int dcc_fix_debug_info(const char *path, const char *client_path, const char *server_path) { #ifndef HAVE_ELF_H rs_trace("no , so can't change %s to %s in debug info for %s", server_path, client_path, path); return 0; #else /* * We can only safely replace a string with another of exactly * the same length. (Replacing a string with a shorter string * results in errors from gdb.) * So we append trailing slashes on the client side path. */ size_t client_path_len = strlen(client_path); size_t server_path_len = strlen(server_path); assert(client_path_len <= server_path_len); char *client_path_plus_slashes = malloc(server_path_len + 1); if (!client_path_plus_slashes) { rs_log_crit("failed to allocate memory"); return 1; } strcpy(client_path_plus_slashes, client_path); while (client_path_len < server_path_len) { client_path_plus_slashes[client_path_len++] = '/'; } client_path_plus_slashes[client_path_len] = '\0'; rs_log_info("client_path_plus_slashes = %s", client_path_plus_slashes); return update_debug_info(path, server_path, client_path_plus_slashes); #endif } #ifdef TEST const char *rs_program_name; int main(int argc, char **argv) { rs_program_name = argv[0]; rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO); rs_trace_set_level(RS_LOG_DEBUG); if (argc != 4) { rs_log_error("Usage: %s ", rs_program_name); exit(1); } return dcc_fix_debug_info(argv[1], argv[2], argv[3]); } #endif distcc-3.4/src/fix_debug_info.h000066400000000000000000000021241404653710500165440ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Fergus Henderson */ #ifndef DISTCC_FIX_DEBUG_INFO_H__ #define DISTCC_FIX_DEBUG_INFO_H__ int dcc_fix_debug_info(const char *path, const char *client_cwd, const char *server_cwd); #endif /* DISTCC_FIX_DEBUG_INFO_H__ */ distcc-3.4/src/gcc-id.c000066400000000000000000000051311404653710500147170ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright (C) 2007 Lennart Poettering * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include "distcc.h" #include "hosts.h" #include "zeroconf.h" #include "trace.h" static char *strip_bad_chars(char *s) { char *k; for (k = s; *k; k++) { if (*k >= 'a' && *k <= 'z') continue; if (*k >= '0' && *k <= '9') continue; if (*k >= 'A' && *k <= 'Z') *k = tolower(*k); else *k = '-'; } return s; } static char* read_string_from_popen(const char *cmdline, char *s, size_t nbytes) { FILE *p = NULL; char *ret = NULL; errno = 0; if (!(p = popen(cmdline, "r"))) { rs_log_crit("Failed to read string from C compiler: %s\n", errno ? strerror(errno) : "failure"); goto fail; } if (!fgets(s, (int) nbytes, p)) { rs_log_crit("Failed to read string from C compiler.\n"); goto fail; } s[nbytes-1] = 0; s[strcspn(s, " \t\n\r")] = 0; ret = s; fail: if (p) pclose(p); return ret; } char* dcc_get_gcc_version(char *s, size_t nbytes) { return read_string_from_popen("cc -dumpversion", s, nbytes); } char* dcc_get_gcc_machine(char *s, size_t nbytes) { return read_string_from_popen("cc -dumpmachine", s, nbytes); } char* dcc_make_dnssd_subtype(char *stype, size_t nbytes, const char *v, const char *m) { char version[64], machine[64]; strncpy(version, v, sizeof(version)-1); version[sizeof(version)-1] = 0; strncpy(machine, m, sizeof(machine)-1); machine[sizeof(machine)-1] = 0; strip_bad_chars(version); strip_bad_chars(machine); snprintf(stype, nbytes, "_%s--%s._sub." DCC_DNS_SERVICE_TYPE, machine, version); stype[nbytes-1] = 0; return stype; } distcc-3.4/src/h_argvtostr.c000066400000000000000000000027551404653710500161440ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_argvtostr.c,v 1.4 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" const char *rs_program_name = __FILE__; /** * @file * * Test argv-to-string converter. **/ int main(int argc, char *argv[]) { rs_trace_set_level(RS_LOG_WARNING); if (argc < 2) { rs_log_error("usage: h_scanargs COMMAND ARG...\n"); return 1; } printf("%s\n", dcc_argv_tostr(&argv[1])); return 0; } distcc-3.4/src/h_compile.c000066400000000000000000000063161404653710500155360ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_exten.c,v 1.7 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * Test harness for functions in compile.c. (Only one so far.) **/ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "compile.h" #define USAGE \ "usage: h_compile COMMAND ARGS...\n" \ "where\n" \ " COMMAND is dcc_fresh_dependency_exists,\n" \ " with ARGS being DOTD_FNAME EXCL_PAT REF_TIME\n" \ "or\n" \ " COMMAND is dcc_discrepancy_filename\n" const char *rs_program_name = __FILE__; int main(int argc, char *argv[]) { rs_trace_set_level(RS_LOG_DEBUG); rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO); if (argc < 2) { rs_log_error(USAGE); return 1; } if (strcmp(argv[1], "dcc_fresh_dependency_exists") == 0) { if (argc != 5) { rs_log_error("dcc_fresh_dependency_exists expects DOTD_FNAME " "EXCL_PAT REF_TIME"); return 1; } errno = 0; char *ptr; time_t ref_time = (time_t)strtol(argv[4], &ptr, 0); if (errno || (*ptr != '\0')) { rs_log_error("strtol failed"); return 1; } else { char *result; int ret; ret = dcc_fresh_dependency_exists((const char *)argv[2], (const char *)argv[3], ref_time, &result); if (ret) printf("h_compile.c: UNEXPECTED RETURN VALUE\n"); else printf("result %s\n", result ? result : "(NULL)"); if (result) free(result); } } else if (strcmp(argv[1], "dcc_discrepancy_filename") == 0) { if (argc != 2) { rs_log_error("dcc_discrepancy_filename expects no arguments"); return 1; } char *result; int ret = dcc_discrepancy_filename(&result); if (ret) printf("h_compile.c: UNEXPECTED RETURN VALUE\n"); else printf("%s", result ? result : "(NULL)"); } else { rs_log_error(USAGE); return 1; } return 0; } distcc-3.4/src/h_dotd.c000066400000000000000000000040711404653710500150340ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Test harness for dotd.c. **/ #include #include #include #include #include #include #include #include "dotd.h" #include "trace.h" #define USAGE \ "usage: h_dotd COMMAND ARGS...\n" \ "where\n" \ " COMMAND is dcc_get_dotd_info, ARGS is NAME\n" const char *rs_program_name = __FILE__; int main(int argc, char *argv[]) { rs_trace_set_level(RS_LOG_WARNING); if (argc < 2) { rs_log_error(USAGE); return 1; } if (strcmp(argv[1], "dcc_get_dotd_info") == 0) { char *dotd_fname; int needs_dotd, sets_dotd_target; char *dotd_target; dcc_get_dotd_info(argv + 2, &dotd_fname, &needs_dotd, &sets_dotd_target, &dotd_target); /* Print out in a format easily digested in Python. */ printf("{'dotd_fname':'%s', 'needs_dotd':%d, 'sets_dotd_target':%d," " 'dotd_target':'%s'}", dotd_fname, needs_dotd, sets_dotd_target, dotd_target ? dotd_target : "None"); } else { rs_log_error(USAGE); return 1; } return 0; } distcc-3.4/src/h_exten.c000066400000000000000000000030351404653710500152240ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_exten.c,v 1.7 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" const char *rs_program_name = __FILE__; /** * Test harness that makes sure the filename extension manipulation * stuff works OK. **/ int main(int argc, char *argv[]) { char *ex; if (argc != 2) { rs_log_error("usage: h_exten FILENAME"); return 1; } printf("%s", (ex = dcc_find_extension(argv[1])) ? ex : "(NULL)"); return 0; } distcc-3.4/src/h_getline.c000066400000000000000000000033621404653710500155330ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2009 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Fergus Henderson */ /* * h_getline.cc: * Helper for tests of getline(). */ #include #include "distcc.h" #include "util.h" #include const char *rs_program_name = "h_getline"; int main(int argc, char** argv) { char *line; size_t n; int c, i; if (argc > 1) { n = atoi(argv[1]); line = malloc(n); } else { n = 0; line = NULL; } printf("original n = %lu, ", (unsigned long) n); long result = getline(&line, &n, stdin); if (result > (long) n) { fprintf(stderr, "ERROR: return value > buffer size\n"); exit(1); } printf("returned %ld, ", (long) result); printf("n = %lu, ", (unsigned long) n); printf("line = '"); for (i = 0; i < result; i++) { putchar(line[i]); } printf("', rest = '"); while ((c = getchar()) != EOF) putchar(c); printf("'\n"); return 0; } distcc-3.4/src/h_hosts.c000066400000000000000000000057551404653710500152540ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_hosts.c,v 1.13 2004/01/30 12:39:14 mbp Exp $ * * Copyright (C) 2002, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Test harness for hosts.c. * * Precondition: DISTCC_HOSTS set in the environment. * * Action: calls the environment parser. * * Output: on the first line, the number of hosts. Then, one per * line, either * * "ssh" USER HOST COMMAND * "tcp" HOST PORT **/ #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "hosts.h" #include "exitcode.h" const char *rs_program_name = "h_hosts"; int main(int UNUSED(argc), char **argv) { struct dcc_hostdef *list, *e; int nhosts, i; int ret; rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO); if (argv[1] && !strcmp(argv[1], "-v")) { rs_trace_set_level(RS_LOG_DEBUG); } if ((ret = dcc_get_hostlist(&list, &nhosts)) != 0) { rs_log_error("failed to parse \"%s\"", getenv("DISTCC_HOSTS")); exit(ret); } printf("%d\n", nhosts); for (i = 0, e = list; i < nhosts; i++, e = e->next) { if (!e) { rs_log_error("entry %d is NULL", i); exit(1); } printf("%4d ", e->n_slots); if (e->mode == DCC_MODE_LOCAL) { printf("LOCAL\n"); } else if (e->mode == DCC_MODE_SSH) { printf("SSH %s %s %s\n", e->user ? e->user : "(no-user)", e->hostname ? e->hostname : "(no-hostname)", e->ssh_command ? e->ssh_command : "(no-command)"); } else if (e->mode == DCC_MODE_TCP) { printf("TCP %s %d\n", e->hostname ? e->hostname : "(no-hostname)", e->port); } else { printf("BOGUS %d\n", e->mode); } } if (e) { rs_log_error("extra entries in list!"); exit(EXIT_BAD_HOSTSPEC); } exit(0); } distcc-3.4/src/h_issource.c000066400000000000000000000031351404653710500157360ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_issource.c,v 1.7 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" const char *rs_program_name = __FILE__; /** * Test harness: determine whether a file is source, and is preprocessed. **/ int main(int argc, char *argv[]) { if (argc != 2) { rs_log_error("usage: %s FILENAME", argv[0]); return 1; } printf("%s %s\n", dcc_is_source(argv[1]) ? "source" : "not-source", dcc_is_preprocessed(argv[1]) ? "preprocessed" : "not-preprocessed"); return 0; } distcc-3.4/src/h_parsemask.c000066400000000000000000000036331404653710500160730ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "access.h" const char * rs_program_name = "h_parsemask"; int main(int argc, char **argv) { int ret; dcc_address_t value, mask; struct sockaddr_in client_ia; rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO); rs_trace_set_level(RS_LOG_INFO); if (argc != 3) { rs_log_error("usage: h_parsemask MASK CLIENT"); return EXIT_BAD_ARGUMENTS; } ret = dcc_parse_mask(argv[1], &value, &mask); if (ret) return ret; client_ia.sin_family = AF_INET; if (!inet_aton(argv[2], &client_ia.sin_addr)) { rs_log_error("can't parse client address \"%s\"", argv[2]); return EXIT_BAD_ARGUMENTS; } return dcc_check_address((struct sockaddr *) &client_ia, &value, &mask); } distcc-3.4/src/h_sa2str.c000066400000000000000000000035671404653710500153310ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_sa2str.c,v 1.1 2004/01/10 23:15:32 mbp Exp $ * * Copyright (C) 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "srvnet.h" #include "access.h" #include "netutil.h" #include "snprintf.h" const char *rs_program_name = "h_sa2str"; /* Try to print out a sockaddr */ int main(void) { struct sockaddr_in sa; char *buf; int ret; sa.sin_family = AF_INET; sa.sin_addr.s_addr = (in_addr_t) htonl(0x01020304); sa.sin_port = 4200; if ((ret = dcc_sockaddr_to_string((struct sockaddr *) &sa, sizeof sa, &buf))) return ret; puts(buf); free(buf); return 0; } distcc-3.4/src/h_scanargs.c000066400000000000000000000036271404653710500157110ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_scanargs.c,v 1.9 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "implicit.h" const char *rs_program_name = __FILE__; /** * Test harness: make argument-parsing code accessible from the * command line so that it can be tested. **/ int main(int argc, char *argv[]) { int result; char *infname, *outfname; char **newargv, **outargv; rs_trace_set_level(RS_LOG_DEBUG); if (argc < 2) { rs_log_error("usage: h_scanargs COMMAND ARG...\n"); return 1; } result = dcc_find_compiler(argv, &newargv); if (result) return result; result = dcc_scan_args(newargv, &infname, &outfname, &outargv); printf("%s %s %s\n", result == 0 ? "distribute" : "local", infname ? infname : "(NULL)", outfname ? outfname : "(NULL)"); return 0; } distcc-3.4/src/h_strip.c000066400000000000000000000031451404653710500152440ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_strip.c,v 1.4 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" const char *rs_program_name = __FILE__; /** * Test harness: determine whether a file is source, and is preprocessed. **/ int main(int argc, char *argv[]) { char **new_args; int ret; if (argc < 2) { rs_log_error("usage: %s ARGS...", argv[0]); return 1; } if ((ret = dcc_strip_local_args(argv + 1, &new_args))) { return ret; } printf("%s\n", dcc_argv_tostr(new_args)); return 0; } distcc-3.4/src/help.c000066400000000000000000000050271404653710500145250ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * Tell me what you need, and I'll tell you how to * get along without it. -- Dilbert */ #include #include #include #include #include #include #include "distcc.h" #include "trace.h" int dcc_trace_version(void) { rs_trace("%s %s %s; built %s %s", rs_program_name, PACKAGE_VERSION, GNU_HOST, __DATE__, __TIME__); return 0; } int dcc_show_version(const char *prog) { /* The "built" message is the time this file was built, which may not be * completely accurate for the program as a whole unless you do "make * clean". * * Message looks like the one from "gcc --version". */ printf("%s %s %s\n" " (protocols 1, 2 and 3) (default port %d)\n" " built %s %s\n" "Copyright (C) 2002, 2003, 2004 by Martin Pool.\n" "Includes miniLZO (C) 1996-2002 by Markus Franz Xaver Johannes Oberhumer.\n" "Portions Copyright (C) 2007-2008 Google.\n" "\n" "distcc comes with ABSOLUTELY NO WARRANTY. distcc is free software, and\n" "you may use, modify and redistribute it under the terms of the GNU \n" "General Public License version 2 or later.\n" #ifdef HAVE_AVAHI "\nBuilt with Zeroconf support.\n" #endif #ifdef HAVE_GSSAPI "\nBuilt with GSS-API support for mutual authentication.\n" #endif "\n" "Please report bugs to %s\n" "\n" , prog, PACKAGE_VERSION, GNU_HOST, DISTCC_DEFAULT_PORT, __DATE__, __TIME__, PACKAGE_BUGREPORT); return 0; } distcc-3.4/src/history.c000066400000000000000000000036311404653710500152750ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include "distcc.h" #include "mon.h" #include "trace.h" /* Number of previous states to retain for drawing history. */ const int dcc_max_history_queue = 200; void dcc_history_push(struct dcc_history *history, enum dcc_phase new_state) { history->now = (history->now + 1) % history->len; history->past_phases[history->now] = new_state; } struct dcc_history* dcc_history_new(void) { struct dcc_history *history; int i; history = malloc(sizeof *history); if (!history) { rs_log_crit("allocation failed!"); return NULL; } history->len = dcc_max_history_queue; history->now = 0; history->past_phases = malloc(history->len * (sizeof *history->past_phases)); if (!history->past_phases) { rs_log_crit("history allocation failed"); return NULL; } for (i = 0; i < history->len; i++) history->past_phases[i] = DCC_PHASE_DONE; return history; } distcc-3.4/src/hostfile.c000066400000000000000000000034621404653710500154130ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * Copyright 2008 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "hosts.h" /* TODO: Perhaps in the future allow filenames to be given in environment * variables to cause other files to be "included". */ /** * Return a hostlist read from fname (possibly recursively.) **/ int dcc_parse_hosts_file(const char *fname, struct dcc_hostdef **ret_list, int *ret_nhosts) { char *body; int ret; rs_trace("load hosts from %s", fname); if ((ret = dcc_load_file_string(fname, &body)) != 0) return ret; ret = dcc_parse_hosts(body, fname, ret_list, ret_nhosts, NULL); free(body); return ret; } distcc-3.4/src/hosts.c000066400000000000000000000501561404653710500147400ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004, 2009 by Martin Pool * Copyright 2004 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* dcc_randomize_host_list() and friends: * Author: Josh Hyman */ /* The lyf so short, the craft so long to lerne. * -- Chaucer */ /** * @file * * Routines to parse $DISTCC_HOSTS. Actual decisions about * where to run a job are in where.c. * * The grammar of this variable is, informally: * DISTCC_HOSTS = HOSTSPEC ... HOSTSPEC = LOCAL_HOST | SSH_HOST | TCP_HOST | OLDSTYLE_TCP_HOST | GLOBAL_OPTION LOCAL_HOST = localhost[/LIMIT] SSH_HOST = [USER]@HOSTID[/LIMIT][:COMMAND][OPTIONS] TCP_HOST = HOSTID[:PORT][/LIMIT][OPTIONS] OLDSTYLE_TCP_HOST = HOSTID[/LIMIT][:PORT][OPTIONS] HOSTID = HOSTNAME | IPV4 OPTIONS = ,OPTION[OPTIONS] OPTION = lzo | cpp GLOBAL_OPTION = --randomize * * Any amount of whitespace may be present between hosts. * * The command specified for SSH defines the location of the remote * server, e.g. "/usr/local/bin/distccd". This is provided as a * convenience who have trouble getting their PATH set correctly for * sshd to find distccd, and should not normally be needed. * * If you need to specify special options for ssh, they should be put * in ~/.ssh/config and referenced by the hostname. * * The TCP port defaults to 3632 and should not normally need to be * overridden. * * IPv6 literals are not supported yet. They will need to be * surrounded by square brackets because they may contain a colon, * which would otherwise be ambiguous. This is consistent with other * URL-like schemes. */ /* Alexandre Oliva writes I take this opportunity to plead people to consider such issues when proposing additional syntax for DISTCC_HOSTS: if it was possible to handle DISTCC_HOSTS as a single shell word (perhaps after turning blanks into say commas), without the risk of any shell active characters such as {, }, ~, $, quotes getting in the way, outputting distcc commands that override DISTCC_HOSTS would be far simpler. TODO: Perhaps entries in the host list that "look like files" (start with '/' or '~') should be read in as files? This could even be recursive. */ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "hosts.h" #include "exitcode.h" #include "snprintf.h" #include "config.h" #ifdef HAVE_AVAHI #include "zeroconf.h" #define ZEROCONF_MAGIC "+zeroconf" #endif const int dcc_default_port = DISTCC_DEFAULT_PORT; /*** * A simple container which would hold a host -> rand int pair ***/ struct rand_container { struct dcc_hostdef *host; int rand; }; int dcc_randomize_host_list(struct dcc_hostdef **host_list, int length); int dcc_compare_container(const void *a, const void *b); #ifndef HAVE_STRNDUP /** * Copy at most @p size characters from @p src, plus a terminating nul. * * Really this needs to be in util.c, but it's only used here. **/ char *strndup(const char *src, size_t size); char *strndup(const char *src, size_t size) { char *dst; dst = malloc(size + 1); if (dst == NULL) return NULL; strncpy(dst, src, size); dst[size] = '\0'; return dst; } #endif /** * Get a list of hosts to use. * * Hosts are taken from DISTCC_HOSTS, if that exists. Otherwise, they are * taken from $DISTCC_DIR/hosts, if that exists. Otherwise, they are taken * from ${sysconfdir}/distcc/hosts, if that exists. Otherwise, we fail. **/ int dcc_get_hostlist(struct dcc_hostdef **ret_list, int *ret_nhosts) { char *env; char *path, *top; int ret; *ret_list = NULL; *ret_nhosts = 0; if ((env = getenv("DISTCC_HOSTS")) != NULL) { rs_trace("read hosts from environment"); return dcc_parse_hosts(env, "$DISTCC_HOSTS", ret_list, ret_nhosts, NULL); } /* $DISTCC_DIR or ~/.distcc */ if ((ret = dcc_get_top_dir(&top)) == 0) { /* if we failed to get it, just warn */ checked_asprintf(&path, "%s/hosts", top); if (path != NULL && access(path, R_OK) == 0) { ret = dcc_parse_hosts_file(path, ret_list, ret_nhosts); free(path); return ret; } else { rs_trace("not reading %s: %s", path, strerror(errno)); free(path); } } checked_asprintf(&path, "%s/distcc/hosts", SYSCONFDIR); if (path != NULL && access(path, R_OK) == 0) { ret = dcc_parse_hosts_file(path, ret_list, ret_nhosts); free(path); return ret; } else { rs_trace("not reading %s: %s", path, strerror(errno)); free(path); } /* FIXME: Clearer message? */ rs_log_warning("no hostlist is set; can't distribute work"); return EXIT_BAD_HOSTSPEC; } /** * Parse an optionally present multiplier. * * *psrc is the current parse cursor; it is advanced over what is read. * * If a multiplier is present, *psrc points to a substring starting with '/'. * The host definition is updated to the numeric value following. Otherwise * the hostdef is unchanged. **/ static int dcc_parse_multiplier(const char **psrc, struct dcc_hostdef *hostdef) { const char *token = *psrc; if ((*psrc)[0] == '/' || (*psrc)[0] == '=') { int val; (*psrc)++; val = atoi(*psrc); if (val == 0) { rs_log_error("bad multiplier \"%s\" in host specification", token); return EXIT_BAD_HOSTSPEC; } while (isdigit((uint8_t)**psrc)) (*psrc)++; hostdef->n_slots = val; } return 0; } /** * Parse an optionally present option string. * * At the moment the only two options we have is "lzo" for compression, * and "cpp" if the server supports doing the preprocessing there, also. **/ static int dcc_parse_options(const char **psrc, struct dcc_hostdef *host) { const char *started = *psrc, *p = *psrc; host->compr = DCC_COMPRESS_NONE; host->cpp_where = DCC_CPP_ON_CLIENT; #ifdef HAVE_GSSAPI host->authenticate = 0; host->auth_name = NULL; #endif while (p[0] == ',') { p++; if (str_startswith("lzo", p)) { rs_trace("got LZO option"); host->compr = DCC_COMPRESS_LZO1X; p += 3; } else if (str_startswith("down", p)) { /* if "hostid,down", mark it down, and strip down from hostname */ host->is_up = 0; p += 4; } else if (str_startswith("cpp", p)) { rs_trace("got CPP option"); host->cpp_where = DCC_CPP_ON_SERVER; p += 3; #ifdef HAVE_GSSAPI } else if (str_startswith("auth", p)) { rs_trace("got GSSAPI option"); host->authenticate = 1; p += 4; if (p[0] == '=') { p++; int ret; if ((ret = dcc_dup_part(&p, &host->auth_name, "/: \t\n\r\f,"))) return ret; if (host->auth_name) { rs_trace("using \"%s\" server name instead of fqdn " "lookup for GSS-API auth", host->auth_name); } } #endif } else { rs_log_error("unrecognized option in host specification: %s", started); return EXIT_BAD_HOSTSPEC; } } if (dcc_get_protover_from_features(host->compr, host->cpp_where, &host->protover) == -1) { rs_log_error("invalid host options: %s", started); return EXIT_BAD_HOSTSPEC; } *psrc = p; return 0; } static int dcc_parse_ssh_host(struct dcc_hostdef *hostdef, const char *token_start) { int ret; const char *token = token_start; /* Everything up to '@' is the username */ if ((ret = dcc_dup_part(&token, &hostdef->user, "@")) != 0) return ret; if (token[0] != '@') { rs_log_error("expected '@' to start ssh token"); return EXIT_BAD_HOSTSPEC; } token++; if ((ret = dcc_dup_part(&token, &hostdef->hostname, "/: \t\n\r\f,")) != 0) return ret; if (!hostdef->hostname) { rs_log_error("hostname is required in SSH host specification \"%s\"", token_start); return EXIT_BAD_HOSTSPEC; } if ((ret = dcc_parse_multiplier(&token, hostdef)) != 0) return ret; if (token[0] == ':') { token++; if ((ret = dcc_dup_part(&token, &hostdef->ssh_command, " \t\n\r\f,"))) return ret; } if ((ret = dcc_parse_options(&token, hostdef))) return ret; hostdef->mode = DCC_MODE_SSH; return 0; } static int dcc_parse_tcp_host(struct dcc_hostdef *hostdef, const char * const token_start) { int ret; const char *token = token_start; if (token[0] == '[') { /* Skip the leading bracket, which is not part of the address */ token++; /* We have an IPv6 Address */ if ((ret = dcc_dup_part(&token, &hostdef->hostname, "/] \t\n\r\f,"))) return ret; if(token[0] != ']') { rs_log_error("IPv6 Hostname requires closing ']'"); return EXIT_BAD_HOSTSPEC; } token++; } else { /* Parse IPv4 address */ if ((ret = dcc_dup_part(&token, &hostdef->hostname, "/: \t\n\r\f,"))) return ret; } if (!hostdef->hostname) { rs_log_error("hostname is required in tcp host specification \"%s\"", token_start); return EXIT_BAD_HOSTSPEC; } if ((ret = dcc_parse_multiplier(&token, hostdef)) != 0) return ret; hostdef->port = dcc_default_port; if (token[0] == ':') { char *tail; token++; hostdef->port = strtol(token, &tail, 10); if (*tail != '\0' && !isspace((uint8_t)*tail) && *tail != '/' && *tail != ',') { rs_log_error("invalid tcp port specification in \"%s\"", token); return EXIT_BAD_HOSTSPEC; } else { token = tail; } } if ((ret = dcc_parse_multiplier(&token, hostdef)) != 0) return ret; if ((ret = dcc_parse_options(&token, hostdef))) return ret; hostdef->mode = DCC_MODE_TCP; return 0; } static int dcc_parse_localhost(struct dcc_hostdef *hostdef, const char * token_start) { const char *token = token_start + strlen("localhost"); hostdef->mode = DCC_MODE_LOCAL; hostdef->hostname = strdup("localhost"); /* Run only two tasks on localhost by default. * * It might be nice to run more if there are more CPUs, but determining * the number of CPUs on Linux is a bit expensive since it requires * examining mtab and /proc/stat. Anyone lucky enough to have a >2 CPU * machine can specify a number in the host list. */ hostdef->n_slots = 2; return dcc_parse_multiplier(&token, hostdef); } /** Given a host with its protover fields set, set * its feature fields appropriately. Returns 0 if the protocol * is known, non-zero otherwise. */ int dcc_get_features_from_protover(enum dcc_protover protover, enum dcc_compress *compr, enum dcc_cpp_where *cpp_where) { if (protover > 1) { *compr = DCC_COMPRESS_LZO1X; } else { *compr = DCC_COMPRESS_NONE; } if (protover > 2) { *cpp_where = DCC_CPP_ON_SERVER; } else { *cpp_where = DCC_CPP_ON_CLIENT; } if (protover == 0 || protover > 3) { return 1; } else { return 0; } } /** Given a host with its feature fields set, set * its protover appropriately. Return the protover, * or -1 on error. */ int dcc_get_protover_from_features(enum dcc_compress compr, enum dcc_cpp_where cpp_where, enum dcc_protover *protover) { *protover = -1; if (compr == DCC_COMPRESS_NONE && cpp_where == DCC_CPP_ON_CLIENT) { *protover = DCC_VER_1; } if (compr == DCC_COMPRESS_LZO1X && cpp_where == DCC_CPP_ON_SERVER) { *protover = DCC_VER_3; } if (compr == DCC_COMPRESS_LZO1X && cpp_where == DCC_CPP_ON_CLIENT) { *protover = DCC_VER_2; } if (compr == DCC_COMPRESS_NONE && cpp_where == DCC_CPP_ON_SERVER) { rs_log_error("pump mode (',cpp') requires compression (',lzo')"); } return *protover; } /** * @p where is the host list, taken either from the environment or file. * * @return 0 if parsed successfully; nonzero if there were any errors, * or if no hosts were defined. **/ int dcc_parse_hosts(const char *where, const char *source_name, struct dcc_hostdef **ret_list, int *ret_nhosts, struct dcc_hostdef **ret_prev) { int ret, flag_randomize = 0; struct dcc_hostdef *curr, *_prev; if (!ret_prev) { ret_prev = &_prev; _prev = NULL; } /* TODO: Check for '/' in places where it might cause trouble with * a lock file name. */ /* A simple, hardcoded scanner. Some of the GNU routines might be * useful here, but they won't work on less capable systems. * * We repeatedly attempt to extract a whitespace-delimited host * definition from the string until none remain. Allocate an * entry; hook to previous entry. We then determine if there is a * '@' in it, which tells us whether it is an SSH or TCP * definition. We then duplicate the relevant subcomponents into * the relevant fields. */ while (1) { int token_len; const char *token_start; int has_at; if (where[0] == '\0') break; /* end of string */ /* skip over comments */ if (where[0] == '#') { do where++; while (where[0] != '\n' && where[0] != '\r' && where[0] != '\0'); continue; } if (isspace((uint8_t)where[0])) { where++; /* skip space */ continue; } token_start = where; token_len = strcspn(where, " #\t\n\f\r"); /* intercept keywords which are not actually hosts */ if (!strncmp(token_start, "--randomize", 11)) { flag_randomize = 1; where = token_start + token_len; continue; } if(!strncmp(token_start, "--localslots_cpp", 16)) { const char *ptr; ptr = token_start + 16; if(dcc_parse_multiplier(&ptr, dcc_hostdef_local_cpp) == 0) { where = token_start + token_len; continue; } } if(!strncmp(token_start, "--localslots", 12)) { const char *ptr; ptr = token_start + 12; if(dcc_parse_multiplier(&ptr, dcc_hostdef_local) == 0) { where = token_start + token_len; continue; } } #ifdef HAVE_AVAHI if (token_len == sizeof(ZEROCONF_MAGIC)-1 && !strncmp(token_start, ZEROCONF_MAGIC, (unsigned) token_len)) { if ((ret = dcc_zeroconf_add_hosts(ret_list, ret_nhosts, 4, ret_prev) != 0)) return ret; goto skip; } #endif /* Allocate new list item */ curr = calloc(1, sizeof(struct dcc_hostdef)); if (!curr) { rs_log_crit("failed to allocate host definition"); return EXIT_OUT_OF_MEMORY; } /* by default, mark the host up */ curr->is_up = 1; /* Store verbatim hostname */ if (!(curr->hostdef_string = strndup(token_start, (size_t) token_len))) { rs_log_crit("failed to allocate hostdef_string"); return EXIT_OUT_OF_MEMORY; } /* Link into list */ if (*ret_prev) { (*ret_prev)->next = curr; } else { *ret_list = curr; /* first */ } /* Default task limit. A bit higher than the local limit to allow for * some files in transit. */ curr->n_slots = 4; curr->protover = DCC_VER_1; /* default */ curr->compr = DCC_COMPRESS_NONE; has_at = (memchr(token_start, '@', (size_t) token_len) != NULL); if (!strncmp(token_start, "localhost", 9) && (token_len == 9 || token_start[9] == '/')) { rs_trace("found localhost token \"%.*s\"", token_len, token_start); if ((ret = dcc_parse_localhost(curr, token_start)) != 0) return ret; } else if (has_at) { rs_trace("found ssh token \"%.*s\"", token_len, token_start); if ((ret = dcc_parse_ssh_host(curr, token_start)) != 0) return ret; } else { rs_trace("found tcp token \"%.*s\"", token_len, token_start); if ((ret = dcc_parse_tcp_host(curr, token_start)) != 0) return ret; } if (!curr->is_up) { rs_trace("host %s is down", curr->hostdef_string); } (*ret_nhosts)++; *ret_prev = curr; #ifdef HAVE_AVAHI skip: #endif /* continue to next token if any */ where = token_start + token_len; } if (*ret_nhosts) { if (flag_randomize) if ((ret = dcc_randomize_host_list(ret_list, *ret_nhosts)) != 0) return ret; return 0; } else { rs_log_warning("%s contained no hosts; can't distribute work", source_name); return EXIT_BAD_HOSTSPEC; } } int dcc_compare_container(const void *a, const void *b) { struct rand_container *i, *j; i = (struct rand_container *) a; j = (struct rand_container *) b; if (i->rand == j->rand) return 0; else if (i->rand > j->rand) return 1; else return -1; } int dcc_randomize_host_list(struct dcc_hostdef **host_list, int length) { int i; unsigned int rand_val; struct dcc_hostdef *curr; struct rand_container *c; c = malloc(length * sizeof(struct rand_container)); if (!c) { rs_log_crit("failed to allocate host definition"); return EXIT_OUT_OF_MEMORY; } /* { #ifdef HAVE_GETTIMEOFDAY int ret; struct timeval tv; if ((ret = gettimeofday(&tv, NULL)) == 0) rand_val = (unsigned int) tv.tv_usec; else #else rand_val = (unsigned int) time(NULL) ^ (unsigned int) getpid(); #endif } */ rand_val = (unsigned int) getpid(); /* create pairs of hosts -> random numbers */ srand(rand_val); curr = *host_list; for (i = 0; i < length; i++) { c[i].host = curr; c[i].rand = rand(); curr = curr->next; } /* sort */ qsort(c, length, sizeof(struct rand_container), &dcc_compare_container); /* reorder the list */ for (i = 0; i < length; i++) { if (i != length - 1) c[i].host->next = c[i+1].host; else c[i].host->next = NULL; } /* move the start of the list */ *host_list = c[0].host; free(c); return 0; } int dcc_free_hostdef(struct dcc_hostdef *host) { /* ANSI C requires free() to accept NULL */ free(host->user); free(host->hostname); free(host->ssh_command); free(host->hostdef_string); memset(host, 0xf1, sizeof *host); free(host); return 0; } distcc-3.4/src/hosts.h000066400000000000000000000053641404653710500147460ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Declarations for distcc host selection stuff. **/ /** * A simple linked list of host definitions. All strings are mallocd. **/ struct dcc_hostdef { enum { DCC_MODE_TCP = 1, DCC_MODE_SSH, DCC_MODE_LOCAL } mode; char * user; char * hostname; int port; char * ssh_command; /** Mark the host as up == 1, by default, or down == 0, if !hostname */ int is_up; /** Number of tasks that can be dispatched concurrently to this machine. */ int n_slots; /** The full name of this host, taken verbatim from the host * definition. **/ char * hostdef_string; enum dcc_protover protover; /** The kind of compression to use for this host */ enum dcc_compress compr; /** Where are we doing preprocessing? */ enum dcc_cpp_where cpp_where; #ifdef HAVE_GSSAPI /* Are we authenticating with this host? */ int authenticate; char * auth_name; #endif struct dcc_hostdef *next; }; /** Static definition of localhost **/ extern struct dcc_hostdef *dcc_hostdef_local; extern struct dcc_hostdef *dcc_hostdef_local_cpp; /* hosts.c */ int dcc_get_hostlist(struct dcc_hostdef **ret_list, int *ret_nhosts); int dcc_free_hostdef(struct dcc_hostdef *host); int dcc_get_features_from_protover(enum dcc_protover protover, enum dcc_compress *compr, enum dcc_cpp_where *cpp_where); int dcc_get_protover_from_features(enum dcc_compress compr, enum dcc_cpp_where cpp_where, enum dcc_protover *protover); /* hostfile.c */ int dcc_parse_hosts_file(const char *fname, struct dcc_hostdef **ret_list, int *ret_nhosts); distcc-3.4/src/implicit.c000066400000000000000000000064651404653710500154160ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2008 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "I do not trouble myself to be understood. I see * that the elementary laws never apologize." * -- Whitman, "Song of Myself". */ #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "implicit.h" /** * @file * * Handle invocations where the compiler name is implied rather than * specified. That is, "distcc -c foo.c". * * This method of invocation is less transparent than the masquerade system, * and less explicit than giving the real compiler name. But it is pretty * simple, and is retained for that reason. * * This is used on the client only. The compiler name is always passed (as * argv[0]) to the server. * * The current implementation determines that no compiler name has been * specified by checking whether the first argument is either an option, or a * source or object file name. If not, it is assumed to be the name of the * compiler to use. * * At the moment the default compiler name is always "cc", but this could * change to come from an environment variable. That's not supported at the * moment, and may never be. If you need that level of control, using a * different invocation method is recommended. **/ /** * Find the compiler for non-masquerade use. * * If we're invoked with no compiler name, insert one. * * We can tell there's no compiler name because argv[1] will be either * a source filename or an object filename or an option. I don't * think anything else is possible. * * Returns a dynamically allocated argv array in *out_argv. * The caller is responsible for deallocating it. **/ int dcc_find_compiler(char **argv, char ***out_argv) { int ret; if (argv[1][0] == '-' || dcc_is_source(argv[1]) || dcc_is_object(argv[1])) { if ((ret = dcc_copy_argv(argv, out_argv, 0)) != 0) { return ret; } /* change "distcc -c foo.c" -> "cc -c foo.c" */ free((*out_argv)[0]); (*out_argv)[0] = strdup("cc"); if ((*out_argv)[0] == NULL) { return EXIT_OUT_OF_MEMORY; } return 0; } else { /* skip "distcc", point to "gcc -c foo.c" */ return dcc_copy_argv(argv + 1, out_argv, 0); } } distcc-3.4/src/implicit.h000066400000000000000000000020711404653710500154100ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/implicit.h,v 1.3 2002/09/18 06:57:45 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ int dcc_find_compiler(char **argv, char ***); distcc-3.4/src/include_server_if.c000066400000000000000000000204771404653710500172720ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Authors: Manos Renieris, Fergus Henderson */ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "rpc.h" #include "clinet.h" #include "exitcode.h" #include "util.h" #include "hosts.h" #include "include_server_if.h" static int dcc_count_slashes(const char *path); static int dcc_count_leading_dotdots(const char *path); static int dcc_categorize_file(const char *include_server_filename); /* The include server puts all files in its own special directory, * which is n path components long, where n = INCLUDE_SERVER_DIR_DEPTH */ #define INCLUDE_SERVER_DIR_DEPTH 3 /** Talks to the include server, over the AF_UNIX socket specified * in env variable INCLUDE_SERVER_PORT. If all goes well, * it returns the array of files in @p files and returns 0; * if anything goes wrong, it returns a non-zero value. */ int dcc_talk_to_include_server(char **argv, char ***files) { char *include_server_port; int fd; struct sockaddr_un sa; int ret; char *stub; /* for testing purposes, if INCLUDE_SERVER_STUB is set, use its value rather than the include server */ stub = getenv("INCLUDE_SERVER_STUB"); if (stub != NULL) { ret = dcc_tokenize_string(stub, files); rs_log_warning("INCLUDE_SERVER_STUB is set to '%s'; " "ignoring include server", dcc_argv_tostr(*files)); return ret; } include_server_port = getenv("INCLUDE_SERVER_PORT"); if (include_server_port == NULL) { rs_log_warning("INCLUDE_SERVER_PORT not set - " "did you forget to run under 'pump'?"); return 1; } if (strlen(include_server_port) >= ((int)sizeof(sa.sun_path) - 1)) { rs_log_warning("$INCLUDE_SERVER_PORT is longer than %ld characters", ((long) sizeof(sa.sun_path) - 1)); return 1; } strcpy(sa.sun_path, include_server_port); sa.sun_family = AF_UNIX; if (dcc_connect_by_addr((struct sockaddr *) &sa, sizeof(sa), &fd)) return 1; /* TODO? switch include_server to use more appropriate token names */ if (dcc_x_cwd(fd) || dcc_x_argv(fd, "ARGC", "ARGV", argv) || dcc_r_argv(fd, "ARGC", "ARGV", files)) { rs_log_warning("failed to talk to include server '%s'", include_server_port); dcc_close(fd); /* We are failing anyway, so we can ignore the return value of dcc_close() */ return 1; } if (dcc_close(fd)) { return 1; } if (dcc_argv_len(*files) == 0) { rs_log_warning("include server gave up analyzing"); return 1; } return 0; } /* The include server puts all files in its own special directory, * which is n path components long, where n = INCLUDE_SERVER_DIR_DEPTH * The original file should drop those components. * Also, we need to strip the .lzo and .lzo.abs suffixes. */ int dcc_get_original_fname(const char *fname, char **original_fname) { int i; char *work, *alloced_work, *extension; alloced_work = work = strdup(fname); if (work == NULL) return EXIT_OUT_OF_MEMORY; /* Since all names are supposed to be absolute, they start with * a slash. We are trying to drop INCLUDE_SERVER_DIR_DEPTH path * components, so we start right after the first slash, and we look * for a slash, and then we skip that slash and look for a slash, etc. */ for (i = 0; i < INCLUDE_SERVER_DIR_DEPTH; ++i) { work = strchr(work + 1, '/'); if (work == NULL) { return 1; } } /* This code removes an abs extension if it's there, and then a .lzo extension if it's there. As a result a .lzo.abs extension is removed, but not a .abs.lzo extension. */ extension = dcc_find_extension(work); if (extension && (strcmp(extension, ".abs") == 0)) { *extension = '\0'; } extension = dcc_find_extension(work); if (extension && (strcmp(extension, ".lzo") == 0)) { *extension = '\0'; } *original_fname = strdup(work); if (*original_fname == NULL) { free(alloced_work); return EXIT_OUT_OF_MEMORY; } free(alloced_work); return 0; } /** * This implements the --scan_includes option. * Talks to the include server, and prints the results to stdout. */ int dcc_approximate_includes(struct dcc_hostdef *host, char **argv) { char **files; int i; int ret; if (host->cpp_where != DCC_CPP_ON_SERVER) { rs_log_error("'--scan_includes' specified, " "but distcc wouldn't have used include server " "(make sure hosts list includes ',cpp' option?)"); return EXIT_DISTCC_FAILED; //return 0; } if ((ret = dcc_talk_to_include_server(argv, &files))) { rs_log_error("failed to get includes from include server"); return ret; } for (i = 0; files[i]; i++) { if ((ret = dcc_categorize_file(files[i]))) return ret; } return 0; } /* * A subroutine of dcc_approximate_includes(). * Take a filename output from the include server, * convert the filename back so that it refers to the original source tree * (as opposed to the include server's mirror tree), * categorize it as SYSTEMDIR, DIRECTORY, SYMLINK, or FILE, * and print the category and original name to stdout. * For SYMLINKs, also print out what the symlink points to. */ static int dcc_categorize_file(const char *include_server_filename) { char *filename; int is_symlink = 0; int is_forced_directory = 0; int is_system_include_directory = 0; char link_target[MAXPATHLEN + 1]; int ret; if ((ret = dcc_is_link(include_server_filename, &is_symlink))) return ret; if (is_symlink) if ((ret = dcc_read_link(include_server_filename, link_target))) return ret; if ((ret = dcc_get_original_fname(include_server_filename, &filename))) { rs_log_error("dcc_get_original_fname failed"); return ret; } if (str_endswith("/forcing_technique_271828", filename)) { /* Replace "/forcing_technique_271818" with "". */ filename[strlen(filename) - strlen("/forcing_technique_271828")] = '\0'; is_forced_directory = 1; } if (is_symlink) { int leading_dotdots = dcc_count_leading_dotdots(link_target); is_system_include_directory = leading_dotdots > 0 && leading_dotdots > dcc_count_slashes(filename) && strcmp(link_target + 3 * leading_dotdots - 1, filename) == 0; } printf("%-9s %s\n", is_system_include_directory ? "SYSTEMDIR" : is_forced_directory ? "DIRECTORY" : is_symlink ? "SYMLINK" : "FILE", filename); return 0; } /* Count the number of slashes in a path. */ static int dcc_count_slashes(const char *path) { int i; int count = 0; for (i = 0; path[i]; i++) { if (path[i] == '/') count++; } return count; } /* Count the number of leading "../" references in a path. */ static int dcc_count_leading_dotdots(const char *path) { int count = 0; while (str_startswith("../", path)) { path += 3; count++; } return count; } distcc-3.4/src/include_server_if.h000066400000000000000000000020631404653710500172660ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Manos Renieris */ int dcc_talk_to_include_server(char **argv, char ***files); int dcc_get_original_fname(const char *fname, char **original_fname); int dcc_approximate_includes(struct dcc_hostdef *host, char **argv); distcc-3.4/src/io.c000066400000000000000000000176001404653710500142040ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Common low-level IO utilities. * * This code is not meant to know about our protocol, only to provide * a more comfortable layer on top of Unix IO. * * @todo Perhaps write things out using writev() to reduce the number * of system calls, and the risk of small packets when not using * TCP_CORK. */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SELECT_H # include #endif #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" int dcc_get_io_timeout(void) { /** Timeout for all IO other than opening connections. Much longer, * because compiling files can take a long time. **/ static const int default_dcc_io_timeout = 300; /* seconds */ static int current_timeout = 0; if (current_timeout > 0) return current_timeout; const char *user_timeout = getenv("DISTCC_IO_TIMEOUT"); if (user_timeout) { int parsed_user_timeout = atoi(user_timeout); if (parsed_user_timeout <= 0) { rs_log_error("Bad DISTCC_IO_TIMEOUT value: %s", user_timeout); exit(EXIT_BAD_ARGUMENTS); } current_timeout = parsed_user_timeout; } else { current_timeout = default_dcc_io_timeout; } return current_timeout; } /** * @todo Perhaps only apply the timeout for initial connections, not when * doing regular IO. **/ int dcc_select_for_read(int fd, int timeout) { fd_set fds; int rs; struct timeval tv; tv.tv_sec = timeout; tv.tv_usec = 0; while (1) { FD_ZERO(&fds); FD_SET(fd, &fds); /* Linux updates the timeval to reflect the remaining time, but other * OSs may not. So on other systems, we may wait a bit too long if * the client is interrupted -- but that won't happen very often so * it's no big deal. */ rs_trace("select for read on fd%d for %ds", fd, (int) tv.tv_sec); rs = select(fd+1, &fds, NULL, NULL, &tv); if (rs == -1 && errno == EINTR) { rs_trace("select was interrupted"); continue; } else if (rs == -1) { rs_log_error("select() failed: %s", strerror(errno)); return EXIT_IO_ERROR; } else if (rs == 0) { rs_log_error("IO timeout"); return EXIT_IO_ERROR; } else if (!FD_ISSET(fd, &fds)) { rs_log_error("how did fd not get set?"); continue; } else { break; /* woot */ } } return 0; } /* * Calls select() to block until the specified fd becomes writeable * or has an error condition, or the timeout expires. */ int dcc_select_for_write(int fd, int timeout) { fd_set write_fds; fd_set except_fds; int rs; struct timeval tv; tv.tv_sec = timeout; tv.tv_usec = 0; while (1) { FD_ZERO(&write_fds); FD_ZERO(&except_fds); FD_SET(fd, &write_fds); FD_SET(fd, &except_fds); rs_trace("select for write on fd%d", fd); rs = select(fd + 1, NULL, &write_fds, &except_fds, &tv); if (rs == -1 && errno == EINTR) { rs_trace("select was interrupted"); continue; } else if (rs == -1) { rs_log_error("select failed: %s", strerror(errno)); return EXIT_IO_ERROR; } else if (rs == 0) { rs_log_error("IO timeout"); return EXIT_IO_ERROR; } else { if (FD_ISSET(fd, &except_fds)) { rs_trace("error condition on fd%d", fd); /* * Don't fail here; we couldn't give a good error * message, because we don't know what the error * condition is. Instead just return 0 (success), * indicating that the select has successfully finished. * The next call to write() for that fd will fail but * will also set errno properly so that we can give a * good error message at that point. */ } return 0; } } } /** * Read exactly @p len bytes from a file. **/ int dcc_readx(int fd, void *buf, size_t len) { ssize_t r; int ret; while (len > 0) { r = read(fd, buf, len); if (r == -1 && errno == EAGAIN) { if ((ret = dcc_select_for_read(fd, dcc_get_io_timeout()))) return ret; else continue; } else if (r == -1 && errno == EINTR) { continue; } else if (r == -1) { rs_log_error("failed to read: %s", strerror(errno)); return EXIT_IO_ERROR; } else if (r == 0) { rs_log_error("unexpected eof on fd%d", fd); return EXIT_TRUNCATED; } else { buf = &((char *) buf)[r]; len -= r; } } return 0; } /** * Write bytes to an fd. Keep writing until we're all done or something goes * wrong. * * @returns 0 or exit code. **/ int dcc_writex(int fd, const void *buf, size_t len) { ssize_t r; int ret; while (len > 0) { r = write(fd, buf, len); if (r == -1 && errno == EAGAIN) { if ((ret = dcc_select_for_write(fd, dcc_get_io_timeout()))) return ret; else continue; } else if (r == -1 && errno == EINTR) { continue; } else if (r == -1) { rs_log_error("failed to write: %s", strerror(errno)); return EXIT_IO_ERROR; } else { buf = &((char *) buf)[r]; len -= r; } } return 0; } /** * Stick a TCP cork in the socket. It's not clear that this will help * performance, but it might. * * This is a no-op if we don't think this platform has corks. **/ int tcp_cork_sock(int POSSIBLY_UNUSED(fd), int POSSIBLY_UNUSED(corked)) { #if defined(TCP_CORK) && defined(SOL_TCP) if (!dcc_getenv_bool("DISTCC_TCP_CORK", 1) || !(not_sd_is_socket(fd, AF_INET, SOCK_STREAM, 1) || not_sd_is_socket(fd, AF_INET6, SOCK_STREAM, 1))) return 0; if (setsockopt(fd, SOL_TCP, TCP_CORK, &corked, sizeof corked) == -1) { if (errno == ENOSYS || errno == ENOTSUP) { if (corked) rs_trace("no corks allowed on fd%d", fd); /* no need to complain about not uncorking */ } else { rs_log_warning("setsockopt(corked=%d) failed: %s", corked, strerror(errno)); /* continue anyhow */ } } #endif /* def TCP_CORK */ return 0; } int dcc_close(int fd) { if (close(fd) != 0) { rs_log_error("failed to close fd%d: %s", fd, strerror(errno)); return EXIT_IO_ERROR; } return 0; } distcc-3.4/src/loadfile.c000066400000000000000000000062041404653710500153520ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** * Load a whole file into a new string in a malloc'd memory buffer. * * Files larger than a certain reasonableness limit are not loaded, because * this is only used for reasonably short text files. * * Files that do not exist cause EXIT_NO_SUCH_FILE, but no error message. * (This suits our case of loading configuration files. It could be made * optional.) **/ int dcc_load_file_string(const char *filename, char **retbuf) { int fd; int ret; ssize_t read_bytes; struct stat sb; char *buf; /* Open the file */ if ((fd = open(filename, O_RDONLY)) == -1) { if (errno == ENOENT) return EXIT_NO_SUCH_FILE; else { rs_log_warning("failed to open %s: %s", filename, strerror(errno)); return EXIT_IO_ERROR; } } /* Find out how big the file is */ if (fstat(fd, &sb) == -1) { rs_log_error("fstat %s failed: %s", filename, strerror(errno)); ret = EXIT_IO_ERROR; goto out_close; } if (sb.st_size > 1<<20) { rs_log_error("%s is too large to load (%ld bytes)", filename, (long) sb.st_size); ret = EXIT_OUT_OF_MEMORY; goto out_close; } /* Allocate a buffer, allowing space for a nul. */ if ((*retbuf = buf = malloc((size_t) sb.st_size + 1)) == NULL) { rs_log_error("failed to allocate %ld byte file buffer", (long) sb.st_size); ret = EXIT_OUT_OF_MEMORY; goto out_close; } /* Read everything */ if ((read_bytes = read(fd, buf, (size_t) sb.st_size)) == -1) { rs_log_error("failed to read %s: %s", filename, strerror(errno)); ret = EXIT_IO_ERROR; goto out_free; } /* Null-terminate. It's OK if we read a bit less than we expected to. */ buf[read_bytes] = '\0'; ret = 0; out_close: dcc_close(fd); return ret; out_free: free(*retbuf); dcc_close(fd); return ret; } distcc-3.4/src/lock.c000066400000000000000000000230501404653710500145210ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Power is nothing without control * -- Pirelli tyre advertisement. */ /** * @file * * @brief Manage lockfiles. * * distcc uses a simple disk-based lockfile system to keep track of how many * jobs are queued on various machines. These locks might be used for * something else in the future. * * We use locks rather than e.g. a database or a central daemon because we * want to make sure that the lock will be removed if the client terminates * unexpectedly. * * The files themselves (as opposed to the lock on them) are never cleaned up; * since locking & creation is nonatomic I can't think of a clean way to do * it. There shouldn't be many of them, and dead ones will be caught by the * tmpreaper. In any case they're zero bytes. * * Sys V semaphores might work well here, but the interface is a bit ugly and * they are probably not portable to Cygwin. In particular they can leak if * the process is abruptly terminated, which is likely to happen to distcc. */ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "hosts.h" #include "lock.h" #include "exitcode.h" #include "snprintf.h" /* Note that we use the _same_ lock file for * dcc_hostdef_local and dcc_hostdef_local_cpp, * so that they both use the same underlying lock. * This ensures that we respect the limits for * both "localslots" and "localslots_cpp". * * Extreme care with lock ordering is required in order to avoid * deadlocks. In particular, the following invariants apply: * * - Each distcc process should hold no more than two locks at a time; * one local lock, and one remote lock. * * - When acquiring more than one lock, a strict lock ordering discipline * must be observed: the remote lock must be acquired first, before the * local lock; and conversely the local lock must be released first, * before the remote lock. */ struct dcc_hostdef _dcc_local = { DCC_MODE_LOCAL, NULL, (char *) "localhost", 0, NULL, 1, /* host is_up */ 4, /* number of tasks */ (char *)"localhost", /* verbatim string */ DCC_VER_1, /* protocol (ignored) */ DCC_COMPRESS_NONE, /* compression (ignored) */ DCC_CPP_ON_CLIENT, /* where to cpp (ignored) */ #ifdef HAVE_GSSAPI 0, /* Authentication? */ NULL, /* Authentication name */ #endif NULL }; struct dcc_hostdef *dcc_hostdef_local = &_dcc_local; struct dcc_hostdef _dcc_local_cpp = { DCC_MODE_LOCAL, NULL, (char *) "localhost", 0, NULL, 1, /* host is_up */ 8, /* number of tasks */ (char *)"localhost", /* verbatim string */ DCC_VER_1, /* protocol (ignored) */ DCC_COMPRESS_NONE, /* compression (ignored) */ DCC_CPP_ON_CLIENT, /* where to cpp (ignored) */ #ifdef HAVE_GSSAPI 0, /* Authentication? */ NULL, /* Authentication name */ #endif NULL }; struct dcc_hostdef *dcc_hostdef_local_cpp = &_dcc_local_cpp; /** * Returns a newly allocated buffer. **/ int dcc_make_lock_filename(const char *lockname, const struct dcc_hostdef *host, int iter, char **filename_ret) { char * buf; int ret; char *lockdir; if ((ret = dcc_get_lock_dir(&lockdir))) return ret; if (host->mode == DCC_MODE_LOCAL) { if (asprintf(&buf, "%s/%s_localhost_%d", lockdir, lockname, iter) == -1) return EXIT_OUT_OF_MEMORY; } else if (host->mode == DCC_MODE_TCP) { if (asprintf(&buf, "%s/%s_tcp_%s_%d_%d", lockdir, lockname, host->hostname, host->port, iter) == -1) return EXIT_OUT_OF_MEMORY; } else if (host->mode == DCC_MODE_SSH) { if (asprintf(&buf, "%s/%s_ssh_%s_%d", lockdir, lockname, host->hostname, iter) == -1) return EXIT_OUT_OF_MEMORY; } else { rs_log_crit("oops"); return EXIT_PROTOCOL_ERROR; } *filename_ret = buf; return 0; } /** * Get an exclusive, non-blocking lock on a file using whatever method * is available on this system. * * @retval 0 if we got the lock * @retval -1 with errno set if the file is already locked. **/ static int sys_lock(int fd, int block) { #if defined(F_SETLK) struct flock lockparam; lockparam.l_type = F_WRLCK; lockparam.l_whence = SEEK_SET; lockparam.l_start = 0; lockparam.l_len = 0; /* whole file */ return fcntl(fd, block ? F_SETLKW : F_SETLK, &lockparam); #elif defined(HAVE_FLOCK) return flock(fd, LOCK_EX | (block ? 0 : LOCK_NB)); #elif defined(HAVE_LOCKF) return lockf(fd, block ? F_LOCK : F_TLOCK, 0); #else # error "No supported lock method. Please port this code." #endif } int dcc_unlock(int lock_fd) { #if defined(F_SETLK) struct flock lockparam; lockparam.l_type = F_UNLCK; lockparam.l_whence = SEEK_SET; lockparam.l_start = 0; lockparam.l_len = 0; if (fcntl(lock_fd, F_SETLK, &lockparam) == -1) { rs_log_error("fcntl(fd%d, F_SETLK, F_UNLCK) failed: %s", lock_fd, strerror(errno)); close(lock_fd); return EXIT_IO_ERROR; } #elif defined (HAVE_FLOCK) /* flock() style locks are released when the fd is closed */ #elif defined (HAVE_LOCKF) if (lockf(lock_fd, F_ULOCK, 0) == -1) { rs_log_error("lockf(fd%d, F_ULOCK, 0) failed: %s", lock_fd, strerror(errno)); close(lock_fd); return EXIT_IO_ERROR; } #endif rs_trace("release lock fd%d", lock_fd); /* All our current locks can just be closed */ if (close(lock_fd)) { rs_log_error("close failed: %s", strerror(errno)); return EXIT_IO_ERROR; } return 0; } /** * Open a lockfile, creating if it does not exist. **/ int dcc_open_lockfile(const char *fname, int *plockfd) { /* Create if it doesn't exist. We don't actually do anything with * the file except lock it. * * The file is created with the loosest permissions allowed by the user's * umask, to give the best chance of avoiding problems if they should * happen to use a shared lock dir. */ /* FIXME: If we fail to open with EPERM or something similar, try deleting * the file and try again. That might fix problems with root-owned files * in user home directories. */ *plockfd = open(fname, O_WRONLY|O_CREAT, 0666); if (*plockfd == -1 && errno != EEXIST) { rs_log_error("failed to create %s: %s", fname, strerror(errno)); return EXIT_IO_ERROR; } return 0; } /** * Lock a server slot, in either blocking or nonblocking mode. * * In blocking mode, this function will not return until either the lock has * been acquired, or an error occurred. In nonblocking mode, it will instead * return EXIT_BUSY if some other process has this slot locked. * * @param slot 0-based index of available slots on this host. * @param block True for blocking mode. * * @param lock_fd On return, contains the lock file descriptor to allow * it to be closed. **/ int dcc_lock_host(const char *lockname, const struct dcc_hostdef *host, int slot, int block, int *lock_fd) { char *fname; int ret; /* if host is down, return EXIT_BUSY */ if (!host->is_up) return EXIT_BUSY; if ((ret = dcc_make_lock_filename(lockname, host, slot, &fname))) return ret; if ((ret = dcc_open_lockfile(fname, lock_fd)) != 0) { free(fname); return ret; } if (sys_lock(*lock_fd, block) == 0) { rs_trace("got %s lock on %s slot %d as fd%d", lockname, host->hostdef_string, slot, *lock_fd); free(fname); return 0; } else { switch (errno) { #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif case EAGAIN: case EACCES: /* HP-UX and Cygwin give this for exclusion */ rs_trace("%s is busy", fname); ret = EXIT_BUSY; break; default: rs_log_error("lock %s failed: %s", fname, strerror(errno)); ret = EXIT_IO_ERROR; break; } dcc_close(*lock_fd); free(fname); return ret; } } distcc-3.4/src/lock.h000066400000000000000000000025011404653710500145240ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ int dcc_lock_host(const char *lockname, const struct dcc_hostdef *host, int slot, int block, int *lock_fd); int dcc_unlock(int lock_fd); int dcc_make_lock_filename(const char *lockname, const struct dcc_hostdef *host, int iter, char **); int dcc_open_lockfile(const char *fname, int *plockfd); distcc-3.4/src/lsdistcc.c000066400000000000000000001137371404653710500154150ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * lsdistcc -- A simple distcc server discovery program * Assumes all distcc servers are in DNS and are named distcc1...distccN. * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Program to autodetect listening distcc servers by looking in DNS * for hosts named according to a given format. * hosts are considered good servers based solely on whether their * name fits the format and whether they are listening on the right port * (and optionally whether they respond when you send them a compile job). * Stops looking for servers after the first one it doesn't find in DNS. * Prints results to stdout. * Terminates with error status if no servers found. * * Examples: * * In your build script, add the lines * DISTCC_HOSTS=`lsdistcc` * export DISTCC_HOSTS * before the line that invokes make. * * Or, in your Makefile, add the lines * export DISTCC_HOSTS = $(shell lsdistcc) * * Changelog: * * Wed Jun 20 2007 - Manos Renieris, Google * Added -P option. * * Mon Jun 4 2007 - Manos Renieris, Google * Reformatted in 80 columns. * * Tue Jan 31 2006 - Dan Kegel, Google * Added -x option to list down hosts with ,down suffix (since * in sharded server cache mode, the hash space is partitioned * over all servers regardless of whether they're up or down at the moment) * * Thu Jan 5 2006 - Dan Kegel, Google * Actually read the output from the server and partially parse it. * * Sat Nov 26 2005 - Dan Kegel, Google * Added -l option, improved -v output * * Tue Nov 22 2005 - Dan Kegel & Dongmin Zhang, Google * added -pcc option to check that server actually responds when you send * it a job * added -c0 option to disable connect check * * Thu Oct 13 2005 - Dan Kegel, Google * use rslave to do asynchronous-ish hostname lookup, do all connects * in parallel * * Wed Oct 5 2005 - Dan Kegel, Google * Added -d, -m options * * Fri Sep 16 2005 - Dan Kegel, Google * Created * Added -v option --------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "clinet.h" #include "netutil.h" #include "util.h" #include "trace.h" #include "rslave.h" #include "../lzo/minilzo.h" /* Linux calls this setrlimit() argument NOFILE; bsd calls it OFILE */ #ifndef RLIMIT_NOFILE #define RLIMIT_NOFILE RLIMIT_OFILE #endif enum status_e { STATE_LOOKUP = 0, STATE_CONNECT, STATE_CONNECTING, STATE_READ_DONEPKT, STATE_READ_STATPKT, STATE_READ_REST, STATE_CLOSE, STATE_DONE}; struct state_s { rslave_request_t req; rslave_result_t res; struct timeval start; struct timeval deadline; char curhdrbuf[12]; int curhdrlen; enum status_e status; int ntries; int fd; int up; /* default is 0, set to 1 on success */ }; typedef struct state_s state_t; /* Default parameters */ #define DEFAULT_FORMAT "distcc%d" /* hostname format */ #define DEFAULT_PORT 3632 /* TCP port to connect to */ #define DEFAULT_PROTOCOL 1 /* protocol we'll try to speak */ #define DEFAULT_BIGTIMEOUT 7 /* max total runtime, seconds */ #define DEFAULT_DNSTIMEOUT_MS 500 /* individual DNS timeout, msec */ #define DEFAULT_CONNTIMEOUT_MS 900 /* individual connect timeout, msec */ #define DEFAULT_COMPTIMEOUT_MS 1500 /* individual compile timeout, msec (FIXME: should be lower) */ #define DEFAULT_OVERLAP 1 /* number of simultaneous DNS queries -1 */ #define DEFAULT_DNSGAP 0 /* number of missing hosts in DNS before we stop looking */ #define DEFAULT_COMPILER "none" char canned_query[1000]; size_t canned_query_len = 0; int opt_latency = 0; int opt_numeric = 0; int opt_overlap = DEFAULT_OVERLAP; int opt_dnsgap = DEFAULT_DNSGAP; int opt_port = DEFAULT_PORT; int opt_protocol = DEFAULT_PROTOCOL; int opt_bigtimeout_sec = DEFAULT_BIGTIMEOUT; int opt_conntimeout_ms = DEFAULT_CONNTIMEOUT_MS; int opt_comptimeout_ms = DEFAULT_COMPTIMEOUT_MS; int opt_dnstimeout_ms = DEFAULT_DNSTIMEOUT_MS; int opt_verbose = 0; int opt_domain = 0; int opt_match = 0; int opt_bang_down = 0; const char *opt_compiler = NULL; const char *protocol_suffix[] = { NULL, /* to make the rest 1-based */ "", ",lzo", ",lzo,cpp" }; #define MAXHOSTS 500 #define MAXTRIES 5 /* this constant can't be changed without changing some code */ #define MAXFDS (MAXHOSTS+2) /* just plain globals */ int fd2state[MAXHOSTS+1000]; /* kludge - fragile */ int nok; int ndone; /* globals used by other compilation units */ const char *rs_program_name = "lsdistcc"; /* Forward declarations (solely to prevent compiler warnings) */ void usage(void); int bitcompare(const unsigned char *a, const unsigned char *b, int nbits); void timeout_handler(int x); void get_thename(const char**sformat, const char *domain_name, int i, char *thename); int detect_distcc_servers(const char **argv, int argc, int opti, int bigtimeout, int dnstimeout, int matchbits, int overlap, int dnsgap); void server_read_packet_header(state_t *sp); void server_handle_event(state_t *sp); void usage(void) { printf("Usage: lsdistcc [-tTIMEOUT] [-mBITS] [-nvd] [format]\n\ Uses 'for i=1... sprintf(format, i)' to construct names of servers,\n\ stops after %d seconds or at second server that doesn't resolve,\n\ prints the names of all such servers listening on distcc's port.\n\ Default format is %s. \n\ If a list of host names are given in the command line,\n\ lsdistcc will only check those hosts. \n\ Options:\n\ -l Output latency in milliseconds after each hostname\n\ (not including DNS latency)\n\ -n Print IP address rather than name\n\ -x Append ,down to down hosts in host list\n\ -tTIMEOUT Set number of seconds to stop searching after [%d]\n\ -hHTIMEOUT Set number of milliseconds before retrying gethostbyname [%d]\n\ -cCTIMEOUT Set number of milliseconds before giving up on connect [%d]\n\ (0 to inhibit connect)\n\ -kKTIMEOUT Set number of milliseconds before giving up on compile [%d]\n\ (0 to inhibit compile)\n\ -mBITS Set number of bits of address that must match first host found [0]\n\ -oOVERLAP Set number of extra DNS requests to send [%d]\n\ -gDNSGAP Set number of missing DNS entries to tolerate [%d]\n\ -rPORT Port to connect to [%d]\n\ -PPROTOCOL Protocol version to use (1-3) [%d]\n\ -pCOMPILER Name of compiler to use [%s]\n\ -d Append DNS domain name to format\n\ -v Verbose\n\ \n\ Example:\n\ lsdistcc -l -p$COMPILER\n\ lsdistcc -p$COMPILER hosta somehost hostx hosty\n\ ", DEFAULT_BIGTIMEOUT, DEFAULT_FORMAT, DEFAULT_BIGTIMEOUT, DEFAULT_DNSTIMEOUT_MS, DEFAULT_CONNTIMEOUT_MS, DEFAULT_COMPTIMEOUT_MS, DEFAULT_OVERLAP, DEFAULT_DNSGAP, DEFAULT_PORT, DEFAULT_PROTOCOL, DEFAULT_COMPILER); exit(1); } /* Compare first nbits of a[] and b[] * If nbits is 1, only compares the MSB of a[0] and b[0] * Return 0 on equal, nonzero on nonequal */ int bitcompare(const unsigned char *a, const unsigned char *b, int nbits) { int fullbytes = nbits/8; int leftoverbits = nbits & 7; if (fullbytes) { int d = memcmp((char *)a, (char *)b, (size_t) fullbytes); if (d) return d; } if (leftoverbits) { int mask = 0; int i; for (i=0; i main() { assert(bitcompare("0", "0", 8) == 0); assert(bitcompare("0", "1", 8) != 0); assert(bitcompare("0", "1", 7) == 0); } #endif /* On timeout, silently terminate program */ void timeout_handler(int x) { (void) x; if (opt_verbose > 0) fprintf(stderr, "Timeout!\n"); /* FIXME: is it legal to call exit here? */ exit(0); } static void generate_query(void) { const char* program = "int foo(){return 0;}"; unsigned char lzod_program[1000]; unsigned char lzo_work_mem[LZO1X_1_MEM_COMPRESS]; lzo_uint lzod_program_len; lzo1x_1_compress((const unsigned char *)program, strlen(program), lzod_program, &lzod_program_len, lzo_work_mem); switch (opt_protocol) { case 1: { static const char canned_query_fmt_protocol_1[]= "DIST00000001" "ARGC00000005" "ARGV%08x%s" "ARGV00000002-c" "ARGV00000007hello.c" "ARGV00000002-o" "ARGV00000007hello.o" "DOTI%08x%s"; sprintf(canned_query, canned_query_fmt_protocol_1, (unsigned)strlen(opt_compiler), opt_compiler, (unsigned)strlen(program), program); canned_query_len = strlen(canned_query); break; } case 2: { static const char canned_query_fmt_protocol_2[]= "DIST00000002" "ARGC00000005" "ARGV%08x%s" "ARGV00000002-c" "ARGV00000007hello.c" "ARGV00000002-o" "ARGV00000007hello.o" "DOTI%08x"; sprintf(canned_query, canned_query_fmt_protocol_2, (unsigned)strlen(opt_compiler), opt_compiler, (unsigned)lzod_program_len); canned_query_len = strlen(canned_query) + lzod_program_len; memcpy(canned_query + strlen(canned_query), lzod_program, lzod_program_len); break; } case 3: { static const char canned_query_fmt_protocol_3[]= "DIST00000003" "CDIR00000001/" "ARGC00000005" "ARGV%08x%s" "ARGV00000002-c" "ARGV00000007hello.c" "ARGV00000002-o" "ARGV00000007hello.o" "NFIL00000001" "NAME00000008/hello.c" "FILE%08x"; sprintf(canned_query, canned_query_fmt_protocol_3, (unsigned)strlen(opt_compiler), opt_compiler, (unsigned)lzod_program_len); canned_query_len = strlen(canned_query) + lzod_program_len; memcpy(canned_query + strlen(canned_query), lzod_program, lzod_program_len); break; } } } /* Try reading a protocol packet header */ void server_read_packet_header(state_t *sp) { int arg; int nread; nread = read(sp->fd, sp->curhdrbuf + sp->curhdrlen, (size_t)(12 - sp->curhdrlen)); if (nread == 0) { /* A nonblocking read returning zero bytes means EOF. * FIXME: it may mean this only on the first read after poll said * bytes were ready, so beware of false EOFs here? */ if (opt_verbose > 0) fprintf(stderr, "lsdistcc: premature EOF while waiting for " "result from server %s\n", sp->req.hname); sp->status = STATE_CLOSE; return; } if (nread > 0) sp->curhdrlen += nread; if (sp->curhdrlen < 12) return; arg = (int)strtol(sp->curhdrbuf+4, NULL, 16); if (opt_verbose > 2) { int i; printf("Got hdr '%12.12s' = ", sp->curhdrbuf); for (i=0; i < sp->curhdrlen; i++) printf("%2x", sp->curhdrbuf[i]); printf("\n"); } /* Parse and validate the packet header, move on to next state */ switch (sp->status) { case STATE_READ_DONEPKT: if (memcmp(sp->curhdrbuf, "DONE", 4) != 0) { if (opt_verbose > 1) fprintf(stderr, "%s wrong protocol; expected DONE, got %4.4s!\n", sp->req.hname, sp->curhdrbuf); sp->status = STATE_CLOSE; break; } if (arg != opt_protocol) { if (opt_verbose > 1) fprintf(stderr, "%s wrong protocol, expected %d got %d!\n", sp->req.hname, opt_protocol, arg); sp->status = STATE_CLOSE; break; } /* No body to this type. Read next packet. */ sp->curhdrlen = 0; sp->status = STATE_READ_STATPKT; break; case STATE_READ_STATPKT: if (memcmp(sp->curhdrbuf, "STAT", 4) != 0) { if (opt_verbose > 1) fprintf(stderr, "%s wrong protocol! Expected STAT, got %4.4s\n", sp->req.hname, sp->curhdrbuf); sp->status = STATE_CLOSE; break; } if (arg != 0) { if (opt_verbose > 1) { /* FIXME: only conditional because my server uses load shedding */ fprintf(stderr, "lsdistcc: warning: test compile on %s failed! " "status 0x%x\n", sp->req.hname, arg); } sp->status = STATE_CLOSE; break; } /* No body to this type. Read next packet. */ sp->curhdrlen = 0; sp->status = STATE_READ_REST; break; default: fprintf(stderr, "bug\n"); exit(1); } } /* Grind state machine for a single server */ /* Take one transition through the state machine, unless that takes you to STATE_CLOSE, in which case go through that state too, into STATE_DONE */ void server_handle_event(state_t *sp) { struct timeval now; gettimeofday(&now, 0); do { struct sockaddr_in sa; if (opt_verbose > 2) fprintf(stderr, "now %lld %ld: server_handle_event: %s: state %d\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname, sp->status); switch (sp->status) { case STATE_CONNECT: if (opt_conntimeout_ms == 0) { sp->fd = -1; sp->up = 1; sp->status = STATE_CLOSE; break; } /* Now do a nonblocking connect to that address */ memset(&sa, 0, sizeof sa); sa.sin_family = AF_INET; sa.sin_port = htons(opt_port); memcpy(&sa.sin_addr, sp->res.addr, 4); if ((sp->fd = socket(sa.sin_family, SOCK_STREAM, 0)) == -1) { fprintf(stderr, "failed to create socket: %s", strerror(errno)); sp->status = STATE_DONE; } else { dcc_set_nonblocking(sp->fd); /* start the nonblocking connect... */ if (opt_verbose > 0) fprintf(stderr, "now %lld %ld: Connecting to %s\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); if (connect(sp->fd, (struct sockaddr *)&sa, sizeof(sa)) && errno != EINPROGRESS) { if (opt_verbose > 0) fprintf(stderr, "failed to connect socket: %s", strerror(errno)); sp->status = STATE_CLOSE; } else { sp->status = STATE_CONNECTING; fd2state[sp->fd] = sp->res.id; gettimeofday(&now, 0); sp->start = now; sp->deadline = now; sp->deadline.tv_usec += 1000 * opt_conntimeout_ms; sp->deadline.tv_sec += sp->deadline.tv_usec / 1000000; sp->deadline.tv_usec = sp->deadline.tv_usec % 1000000; } } break; case STATE_CONNECTING: { int connecterr; socklen_t len = sizeof(connecterr); int nsend; int nsent; if (getsockopt(sp->fd, SOL_SOCKET, SO_ERROR, (char *)&connecterr, &len) < 0) { fprintf(stderr, "getsockopt SO_ERROR failed?!"); sp->status = STATE_CLOSE; break; } if (connecterr) { if (opt_verbose > 0) fprintf(stderr, "now %lld %ld: Connecting to %s failed " "with errno %d = %s\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname, connecterr, strerror(connecterr)); sp->status = STATE_CLOSE; /* not listening */ break; } if (opt_comptimeout_ms == 0 || !opt_compiler) { /* connect succeeded, don't need to compile */ sp->up = 1; sp->status = STATE_CLOSE; break; } if (opt_verbose > 0) fprintf(stderr, "now %lld %ld: %s: sending compile request\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); nsend = canned_query_len; nsent = write(sp->fd, canned_query, nsend); if (nsent != nsend) { if (opt_verbose > 1) { if (nsent == -1) fprintf(stderr, "now %lld %ld: Sending to %s failed, " "errno %d\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname, connecterr); else fprintf(stderr, "now %lld %ld: Sending to %s failed, " "nsent %d != nsend %d\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname, nsent, nsend); } /* ??? remote disconnect? Buffer too small? */ sp->status = STATE_CLOSE; break; } sp->status=STATE_READ_DONEPKT; sp->curhdrlen = 0; sp->deadline = now; sp->deadline.tv_usec += 1000 * opt_comptimeout_ms; sp->deadline.tv_sec += sp->deadline.tv_usec / 1000000; sp->deadline.tv_usec = sp->deadline.tv_usec % 1000000; } break; case STATE_READ_DONEPKT: case STATE_READ_STATPKT: server_read_packet_header(sp); break; case STATE_READ_REST: { char buf[1000]; int nread; nread = read(sp->fd, buf, sizeof(buf)); if (nread == 0) { /* A nonblocking read returning zero bytes means EOF. * FIXME: it may mean this only on the first read after * poll said bytes were ready, so beware of false EOFs here? */ sp->up = 1; sp->status = STATE_CLOSE; } } break; case STATE_CLOSE: if (sp->fd != -1) { close(sp->fd); sp->fd = -1; } if (opt_bang_down || sp->up) { if (opt_numeric) printf("%d.%d.%d.%d", sp->res.addr[0], sp->res.addr[1], sp->res.addr[2], sp->res.addr[3]); else printf("%s", sp->req.hname); if (opt_port != DEFAULT_PORT) printf(":%d", opt_port); printf("%s", protocol_suffix[opt_protocol]); if (opt_bang_down && !sp->up) printf(",down"); if (opt_latency) { int latency_ms; gettimeofday(&now, 0); latency_ms = (now.tv_usec - sp->start.tv_usec) / 1000 + 1000 * (now.tv_sec - sp->start.tv_sec); printf(" %d", latency_ms); } putchar('\n'); if (opt_verbose) fflush(stdout); } nok++; sp->status = STATE_DONE; ndone++; break; case STATE_DONE: ; default: ; } } while (sp->status == STATE_CLOSE); } /* A helper function for detecting all listening distcc servers: this * routine makes one pass through the poll() loop and analyzes what it * sees. */ static int one_poll_loop(struct rslave_s* rs, struct state_s states[], int start_state, int end_state, int nwithtries[], int* ngotaddr, int* nbaddns, unsigned char firstipaddr[4], int dnstimeout_usec, int matchbits, int overlap, int dnsgap) { int i; int nfds; struct state_s *sp; int nready; int found; struct timeval now; struct pollfd pollfds[MAXFDS]; /* See which sockets have any events */ nfds = 0; memset(pollfds, 0, sizeof(pollfds)); pollfds[nfds].fd = rslave_getfd_fromSlaves(rs); pollfds[nfds++].events = POLLIN; pollfds[nfds].fd = rslave_getfd_toSlaves(rs); /* Decide if we want to be notified if slaves are ready to handle * a DNS request. * To avoid sending too many DNS requests, we avoid sending more if * the number of first tries is greater than 'overlap' * or the number of outstanding DNS requests plus the number of * already satisfied ones would be greater than or equal to the max * number of hosts we're looking for. */ pollfds[nfds++].events = ((nwithtries[1] <= overlap) && (nwithtries[1]+ nwithtries[2]+ nwithtries[3]+ nwithtries[4]+ *ngotaddr < end_state)) ? POLLOUT : 0; /* Set interest bits. * When connecting, we want to know if we can write (aka if the * connect has finished); when waiting for a compile to finish, * we want to know if we can read. */ for (i=start_state; i<=end_state; i++) { switch (states[i].status) { case STATE_CONNECTING: pollfds[nfds].fd = states[i].fd; pollfds[nfds++].events = POLLOUT; break; case STATE_READ_DONEPKT: case STATE_READ_STATPKT: case STATE_READ_REST: pollfds[nfds].fd = states[i].fd; pollfds[nfds++].events = POLLIN; break; default: ; } } /* When polling, wait for no more than 50 milliseconds. * Anything lower doesn't help performance much. * Anything higher would inflate all our timeouts, * cause retries not to be sent as soon as they should, * and make the program take longer than it should. */ nready = poll(pollfds, (unsigned)nfds, 50); if (nready == -1) { fprintf(stderr, "lsdistcc: poll failed: %s\n", strerror(errno)); exit(1); } gettimeofday(&now, 0); /***** Check for timeout events *****/ sp = NULL; found = FALSE; for (i=start_state; i<=end_state; i++) { sp = &states[i]; if (sp->status == STATE_LOOKUP && sp->ntries > 0 && sp->ntries < MAXTRIES && (sp->deadline.tv_sec < now.tv_sec || (sp->deadline.tv_sec == now.tv_sec && sp->deadline.tv_usec < now.tv_usec))) { found = TRUE; nwithtries[sp->ntries]--; sp->ntries++; nwithtries[sp->ntries]++; if (opt_verbose > 0) fprintf(stderr, "now %lld %ld: Resending %s because " "deadline was %lld %ld\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname, (long long) sp->deadline.tv_sec, (long) sp->deadline.tv_usec/1000); break; } if (sp->status == STATE_CONNECTING && (sp->deadline.tv_sec < now.tv_sec || (sp->deadline.tv_sec == now.tv_sec && sp->deadline.tv_usec < now.tv_usec))) { sp->status = STATE_CLOSE; server_handle_event(sp); if (opt_verbose > 0) fprintf(stderr, "now %lld %ld: %s timed out while connecting\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); } if ((sp->status == STATE_READ_DONEPKT || sp->status == STATE_READ_STATPKT || sp->status == STATE_READ_REST) && (sp->deadline.tv_sec < now.tv_sec || (sp->deadline.tv_sec == now.tv_sec && sp->deadline.tv_usec < now.tv_usec))) { sp->status = STATE_CLOSE; server_handle_event(sp); if (opt_verbose > 0) fprintf(stderr, "now %lld %ld: %s timed out while compiling\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); } } if (!found && (nwithtries[1] <= overlap) && (pollfds[1].revents & POLLOUT)) { /* Look for a fresh record to send */ for (i=start_state; i<=end_state; i++) { sp = &states[i]; if (sp->status == STATE_LOOKUP && sp->ntries == 0) { found = TRUE; nwithtries[sp->ntries]--; sp->ntries++; nwithtries[sp->ntries]++; break; } } } /* If we found a record to send or resend, send it, and mark its timeout. */ if (found) { if (opt_verbose) fprintf(stderr, "now %lld %ld: Looking up %s\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); rslave_writeRequest(rs, &sp->req); sp->deadline = now; sp->deadline.tv_usec += dnstimeout_usec; sp->deadline.tv_sec += sp->deadline.tv_usec / 1000000; sp->deadline.tv_usec = sp->deadline.tv_usec % 1000000; } /***** Check poll results for DNS results *****/ if (pollfds[0].revents & POLLIN) { /* A reply is ready, huzzah! */ rslave_result_t result; if (rslave_readResult(rs, &result)) { printf("bug: can't read from pipe\n"); } else { /* Find the matching state_t, save the result, and mark it as done */ /* printf("result.id %d\n", result.id); fflush(stdout); */ assert(result.id >= start_state && result.id <= end_state); sp = &states[result.id]; if (sp->status == STATE_LOOKUP) { nwithtries[sp->ntries]--; sp->res = result; (*ngotaddr)++; if (matchbits > 0) { if (*ngotaddr == 1) { memcpy(firstipaddr, result.addr, 4); } else { /* break if new server on a 'different network' than first server */ if (bitcompare(firstipaddr, result.addr, matchbits)) result.err = -1; } } if (result.err) { if (opt_verbose) fprintf(stderr, "now %lld %ld: %s not found\n", (long long) now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); sp->status = STATE_DONE; ndone++; (*nbaddns)++; if (*nbaddns > dnsgap) { int highest = 0; /* start no more lookups */ for (i=start_state; i <= end_state; i++) if (states[i].ntries > 0) highest = i; assert(highest <= end_state); if (opt_verbose && end_state != highest) fprintf(stderr, "Already searching up to host %d, " "won't search any higher\n", highest); end_state = highest; assert(end_state <= MAXHOSTS); } } else { sp->status = STATE_CONNECT; server_handle_event(sp); } } } } /***** Grind state machine for each remote server *****/ for (i=2; i rlim.rlim_max) rlim.rlim_cur = rlim.rlim_max; setrlimit(RLIMIT_NOFILE, &rlim); getrlimit(RLIMIT_NOFILE, &rlim); if (rlim.rlim_cur > 14) maxfds = (int)(rlim.rlim_cur - 10); } /* Don't run longer than bigtimeout seconds */ signal(SIGALRM, timeout_handler); alarm((unsigned) bigtimeout); if (rslave_init(&rs)) return 0; ngotaddr = 0; memset(nwithtries, 0, sizeof(nwithtries)); memset(states, 0, sizeof(states)); /* all hosts start off in state 'sent 0' */ for (i=1; i<=n; i++) { rslave_request_t *req = &states[i].req; get_thename(sformat, domain_name, i, thename); rslave_request_init(req, thename, i); states[i].status = STATE_LOOKUP; states[i].ntries = 0; nwithtries[0]++; } ndone = 0; nok = 0; nbaddns = 0; /* Loop until we're done finding distcc servers. We have to do * this loop in groups, with each group using no more than maxfds * fd's. One call to one_poll_loop uses n + 2 fds. */ for (start_state = 1; start_state <= n; start_state = end_state + 1) { int orig_end_state; end_state = start_state + maxfds-2; if (end_state > n) end_state = n; orig_end_state = end_state; while (ndone < end_state) { end_state = one_poll_loop(&rs, states, start_state, end_state, nwithtries, &ngotaddr, &nbaddns, firstipaddr, dnstimeout_usec, matchbits, overlap, dnsgap); } if (end_state < orig_end_state) { /* If we lowered end_state, it means we decided to stop * searching early. */ break; } } return nok; } int main(int argc, char **argv) { int opti; int nfound; for (opti = 1; opti < argc && argv[opti][0] == '-'; opti++) { switch (argv[opti][1]) { case 'm': opt_match = atoi(argv[opti]+2); if (opt_match > 31 || opt_match < 0) usage(); break; case 't': opt_bigtimeout_sec = atoi(argv[opti]+2); if (opt_bigtimeout_sec < 0) usage(); break; case 'h': opt_dnstimeout_ms = atoi(argv[opti]+2); if (opt_dnstimeout_ms < 0) usage(); break; case 'c': opt_conntimeout_ms = atoi(argv[opti]+2); if (opt_conntimeout_ms < 0) usage(); break; case 'k': opt_comptimeout_ms = atoi(argv[opti]+2); if (opt_comptimeout_ms < 0) usage(); break; case 'o': opt_overlap = atoi(argv[opti]+2); if (opt_overlap < 0) usage(); break; case 'g': opt_dnsgap = atoi(argv[opti]+2); if (opt_dnsgap < 0) usage(); break; case 'P': opt_protocol = atoi(argv[opti]+2); if (opt_protocol <= 0 || opt_protocol > 3) { usage(); } break; case 'p': opt_compiler = argv[opti]+2; if (! *opt_compiler) usage(); break; case 'r': opt_port = atoi(argv[opti]+2); if (opt_port <= 0) usage(); break; case 'l': opt_latency = 1; break; case 'n': opt_numeric = 1; break; case 'x': opt_bang_down = 1; break; case 'v': opt_verbose++; break; case 'd': opt_domain++; break; default: usage(); } } if (opt_compiler) generate_query(); nfound = detect_distcc_servers((const char **)argv, argc, opti, opt_bigtimeout_sec, opt_dnstimeout_ms, opt_match, opt_overlap, opt_dnsgap); /* return failure if no servers found */ return (nfound > 0) ? 0 : 1; } distcc-3.4/src/mon-gnome.c000066400000000000000000000444701404653710500154760ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * @file * * Gnome 2.x monitor for distcc. * * For each slot we have a record in a tree model, including an array * indicating the past states. This is stored in the "history" column * of the TreeMode for that slot. * * The renderer knows how to walk over the queue and draw state * rectangles for the values it finds. The queue is implemented as a * circular array, whose values are initialized to idle. * * Starved jobs are currently not shown in the chart view. * * Colors should perhaps be customizable with reasonable defaults. */ /* FIXME: When the dialogs are dismissed, they seem to get destroyed. We need to make sure that they just get hidden and can be summoned again. */ /* last one using chart drawingarea is 1.43.2.37 */ #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_LOADAVG_H # include #endif #ifdef WITH_GNOME # include #endif #include #include "types.h" #include "distcc.h" #include "rpc.h" #include "trace.h" #include "exitcode.h" #include "mon.h" #include "renderer.h" const char *rs_program_name = "distccmon-gnome"; static GtkWidget *chart_treeview; static GtkListStore *chart_model; /* Note: these must match the types given in order in the call to gtk_list_store_new() */ enum { COLUMN_HOST, COLUMN_SLOT, COLUMN_FILE, COLUMN_STATE, COLUMN_HISTORY, }; /* * Colors used for drawing different state stripes. * * These color names are from the GNOME standard palette. */ GdkRGBA task_color[DCC_PHASE_DONE]; const char * task_color_string[] = { "#999900000000", /* DCC_PHASE_STARTUP, accent red dark */ "#999900000000", /* DCC_PHASE_BLOCKED, accent red dark */ "#c1c166665a5a", /* DCC_PHASE_CONNECT, red medium */ "#88887f7fa3a3", /* DCC_PHASE_CPP, purple medium*/ "#e0e0c3c39e9e", /* DCC_PHASE_SEND, face skin medium*/ "#8383a6a67f7f", /* DCC_PHASE_COMPILE, green medium */ "#75759090aeae", /* DCC_PHASE_RECEIVE, blue medium*/ "#000000000000", /* DCC_PHASE_DONE */ }; /** * Initialize rgba colors for drawing in the right color for each state. **/ static void dcc_create_state_colors (void) { enum dcc_phase i_state; for (i_state = 0; i_state <= DCC_PHASE_DONE; i_state++) { gdk_rgba_parse(&task_color[i_state],task_color_string[i_state]); } } static void dcc_setup_tree_model (void) { /* Create a table for process status */ chart_model = gtk_list_store_new (5, G_TYPE_STRING, /* host */ G_TYPE_INT, /* slot */ G_TYPE_STRING, /* file */ G_TYPE_STRING, /* state */ G_TYPE_POINTER /* history */ ); } static void dcc_row_history_push (GtkListStore *model, GtkTreeIter *tree_iter, enum dcc_phase new_state) { struct dcc_history *history; gtk_tree_model_get(GTK_TREE_MODEL (model), tree_iter, COLUMN_HISTORY, &history, -1); dcc_history_push(history, new_state); /* Perhaps we should call gtk_tree_model_row_changed(), but at the moment every call to this is associated with some other change to the model so I don't think there's any need. */ } static void dcc_set_row_from_task (GtkListStore *model, GtkTreeIter *tree_iter, struct dcc_task_state *task) { dcc_row_history_push (model, tree_iter, task->curr_phase); gtk_list_store_set (model, tree_iter, COLUMN_HOST, task->host, COLUMN_SLOT, task->slot, COLUMN_FILE, task->file, COLUMN_STATE, dcc_get_phase_name(task->curr_phase), -1); } static void dcc_insert_row_from_task (GtkListStore *model, GtkTreeIter *tree_iter, GtkTreeIter *insert_before, struct dcc_task_state *task_iter) { struct dcc_history *history; history = dcc_history_new(); dcc_history_push(history, task_iter->curr_phase); gtk_list_store_insert_before(chart_model, tree_iter, insert_before); gtk_list_store_set(model, tree_iter, COLUMN_HOST, task_iter->host, COLUMN_SLOT, task_iter->slot, COLUMN_FILE, task_iter->file, COLUMN_STATE, dcc_get_phase_name(task_iter->curr_phase), COLUMN_HISTORY, history, -1); } static void dcc_set_row_idle(GtkListStore *model, GtkTreeIter *tree_iter) { struct dcc_history *history; gtk_tree_model_get(GTK_TREE_MODEL (model), tree_iter, COLUMN_HISTORY, &history, -1); /* only write to the treemodel if it was previously non-idle */ if (history->past_phases[history->now] != DCC_PHASE_DONE) { gtk_list_store_set (model, tree_iter, COLUMN_FILE, NULL, COLUMN_STATE, NULL, -1); } else { /* it still changed... */ GtkTreePath *path; path = gtk_tree_model_get_path(GTK_TREE_MODEL(model), tree_iter); gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, tree_iter); gtk_tree_path_free(path); } dcc_history_push(history, DCC_PHASE_DONE); } /** * * We update the list model in place by looking for slots which have a * different state to last time we polled. * * mon.c always returns state records to us in a consistent order, * sorted by hostname and then by slot. The list model is always held * in the same order. Over time some slots may become empty, or some * new slots may be used. * * Walking through the task list and the tree store in order makes it * fairly easy to see where tasks have been inserted, removed, or * changed. * * When there is no task for a row, we don't remove the row from the * list model. This is for two reasons: one is that it stops rows * bouncing around too much when they're not fully loaded. In the * future when we draw a state history, this will allow rows to * persist showing what they did in the past, even if they're doing * nothing now. * * Every time through, we update each table row exactly once, whether * that is adding new state, setting it back to idle, or inserting * it. In particular, on each pass we add one value to the start of * every state history. **/ static void dcc_update_store_from_tasks (struct dcc_task_state *task_list) { struct dcc_task_state *task_iter; GtkTreeIter tree_iter[1]; gboolean tree_valid; int cmp; GtkTreeModel *tree_model = GTK_TREE_MODEL (chart_model); tree_valid = gtk_tree_model_get_iter_first (tree_model, tree_iter); for (task_iter = task_list; task_iter != NULL && tree_valid; ) { gchar *row_host; int row_slot; if (task_iter->curr_phase == DCC_PHASE_DONE || task_iter->host[0] == '\0' || task_iter->file[0] == '\0') { /* skip this */ task_iter = task_iter->next; continue; } gtk_tree_model_get (tree_model, tree_iter, COLUMN_HOST, &row_host, COLUMN_SLOT, &row_slot, -1); cmp = strcmp (task_iter->host, row_host); if (cmp == 0) cmp = task_iter->slot - row_slot; g_free(row_host); /* g_message ("host %s, slot %d, file %s -> cmp=%d", */ /* task_iter->host, task_iter->slot, task_iter->file, cmp); */ /* What is the relative order of the task and the row, based on host and slot? */ if (cmp == 0) { /* If the task and row match, then update the row from the task if necessary */ dcc_set_row_from_task (chart_model, tree_iter, task_iter); /* Proceed to next task and row */ task_iter = task_iter->next; } else if (cmp < 0) { /* If this task comes before the row, then the task must be on a slot that is not yet on the table store. Insert a row. */ /* g_message ("insert row for host %s, slot %d", */ /* task_iter->host, task_iter->slot); */ dcc_insert_row_from_task (chart_model, tree_iter, tree_iter, task_iter); /* Proceed to next task and the row after the one we just inserted. */ task_iter = task_iter->next; } else /* cmp > 0 */ { /* If this row comes before the current task, then the row must be for a slot that's no longer in use. Clear the row */ dcc_set_row_idle (chart_model, tree_iter); /* Compare next row against the same task */ } tree_valid = gtk_tree_model_iter_next (tree_model, tree_iter); } /* If we finished the tree before we finished the task list, then just insert all the others at the end. */ for (; task_iter != NULL; task_iter = task_iter->next) { if (task_iter->curr_phase == DCC_PHASE_DONE) continue; if (task_iter->host[0] == '\0' || task_iter->file[0] == '\0') continue; /* g_message ("append row for host %s, slot %d", */ /* task_iter->host, task_iter->slot); */ dcc_insert_row_from_task (chart_model, tree_iter, NULL, /* insert at end */ task_iter); } /* If we finished the task list before we finished the rows, clear all the others. */ for (; tree_valid; tree_valid = gtk_tree_model_iter_next (tree_model, tree_iter)) { /* g_message ("clobber row"); */ dcc_set_row_idle (chart_model, tree_iter); } } /** * Callback when the timer triggers, causing a refresh. Loads the * current state from the state monitor and puts it into the table * model, which should then redraw itself. **/ static gint dcc_gnome_update_cb (gpointer UNUSED(view_void)) { struct dcc_task_state *task_list; if (dcc_mon_poll (&task_list)) { rs_log_warning("poll failed"); return TRUE; } dcc_update_store_from_tasks (task_list); dcc_task_state_free (task_list); return TRUE; /* please call again */ } static gchar *dcc_gnome_get_title (void) { char host[256]; const char *user; struct passwd *pw; if (gethostname(host, sizeof host) == -1) strcpy (host, "localhost"); /* We need to look up from our pid rather than using $LOGIN or $USER because that's consistent with the monitor routines. Otherwise you might get strange results from "sudo distccmon-gnome". */ user = NULL; pw = getpwuid (getuid ()); if (pw) user = pw->pw_name; if (!user) user = ""; return g_strdup_printf ("distcc Monitor - %s@%s", user, host); } static gint dcc_gnome_load_update_cb (gpointer data) { gchar message[200]; double loadavg[3]; guint context_id; if (getloadavg (loadavg, 3) == -1) { rs_log_error ("getloadavg failed: %s", strerror (errno)); return FALSE; /* give up */ } snprintf (message, sizeof message, "Load average: %.2f, %.2f, %.2f", loadavg[0], loadavg[1], loadavg[2]); context_id = gtk_statusbar_get_context_id(GTK_STATUSBAR (data), "load"); gtk_statusbar_pop(GTK_STATUSBAR (data), context_id); gtk_statusbar_push(GTK_STATUSBAR (data), context_id, message); return TRUE; /* please call again */ } /** * Configure GtkTreeView with the right columns bound to * renderers, and a data model. **/ static void dcc_gnome_make_proc_view (GtkTreeModel *proc_model, GtkWidget **widget_return) { GtkCellRenderer *text_renderer, *chart_renderer; GtkTreeSelection *selection; GtkTreeViewColumn *column; GtkWidget *proc_scroll; chart_treeview = gtk_tree_view_new_with_model (proc_model); g_object_set (G_OBJECT (chart_treeview), "headers-visible", TRUE, NULL); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (chart_treeview)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE); text_renderer = gtk_cell_renderer_text_new (); chart_renderer = dcc_cell_renderer_chart_new (); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (chart_treeview)); gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE); /* Host */ column = gtk_tree_view_column_new_with_attributes ("Host", text_renderer, "text", COLUMN_HOST, NULL); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (chart_treeview), column); /* gtk_tree_view_column_set_sort_column_id (column, COLUMN_HOST); */ column = gtk_tree_view_column_new_with_attributes ("Slot", text_renderer, "text", COLUMN_SLOT, NULL); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (chart_treeview), column); /* File */ column = gtk_tree_view_column_new_with_attributes ("File", text_renderer, "text", COLUMN_FILE, NULL); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (chart_treeview), column); column = gtk_tree_view_column_new_with_attributes ("State", text_renderer, "text", COLUMN_STATE, NULL); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (chart_treeview), column); /* Tasks - for each cell, rebind the stock-id property onto that value from the table model */ column = gtk_tree_view_column_new_with_attributes ("Tasks", chart_renderer, "history", COLUMN_HISTORY, NULL); gtk_tree_view_column_set_resizable (column, TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW (chart_treeview), column); proc_scroll = gtk_scrolled_window_new (NULL, NULL); /* no horizontal scrolling; let the table stretch */ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (proc_scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_container_add (GTK_CONTAINER (proc_scroll), chart_treeview); *widget_return = proc_scroll; } static GtkWidget * dcc_gnome_make_load_bar (void) { GtkWidget *bar; gint context_id; bar = gtk_statusbar_new (); gtk_widget_set_margin_top(GTK_WIDGET(bar), 0); gtk_widget_set_margin_bottom(GTK_WIDGET(bar), 0); context_id = gtk_statusbar_get_context_id(GTK_STATUSBAR (bar), "load"); gtk_statusbar_push(GTK_STATUSBAR (bar), context_id, "Load: "); g_timeout_add (2000, /* ms */ dcc_gnome_load_update_cb, bar); dcc_gnome_load_update_cb (bar); return bar; } static GtkWidget * dcc_gnome_make_mainwin (void) { GtkWidget *mainwin; mainwin = gtk_window_new (GTK_WINDOW_TOPLEVEL); { char *title; title = dcc_gnome_get_title (); gtk_window_set_title (GTK_WINDOW (mainwin), title); free (title); } /* Set a reasonable default size that allows all columns and a few rows to be seen with a typical theme */ gtk_window_set_default_size (GTK_WINDOW (mainwin), 500, 300); /* Quit when it's closed */ g_signal_connect (G_OBJECT(mainwin), "delete-event", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (G_OBJECT(mainwin), "destroy", G_CALLBACK (gtk_main_quit), NULL); #if GTK_CHECK_VERSION(2,2,0) gtk_window_set_icon_from_file (GTK_WINDOW (mainwin), ICONDIR "/distccmon-gnome.png", NULL); #endif return mainwin; } static int dcc_gnome_make_app (void) { GtkWidget *topbox, *proc_align, *load_bar; GtkWidget *mainwin; /* Create the main window */ mainwin = dcc_gnome_make_mainwin (); /* Create a gtkbox for the contents */ topbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (mainwin), topbox); load_bar = dcc_gnome_make_load_bar (); dcc_setup_tree_model (); dcc_gnome_make_proc_view (GTK_TREE_MODEL (chart_model), &proc_align); gtk_container_add (GTK_CONTAINER (topbox), proc_align); gtk_box_set_child_packing (GTK_BOX (topbox), GTK_WIDGET (proc_align), TRUE, TRUE, 0, GTK_PACK_START); gtk_box_pack_end (GTK_BOX (topbox), load_bar, FALSE, /* expand */ FALSE, 0); g_timeout_add_full (G_PRIORITY_HIGH_IDLE, 500, /* ms */ dcc_gnome_update_cb, NULL, NULL); /* Show the application window */ gtk_widget_show_all (mainwin); return 0; } int main(int argc, char **argv) { /* We don't want to take too much time away from the real work of * compilation */ nice(5); gtk_init (&argc, &argv); /* do our own initialization */ dcc_create_state_colors(); dcc_gnome_make_app (); /* Keep running until quit */ gtk_main (); return 0; } distcc-3.4/src/mon-notify.c000066400000000000000000000066221404653710500156760ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "rpc.h" #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "snprintf.h" #include "mon.h" #include "util.h" #include "netutil.h" static volatile int pipe_fd[2]; static void dcc_mon_siginfo_handler (int UNUSED (whatsig)) { /* Just ignore any errors. If people aren't listening or the pipe * is full, too bad. */ write (pipe_fd[1], "*", 1); } /* * Try to setup dnotify on the state directory. This returns the * descriptor of a pipe in @p dummy_fd. Every time the state changes, * a single byte is written to this pipe. A caller who select()s on * the pipe will therefore be woken every time there is a change. * * If we can do dnotify, create the dummy pipe and turn it on. * * @fixme One problem here is that if the state directory is deleted * and recreated, then we'll never notice and find the new one. I * don't know of any good fix, other than perhaps polling every so * often. So just don't do that. * * @fixme If this function is called repeatedly it will leak FDs. * * @todo Reimplement this on top of kevent for BSD. */ int dcc_mon_setup_notify (int *dummy_fd) { #ifdef F_NOTIFY char *state_dir; int ret; int fd; if (signal (SIGIO, dcc_mon_siginfo_handler) == SIG_ERR) { rs_log_error ("signal(SIGINFO) failed: %s", strerror(errno)); return EXIT_IO_ERROR; } if (pipe ((int *) pipe_fd) == -1) { rs_log_error ("pipe failed: %s", strerror (errno)); return EXIT_IO_ERROR; } *dummy_fd = pipe_fd[0]; /* read end */ dcc_set_nonblocking (pipe_fd[0]); dcc_set_nonblocking (pipe_fd[1]); if ((ret = dcc_get_state_dir (&state_dir))) return ret; if ((fd = open (state_dir, O_RDONLY)) == -1) { rs_log_error ("failed to open %s: %s", state_dir, strerror (errno)); free (state_dir); return EXIT_IO_ERROR; } /* CAUTION! Signals can start arriving immediately. Be ready. */ if (fcntl (fd, F_NOTIFY, DN_RENAME|DN_DELETE|DN_MULTISHOT) == -1) { rs_log_warning ("setting F_NOTIFY failed: %s", strerror (errno)); free (state_dir); return EXIT_IO_ERROR; } return 0; #else /* F_NOTIFY */ return EXIT_IO_ERROR; #endif /* F_NOTIFY */ } distcc-3.4/src/mon-text.c000066400000000000000000000054771404653710500153610ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "rpc.h" #include "trace.h" #include "exitcode.h" #include "snprintf.h" #include "mon.h" /** * @file * * Plain text monitor program. Just prints out the state once, or * repeatedly, kind of like Linux vmstat. */ const char *rs_program_name = "distccmon-text"; static void usage(void) { fprintf(stderr, "usage: distccmon-text [DELAY]\n" "\n" "Displays current compilation jobs in text form.\n" "\n" "If delay is specified, repeatedly updates after that many (fractional)\n" "seconds. Otherwise, runs just once.\n"); } int main(int argc, char *argv[]) { struct dcc_task_state *list; int ret; float delay; char *end; dcc_set_trace_from_env(); if (argc == 1) delay = 0.0; else if (argc == 2) { delay = strtod(argv[1], &end); if (*end) { usage(); return 1; } } else { usage(); return 1; } /* We might be writing to e.g. a pipe that's being read by some * other program, so make sure we're always line buffered. */ setvbuf (stdout, NULL, _IOLBF, BUFSIZ); do { struct dcc_task_state *i; if ((ret = dcc_mon_poll(&list))) return ret; for (i = list; i; i = i->next) { #if 1 if (i->curr_phase == DCC_PHASE_DONE) continue; #endif /* Assume 80 cols = */ printf("%6ld %-10.10s %-30.30s %24.24s[%d]\n", (long) i->cpid, dcc_get_phase_name(i->curr_phase), i->file, i->host, i->slot); } printf("\n"); /* XXX: usleep() is probably not very portable */ usleep(delay * 1000000); dcc_task_state_free(list); } while (delay); return 0; } distcc-3.4/src/mon.c000066400000000000000000000225601404653710500143670ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "rpc.h" #include "trace.h" #include "exitcode.h" #include "snprintf.h" #include "mon.h" #include "util.h" /** * @file * * Common routines for monitoring compiler state. * * Every time the client wants an update, it can call dcc_mon_poll(), * which returns a newly allocated list of all running processes. * * The list is returned sorted by hostname and then by slot, so tasks * will be more stable from one call to the next. **/ /* TODO: Shouldn't fail if the directory doesn't exist at the moment * it's called. */ /* * State files older than this are assumed to be leftovers from * compilers that died off. It's possible for a remote compilation to * take a very long time, and combined with the check that the process * exists we can allow this to be reasonably large. */ const int dcc_phase_max_age = 60; /** * Check if the state file @p fd is too old to be believed -- probably * because it was left over from a client that was killed. * * If so, close @p fd, unlink the file, and return EXIT_GONE. * * fd is closed on failure. **/ static int dcc_mon_kill_old(int fd, char *fullpath) { struct stat st; time_t now; /* Check if the file is old. */ if (fstat(fd, &st) == -1) { dcc_close(fd); rs_log_warning("error statting %s: %s", fullpath, strerror(errno)); return EXIT_IO_ERROR; } time(&now); /* Time you hear the siren / it's already too late */ if (now - st.st_mtime > dcc_phase_max_age) { dcc_close(fd); /* close first for windoze */ rs_trace("unlink %s", fullpath); if (unlink(fullpath) == -1) { rs_log_warning("unlink %s failed: %s", fullpath, strerror(errno)); return EXIT_IO_ERROR; } return EXIT_GONE; } return 0; } static int dcc_mon_read_state(int fd, char *fullpath, struct dcc_task_state *lp) { int nread; /* Don't use dcc_readx(), because not being able to read it is not * a big deal. */ nread = read(fd, lp, sizeof *lp); if (nread == -1) { rs_trace("failed to read state from %s: %s", fullpath, strerror(errno)); return EXIT_IO_ERROR; } else if (nread == 0) { /* empty file; just bad timing. */ return EXIT_IO_ERROR; } else if (nread != sizeof *lp) { rs_trace("short read getting state from %s", fullpath); return EXIT_IO_ERROR; } /* sanity-check some fields */ if (lp->magic != DCC_STATE_MAGIC) { rs_log_warning("wrong magic number: %s", fullpath); return EXIT_IO_ERROR; } if (lp->struct_size != sizeof (struct dcc_task_state)) { rs_log_warning("wrong structure size: %s: version mismatch?", fullpath); return EXIT_IO_ERROR; } lp->file[sizeof lp->file - 1] = '\0'; lp->host[sizeof lp->host - 1] = '\0'; if (lp->curr_phase > DCC_PHASE_DONE) { lp->curr_phase = DCC_PHASE_COMPILE; } lp->next = 0; return 0; } /** * Check that the process named by the file still exists; if not, * return EXIT_GONE. **/ static int dcc_mon_check_orphans(struct dcc_task_state *monl) { /* signal 0 just checks if it exists */ if (!kill(monl->cpid, 0)) { return 0; /* it's here */ } else if (errno == EPERM) { /* It's here, but it's not ours. Assume it's still a real * distcc process. */ return 0; } else if (errno == ESRCH) { return EXIT_GONE; /* no such pid */ } else { rs_log_warning("kill %ld, 0 failed: %s", (long) monl->cpid, strerror(errno)); return EXIT_GONE; } } /** * Read state. If loaded successfully, store a pointer to the newly * allocated structure into *ppl. */ static int dcc_mon_load_state(int fd, char *fullpath, struct dcc_task_state **ppl) { int ret; struct dcc_task_state *tl; tl = calloc(1, sizeof *tl); if (!tl) { rs_log_crit("failed to allocate dcc_task_state"); return EXIT_OUT_OF_MEMORY; } ret = dcc_mon_read_state(fd, fullpath, tl); if (ret) { dcc_task_state_free(tl); *ppl = NULL; return ret; } if (tl->curr_phase != DCC_PHASE_DONE) { ret = dcc_mon_check_orphans(tl); if (ret) { dcc_task_state_free(tl); *ppl = NULL; return ret; } } *ppl = tl; return ret; } /* Free the whole list */ int dcc_task_state_free(struct dcc_task_state *lp) { struct dcc_task_state *next; while (lp) { next = lp->next; /* save from clobbering */ free(lp); /* nothing dynamically allocated in them anymore */ lp = next; } return 0; } /** * Read in @p filename from inside @p dirname, and try to parse it as * a status file. * * If a new entry is read, a pointer to it is returned in @p lp. **/ static int dcc_mon_do_file(char *dirname, char *filename, struct dcc_task_state **lp) { int fd; char *fullpath; int ret; *lp = NULL; /* Is this a file we want to see */ if (!str_startswith(dcc_state_prefix, filename)) { /* rs_trace("skipped"); */ return 0; } checked_asprintf(&fullpath, "%s/%s", dirname, filename); if (fullpath == NULL) { return EXIT_OUT_OF_MEMORY; } rs_trace("process %s", fullpath); /* Remember that the file might disappear at any time, so open it * now so that we can hang on. */ if ((fd = open(fullpath, O_RDONLY|O_BINARY, 0)) == -1) { if (errno == ENOENT) { rs_trace("%s disappeared", fullpath); ret = 0; goto out_free; } else { /* hm */ rs_log_warning("failed to open %s: %s", fullpath, strerror(errno)); ret = EXIT_IO_ERROR; goto out_free; } } if ((ret = dcc_mon_kill_old(fd, fullpath))) { /* closes fd on failure */ goto out_free; } ret = dcc_mon_load_state(fd, fullpath, lp); dcc_close(fd); out_free: free(fullpath); return ret; /* ok */ } /** * Insert @p new into the list at the appropriate sorted position. **/ static void dcc_mon_insert_sorted(struct dcc_task_state **list, struct dcc_task_state *new) { int s; struct dcc_task_state *i; for (; (i = *list) != NULL; list = &i->next) { /* Should we go before *list? If the hostname comes first, or * the name is the same and the slot is lower. */ s = strcmp(i->host, new->host); if (s > 0) { /* new's host is earlier */ break; } else if (s == 0) { /* same host; compare slots */ if (new->slot < i->slot) break; } } /* OK, insert it before the current contents of *list, which may * be NULL */ *list = new; new->next = i; } /** * Read through the state directory and return information about all * processes we find there. * * This function has to handle any files in there that happen to be * corrupt -- that can easily happen if e.g. a client crashes or is * interrupted, or is even just in the middle of writing its file. **/ int dcc_mon_poll(struct dcc_task_state **p_list) { int ret; char *dirname; DIR *d; struct dirent *de; *p_list = NULL; if ((ret = dcc_get_state_dir(&dirname))) return ret; if ((d = opendir(dirname)) == NULL) { rs_log_error("failed to opendir %s: %s", dirname, strerror(errno)); ret = EXIT_IO_ERROR; return ret; } while ((de = readdir(d)) != NULL) { struct dcc_task_state *pthis; if (dcc_mon_do_file(dirname, de->d_name, &pthis) == 0 && pthis) { /* We can succeed without getting a new entry back, but it * turns out that this time we did get one. So insert it * into the right point on the list. */ dcc_mon_insert_sorted(p_list, pthis); } } closedir(d); return 0; } distcc-3.4/src/mon.h000066400000000000000000000230221404653710500143660ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * Copyright (C) 2003 by Frerich Raabe * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef _DISTCC_MON_H #define _DISTCC_MON_H #ifdef __cplusplus extern "C" { #endif /* Writing Monitors for distcc --------------------------- It is possible for third party developers to write monitoring software for distcc clusters, and you are encouranged to do so. This appendix attempts to provide you with all the information you'll need to write a distcc monitor, but just like all other software, distcc is not perfect; in case you are stuck, can't seem to get your monitor working, or just think a particular quirk in the way a monitor was to be written is worth being pointed out, don't hesitate to subscribe to the list (http://lists.samba.org/) and present your problem. Limitations on monitoring ------------------------- As of distcc 2.11, monitoring information is only available for currently running jobs originating from your machine and account. There is no direct interface available for finding out about jobs scheduled onto your machine by other users. The state information is stored as files in the $DISTCC_DIR (typically ~/.distcc/state), which are updated by client processes as they run. The goal of the design is to be adequately secure and not to reduce the performance of compilation, which is after all the whole point. If you have permission to read the state files of some other users, you can run a monitor on them by setting DISTCC_DIR before running the monitor. distcc does not maintain a history of tasks that have completed. Your monitor program must do that if you want to present that information. mon-gnome.c has a simple implementation of this. Possible Approaches ------------------- Right now, there are two general approaches which developers can follow to develop distcc monitors: 1 - Writing a program which parses the output of the distccmon-text monitor. This is the most flexible solution, since it poses very little requirements for the monitor - you are free to use whatever programming language you prefer, and the only requirement your software has is that the distccmon-text monitor exists on the user systems, and that its output is compatible with the output of the distccmon-text monitor you developed your software with. Alas, the latter also embodies a problem, since parsing a programs text output is fragile, and it's not guaranteed that the output format of the distccmon-text monitor won't change in the future. 2 - Writing a program which links against distcc. This is the cleaner solution from a software engineer's point of view, since you retrieve the status information from distcc via, more or less typesafe, data structures, and don't have to bother parsing text output. The distcc functions and data types which your monitor will probably want to use are declared in the header files exitcode.h, mon.h and state.h. Unfortunately, this requires that you use a programming language which is able to link against the relevant distcc source files (i.e. C or C++), and that the system which builds your monitor has the distcc sources installed. Also, it's currently not guaranteed that the interface established by these three header files maintains source or binary compatibility between distcc releases. Since only the second approach requires detailed knowledge about the interface to distcc's monitoring facilities, only the second approach will be documented in this chapter. For the first approach, consult your programming manuals for how to parse the stdout output of external processes. The C Interface Provided by distcc ---------------------------------- In case you decide to let your monitor link directly against distcc, you will get exposed to the interface which distcc offers to provide your monitor with status information about the cluster. The general concept behind this interface is that you should poll distcc regularly for status information, and it will return a list of jobs which are currently being processed on the network. In practice, this interface is made up of the following function: int dcc_mon_poll(struct dcc_task_state **ppl) This function, declared in the mon.h header file, allows you to poll a list of jobs which are currently being processed on the distcc cluster. It returns 0 in case the poll was successful, otherwise one of the errors declared in the exitcode.h header file. The "ppl" list is a single-linked list of dcc_task_state structs, which represent the "jobs" being worked on. The dcc_task_state struct is declared in the state.h header file. int dcc_task_state_free(struct dcc_history *) Call this method and pass it the list of dcc_task_state structs you acquired by calling dcc_mon_poll in order to free the resources allocated by the list. So generally, the algorithm you will employ is: - Acquire a list of jobs by calling dcc_mon_poll. - Process the list of jobs, displaying results to the user. - Free the resources allocated by the list of jobs by calling dcc_task_state_free. For being able to do the second of the three steps listed above, you will need to know what information the dcc_task_state struct (which represents a job) provides. For a full list of properties, refer to the state.h header file, for convenience here is a list of noteworthy properties: unsigned long cpid The process ID of the compiler process for this job (on the remote host). char file[128] The name of the input file of this job. char host[128] The name of the remote host this job is being processed on. int slot The CPU slot which is occupied by this job on the remote hosts. enum dcc_phase curr_phase This variable holds the current state of the job (i.e. preprocess, compile, send, receive etc.). Refer to the state.h header file for the complete list of values declared in the dcc_phase enumeration. Note that there's a convenience function const char *dcc_get_state_name(enum dcc_phase state) declared in the state.h header file which lets you retrieve a descriptive string representation of the given enum, suitable for display to the user. struct dcc_task_state *next A pointer to the next dcc_task_state struct in the list, or NULL if this job is the last in the list. */ /** * Read the list of running processes for this user. * * @param ppl On return, receives a pointer to the start of a list of * status elements, representing the running processes. *ppl will be * NULL if there are no processes running. * * @return 0 for success or an error from exitcode.h. * * The list is not sorted in any particular order, but it will tend to * remain stable from one call to the next. * * The caller should free the list through dcc_task_state_free(). **/ int dcc_mon_poll(struct dcc_task_state **ppl); /** * Free a list of dcc_task_state elements, including all their contents. **/ int dcc_task_state_free(struct dcc_task_state *); /* A circular buffer of the history of a particular slot. The most * recent record is in past_phases[now]; the previous one is in * past_phases[(len+now-1) % len]. All of the data is always valid - * it is initialized to idle. */ struct dcc_history { int now; int len; enum dcc_phase *past_phases; }; void dcc_history_push(struct dcc_history *history, enum dcc_phase new_state); struct dcc_history* dcc_history_new(void); #if 0 /* Disabled because we don't use dnotify at the moment. * * It turns out that being notified of every change is in fact not a * very desirable thing: the state can change many times per second * frequently when several clients are running, and waking up the * monitor each time is expensive. */ /** * Set up to notify the monitor when the compiler state changes. * * On successful return, @p dummy_fd receives the file descriptor of a * pipe. When the state changes, a single byte will be written to * that pipe. By including the pipe fd in a select() or poll() set, * the monitor will be woken when the state has changed. * * The client should do a nonblocking read from the pipe to empty it * out each time a notification is received. * * This is currently only implemented on Linux. * * @return 0 for success or an exitcode.h value. In particular, * returns EXIT_IO_ERROR if notifications are not available on this * system. **/ int dcc_mon_setup_notify (int *dummy_fd); #endif /* 0 */ #ifdef __cplusplus } #endif #endif /* _DISTCC_MON_H */ distcc-3.4/src/ncpus.c000066400000000000000000000104431404653710500147230ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Thanks to Dimitri PAPADOPOULOS-ORFANOS for researching many of the methods * in this file. */ #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" /** * Determine number of processors online. * * We will in the future use this to gauge how many concurrent tasks * should run on this machine. Obviously this is only very rough: the * correct number needs to take into account disk buffers, IO * bandwidth, other tasks, etc. **/ #if defined(__hpux__) || defined(__hpux) #include #include int dcc_ncpus(int *ncpus) { struct pst_dynamic psd; if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) != -1) { *ncpus = psd.psd_proc_cnt; return 0; } else { rs_log_error("pstat_getdynamic failed: %s", strerror(errno)); *ncpus = 1; return EXIT_DISTCC_FAILED; } } #elif defined(__VOS__) #ifdef __GNUC__ #define $shortmap #endif #include extern void s$get_module_info (char_varying *module_name, void *mip, short int *code); int dcc_ncpus(int *ncpus) { short int code; module_info mi; char_varying(66) module_name; strcpy_vstr_nstr (&module_name, ""); mi.version = MODULE_INFO_VERSION_1; s$get_module_info ((char_varying *)&module_name, (void *)&mi, &code); if (code != 0) *ncpus = 1; /* safe guess... */ else *ncpus = mi.n_user_cpus; return 0; } #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(__bsdi__) /* http://www.FreeBSD.org/cgi/man.cgi?query=sysctl&sektion=3&manpath=FreeBSD+4.6-stable http://www.openbsd.org/cgi-bin/man.cgi?query=sysctl&sektion=3&manpath=OpenBSD+Current http://www.tac.eu.org/cgi-bin/man-cgi?sysctl+3+NetBSD-current */ #include #include #include int dcc_ncpus(int *ncpus) { int mib[2]; size_t len = sizeof(*ncpus); mib[0] = CTL_HW; mib[1] = HW_NCPU; if (sysctl(mib, 2, ncpus, &len, NULL, 0) == 0) return 0; else { rs_log_error("sysctl(CTL_HW:HW_NCPU) failed: %s", strerror(errno)); *ncpus = 1; return EXIT_DISTCC_FAILED; } } #else /* every other system */ /* http://www.opengroup.org/onlinepubs/007904975/functions/sysconf.html http://docs.sun.com/?p=/doc/816-0213/6m6ne38dd&a=view http://www.tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V40G_HTML/MAN/MAN3/0629____.HTM http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650&db=man&fname=/usr/share/catman/p_man/cat3c/sysconf.z */ int dcc_ncpus(int *ncpus) { #if defined(_SC_NPROCESSORS_ONLN) /* Linux, Solaris, Tru64, UnixWare 7, and Open UNIX 8 */ *ncpus = sysconf(_SC_NPROCESSORS_ONLN); #elif defined(_SC_NPROC_ONLN) /* IRIX */ *ncpus = sysconf(_SC_NPROC_ONLN); #else #warning "Please port this function" *ncpus = -1; /* unknown */ #endif if (*ncpus == -1) { rs_log_error("sysconf(_SC_NPROCESSORS_ONLN) failed: %s", strerror(errno)); *ncpus = 1; return EXIT_DISTCC_FAILED; } else if (*ncpus == 0) { /* if there are no cpus, what are we running on? But it has * apparently been observed to happen on ARM Linux */ *ncpus = 1; } return 0; } #endif distcc-3.4/src/netutil.c000066400000000000000000000130151404653710500152550ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ARPA_NAMESER_H # include #endif #include #ifdef HAVE_RESOLV_H # include #endif #include #include "types.h" #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "srvnet.h" #include "access.h" #include "netutil.h" #include "snprintf.h" /* work out what fcntl flag to use for non-blocking */ #ifdef O_NONBLOCK # define NONBLOCK_FLAG O_NONBLOCK #elif defined(SYSV) # define NONBLOCK_FLAG O_NDELAY #else # define NONBLOCK_FLAG FNDELAY #endif #ifndef AF_UNIX # define AF_UNIX AF_LOCAL #endif #ifndef HAVE_HSTRERROR /* Missing on e.g. Solaris 2.6 */ const char *hstrerror(int err) { switch (err) { case HOST_NOT_FOUND: return "Host not found"; case TRY_AGAIN: return "Name server not contacted"; case NO_RECOVERY: return "Non-recoverable error"; case NO_ADDRESS: return "No IP address for host"; default: return "Unknown error"; } } #endif /** * Set a fd into blocking mode **/ void dcc_set_blocking(int fd) { int val; if ((val = fcntl(fd, F_GETFL, 0)) == -1) return; if (val & NONBLOCK_FLAG) { val &= ~NONBLOCK_FLAG; fcntl(fd, F_SETFL, val); } } /** * Set a fd into nonblocking mode **/ void dcc_set_nonblocking(int fd) { int val; if ((val = fcntl(fd, F_GETFL, 0)) == -1) return; if (!(val & NONBLOCK_FLAG)) { val |= NONBLOCK_FLAG; fcntl(fd, F_SETFL, val); } } /* Ask for the server not to be awakened until some data has arrived * on the socket. This works for our protocol because the client * sends a request immediately after connection without waiting for * anything from the server. */ void dcc_defer_accept(int POSSIBLY_UNUSED(listen_fd)) { #ifdef TCP_DEFER_ACCEPT int val = 1; if (!dcc_getenv_bool("DISTCC_TCP_DEFER_ACCEPT", 1)) { rs_trace("TCP_DEFER_ACCEPT disabled"); return; } if (setsockopt(listen_fd, SOL_TCP, TCP_DEFER_ACCEPT, &val, sizeof val) == -1) { rs_log_warning("failed to set TCP_DEFER_ACCEPT: %s", strerror(errno)); } else { rs_trace("TCP_DEFER_ACCEPT turned on"); } #endif } #ifdef ENABLE_RFC2553 /* TODO: Make the returned strings consistent with the other * implementation. */ int dcc_sockaddr_to_string(struct sockaddr *sa, size_t salen, char **p_buf) { int err; char host[1024]; char port[32]; if (!sa) { *p_buf = strdup("NOTSOCKET"); return 0; } else if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6) { err = getnameinfo(sa, salen, host, sizeof host, port, sizeof port, NI_NUMERICHOST | NI_NUMERICSERV); if (err) { rs_log_warning("getnameinfo failed: %s", gai_strerror(err)); *p_buf = strdup("(UNKNOWN)"); return 0; /* it's still a valid string */ } checked_asprintf(p_buf, "%s:%s", host, port); } else if (sa->sa_family == AF_UNIX) { /* NB: The word 'sun' is predefined on Solaris */ struct sockaddr_un *sa_un = (struct sockaddr_un *) sa; checked_asprintf(p_buf, "UNIX-DOMAIN %s", sa_un->sun_path); } else { checked_asprintf(p_buf, "UNKNOWN-FAMILY %d", sa->sa_family); } return 0; } #else /* ndef ENABLE_RFC2553 */ int dcc_sockaddr_to_string(struct sockaddr *sa, size_t UNUSED(salen), char **p_buf) { if (!sa) { *p_buf = strdup("NOTSOCKET"); return 0; } else if (sa->sa_family == AF_INET) { /* The double-cast here suppresses warnings from -Wcast-align. */ struct sockaddr_in *sain = (struct sockaddr_in *) (void *) sa; checked_asprintf(p_buf, "%s:%d", inet_ntoa(sain->sin_addr), ntohs(sain->sin_port)); } else if (sa->sa_family == AF_UNIX) { /* NB: The word 'sun' is predefined on Solaris */ struct sockaddr_un *sa_un = (struct sockaddr_un *) sa; checked_asprintf(p_buf, "UNIX-DOMAIN %s", sa_un->sun_path); } else { checked_asprintf(p_buf, "UNKNOWN-FAMILY %d", sa->sa_family); } return 0; } #endif /* ndef ENABLE_RFC2553 */ distcc-3.4/src/netutil.h000066400000000000000000000023701404653710500152640ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ struct sockaddr; int dcc_sockaddr_to_string(struct sockaddr *sa, size_t salen, char **p_buf); void dcc_set_nonblocking(int fd); void dcc_set_blocking(int fd); #ifndef HAVE_HSTRERROR /* Missing on e.g. Solaris 2.6 */ const char *hstrerror(int err); #endif void dcc_defer_accept(int); distcc-3.4/src/prefork.c000066400000000000000000000122011404653710500152350ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* The dead cry out with joy when their books are reprinted */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "dopt.h" #include "exec.h" #include "srvnet.h" #include "types.h" #include "daemon.h" #include "netutil.h" #include "stats.h" void dcc_manage_kids(int listen_fd); static void dcc_sigchld_handler(int sig); static void dcc_create_kids(int listen_fd); static int dcc_preforked_child(int listen_fd); /** * Main loop for the parent process with the new preforked implementation. * The parent is just responsible for keeping a pool of children and they * accept connections themselves. **/ int dcc_preforking_parent(int listen_fd) { int ret; /* use sigaction instead of signal() because we need persistent handler, not oneshot */ struct sigaction act_child; memset(&act_child, 0, sizeof act_child); act_child.sa_handler = dcc_sigchld_handler; sigaction(SIGCHLD, &act_child, NULL); if (arg_stats) { ret = dcc_stats_init(); if (ret) return ret; dcc_create_kids(listen_fd); /* Start the stats collection and web server */ return dcc_stats_server(listen_fd); } else { while (1) { dcc_create_kids(listen_fd); /* wait for any children to exit, and then start some more */ dcc_reap_kids(TRUE); } } } static void dcc_sigchld_handler(int UNUSED(sig)) { /* Do nothing. Only here to break out of select() in dcc_stats_server() * and select() in dcc_collect_child(). */ } /** * Functions in the parent can call this to clean up and maintain the pool of * children **/ void dcc_manage_kids(int listen_fd) { dcc_reap_kids(FALSE); dcc_create_kids(listen_fd); } /** * Fork children until we have dcc_max_kids of them **/ static void dcc_create_kids(int listen_fd) { pid_t kid; while (dcc_nkids < dcc_max_kids) { if ((kid = fork()) == -1) { rs_log_error("fork failed: %s", strerror(errno)); dcc_exit(EXIT_OUT_OF_MEMORY); /* probably */ } else if (kid == 0) { dcc_stats_init_kid(); dcc_exit(dcc_preforked_child(listen_fd)); } else { /* in parent */ ++dcc_nkids; rs_trace("up to %d children", dcc_nkids); } } } /** * Fork a child to repeatedly accept and handle incoming connections. * * To protect against leaks, we quit after 50 requests and let the parent * recreate us. **/ static int dcc_preforked_child(int listen_fd) { int ireq; time_t start, now; const int child_requests = 50; const time_t child_lifetime = 60 /* seconds */; start = now = time(NULL); for (ireq = 0; ireq < child_requests || now - start < child_lifetime; ireq++) { int acc_fd; struct dcc_sockaddr_storage cli_addr; socklen_t cli_len; cli_len = sizeof cli_addr; /* Cancel any previously scheduled alarm */ if (dcc_job_lifetime) alarm(0); do { acc_fd = accept(listen_fd, (struct sockaddr *) &cli_addr, &cli_len); } while (acc_fd == -1 && errno == EINTR); /* Kill this process if the compile job takes too long. * The synchronous timeout should happen first, so this alarm * should fire only if the client stops transferring network data without disconnecting. */ if (dcc_job_lifetime) alarm(dcc_job_lifetime+30); if (acc_fd == -1) { rs_log_error("accept failed: %s", strerror(errno)); dcc_exit(EXIT_CONNECT_FAILED); } dcc_stats_event(STATS_TCP_ACCEPT); dcc_service_job(acc_fd, acc_fd, (struct sockaddr *) &cli_addr, cli_len); dcc_close(acc_fd); now = time(NULL); } rs_log_info("worn out"); return 0; } distcc-3.4/src/pump.c000066400000000000000000000107721404653710500145610ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* pump.c - Transfer of bulk data (source, object code) */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SELECT_H # include #endif #include #ifdef HAVE_SYS_MMAN_H # include #endif #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /* * Receive either compressed or uncompressed bulk data. */ int dcc_r_bulk(int ofd, int ifd, unsigned f_size, enum dcc_compress compression) { if (f_size == 0) return 0; /* don't decompress nothing */ if (compression == DCC_COMPRESS_NONE) { return dcc_pump_readwrite(ofd, ifd, f_size); } else if (compression == DCC_COMPRESS_LZO1X) { return dcc_r_bulk_lzo1x(ofd, ifd, f_size); } else { rs_log_error("impossible compression %d", compression); return EXIT_PROTOCOL_ERROR; } } /** * Copy @p n bytes from @p ifd to @p ofd. * * Does not use sendfile(), so either one may be a socket. * * In the current code at least one of the files will always be a regular * (disk) file, even though it may not be mmapable. That should mean that * writes to it will always complete immediately. That in turn means that on * each pass through the main loop we ought to either completely fill our * buffer, or completely drain it, depending on which one is the disk. * * In future we may put back the ability to feed the compiler from a fifo, in * which case it may be that the writes don't complete. * * We might try selecting on both buffers and handling whichever is ready. * This would require some approximation to a circular buffer though, which * might be more complex. **/ int dcc_pump_readwrite(int ofd, int ifd, size_t n) { static char buf[262144]; /* we're not recursive */ char *p; ssize_t r_in, r_out, wanted; int ret; while (n > 0) { wanted = (n > sizeof buf) ? (sizeof buf) : n; r_in = read(ifd, buf, (size_t) wanted); if (r_in == -1 && errno == EAGAIN) { if ((ret = dcc_select_for_read(ifd, dcc_get_io_timeout())) != 0) return ret; else continue; } else if (r_in == -1 && errno == EINTR) { continue; } else if (r_in == -1) { rs_log_error("failed to read %ld bytes: %s", (long) wanted, strerror(errno)); return EXIT_IO_ERROR; } else if (r_in == 0) { rs_log_error("unexpected eof on fd%d", ifd); return EXIT_IO_ERROR; } n -= r_in; p = buf; /* We now have r_in bytes waiting to go out, starting at p. Keep * going until they're all written out. */ while (r_in > 0) { r_out = write(ofd, p, (size_t) r_in); if (r_out == -1 && errno == EAGAIN) { if ((ret = dcc_select_for_write(ofd, dcc_get_io_timeout())) != 0) { return ret; } else { continue; } } else if (r_out == -1 && errno == EINTR) { continue; } else if (r_out == -1 || r_out == 0) { rs_log_error("failed to write: %s", strerror(errno)); return EXIT_IO_ERROR; } r_in -= r_out; p += r_out; } } return 0; } distcc-3.4/src/remote.c000066400000000000000000000256421404653710500150750ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * Send a compilation request to a remote server. */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "rpc.h" #include "exitcode.h" #include "util.h" #include "clinet.h" #include "hosts.h" #include "exec.h" #include "lock.h" #include "compile.h" #include "bulk.h" #ifdef HAVE_GSSAPI #include "auth.h" /* Global security context in case confidentiality/integrity */ /* type services are needed in the future. */ extern gss_ctx_id_t distcc_ctx_handle; #endif /* * TODO: If cpp finishes early and fails then perhaps break out of * trying to connect. * * TODO: If we abort, perhaps kill the SSH child rather than closing * the socket. Closing while a lot of stuff has been written through * might make us block until the other side reads all the data. */ /** * Open a connection using either a TCP socket or SSH. Return input * and output file descriptors (which may or may not be different.) **/ static int dcc_remote_connect(struct dcc_hostdef *host, int *to_net_fd, int *from_net_fd, pid_t *ssh_pid) { int ret; if (host->mode == DCC_MODE_TCP) { *ssh_pid = 0; if ((ret = dcc_connect_by_name(host->hostname, host->port, to_net_fd)) != 0) return ret; *from_net_fd = *to_net_fd; return 0; } else if (host->mode == DCC_MODE_SSH) { if ((ret = dcc_ssh_connect(NULL, host->user, host->hostname, host->ssh_command, from_net_fd, to_net_fd, ssh_pid))) return ret; return 0; } else { rs_log_crit("impossible host mode"); return EXIT_DISTCC_FAILED; } } static int dcc_wait_for_cpp(pid_t cpp_pid, int *status, const char *input_fname) { int ret; if (cpp_pid) { dcc_note_state(DCC_PHASE_CPP, NULL, NULL, DCC_LOCAL); /* Wait for cpp to finish (if not already done), check the * result, then send the .i file */ if ((ret = dcc_collect_child("cpp", cpp_pid, status, timeout_null_fd))) return ret; /* Although cpp failed, there is no need to try running the command * locally, because we'd presumably get the same result. Therefore * critique the command and log a message and return an indication * that compilation is complete. */ if (dcc_critique_status(*status, "cpp", input_fname, dcc_hostdef_local, 0)) return 0; } return 0; } /* Send a request across to the already-open server. * * CPP_PID is the PID of the preprocessor running in the background. * We wait for it to complete before reading its output. */ static int dcc_send_header(int net_fd, char **argv, struct dcc_hostdef *host) { int ret; tcp_cork_sock(net_fd, 1); if ((ret = dcc_x_req_header(net_fd, host->protover))) return ret; if (host->cpp_where == DCC_CPP_ON_SERVER) { if ((ret = dcc_x_cwd(net_fd))) return ret; } if ((ret = dcc_x_argv(net_fd, "ARGC", "ARGV", argv))) return ret; return 0; } /** * Pass a compilation across the network. * * When this function is called, the preprocessor has already been * started in the background. It may have already completed, or it * may still be running. The goal is that preprocessing will overlap * with setting up the network connection, which may take some time * but little CPU. * * If this function fails, compilation will be retried on the local * machine. * * @param argv Compiler command to run. * * @param cpp_fname Filename of preprocessed source. May not be complete yet, * depending on @p cpp_pid. * * @param files If we are doing preprocessing on the server, the names of * all the files needed; otherwise, NULL. * * @param output_fname File that the object code should be delivered to. * * @param cpp_pid If nonzero, the pid of the preprocessor. Must be * allowed to complete before we send the input file. * * @param local_cpu_lock_fd If != -1, file descriptor for the lock file. * Should be != -1 iff (host->cpp_where != DCC_CPP_ON_SERVER). * If != -1, the lock must be held on entry to this function, * and THIS FUNCTION WILL RELEASE THE LOCK. * * @param host Definition of host to send this job to. * * @param status on return contains the wait-status of the remote * compiler. * * Returns 0 on success, otherwise error. Returning nonzero does not * necessarily imply the remote compiler itself succeeded, only that * there were no communications problems. * * TODO: consider refactoring this (perhaps as two separate subroutines?) * to avoid the need for releasing the lock as a side effect of this call. */ int dcc_compile_remote(char **argv, char *input_fname, char *cpp_fname, char **files, char *output_fname, char *deps_fname, char *server_stderr_fname, pid_t cpp_pid, int local_cpu_lock_fd, struct dcc_hostdef *host, int *status) { int to_net_fd = -1, from_net_fd = -1; int ret; pid_t ssh_pid = 0; int ssh_status; off_t doti_size; struct timeval before, after; unsigned int n_files; if (gettimeofday(&before, NULL)) rs_log_warning("gettimeofday failed"); dcc_note_execution(host, argv); dcc_note_state(DCC_PHASE_CONNECT, input_fname, host->hostname, DCC_REMOTE); /* For ssh support, we need to allow for separate fds writing to and * reading from the network, because our connection to the ssh client may * be over pipes, which are one-way connections. */ *status = 0; if ((ret = dcc_remote_connect(host, &to_net_fd, &from_net_fd, &ssh_pid))) goto out; #ifdef HAVE_GSSAPI /* Perform requested security. */ if(host->authenticate) { rs_log_info("Performing authentication."); if ((ret = dcc_gssapi_perform_requested_security(host, to_net_fd, from_net_fd)) != 0) { rs_log_crit("Failed to perform authentication."); goto out; } /* Context deleted here as we no longer need it. However, we have it available */ /* in case we want to use confidentiality/integrity type services in the future. */ dcc_gssapi_delete_ctx(&distcc_ctx_handle); } else { rs_log_info("No authentication requested."); } #endif dcc_note_state(DCC_PHASE_SEND, NULL, NULL, DCC_REMOTE); if (host->cpp_where == DCC_CPP_ON_SERVER) { if ((ret = dcc_send_header(to_net_fd, argv, host))) { goto out; } n_files = dcc_argv_len(files); if ((ret = dcc_x_many_files(to_net_fd, n_files, files))) { goto out; } } else { /* This waits for cpp and puts its status in *status. If cpp failed, * then the connection will have been dropped and we need not bother * trying to get any response from the server. */ if ((ret = dcc_send_header(to_net_fd, argv, host))) goto out; if ((ret = dcc_wait_for_cpp(cpp_pid, status, input_fname))) goto out; /* We are done with local preprocessing. Unlock to allow someone * else to start preprocessing. */ if (local_cpu_lock_fd != -1) { dcc_unlock(local_cpu_lock_fd); local_cpu_lock_fd = -1; } if (*status != 0) goto out; if ((ret = dcc_x_file(to_net_fd, cpp_fname, "DOTI", host->compr, &doti_size))) goto out; } rs_trace("client finished sending request to server"); tcp_cork_sock(to_net_fd, 0); /* but it might not have been read in by the server yet; there's * 100kB or more of buffers in the two kernels. */ /* OK, now all of the source has at least made it into the * client's TCP transmission queue, sometime soon the server will * start compiling it. */ dcc_note_state(DCC_PHASE_COMPILE, NULL, host->hostname, DCC_REMOTE); /* If cpp failed, just abandon the connection, without trying to * receive results. */ if (ret == 0 && *status == 0) { ret = dcc_retrieve_results(from_net_fd, status, output_fname, deps_fname, server_stderr_fname, host); } if (gettimeofday(&after, NULL)) { rs_log_warning("gettimeofday failed"); } else if (host->cpp_where == DCC_CPP_ON_CLIENT) { double secs, rate; dcc_calc_rate(doti_size, &before, &after, &secs, &rate); rs_log(RS_LOG_INFO|RS_LOG_NONAME, "%lu bytes from %s compiled on %s in %.4fs, rate %.0fkB/s", (unsigned long) doti_size, input_fname, host->hostname, secs, rate); } out: if (local_cpu_lock_fd != -1) { dcc_unlock(local_cpu_lock_fd); local_cpu_lock_fd = -1; /* Not really needed; just for consistency. */ } /* Close socket so that the server can terminate, rather than * making it wait until we've finished our work. */ if (to_net_fd != from_net_fd) { if (to_net_fd != -1) dcc_close(to_net_fd); } if (from_net_fd != -1) dcc_close(from_net_fd); /* Collect the SSH child. Strictly this is unnecessary; it might slow the * client down a little when things could otherwise be proceeding in the * background. But it helps make sure that we don't assume we succeeded * when something possibly went wrong, and it allows us to account for the * cost of the ssh child. */ if (ssh_pid) { dcc_collect_child("ssh", ssh_pid, &ssh_status, timeout_null_fd); /* ignore failure */ } return ret; } distcc-3.4/src/renderer.c000066400000000000000000000170261404653710500154050ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * GtkCellRenderer subclass for drawing strip charts. * * Based on the example of gtkcellrendererpixbuf and hacked up. * * Each table cell corresponds to one execution slot for the client. * Each host can have several slots. At most one task can run on each * slot at any time. Therefore we can draw the history of tasks in * this slot as a set of rectangles that do not overlap in time. * * The renderer looks directly at the list of running tasks to find * the ones in its slot. It accesses the list through a global * variable. This is pretty gross in terms of the Gtk object system, * but it avoids worrying about memory management and filtering the * tasks to put them on the right view of the model. **/ #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "rpc.h" #include "trace.h" #include "exitcode.h" #include "mon.h" #include "netutil.h" #include "renderer.h" struct _DccCellRendererChart { GtkCellRenderer parent; /** History of tasks for this slot. Exposed through the "history" * property. */ struct dcc_history *history; }; struct _DccCellRendererChartClass { GtkCellRendererClass parent_class; }; enum { PROP_ZERO, PROP_HISTORY }; /** * Create a new cell renderer to display a chart of compilation jobs. **/ GtkCellRenderer * dcc_cell_renderer_chart_new (void) { return g_object_new (DCC_TYPE_CELL_RENDERER_CHART, NULL); } static void dcc_cell_renderer_chart_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { DccCellRendererChart *renderer; renderer = DCC_CELL_RENDERER_CHART (object); switch (prop_id) { case PROP_HISTORY: renderer->history = g_value_get_pointer (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void dcc_cell_renderer_chart_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { DccCellRendererChart *renderer; renderer = DCC_CELL_RENDERER_CHART (object); switch (prop_id) { case PROP_HISTORY: g_value_set_pointer (value, renderer->history); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } /** * Actually draw one cell (one strip chart) into a widget. * * I tried checking against the expose area to see whether we needed * to repaint the whole thing, but it does not seem to help very much. * GTK+ always tells us the whole cell is exposed when it updates the * table, even if part of the cell is actually obscured by some other * window. The refresh events are the performance-critical ones for * us; the others don't matter nearly so much. **/ static void dcc_cell_renderer_chart_render (GtkCellRenderer *cell, cairo_t *cr, GtkWidget *UNUSED(widget), const GdkRectangle *UNUSED(background_area), const GdkRectangle *cell_area, GtkCellRendererState UNUSED(flags)) { const struct dcc_history *history; enum dcc_phase state; int x1, y1; int bar_height, bar_width; int xpad, ypad; int i; const enum dcc_phase *phases; DccCellRendererChart *cellchart = (DccCellRendererChart *) cell; history = cellchart->history; g_return_if_fail (history); /* Perhaps we should just ignore this.. */ gtk_cell_renderer_get_padding(cell, &xpad, &ypad); x1 = cell_area->x + xpad; y1 = cell_area->y + ypad; bar_height = cell_area->height - (2 * ypad); /* bar width is chosen such that the history roughly fills the cell (but it must be at least 1). We use the full history, not just the amount we currently have. Round up. */ bar_width = (cell_area->width + history->len - 1) / history->len; if (bar_width < 1) bar_width = 1; phases = history->past_phases; for (i = 0; i < history->len; i++) { state = phases[(history->len + history->now - i) % history->len]; g_return_if_fail (state <= DCC_PHASE_DONE); if (state != DCC_PHASE_DONE) { gdk_cairo_set_source_rgba (cr, &task_color[state]); cairo_rectangle (cr, x1, y1, bar_width, bar_height); cairo_fill (cr); } x1 += bar_width; } } static void dcc_cell_renderer_chart_class_init (DccCellRendererChartClass *class, gpointer UNUSED(klass)) { GParamSpec *spec; GObjectClass *object_class = G_OBJECT_CLASS (class); GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class); object_class->get_property = dcc_cell_renderer_chart_get_property; object_class->set_property = dcc_cell_renderer_chart_set_property; cell_class->render = dcc_cell_renderer_chart_render; spec = g_param_spec_pointer ("history", "Slot history", "", G_PARAM_READABLE | G_PARAM_WRITABLE); g_object_class_install_property (object_class, PROP_HISTORY, spec); } /* Instance initialization */ static void dcc_cell_renderer_chart_init (DccCellRendererChart *cell, gpointer UNUSED(klass)) { cell->history = NULL; } /** * Return metaobject info to GObject system. Or something. **/ GType dcc_cell_renderer_chart_get_type (void) { static GType cell_chart_type = 0; if (!cell_chart_type) { static const GTypeInfo cell_chart_info = { sizeof (DccCellRendererChartClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) dcc_cell_renderer_chart_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (DccCellRendererChart), 0, /* n_preallocs */ (GInstanceInitFunc) dcc_cell_renderer_chart_init, NULL /* value_table */ }; cell_chart_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, "DccCellRendererChart", &cell_chart_info, 0); } return cell_chart_type; } distcc-3.4/src/renderer.h000066400000000000000000000041231404653710500154040ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Implementation of a GtkCellRenderer subclass that draws a little * chart of programs that have run in that slot. **/ #define DCC_TYPE_CELL_RENDERER_CHART (dcc_cell_renderer_chart_get_type ()) #define DCC_CELL_RENDERER_CHART(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DCC_TYPE_CELL_RENDERER_CHART, DccCellRendererChart)) #define DCC_CELL_RENDERER_CHART_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DCC_TYPE_CELL_RENDERER_CHART, DccCellRendererChartClass)) #define DCC_IS_CELL_RENDERER_CHART(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DCC_TYPE_CELL_RENDERER_CHART)) #define DCC_IS_CELL_RENDERER_CHART_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DCC_TYPE_CELL_RENDERER_CHART)) #define DCC_CELL_RENDERER_CHART_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DCC_TYPE_CELL_RENDERER_CHART, DccCellRendererChartClass)) typedef struct _DccCellRendererChart DccCellRendererChart; typedef struct _DccCellRendererChartClass DccCellRendererChartClass; GType dcc_cell_renderer_chart_get_type (void); GtkCellRenderer *dcc_cell_renderer_chart_new (void); extern const guint dcc_max_history_queue; extern GdkRGBA task_color[]; distcc-3.4/src/rpc.c000066400000000000000000000206741404653710500143660ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* 15 Every one that is found shall be thrust * through; and every one that is joined unto * them shall fall by the sword. * -- Isaiah 13 */ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "rpc.h" #include "snprintf.h" /** * @file * * Very simple RPC-like layer. Requests and responses are build of * little packets each containing a 4-byte ascii token, an 8-byte hex * value or length, and optionally data corresponding to the length. * * 'x' means transmit, and 'r' means receive. * * This builds on top of io.c and is called by the various routines * that handle communication. **/ /** * Transmit token name (4 characters) and value (32-bit int, as 8 hex * characters). **/ int dcc_x_token_int(int ofd, const char *token, unsigned param) { char buf[13]; int shift; char *p; const char *hex = "0123456789abcdef"; if (strlen(token) != 4) { rs_log_crit("token \"%s\" seems wrong", token); return EXIT_PROTOCOL_ERROR; } memcpy(buf, token, 4); /* Quick and dirty int->hex. The only standard way is to call snprintf * (?), which is undesirably slow for such a frequently-called * function. */ for (shift=28, p = &buf[4]; shift >= 0; shift -= 4, p++) { *p = hex[(param >> shift) & 0xf]; } buf[12] = '\0'; rs_trace("send %s", buf); return dcc_writex(ofd, buf, 12); } /** * Send start of a result: DONE **/ int dcc_x_result_header(int ofd, enum dcc_protover protover) { return dcc_x_token_int(ofd, "DONE", protover); } int dcc_x_cc_status(int ofd, int status) { return dcc_x_token_int(ofd, "STAT", (unsigned) status); } int dcc_r_token(int ifd, char *buf) { return dcc_readx(ifd, buf, 4); } /** * We got a mismatch on a token, which indicates either a bug in distcc, or * that somebody (inetd?) is interfering with our network stream, or perhaps * some other network problem. Whatever's happened, a bit more debugging * information would be handy. **/ int dcc_explain_mismatch(const char *buf, size_t buflen, int ifd) { ssize_t ret; char extrabuf[200]; char *p; size_t l; memcpy(extrabuf, buf, buflen); /* Read a bit more context, and find the printable prefix. */ ret = read(ifd, extrabuf + buflen, sizeof extrabuf - 1 - buflen); if (ret == -1) { ret = 0; /* pah, use what we've got */ } l = buflen + ret; extrabuf[l] = '\0'; for (p = extrabuf; *p; p++) if (!(isprint((uint8_t)*p) || *p == ' ' || *p == '\t')) { *p = '\0'; break; } rs_log_error("error context: \"%s\"", extrabuf); return 0; /* i just feel really sad... */ } /** * Read a token and value. The receiver always knows what token name * is expected next -- indeed the names are really only there as a * sanity check and to aid debugging. * * @param ifd fd to read from * @param expected 4-char token that is expected to come in next * @param val receives the parameter value **/ int dcc_r_token_int(int ifd, const char *expected, unsigned *val) { char buf[13], *bum; int ret; if (strlen(expected) != 4) { rs_log_error("expected token \"%s\" seems wrong", expected); return EXIT_PROTOCOL_ERROR; } if ((ret = dcc_readx(ifd, buf, 12))) { rs_log_error("read failed while waiting for token \"%s\"", expected); return ret; } if (memcmp(buf, expected, 4)) { rs_log_error("protocol derailment: expected token \"%s\"", expected); dcc_explain_mismatch(buf, 12, ifd); return EXIT_PROTOCOL_ERROR; } buf[12] = '\0'; /* terminate */ *val = strtoul(&buf[4], &bum, 16); if (bum != &buf[12]) { rs_log_error("failed to parse parameter of token \"%s\"", expected); dcc_explain_mismatch(buf, 12, ifd); return EXIT_PROTOCOL_ERROR; } rs_trace("got %s", buf); return 0; } /** * Read a token and value. Fill in both token and value; * unlike dcc_r_token_int this is for the case when we do not know what * the next token will be. * * @param ifd fd to read from * @param token receives the 4-char token * @param val receives the parameter value **/ int dcc_r_sometoken_int(int ifd, char *token, unsigned *val) { char buf[13], *bum; int ret; if ((ret = dcc_readx(ifd, buf, 12))) { rs_log_error("read failed while waiting for some token"); return ret; } memcpy(token, buf, 4); token[4] = '\0'; buf[12] = '\0'; /* terminate */ *val = strtoul(&buf[4], &bum, 16); if (bum != &buf[12]) { rs_log_error("failed to parse parameter of token \"%s\"", token); dcc_explain_mismatch(buf, 12, ifd); return EXIT_PROTOCOL_ERROR; } rs_trace("got %s", buf); return 0; } /** * Read a byte string of length @p l into a newly allocated buffer, returned in @p buf. **/ int dcc_r_str_alloc(int fd, unsigned l, char **buf) { char *s; #if 0 /* never true */ if (l < 0) { rs_log_crit("oops, l < 0"); return EXIT_PROTOCOL_ERROR; } #endif /* rs_trace("read %d byte string", l); */ s = *buf = malloc((size_t) l + 1); if (!s) rs_log_error("malloc failed"); if (dcc_readx(fd, s, (size_t) l)) return EXIT_OUT_OF_MEMORY; s[l] = 0; return 0; } /** * Write a token, and then the string @p buf. * * The length of buf is determined by its nul delimiter, but the \0 is not sent. **/ int dcc_x_token_string(int fd, const char *token, const char *buf) { int ret; size_t len; len = strlen(buf); if ((ret = dcc_x_token_int(fd, token, (unsigned) len))) return ret; if ((ret = dcc_writex(fd, buf, len))) return ret; rs_trace("send string '%s'", buf); return 0; } int dcc_r_token_string(int ifd, const char *expect_token, char **p_str) { unsigned a_len; int ret; if ((ret = dcc_r_token_int(ifd, expect_token, &a_len))) return ret; if ((ret = dcc_r_str_alloc(ifd, a_len, p_str))) return ret; rs_trace("got '%s'", *p_str); return 0; } /** * Read an argv-type vector from the network. **/ int dcc_r_argv(int ifd, const char *argc_token, const char *argv_token, /*@out@*/ char ***argv) { unsigned i; unsigned argc; char **a; int ret; *argv = NULL; if (dcc_r_token_int(ifd, argc_token, &argc)) return EXIT_PROTOCOL_ERROR; rs_trace("reading %d arguments from job submission", argc); /* Have to make the argv one element too long, so that it can be * terminated by a null element. */ *argv = a = (char **) calloc((size_t) argc+1, sizeof a[0]); if (a == NULL) { rs_log_error("alloc failed"); return EXIT_OUT_OF_MEMORY; } a[argc] = NULL; for (i = 0; i < argc; i++) { if ((ret = dcc_r_token_string(ifd, argv_token, &a[i]))) return ret; rs_trace("argv[%d] = \"%s\"", i, a[i]); } dcc_trace_argv("got arguments", a); return 0; } distcc-3.4/src/rpc.h000066400000000000000000000037151404653710500143700ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* His hand is stretched out, and who shall turn it back? * -- Isaiah 14:27 */ #ifndef __DISTCC_RPC_H__ #define __DISTCC_RPC_H__ int dcc_x_result_header(int ofd, enum dcc_protover); int dcc_r_result_header(int ofd, enum dcc_protover); int dcc_x_cc_status(int, int); int dcc_r_cc_status(int, int *); int dcc_x_token_int(int ofd, const char *token, unsigned param); int dcc_r_token_int(int ifd, const char *expected, unsigned int *val); int dcc_x_token_string(int fd, const char *token, const char *buf); int dcc_r_token_string(int ifd, const char *expect_token, char **p_str); int dcc_r_sometoken_int(int ifd, char *token, unsigned *val); int dcc_explain_mismatch(const char *buf, size_t buflen, int ifd); /* srvrpc.c */ int dcc_r_request_header(int ifd, enum dcc_protover *); int dcc_r_argv(int ifd, const char *argc_token, const char *argv_token, /*@out@*/ char ***argv); #endifdistcc-3.4/src/rslave.c000066400000000000000000000120561404653710500150710ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* don't blame me, I was in a hurry */ #include #include #include #include #include #include #include #include #include #include #include #include "rslave.h" /*-------------------------------------------------------------------------- Class to provide asynchronous DNS lookup. To use, first call rslave_init() very early in your program to fork the dns slave processes. Then call rslave_write() any time you need a DNS name resolved and rslave_read() to retrieve the next result. Order of lookup requests is not preserved. Call rslave_getfd() and select on that fd for readability if you want to only call rslave_read() once it won't block. The slaves will shut down when their input file descriptor is closed, which normally happens when your program exits. --------------------------------------------------------------------------*/ int rslave_getfd_fromSlaves(struct rslave_s *rslave) { return rslave->pipeFromSlaves[0]; } int rslave_getfd_toSlaves(struct rslave_s *rslave) { return rslave->pipeToSlaves[1]; } void rslave_request_init(struct rslave_request_s *buf, const char *hostname, int id) { memset(buf, 0, sizeof(*buf)); strncpy(buf->hname, hostname, rslave_HOSTLEN); buf->id = id; } int rslave_writeRequest(struct rslave_s *rslave, const struct rslave_request_s *req) { if (write(rslave->pipeToSlaves[1], req, sizeof(*req)) != sizeof(*req)) return -1; return 0; } int rslave_gethostbyname(struct rslave_s *rslave, const char *hostname, int id) { struct rslave_request_s buf; rslave_request_init(&buf, hostname, id); return rslave_writeRequest(rslave, &buf); } int rslave_readRequest(struct rslave_s *rslave, struct rslave_request_s *req) { if (read(rslave->pipeToSlaves[0], req, sizeof(*req)) != sizeof(*req)) return -1; return 0; } int rslave_writeResult(struct rslave_s *rslave, struct rslave_result_s *result) { if (write(rslave->pipeFromSlaves[1], result, sizeof(*result)) != sizeof(*result)) return -1; return 0; } int rslave_readResult(struct rslave_s *rslave, struct rslave_result_s *result) { if (read(rslave->pipeFromSlaves[0], result, sizeof(*result)) != sizeof(*result)) return -1; return 0; } void be_a_dnsslave(struct rslave_s *rslave); void be_a_dnsslave(struct rslave_s *rslave) { struct rslave_request_s req; while (rslave_readRequest(rslave, &req) == 0) { struct rslave_result_s result; struct hostent *h; /* fprintf(stderr, "Calling gethostbyname on %s\n", req.hname); */ h = gethostbyname(req.hname); memset(&result, 0, sizeof(result)); result.id = req.id; result.err = h_errno; if (h && (h->h_length == sizeof(result.addr))) { memcpy(result.addr, h->h_addr_list[0], (unsigned) h->h_length); result.err = 0; } if (rslave_writeResult(rslave, &result)) break; } exit(0); } /*-------------------------------------------------------------------------- Initialize an rslave_s and fork slave processes. Returns 0 on success, -1 on error. --------------------------------------------------------------------------*/ int rslave_init(struct rslave_s *rslave) { int err; int i; int nslaves = rslave_NSLAVES; memset(rslave, 0, sizeof(*rslave)); err = pipe(rslave->pipeToSlaves); if (err == -1) return -1; err = pipe(rslave->pipeFromSlaves); if (err == -1) return -1; for (i=0; ipipeToSlaves[1]); close(rslave->pipeFromSlaves[0]); be_a_dnsslave(rslave); break; default: /* parent */ rslave->pids[i] = childpid; /* Save pid so we can kill it later */ break; } } close(rslave->pipeToSlaves[0]); close(rslave->pipeFromSlaves[1]); rslave->nslaves = nslaves; return 0; } /* TODO: add rslave_shutdown() that kills all the slaves by iterating through rslave->pids[] */ distcc-3.4/src/rslave.h000066400000000000000000000045131404653710500150750ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef rslave_H #define rslave_H /* don't blame me, I was in a hurry */ #include /* for pid_t */ /* maximum length of hostname */ #define rslave_HOSTLEN 200 /* Number of DNS slave processes. Emperically I've found that I need * for up to about 50 servers, you need 1 for main lookup plus two spares for retries; * for up to about 150 servers, you need 2 for main lookup plus a few spares for retries. * Six seems like it should be enough for most sites. */ #define rslave_NSLAVES 6 struct rslave_s { int nslaves; int pipeToSlaves[2]; int pipeFromSlaves[2]; pid_t pids[rslave_NSLAVES]; }; struct rslave_request_s { int id; char hname[rslave_HOSTLEN+1]; }; typedef struct rslave_request_s rslave_request_t; struct rslave_result_s { int id; int err; unsigned char addr[4]; }; typedef struct rslave_result_s rslave_result_t; int rslave_init(struct rslave_s *rslave); int rslave_gethostbyname(struct rslave_s *rslave, const char *hostname, int id); void rslave_request_init(struct rslave_request_s *buf, const char *hostname, int id); int rslave_readRequest(struct rslave_s *rslave, struct rslave_request_s *req); int rslave_writeRequest(struct rslave_s *rslave, const struct rslave_request_s *req); int rslave_writeResult(struct rslave_s *rslave, struct rslave_result_s *result); int rslave_readResult(struct rslave_s *rslave, struct rslave_result_s *result); int rslave_getfd_fromSlaves(struct rslave_s *rslave); int rslave_getfd_toSlaves(struct rslave_s *rslave); #endif distcc-3.4/src/safeguard.c000066400000000000000000000045611404653710500155400ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** * @file * @brief Protect against unbounded recursion. * * It would be fairly easy for somebody to get confused in masquerade mode and * try to get distcc to invoke itself in a loop. We can't always work out the * right thing to do but we can at least flag an error. * * This environment variable is set to guard against distcc accidentally * recursively invoking itself, thinking it's the real compiler. **/ static const char dcc_safeguard_name[] = "_DISTCC_SAFEGUARD"; static char dcc_safeguard_set[] = "_DISTCC_SAFEGUARD=1"; static int dcc_safeguard_level; int dcc_recursion_safeguard(void) { char *env = getenv(dcc_safeguard_name); if (env) { rs_trace("safeguard: %s", env); if (!(dcc_safeguard_level = atoi(env))) dcc_safeguard_level = 1; } else dcc_safeguard_level = 0; rs_trace("safeguard level=%d", dcc_safeguard_level); return dcc_safeguard_level; } int dcc_increment_safeguard(void) { if (dcc_safeguard_level > 0) dcc_safeguard_set[sizeof dcc_safeguard_set-2] = dcc_safeguard_level+'1'; rs_trace("setting safeguard: %s", dcc_safeguard_set); if ((putenv(strdup(dcc_safeguard_set)) == -1)) { rs_log_error("putenv failed"); /* and continue */ } return 0; } distcc-3.4/src/sendfile.c000066400000000000000000000201131404653710500153570ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2008 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "I've always wanted to use sendfile(), but * never had a reason until now" * -- mbp */ #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SENDFILE_H # include #endif /* !HAVE_SYS_SENDFILE_H */ #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /* * Could also use sendfilev() on Solaris >= 8: * * http://docs.sun.com/db/doc/816-0217/6m6nhtaps?a=view */ #ifdef HAVE_SENDFILE /* If you don't have it, just use dcc_pump_readwrite */ /** * sys_sendfile maps all the different implementations of sendfile() into * something like the Linux interface. * * Our sockets are never non-blocking, so that seems to me to say that * the kernel will never return EAGAIN -- we will always either send * the whole thing or get an error. Is that really true? * * How nice to have the function parameters reversed between platforms * in a way that will not give a compiler warning. * * @param offset offset in input to start writing; updated on return * to reflect the number of bytes sent. * * sys_sendfile returns the number of bytes sent, if transmission succeeded. * If there was an error, it returns -1 with errno set. It should never * return 0. **/ #if defined(__FreeBSD__) static ssize_t sys_sendfile(int ofd, int ifd, off_t *offset, size_t size) { off_t sent_bytes; int ret; /* According to the manual, this can never partially complete on a * socket open for blocking IO. */ ret = sendfile(ifd, ofd, *offset, size, 0, &sent_bytes, 0); if (ret == -1) { /* http://cvs.apache.org/viewcvs.cgi/apr/network_io/unix/sendrecv.c?rev=1.95&content-type=text/vnd.viewcvs-markup */ if (errno == EAGAIN) { if (sent_bytes == 0) { /* Didn't send anything. Return error with errno == EAGAIN. */ return -1; } else { /* We sent some bytes, but they we would block. Treat this as * success for now. */ *offset += sent_bytes; return sent_bytes; } } else { /* some other error */ return -1; } } else if (ret == 0) { *offset += size; return size; } else { rs_log_error("don't know how to handle return %d from BSD sendfile", ret); return -1; } } #elif defined(linux) || defined(__GNU__) static ssize_t sys_sendfile(int ofd, int ifd, off_t *offset, size_t size) { return sendfile(ofd, ifd, offset, size); } #elif defined(__hpux) || defined(__hpux__) /* HP cc in ANSI mode defines __hpux; gcc defines __hpux__ */ static ssize_t sys_sendfile(int ofd, int ifd, off_t *offset, size_t size) { ssize_t ret; ret = sendfile(ofd, ifd, *offset, size, NULL, 0); if (ret == -1) { return -1; } else if (ret > 0) { *offset += ret; return ret; } else { rs_log_error("don't know how to handle return %ld from HP-UX sendfile", (long) ret); return -1; } } #elif defined(__MACH__) && defined(__APPLE__) static ssize_t sys_sendfile(int ofd, int ifd, off_t *offset, size_t size) { off_t sent_bytes = size; int ret; ret = sendfile(ofd, ifd, *offset, &sent_bytes, NULL, 0); if (ret == -1) { if (errno == EAGAIN) { if (sent_bytes == 0) { /* Didn't send anything. Return error with errno == EAGAIN. */ return -1; } else { /* We sent some bytes, but they we would block. Treat this as * success for now. */ *offset += sent_bytes; return sent_bytes; } } else { /* some other error */ return -1; } } else if (ret == 0) { *offset += size; return size; } else { rs_log_error("don't know how to handle return %d from OS X sendfile", ret); return -1; } } #else /* Please write a sendfile implementation for your system! */ static ssize_t sys_sendfile(int UNUSED(ofd), int UNUSED(ifd), off_t *UNUSED(offset), size_t UNUSED(size)) { rs_log_warning("no sendfile implementation on this platform"); errno = ENOSYS; return -1; } #endif /* !(__FreeBSD__) && !def(linux) && ... */ /* * Transmit the body of a file using sendfile(). * * Linux at the moment requires the input be page-based -- ie a disk file, and * only on particular filesystems. If the sendfile() call fails in a way that * makes us think that regular IO might work, then we try that instead. For * example, the /tmp filesystem may not support sendfile(). */ int dcc_pump_sendfile(int ofd, int ifd, size_t size) { ssize_t sent; off_t offset = 0; int ret; while (size) { /* Handle possibility of partial transmission, e.g. if * sendfile() is interrupted by a signal. size is decremented * as we go. */ sent = sys_sendfile(ofd, ifd, &offset, size); if (sent == -1) { if (errno == EAGAIN) { /* Sleep until we're able to write out more data. */ if ((ret = dcc_select_for_write(ofd, dcc_get_io_timeout())) != 0) { return ret; } rs_trace("select() returned, continuing to write"); } else if (errno == EINTR) { rs_trace("sendfile() interrupted, continuing"); } else if (offset == 0) { /* The offset==0 tests is because we may be part way through * the file. We can't just naively go back to read/write * because sendfile() does not update the file pointer: we * would need to lseek() first. That case is not handled at * the moment because it's unlikely that sendfile() would * suddenly be unsupported while we're using it. A failure * halfway through probably indicates a genuine error. */ rs_log_info("decided to use read/write rather than sendfile"); return dcc_pump_readwrite(ofd, ifd, size); } else { rs_log_error("sendfile failed: %s", strerror(errno)); return EXIT_IO_ERROR; } } else if (sent == 0) { rs_log_error("sendfile returned 0? can't cope"); return EXIT_IO_ERROR; } else if (sent != (ssize_t) size) { /* offset is automatically updated by sendfile. */ size -= sent; rs_log_notice("sendfile: partial transmission of %ld bytes; retrying %ld @%ld", (long) sent, (long) size, (long) offset); } else { /* normal case, everything was sent. */ break; } } return 0; } #endif /* def HAVE_SENDFILE */ distcc-3.4/src/serve.c000066400000000000000000000745521404653710500147320ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* He who waits until circumstances completely favour * * his undertaking will never accomplish anything. * * -- Martin Luther */ /** * @file * * Actually serve remote requests. Called from daemon.c. * * @todo Make sure wait statuses are packed in a consistent format * (exit<<8 | signal). Is there any platform that doesn't do this? * * @todo The server should catch signals, and terminate the compiler process * group before handling them. * * @todo It might be nice to detect that the client has dropped the * connection, and then kill the compiler immediately. However, we probably * won't notice that until we try to do IO. SIGPIPE won't help because it's * not triggered until we try to do IO. I don't think it matters a lot, * though, because the client's not very likely to do that. The main case is * probably somebody getting bored and interrupting compilation. * * What might help is to select() on the network socket while we're waiting * for the child to complete, allowing SIGCHLD to interrupt the select() when * the child completes. However I'm not sure if it's really worth the trouble * of doing that just to handle a fairly marginal case. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "stats.h" #include "rpc.h" #include "exitcode.h" #include "snprintf.h" #include "dopt.h" #include "bulk.h" #include "exec.h" #include "srvnet.h" #include "hosts.h" #include "daemon.h" #include "stringmap.h" #include "dotd.h" #include "fix_debug_info.h" #ifdef HAVE_GSSAPI #include "auth.h" /* Global security context in case confidentiality/integrity */ /* type services are needed in the future. */ extern gss_ctx_id_t distccd_ctx_handle; /* Simple boolean, with a non-zero value indicating that the */ /* --auth option was specified. */ int dcc_auth_enabled = 0; #endif /** * We copy all serious distccd messages to this file, as well as sending the * compiler errors there, so they're visible to the client. **/ static int dcc_compile_log_fd = -1; static int dcc_run_job(int in_fd, int out_fd); /** * Copy all server messages to the error file, so that they can be * echoed back to the client if necessary. **/ static int dcc_add_log_to_file(const char *err_fname) { if (dcc_compile_log_fd != -1) { rs_log_crit("compile log already open?"); return 0; /* continue? */ } dcc_compile_log_fd = open(err_fname, O_WRONLY|O_CREAT|O_TRUNC, 0600); if (dcc_compile_log_fd == -1) { rs_log_error("failed to open %s: %s", err_fname, strerror(errno)); return EXIT_IO_ERROR; } /* Only send fairly serious errors back */ rs_add_logger(rs_logger_file, RS_LOG_WARNING, NULL, dcc_compile_log_fd); return 0; } static int dcc_remove_log_to_file(void) { if (dcc_compile_log_fd == -1) { rs_log_warning("compile log not open?"); return 0; /* continue? */ } /* must exactly match call in dcc_add_log_to_file */ rs_remove_logger(rs_logger_file, RS_LOG_WARNING, NULL, dcc_compile_log_fd); dcc_close(dcc_compile_log_fd); dcc_compile_log_fd = -1; return 0; } /* Read and execute a job to/from socket. This is the common entry point no * matter what mode the daemon is running in: preforked, nonforked, or * ssh/inetd. */ int dcc_service_job(int in_fd, int out_fd, struct sockaddr *cli_addr, int cli_len) { int ret; dcc_job_summary_clear(); /* Log client name and check access if appropriate. For ssh connections * the client comes from a unix-domain socket and that's always * allowed. */ if ((ret = dcc_check_client(cli_addr, cli_len, opt_allowed)) != 0) goto out; #ifdef HAVE_GSSAPI /* If requested perform authentication. */ if (dcc_auth_enabled) { rs_log_info("Performing authentication."); if ((ret = dcc_gssapi_check_client(in_fd, out_fd)) != 0) { goto out; } } else { rs_log_info("No authentication requested."); } /* Context deleted here as we no longer need it. However, we have it available */ /* in case we want to use confidentiality/integrity type services in the future. */ if (dcc_auth_enabled) { dcc_gssapi_delete_ctx(&distccd_ctx_handle); } #endif ret = dcc_run_job(in_fd, out_fd); dcc_job_summary(); out: return ret; } static int dcc_input_tmpnam(char * orig_input, char **tmpnam_ret) { const char *input_exten; rs_trace("input file %s", orig_input); input_exten = dcc_find_extension(orig_input); if (input_exten) input_exten = dcc_preproc_exten(input_exten); if (!input_exten) /* previous line might return NULL */ input_exten = ".tmp"; return dcc_make_tmpnam("distccd", input_exten, tmpnam_ret); } /** * Check argv0 against a list of allowed commands, and possibly map it to a new value. * If *compiler_name is changed, the original value is free'd, and a new value is malloc'd. * * If the environment variable DISTCC_CMDLIST is set, * load a list of supported commands from the file named by DISTCC_CMDLIST, and * refuse to serve any command whose last DISTCC_CMDLIST_NUMWORDS last words * don't match those of a command in that list. * Each line of the file is simply a filename. * This is chiefly useful for those few installations which have so many * compilers available such that the compiler must be specified with an absolute pathname. * * Example: if the compilers are installed in a different location on * this server, e.g. if they've been copied from a shared NFS directory onto a * local hard drive, you might have lines like * /local/tools/blort/sh4-linux/gcc-3.3.3-glibc-2.2.5/bin/sh4-linux-gcc * /local/tools/blort/sh4-linux/gcc-2.95.3-glibc-2.2.5/bin/sh4-linux-gcc * and set DISTCC_CMDLIST_NUMWORDS=3; that way e.g. any of the commands * /local/tools/gcc-3.3.3-glibc-2.2.5/bin/sh4-linux-gcc * /shared/tools/gcc-3.3.3-glibc-2.2.5/bin/sh4-linux-gcc * /zounds/gcc-3.3.3-glibc-2.2.5/bin/sh4-linux-gcc * will invoke * /local/tools/blort/sh4-linux/gcc-3.3.3-glibc-2.2.5/bin/sh4-linux-gcc * * Returns 0 (which will abort the compile) if compiler not in list. * (This is because the list is intended to be complete, * and any attempt to use a command not in the list indicates a confused user. * FIXME: should probably give user the option of changing this * behavior at runtime, so normal command lookup can continue even if command * not found in table.) **/ static int dcc_remap_compiler(char **compiler_name) { static int cmdlist_checked=0; static stringmap_t *map=0; const char *newname; /* load file if not already */ if (!cmdlist_checked) { char *filename; cmdlist_checked = 1; filename = getenv("DISTCC_CMDLIST"); if (filename) { const char *nw = getenv("DISTCC_CMDLIST_NUMWORDS"); int numFinalWordsToMatch=1; if (nw) numFinalWordsToMatch = atoi(nw); map = stringmap_load(filename, numFinalWordsToMatch); if (map) { rs_trace("stringmap_load(%s, %d) found %d commands", filename, numFinalWordsToMatch, map->n); } else { rs_log_error("stringmap_load(%s, %d) failed: %s", filename, numFinalWordsToMatch, strerror(errno)); return EXIT_IO_ERROR; } } } if (!map) return 1; /* no list of allowed names, so ok */ /* Find what this compiler maps to */ newname = stringmap_lookup(map, *compiler_name); if (!newname) { rs_log_warning("lookup of %s in DISTCC_CMDLIST failed", *compiler_name); return 0; /* not in list, so forbidden. FIXME: make failure an option */ } /* If mapping is not the identity mapping, replace the original name */ if (strcmp(newname, *compiler_name)) { rs_trace("changed compiler from %s to %s", *compiler_name, newname); free(*compiler_name); *compiler_name = strdup(newname); } return 1; } /** * Find the absolute path for the first occurrence of @p compiler_name on the * PATH. Print a warning if it looks like a symlink to distcc. * * We want to guard against somebody accidentally running the server with a * masqueraded compiler on its $PATH. The worst that's likely to happen here * is wasting some time running a distcc or ccache client that does nothing, * so it's not a big deal. (This could be easy to do if it's on the default * PATH and they start the daemon from the command line.) * * At the moment we don't look for the compiler too. **/ static int dcc_check_compiler_masq(char *compiler_name) { const char *envpath, *p, *n; char *buf = NULL; struct stat sb; int len; char linkbuf[MAXPATHLEN]; if (compiler_name[0] == '/') return 0; if (!(envpath = getenv("PATH"))) { rs_trace("PATH seems not to be defined"); return 0; } for (n = p = envpath; *n; p = n) { n = strchr(p, ':'); if (n) len = n++ - p; else { len = strlen(p); n = p + len; } if (asprintf(&buf, "%.*s/%s", len, p, compiler_name) == -1) { rs_log_crit("asprintf failed"); return EXIT_DISTCC_FAILED; } if (lstat(buf, &sb) == -1) continue; /* ENOENT, EACCESS, etc */ if (!S_ISLNK(sb.st_mode)) { rs_trace("%s is not a symlink", buf); break; /* found it */ } if ((len = readlink(buf, linkbuf, sizeof linkbuf)) <= 0) continue; linkbuf[len] = '\0'; if (strstr(linkbuf, "distcc")) { rs_log_warning("%s on distccd's path is %s and really a link to %s", compiler_name, buf, linkbuf); break; /* but use it anyhow */ } else { rs_trace("%s is a safe symlink to %s", buf, linkbuf); break; /* found it */ } } free(buf); return 0; } /** * Make sure there is a masquerade to distcc in LIBDIR/distcc in order to * execute a binary of the same name. * * Before this it was possible to execute arbitrary command after connecting * to distcc, which is quite a security risk when combined with any local root * privilege escalation exploit. See CVE 2004-2687 * * https://nvd.nist.gov/vuln/detail/CVE-2004-2687 * https://github.com/distcc/distcc/issues/155 **/ static int dcc_check_compiler_whitelist(char *_compiler_name) { char *compiler_name = _compiler_name; /* Support QtCreator by treating /usr/bin and /bin absolute paths as non-absolute * see https://github.com/distcc/distcc/issues/279 */ const char *creator_paths[] = { "/bin/", "/usr/bin/", NULL }; int i; for (i = 0 ; creator_paths[i] ; ++i) { size_t len = strlen(creator_paths[i]); // /bin and /usr/bin are absolute paths (= compare from the string start) // use strncasecmp() to support case-insensitive / (= on Mac). if (strncasecmp(_compiler_name, creator_paths[i], len) == 0) { compiler_name = _compiler_name + len; // stop at the first hit break; } } if (strchr(compiler_name, '/')) { rs_log_crit("compiler name <%s> cannot be an absolute path (or must set DISTCC_CMDLIST or pass --enable-tcp-insecure)", _compiler_name); return EXIT_BAD_ARGUMENTS; } #ifdef HAVE_FSTATAT int dirfd = open(LIBDIR "/distcc", O_RDONLY); if (dirfd < 0) { if (errno == ENOENT) rs_log_crit("no %s", LIBDIR "/distcc"); return EXIT_DISTCC_FAILED; } if (faccessat(dirfd, compiler_name, X_OK, 0) < 0) { char *compiler_path = NULL; if (asprintf(&compiler_path, "/usr/lib/distcc/%s", compiler_name) >= 0) { if (access(compiler_path, X_OK) < 0) { free(compiler_path); close(dirfd); rs_log_crit("%s not in %s or %s whitelist.", compiler_name, LIBDIR "/distcc", "/usr/lib/distcc"); return EXIT_BAD_ARGUMENTS; /* ENOENT, EACCESS, etc */ } free(compiler_path); } } close(dirfd); rs_trace("%s in" LIBDIR "/distcc whitelist", compiler_name); return 0; #else // make do with access(): char *compiler_path; int ret = 0; if (asprintf(&compiler_path, "%s/distcc/%s", LIBDIR, compiler_name) >= 0) { if (access(compiler_path, X_OK) < 0) { free(compiler_path); /* check /usr/lib/distcc too */ if (asprintf(&compiler_path, "/usr/lib/distcc/%s", compiler_name) >= 0) { if (access(compiler_path, X_OK) < 0) { rs_log_crit("%s not in %s or %s whitelist.", compiler_name, LIBDIR "/distcc", "/usr/lib/distcc"); ret = EXIT_BAD_ARGUMENTS; /* ENOENT, EACCESS, etc */ } free(compiler_path); } } else { free(compiler_path); } rs_trace("%s in" LIBDIR "/distcc whitelist", compiler_name); } else { rs_log_crit("Couldn't check if %s is in %s whitelist.", compiler_name, LIBDIR "/distcc"); ret = EXIT_DISTCC_FAILED; } return ret; #endif } static const char *include_options[] = { "-I", "-include", "-imacros", "-idirafter", "-iprefix", "-iwithprefix", "-iwithprefixbefore", "-isystem", "-iquote", NULL }; /** * Prepend @p root_dir string to source file if absolute. **/ static int tweak_input_argument_for_server(char **argv, const char *root_dir) { unsigned i; /* Look for the source file and act if absolute. Note: dcc_scan_args * rejects compilations with more than one source file. */ for (i=0; argv[i]; i++) if (dcc_is_source(argv[i]) && argv[i][0]=='/') { unsigned j = 0; char *prefixed_name; while (argv[i][j] == '/') j++; if (asprintf(&prefixed_name, "%s/%s", root_dir, argv[i] + j) == -1) { rs_log_crit("asprintf failed"); return EXIT_OUT_OF_MEMORY; } rs_trace("changed input from \"%s\" to \"%s\"", argv[i], prefixed_name); free(argv[i]); argv[i] = prefixed_name; dcc_trace_argv("command after", argv); return 0; } return 0; } /** * Prepend @p root_dir to arguments of include options that are absolute. **/ static int tweak_include_arguments_for_server(char **argv, const char *root_dir) { int index_of_first_filename_char = 0; const char *include_option; unsigned int i, j; for (i = 0; argv[i]; ++i) { for (j = 0; include_options[j]; ++j) { if (str_startswith(include_options[j], argv[i])) { if (strcmp(argv[i], include_options[j]) == 0) { /* "-I foo" , change the next argument */ ++i; include_option = ""; index_of_first_filename_char = 0; } else { /* "-Ifoo", change this argument */ include_option = include_options[j]; index_of_first_filename_char = strlen(include_option); } if (argv[i] != NULL) { /* in case of a dangling -I */ if (argv[i][index_of_first_filename_char] == '/') { char *buf; checked_asprintf(&buf, "%s%s%s", include_option, root_dir, argv[i] + index_of_first_filename_char); if (buf == NULL) { return EXIT_OUT_OF_MEMORY; } free(argv[i]); argv[i] = buf; } } break; /* from the inner loop; go look at the next argument */ } } } return 0; } /* The -MT command line flag does not work as advertised for distcc: * it augments, rather than replace, the list of targets in the dotd file. * The behavior we want though, is the replacing behavior. * So here we delete the "-MT target" arguments, and we return the target, * for use in the .d rewriting in dotd.c. */ static int dcc_convert_mt_to_dotd_target(char **argv, char **dotd_target) { int i; *dotd_target = NULL; for (i = 0; argv[i]; ++i) { if (strcmp(argv[i], "-MT") == 0) { break; } } /* if we reached the end without finding -MT, fine. */ if (argv[i] == NULL) return 0; /* if we find -MT but only at the very end, that's an error. */ if (argv[i+1] == NULL) { rs_trace("found -MT at the end of the command line"); return 1; } /* the dotd_target is the argument of -MT */ *dotd_target = argv[i+1]; /* copy the next-next argument on top of this. */ for (; argv[i+2]; ++i) { argv[i] = argv[i+2]; } /* and then put the terminal null in. */ argv[i] = argv[i+2]; return 0; } /** * Add -MMD and -MF to get a .d file. * Find what the dotd target should be (if any). * Prepend @p root_dir to every command * line argument that refers to a file/dir by an absolute name. **/ static int tweak_arguments_for_server(char **argv, const char *root_dir, const char *deps_fname, char **dotd_target, char ***tweaked_argv) { int ret; *dotd_target = 0; if ((ret = dcc_copy_argv(argv, tweaked_argv, 3))) return 1; if ((ret = dcc_convert_mt_to_dotd_target(*tweaked_argv, dotd_target))) return 1; if (!dcc_argv_search(*tweaked_argv, "-MD") && !dcc_argv_search(*tweaked_argv, "-MMD")) { dcc_argv_append(*tweaked_argv, strdup("-MMD")); } dcc_argv_append(*tweaked_argv, strdup("-MF")); dcc_argv_append(*tweaked_argv, strdup(deps_fname)); tweak_include_arguments_for_server(*tweaked_argv, root_dir); tweak_input_argument_for_server(*tweaked_argv, root_dir); return 0; } /** * Read the client working directory from in_fd socket, * and set up the server side directory corresponding to that. * Inputs: * @p in_fd: the file descriptor for the socket. * Outputs: * @p temp_dir: a temporary directory on the server, * corresponding to the client's root directory (/), * @p client_side_cwd: the current directory on the client * @p server_side_cwd: the corresponding directory on the server; * server_side_cwd = temp_dir + client_side_cwd **/ static int make_temp_dir_and_chdir_for_cpp(int in_fd, char **temp_dir, char **client_side_cwd, char **server_side_cwd) { int ret = 0; if ((ret = dcc_get_new_tmpdir(temp_dir))) return ret; if ((ret = dcc_r_cwd(in_fd, client_side_cwd))) return ret; checked_asprintf(server_side_cwd, "%s%s", *temp_dir, *client_side_cwd); if (*server_side_cwd == NULL) { ret = EXIT_OUT_OF_MEMORY; } else if ((ret = dcc_mk_tmp_ancestor_dirs(*server_side_cwd))) { ; /* leave ret the way it is */ } else if ((ret = dcc_mk_tmpdir(*server_side_cwd))) { ; /* leave ret the way it is */ } else if (chdir(*server_side_cwd) == -1) { ret = EXIT_IO_ERROR; } return ret; } /** * Read a request, run the compiler, and send a response. **/ static int dcc_run_job(int in_fd, int out_fd) { char **argv = NULL; char **tweaked_argv = NULL; int status = 0; char *temp_i = NULL, *temp_o = NULL; char *err_fname = NULL, *out_fname = NULL, *deps_fname = NULL; char *temp_dir = NULL; /* for receiving multiple files */ int ret = 0, compile_ret = 0; char *orig_input = NULL, *orig_output = NULL; char *orig_input_tmp, *orig_output_tmp; char *dotd_target = NULL; pid_t cc_pid; enum dcc_protover protover; enum dcc_compress compr; struct timeval start, end; int time_ms; char *time_str; int job_result = -1; enum dcc_cpp_where cpp_where; char *server_cwd = NULL; char *client_cwd = NULL; int changed_directory = 0; gettimeofday(&start, NULL); if ((ret = dcc_make_tmpnam("distcc", ".deps", &deps_fname))) goto out_cleanup; if ((ret = dcc_make_tmpnam("distcc", ".stderr", &err_fname))) goto out_cleanup; if ((ret = dcc_make_tmpnam("distcc", ".stdout", &out_fname))) goto out_cleanup; dcc_remove_if_exists(deps_fname); dcc_remove_if_exists(err_fname); dcc_remove_if_exists(out_fname); /* Capture any messages relating to this compilation to the same file as * compiler errors so that they can all be sent back to the client. */ dcc_add_log_to_file(err_fname); /* Ignore SIGPIPE; we consistently check error codes and will see the * EPIPE. Note that it is set back to the default behaviour when spawning * a child, to handle cases like the assembler dying while its being fed * from the compiler */ dcc_ignore_sigpipe(1); /* Allow output to accumulate into big packets. */ tcp_cork_sock(out_fd, 1); if ((ret = dcc_r_request_header(in_fd, &protover))) goto out_cleanup; dcc_get_features_from_protover(protover, &compr, &cpp_where); if (cpp_where == DCC_CPP_ON_SERVER) { if ((ret = make_temp_dir_and_chdir_for_cpp(in_fd, &temp_dir, &client_cwd, &server_cwd))) goto out_cleanup; changed_directory = 1; } if ((ret = dcc_r_argv(in_fd, "ARGC", "ARGV", &argv)) || (ret = dcc_scan_args(argv, &orig_input_tmp, &orig_output_tmp, &tweaked_argv))) goto out_cleanup; /* The orig_input_tmp and orig_output_tmp values returned by dcc_scan_args() * are aliased with some element of tweaked_argv. We need to copy them, * because the calls to dcc_set_input() and dcc_set_output() below will * free those elements. */ orig_input = strdup(orig_input_tmp); orig_output = strdup(orig_output_tmp); if (orig_input == NULL || orig_output == NULL) { ret = EXIT_OUT_OF_MEMORY; goto out_cleanup; } /* Our new argv is what dcc_scan_args put into tweaked_argv */ /* Put tweaked_argv into argv, and free old argv */ dcc_free_argv(argv); argv = tweaked_argv; tweaked_argv = NULL; rs_trace("output file %s", orig_output); if ((ret = dcc_make_tmpnam("distccd", ".o", &temp_o))) goto out_cleanup; /* if the protocol is multi-file, then we need to do the following * in a loop. */ if (cpp_where == DCC_CPP_ON_SERVER) { if (dcc_r_many_files(in_fd, temp_dir, compr) || dcc_set_output(argv, temp_o) || tweak_arguments_for_server(argv, temp_dir, deps_fname, &dotd_target, &tweaked_argv)) goto out_cleanup; /* Repeat the switcharoo trick a few lines above. */ dcc_free_argv(argv); argv = tweaked_argv; tweaked_argv = NULL; } else { if ((ret = dcc_input_tmpnam(orig_input, &temp_i))) goto out_cleanup; if ((ret = dcc_r_token_file(in_fd, "DOTI", temp_i, compr)) || (ret = dcc_set_input(argv, temp_i)) || (ret = dcc_set_output(argv, temp_o))) goto out_cleanup; } if (!dcc_remap_compiler(&argv[0])) goto out_cleanup; if ((ret = dcc_check_compiler_masq(argv[0]))) goto out_cleanup; if (!opt_enable_tcp_insecure && !getenv("DISTCC_CMDLIST") && dcc_check_compiler_whitelist(argv[0])) goto out_cleanup; /* unsafe compiler options. See https://youtu.be/bSkpMdDe4g4?t=53m12s on securing https://godbolt.org/ */ char *a; int i; for (i = 0; (a = argv[i]); i++) if (strncmp(a, "-fplugin=", strlen("-fplugin=")) == 0 || strncmp(a, "-specs=", strlen("-specs=")) == 0) { rs_log_warning("-fplugin= and/or -specs= passed, which are insecure and not supported."); goto out_cleanup; } if ((compile_ret = dcc_spawn_child(argv, &cc_pid, "/dev/null", out_fname, err_fname)) || (compile_ret = dcc_collect_child("cc", cc_pid, &status, in_fd))) { /* We didn't get around to finding a wait status from the actual * compiler */ status = W_EXITCODE(compile_ret, 0); } if ((ret = dcc_x_result_header(out_fd, protover)) || (ret = dcc_x_cc_status(out_fd, status)) || (ret = dcc_x_file(out_fd, err_fname, "SERR", compr, NULL)) || (ret = dcc_x_file(out_fd, out_fname, "SOUT", compr, NULL))) { /* We get a protocol derailment if we send DOTO 0 here */ if (job_result == -1) job_result = STATS_COMPILE_ERROR; } else if (WIFSIGNALED(status) || WEXITSTATUS(status)) { /* Something went wrong, so send DOTO 0 */ dcc_x_token_int(out_fd, "DOTO", 0); if (job_result == -1) job_result = STATS_COMPILE_ERROR; } else { if (cpp_where == DCC_CPP_ON_SERVER) { rs_trace("fixing up debug info"); /* * We update the debugging information, replacing all occurrences * of temp_dir (the server temp directory that corresponds to the * client's root directory) with "/", to convert server path * names to client path names. This is safe to do only because * temp_dir is of the form "/var/tmp/distccd-XXXXXX" where XXXXXX * is randomly chosen by mkdtemp(), which makes it inconceivably * unlikely that this pattern could occur in the debug info by * chance. */ if ((ret = dcc_fix_debug_info(temp_o, "/", temp_dir))) goto out_cleanup; } if ((ret = dcc_x_file(out_fd, temp_o, "DOTO", compr, NULL))) goto out_cleanup; if (cpp_where == DCC_CPP_ON_SERVER) { char *cleaned_dotd; ret = dcc_cleanup_dotd(deps_fname, &cleaned_dotd, temp_dir, dotd_target ? dotd_target : orig_output, temp_o); if (ret) goto out_cleanup; ret = dcc_x_file(out_fd, cleaned_dotd, "DOTD", compr, NULL); free(cleaned_dotd); } job_result = STATS_COMPILE_OK; } if (compile_ret == EXIT_IO_ERROR) { job_result = STATS_CLI_DISCONN; } else if (compile_ret == EXIT_TIMEOUT) { job_result = STATS_COMPILE_TIMEOUT; } dcc_critique_status(status, argv[0], orig_input, dcc_hostdef_local, 0); tcp_cork_sock(out_fd, 0); rs_log(RS_LOG_INFO|RS_LOG_NONAME, "job complete"); out_cleanup: /* Restore the working directory, if needed. */ if (changed_directory) { if (chdir(dcc_daemon_wd) != 0) { rs_log_warning("chdir(%s) failed: %s", dcc_daemon_wd, strerror(errno)); } } switch (ret) { case EXIT_BUSY: /* overloaded */ job_result = STATS_REJ_OVERLOAD; break; case EXIT_IO_ERROR: /* probably client disconnected */ job_result = STATS_CLI_DISCONN; break; case EXIT_PROTOCOL_ERROR: job_result = STATS_REJ_BAD_REQ; break; default: if (job_result != STATS_COMPILE_ERROR && job_result != STATS_COMPILE_OK && job_result != STATS_CLI_DISCONN && job_result != STATS_COMPILE_TIMEOUT) { job_result = STATS_OTHER; } } gettimeofday(&end, NULL); time_ms = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000; dcc_job_summary_append(" "); dcc_job_summary_append(stats_text[job_result]); if (job_result == STATS_COMPILE_OK) { /* special case, also log compiler, file and time */ dcc_stats_compile_ok(argv[0], orig_input, start, end, time_ms); } else { dcc_stats_event(job_result); } checked_asprintf(&time_str, " exit:%d sig:%d core:%d ret:%d time:%dms ", WEXITSTATUS(status), WTERMSIG(status), WCOREDUMP(status), ret, time_ms); if (time_str != NULL) dcc_job_summary_append(time_str); free(time_str); /* append compiler and input file info */ if (job_result == STATS_COMPILE_ERROR || job_result == STATS_COMPILE_OK) { dcc_job_summary_append(argv[0]); dcc_job_summary_append(" "); dcc_job_summary_append(orig_input); } dcc_remove_log_to_file(); dcc_cleanup_tempfiles(); free(orig_input); free(orig_output); if (argv) dcc_free_argv(argv); if (tweaked_argv) dcc_free_argv(tweaked_argv); free(temp_dir); free(temp_i); free(temp_o); free(deps_fname); free(err_fname); free(out_fname); free(client_cwd); free(server_cwd); return ret; } distcc-3.4/src/setuid.c000066400000000000000000000077411404653710500150770ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "daemon.h" #include "exitcode.h" #ifdef __linux__ #include #ifndef PR_SET_NO_NEW_PRIVS #define PR_SET_NO_NEW_PRIVS 38 #endif #endif const char *opt_user = "distcc"; /** * @file * * Functions for setting the daemon's persona. * * It is better to create separate userids for daemons rather than to just use * "nobody". * * Personas may be specified either as a name or an ID. **/ /** * Try to find an appropriate uid,gid to change to. * * In order, we try "distcc" or the user on the command line, or "nobody", or * failing that the traditional value for nobody of 65534. */ static int dcc_preferred_user(uid_t *puid, gid_t *pgid) { struct passwd *pw; if ((pw = getpwnam(opt_user))) { *puid = pw->pw_uid; *pgid = pw->pw_gid; return 0; /* cool */ } /* Note getpwnam() does not set errno */ rs_log_warning("no such user as \"%s\"", opt_user); /* try something else */ if ((pw = getpwnam("nobody"))) { *puid = pw->pw_uid; *pgid = pw->pw_gid; return 0; /* cool */ } /* just use traditional value */ *puid = *pgid = 65534; return 0; } /** * Make sure that distccd never runs as root, by discarding privileges if we * have them. * * This used to also check gid!=0, but on BSD that is group wheel and is * apparently common for daemons or users. * * This is run before dissociating from the calling terminal so any errors go * to stdout. **/ int dcc_discard_root(void) { uid_t uid; gid_t gid; int ret; if (getuid() != 0 && geteuid() != 0) { /* Already not root. No worries. */ return 0; } if ((ret = dcc_preferred_user(&uid, &gid)) != 0) return ret; /* GNU C Library Manual says that when run by root, setgid() and setuid() * permanently discard privileges: both the real and effective uid are * set. */ if (setgid(gid)) { rs_log_error("setgid(%d) failed: %s", (int) gid, strerror(errno)); return EXIT_SETUID_FAILED; } #ifdef HAVE_SETGROUPS /* Get rid of any supplementary groups this process might have * inherited. */ /* XXX: OS X Jaguar broke setgroups so that setting it to 0 fails. */ if (setgroups(1, &gid)) { rs_log_error("setgroups failed: %s", strerror(errno)); return EXIT_SETUID_FAILED; } #endif if (setuid(uid)) { rs_log_error("setuid(%d) failed: %s", (int) uid, strerror(errno)); return EXIT_SETUID_FAILED; } if (getuid() == 0 || geteuid() == 0) { rs_log_crit("still have root privileges after trying to discard them!"); return EXIT_SETUID_FAILED; } #ifdef __linux__ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0) rs_trace("successfully set no_new_privs"); #endif rs_trace("discarded root privileges, changed to uid=%d gid=%d", (int) uid, (int) gid); return 0; } distcc-3.4/src/snprintf.c000066400000000000000000000717401404653710500154450ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright Patrick Powell 1995 * This code is based on code written by Patrick Powell (papowell@astart.com) * It may be used for any purpose as long as this notice remains intact * on all source code distributions */ /* * NOTE: If you change this file, please merge it into rsync, samba, etc. */ /************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * A bombproof version of doprnt (dopr) included. * Sigh. This sort of thing is always nasty do deal with. Note that * the version here does not include floating point... * * snprintf() is used instead of sprintf() as it does limit checks * for string length. This covers a nasty loophole. * * The other functions are there to prevent NULL pointers from * causing nast effects. * * More Recently: * Brandon Long 9/15/96 for mutt 0.43 * This was ugly. It is still ugly. I opted out of floating point * numbers, but the formatter understands just about everything * from the normal C string format, at least as far as I can tell from * the Solaris 2.5 printf(3S) man page. * * Brandon Long 10/22/97 for mutt 0.87.1 * Ok, added some minimal floating point support, which means this * probably requires libm on most operating systems. Don't yet * support the exponent (e,E) and sigfig (g,G). Also, fmtint() * was pretty badly broken, it just wasn't being exercised in ways * which showed it, so that's been fixed. Also, formatted the code * to mutt conventions, and removed dead code left over from the * original. Also, there is now a builtin-test, just compile with: * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm * and run snprintf for results. * * Thomas Roessler 01/27/98 for mutt 0.89i * The PGP code was using unsigned hexadecimal formats. * Unfortunately, unsigned formats simply didn't work. * * Michael Elkins 03/05/98 for mutt 0.90.8 * The original code assumed that both snprintf() and vsnprintf() were * missing. Some systems only have snprintf() but not vsnprintf(), so * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. * * Andrew Tridgell (tridge@samba.org) Oct 1998 * fixed handling of %.0f * added test for HAVE_LONG_DOUBLE * * tridge@samba.org, idra@samba.org, April 2001 * got rid of fcvt code (twas buggy and made testing harder) * added C99 semantics * * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0 * actually print args for %g and %e * * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0 * Since includes.h isn't included here, VA_COPY has to be defined here. I don't * see any include file that is guaranteed to be here, so I'm defining it * locally. Fixes AIX and Solaris builds. * * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13 * put the ifdef for HAVE_VA_COPY in one place rather than in lots of * functions * * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4 * Fix usage of va_list passed as an arg. Use __va_copy before using it * when it exists. * * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14 * Fix incorrect zpadlen handling in fmtfp. * Thanks to Ollie Oldham for spotting it. * few mods to make it easier to compile the tests. * added the "Ollie" test to the floating point ones. * * Martin Pool (mbp@samba.org) April 2003 * Remove NO_CONFIG_H so that the test case can be built within a source * tree with less trouble. * Remove unnecessary SAFE_FREE() definition. * Update ifdefs to make sure that this file compiles to an (almost) empty * object file on systems that already have all the functions we need. **************************************************************/ #ifndef NO_CONFIG_H #include #else #define NULL 0 #endif #ifdef TEST_SNPRINTF /* need math library headers for testing */ /* In test mode, we pretend that this system doesn't have any snprintf * functions, regardless of what config.h says. */ # undef HAVE_SNPRINTF # undef HAVE_VSNPRINTF # undef HAVE_C99_VSNPRINTF # undef HAVE_ASPRINTF # undef HAVE_VASPRINTF # include #endif /* TEST_SNPRINTF */ /* Solaris x86, for instance, declares vsnprintf here. */ #include #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #ifdef HAVE_CTYPE_H #include #endif #include #include #ifdef HAVE_STDLIB_H #include #endif #include "snprintf.h" #include "va_copy.h" #if !defined(HAVE_SNPRINTF) || \ !defined(HAVE_VSNPRINTF) || \ !defined(HAVE_C99_VSNPRINTF) || \ !defined(HAVE_VASPRINTF) || \ !defined(HAVE_ASPRINTF) /* Lots of code to define our own vsnprintf(). */ #ifdef HAVE_LONG_DOUBLE #define LDOUBLE long double #else #define LDOUBLE double #endif #ifdef HAVE_LONG_LONG #define LLONG long long #else #define LLONG long #endif /* yes this really must be a ||. Don't muck with this (tridge) */ #if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in); static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, const char *value, int flags, int min, int max); static void fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags); static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue, int min, int max, int flags); static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); /* * dopr(): poor man's version of doprintf */ /* format read states */ #define DP_S_DEFAULT 0 #define DP_S_FLAGS 1 #define DP_S_MIN 2 #define DP_S_DOT 3 #define DP_S_MAX 4 #define DP_S_MOD 5 #define DP_S_CONV 6 #define DP_S_DONE 7 /* format flags - Bits */ #define DP_F_MINUS (1 << 0) #define DP_F_PLUS (1 << 1) #define DP_F_SPACE (1 << 2) #define DP_F_NUM (1 << 3) #define DP_F_ZERO (1 << 4) #define DP_F_UP (1 << 5) #define DP_F_UNSIGNED (1 << 6) /* Conversion Flags */ #define DP_C_SHORT 1 #define DP_C_LONG 2 #define DP_C_LDOUBLE 3 #define DP_C_LLONG 4 #define char_to_int(p) ((p)- '0') #ifndef MAX #define MAX(p,q) (((p) >= (q)) ? (p) : (q)) #endif static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) { char ch; LLONG value; LDOUBLE fvalue; char *strvalue; const char *const_strvalue; int min; int max; int state; int flags; int cflags; size_t currlen; va_list args; VA_COPY(args, args_in); state = DP_S_DEFAULT; currlen = flags = cflags = min = 0; max = -1; ch = *format++; while (state != DP_S_DONE) { if (ch == '\0') state = DP_S_DONE; switch(state) { case DP_S_DEFAULT: if (ch == '%') state = DP_S_FLAGS; else dopr_outch (buffer, &currlen, maxlen, ch); ch = *format++; break; case DP_S_FLAGS: switch (ch) { case '-': flags |= DP_F_MINUS; ch = *format++; break; case '+': flags |= DP_F_PLUS; ch = *format++; break; case ' ': flags |= DP_F_SPACE; ch = *format++; break; case '#': flags |= DP_F_NUM; ch = *format++; break; case '0': flags |= DP_F_ZERO; ch = *format++; break; default: state = DP_S_MIN; break; } break; case DP_S_MIN: if (isdigit((unsigned char)ch)) { min = 10*min + char_to_int (ch); ch = *format++; } else if (ch == '*') { min = va_arg (args, int); ch = *format++; state = DP_S_DOT; } else { state = DP_S_DOT; } break; case DP_S_DOT: if (ch == '.') { state = DP_S_MAX; ch = *format++; } else { state = DP_S_MOD; } break; case DP_S_MAX: if (isdigit((unsigned char)ch)) { if (max < 0) max = 0; max = 10*max + char_to_int (ch); ch = *format++; } else if (ch == '*') { max = va_arg (args, int); ch = *format++; state = DP_S_MOD; } else { state = DP_S_MOD; } break; case DP_S_MOD: switch (ch) { case 'h': cflags = DP_C_SHORT; ch = *format++; break; case 'l': cflags = DP_C_LONG; ch = *format++; if (ch == 'l') { /* It's a long long */ cflags = DP_C_LLONG; ch = *format++; } break; case 'L': cflags = DP_C_LDOUBLE; ch = *format++; break; default: break; } state = DP_S_CONV; break; case DP_S_CONV: switch (ch) { case 'd': case 'i': if (cflags == DP_C_SHORT) value = va_arg (args, int); else if (cflags == DP_C_LONG) value = va_arg (args, long int); else if (cflags == DP_C_LLONG) value = va_arg (args, LLONG); else value = va_arg (args, int); fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'o': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (long)va_arg (args, unsigned LLONG); else value = (long)va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); break; case 'u': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (LLONG)va_arg (args, unsigned LLONG); else value = (long)va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'X': flags |= DP_F_UP; case 'x': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (LLONG)va_arg (args, unsigned LLONG); else value = (long)va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); break; case 'f': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); /* um, floating point? */ fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); break; case 'E': flags |= DP_F_UP; case 'e': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); break; case 'G': flags |= DP_F_UP; case 'g': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); break; case 'c': dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); break; case 's': strvalue = va_arg (args, char *); const_strvalue = strvalue; if (!const_strvalue) const_strvalue = "(NULL)"; if (max == -1) { max = strlen(const_strvalue); } if (min > 0 && max >= 0 && min > max) max = min; fmtstr (buffer, &currlen, maxlen, const_strvalue, flags, min, max); break; case 'p': strvalue = va_arg (args, void *); fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); break; case 'n': if (cflags == DP_C_SHORT) { short int *num; num = va_arg (args, short int *); *num = currlen; } else if (cflags == DP_C_LONG) { long int *num; num = va_arg (args, long int *); *num = (long int)currlen; } else if (cflags == DP_C_LLONG) { LLONG *num; num = va_arg (args, LLONG *); *num = (LLONG)currlen; } else { int *num; num = va_arg (args, int *); *num = currlen; } break; case '%': dopr_outch (buffer, &currlen, maxlen, ch); break; case 'w': /* not supported yet, treat as next char */ ch = *format++; break; default: /* Unknown, skip */ break; } ch = *format++; state = DP_S_DEFAULT; flags = cflags = min = 0; max = -1; break; case DP_S_DONE: break; default: /* hmm? */ break; /* some picky compilers need this */ } } if (maxlen != 0) { if (currlen < maxlen - 1) buffer[currlen] = '\0'; else if (maxlen > 0) buffer[maxlen - 1] = '\0'; } VA_COPY_END(args); return currlen; } static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, const char *value, int flags, int min, int max) { int padlen, strln; /* amount to pad */ int cnt = 0; #ifdef DEBUG_SNPRINTF printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); #endif if (value == 0) { value = ""; } for (strln = 0; value[strln]; ++strln); /* strlen */ padlen = min - strln; if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justify */ while ((padlen > 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; ++cnt; } while (*value && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, *value++); ++cnt; } while ((padlen < 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; ++cnt; } } /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ static void fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags) { int signvalue = 0; unsigned long uvalue; char convert[20]; int place = 0; int spadlen = 0; /* amount to space pad */ int zpadlen = 0; /* amount to zero pad */ int caps = 0; if (max < 0) max = 0; uvalue = value; if(!(flags & DP_F_UNSIGNED)) { if( value < 0 ) { signvalue = '-'; uvalue = -value; } else { if (flags & DP_F_PLUS) /* Do a sign (+/i) */ signvalue = '+'; else if (flags & DP_F_SPACE) signvalue = ' '; } } if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ do { convert[place++] = (caps? "0123456789ABCDEF":"0123456789abcdef") [uvalue % (unsigned)base ]; uvalue = (uvalue / (unsigned)base ); } while(uvalue && (place < 20)); if (place == 20) place--; convert[place] = 0; zpadlen = max - place; spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); if (zpadlen < 0) zpadlen = 0; if (spadlen < 0) spadlen = 0; if (flags & DP_F_ZERO) { zpadlen = MAX(zpadlen, spadlen); spadlen = 0; } if (flags & DP_F_MINUS) spadlen = -spadlen; /* Left Justifty */ #ifdef DEBUG_SNPRINTF printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", zpadlen, spadlen, min, max, place); #endif /* Spaces */ while (spadlen > 0) { dopr_outch (buffer, currlen, maxlen, ' '); --spadlen; } /* Sign */ if (signvalue) dopr_outch (buffer, currlen, maxlen, signvalue); /* Zeros */ if (zpadlen > 0) { while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } } /* Digits */ while (place > 0) dopr_outch (buffer, currlen, maxlen, convert[--place]); /* Left Justified spaces */ while (spadlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); ++spadlen; } } static LDOUBLE abs_val(LDOUBLE value) { LDOUBLE result = value; if (value < 0) result = -value; return result; } static LDOUBLE POW10(int exp) { LDOUBLE result = 1; while (exp) { result *= 10; exp--; } return result; } static LLONG ROUND(LDOUBLE value) { LLONG intpart; intpart = (LLONG)value; value = value - intpart; if (value >= 0.5) intpart++; return intpart; } /* a replacement for modf that doesn't need the math library. Should be portable, but slow */ static double my_modf(double x0, double *iptr) { int i; long l; double x = x0; double f = 1.0; for (i=0;i<100;i++) { l = (long)x; if (l <= (x+1) && l >= (x-1)) break; x *= 0.1; f *= 10.0; } if (i == 100) { /* yikes! the number is beyond what we can handle. What do we do? */ (*iptr) = 0; return 0; } if (i != 0) { double i2; double ret; ret = my_modf(x0-l*f, &i2); (*iptr) = l*f + i2; return ret; } (*iptr) = l; return x - (*iptr); } static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue, int min, int max, int flags) { int signvalue = 0; double ufvalue; char iconvert[311]; char fconvert[311]; int iplace = 0; int fplace = 0; int padlen = 0; /* amount to pad */ int zpadlen = 0; int caps = 0; int idx; double intpart; double fracpart; double temp; /* * AIX manpage says the default is 0, but Solaris says the default * is 6, and sprintf on AIX defaults to 6 */ if (max < 0) max = 6; ufvalue = abs_val (fvalue); if (fvalue < 0) { signvalue = '-'; } else { if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ signvalue = '+'; } else { if (flags & DP_F_SPACE) signvalue = ' '; } } #if 0 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ #endif #if 0 if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ #endif /* * Sorry, we only support 16 digits past the decimal because of our * conversion method */ if (max > 16) max = 16; /* We "cheat" by converting the fractional part to integer by * multiplying by a factor of 10 */ temp = ufvalue; my_modf(temp, &intpart); fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); if (fracpart >= POW10(max)) { intpart++; fracpart -= POW10(max); } /* Convert integer part */ do { temp = intpart*0.1; my_modf(temp, &intpart); idx = (int) ((temp -intpart +0.05)* 10.0); /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ /* printf ("%llf, %f, %x\n", temp, intpart, idx); */ iconvert[iplace++] = (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; } while (intpart && (iplace < 311)); if (iplace == 311) iplace--; iconvert[iplace] = 0; /* Convert fractional part */ if (fracpart) { do { temp = fracpart*0.1; my_modf(temp, &fracpart); idx = (int) ((temp -fracpart +0.05)* 10.0); /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */ /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx); */ fconvert[fplace++] = (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; } while(fracpart && (fplace < 311)); if (fplace == 311) fplace--; } fconvert[fplace] = 0; /* -1 for decimal point, another -1 if we are printing a sign */ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); zpadlen = max - fplace; if (zpadlen < 0) zpadlen = 0; if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justifty */ if ((flags & DP_F_ZERO) && (padlen > 0)) { if (signvalue) { dopr_outch (buffer, currlen, maxlen, signvalue); --padlen; signvalue = 0; } while (padlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --padlen; } } while (padlen > 0) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; } if (signvalue) dopr_outch (buffer, currlen, maxlen, signvalue); while (iplace > 0) dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); #ifdef DEBUG_SNPRINTF printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); #endif /* * Decimal point. This should probably use locale to find the correct * char to print out. */ if (max > 0) { dopr_outch (buffer, currlen, maxlen, '.'); while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } while (fplace > 0) dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); } while (padlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; } } static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) { if (*currlen < maxlen) { buffer[(*currlen)] = c; } (*currlen)++; } int vsnprintf (char *str, size_t count, const char *fmt, va_list args) { return dopr(str, count, fmt, args); } #endif /* yes this really must be a ||. Don't muck wiith this (tridge) * * The logic for these two is that we need our own definition if the * OS *either* has no definition of *sprintf, or if it does have one * that doesn't work properly according to the autoconf test. Perhaps * these should really be smb_snprintf to avoid conflicts with buggy * linkers? -- mbp */ #if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) int snprintf(char *str,size_t count,const char *fmt,...) { size_t ret; va_list ap; va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); return ret; } #endif #endif /* HAVE_SNPRINTF, and everything */ #ifndef HAVE_VASPRINTF int vasprintf(char **ptr, const char *format, va_list ap) { int ret; va_list ap2; VA_COPY(ap2, ap); ret = vsnprintf(NULL, 0, format, ap2); VA_COPY_END(ap2); if (ret <= 0) return ret; (*ptr) = (char *)malloc(ret+1); if (!*ptr) return -1; VA_COPY(ap2, ap); ret = vsnprintf(*ptr, ret+1, format, ap2); VA_COPY_END(ap2); return ret; } #endif /* HAVE_VASPRINTF */ #ifndef HAVE_ASPRINTF int asprintf(char **ptr, const char *format, ...) { va_list ap; int ret; *ptr = NULL; va_start(ap, format); ret = vasprintf(ptr, format, ap); va_end(ap); return ret; } #endif /* HAVE_ASPRINTF */ /* Like asprintf(), but on error it sets *ptr to NULL * rather than returning -1. Unlike asprintf(), it * guarantees to always set *ptr. */ int checked_asprintf(char **ptr, const char *format, ...) { va_list ap; int ret; *ptr = NULL; va_start(ap, format); ret = vasprintf(ptr, format, ap); va_end(ap); if (ret == -1) { *ptr = NULL; } return ret; } #ifdef TEST_SNPRINTF int sprintf(char *str,const char *fmt,...); int main (void) { char buf1[1024]; char buf2[1024]; char *fp_fmt[] = { "%1.1f", "%-1.5f", "%1.5f", "%123.9f", "%10.5f", "% 10.5f", "%+22.9f", "%+4.9f", "%01.3f", "%4f", "%3.1f", "%3.2f", "%.0f", "%f", "-16.16f", NULL }; double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996, 0.9996, 1.996, 4.136, 5.030201, 0.00205, /* END LIST */ 0}; char *int_fmt[] = { "%-1.5d", "%1.5d", "%123.9d", "%5.5d", "%10.5d", "% 10.5d", "%+22.33d", "%01.3d", "%4d", "%d", NULL }; long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; char *str_fmt[] = { "10.5s", "5.10s", "10.1s", "0.10s", "10.0s", "1.10s", "%s", "%.1s", "%.10s", "%10s", NULL }; char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; int x, y; int fail = 0; int num = 0; printf ("Testing snprintf format codes against system sprintf...\n"); for (x = 0; fp_fmt[x] ; x++) { for (y = 0; fp_nums[y] != 0 ; y++) { int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]); int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); sprintf (buf2, fp_fmt[x], fp_nums[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", fp_fmt[x], buf1, buf2); fail++; } if (l1 != l2) { printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]); fail++; } num++; } } for (x = 0; int_fmt[x] ; x++) { for (y = 0; int_nums[y] != 0 ; y++) { int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]); int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); sprintf (buf2, int_fmt[x], int_nums[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", int_fmt[x], buf1, buf2); fail++; } if (l1 != l2) { printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]); fail++; } num++; } } for (x = 0; str_fmt[x] ; x++) { for (y = 0; str_vals[y] != 0 ; y++) { int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]); int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); sprintf (buf2, str_fmt[x], str_vals[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", str_fmt[x], buf1, buf2); fail++; } if (l1 != l2) { printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]); fail++; } num++; } } printf ("%d tests failed out of %d.\n", fail, num); printf("seeing how many digits we support\n"); { double v0 = 0.12345678901234567890123456789012345678901; for (x=0; x<100; x++) { double p = pow(10, x); double r = v0*p; snprintf(buf1, sizeof(buf1), "%1.1f", r); sprintf(buf2, "%1.1f", r); if (strcmp(buf1, buf2)) { printf("we seem to support %d digits\n", x-1); break; } } } return 0; } #endif /* TEST_SNPRINTF */ distcc-3.4/src/snprintf.h000066400000000000000000000023661404653710500154500ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- */ /* * Copyright Patrick Powell 1995 * This code is based on code written by Patrick Powell (papowell@astart.com) * It may be used for any purpose as long as this notice remains intact * on all source code distributions */ #include #include "config.h" #ifdef __GNUC__ /** Use gcc attribute to check printf fns. a1 is the 1-based index of * the parameter containing the format, and a2 the index of the first * argument. **/ #define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) #else #define PRINTF_ATTRIBUTE(a1, a2) #endif /* Note that the HAVE_DECL macros are defined to 0 if the declaration * is not present, rather than being undefined as is the case for most * autoconf tests. */ #if !HAVE_DECL_VASPRINTF int vasprintf(char **ptr, const char *format, va_list ap); #endif #if !HAVE_DECL_SNPRINTF int snprintf(char *,size_t ,const char *, ...) PRINTF_ATTRIBUTE(3,4); #endif #if !HAVE_DECL_ASPRINTF int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); #endif #if !HAVE_DECL_VSNPRINTF int vsnprintf(char *, size_t, const char *, va_list); #endif int checked_asprintf(char **, const char *, ...) PRINTF_ATTRIBUTE(2,3); distcc-3.4/src/srvnet.c000066400000000000000000000165121404653710500151170ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "Happy is the man who finds wisdom, and the man who * gets understanding; for the gain from it is better * than gain from silver and its profit better than * gold." -- Proverbs 3:13 */ /** * @file * * Server-side networking. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ARPA_NAMESER_H # include #endif #include #ifdef HAVE_RESOLV_H # include #endif #include "types.h" #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "srvnet.h" #include "access.h" #include "netutil.h" #include "dopt.h" /* * Listen on a predetermined address (often the passive address). The way in * which we get the address depends on the resolver API in use. **/ static int dcc_listen_by_addr(int fd, struct sockaddr *sa, size_t salen) { int one = 1; char *sa_buf = NULL; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)); dcc_sockaddr_to_string(sa, salen, &sa_buf); if (sa_buf == NULL) { return EXIT_OUT_OF_MEMORY; } /* now we've got a socket - we need to bind it */ if (bind(fd, sa, salen) == -1) { rs_log_error("bind of %s failed: %s", sa_buf ? sa_buf : "UNKNOWN", strerror(errno)); free(sa_buf); close(fd); return EXIT_BIND_FAILED; } rs_log_info("listening on %s", sa_buf ? sa_buf : "UNKNOWN"); free(sa_buf); /* This should be at least 2X the number of threads, and AMD EPYX sells 64-thread CPUs (2019) */ if (listen(fd, 1024)) { rs_log_error("listen failed: %s", strerror(errno)); close(fd); return EXIT_BIND_FAILED; } return 0; } #if defined(ENABLE_RFC2553) /* This version uses getaddrinfo. It will probably use IPv6 if that's * supported by your configuration, kernel, and library. */ int dcc_socket_listen(int port, int *fd_out, const char *listen_addr) { char portname[20]; struct addrinfo hints; struct addrinfo *res, *ai; int error; int ret; /* getaddrinfo() ought to check for this, but some versions do not. * (Debian Bug#192876.) */ if (port < 1 || port > 65535) { rs_log_error("port number out of range: %d", port); return EXIT_BAD_ARGUMENTS; } /* getaddrinfo wants a string for the service name */ snprintf(portname, sizeof portname, "%d", port); /* Set-up hints structure. */ memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; if (listen_addr == NULL) hints.ai_flags = AI_PASSIVE; /* bind all */ error = getaddrinfo(listen_addr, portname, &hints, &res); if (error) { rs_log_error("getaddrinfo failed for host %s service %s: %s", listen_addr ? listen_addr : "(passive)", portname, gai_strerror(error)); return EXIT_BIND_FAILED; } /* The first sockaddr returned will typically be an IPv6 socket. Some * kernels might not support that. */ for (ai = res; ai; ai=ai->ai_next) { int af = ai->ai_addr->sa_family; if ((*fd_out = socket(af, SOCK_STREAM, 0)) == -1) { if (errno == EAFNOSUPPORT) { rs_log_notice("socket address family %d not supported", af); continue; } else { rs_log_error("socket creation failed: %s", strerror(errno)); return EXIT_BIND_FAILED; } } else { ret = dcc_listen_by_addr(*fd_out, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); return ret; } } rs_log_error("failed to find any supported socket family"); return EXIT_BIND_FAILED; } #else /* ndef ENABLE_RFC2553 */ /* This version uses inet_aton */ int dcc_socket_listen(int port, int *listen_fd, const char *listen_addr) { struct sockaddr_in sock; if (port < 1 || port > 65535) { /* htons() will truncate, not check */ rs_log_error("port number out of range: %d", port); return EXIT_BAD_ARGUMENTS; } memset((char *) &sock, 0, sizeof(sock)); sock.sin_port = htons(port); sock.sin_family = PF_INET; if (listen_addr) { if (!inet_aton(listen_addr, &sock.sin_addr)) { rs_log_error("listen address \"%s\" is not a valid IPv4 address", listen_addr); return EXIT_BAD_ARGUMENTS; } } else { sock.sin_addr.s_addr = INADDR_ANY; } if ((*listen_fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { rs_log_error("socket creation failed: %s", strerror(errno)); return EXIT_BIND_FAILED; } return dcc_listen_by_addr(*listen_fd, (struct sockaddr *) &sock, sizeof sock); } #endif /* ndef ENABLE_RFC2553 */ /** * Determine if a file descriptor is in fact a socket **/ int is_a_socket(int fd) { int v; socklen_t len = sizeof(int); return (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *) &v, &len) == 0); } /** * Log client IP address and perform access control checks. * * Note that PSA may be NULL if the sockaddr is unknown. **/ int dcc_check_client(struct sockaddr *psa, int salen, struct dcc_allow_list *allowed) { char *client_ip; struct dcc_allow_list *l; int ret; if ((ret = dcc_sockaddr_to_string(psa, salen, &client_ip)) != 0) return ret; rs_log_info("connection from %s", client_ip); dcc_job_summary_append("client: "); dcc_job_summary_append(client_ip); if (!psa) { /* if no sockaddr, must be a pipe or something. */ free(client_ip); return 0; } if (!allowed) { /* if no ACL, default open */ free(client_ip); return 0; } for (l = allowed; l; l = l->next) { ret = dcc_check_address(psa, &l->addr, &l->mask); if (ret != EXIT_ACCESS_DENIED) break; } if (ret != 0) { rs_log_error("connection from client '%s' denied by access list", client_ip); } free(client_ip); return ret; } distcc-3.4/src/srvnet.h000066400000000000000000000021541404653710500151210ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* srvnet.c */ int dcc_socket_listen(int port, int *fd, const char *listen_addr); int is_a_socket(int fd); struct dcc_allow_list; int dcc_check_client(struct sockaddr *, int, struct dcc_allow_list *); distcc-3.4/src/srvrpc.c000066400000000000000000000126321404653710500151140ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Server-specific RPC code. **/ #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "rpc.h" #include "exitcode.h" #include "dopt.h" #include "hosts.h" #include "bulk.h" #include "snprintf.h" int dcc_r_request_header(int ifd, enum dcc_protover *ver_ret) { unsigned vers; int ret; if ((ret = dcc_r_token_int(ifd, "DIST", &vers)) != 0) { rs_log_error("client did not provide distcc magic fairy dust"); return ret; } if (vers > DCC_VER_3) { rs_log_error("can't handle requested protocol version is %d", vers); return EXIT_PROTOCOL_ERROR; } *ver_ret = (enum dcc_protover) vers; return 0; } /** * Receive the working directory from the client */ int dcc_r_cwd(int ifd, char **cwd) { return dcc_r_token_string(ifd, "CDIR", cwd); } /* @p path must be point to malloc'ed memory * Replaces **path with a pointer to a string containing * dirname + path. * path must be absolute. */ static int prepend_dir_to_name(const char *dirname, char **path) { char *buf; checked_asprintf(&buf, "%s%s", dirname, *path); if (buf == NULL) { return EXIT_OUT_OF_MEMORY; } free(*path); *path = buf; return 0; } int dcc_r_many_files(int in_fd, const char *dirname, enum dcc_compress compr) { int ret = 0; unsigned int n_files; unsigned int i; char *name = 0; char *link_target = 0; char token[5]; if ((ret = dcc_r_token_int(in_fd, "NFIL", &n_files))) return ret; for (i = 0; i < n_files; ++i) { /* like dcc_r_argv */ unsigned int link_or_file_len; if ((ret = dcc_r_token_string(in_fd, "NAME", &name))) goto out_cleanup; /* FIXME: verify that name starts with '/' and doesn't contain '..'. */ if ((ret = prepend_dir_to_name(dirname, &name))) goto out_cleanup; if ((ret = dcc_r_sometoken_int(in_fd, token, &link_or_file_len))) goto out_cleanup; /* Must prepend the dirname for the file name, a link's target name. */ if (strncmp(token, "LINK", 4) == 0) { if ((ret = dcc_r_str_alloc(in_fd, link_or_file_len, &link_target))){ goto out_cleanup; } /* FIXME: verify that link_target doesn't contain '..'. * But the include server uses '..' to reference system * directories (see _MakeLinkFromMirrorToRealLocation * in include_server/compiler_defaults.py), so we'll need to * modify that first. */ if (link_target[0] == '/') { if ((ret = prepend_dir_to_name(dirname, &link_target))) { goto out_cleanup; } } if ((ret = dcc_mk_tmp_ancestor_dirs(name))) { goto out_cleanup; } if (symlink(link_target, name) != 0) { rs_log_error("failed to create path for %s: %s", name, strerror(errno)); ret = 1; goto out_cleanup; } if ((ret = dcc_add_cleanup(name))) { /* bailing out */ unlink(name); goto out_cleanup; } } else if (strncmp(token, "FILE", 4) == 0) { if ((ret = dcc_r_file(in_fd, name, link_or_file_len, compr))) { goto out_cleanup; } if ((ret = dcc_add_cleanup(name))) { /* bailing out */ unlink(name); goto out_cleanup; } } else { char buf[4 + sizeof(link_or_file_len)]; /* unexpected token */ rs_log_error("protocol derailment: expected token FILE or LINK"); /* We should explain what happened here, but we have already read * a few more bytes. */ memcpy(buf, token, 4); /* TODO(manos): this is probably not kosher */ memcpy(&buf[4], &link_or_file_len, sizeof(link_or_file_len)); dcc_explain_mismatch(buf, 12, in_fd); ret = EXIT_PROTOCOL_ERROR; goto out_cleanup; } out_cleanup: free(name); name = NULL; free(link_target); link_target = NULL; if (ret) break; } return ret; } distcc-3.4/src/ssh.c000066400000000000000000000163201404653710500143700ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2001-2004 by Martin Pool * Copyright (C) 1996-2001 by Andrew Tridgell * Copyright (C) 1996 by Paul Mackerras * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * ssh.c -- Open a connection a server over ssh or something similar. * * The ssh connection always opens immediately from distcc's point of view, * because the local socket/pipe to the child is ready. If the remote * connection failed or is slow, distcc will only know when it tries to read * or write. (And in fact the first page or more written will go out * immediately too...) * * This file always uses nonblocking ssh, which has proven in rsync to be the * better solution for ssh. It may cause trouble with ancient proprietary rsh * implementations which can't handle their input being in nonblocking mode. * rsync has a configuration option for that, but I don't support it here, * because there's no point using rsh, you might as well use the native * protocol. */ #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "exec.h" #include "snprintf.h" #include "netutil.h" const char *dcc_default_ssh = "ssh"; /** * Create a file descriptor pair - like pipe() but use socketpair if * possible (because of blocking issues on pipes). * * Always set non-blocking. */ static int fd_pair(int fd[2]) { int ret; #if HAVE_SOCKETPAIR ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); #else ret = pipe(fd); #endif if (ret == 0) { dcc_set_nonblocking(fd[0]); dcc_set_nonblocking(fd[1]); } return ret; } /** * Create a child connected to use on stdin/stdout. * * This is derived from CVS code * * Note that in the child STDIN is set to blocking and STDOUT is set to * non-blocking. This is necessary as rsh relies on stdin being blocking and * ssh relies on stdout being non-blocking **/ static int dcc_run_piped_cmd(char **argv, int *f_in, int *f_out, pid_t * child_pid) { pid_t pid; int to_child_pipe[2]; int from_child_pipe[2]; dcc_trace_argv("execute", argv); if (fd_pair(to_child_pipe) < 0) { rs_log_error("fd_pair: %s", strerror(errno)); return EXIT_IO_ERROR; } if (fd_pair(from_child_pipe) < 0) { dcc_close(to_child_pipe[0]); dcc_close(to_child_pipe[1]); rs_log_error("fd_pair: %s", strerror(errno)); return EXIT_IO_ERROR; } *child_pid = pid = fork(); if (pid == -1) { rs_log_error("fork failed: %s", strerror(errno)); dcc_close(to_child_pipe[0]); dcc_close(to_child_pipe[1]); dcc_close(from_child_pipe[0]); dcc_close(from_child_pipe[1]); return EXIT_IO_ERROR; } if (pid == 0) { if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 || close(to_child_pipe[1]) < 0 || close(from_child_pipe[0]) < 0 || dup2(from_child_pipe[1], STDOUT_FILENO) < 0) { rs_log_error("dup/close: %s", strerror(errno)); return EXIT_IO_ERROR; } if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]); if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]); dcc_set_blocking(STDIN_FILENO); execvp(argv[0], (char **) argv); rs_log_error("failed to exec %s: %s", argv[0], strerror(errno)); return EXIT_IO_ERROR; } if (dcc_close(from_child_pipe[1]) || dcc_close(to_child_pipe[0])) { rs_log_error("failed to close pipes"); return EXIT_IO_ERROR; } *f_in = from_child_pipe[0]; *f_out = to_child_pipe[1]; return 0; } /** * Open a connection to a remote machine over ssh. * * Based on code in rsync, but rewritten. * * @note The tunnel command is always opened directly using execvp(), not * through a shell. So you cannot pass shell operators like redirections, and * at the moment you cannot specify additional options. Perhaps it would be * nice for us to parse it into an argv[] string by splitting on * wildcards/quotes, but at the moment this seems redundant. It can be done * adequately using .ssh/config I think. * * @note the ssh command does need to be tokenized as we have hundreds of * users and a corporate requirement that keeps us from modifying the * system ssh config files. We can at the same time set command-line options * through the tool in use one level above this. - prw 08/09/2016 * **/ int dcc_ssh_connect(char *ssh_cmd, char *user, char *machine, char *path, int *f_in, int *f_out, pid_t *ssh_pid) { pid_t ret; const int max_ssh_args = 12; char *ssh_args[max_ssh_args]; char *child_argv[11+max_ssh_args]; int i,j; int num_ssh_args = 0; char *ssh_cmd_in; /* We need to cast away constness. I promise the strings in the argv[] * will not be modified. */ if (!ssh_cmd && (ssh_cmd_in = getenv("DISTCC_SSH"))) { ssh_cmd = strtok(ssh_cmd_in, " "); char *token = strtok(NULL, " "); while (token != NULL) { ssh_args[num_ssh_args++] = token; token = strtok(NULL, " "); if (num_ssh_args == max_ssh_args) break; } } if (!ssh_cmd) ssh_cmd = (char *) dcc_default_ssh; if (!machine) { rs_log_crit("no machine defined!"); return EXIT_DISTCC_FAILED; } if (!path) path = (char *) "distccd"; i = 0; child_argv[i++] = ssh_cmd; for (j=0; j * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "rpc.h" #include "trace.h" #include "exitcode.h" #include "snprintf.h" #include "util.h" const char *dcc_state_prefix = "binstate_"; static struct dcc_task_state *my_state = NULL; static struct dcc_task_state local_state, remote_state; static struct dcc_task_state *direct_my_state(const enum dcc_host target); /** * @file * * This file provides a way for distcc processes to make little notes * about what they're up to that can be read by a monitor process. * * State is stored as follows. * * Within our temporary directory, we create a subdirectory called "state". * * Each process creates a file named "binstate%d", for its pid. We * always rewrite this file from the beginning. * * Inside each of these, we store a binary struct in the native host * encoding. Ugly, but quick and easy both in code and CPU time. * * Any process reading these files needs to handle the fact that they may be * truncated or otherwise incorrect. * * When the process exits, it removes its state file. If you didn't * notice it already, it's too late now. * * In addition, if the process identified by the file no longer * exists, then the file must be orphaned by a process that suddenly * terminated. The file is ignored and can be deleted by the first * process that notices it. * * The reader interface for these files is in mon.c * * These files are considered a private format, and they may change * between distcc releases. The only supported way to read them is * through mon.c. **/ /** * Return newly allocated buffer holding the name of this process's state file. * * (This can't reliably be static because we might fork...) **/ static int dcc_get_state_filename(char **fname) { int ret; char *dir; if ((ret = dcc_get_state_dir(&dir))) return ret; if (asprintf(fname, "%s/%s%ld", dir, dcc_state_prefix, (long) getpid()) == -1) { return EXIT_OUT_OF_MEMORY; } return 0; } const char *dcc_get_phase_name(enum dcc_phase phase) { switch (phase) { case DCC_PHASE_STARTUP: return "Startup"; case DCC_PHASE_BLOCKED: return "Blocked"; case DCC_PHASE_COMPILE: return "Compile"; case DCC_PHASE_CPP: return "Preprocess"; case DCC_PHASE_CONNECT: return "Connect"; case DCC_PHASE_SEND: return "Send"; case DCC_PHASE_RECEIVE: return "Receive"; case DCC_PHASE_DONE: return "Done"; default: return "Unknown"; } } /** * Get a file descriptor for writing to this process's state file. * file. **/ static int dcc_open_state(int *p_fd, const char *fname) { int fd; fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 0666); if (fd == -1) { rs_log_error("failed to open %s: %s", fname, strerror(errno)); return EXIT_IO_ERROR; } *p_fd = fd; return 0; } /** * Remove the state file for this process. * * This can be called from atexit(). **/ void dcc_remove_state_file (void) { char *fname; int ret; if ((ret = dcc_get_state_filename(&fname))) return; if (unlink(fname) == -1) { /* It's OK if we never created it */ if (errno != ENOENT) { rs_log_warning("failed to unlink %s: %s", fname, strerror(errno)); ret = EXIT_IO_ERROR; } } free(fname); (void) ret; } static int dcc_write_state(int fd) { int ret; /* Write out as one big blob. fd is positioned at the start of * the file. */ if ((ret = dcc_writex(fd, my_state, sizeof *my_state))) return ret; return 0; } /** * Record the state of this process. * * The filename is trimmed down to its basename. * * If the source_file or host are NULL, then are left unchanged from * their previous value. **/ int dcc_note_state(enum dcc_phase state, const char *source_file, const char *host, enum dcc_host target) { int fd; int ret; char *fname; struct timeval tv; if (!direct_my_state(target)) return -1; my_state->struct_size = sizeof *my_state; my_state->magic = DCC_STATE_MAGIC; my_state->cpid = (unsigned long) getpid(); if ((ret = dcc_get_state_filename(&fname))) return ret; source_file = dcc_find_basename(source_file); if (source_file) { strlcpy(my_state->file, source_file, sizeof my_state->file); } if (host) { strlcpy(my_state->host, host, sizeof my_state->host); } if (gettimeofday(&tv, NULL) == -1) { rs_log_error("gettimeofday failed: %s", strerror(errno)); return EXIT_DISTCC_FAILED; } my_state->curr_phase = state; rs_trace("note state %d, file \"%s\", host \"%s\"", state, source_file ? source_file : "(NULL)", host ? host : "(NULL)"); if ((ret = dcc_open_state(&fd, fname))) { free(fname); return ret; } if ((ret = dcc_write_state(fd))) { dcc_close(fd); free(fname); return ret; } dcc_close(fd); free(fname); return 0; } void dcc_note_state_slot(int slot, enum dcc_host target) { if (direct_my_state(target)) my_state->slot = slot; } /** Point 'my_state' to the local or remote host state information, depending on target. Return 'my_state' pointer. **/ static struct dcc_task_state *direct_my_state(const enum dcc_host target) { switch (target) { case DCC_LOCAL: my_state = &local_state; break; case DCC_REMOTE: my_state = &remote_state; break; case DCC_UNKNOWN: break; } if (!my_state) rs_log_error("my_state == NULL"); return my_state; } distcc-3.4/src/state.h000066400000000000000000000052341404653710500147220ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef _DISTCC_STATE_H #define _DISTCC_STATE_H #ifdef __cplusplus extern "C" { #endif int dcc_get_state_dir (char **p); int dcc_open_state_file (int *p_fd); /* Note that these must be in the order in which they are encountered * for the state file to work properly. It's OK if some are skipped * though. */ enum dcc_phase { DCC_PHASE_STARTUP, DCC_PHASE_BLOCKED, DCC_PHASE_CONNECT, DCC_PHASE_CPP, DCC_PHASE_SEND, DCC_PHASE_COMPILE, /**< or unknown */ DCC_PHASE_RECEIVE, DCC_PHASE_DONE /**< MUST be last */ }; enum dcc_host { DCC_UNKNOWN, DCC_LOCAL, DCC_REMOTE }; int dcc_note_state (enum dcc_phase state, const char *file, const char *host, enum dcc_host); void dcc_remove_state_file (void); extern const char *dcc_state_prefix; #define DCC_STATE_MAGIC 0x44494800 /* DIH\0 */ /** * State and history of a distcc process. Used in memory and also in native * format for binary state files. * * This should be <4kB, so that it will normally be written out * atomically. **/ struct dcc_task_state { size_t struct_size; unsigned long magic; unsigned long cpid; /**< Client pid */ char file[128]; /**< Input filename */ char host[128]; /**< Destination host description */ int slot; /**< Which CPU slot for this host */ enum dcc_phase curr_phase; /** In memory, point to the next in a list of all tasks. In the * file, undefined. */ struct dcc_task_state *next; }; const char *dcc_get_phase_name(enum dcc_phase); void dcc_note_state_slot(int slot, enum dcc_host target); #ifdef __cplusplus } #endif #endif /* _DISTCC_STATE_H */ distcc-3.4/src/stats.c000066400000000000000000000362671404653710500147450ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Thomas Kho */ #include #include #include #include #include #include #include #include #include #include #include #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "dopt.h" #include "stats.h" #include "srvnet.h" #include "util.h" #include "netutil.h" #include "fcntl.h" #include "daemon.h" int dcc_statspipe[2]; #define MAX_FILENAME_LEN 1024 /* in prefork.c */ void dcc_manage_kids(int listen_fd); struct stats_s { int counters[STATS_ENUM_MAX]; int kids_avg[3]; /* 1, 5, 15m */ int longest_job_time; char longest_job_name[MAX_FILENAME_LEN]; char longest_job_compiler[MAX_FILENAME_LEN]; int io_rate; /* read/write sectors per second */ int compile_timeseries[300]; /* 300 3-sec time intervals */ /* * linked list of statsdata. This is to keep the last * couple of minutes of compile stats for analysis. */ struct statsdata *sd_root; } dcc_stats; struct statsdata { enum stats_e type; struct statsdata *next; /* used only for STATS_COMPILE_OK */ struct timeval start; struct timeval stop; int time; char filename[MAX_FILENAME_LEN]; char compiler[MAX_FILENAME_LEN]; }; const char *stats_text[20] = { "TCP_ACCEPT", "REJ_BAD_REQ", "REJ_OVERLOAD", "COMPILE_OK", "COMPILE_ERROR", "COMPILE_TIMEOUT", "CLI_DISCONN", "OTHER" }; /* Call this to initialize stats */ int dcc_stats_init() { if (arg_stats) { if (pipe(dcc_statspipe) == -1) { return -1; } } memset(&dcc_stats, 0, sizeof(dcc_stats)); return 0; } /* In the preforking model call this to initialize stats for forked children */ void dcc_stats_init_kid() { if (arg_stats) { close(dcc_statspipe[0]); } } /** * Logs countable event of type e to stats server **/ void dcc_stats_event(enum stats_e e) { if (arg_stats) { struct statsdata sd; memset(&sd, 0, sizeof(sd)); sd.type = e; dcc_writex(dcc_statspipe[1], &sd, sizeof(sd)); } } /** * Logs a completed job to stats server **/ void dcc_stats_compile_ok(char *compiler, char *filename, struct timeval start, struct timeval stop, int time_usec) { if (arg_stats) { struct statsdata sd; memset(&sd, 0, sizeof(sd)); sd.type = STATS_COMPILE_OK; /* also send compiler, filename & runtime */ memcpy(&(sd.start), &start, sizeof(struct timeval)); memcpy(&(sd.stop), &stop, sizeof(struct timeval)); sd.time = time_usec; strncpy(sd.filename, filename, MAX_FILENAME_LEN - 1); strncpy(sd.compiler, compiler, MAX_FILENAME_LEN - 1); dcc_writex(dcc_statspipe[1], &sd, sizeof(sd)); } } /* * tracks the compile times */ static void dcc_stats_update_compile_times(struct statsdata *sd) { struct statsdata *prev_sd = NULL; struct statsdata *curr_sd = NULL; struct statsdata *new_sd; time_t two_min_ago = time(NULL) - 120; /* Record file with longest runtime */ if (dcc_stats.longest_job_time < sd->time) { dcc_stats.longest_job_time = sd->time; strncpy(dcc_stats.longest_job_name, sd->filename, MAX_FILENAME_LEN); strncpy(dcc_stats.longest_job_compiler, sd->compiler, MAX_FILENAME_LEN); } /* store stats for compile time calcs */ new_sd = malloc(sizeof(struct statsdata)); memcpy(new_sd, sd, sizeof(struct statsdata)); new_sd->next = dcc_stats.sd_root; dcc_stats.sd_root = new_sd; /* drop elements older than 2min */ curr_sd = dcc_stats.sd_root; while (curr_sd != NULL) { if (curr_sd->stop.tv_sec < two_min_ago) { /* delete the stat */ if (prev_sd == NULL) { dcc_stats.sd_root = curr_sd->next; } else { prev_sd->next = curr_sd->next; } free(curr_sd); curr_sd = prev_sd->next; } else { /* we didn't delete anything. move forward by one */ prev_sd = curr_sd; curr_sd = curr_sd->next; } } } /* caclulate the avg kids used */ static void dcc_stats_calc_kid_avg(void) { static int total_5m[5] = {0}; static int total_15m[15] = {0}; static int pos_5m = 0; static int pos_15m = 0; static time_t last = 0; struct timeval now; struct timeval time_p; struct statsdata *curr_sd; int total_running = 0; int running = 0; int t = 0; int x = 0; int total = 0; gettimeofday(&now, NULL); /* calculate average kids used over the last minute */ if ((now.tv_sec - 60) >= last) { /* we look at 1min ago back to 2 min ago because we only register * compiles when they complete. If we look right now, we miss all * the current compiles that haven't completed. */ for (t=60; t<120; t++) { time_p.tv_usec = now.tv_usec; time_p.tv_sec = now.tv_sec - t; running = 0; curr_sd = dcc_stats.sd_root; while (curr_sd != NULL) { if ((dcc_timecmp(curr_sd->start, time_p) <= 0) && (dcc_timecmp(curr_sd->stop, time_p) >= 0)) { running++; } curr_sd = curr_sd->next; } total_running += running; } dcc_stats.kids_avg[0] = total_running / 60; /* populate 5m kid avgs */ total_5m[pos_5m] = dcc_stats.kids_avg[0]; pos_5m++; if (pos_5m >= 5) pos_5m = 0; /* calc 5m kid avg */ total = 0; for (x=0; x<5; x++) total += total_5m[x]; dcc_stats.kids_avg[1] = total/5; /* populate 15m kid avgs */ total_15m[pos_15m] = dcc_stats.kids_avg[0]; pos_15m++; if (pos_15m >= 15) pos_15m = 0; /* calc 15m kid avg */ total = 0; for (x=0; x<15; x++) total += total_15m[x]; dcc_stats.kids_avg[2] = total/15; last = now.tv_sec; } } /* * Updates a running total of compiles in the last 1, 5, 15 minutes * * Returns the oldest slot */ static int dcc_stats_update_running_total(int increment) { static int prev_slot; static time_t last = 0; static int total = 0; int i; int cur_slot; int *const cts = dcc_stats.compile_timeseries; time_t now = time(NULL); cur_slot = (now / 3) % 300; if (last + 900 < now) { /* reset all stats; last call was >15 min ago */ for (i = 0; i < 300; i++) cts[i] = total; prev_slot = cur_slot; } if (prev_slot != cur_slot) { /* different timeslot, so set the interval [prev, cur) */ for (i = (prev_slot)%300; i != cur_slot; i = (i+1)%300) { cts[i] = total; } prev_slot = cur_slot; } total += increment; last = now; return cur_slot; } static int *dcc_stats_get_compile_totals(void) { int cur_slot; static int ct[3]; /* 1, 5, 15 min compile totals */ int *const cts = dcc_stats.compile_timeseries; cur_slot = dcc_stats_update_running_total(0); ct[0] = cts[(cur_slot + 299)%300] - cts[(cur_slot+280)%300]; ct[1] = cts[(cur_slot + 299)%300] - cts[(cur_slot+200)%300]; ct[2] = cts[(cur_slot + 299)%300] - cts[(cur_slot+1)%300]; return ct; } /* Sets dcc_stats.io_rate at most 50 secs */ static void dcc_stats_minutely_update(void) { static int prev_io_tot = -1; static time_t last = 0; int n_reads, n_writes; time_t now = time(NULL); if (last + 50 < now) { dcc_get_disk_io_stats(&n_reads, &n_writes); if (prev_io_tot == -1) dcc_stats.io_rate = -1; else dcc_stats.io_rate = (n_reads + n_writes - prev_io_tot) / (now - last); prev_io_tot = n_reads + n_writes; last = now; } } static long dcc_get_tmpdirinfo(void) { const char *tmp_dir; struct statvfs buf; if (dcc_get_tmp_top(&tmp_dir) != 0) return -1; if (statvfs(tmp_dir, &buf) != 0) return -1; if (buf.f_bsize >= 1024) return buf.f_bavail * (buf.f_bsize / 1024) / 1024; else return (buf.f_bavail * buf.f_bsize) / (1024 * 1024); } /** * Accept a connection on the stats port and send the reply, regardless of data * that the client sends us. **/ static void dcc_service_stats_request(int http_fd) { int acc_fd; int *ct; int num_D; int max_RSS; char *max_RSS_name; size_t reply_len; char challenge[1024]; char reply[2048]; struct dcc_sockaddr_storage cli_addr; socklen_t cli_len = sizeof(cli_addr); double loadavg[3]; int free_space_mb; ssize_t ret; const char replytemplate[] = "\ HTTP/1.0 200 OK\n\ Content-Type: text/plain\n\ Connection: close\n\n\ argv /distccd\n\ \n\ dcc_tcp_accept %d\n\ dcc_rej_bad_req %d\n\ dcc_rej_overload %d\n\ dcc_compile_ok %d\n\ dcc_compile_error %d\n\ dcc_compile_timeout %d\n\ dcc_cli_disconnect %d\n\ dcc_other %d\n\ dcc_longest_job %s\n\ dcc_longest_job_compiler %s\n\ dcc_longest_job_time_msecs %d\n\ dcc_max_kids %d\n\ dcc_avg_kids1 %d\n\ dcc_avg_kids2 %d\n\ dcc_avg_kids3 %d\n\ dcc_current_load %d\n\ dcc_load1 %1.2lf\n\ dcc_load2 %1.2lf\n\ dcc_load3 %1.2lf\n\ dcc_num_compiles1 %d\n\ dcc_num_compiles2 %d\n\ dcc_num_compiles3 %d\n\ dcc_num_procstate_D %d\n\ dcc_max_RSS %d\n\ dcc_max_RSS_name %s\n\ dcc_io_rate %d\n\ dcc_free_space %d MB\n\ \n"; dcc_stats_minutely_update(); /* force update to get fresh disk io data */ ct = dcc_stats_get_compile_totals(); dcc_getloadavg(loadavg); free_space_mb = dcc_get_tmpdirinfo(); dcc_get_proc_stats(&num_D, &max_RSS, &max_RSS_name); if (dcc_stats.longest_job_name[0] == 0) strcpy(dcc_stats.longest_job_name, "none"); if (dcc_stats.longest_job_compiler[0] == 0) strcpy(dcc_stats.longest_job_compiler, "none"); acc_fd = accept(http_fd, (struct sockaddr *) &cli_addr, &cli_len); if (dcc_check_client((struct sockaddr *)&cli_addr, (int) cli_len, opt_allowed) == 0) { reply_len = snprintf(reply, 2048, replytemplate, dcc_stats.counters[STATS_TCP_ACCEPT], dcc_stats.counters[STATS_REJ_BAD_REQ], dcc_stats.counters[STATS_REJ_OVERLOAD], dcc_stats.counters[STATS_COMPILE_OK], dcc_stats.counters[STATS_COMPILE_ERROR], dcc_stats.counters[STATS_COMPILE_TIMEOUT], dcc_stats.counters[STATS_CLI_DISCONN], dcc_stats.counters[STATS_OTHER], dcc_stats.longest_job_name, dcc_stats.longest_job_compiler, dcc_stats.longest_job_time, dcc_max_kids, dcc_stats.kids_avg[0], dcc_stats.kids_avg[1], dcc_stats.kids_avg[2], dcc_getcurrentload(), loadavg[0], loadavg[1], loadavg[2], ct[0], ct[1], ct[2], num_D, max_RSS, max_RSS_name, dcc_stats.io_rate, free_space_mb); dcc_set_nonblocking(acc_fd); ret = read(acc_fd, challenge, 1024); /* empty the receive queue */ if (ret < 0) rs_log_info("read on acc_fd failed"); dcc_writex(acc_fd, reply, reply_len); } /* Don't think we need this to prevent RST anymore, since we read() now */ #if 0 shutdown(acc_fd, SHUT_WR); /* prevent connection reset */ #endif dcc_close(acc_fd); } /** * Process a packet of stats data **/ static void dcc_stats_process(struct statsdata *sd) { if (sd->type > STATS_ENUM_MAX) { /* Got a bad message */ return; } switch (sd->type) { case STATS_TCP_ACCEPT: case STATS_REJ_BAD_REQ: case STATS_REJ_OVERLOAD: break; case STATS_COMPILE_OK: dcc_stats_update_compile_times(sd); /* fallthrough */ case STATS_COMPILE_ERROR: case STATS_COMPILE_TIMEOUT: case STATS_CLI_DISCONN: /* We want to update the running compile total for all jobs that * non-trivially tax the CPU */ dcc_stats_update_running_total(1); default: ; } dcc_stats.counters[sd->type]++; } /** * Collect runtime statistics from kids and serve them via HTTP * Also, maintains the pool of kids. **/ int dcc_stats_server(int listen_fd) { int http_fd, max_fd; int i, ret; fd_set fds, fds_master; struct statsdata sd; struct timeval timeout; /* clear stats data */ for (i = 0; i < STATS_ENUM_MAX; i++) dcc_stats.counters[i] = 0; dcc_stats.longest_job_time = -1; dcc_stats.longest_job_name[0] = 0; dcc_stats.io_rate = -1; if ((ret = dcc_socket_listen(arg_stats_port, &http_fd, opt_listen_addr)) != 0) { return ret; } rs_log_info("HTTP server started on port %d\n", arg_stats_port); /* We don't want children to inherit this FD */ fcntl(http_fd, F_SETFD, FD_CLOEXEC); max_fd = (http_fd > dcc_statspipe[0]) ? (http_fd + 1) : (dcc_statspipe[0] + 1); FD_ZERO(&fds_master); FD_SET(dcc_statspipe[0], &fds_master); FD_SET(http_fd, &fds_master); while (1) { dcc_stats_minutely_update(); dcc_stats_calc_kid_avg(); timeout.tv_sec = 60; timeout.tv_usec = 0; fds = fds_master; ret = select(max_fd, &fds, NULL, NULL, &timeout); if (ret != -1) { if (FD_ISSET(dcc_statspipe[0], &fds)) { /* Received stats report from a child */ if (read(dcc_statspipe[0], &sd, sizeof(sd)) != -1) { dcc_stats_process(&sd); } } if (FD_ISSET(http_fd, &fds)) { /* Received request on stats reporting port */ dcc_service_stats_request(http_fd); } } else { if (errno == EINTR) { /* Interrupted -- SIGCHLD? */ } } dcc_manage_kids(listen_fd); } } distcc-3.4/src/stats.h000066400000000000000000000030601404653710500147330ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * Author: Thomas Kho */ #ifndef _DISTCC_STATS_H #define _DISTCC_STATS_H #ifdef __cplusplus extern "C" { #endif enum stats_e { STATS_TCP_ACCEPT, STATS_REJ_BAD_REQ, STATS_REJ_OVERLOAD, STATS_COMPILE_OK, STATS_COMPILE_ERROR, STATS_COMPILE_TIMEOUT, STATS_CLI_DISCONN, STATS_OTHER, STATS_ENUM_MAX }; extern const char *stats_text[20]; int dcc_stats_init(void); void dcc_stats_init_kid(void); int dcc_stats_server(int listen_fd); void dcc_stats_event(enum stats_e e); void dcc_stats_compile_ok(char *compiler, char *filename, struct timeval start, struct timeval stop, int time_usec); #ifdef __cplusplus } #endif #endif /* _DISTCC_STATS_H */ distcc-3.4/src/stringmap.c000066400000000000000000000120531404653710500155760ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include "stringmap.h" #ifndef NULL #define NULL 0 #endif #ifndef PATH_MAX #define PATH_MAX 4096 #endif /* Load the given list of strings into the key/value map. * The key for each string is the numFinalWordsToMatch of the string; * the value for each string is the entire string. * FIXME: doesn't work for utf-8 strings, since it scans raw chars for / */ stringmap_t *stringmap_load(const char *filename, int numFinalWordsToMatch) { stringmap_t *result; FILE *fp; char buf[2*PATH_MAX]; int n; result = calloc(1, sizeof(*result)); if (!result) return NULL; result->numFinalWordsToMatch = numFinalWordsToMatch; fp = fopen(filename, "r"); if (!fp) { free(result); return NULL; } n=0; while (fgets(buf, sizeof(buf), fp)) n++; result->n = n; result->map = malloc(n * sizeof(result->map[0])); rewind(fp); n=0; while (fgets(buf, sizeof(buf), fp)) { int pos, w; int len = strlen(buf); /* strip trailing \n */ if (len > 0 && buf[len-1] == '\n') { buf[len-1] = 0; len--; } /* set pos to the start of the significant part of the string */ for (pos=len-1, w=0; pos>0; pos--) { if (buf[pos] == '/') { w++; if (w >= numFinalWordsToMatch) { pos++; break; } } } result->map[n].value = strdup(buf); result->map[n].key = strdup(buf+pos); n++; } fclose(fp); return result; } const char *stringmap_lookup(const stringmap_t *map, const char *string) { int i, w; int len = strlen(string); int pos; for (pos=len-1, w=0; pos>0; pos--) { if (string[pos] == '/') { w++; if (w >= map->numFinalWordsToMatch) { pos++; break; } } } for (i=0; in; i++) { /*printf("Comparing %s and %s\n", map->map[i].key, string+pos);*/ if (!strcmp(map->map[i].key, string+pos)) return map->map[i].value; } return NULL; } #if 0 void dumpMap(stringmap_t *sm) { int i; printf("map has %d elements, and numFinalWordsToMatch is %d\n", sm->n, sm->numFinalWordsToMatch); for (i=0; i < sm->n; i++) { printf("row %d: key %s, value %s\n", i, sm->map[i].key, sm->map[i].value); } } #define verifyMap(sm, a, b) { \ const char *c = stringmap_lookup(sm, a); \ if (!b) \ assert(!c); \ else { \ assert(c); \ assert(!strcmp(b, c)); } } int main(int argc, char **argv) { FILE *fp; stringmap_t *sm; fp = fopen("stringmap_test.dat", "w"); fprintf(fp, "/foo/bar/bletch\n"); fclose(fp); sm = stringmap_load("stringmap_test.dat", 1); dumpMap(sm); verifyMap(sm, "/bar/bletch", "/foo/bar/bletch"); verifyMap(sm, "bletch", "/foo/bar/bletch"); verifyMap(sm, "/whatever/bletch", "/foo/bar/bletch"); verifyMap(sm, "baz", NULL); verifyMap(sm, "/foo/bar/bletch", "/foo/bar/bletch"); fp = fopen("stringmap_test.dat", "w"); fprintf(fp, "/usr/bin/gcc\n"); fprintf(fp, "/usr/bin/cc\n"); fclose(fp); sm = stringmap_load("stringmap_test.dat", 1); dumpMap(sm); verifyMap(sm, "/usr/bin/gcc", "/usr/bin/gcc"); verifyMap(sm, "/usr/bin/cc", "/usr/bin/cc"); verifyMap(sm, "gcc", "/usr/bin/gcc"); verifyMap(sm, "cc", "/usr/bin/cc"); verifyMap(sm, "g77", NULL); fp = fopen("stringmap_test.dat", "w"); fprintf(fp, "/usr/bin/i686-blah-blah/gcc\n"); fprintf(fp, "/usr/bin/i386-blah-blah/gcc\n"); fclose(fp); sm = stringmap_load("stringmap_test.dat", 2); dumpMap(sm); verifyMap(sm, "/usr/bin/i686-blah-blah/gcc", "/usr/bin/i686-blah-blah/gcc"); verifyMap(sm, "/usr/bin/i386-blah-blah/gcc", "/usr/bin/i386-blah-blah/gcc"); verifyMap(sm, "i686-blah-blah/gcc", "/usr/bin/i686-blah-blah/gcc"); verifyMap(sm, "i386-blah-blah/gcc", "/usr/bin/i386-blah-blah/gcc"); verifyMap(sm, "gcc", NULL); verifyMap(sm, "g77", NULL); return 0; } #endif distcc-3.4/src/stringmap.h000066400000000000000000000030171404653710500156030ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef STRINGMAP_H #define STRINGMAP_H typedef struct { /* the strings, and what they map to */ struct { char *key; char *value; } *map; /* number of elements in map */ int n; /* if nonzero, ignore all but this many trailing words, * where words are separated by the '/' char * Example: * comparison num=1 num=2 num=3 * a/b/z =? 1/y/z match no no * a/b/z =? 1/b/z match match no */ int numFinalWordsToMatch; } stringmap_t; stringmap_t *stringmap_load(const char *filename, int numFinalWordsToMatch); const char *stringmap_lookup(const stringmap_t *map, const char *string); #endif distcc-3.4/src/strip.c000066400000000000000000000137511404653710500147410ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2008 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** * Strip arguments like -D and -I from a command line, because they do * not need to be passed across the wire. This covers options for * both the preprocess and link phases, since they should never happen * remotely. * * In the case where we inadvertently do cause preprocessing to happen * remotely, it is possible that omitting these options will make * failure more obvious and avoid false success. * * Giving -L on a compile-only command line is a bit weird, but it is * observed to happen in Makefiles that are not strict about CFLAGS vs * LDFLAGS, etc. * * NOTE: gcc-3.2's manual in the "preprocessor options" section * describes some options, such as -d, that only take effect when * passed directly to cpp. When given to gcc they have different * meanings. * * The value stored in '*out_argv' is malloc'd, but the arguments that * are pointed to by that array are aliased with the values pointed * to by 'from'. The caller is responsible for calling free() on * '*out_argv'. **/ int dcc_strip_local_args(char **from, char ***out_argv) { char **to; int from_i, to_i; int from_len; from_len = dcc_argv_len(from); *out_argv = to = malloc((from_len + 1) * sizeof (char *)); if (!to) { rs_log_error("failed to allocate space for arguments"); return EXIT_OUT_OF_MEMORY; } /* skip through argv, copying all arguments but skipping ones that * ought to be omitted */ for (from_i = to_i = 0; from[from_i]; from_i++) { if (str_equal("-D", from[from_i]) || str_equal("-I", from[from_i]) || str_equal("-U", from[from_i]) || str_equal("-L", from[from_i]) || str_equal("-l", from[from_i]) || str_equal("-MF", from[from_i]) || str_equal("-MT", from[from_i]) || str_equal("-MQ", from[from_i]) || str_equal("-include", from[from_i]) || str_equal("-imacros", from[from_i]) || str_equal("-iprefix", from[from_i]) || str_equal("-iwithprefix", from[from_i]) || str_equal("-isystem", from[from_i]) || str_equal("-iwithprefixbefore", from[from_i]) || str_equal("-idirafter", from[from_i])) { /* skip next word, being option argument */ if (from[from_i+1]) from_i++; } else if (str_startswith("-Wp,", from[from_i]) || str_startswith("-Wl,", from[from_i]) || str_startswith("-D", from[from_i]) || str_startswith("-U", from[from_i]) || str_startswith("-I", from[from_i]) || str_startswith("-l", from[from_i]) || str_startswith("-L", from[from_i]) || str_startswith("-MF", from[from_i]) || str_startswith("-MT", from[from_i]) || str_startswith("-MQ", from[from_i]) || str_startswith("-isystem", from[from_i]) || str_startswith("-stdlib", from[from_i])) { /* Something like "-DNDEBUG" or * "-Wp,-MD,.deps/nsinstall.pp". Just skip this word */ ; } else if (str_equal("-undef", from[from_i]) || str_equal("-nostdinc", from[from_i]) || str_equal("-nostdinc++", from[from_i]) || str_equal("-MD", from[from_i]) || str_equal("-MMD", from[from_i]) || str_equal("-MG", from[from_i]) || str_equal("-MP", from[from_i])) { /* Options that only affect cpp; skip */ ; } else { to[to_i++] = from[from_i]; } } /* NULL-terminate */ to[to_i] = NULL; dcc_trace_argv("result", to); return 0; } /** * Remove "-o" options from argument list. * * This is used when running the preprocessor, when we just want it to write * to stdout, which is the default when no -o option is specified. * * Structurally similar to dcc_strip_local_args() **/ int dcc_strip_dasho(char **from, char ***out_argv) { char **to; int from_i, to_i; int from_len; from_len = dcc_argv_len(from); *out_argv = to = malloc((from_len + 1) * sizeof (char *)); if (!to) { rs_log_error("failed to allocate space for arguments"); return EXIT_OUT_OF_MEMORY; } /* skip through argv, copying all arguments but skipping ones that * ought to be omitted */ for (from_i = to_i = 0; from[from_i]; ) { if (!strcmp(from[from_i], "-o")) { /* skip "-o FILE" */ from_i += 2; } else if (str_startswith("-o", from[from_i])) { /* skip "-oFILE" */ from_i++; } else { to[to_i++] = from[from_i++]; } } /* NULL-terminate */ to[to_i] = NULL; dcc_trace_argv("result", to); return 0; } distcc-3.4/src/tempfile.c000066400000000000000000000264571404653710500154140ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "More computing sins are committed in the name of * efficiency (without necessarily achieving it) than * for any other single reason - including blind * stupidity." -- W.A. Wulf */ #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "snprintf.h" #include "exitcode.h" #ifdef __CYGWIN32__ #define NOGDI #define WIN32_LEAN_AND_MEAN #include #endif /** * @file * * Routines for naming, generating and removing temporary files. * * Temporary files are stored under $TMPDIR or /tmp. * * From 2.10 on, our lock and state files are not stored in there. * * It would be nice if we could use a standard function, but I don't * think any of them are adequate: we need to control the extension * and know the filename. tmpfile() does not give back the filename. * tmpnam() is insecure. mkstemp() does not allow us to set the * extension. * * It sucks that there is no standard function. The implementation * below is inspired by the __gen_tempname() code in glibc; hopefully * it will be secure on all platforms. * * We need to touch the filename before running commands on it, * because we cannot be sure that the compiler will create it * securely. * * Even with all this, we are not necessarily secure in the presence * of a tmpreaper if the attacker can play timing tricks. However, * since we are not setuid and since there is no completely safe way * to write tmpreapers, this is left alone for now. * * If you're really paranoid, you should just use per-user TMPDIRs. * * @sa http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/avoid-race.html#TEMPORARY-FILES **/ /** * Create the directory @p path, and register it for deletion when this * compilation finished. If it already exists as a directory * we succeed, but we don't register the directory for deletion. **/ int dcc_mk_tmpdir(const char *path) { struct stat buf; int ret; if (stat(path, &buf) == -1) { if (mkdir(path, 0777) == -1) { return EXIT_IO_ERROR; } if ((ret = dcc_add_cleanup(path))) { /* bailing out */ rmdir(path); return ret; } } else { /* we could stat the file successfully; if it's a directory, * all is well, but we should not it delete later, since we did * not make it. */ if (S_ISDIR(buf.st_mode)) { return 0; } else { rs_log_error("mkdir '%s' failed: %s", path, strerror(errno)); return EXIT_IO_ERROR; } } return 0; } /** * Create the directory @p path. If it already exists as a directory * we succeed. **/ int dcc_mkdir(const char *path) { if ((mkdir(path, 0777) == -1) && (errno != EEXIST)) { rs_log_error("mkdir '%s' failed: %s", path, strerror(errno)); return EXIT_IO_ERROR; } return 0; } #ifndef HAVE_MKDTEMP static char* mkdtemp(char *pattern) { /* We could try this a few times if we wanted */ char* path = mktemp(pattern); if (path == NULL) return NULL; if (mkdir(path, 0700) == 0) return path; return NULL; } #endif /* This function creates a temporary directory, to be used for * all (input) files during one compilation. * The name of the directory is stored in @p tempdir, which is * malloc'ed here. The caller is responsible for freeing it. * The format of the directory name is /distccd_ * Returns the new temp dir in tempdir. */ int dcc_get_new_tmpdir(char **tempdir) { int ret; const char *tmp_top; char *s; if ((ret = dcc_get_tmp_top(&tmp_top))) { return ret; } if (asprintf(&s, "%s/distccd_XXXXXX", tmp_top) == -1) return EXIT_OUT_OF_MEMORY; if ((*tempdir = mkdtemp(s)) == 0) { return EXIT_IO_ERROR; } if ((ret = dcc_add_cleanup(s))) { /* bailing out */ rmdir(s); return ret; } return 0; } /* This function returns a directory-name, it does not end in a slash. */ int dcc_get_tmp_top(const char **p_ret) { #ifdef __CYGWIN32__ int ret; char *s = malloc(MAXPATHLEN+1); int f,ln; GetTempPath(MAXPATHLEN+1,s); /* Convert slashes */ for (f = 0, ln = strlen(s); f != ln; f++) if (s[f]=='\\') s[f]='/'; /* Delete trailing slashes -- but leave one slash if s is all slashes */ for (f = strlen(s)-1; f > 0 && s[f] == '/'; f--) s[f]='\0'; if ((ret = dcc_add_cleanup(s))) { free(s); return ret; } *p_ret = s; return 0; #else const char *d; d = getenv("TMPDIR"); if (!d || d[0] == '\0') { *p_ret = "/tmp"; return 0; } else { *p_ret = d; return 0; } #endif } /** * Create the full @path. If it already exists as a directory * we succeed. */ int dcc_mk_tmp_ancestor_dirs(const char *path) { char *copy = 0; char *p; int ret; copy = strdup(path); if (copy == NULL) { return EXIT_OUT_OF_MEMORY; } dcc_truncate_to_dirname(copy); if (copy[0] == '\0') { free(copy); return 0; } /* First, let's try and see if all parent directories * exist already */ if ((ret = dcc_mk_tmpdir(copy)) == 0) { free(copy); return 0; } /* This is the "pessimistic" algorithm for making directories, * which assumes that most directories that it's asked to create * do not exist. It's expensive for very deep directories; * it tries to make all the directories from the root to that * dir. However, it only gets called if we tried to make a dir * in a directory and failed; which means we only get called * once per directory. */ /* Body of this loop does not execute when *p=='\0'; * therefore the very last component of the directory does not * get created here. */ for (p = copy; *p != '\0'; ++p) { if (*p == '/' && p != copy) { *p = '\0'; if ((ret = dcc_mk_tmpdir(copy))) { free(copy); return ret; } *p = '/'; } } ret = dcc_mk_tmpdir(copy); free(copy); return ret; } /** * Return a static string holding DISTCC_DIR, or ~/.distcc. * The directory is created if it does not exist. **/ int dcc_get_top_dir(char **path_ret) { char *env; static char *cached; int ret; if (cached) { *path_ret = cached; return 0; } if ((env = getenv("DISTCC_DIR"))) { if ((cached = strdup(env)) == NULL) { return EXIT_OUT_OF_MEMORY; } else { *path_ret = cached; return 0; } } if ((env = getenv("HOME")) == NULL) { rs_log_warning("HOME is not set; can't find distcc directory"); return EXIT_BAD_ARGUMENTS; } if (asprintf(path_ret, "%s/.distcc", env) == -1) { rs_log_error("asprintf failed"); return EXIT_OUT_OF_MEMORY; } ret = dcc_mkdir(*path_ret); if (ret == 0) cached = *path_ret; return ret; } /** * Return a subdirectory of the DISTCC_DIR of the given name, making * sure that the directory exists. **/ int dcc_get_subdir(const char *name, char **dir_ret) { int ret; char *topdir; if ((ret = dcc_get_top_dir(&topdir))) return ret; if (asprintf(dir_ret, "%s/%s", topdir, name) == -1) { rs_log_error("asprintf failed"); return EXIT_OUT_OF_MEMORY; } return dcc_mkdir(*dir_ret); } int dcc_get_lock_dir(char **dir_ret) { static char *cached; int ret; if (cached) { *dir_ret = cached; return 0; } else { ret = dcc_get_subdir("lock", dir_ret); if (ret == 0) cached = *dir_ret; return ret; } } int dcc_get_state_dir(char **dir_ret) { static char *cached; int ret; if (cached) { *dir_ret = cached; return 0; } else { ret = dcc_get_subdir("state", dir_ret); if (ret == 0) cached = *dir_ret; return ret; } } /** * Create a file inside the temporary directory and register it for * later cleanup, and return its name. * * The file will be reopened later, possibly in a child. But we know * that it exists with appropriately tight permissions. **/ int dcc_make_tmpnam(const char *prefix, const char *suffix, char **name_ret) { char *s = NULL; const char *tempdir; int ret; unsigned long random_bits; int fd; if ((ret = dcc_get_tmp_top(&tempdir))) return ret; if (access(tempdir, W_OK|X_OK) == -1) { rs_log_error("can't use TMPDIR \"%s\": %s", tempdir, strerror(errno)); return EXIT_IO_ERROR; } random_bits = (unsigned long) getpid() << 16; # if HAVE_GETTIMEOFDAY { struct timeval tv; gettimeofday(&tv, NULL); random_bits ^= tv.tv_usec << 16; random_bits ^= tv.tv_sec; } # else random_bits ^= time(NULL); # endif #if 0 random_bits = 0; /* FOR TESTING */ #endif do { free(s); if (asprintf(&s, "%s/%s_%08lx%s", tempdir, prefix, random_bits & 0xffffffffUL, suffix) == -1) return EXIT_OUT_OF_MEMORY; /* Note that if the name already exists as a symlink, this * open call will fail. * * The permissions are tight because nobody but this process * and our children should do anything with it. */ fd = open(s, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd == -1) { /* try again */ rs_trace("failed to create %s: %s", s, strerror(errno)); random_bits += 7777; /* fairly prime */ continue; } if (close(fd) == -1) { /* huh? */ rs_log_warning("failed to close %s: %s", s, strerror(errno)); return EXIT_IO_ERROR; } break; } while (1); if ((ret = dcc_add_cleanup(s))) { /* bailing out */ unlink(s); free(s); return ret; } *name_ret = s; return 0; } distcc-3.4/src/timefile.c000066400000000000000000000075541404653710500154020ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * @brief Track timeouts by setting the mtime of a file. * * distcc needs to set timeouts to backoff from unreachable hosts. As a very * simple and robust way of keeping track of this, we simply touch a file in * our state directory, whenever we fail to connect. Future invocations can * look at how recently the host failed when deciding whether to use it again. **/ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "snprintf.h" #include "lock.h" #include "timefile.h" /** * Record the current time against the specified function and host. **/ int dcc_mark_timefile(const char *lockname, const struct dcc_hostdef *host) { char *filename; int fd; int ret; if ((ret = dcc_make_lock_filename(lockname, host, 0, &filename))) return ret; if ((ret = dcc_open_lockfile(filename, &fd))) { free(filename); return ret; } /* Merely opening it with O_WRONLY is not necessarily enough to set its * mtime to the current time. */ if (write(fd, "x", 1) != 1) { rs_log_error("write to %s failed: %s", lockname, strerror(errno)); dcc_close(fd); return EXIT_IO_ERROR; } dcc_close(fd); rs_trace("mark %s", filename); free(filename); return 0; } /** * Remove the specified timestamp. **/ int dcc_remove_timefile(const char *lockname, const struct dcc_hostdef *host) { char *filename; int ret = 0; if ((ret = dcc_make_lock_filename(lockname, host, 0, &filename))) return ret; if (unlink(filename) == 0) { rs_trace("remove %s", filename); } else { if (errno == ENOENT) { /* it's ok if somebody else already removed it */ } else { rs_log_error("unlink %s failed: %s", filename, strerror(errno)); ret = EXIT_IO_ERROR; } } free(filename); return 0; } /** * Return the mtime for a timestamp file. * * If the timestamp doesn't exist then we count it as time zero. **/ int dcc_check_timefile(const char *lockname, const struct dcc_hostdef *host, time_t *mtime) { char *filename; struct stat sb; int ret; if ((ret = dcc_make_lock_filename(lockname, host, 0, &filename))) return ret; if (stat(filename, &sb) == -1) { *mtime = (time_t) 0; if (errno == ENOENT) { /* just no record for this file; that's fine. */ free(filename); return 0; } else { rs_log_error("stat %s failed: %s", filename, strerror(errno)); free(filename); return EXIT_IO_ERROR; } } *mtime = sb.st_mtime; free(filename); return 0; } distcc-3.4/src/timefile.h000066400000000000000000000024061404653710500153760ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* timefile.c */ int dcc_mark_timefile(const char *lockname, const struct dcc_hostdef *host); int dcc_remove_timefile(const char *lockname, const struct dcc_hostdef *host); int dcc_check_timefile(const char *lockname, const struct dcc_hostdef *host, time_t *mtime); distcc-3.4/src/timeval.c000066400000000000000000000035031404653710500152330ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * struct timeval subtraction. * * Copyright (C) 1991-2013 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include "timeval.h" /* Subtract the `struct timeval' values X and Y, storing the result in RESULT. Return 1 if the difference is negative, otherwise 0. */ int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) { /* Perform the carry for the later subtraction by updating Y. */ if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (x->tv_usec - y->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; } /* Compute the time remaining to wait. `tv_usec' is certainly positive. */ result->tv_sec = x->tv_sec - y->tv_sec; result->tv_usec = x->tv_usec - y->tv_usec; /* Return 1 if result is negative. */ return x->tv_sec < y->tv_sec; } distcc-3.4/src/timeval.h000066400000000000000000000017651404653710500152500ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * struct timeval subtraction. * * Copyright (C) 1991-2013 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); distcc-3.4/src/trace.c000066400000000000000000000250651404653710500146770ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * ecolog - Reusable application logging library. * * Copyright (C) 2000 - 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* | Finality is death. | Perfection is finality. | Nothing is perfect. | There are lumps in it. */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "snprintf.h" #include "va_copy.h" struct rs_logger_list { rs_logger_fn *fn; void *private_ptr; int private_int; int max_level; struct rs_logger_list *next; }; static struct rs_logger_list *logger_list = NULL; /* really bool */ int rs_trace_syslog = FALSE; int rs_trace_level = RS_LOG_NOTICE; #ifdef UNUSED /* nothing */ #elif defined(__GNUC__) # define UNUSED(x) x __attribute__((unused)) #elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define UNUSED(x) x #endif /* !__GNUC__ && !__LCLINT__ */ static void rs_log_va(int level, char const *fn, char const *fmt, va_list va); #if SIZEOF_SIZE_T > SIZEOF_LONG # warning size_t is larger than a long integer, values in trace messages may be wrong #endif /** * Log severity strings, if any. Must match ordering in * ::rs_loglevel. */ static const char *rs_severities[] = { "EMERGENCY! ", "ALERT! ", "CRITICAL! ", "ERROR: ", "Warning: ", "", "", "" }; /********************************************************************** * Functions for manipulating the list of loggers **********************************************************************/ void rs_remove_all_loggers(void) { struct rs_logger_list *l, *next; for (l = logger_list; l; l = next) { next = l -> next; /* save before destruction */ free(l); } logger_list = NULL; } void rs_add_logger(rs_logger_fn fn, int max_level, void *private_ptr, int private_int) { struct rs_logger_list *l; if ((l = malloc(sizeof *l)) == NULL) return; l->fn = fn; l->max_level = max_level; l->private_ptr = private_ptr; l->private_int = private_int; l->next = logger_list; logger_list = l; } /** * Remove only the logger that exactly matches the specified parameters **/ void rs_remove_logger(rs_logger_fn fn, int max_level, void *private_ptr, int private_int) { struct rs_logger_list *l, **pl; for (pl = &logger_list; *pl; pl = &((*pl)->next)) { l = *pl; if (l->fn == fn && l->max_level == max_level && l->private_ptr == private_ptr && l->private_int == private_int) { /* unhook from list by adjusting whoever points to this. */ *pl = l->next; free(l); return; } } } /** * Set the least important (i.e. largest) message severity that * will be output. */ void rs_trace_set_level(rs_loglevel level) { rs_trace_level = level; } /** * Work out a log level from a string name. * * Returns -1 for invalid names. */ int rs_loglevel_from_name(const char *name) { if (!strcmp(name, "emerg") || !strcmp(name, "emergency")) return RS_LOG_EMERG; else if (!strcmp(name, "alert")) return RS_LOG_ALERT; else if (!strcmp(name, "critical") || !strcmp(name, "crit")) return RS_LOG_CRIT; else if (!strcmp(name, "error") || !strcmp(name, "err")) return RS_LOG_ERR; else if (!strcmp(name, "warning") || !strcmp(name, "warn")) return RS_LOG_WARNING; else if (!strcmp(name, "notice") || !strcmp(name, "note")) return RS_LOG_NOTICE; else if (!strcmp(name, "info")) return RS_LOG_INFO; else if (!strcmp(name, "debug")) return RS_LOG_DEBUG; return -1; } /** * If you don't initialize a logger before first logging, then we * write to stderr by default. **/ static void rs_lazy_default(void) { static int called; if (called) return; called = 1; if (logger_list == NULL) rs_add_logger(rs_logger_file, RS_LOG_WARNING, NULL, STDERR_FILENO); } /* Heart of the matter */ static void rs_log_va(int flags, char const *caller_fn_name, char const *fmt, va_list va) { int level = flags & RS_LOG_PRIMASK; struct rs_logger_list *l; rs_lazy_default(); if (level <= rs_trace_level) for (l = logger_list; l; l = l->next) if (level <= l->max_level) { /* We need to use va_copy() here, because functions like vsprintf * may destructively modify their va_list argument, but we need * to ensure that it's still valid next time around the loop. */ va_list copied_va; VA_COPY(copied_va, va); l->fn(flags, caller_fn_name, fmt, copied_va, l->private_ptr, l->private_int); VA_COPY_END(copied_va); } } void rs_format_msg(char *buf, size_t buf_len, int flags, const char *fn, const char *fmt, va_list va) { unsigned level = flags & RS_LOG_PRIMASK; int len; const char *sv; *buf = '\0'; len = 0; if (!(flags & RS_LOG_NO_PROGRAM)) { strcpy(buf, rs_program_name); len = strlen(buf); } if (!(flags & RS_LOG_NO_PID)) { /* You might like to cache the pid, but that would cause trouble when we fork. */ sprintf(buf+len, "[%d] ", (int) getpid()); } else if (~flags & RS_LOG_NO_PROGRAM) { strcat(buf+len, ": "); } len = strlen(buf); if (!(flags & RS_LOG_NONAME) && fn) { sprintf(buf+len, "(%s) ", fn); len = strlen(buf); } sv = rs_severities[level]; if (*sv) { strcpy(buf + len, sv); len = strlen(buf); } vsnprintf(buf + len, buf_len - len, fmt, va); } /** * Called by a macro, used on platforms where we can't determine the * calling function name. */ void rs_log0_nofn(int level, char const *fmt, ...) { va_list va; va_start(va, fmt); rs_log_va(level, NULL, fmt, va); va_end(va); } void rs_log0(int level, char const *fn, char const *fmt, ...) { va_list va; va_start(va, fmt); rs_log_va(level, fn, fmt, va); va_end(va); } void rs_logger_syslog(int flags, const char *fn, char const *fmt, va_list va, void * UNUSED(private_ptr), int UNUSED(private_int)) { /* NOTE NO TRAILING NUL */ char buf[4090]; /* you're never going to want program or pid in a syslog message, * because it's redundant. */ rs_format_msg(buf, sizeof buf, flags | RS_LOG_NO_PROGRAM | RS_LOG_NO_PID, fn, fmt, va); syslog(flags & RS_LOG_PRIMASK, "%s", buf); } void rs_logger_file(int flags, const char *fn, char const *fmt, va_list va, void * UNUSED(private_ptr), int log_fd) { /* NOTE NO TRAILING NUL */ char buf[4090]; size_t len; ssize_t ret; rs_format_msg(buf, sizeof buf, flags, fn, fmt, va); len = strlen(buf); if (len > (int) sizeof buf - 2) len = (int) sizeof buf - 2; strcpy(&buf[len], "\n"); ret = write(log_fd, buf, len + 1); if (ret == -1) { ret = write(/* stderr */ 2, buf, len + 1); } } /* ======================================================================== */ /* functions for handling compilers without varargs macros */ /* This is called directly if the machine doesn't allow varargs * macros. */ void rs_log_error_nofn(char const *s, ...) { va_list va; va_start(va, s); rs_log_va(RS_LOG_ERR, NULL, s, va); va_end(va); } /* This is called directly if the machine doesn't allow varargs * macros. */ void rs_log_warning_nofn(char const *s, ...) { va_list va; va_start(va, s); rs_log_va(RS_LOG_WARNING, NULL, s, va); va_end(va); } /* This is called directly if the machine doesn't allow varargs * macros. */ void rs_log_critical_nofn(char const *s, ...) { va_list va; va_start(va, s); rs_log_va(RS_LOG_CRIT, NULL, s, va); va_end(va); } /* This is called directly if the machine doesn't allow varargs * macros. */ void rs_log_info_nofn(char const *s, ...) { va_list va; va_start(va, s); rs_log_va(RS_LOG_INFO, NULL, s, va); va_end(va); } /* This is called directly if the machine doesn't allow varargs * macros. */ void rs_log_notice_nofn(char const *s, ...) { va_list va; va_start(va, s); rs_log_va(RS_LOG_NOTICE, NULL, s, va); va_end(va); } /* This is called directly if the machine doesn't allow varargs * macros. */ void rs_log_trace_nofn(char const *s, ...) { va_list va; va_start(va, s); rs_log_va(RS_LOG_DEBUG, NULL, s, va); va_end(va); } /** * Return true if the library contains trace code; otherwise false. * If this returns false, then trying to turn trace on will achieve * nothing. */ int rs_supports_trace(void) { #ifdef DO_RS_TRACE return 1; #else return 0; #endif /* !DO_RS_TRACE */ } static char job_summary[4096*4]; void dcc_job_summary_clear(void) { job_summary[0] = 0; job_summary[sizeof(job_summary) - 1] = '\0'; } void dcc_job_summary(void) { rs_log_notice("%s", job_summary); } void dcc_job_summary_append(const char *s) { int64_t len = (4096 * 4 - 1) - strlen(job_summary); if (len > 0) strncat(job_summary, s, len); } distcc-3.4/src/trace.h000066400000000000000000000163421404653710500147020ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * librsync -- generate and apply network deltas * * Copyright (C) 2000, 2001, 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** * @file * * Reusable trace library. * * @todo A function like perror that includes strerror output. Apache * does this by adding flags as well as the severity level which say * whether such information should be included. * * @todo Also check in configure for the C9X predefined identifier `_function', or * whatever it's called. **/ /* Provide simple macro statement wrappers (adapted from glib, and originally from Perl): * RS_STMT_START { statements; } RS_STMT_END; * can be used as a single statement, as in * if (x) RS_STMT_START { ... } RS_STMT_END; else ... * * For gcc we will wrap the statements within `({' and `})' braces. * For SunOS they will be wrapped within `if (1)' and `else (void) 0', * and otherwise within `do' and `while (0)'. */ #if !(defined (RS_STMT_START) && defined (RS_STMT_END)) # if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) # define RS_STMT_START (void)( # define RS_STMT_END ) # else # if (defined (sun) || defined (__sun__)) # define RS_STMT_START if (1) # define RS_STMT_END else (void)0 # else # define RS_STMT_START do # define RS_STMT_END while (0) # endif # endif #endif #include /* unconditionally on */ #define DO_RS_TRACE /** * Log severity levels. * * These have the same numeric values as the levels for syslog, at * least in glibc. * * Trace may be turned off. * * Error is always on, but you can return and continue in some way. */ typedef enum { RS_LOG_EMERG = 0, /**< System is unusable */ RS_LOG_ALERT = 1, /**< Action must be taken immediately */ RS_LOG_CRIT = 2, /**< Critical conditions */ RS_LOG_ERR = 3, /**< Error conditions */ RS_LOG_WARNING = 4, /**< Warning conditions */ RS_LOG_NOTICE = 5, /**< Normal but significant condition */ RS_LOG_INFO = 6, /**< Informational */ RS_LOG_DEBUG = 7 /**< Debug-level messages */ } rs_loglevel; int rs_loglevel_from_name(const char *name); enum { RS_LOG_PRIMASK = 7, /**< Mask to extract priority part. \internal */ RS_LOG_NONAME = 8, /**< \b Don't show function name in message. */ RS_LOG_NO_PROGRAM = 16, RS_LOG_NO_PID = 32 }; /** * \typedef rs_logger_fn * \brief Callback to write out log messages. * \param level a syslog level. * \param msg message to be logged. * * \param private Opaque data passed in when logger was added. For * example, pointer to file descriptor. */ typedef void rs_logger_fn(int flags, const char *fn, char const *msg, va_list, void *private_ptr, int private_int); void rs_format_msg(char *buf, size_t, int, const char *, const char *fmt, va_list); void rs_trace_set_level(rs_loglevel level); void rs_add_logger(rs_logger_fn *, int level, void *, int); void rs_remove_logger(rs_logger_fn *, int level, void *, int); void rs_remove_all_loggers(void); void rs_logger_file(int level, const char *fn, char const *fmt, va_list va, void *, int); void rs_logger_syslog(int level, const char *fn, char const *fmt, va_list va, void *, int); /** Check whether the library was compiled with debugging trace support. */ int rs_supports_trace(void); void rs_log0(int level, char const *fn, char const *fmt, ...) #if defined(__GNUC__) __attribute__ ((format(printf, 3, 4))) #endif /* __GNUC__ */ ; /* TODO: Check for the __FUNCTION__ thing, rather than gnuc */ #if defined(HAVE_VARARG_MACROS) && defined(__GNUC__) #if 1 || defined(DO_RS_TRACE) # define rs_trace(fmt, arg...) \ do { rs_log0(RS_LOG_DEBUG, __FUNCTION__, fmt , ##arg); \ } while (0) #else # define rs_trace(s, str...) #endif /* !DO_RS_TRACE */ #define rs_log(l, s, str...) do { \ rs_log0((l), __FUNCTION__, (s) , ##str); \ } while (0) #define rs_log_crit(s, str...) do { \ rs_log0(RS_LOG_CRIT, __FUNCTION__, (s) , ##str); \ } while (0) #define rs_log_error(s, str...) do { \ rs_log0(RS_LOG_ERR, __FUNCTION__, (s) , ##str); \ } while (0) #define rs_log_notice(s, str...) do { \ rs_log0(RS_LOG_NOTICE, __FUNCTION__, (s) , ##str); \ } while (0) #define rs_log_warning(s, str...) do { \ rs_log0(RS_LOG_WARNING, __FUNCTION__, (s) , ##str); \ } while (0) #define rs_log_info(s, str...) do { \ rs_log0(RS_LOG_INFO, __FUNCTION__, (s) , ##str); \ } while (0) #else /* not defined HAVE_VARARG_MACROS */ /* If we don't have gcc vararg macros, then we fall back to making the * log routines just plain functions. On platforms without gcc (boo * hiss!) this means at least you get some messages, but not the nice * function names etc. */ #define rs_log rs_log0_nofn #define rs_trace rs_log_trace_nofn #define rs_log_info rs_log_info_nofn #define rs_log_notice rs_log_notice_nofn #define rs_log_warning rs_log_warning_nofn #define rs_log_error rs_log_error_nofn #define rs_log_crit rs_log_critical_nofn #endif /* HAVE_VARARG_MACROS */ void rs_log_trace_nofn(char const *s, ...); void rs_log_info_nofn(char const *, ...); void rs_log_notice_nofn(char const *, ...); void rs_log_warning_nofn(char const *s, ...); void rs_log_error_nofn(char const *s, ...); void rs_log_critical_nofn(char const *, ...); void rs_log0_nofn(int level, char const *fmt, ...); /** * \macro rs_trace_enabled() * * Call this before putting too much effort into generating trace * messages. */ /* really bool */ extern int rs_trace_syslog; extern int rs_trace_level; #ifdef DO_RS_TRACE # define rs_trace_enabled() ((rs_trace_level & RS_LOG_PRIMASK) >= RS_LOG_DEBUG) #else # define rs_trace_enabled() 0 #endif /** * Name of the program, to be included in log messages. * * @note This must be defined exactly once in each program that links to * trace.c **/ extern const char *rs_program_name; void dcc_job_summary_clear(void); void dcc_job_summary(void); void dcc_job_summary_append(const char *s); distcc-3.4/src/traceenv.c000066400000000000000000000057301404653710500154050ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" /** * Setup client error/trace output. * * Trace goes to the file specified by DISTCC_LOG, if any. Otherwise, it goes * to stderr, except that UNCACHED_ERR_FD can redirect it elsewhere, for use * under ccache. * * The exact setting of log level is a little strange, but for a good * reason: if you ask for verbose, you get everything. Otherwise, if * you set a file, you get INFO and above. Otherwise, you only get * WARNING messages. In practice this seems to be a nice balance. **/ void dcc_set_trace_from_env(void) { const char *logfile, *logfd_name; int fd; int failed_to_open_logfile = 0; int save_errno = 0; int level = RS_LOG_WARNING; /* by default, warnings only */ /* let the decision on what to log rest on the loggers */ /* the email-an-error functionality in emaillog.c depends on this */ rs_trace_set_level(RS_LOG_DEBUG); if ((logfile = getenv("DISTCC_LOG")) && logfile[0]) { fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0666); if (fd != -1) { /* asked for a file, and we can open that file: include info messages */ level = RS_LOG_INFO; } else { /* asked for a file, can't use it; use stderr instead */ fd = STDERR_FILENO; save_errno = errno; failed_to_open_logfile = 1; } } else { /* not asked for file */ if ((logfd_name = getenv("UNCACHED_ERR_FD")) == NULL || (fd = atoi(logfd_name)) == 0) { fd = STDERR_FILENO; } } if (dcc_getenv_bool("DISTCC_VERBOSE", 0)) { level = RS_LOG_DEBUG; } rs_add_logger(rs_logger_file, level, NULL, fd); if (failed_to_open_logfile) { rs_log_error("failed to open logfile %s: %s", logfile, strerror(save_errno)); } } distcc-3.4/src/types.h000066400000000000000000000024411404653710500147430ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef HAVE_IN_PORT_T #define HAVE_IN_PORT_T typedef int in_port_t; #endif #ifndef HAVE_IN_ADDR_T /* Seems to be equivalent to ulong on FreeBSD 3.3, where it is missing. * http://www.freebsd.org/cgi/man.cgi?query=inet_aton&apropos=0&sektion=0&manpath=FreeBSD+3.3-RELEASE&format=html * * On Linux it is uint32. */ #define HAVE_IN_ADDR_T typedef unsigned long in_addr_t; #endif distcc-3.4/src/util.c000066400000000000000000000646611404653710500145630ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_RESOURCE_H #include #endif #ifdef HAVE_SYS_LOADAVG_H #include #endif #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "snprintf.h" /* I will make a man more precious than fine * gold; even a man than the golden wedge of * Ophir. * -- Isaiah 13:12 */ void dcc_exit(int exitcode) { struct rusage self_ru, children_ru; if (getrusage(RUSAGE_SELF, &self_ru)) { rs_log_warning("getrusage(RUSAGE_SELF) failed: %s", strerror(errno)); memset(&self_ru, 0, sizeof self_ru); } if (getrusage(RUSAGE_CHILDREN, &children_ru)) { rs_log_warning("getrusage(RUSAGE_CHILDREN) failed: %s", strerror(errno)); memset(&children_ru, 0, sizeof children_ru); } /* NB fields must match up for microseconds */ rs_log(RS_LOG_INFO, "exit: code %d; self: %d.%06d user %d.%06d sys; children: %d.%06d user %d.%06d sys", exitcode, (int) self_ru.ru_utime.tv_sec, (int) self_ru.ru_utime.tv_usec, (int) self_ru.ru_stime.tv_sec, (int) self_ru.ru_stime.tv_usec, (int) children_ru.ru_utime.tv_sec, (int) children_ru.ru_utime.tv_usec, (int) children_ru.ru_stime.tv_sec, (int) children_ru.ru_stime.tv_usec); exit(exitcode); } int str_endswith(const char *tail, const char *tiger) { size_t len_tail = strlen(tail); size_t len_tiger = strlen(tiger); if (len_tail > len_tiger) return 0; return !strcmp(tiger + len_tiger - len_tail, tail); } int str_startswith(const char *head, const char *worm) { return !strncmp(head, worm, strlen(head)); } /** * Skim through NULL-terminated @p argv, looking for @p s. **/ int argv_contains(char **argv, const char *s) { while (*argv) { if (!strcmp(*argv, s)) return 1; argv++; } return 0; } /** * Redirect a file descriptor into (or out of) a file. * * Used, for example, to catch compiler error messages into a * temporary file. **/ int dcc_redirect_fd(int fd, const char *fname, int mode) { int newfd; /* ignore errors */ close(fd); newfd = open(fname, mode, 0666); if (newfd == -1) { rs_log_crit("failed to reopen fd%d onto %s: %s", fd, fname, strerror(errno)); return EXIT_IO_ERROR; } else if (newfd != fd) { rs_log_crit("oops, reopened fd%d onto fd%d?", fd, newfd); return EXIT_IO_ERROR; } return 0; } char *dcc_gethostname(void) { static char myname[100] = "\0"; if (!myname[0]) { if (gethostname(myname, sizeof myname - 1) == -1) strcpy(myname, "UNKNOWN"); } return myname; } /** * Look up a boolean environment option, which must be either "0" or * "1". The default, if it's not set or is empty, is @p default. **/ int dcc_getenv_bool(const char *name, int default_value) { const char *e; e = getenv(name); if (!e || !*e) return default_value; if (!strcmp(e, "1")) return 1; else if (!strcmp(e, "0")) return 0; else return default_value; } #define IS_LEGAL_DOMAIN_CHAR(c) (isalnum((uint8_t)c) || ((c) == '-') || ((c) == '.')) /* Copy domain part of hostname to static buffer. * If hostname has no domain part, returns -1. * If domain lookup fails, returns -1. * Otherwise places pointer to domain in *domain_name and returns 0. * * This should yield the same result as the linux command * 'dnsdomainname' or 'hostname -d'. **/ int dcc_get_dns_domain(const char **domain_name) { #if 0 /* Too expensive */ static char host_name[1024]; struct hostent *h; int ret; ret = gethostname(host_name, sizeof(host_name)); if (ret != 0) return -1; h = gethostbyname(host_name); if (h == NULL) { rs_log_error("failed to look up self \"%s\": %s", host_name, hstrerror(h_errno)); return -1; } strncpy(host_name, h->h_name, sizeof(host_name) - 1); host_name[sizeof(host_name) - 1] = '\0'; *domain_name = strchr(h->h_name, '.'); #else /* cheaper */ const char *envh, *envh2; int i; const int MAXDOMAINLEN = 512; /* Kludge for speed: Try to retrieve FQDN from environment. * This can save many milliseconds on a network that's busy and lossy * (glibc retries DNS operations very slowly). */ /* Solaris, BSD tend to put it in HOST. * (Some flavors of Linux put the non-qualified hostname in HOST, * so ignore this if it doesn't have a dot in it.) */ envh = getenv("HOST"); if (envh && !strchr(envh, '.')) envh = NULL; /* Some flavors of Linux put the FQDN in HOSTNAME when * logged in interactively, but not when ssh'd in noninteractively. * Ubuntu's bash puts it in HOSTNAME but doesn't export it! */ envh2 = getenv("HOSTNAME"); if (envh2 && !strchr(envh2, '.')) envh2 = NULL; /* Pick the 'better' of the two. Longer is usually better. */ if (envh2 && (!envh || (strlen(envh) < strlen(envh2)))) envh = envh2; /* If the above didn't work out, fall back to the real way. */ if (!envh || !strchr(envh, '.')) { static char host_name[1024]; struct hostent *h; int ret; ret = gethostname(host_name, sizeof(host_name)); if (ret != 0) return -1; /* If hostname has a dot in it, assume it's the DNS address */ if (!strchr(host_name, '.')) { /* Otherwise ask DNS what our full hostname is */ h = gethostbyname(host_name); if (h == NULL) { rs_log_error("failed to look up self \"%s\": %s", host_name, hstrerror(h_errno)); return -1; } strncpy(host_name, h->h_name, sizeof(host_name) - 1); host_name[sizeof(host_name) - 1] = '\0'; } envh = host_name; } /* validate to avoid possible errors from bad chars or huge value */ for (i=0; envh[i] != '\0'; i++) { if (i > MAXDOMAINLEN || !IS_LEGAL_DOMAIN_CHAR(envh[i])) { rs_log_error("HOST/HOSTNAME present in environment but illegal: '%s'", envh); return -1; } } *domain_name = strchr(envh, '.'); #endif if (*domain_name == NULL) return -1; (*domain_name)++; /* Return 0 on success, or -1 if the domain name is illegal, e.g. empty */ return ((*domain_name)[0] == '\0') ? -1 : 0; } /** * Set the `FD_CLOEXEC' flag of DESC if VALUE is nonzero, * or clear the flag if VALUE is 0. * * From the GNU C Library examples. * * @returns 0 on success, or -1 on error with `errno' set. **/ int set_cloexec_flag (int desc, int value) { int oldflags = fcntl (desc, F_GETFD, 0); /* If reading the flags failed, return error indication now. */ if (oldflags < 0) return oldflags; /* Set just the flag we want to set. */ if (value != 0) oldflags |= FD_CLOEXEC; else oldflags &= ~FD_CLOEXEC; /* Store modified flag word in the descriptor. */ return fcntl (desc, F_SETFD, oldflags); } /** * Ignore or unignore SIGPIPE. * * The server and child ignore it, because distcc code wants to see * EPIPE errors if something goes wrong. However, for invoked * children it is set back to the default value, because they may not * handle the error properly. **/ int dcc_ignore_sigpipe(int val) { if (signal(SIGPIPE, val ? SIG_IGN : SIG_DFL) == SIG_ERR) { rs_log_warning("signal(SIGPIPE, %s) failed: %s", val ? "ignore" : "default", strerror(errno)); return EXIT_DISTCC_FAILED; } return 0; } /** * Search through the $PATH looking for a directory containing a file called * @p compiler_name, which is a symbolic link containing the string "distcc". * * Trim the path to just after the *last* such directory. * * If we find a distcc masquerade dir on the PATH, remove all the dirs up * to that point. **/ int dcc_trim_path(const char *compiler_name) { const char *envpath, *newpath, *p, *n; char linkbuf[MAXPATHLEN], *buf; struct stat sb; size_t len; if (!(envpath = getenv("PATH"))) { rs_trace("PATH seems not to be defined"); return 0; } rs_trace("original PATH %s", envpath); rs_trace("looking for \"%s\"", compiler_name); /* Allocate a buffer that will let us append "/cc" onto any PATH * element, even if there is only one item in the PATH. */ if (!(buf = malloc(strlen(envpath)+1+strlen(compiler_name)+1))) { rs_log_error("failed to allocate buffer for PATH munging"); return EXIT_OUT_OF_MEMORY; } for (n = p = envpath, newpath = NULL; *n; p = n) { n = strchr(p, ':'); if (n) len = n++ - p; else { len = strlen(p); n = p + len; } strncpy(buf, p, len); sprintf(buf + len, "/%s", compiler_name); if (lstat(buf, &sb) == -1) continue; /* ENOENT, EACCESS, etc */ if (!S_ISLNK(sb.st_mode)) break; if ((len = readlink(buf, linkbuf, sizeof linkbuf)) <= 0) continue; linkbuf[len] = '\0'; if (strstr(linkbuf, "distcc")) { /* Set newpath to the part of the PATH past our match. */ newpath = n; } } if (newpath) { int ret = dcc_set_path(newpath); if (ret) return ret; } else rs_trace("not modifying PATH"); free(buf); return 0; } /* Set the PATH environment variable to the indicated value. */ int dcc_set_path(const char *newpath) { char *buf; if (asprintf(&buf, "PATH=%s", newpath) <= 0 || !buf) { rs_log_error("failed to allocate buffer for new PATH"); return EXIT_OUT_OF_MEMORY; } rs_trace("setting %s", buf); if (putenv(buf) < 0) { rs_log_error("putenv PATH failed"); return EXIT_FAILURE; } /* We must leave "buf" allocated. */ return 0; } /* Return the supplied path with the current-working directory prefixed (if * needed) and all "dir/.." references removed. Supply path_len if you want * to use only a substring of the path string, otherwise make it 0. */ char *dcc_abspath(const char *path, int path_len) { static char buf[MAXPATHLEN]; unsigned len; char *p, *slash; if (*path == '/') len = 0; else { char *ret; #ifdef HAVE_GETCWD ret = getcwd(buf, sizeof buf); if (ret == NULL) { rs_log_crit("getcwd failed: %s", strerror(errno)); } #else ret = getwd(buf); if (ret == NULL) { rs_log_crit("getwd failed: %s", strerror(errno)); } #endif len = strlen(buf); if (len >= sizeof buf) { rs_log_crit("getwd overflowed in dcc_abspath()"); } buf[len++] = '/'; } if (path_len <= 0) path_len = strlen(path); if (path_len >= 2 && *path == '.' && path[1] == '/') { path += 2; path_len -= 2; } if (len + (unsigned)path_len >= sizeof buf) { rs_log_error("path overflowed in dcc_abspath()"); exit(EXIT_OUT_OF_MEMORY); } strncpy(buf + len, path, path_len); buf[len + path_len] = '\0'; for (p = buf+len-(len > 0); (p = strstr(p, "/../")) != NULL; p = slash) { *p = '\0'; if (!(slash = strrchr(buf, '/'))) slash = p; strcpy(slash, p+3); } return buf; } /* Return -1 if a < b, 0 if a == b, and 1 if a > b */ int dcc_timecmp(struct timeval a, struct timeval b) { if (a.tv_sec < b.tv_sec) { return -1; } else if (a.tv_sec > b.tv_sec) { return 1; } else if (a.tv_usec < b.tv_usec) { /* at this point their tv_sec must be the same */ return -1; } else if (a.tv_usec > b.tv_usec) { return 1; } else { /* they must be equal */ return 0; } } /* Return the current number of running processes. */ int dcc_getcurrentload(void) { #if defined(linux) double stats[3]; int running; int total; int last_pid; int retval; FILE *f = fopen("/proc/loadavg", "r"); if (NULL == f) return -1; retval = fscanf(f, "%lf %lf %lf %d/%d %d", &stats[0], &stats[1], &stats[2], &running, &total, &last_pid); fclose(f); if (6 != retval) return -1; return running; #else return -1; #endif } /** * Wrapper for getloadavg() that tries to return all 3 samples, and reports * -1 for those samples that are not available. * * Averages are over the last 1, 5, and 15 minutes, respectively. **/ void dcc_getloadavg(double loadavg[3]) { int num; int i; #if defined(HAVE_GETLOADAVG) num = getloadavg(loadavg, 3); #else num = 0; #endif /* If getloadavg() didn't return 3 we want to fill * in the invalid elements with -1 */ if (num < 0) num = 0; for (i=num; i < 3; ++i) loadavg[i] = -1; } /** * Duplicate the part of the string @p psrc up to a character in @p sep * (or end of string), storing the result in @p pdst. @p psrc is updated to * point to the terminator. (If the terminator is not found it will * therefore point to \0. * * If there is no more string, then @p pdst is instead set to NULL, no * memory is allocated, and @p psrc is not advanced. **/ int dcc_dup_part(const char **psrc, char **pdst, const char *sep) { size_t len; len = strcspn(*psrc, sep); if (len == 0) { *pdst = NULL; } else { if (!(*pdst = malloc(len + 1))) { rs_log_error("failed to allocate string duplicate: %d", (int) len); return EXIT_OUT_OF_MEMORY; } strncpy(*pdst, *psrc, len); (*pdst)[len] = '\0'; (*psrc) += len; } return 0; } int dcc_remove_if_exists(const char *fname) { if (unlink(fname) && errno != ENOENT) { rs_log_warning("failed to unlink %s: %s", fname, strerror(errno)); return EXIT_IO_ERROR; } return 0; } int dcc_which(const char *command, char **out) { char *loc = NULL, *_loc, *path, *t; int ret; path = getenv("PATH"); if (!path) return -ENOENT; do { if (strstr(path, "distcc")) continue; /* emulate strchrnul() */ t = strchr(path, ':'); if (!t) t = path + strlen(path); _loc = realloc(loc, t - path + 1 + strlen(command) + 1); if (!_loc) { free(loc); return -ENOMEM; } loc = _loc; strncpy(loc, path, t - path); loc[t - path] = '\0'; strcat(loc, "/"); strcat(loc, command); ret = access(loc, X_OK); if (ret < 0) continue; *out = loc; return 0; } while ((path = strchr(path, ':') + 1)); return -ENOENT; } /* Returns the number of processes in state D, the max non-cc/c++ RSS in kb and * the max RSS program's name */ void dcc_get_proc_stats(int *num_D, int *max_RSS, char **max_RSS_name) { #if defined(linux) DIR *proc = opendir("/proc"); struct dirent *procsubdir; static int pagesize = -1; static char RSS_name[1024]; char statfile[1024]; FILE *f; char name[1024]; char state; int pid; int rss_size; int l; char *c; int isCC; /* If this doesn't cut it for you, see how CVS does it: * http://savannah.nongnu.org/cgi-bin/viewcvs/cvs/ccvs/lib/getpagesize.h */ if (pagesize == -1) { #if HAVE_GETPAGESIZE pagesize = getpagesize(); #else pagesize = 8192; #endif } *num_D = 0; *max_RSS = 0; *max_RSS_name = RSS_name; RSS_name[0] = 0; while ((procsubdir = readdir(proc)) != NULL) { if (sscanf(procsubdir->d_name, "%d", &pid) != 1) continue; strcpy(statfile, "/proc/"); strcat(statfile, procsubdir->d_name); strcat(statfile, "/stat"); f = fopen(statfile, "r"); if (f == NULL) continue; if (fscanf(f, "%*d %s %c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d", name, &state, &rss_size) != 3) { fclose(f); continue; } rss_size = (rss_size * pagesize) / 1024; /* get rss_size in KB */ if (state == 'D') { (*num_D)++; } l = strlen(RSS_name); c = RSS_name; /* check for .*{++,cc} */ isCC = (l >= 2) && ((c[l-1] == 'c' && c[l-2] == 'c') || (c[l-1] == '+' && c[l-2] == '+')); if ((rss_size > *max_RSS) && !isCC) { *max_RSS = rss_size; strncpy(RSS_name, name, 1024); } fclose(f); } closedir(proc); #else static char RSS_name[] = "none"; *num_D = -1; *max_RSS = -1; *max_RSS_name = RSS_name; #endif } /* Returns the number of sector read/writes since boot */ void dcc_get_disk_io_stats(int *n_reads, int *n_writes) { #if defined(linux) int retval; int kernel26 = 1; FILE *f; int reads, writes, minor; char dev[100]; char tmp[1024]; *n_reads = 0; *n_writes = 0; f = fopen("/proc/diskstats", "r"); if (f == NULL) { if (errno != ENOENT) return; /* /proc/diskstats does not exist. probably a 2.4 kernel, so try reading * /proc/partitions */ f = fopen("/proc/partitions", "r"); if (f == NULL) return; kernel26 = 0; } if (!kernel26) /* blast away 2 header lines in /proc/partitions */ { retval = fscanf(f, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s"); if (retval == EOF) { fclose(f); return; } } while (1) { if (kernel26) retval = fscanf(f, " %*d %d %s", &minor, dev); else retval = fscanf(f, " %*d %d %*d %s", &minor, dev); if (retval == EOF || retval != 2) break; if (minor % 64 == 0 && ((dev[0] == 'h' && dev[1] == 'd' && dev[2] == 'a') || (dev[0] == 's' && dev[1] == 'd' && dev[2] == 'a'))) { /* disk stats */ retval = fscanf(f, " %*d %*d %d %*d %*d %*d %d %*d %*d %*d %*d", &reads, &writes); if (retval == EOF || retval != 2) break; /* only add stats for disks, so we don't double count */ *n_reads += reads; *n_writes += writes; } else { #if 0 /* individual partition stats */ retval = fscanf(f, " %*d %d %*d %d", &reads, &writes); if (retval == EOF || retval != 2) break; #endif /* assume the lines aren't longer that 1024 characters */ if (fgets(tmp, 1024, f) == NULL) break; } } fclose(f); #else *n_reads = 0; *n_writes = 0; #endif } #ifndef HAVE_STRLCPY /* like strncpy but does not 0 fill the buffer and always null terminates. bufsize is the size of the destination buffer */ size_t strlcpy(char *d, const char *s, size_t bufsize) { size_t len = strlen(s); size_t ret = len; if (bufsize <= 0) return 0; if (len >= bufsize) len = bufsize-1; memcpy(d, s, len); d[len] = 0; return ret; } #endif #ifndef HAVE_STRSEP static char* strsep(char** str, const char* delims) { char* token; if (*str == NULL) { return NULL; } token = *str; while (**str != '\0') { if (strchr(delims, **str) != NULL) { **str = '\0'; (*str)++; return token; } (*str)++; } *str = NULL; return token; } #endif /* Given a string @p input, this function fills a a newly-allocated array of strings with copies of the input's whitespace-separated parts. Returns 0 on success, 1 on error. */ int dcc_tokenize_string(const char *input, char ***argv_ptr) { size_t n_spaces = 0; char *for_count; char **ap; char *input_copy; /* First of all, make a copy of the input string; * this way, we can destroy the copy. */ input_copy = strdup(input); if (input_copy == NULL) return 1; /* Count the spaces in the string. */ for (for_count = input_copy; *for_count; for_count++) if (isspace((uint8_t)*for_count)) n_spaces++; /* The maximum number of space-delimited strings we * can have is n_spaces + 1, and we need to add another 1 for * the null-termination. */ *argv_ptr = malloc(sizeof(char*) * (n_spaces + 1 + 1)); if (*argv_ptr == NULL) { free(input_copy); return 1; } ap = *argv_ptr; while((*ap = strsep(&input_copy, " \t\n")) != NULL) { /* If the field is empty, do nothing */ if (**ap == '\0') continue; *ap = strdup(*ap); if (*ap == NULL) { char **p; for (p = *argv_ptr; *p; p++) { free(*p); } free(*argv_ptr); free(input_copy); return 1; } ap++; } free(input_copy); return 0; } #ifndef HAVE_GETLINE ssize_t getline(char **lineptr, size_t *n, FILE *stream) { static const int buffer_size_increment = 100; char *buffer; size_t size; size_t bytes_read; int c; char *new_buffer; if (lineptr == NULL || stream == NULL || n == NULL || (*lineptr == NULL && *n != 0)) { /* Invalid parameters. */ return -1; } buffer = *lineptr; size = *n; bytes_read = 0; do { /* Ensure that we have space for next character or '\0'. */ if (bytes_read + 1 > size) { size += buffer_size_increment; new_buffer = realloc(buffer, size); if (new_buffer == NULL) { /* Out of memory. */ *lineptr = buffer; *n = size - buffer_size_increment; return -1; } buffer = new_buffer; } if ((c = fgetc(stream)) == EOF) break; buffer[bytes_read++] = c; } while (c != '\n'); buffer[bytes_read] = '\0'; *lineptr = buffer; *n = size; /* We return -1 on EOF for compatibility with GNU getline(). */ return bytes_read == 0 ? -1 : (ssize_t) bytes_read; } #endif /* from old systemd Copyright 2010 Lennart Poettering Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ static int sd_is_socket_internal(int fd, int type, int listening) { struct stat st_fd; if (fd < 0 || type < 0) return -EINVAL; if (fstat(fd, &st_fd) < 0) return -errno; if (!S_ISSOCK(st_fd.st_mode)) return 0; if (type != 0) { int other_type = 0; socklen_t l = sizeof(other_type); if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) return -errno; if (l != sizeof(other_type)) return -EINVAL; if (other_type != type) return 0; } if (listening >= 0) { int accepting = 0; socklen_t l = sizeof(accepting); if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) return -errno; if (l != sizeof(accepting)) return -EINVAL; if (!accepting != !listening) return 0; } return 1; } union sockaddr_union { struct sockaddr sa; struct sockaddr_in in4; struct sockaddr_in6 in6; struct sockaddr_un un; struct sockaddr_storage storage; }; int not_sd_is_socket(int fd, int family, int type, int listening) { int r; if (family < 0) return -EINVAL; r = sd_is_socket_internal(fd, type, listening); if (r <= 0) return r; if (family > 0) { union sockaddr_union sockaddr = {}; socklen_t l = sizeof(sockaddr); if (getsockname(fd, &sockaddr.sa, &l) < 0) return -errno; if ((size_t)l < sizeof(sa_family_t)) return -EINVAL; return sockaddr.sa.sa_family == family; } return 1; } distcc-3.4/src/util.h000066400000000000000000000044521404653710500145600ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include /* util.c */ int dcc_timecmp(struct timeval a, struct timeval b); int dcc_getcurrentload(void); void dcc_getloadavg(double loadavg[3]); int argv_contains(char **argv, const char *s); int dcc_redirect_fd(int, const char *fname, int); int str_startswith(const char *head, const char *worm); char *dcc_gethostname(void); void dcc_exit(int exitcode) NORETURN; int dcc_getenv_bool(const char *name, int def_value); int set_cloexec_flag (int desc, int value); int dcc_ignore_sigpipe(int val); int dcc_remove_if_exists(const char *fname); int dcc_trim_path(const char *compiler_name); int dcc_set_path(const char *newpath); char *dcc_abspath(const char *path, int path_len); int dcc_get_dns_domain(const char **domain_name); #define str_equal(a, b) (!strcmp((a), (b))) void dcc_get_proc_stats(int *num_D, int *max_RSS, char **max_RSS_name); void dcc_get_disk_io_stats(int *n_reads, int *n_writes); int dcc_which(const char *cmd, char **out); int dcc_dup_part(const char **psrc, char **pdst, const char *sep); #ifndef HAVE_STRLCPY size_t strlcpy(char *d, const char *s, size_t bufsize); #endif int dcc_tokenize_string(const char *in, char ***argv_ptr); #ifndef HAVE_GETLINE ssize_t getline(char **lineptr, size_t *n, FILE *stream); #endif int not_sd_is_socket(int fd, int family, int type, int listening); distcc-3.4/src/va_copy.h000066400000000000000000000031061404653710500152360ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef VA_COPY_H #define VA_COPY_H #include #ifdef HAVE_VA_COPY /* C99: use va_copy(), and match it with calls to va_end(). */ #define VA_COPY(dest, src) va_copy(dest, src) #define VA_COPY_END(dest) va_end(dest) #elif defined(HAVE_UNDERSCORE_UNDERSCORE_VA_COPY) /* Earlier drafts of the C99 standard used __va_copy(). */ #define VA_COPY(dest, src) __va_copy(dest, src) #define VA_COPY_END(dest) va_end(dest) #else /* Pre-C99: the best we can do is to assume that va_list values can be freely copied. This works on most (but not all) pre-C99 C implementations. */ #define VA_COPY(dest, src) ((dest) = (src), (void) 0) #define VA_COPY_END(dest) ((void) 0) #endif #endif /* VA_COPY_H */ distcc-3.4/src/where.c000066400000000000000000000151651404653710500147130ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* I put the shotgun in an Adidas bag and padded it * out with four pairs of tennis socks, not my style * at all, but that was what I was aiming for: If they * think you're crude, go technical; if they think * you're technical, go crude. I'm a very technical * boy. So I decided to get as crude as possible. * These days, though, you have to be pretty technical * before you can even aspire to crudeness. * -- William Gibson, "Johnny Mnemonic" */ /** * @file * * Routines to decide on which machine to run a distributable job. * * The current algorithm (new in 1.2 and subject to change) is as follows. * * CPU lock is held until the job is complete. * * Once the request has been transmitted, the lock is released and a second * job can be sent. * * Servers which wish to limit their load can defer accepting jobs, and the * client will block with that lock held. * * cpp is probably cheap enough that we can allow it to run unlocked. However * that is not true for local compilation or linking. * * @todo Write a test harness for the host selection algorithm. Perhaps a * really simple simulation of machines taking different amounts of time to * build stuff? */ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "hosts.h" #include "lock.h" #include "where.h" #include "exitcode.h" static int dcc_lock_one(struct dcc_hostdef *hostlist, struct dcc_hostdef **buildhost, int *cpu_lock_fd); void dcc_read_localslots_configuration() { struct dcc_hostdef *hostlist; int ret; int n_hosts; if ((ret = dcc_get_hostlist(&hostlist, &n_hosts)) == 0) { while (hostlist) { struct dcc_hostdef *l = hostlist; hostlist = hostlist->next; dcc_free_hostdef(l); } } } int dcc_pick_host_from_list_and_lock_it(struct dcc_hostdef **buildhost, int *cpu_lock_fd) { struct dcc_hostdef *hostlist; int ret; int n_hosts; if ((ret = dcc_get_hostlist(&hostlist, &n_hosts)) != 0) { return EXIT_NO_HOSTS; } if ((ret = dcc_remove_disliked(&hostlist))) return ret; if (!hostlist) { return EXIT_NO_HOSTS; } return dcc_lock_one(hostlist, buildhost, cpu_lock_fd); /* FIXME: Host list is leaked? */ } static void dcc_lock_pause(void) { /* This could do with some tuning. * * My assumption basically is that polling a little too often is * relatively cheap; sleeping when we should be working is bad. However, * if we hit this code at all we're overloaded, so sleeping a while is * perhaps OK. * * We don't use exponential backoff, because that would tend to prefer * later arrivals and penalize jobs that have been waiting for a long * time. This would mean more compiler processes hanging around than is * really necessary, and also by making jobs complete very-out-of-order is * more likely to find Makefile bugs. */ unsigned pause_time_ms = 1000; char *pt = getenv("DISTCC_PAUSE_TIME_MSEC"); if (pt) pause_time_ms = atoi(pt); /* This call to dcc_note_state() is made before the host is known, so it does not make sense and does nothing useful as far as I can tell. */ /* dcc_note_state(DCC_PHASE_BLOCKED, NULL, NULL, DCC_UNKNOWN); */ rs_trace("nothing available, sleeping %ums...", pause_time_ms); if (pause_time_ms > 0) usleep(pause_time_ms * 1000); } /** * Find a host that can run a distributed compilation by examining local state. * It can be either a remote server or localhost (if that is in the list). * * This function does not return (except for errors) until a host has been * selected. If necessary it sleeps until one is free. * * @todo We don't need transmit locks for local operations. **/ static int dcc_lock_one(struct dcc_hostdef *hostlist, struct dcc_hostdef **buildhost, int *cpu_lock_fd) { struct dcc_hostdef *h; int i_cpu; int ret; while (1) { for (i_cpu = 0; i_cpu < 10000; i_cpu++) { char i_cpu_is_usable = 0; for (h = hostlist; h; h = h->next) { if (i_cpu >= h->n_slots) continue; i_cpu_is_usable = 1; ret = dcc_lock_host("cpu", h, i_cpu, 0, cpu_lock_fd); if (ret == 0) { *buildhost = h; dcc_note_state_slot(i_cpu, strcmp(h->hostname, "localhost") == 0 ? DCC_LOCAL : DCC_REMOTE); return 0; } else if (ret == EXIT_BUSY) { continue; } else { rs_log_error("failed to lock"); return ret; } } if (!i_cpu_is_usable) break; } dcc_lock_pause(); } } /** * Lock localhost. Used to get the right balance of jobs when some of * them must be local. **/ int dcc_lock_local(int *cpu_lock_fd) { struct dcc_hostdef *chosen; return dcc_lock_one(dcc_hostdef_local, &chosen, cpu_lock_fd); } int dcc_lock_local_cpp(int *cpu_lock_fd) { int ret; struct dcc_hostdef *chosen; ret = dcc_lock_one(dcc_hostdef_local_cpp, &chosen, cpu_lock_fd); if (ret == 0) { dcc_note_state(DCC_PHASE_CPP, NULL, chosen->hostname, DCC_LOCAL); } return ret; } distcc-3.4/src/where.h000066400000000000000000000023111404653710500147050ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* where.c */ void dcc_read_localslots_configuration(void); int dcc_pick_host_from_list_and_lock_it(struct dcc_hostdef **, int *cpu_lock_fd); int dcc_lock_local(int *cpu_lock_fd); int dcc_lock_local_cpp(int *cpu_lock_fd); distcc-3.4/src/zeroconf-reg.c000066400000000000000000000205171404653710500161760ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright (C) 2007 Lennart Poettering * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "zeroconf.h" #include "trace.h" #include "exitcode.h" struct context { char *name; AvahiThreadedPoll *threaded_poll; AvahiClient *client; AvahiEntryGroup *group; uint16_t port; int n_cpus; int n_jobs; }; static void publish_reply(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata); static void register_stuff(struct context *ctx) { #ifndef ENABLE_RFC2553 static const AvahiProtocol dcc_proto = AVAHI_PROTO_INET; #else static const AvahiProtocol dcc_proto = AVAHI_PROTO_UNSPEC; #endif if (!ctx->group) { if (!(ctx->group = avahi_entry_group_new(ctx->client, publish_reply, ctx))) { rs_log_crit("Failed to create entry group: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } } if (avahi_entry_group_is_empty(ctx->group)) { char cpus[32], jobs[32], machine[64] = "cc_machine=", version[64] = "cc_version=", *m, *v; snprintf(cpus, sizeof(cpus), "cpus=%i", ctx->n_cpus); snprintf(jobs, sizeof(jobs), "jobs=%i", ctx->n_jobs); v = dcc_get_gcc_version(version+11, sizeof(version)-11); m = dcc_get_gcc_machine(machine+11, sizeof(machine)-11); /* Register our service */ if (avahi_entry_group_add_service( ctx->group, AVAHI_IF_UNSPEC, dcc_proto, 0, ctx->name, DCC_DNS_SERVICE_TYPE, NULL, NULL, ctx->port, "txtvers=1", cpus, jobs, "distcc="PACKAGE_VERSION, "gnuhost="GNU_HOST, v ? version : NULL, m ? machine : NULL, (void*)NULL) < 0) { rs_log_crit("Failed to add service: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } if (v && m) { char stype[128]; dcc_make_dnssd_subtype(stype, sizeof(stype), v, m); if (avahi_entry_group_add_service_subtype( ctx->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, ctx->name, DCC_DNS_SERVICE_TYPE, NULL, stype) < 0) { rs_log_crit("Failed to add service: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } } else rs_log_warning("Failed to determine CC version, not registering DNS-SD service subtype!"); if (avahi_entry_group_commit(ctx->group) < 0) { rs_log_crit("Failed to commit entry group: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } } return; fail: avahi_threaded_poll_quit(ctx->threaded_poll); } /* Called when publishing of service data completes */ static void publish_reply(AvahiEntryGroup *UNUSED(g), AvahiEntryGroupState state, void *userdata) { struct context *ctx = userdata; switch (state) { case AVAHI_ENTRY_GROUP_COLLISION: { char *n; /* Pick a new name for our service */ n = avahi_alternative_service_name(ctx->name); assert(n); avahi_free(ctx->name); ctx->name = n; register_stuff(ctx); break; } case AVAHI_ENTRY_GROUP_FAILURE: rs_log_crit("Failed to register service: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); avahi_threaded_poll_quit(ctx->threaded_poll); break; case AVAHI_ENTRY_GROUP_UNCOMMITED: case AVAHI_ENTRY_GROUP_REGISTERING: case AVAHI_ENTRY_GROUP_ESTABLISHED: ; } } static void client_callback(AvahiClient *client, AvahiClientState state, void *userdata) { struct context *ctx = userdata; ctx->client = client; switch (state) { case AVAHI_CLIENT_S_RUNNING: register_stuff(ctx); break; case AVAHI_CLIENT_S_COLLISION: case AVAHI_CLIENT_S_REGISTERING: if (ctx->group) avahi_entry_group_reset(ctx->group); break; case AVAHI_CLIENT_FAILURE: if (avahi_client_errno(client) == AVAHI_ERR_DISCONNECTED) { int error; avahi_client_free(ctx->client); ctx->client = NULL; ctx->group = NULL; /* Reconnect to the server */ if (!(ctx->client = avahi_client_new( avahi_threaded_poll_get(ctx->threaded_poll), AVAHI_CLIENT_NO_FAIL, client_callback, ctx, &error))) { rs_log_crit("Failed to contact server: %s\n", avahi_strerror(error)); avahi_threaded_poll_quit(ctx->threaded_poll); } } else { rs_log_crit("Client failure: %s\n", avahi_strerror(avahi_client_errno(client))); avahi_threaded_poll_quit(ctx->threaded_poll); } break; case AVAHI_CLIENT_CONNECTING: ; } } /* register a distcc service in DNS-SD/mDNS with the given port, number of CPUs, and maximum concurrent jobs */ void* dcc_zeroconf_register(uint16_t port, int n_cpus, int n_jobs) { struct context *ctx = NULL; char service[256] = "distcc@"; int error; ctx = malloc(sizeof(struct context)); assert(ctx); ctx->client = NULL; ctx->group = NULL; ctx->threaded_poll = NULL; ctx->port = port; ctx->n_cpus = n_cpus; ctx->n_jobs = n_jobs; /* Prepare service name */ gethostname(service+7, sizeof(service)-8); service[sizeof(service)-1] = 0; ctx->name = strdup(service); assert(ctx->name); if (!(ctx->threaded_poll = avahi_threaded_poll_new())) { rs_log_crit("Failed to create event loop object.\n"); goto fail; } if (!(ctx->client = avahi_client_new(avahi_threaded_poll_get(ctx->threaded_poll), AVAHI_CLIENT_NO_FAIL, client_callback, ctx, &error))) { rs_log_crit("Failed to create client object: %s\n", avahi_strerror(error)); goto fail; } /* Create the mDNS event handler */ if (avahi_threaded_poll_start(ctx->threaded_poll) < 0) { rs_log_crit("Failed to create thread.\n"); goto fail; } return ctx; fail: if (ctx) dcc_zeroconf_unregister(ctx); return NULL; } /* Unregister this server from DNS-SD/mDNS */ int dcc_zeroconf_unregister(void *u) { struct context *ctx = u; if (ctx->threaded_poll) avahi_threaded_poll_stop(ctx->threaded_poll); if (ctx->client) avahi_client_free(ctx->client); if (ctx->threaded_poll) avahi_threaded_poll_free(ctx->threaded_poll); avahi_free(ctx->name); free(ctx); return 0; } distcc-3.4/src/zeroconf.c000066400000000000000000000455521404653710500154310ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright (C) 2007 Lennart Poettering * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "hosts.h" #include "zeroconf.h" #include "trace.h" #include "exitcode.h" /* How long shall the background daemon be idle before i terminates itself? */ #define MAX_IDLE_TIME 20 /* Maximum size of host file to load */ #define MAX_FILE_SIZE (1024*100) /* General daemon data */ struct daemon_data { struct host *hosts; int fd; int n_slots; AvahiClient *client; AvahiServiceBrowser *browser; AvahiSimplePoll *simple_poll; }; /* Zeroconf service wrapper */ struct host { struct daemon_data *daemon_data; struct host *next; AvahiIfIndex interface; AvahiProtocol protocol; char *service; char *domain; AvahiAddress address; uint16_t port; int n_cpus; int n_jobs; AvahiServiceResolver *resolver; }; /* A generic, system independent lock routine, similar to sys_lock, * but more powerful: * rw: if non-zero: r/w lock instead of r/o lock * enable: lock or unlock * block: block when locking */ static int generic_lock(int fd, int rw, int enable, int block) { #if defined(F_SETLK) struct flock lockparam; lockparam.l_type = enable ? (rw ? F_WRLCK : F_RDLCK) : F_UNLCK; lockparam.l_whence = SEEK_SET; lockparam.l_start = 0; lockparam.l_len = 0; /* whole file */ return fcntl(fd, block ? F_SETLKW : F_SETLK, &lockparam); #elif defined(HAVE_FLOCK) return flock(fd, (enable ? (rw ? LOCK_EX : LOCK_SH) : LOCK_UN) | (block ? LOCK_NB : 0)); #elif defined(HAVE_LOCKF) return lockf(fd, (enable ? (block ? F_LOCK : F_TLOCK) : F_ULOCK)); #else # error "No supported lock method. Please port this code." #endif } /* Return the number of seconds, when the specified file was last * read. If the atime of that file is < clip_time, use clip_time * instead */ static time_t fd_last_used(int fd, time_t clip_time) { struct stat st; time_t now, ft; assert(fd >= 0); if (fstat(fd, &st) < 0) { rs_log_crit("fstat() failed: %s\n", strerror(errno)); return -1; } if ((now = time(NULL)) == (time_t) -1) { rs_log_crit("time() failed: %s\n", strerror(errno)); return -1; } ft = clip_time ? (st.st_atime < clip_time ? clip_time : st.st_atime) : st.st_atime; assert(ft <= now); return now - ft; } static void remove_duplicate_services(struct daemon_data *d); /* Write host data to host file */ static int write_hosts(struct daemon_data *d) { struct host *h; int r = 0; assert(d); rs_log_info("writing zeroconf data.\n"); if (generic_lock(d->fd, 1, 1, 1) < 0) { rs_log_crit("lock failed: %s\n", strerror(errno)); return -1; } if (lseek(d->fd, 0, SEEK_SET) < 0) { rs_log_crit("lseek() failed: %s\n", strerror(errno)); return -1; } if (ftruncate(d->fd, 0) < 0) { rs_log_crit("ftruncate() failed: %s\n", strerror(errno)); return -1; } remove_duplicate_services(d); for (h = d->hosts; h; h = h->next) { char t[256], a[AVAHI_ADDRESS_STR_MAX]; if (h->resolver) /* Not yet fully resolved */ continue; if (h->address.proto == AVAHI_PROTO_INET6) snprintf(t, sizeof(t), "[%s]:%u/%i\n", avahi_address_snprint(a, sizeof(a), &h->address), h->port, h->n_jobs); else snprintf(t, sizeof(t), "%s:%u/%i\n", avahi_address_snprint(a, sizeof(a), &h->address), h->port, h->n_jobs); if (dcc_writex(d->fd, t, strlen(t)) != 0) { rs_log_crit("write() failed: %s\n", strerror(errno)); goto finish; } } r = 0; finish: generic_lock(d->fd, 1, 0, 1); return r; }; /* Free host data */ static void free_host(struct host *h) { assert(h); if (h->resolver) avahi_service_resolver_free(h->resolver); free(h->service); free(h->domain); free(h); } /* Remove hosts with duplicate service names from the host list. * Hosts with multiple IP addresses show up more than once, but * should all have the same service name: "distcc@hostname" */ static void remove_duplicate_services(struct daemon_data *d) { struct host *host1, *host2, *prev; assert(d); for (host1 = d->hosts; host1; host1 = host1->next) { assert(host1->service); for (host2 = host1->next, prev = host1; host2; host2 = prev->next) { assert(host2->service); if (!strcmp(host1->service, host2->service)) { prev->next = host2->next; free_host(host2); } else { prev = host2; } } } } /* Remove a service from the host list */ static void remove_service(struct daemon_data *d, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *domain) { struct host *h, *p = NULL; assert(d); for (h = d->hosts; h; h = h->next) { if (h->interface == interface && h->protocol == protocol && !strcmp(h->service, name) && avahi_domain_equal(h->domain, domain)) { if (p) p->next = h->next; else d->hosts = h->next; free_host(h); break; } else p = h; } } /* Called when a resolve call completes */ static void resolve_reply( AvahiServiceResolver *UNUSED(r), AvahiIfIndex UNUSED(interface), AvahiProtocol UNUSED(protocol), AvahiResolverEvent event, const char *name, const char *UNUSED(type), const char *UNUSED(domain), const char *UNUSED(host_name), const AvahiAddress *a, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags UNUSED(flags), void *userdata) { struct host *h = userdata; switch (event) { case AVAHI_RESOLVER_FOUND: { AvahiStringList *i; /* Look for the number of CPUs in TXT RRs */ for (i = txt; i; i = i->next) { char *key, *value; if (avahi_string_list_get_pair(i, &key, &value, NULL) < 0) continue; if (!strcmp(key, "cpus")) if ((h->n_cpus = atoi(value)) <= 0) h->n_cpus = 1; avahi_free(key); avahi_free(value); } /* Look for the number of jobs in TXT RRs, and if not found, then set n_jobs = n_cpus + 2 */ for (i = txt; i; i = i->next) { char *key, *value; if (avahi_string_list_get_pair(i, &key, &value, NULL) < 0) continue; if (!strcmp(key, "jobs")) if ((h->n_jobs = atoi(value)) <= 0) h->n_jobs = h->n_cpus + 2; avahi_free(key); avahi_free(value); } h->address = *a; h->port = port; avahi_service_resolver_free(h->resolver); h->resolver = NULL; /* Write modified hosts file */ write_hosts(h->daemon_data); break; } case AVAHI_RESOLVER_FAILURE: rs_log_warning("Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(h->daemon_data->client))); free_host(h); break; } } /* Called whenever a new service is found or removed */ static void browse_reply( AvahiServiceBrowser *UNUSED(b), AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags UNUSED(flags), void *userdata) { struct daemon_data *d = userdata; assert(d); switch (event) { case AVAHI_BROWSER_NEW: { struct host *h; h = malloc(sizeof(struct host)); assert(h); rs_log_info("new service: %s\n", name); if (!(h->resolver = avahi_service_resolver_new(d->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_reply, h))) { rs_log_warning("Failed to create service resolver for '%s': %s\n", name, avahi_strerror(avahi_client_errno(d->client))); free(h); } else { /* Fill in missing data */ h->service = strdup(name); assert(h->service); h->domain = strdup(domain); assert(h->domain); h->daemon_data = d; h->interface = interface; h->protocol = protocol; h->next = d->hosts; h->n_cpus = 1; h->n_jobs = 4; d->hosts = h; } break; } case AVAHI_BROWSER_REMOVE: rs_log_info("Removed service: %s\n", name); remove_service(d, interface, protocol, name, domain); write_hosts(d); break; case AVAHI_BROWSER_FAILURE: rs_log_crit("Service Browser failure '%s': %s\n", name, avahi_strerror(avahi_client_errno(d->client))); avahi_simple_poll_quit(d->simple_poll); break; case AVAHI_BROWSER_CACHE_EXHAUSTED: case AVAHI_BROWSER_ALL_FOR_NOW: ; } } static void client_callback(AvahiClient *client, AvahiClientState state, void *userdata) { struct daemon_data *d = userdata; switch (state) { case AVAHI_CLIENT_FAILURE: rs_log_crit("Client failure: %s\n", avahi_strerror(avahi_client_errno(client))); avahi_simple_poll_quit(d->simple_poll); break; case AVAHI_CLIENT_S_COLLISION: case AVAHI_CLIENT_S_REGISTERING: case AVAHI_CLIENT_S_RUNNING: case AVAHI_CLIENT_CONNECTING: ; } } /* The main function of the background daemon */ static int daemon_proc(const char *host_file, const char *lock_file, int n_slots) { int ret = 1; int lock_fd = -1; struct daemon_data d; time_t clip_time; int error; char machine[64], version[64], stype[128]; rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0); /* Prepare daemon data structure */ d.fd = -1; d.hosts = NULL; d.n_slots = n_slots; d.simple_poll = NULL; d.browser = NULL; d.client = NULL; clip_time = time(NULL); rs_log_info("Zeroconf daemon running.\n"); /* Open daemon lock file and lock it */ if ((lock_fd = open(lock_file, O_RDWR|O_CREAT, 0666)) < 0) { rs_log_crit("open('%s') failed: %s\n", lock_file, strerror(errno)); goto finish; } if (generic_lock(lock_fd, 1, 1, 0) < 0) { /* lock failed, there's probably already another daemon running */ goto finish; } /* Open host file */ if ((d.fd = open(host_file, O_RDWR|O_CREAT, 0666)) < 0) { rs_log_crit("open('%s') failed: %s\n", host_file, strerror(errno)); goto finish; } /* Clear host file */ write_hosts(&d); if (!(d.simple_poll = avahi_simple_poll_new())) { rs_log_crit("Failed to create simple poll object.\n"); goto finish; } if (!(d.client = avahi_client_new( avahi_simple_poll_get(d.simple_poll), 0, client_callback, &d, &error))) { rs_log_crit("Failed to create Avahi client object: %s\n", avahi_strerror(error)); goto finish; } if (dcc_get_gcc_version(version, sizeof(version)) && dcc_get_gcc_machine(machine, sizeof(machine))) { dcc_make_dnssd_subtype(stype, sizeof(stype), version, machine); } else { rs_log_warning("Warning, failed to get CC version and machine type.\n"); strncpy(stype, DCC_DNS_SERVICE_TYPE, sizeof(stype)); stype[sizeof(stype)-1] = 0; } rs_log_info("Browsing for '%s'.\n", stype); if (!(d.browser = avahi_service_browser_new( d.client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, stype, NULL, 0, browse_reply, &d))) { rs_log_crit("Failed to create service browser object: %s\n", avahi_strerror(avahi_client_errno(d.client))); goto finish; } /* Check whether the host file has been used recently */ while (fd_last_used(d.fd, clip_time) <= MAX_IDLE_TIME) { /* Iterate the main loop for 5s */ if (avahi_simple_poll_iterate(d.simple_poll, 5000) != 0) { rs_log_crit("Event loop exited abnormally.\n"); goto finish; } } /* Wer are idle */ rs_log_info("Zeroconf daemon unused.\n"); ret = 0; finish: /* Cleanup */ if (lock_fd >= 0) { generic_lock(lock_fd, 1, 0, 0); close(lock_fd); } if (d.fd >= 0) close(d.fd); while (d.hosts) { struct host *h = d.hosts; d.hosts = d.hosts->next; free_host(h); } if (d.client) avahi_client_free(d.client); if (d.simple_poll) avahi_simple_poll_free(d.simple_poll); rs_log_info("zeroconf daemon ended.\n"); return ret; } /* Return path to the zeroconf directory in ~/.distcc */ static int get_zeroconf_dir(char **dir_ret) { static char *cached; int ret; if (cached) { *dir_ret = cached; return 0; } else { ret = dcc_get_subdir("zeroconf", dir_ret); if (ret == 0) cached = *dir_ret; return ret; } } /* Get the host list from zeroconf */ int dcc_zeroconf_add_hosts(struct dcc_hostdef **ret_list, int *ret_nhosts, int n_slots, struct dcc_hostdef **ret_prev) { char *host_file = NULL, *lock_file = NULL, *s = NULL; int lock_fd = -1, host_fd = -1; int fork_daemon = 0; int r = -1; char *dir; struct stat st; if (get_zeroconf_dir(&dir) != 0) { rs_log_crit("failed to get zeroconf dir.\n"); goto finish; } lock_file = malloc(strlen(dir) + sizeof("/lock")); assert(lock_file); sprintf(lock_file, "%s/lock", dir); host_file = malloc(strlen(dir) + sizeof("/hosts")); assert(host_file); sprintf(host_file, "%s/hosts", dir); /* Open lock file */ if ((lock_fd = open(lock_file, O_RDWR|O_CREAT, 0666)) < 0) { rs_log_crit("open('%s') failed: %s\n", lock_file, strerror(errno)); goto finish; } /* Try to lock the lock file */ if (generic_lock(lock_fd, 1, 1, 0) >= 0) { /* The lock succeeded => there's no daemon running yet! */ fork_daemon = 1; generic_lock(lock_fd, 1, 0, 0); } close(lock_fd); /* Shall we fork a new daemon? */ if (fork_daemon) { pid_t pid; rs_log_info("Spawning zeroconf daemon.\n"); if ((pid = fork()) == -1) { rs_log_crit("fork() failed: %s\n", strerror(errno)); goto finish; } else if (pid == 0) { int max_fd, fd; /* Child */ /* Close file descriptors and replace them by /dev/null */ max_fd = (int)sysconf(_SC_OPEN_MAX); if(max_fd == -1) { max_fd = 1024; } for(fd = 0; fd < max_fd; fd++) { close(fd); } fd = open("/dev/null", O_RDWR); assert(fd == 0); fd = dup(0); assert(fd == 1); fd = dup(0); assert(fd == 2); #ifdef HAVE_SETSID setsid(); #endif int ret = chdir("/"); rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0); if (ret != 0) { rs_log_warning("chdir to '/' failed: %s", strerror(errno)); } _exit(daemon_proc(host_file, lock_file, n_slots)); } /* Parent */ /* Wait some time for initial host gathering */ usleep(1000000); /* 1000 ms */ } /* Open host list read-only */ if ((host_fd = open(host_file, O_RDONLY)) < 0) { rs_log_crit("open('%s') failed: %s\n", host_file, strerror(errno)); goto finish; } /* A read lock */ if (generic_lock(host_fd, 0, 1, 1) < 0) { rs_log_crit("lock failed: %s\n", strerror(errno)); goto finish; } /* Get file size */ if (fstat(host_fd, &st) < 0) { rs_log_crit("stat() failed: %s\n", strerror(errno)); goto finish; } if (st.st_size >= MAX_FILE_SIZE) { rs_log_crit("file too large.\n"); goto finish; } /* read file data */ s = malloc((size_t) st.st_size+1); assert(s); if (dcc_readx(host_fd, s, (size_t) st.st_size) != 0) { rs_log_crit("failed to read from file.\n"); goto finish; } s[st.st_size] = 0; /* Parse host data */ if (dcc_parse_hosts(s, host_file, ret_list, ret_nhosts, ret_prev) != 0) { rs_log_crit("failed to parse host file.\n"); goto finish; } r = 0; finish: if (host_fd >= 0) { generic_lock(host_fd, 0, 0, 1); close(host_fd); } free(lock_file); free(host_file); free(s); return r; } distcc-3.4/src/zeroconf.h000066400000000000000000000025671404653710500154350ustar00rootroot00000000000000/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright (C) 2007 Lennart Poettering * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef foozeroconfhfoo #define foozeroconfhfoo #include int dcc_zeroconf_add_hosts(struct dcc_hostdef **re_list, int *ret_nhosts, int slots, struct dcc_hostdef **ret_prev); void *dcc_zeroconf_register(uint16_t port, int n_cpus, int n_jobs); int dcc_zeroconf_unregister(void*); char* dcc_get_gcc_version(char *s, size_t nbytes); char* dcc_get_gcc_machine(char *s, size_t nbytes); char* dcc_make_dnssd_subtype(char *stype, size_t nbytes, const char *v, const char *m); #define DCC_DNS_SERVICE_TYPE "_distcc._tcp" #endif distcc-3.4/survey.txt000066400000000000000000000020321404653710500147310ustar00rootroot00000000000000If you find distcc useful, please take a little time to fill out this survey and mail it to {distcc-survey at google.com}. Don't stress too much about getting scientifically rigorous numbers: rough numbers are more useful than none at all. Ideally, complete the survey for one large application that you work on, where compile speed is important. If after installing distcc you find that it makes your compile slower, or not as much faster as you would be expect, then please write to {distcc at lists.samba.org} instead of filling in the survey, and we'll try to resolve the problem. 0. What version of distcc are you using? 1. Your name and email address: 2. OK to publish this? - yes - yes, but without my identifying details - yes, but without my email address - no, for your eyes only 3. Your codebase: lines of code (by wc -l), and language: 4. Your machines: number, OS, processor, memory, network connectivity: 5. Time to compile, with and without distcc: 6. Any other observations: Thanks! The distcc maintainers. distcc-3.4/test/000077500000000000000000000000001404653710500136155ustar00rootroot00000000000000distcc-3.4/test/comfychair.py000077500000000000000000000352021404653710500163200ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright (C) 2002, 2003 by Martin Pool # Copyright (C) 2003 by Tim Potter # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """comfychair: a Python-based instrument of software torture. Copyright (C) 2002, 2003 by Martin Pool Copyright (C) 2003 by Tim Potter This is a test framework designed for testing programs written in Python, or (through a fork/exec interface) any other language. For more information, see the file README.comfychair. To run a test suite based on ComfyChair, just run it as a program. """ import sys, os, re, shutil class TestCase: """A base class for tests. This class defines required functions which can optionally be overridden by subclasses. It also provides some utility functions for""" def __init__(self): self.test_log = "" self.background_pids = [] self._cleanups = [] self._enter_rundir() self._save_environment() self.add_cleanup(self.teardown) # Prevent localizations interfering with attempts to parse # program output and error messages. LC_ALL has higher # priority (see locale(7)), but set both just in case. os.environ['LANG'] = 'C' os.environ['LC_ALL'] = 'C' # -------------------------------------------------- # Save and restore directory def _enter_rundir(self): self.basedir = os.getcwd() self.add_cleanup(self._restore_directory) self.rundir = os.path.join(self.basedir, '_testtmp', self.__class__.__name__) self.tmpdir = os.path.join(self.rundir, 'tmp') shutil.rmtree(self.rundir, ignore_errors=1) os.makedirs(self.tmpdir) os.chdir(self.rundir) def _restore_directory(self): os.chdir(self.basedir) # -------------------------------------------------- # Save and restore environment def _save_environment(self): self._saved_environ = os.environ.copy() self.add_cleanup(self._restore_environment) def _restore_environment(self): os.environ.clear() os.environ.update(self._saved_environ) def setup(self): """Set up test fixture.""" pass def teardown(self): """Tear down test fixture.""" pass def runtest(self): """Run the test.""" pass def add_cleanup(self, c): """Queue a cleanup to be run when the test is complete.""" self._cleanups.append(c) def apply_cleanups(self, debugger): """Apply cleanup functions and return error code. Returns: 0 on success; 2 if a KeyboardInterrupt occurs; 1 if any other exception occurs. """ while self._cleanups: try: clean_task = self._cleanups.pop() clean_task() except KeyboardInterrupt: print("interrupted during cleanups") _report_error(self, debugger) return 2 except: print("error during cleanups") _report_error(self, debugger) return 1 return 0 def fail(self, reason = ""): """Say the test failed.""" raise AssertionError(reason) ############################################################# # Requisition methods def require(self, predicate, message): """Check a predicate for running this test. If the predicate value is not true, the test is skipped with a message explaining why.""" if not predicate: raise NotRunError(message) def require_root(self): """Skip this test unless run by root.""" self.require(os.getuid() == 0, "must be root to run this test") ############################################################# # Assertion methods def assert_(self, expr, reason = ""): if not expr: raise AssertionError(reason) def assert_equal(self, a, b): if not a == b: raise AssertionError("assertEquals failed: %s %s" % (repr(a), repr(b))) def assert_notequal(self, a, b): if a == b: raise AssertionError("assertNotEqual failed: %s %s" % (repr(a), repr(b))) def assert_re_match(self, pattern, s): """Assert that a string matches a particular pattern Inputs: pattern string: regular expression s string: to be matched Raises: AssertionError if not matched """ if not re.match(pattern, s): raise AssertionError("string does not match regexp\n" " string: %s\n" " re: %s" % (repr(s), repr(pattern))) def assert_re_search(self, pattern, s): """Assert that a string *contains* a particular pattern Inputs: pattern string: regular expression s string: to be searched Raises: AssertionError if not matched """ if not re.search(pattern, s): raise AssertionError("string does not contain regexp\n" " string: %s\n" " re: %s" % (repr(s), repr(pattern))) def assert_no_file(self, filename): assert not os.path.exists(filename), ("file exists but should not: %s" % filename) ############################################################# # Methods for running programs def runcmd_background(self, cmd): self.test_log = self.test_log + "Run in background:\n" + repr(cmd) + "\n" pid = os.fork() if pid == 0: # child try: os.execvp("/bin/sh", ["/bin/sh", "-c", cmd]) finally: os._exit(127) self.test_log = self.test_log + "pid: %d\n" % pid return pid def runcmd(self, cmd, expectedResult = 0): """Run a command, fail if the command returns an unexpected exit code. Return the output produced.""" rc, output, stderr = self.runcmd_unchecked(cmd) if rc != expectedResult: raise AssertionError("""command returned %d; expected %s: \"%s\" stdout: %s stderr: %s""" % (rc, expectedResult, cmd, output, stderr)) return output, stderr def run_captured(self, cmd): """Run a command, capturing stdout and stderr. Based in part on popen2.py Returns (waitstatus, stdout, stderr).""" pid = os.fork() if pid == 0: # child try: pid = os.getpid() openmode = os.O_WRONLY|os.O_CREAT|os.O_TRUNC outfd = os.open('%d.out' % pid, openmode) os.dup2(outfd, 1) os.close(outfd) errfd = os.open('%d.err' % pid, openmode) os.dup2(errfd, 2) os.close(errfd) if isinstance(cmd, str): cmd = ['/bin/sh', '-c', cmd] os.execvp(cmd[0], cmd) finally: os._exit(127) else: # parent exited_pid, waitstatus = os.waitpid(pid, 0) stdout = open('%d.out' % pid).read() stderr = open('%d.err' % pid).read() return waitstatus, stdout, stderr def runcmd_unchecked(self, cmd, skip_on_noexec = 0): """Invoke a command; return (exitcode, stdout, stderr)""" waitstatus, stdout, stderr = self.run_captured(cmd) assert not os.WIFSIGNALED(waitstatus), \ ("%s terminated with signal %d" % (repr(cmd), os.WTERMSIG(waitstatus))) rc = os.WEXITSTATUS(waitstatus) self.test_log = self.test_log + ("""Run command: %s Wait status: %#x (exit code %d, signal %d) stdout: %s stderr: %s""" % (cmd, waitstatus, os.WEXITSTATUS(waitstatus), os.WTERMSIG(waitstatus), stdout, stderr)) if skip_on_noexec and rc == 127: # Either we could not execute the command or the command # returned exit code 127. According to system(3) we can't # tell the difference. raise NotRunError("could not execute %s" % repr(cmd)) return rc, stdout, stderr def explain_failure(self, exc_info = None): print("test_log:") print(self.test_log) def log(self, msg): """Log a message to the test log. This message is displayed if the test fails, or when the runtests function is invoked with the verbose option.""" self.test_log = self.test_log + msg + "\n" class NotRunError(Exception): """Raised if a test must be skipped because of missing resources""" def __init__(self, value = None): self.value = value def _report_error(case, debugger): """Ask the test case to explain failure, and optionally run a debugger Input: case TestCase instance debugger if true, a debugger function to be applied to the traceback """ ex = sys.exc_info() print("-----------------------------------------------------------------") if ex: import traceback traceback.print_exc(file=sys.stdout) case.explain_failure() print("-----------------------------------------------------------------") if debugger: tb = ex[2] debugger(tb) def runtest(testcase_class, ret, verbose=0, debugger=None, subtest=0): """Instantiate test class, run it, and catch and report exceptions. Inputs: testcase_class a class derived from TestCase ret return status, an integer verbose an integer (used as boolean) debugger debugger object to be applied to errors subtest an integer (used as boolean) Returns: a new return status Raises: KeyboardInterrupt If subtest is true, then the ordinary information about the test progress is not printed. """ if not subtest: print("%-30s" % _test_name(testcase_class), end=' ') def failure_print(message): print(message) else: def failure_print(message): print('[%s %s]' % (_test_name(testcase_class), message)) # flush now so that long running tests are easier to follow sys.stdout.flush() obj = None try: try: # run test and sometimes show result obj = testcase_class() obj.setup() obj.runtest() if not subtest: print("OK") except KeyboardInterrupt: failure_print("INTERRUPT") if obj: _report_error(obj, debugger) raise except NotRunError as msg: failure_print("NOTRUN, %s" % msg.value) except: failure_print("FAIL") if obj: _report_error(obj, debugger) return 1 finally: if obj: ret = obj.apply_cleanups(debugger) or ret # Display log file if we're verbose if ret == 0 and verbose: obj.explain_failure() return ret def runtests(test_list, verbose = 0, debugger = None): """Run a series of tests. Inputs: test_list sequence of TestCase classes verbose print more information as testing proceeds debugger debugger object to be applied to errors Returns: unix return code: 0 for success, 1 for failures, 2 for test failure """ import traceback ret = 0 for testcase_class in test_list: try: ret = runtest(testcase_class, ret, verbose=verbose, debugger=debugger) except KeyboardInterrupt: ret = 2 break return ret def _test_name(test_class): """Return a human-readable name for a test class. """ try: return test_class.__name__ except: return repr(test_class) def print_help(): """Help for people running tests""" print("""%s: software test suite based on ComfyChair usage: To run all tests, just run this program. To run particular tests, list them on the command line. options: --help show usage message --list list available tests --verbose, -v show more information while running tests --post-mortem, -p enter Python debugger on error """ % sys.argv[0]) def print_list(test_list): """Show list of available tests""" for test_class in test_list: print(" %s" % _test_name(test_class)) def main(tests, extra_tests=[]): """Main entry point for test suites based on ComfyChair. inputs: tests Sequence of TestCase subclasses to be run by default. extra_tests Sequence of TestCase subclasses that are available but not run by default. Test suites should contain this boilerplate: if __name__ == '__main__': comfychair.main(tests) This function handles standard options such as --help and --list, and by default runs all tests in the suggested order. Calls sys.exit() on completion. """ import getopt, sys opt_verbose = 0 debugger = None opts, args = getopt.getopt(sys.argv[1:], 'pv', ['help', 'list', 'verbose', 'post-mortem']) for opt, opt_arg in opts: if opt == '--help': print_help() return elif opt == '--list': print_list(tests + extra_tests) return elif opt == '--verbose' or opt == '-v': opt_verbose = 1 elif opt == '--post-mortem' or opt == '-p': import pdb debugger = pdb.post_mortem if args: all_tests = tests + extra_tests by_name = {} for t in all_tests: by_name[_test_name(t)] = t which_tests = [] for name in args: which_tests.append(by_name[name]) else: which_tests = tests sys.exit(runtests(which_tests, verbose=opt_verbose, debugger=debugger)) if __name__ == '__main__': print(__doc__) distcc-3.4/test/onetest.py000077500000000000000000000033101404653710500156500ustar00rootroot00000000000000#!/usr/bin/env python3 # # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Usage: onetest.py [--valgrind[=command]] [--lzo] [--pump] TESTNAME This command runs a single test case. TESTNAME should be the name of one of the test cases from testdistcc.py. """ __author__ = 'Fergus Henderson' import testdistcc import comfychair import sys if __name__ == '__main__': while len(sys.argv) > 1 and sys.argv[1].startswith("--"): if sys.argv[1] == "--valgrind": testdistcc._valgrind_command = "valgrind --quiet " del sys.argv[1] elif sys.argv[1].startswith("--valgrind="): testdistcc._valgrind_command = sys.argv[1][len("--valgrind="):] + " " del sys.argv[1] elif sys.argv[1] == "--lzo": testdistcc._server_options = ",lzo" del sys.argv[1] elif sys.argv[1] == "--pump": testdistcc._server_options = ",lzo,cpp" del sys.argv[1] if len(sys.argv) > 1: testname = sys.argv[1] del sys.argv[1] comfychair.main([eval('testdistcc.' + testname)]) else: sys.exit(__doc__) distcc-3.4/test/testdistcc.py000077500000000000000000002355521404653710500163570ustar00rootroot00000000000000#! /usr/bin/env python3 # Copyright (C) 2002, 2003, 2004 by Martin Pool # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """distcc test suite, using comfychair This script is called with $PATH pointing to the appropriate location for the built (or installed) programs to be tested. Options: --valgrind[=command] Run the tests under valgrind. Every program invocation will be prefixed with the valgrind command, which defaults to "valgrind --quiet". --lzo Run the server tests with lzo compression enabled. --pump Run the server tests with remote preprocessing enabled. Example: PATH="`pwd`:$PATH" python test/testdistcc.py --valgrind="valgrind --quiet --num-callers=20" """ # There are pretty strong hierarchies of test cases: ones to do with # running a daemon, compiling a file and so on. This nicely maps onto # a hierarchy of object classes. # It seems to work best if an instance of the class corresponds to an # invocation of a test: this means each method runs just once and so # object state is not very useful, but nevermind. # Having a complicated patterns of up and down-calls within the class # methods seems to make things more complicated. It may be better if # abstract superclasses just provide methods that can be called, # rather than establishing default behaviour. # TODO: Some kind of direct test of the host selection algorithm. # TODO: Test host files containing \r. # TODO: Test that ccache correctly caches compilations through distcc: # make up a random file so it won't hit, then compile once and compile # twice and examine the log file to make sure we got a hit. Also # check that the binary works properly. # TODO: Test cpp from stdin # TODO: Do all this with malloc debugging on. # TODO: Redirect daemon output to a file so that we can more easily # check it. Is there a straightforward way to test that it's also OK # when send through syslogd? # TODO: Check behaviour when children are killed off. # TODO: Test compiling over IPv6 # TODO: Argument scanning tests should be run with various hostspecs, # because that makes a big difference to how the client handles them. # TODO: Test that ccache gets hits when calling distcc. Presumably # this is skipped if we can't find ccache. Need to parse `ccache -s`. # TODO: Set TMPDIR to be inside the working directory, and perhaps # also set DISTCC_SAVE_TEMPS. Might help for debugging. # Check that without DISTCC_SAVE_TEMPS temporary files are cleaned up. # TODO: Perhaps redirect stdout, stderr to a temporary file while # running? Use os.open(), os.dup2(). # TODO: Test crazy option arguments like "distcc -o -output -c foo.c" # TODO: Add test harnesses that just exercise the bulk file transfer # routines. # TODO: Test -MD, -MMD, -M, etc. # TODO: Test using '.include' in an assembly file, and make sure that # it is resolved on the client, not on the server. # TODO: Run "sleep" as a compiler, then kill the client and make sure # that the server and "sleep" promptly terminate. # TODO: Perhaps have a little compiler that crashes. Check that the # signal gets properly reported back. # TODO: Have a little compiler that takes a very long time to run. # Try interrupting the connection and see if the compiler is cleaned # up in a reasonable time. # TODO: Try to build a nonexistent source file. Check that we only # get one error message -- if there were two, we would incorrectly # have tried to build the program both remotely and locally. # TODO: Test compiling a 0-byte source file. This should be allowed. # TODO: Test a compiler that produces 0 byte output. I don't know an # easy way to get that out of gcc aside from the Apple port though. # TODO: Test a compiler that sleeps for a long time; try killing the # server and make sure it goes away. # TODO: Test scheduler. Perhaps run really slow jobs to make things # deterministic, and test that they're dispatched in a reasonable way. # TODO: Test generating dependencies with -MD. Possibly can't be # done. # TODO: Test a nasty cpp that always writes to stdout regardless of # -o. # TODO: Test giving up privilege using --user. Difficult -- we may # need root privileges to run meaningful tests. # TODO: Test that recursion safeguard works. # TODO: Test masquerade mode. Requires us to create symlinks in a # special directory on the path. # TODO: Test SSH mode. May need to skip if we can't ssh to this # machine. Perhaps provide a little null-ssh. # TODO: Test path stripping. # TODO: Test backoff from downed hosts. # TODO: Check again in --no-prefork mode. # TODO: Test lzo is parsed properly # TODO: Test with DISTCC_DIR set, and not set. # TODO: Using --lifetime does cause sporadic failures. Ensure that # teardown kills all daemon processes and then stop using --lifetime. import time, sys, string, os, glob, re, socket import signal, os.path import comfychair from stat import * # this is safe EXIT_DISTCC_FAILED = 100 EXIT_BAD_ARGUMENTS = 101 EXIT_BIND_FAILED = 102 EXIT_CONNECT_FAILED = 103 EXIT_COMPILER_CRASHED = 104 EXIT_OUT_OF_MEMORY = 105 EXIT_BAD_HOSTSPEC = 106 EXIT_COMPILER_MISSING = 110 EXIT_ACCESS_DENIED = 113 DISTCC_TEST_PORT = 42000 _cc = None # full path to gcc _valgrind_command = "" # Command to invoke valgrind (or other # similar debugging tool). # e.g. "valgrind --quiet --num-callsers=20 " _server_options = "" # Distcc host options to use for the server. # Should be "", ",lzo", or ",lzo,cpp". def _ShellSafe(s): '''Returns a version of s that will be interpreted literally by the shell.''' return "'" + s.replace("'", "'\"'\"'") + "'" # Some tests only make sense for certain object formats def _FirstBytes(filename, count): '''Returns the first count bytes from the given file.''' f = open(filename, 'rb') try: return f.read(count) finally: f.close() def _IsElf(filename): '''Given a filename, determine if it's an ELF object file or executable. The magic number used ('\177ELF' at file-start) is taken from /usr/share/file/magic on an ubuntu machine. ''' contents = _FirstBytes(filename, 5) return contents.startswith(b'\177ELF') def _IsMachO(filename): '''Given a filename, determine if it's an Mach-O object file or executable. The magic number used ('0xcafebabe' or '0xfeedface') is taken from /usr/share/file/magic on an ubuntu machine. ''' contents = _FirstBytes(filename, 10) return (contents.startswith(b'\xCA\xFE\xBA\xBE') or contents.startswith(b'\xFE\xED\xFA\xCE') or contents.startswith(b'\xCE\xFA\xED\xFE') or # The magic file says '4-bytes (BE) & 0xfeffffff == # 0xfeedface' and '4-bytes (LE) & 0xfffffffe == # 0xfeedface' are also mach-o. contents.startswith(b'\xFF\xED\xFA\xCE') or contents.startswith(b'\xCE\xFA\xED\xFF')) def _IsPE(filename): '''Given a filename, determine if it's a Microsoft PE object file or executable. The magic number used ('MZ') is taken from /usr/share/file/magic on an ubuntu machine. ''' contents = _FirstBytes(filename, 5) return contents.startswith(b'MZ') def _Touch(filename): '''Update the access and modification time of the given file, creating an empty file if it does not exist. ''' f = open(filename, 'a') try: os.utime(filename, None) finally: f.close() class SimpleDistCC_Case(comfychair.TestCase): '''Abstract base class for distcc tests''' def setup(self): self.stripEnvironment() self.initCompiler() def initCompiler(self): self._cc = self._get_compiler() def stripEnvironment(self): """Remove all DISTCC variables from the environment, so that the test is not affected by the development environment.""" for key in list(os.environ.keys()): if key[:7] == 'DISTCC_': # NOTE: This only works properly on Python 2.2: on # earlier versions, it does not call unsetenv() and so # subprocesses may get confused. del os.environ[key] os.environ['TMPDIR'] = self.tmpdir ddir = os.path.join(self.tmpdir, 'distccdir') os.mkdir(ddir) os.environ['DISTCC_DIR'] = ddir def valgrind(self): return _valgrind_command; def distcc(self): return self.valgrind() + "distcc " def distccd(self): return self.valgrind() + "distccd " def distcc_with_fallback(self): return "DISTCC_FALLBACK=1 " + self.distcc() def distcc_without_fallback(self): return "DISTCC_FALLBACK=0 " + self.distcc() def _get_compiler(self): cc = self._find_compiler("cc") if self.is_clang(cc): return self._find_compiler("clang") elif self.is_gcc(cc): return self._find_compiler("gcc") raise AssertionError("Unknown compiler") def _find_compiler(self, compiler): for path in os.environ['PATH'].split (':'): abs_path = os.path.join (path, compiler) if os.path.isfile (abs_path): return abs_path return None def is_gcc(self, compiler): out, err = self.runcmd(compiler + " --version") if re.search('Free Software Foundation', out): return True return False def is_clang(self, compiler): out, err = self.runcmd(compiler + " --version") if re.search('clang', out): return True return False class WithDaemon_Case(SimpleDistCC_Case): """Start the daemon, and then run a command locally against it. The daemon doesn't detach until it has bound the network interface, so as soon as that happens we can go ahead and start the client.""" def setup(self): SimpleDistCC_Case.setup(self) self.daemon_pidfile = os.path.join(os.getcwd(), "daemonpid.tmp") self.daemon_logfile = os.path.join(os.getcwd(), "distccd.log") self.server_port = DISTCC_TEST_PORT # random.randint(42000, 43000) self.startDaemon() self.setupEnv() def setupEnv(self): os.environ['DISTCC_HOSTS'] = ('127.0.0.1:%d%s' % (self.server_port, _server_options)) os.environ['DISTCC_LOG'] = os.path.join(os.getcwd(), 'distcc.log') os.environ['DISTCC_VERBOSE'] = '1' def teardown(self): SimpleDistCC_Case.teardown(self) def killDaemon(self): try: pid = int(open(self.daemon_pidfile, 'rt').read()) except IOError: # the daemon probably already exited, perhaps because of a timeout return os.kill(pid, signal.SIGTERM) # We can't wait on it, because it detached. So just keep # pinging until it goes away. while 1: try: os.kill(pid, 0) except OSError: break time.sleep(0.2) def daemon_command(self): """Return command to start the daemon""" return (self.distccd() + "--verbose --lifetime=%d --daemon --log-file %s " "--pid-file %s --port %d --allow 127.0.0.1 --enable-tcp-insecure" % (self.daemon_lifetime(), _ShellSafe(self.daemon_logfile), _ShellSafe(self.daemon_pidfile), self.server_port)) def daemon_lifetime(self): # Enough for most tests, even on a fairly loaded machine. # Might need more for long-running tests. return 60 def startDaemon(self): """Start a daemon in the background, return its pid""" # The daemon detaches once it has successfully bound the # socket, so if something goes wrong at startup we ought to # find out straight away. If it starts successfully, then we # can go ahead and try to connect. # We run the daemon in a 'daemon' subdirectory to make # sure that it has a different directory than the client. old_tmpdir = os.environ['TMPDIR'] daemon_tmpdir = old_tmpdir + "/daemon_tmp" os.mkdir(daemon_tmpdir) os.environ['TMPDIR'] = daemon_tmpdir os.mkdir("daemon") os.chdir("daemon") try: while 1: cmd = self.daemon_command() result, out, err = self.runcmd_unchecked(cmd) if result == 0: break elif result == EXIT_BIND_FAILED: self.server_port += 1 continue else: self.fail("failed to start daemon: %d" % result) self.add_cleanup(self.killDaemon) finally: os.environ['TMPDIR'] = old_tmpdir os.chdir("..") class StartStopDaemon_Case(WithDaemon_Case): def runtest(self): pass class VersionOption_Case(SimpleDistCC_Case): """Test that --version returns some kind of version string. This is also a good test that the programs were built properly and are executable.""" def runtest(self): for prog in 'distcc', 'distccd': out, err = self.runcmd("%s --version" % prog) assert out[-1] == '\n' out = out[:-1] line1,line2,trash = out.split('\n', 2) self.assert_re_match(r'^%s [\w.-]+ [.\w-]+$' % prog, line1) self.assert_re_match(r'^[ \t]+\(protocol.*\) \(default port 3632\)$' , line2) class HelpOption_Case(SimpleDistCC_Case): """Test --help is reasonable.""" def runtest(self): for prog in 'distcc', 'distccd': out, err = self.runcmd(prog + " --help") self.assert_re_search("Usage:", out) class BogusOption_Case(SimpleDistCC_Case): """Test handling of --bogus-option. Now that we support implicit compilers, this is passed to gcc, which returns a non-zero status.""" def runtest(self): error_rc, _, _ = self.runcmd_unchecked(self._cc + " --bogus-option") assert error_rc != 0 self.runcmd(self.distcc() + self._cc + " --bogus-option", error_rc) self.runcmd(self.distccd() + self._cc + " --bogus-option", EXIT_BAD_ARGUMENTS) class CompilerOptionsPassed_Case(SimpleDistCC_Case): """Test that options following the compiler name are passed to the compiler.""" def runtest(self): out, err = self.runcmd("DISTCC_HOSTS=localhost " + self.distcc() + self._cc + " --help") if re.search('distcc', out): raise AssertionError("compiler help contains \"distcc\": \"%s\"" % out) if self.is_gcc(self._cc): self.assert_re_match(r"Usage: [^ ]*gcc", out) elif self.is_clang(self._cc): self.assert_re_match(r"OVERVIEW: [^ ]*clang", out) else: raise AssertionError("Unknown compiler found") class StripArgs_Case(SimpleDistCC_Case): """Test -D and -I arguments are removed""" def runtest(self): cases = (("gcc -c hello.c", "gcc -c hello.c"), ("cc -Dhello hello.c -c", "cc hello.c -c"), ("gcc -g -O2 -W -Wall -Wshadow -Wpointer-arith -Wcast-align -c -o h_strip.o h_strip.c", "gcc -g -O2 -W -Wall -Wshadow -Wpointer-arith -Wcast-align -c -o h_strip.o h_strip.c"), # invalid but should work ("cc -c hello.c -D", "cc -c hello.c"), ("cc -c hello.c -D -D", "cc -c hello.c"), ("cc -c hello.c -I ../include", "cc -c hello.c"), ("cc -c -I ../include hello.c", "cc -c hello.c"), ("cc -c -I. -I.. -I../include -I/home/mbp/garnome/include -c -o foo.o foo.c", "cc -c -c -o foo.o foo.c"), ("cc -c -DDEBUG -DFOO=23 -D BAR -c -o foo.o foo.c", "cc -c -c -o foo.o foo.c"), # New options stripped in 0.11 ("cc -o nsinstall.o -c -DOSTYPE=\"Linux2.4\" -DOSARCH=\"Linux\" -DOJI -D_BSD_SOURCE -I../dist/include -I../dist/include -I/home/mbp/work/mozilla/mozilla-1.1/dist/include/nspr -I/usr/X11R6/include -fPIC -I/usr/X11R6/include -Wall -W -Wno-unused -Wpointer-arith -Wcast-align -pedantic -Wno-long-long -pthread -pipe -DDEBUG -D_DEBUG -DDEBUG_mbp -DTRACING -g -I/usr/X11R6/include -include ../config-defs.h -DMOZILLA_CLIENT -Wp,-MD,.deps/nsinstall.pp nsinstall.c", "cc -o nsinstall.o -c -fPIC -Wall -W -Wno-unused -Wpointer-arith -Wcast-align -pedantic -Wno-long-long -pthread -pipe -g nsinstall.c"), ) for cmd, expect in cases: o, err = self.runcmd("h_strip %s" % cmd) if o[-1] == '\n': o = o[:-1] self.assert_equal(o, expect) class IsSource_Case(SimpleDistCC_Case): def runtest(self): """Test distcc's method for working out whether a file is source""" cases = (( "hello.c", "source", "not-preprocessed" ), ( "hello.cc", "source", "not-preprocessed" ), ( "hello.cxx", "source", "not-preprocessed" ), ( "hello.cpp", "source", "not-preprocessed" ), ( "hello.c++", "source", "not-preprocessed" ), # ".m" is Objective-C; ".M" and ".mm" are Objective-C++ ( "hello.m", "source", "not-preprocessed" ), ( "hello.M", "source", "not-preprocessed" ), ( "hello.mm", "source", "not-preprocessed" ), # ".mi" and ".mii" are preprocessed Objective-C/Objective-C++. ( "hello.mi", "source", "preprocessed" ), ( "hello.mii", "source", "preprocessed" ), ( "hello.2.4.4.i", "source", "preprocessed" ), ( ".foo", "not-source", "not-preprocessed" ), ( "gcc", "not-source", "not-preprocessed" ), ( "hello.ii", "source", "preprocessed" ), ( "boot.s", "not-source", "not-preprocessed" ), ( "boot.S", "not-source", "not-preprocessed" )) for f, issrc, iscpp in cases: o, err = self.runcmd("h_issource '%s'" % f) expected = ("%s %s\n" % (issrc, iscpp)) if o != expected: raise AssertionError("issource %s gave %s, expected %s" % (f, repr(o), repr(expected))) class ScanArgs_Case(SimpleDistCC_Case): '''Test understanding of gcc command lines.''' def runtest(self): cases = [("gcc -c hello.c", "distribute", "hello.c", "hello.o"), ("gcc hello.c", "local"), ("gcc -o /tmp/hello.o -c ../src/hello.c", "distribute", "../src/hello.c", "/tmp/hello.o"), ("gcc -DMYNAME=quasibar.c bar.c -c -o bar.o", "distribute", "bar.c", "bar.o"), ("gcc -ohello.o -c hello.c", "distribute", "hello.c", "hello.o"), ("ccache gcc -c hello.c", "distribute", "hello.c", "hello.o"), ("gcc hello.o", "local"), ("gcc -o hello.o hello.c", "local"), ("gcc -o hello.o -c hello.s", "local"), ("gcc -o hello.o -c hello.S", "local"), ("gcc -fprofile-arcs -ftest-coverage -c hello.c", "local", "hello.c", "hello.o"), ("gcc -S hello.c", "distribute", "hello.c", "hello.s"), ("gcc -c -S hello.c", "distribute", "hello.c", "hello.s"), ("gcc -S -c hello.c", "distribute", "hello.c", "hello.s"), ("gcc -M hello.c", "local"), ("gcc -ME hello.c", "local"), ("gcc -MD -c hello.c", "distribute", "hello.c", "hello.o"), ("gcc -MMD -c hello.c", "distribute", "hello.c", "hello.o"), # Assemble to stdout (thanks Alexandre). ("gcc -S foo.c -o -", "local"), ("-S -o - foo.c", "local"), ("-c -S -o - foo.c", "local"), ("-S -c -o - foo.c", "local"), # dasho syntax ("gcc -ofoo.o foo.c -c", "distribute", "foo.c", "foo.o"), ("gcc -ofoo foo.o", "local"), # tricky this one -- no dashc ("foo.c -o foo.o", "local"), ("foo.c -o foo.o -c", "distribute", "foo.c", "foo.o"), # Produce assembly listings ("gcc -Wa,-alh,-a=foo.lst -c foo.c", "local"), ("gcc -Wa,--MD -c foo.c", "local"), ("gcc -Wa,-xarch=v8 -c foo.c", "distribute", "foo.c", "foo.o"), # Produce .rpo files ("g++ -frepo foo.C", "local"), ("gcc -xassembler-with-cpp -c foo.c", "local"), ("gcc -x assembler-with-cpp -c foo.c", "local"), ("gcc -specs=foo.specs -c foo.c", "local"), # Fixed in 2.18.4 -- -dr writes rtl to a local file ("gcc -dr -c foo.c", "local"), ] for tup in cases: self.checkScanArgs(*tup) def checkScanArgs(self, ccmd, mode, input=None, output=None): o, err = self.runcmd("h_scanargs %s" % ccmd) o = o[:-1] # trim \n os = o.split() if mode != os[0]: self.fail("h_scanargs %s gave %s mode, expected %s" % (ccmd, os[0], mode)) if mode == 'distribute': if os[1] != input: self.fail("h_scanargs %s gave %s input, expected %s" % (ccmd, os[1], input)) if os[2] != output: self.fail("h_scanargs %s gave %s output, expected %s" % (ccmd, os[2], output)) class DotD_Case(SimpleDistCC_Case): '''Test the mechanism for calculating .d file names''' def runtest(self): # Each case specifies: # # - A compilation command. # # - A glob expression supposed to match exactly one file, the dependency # file (which is not always a .d file, btw). The glob expression is # our human intuition, based on our reading of the gcc manual pages, # of the range of possible dependency names actually produced. # # - Whether 0 or 1 such dependency files exist. # # - The expected target name (or None). # # The dotd_name is thus divined by examination of the compilation # directory where we actually run gcc. cases = [ ("foo.c -o hello.o -MD", "*.d", 1, None), ("foo.c -o hello.. -MD", "*.d", 1, None), ("foo.c -o hello.bar.foo -MD", "*.d", 1, None), ("foo.c -o hello.o", "*.d", 0, None), ("foo.c -o hello.bar.foo -MD", "*.d", 1, None), ("foo.c -MD", "*.d", 1, None), ("foo.c -o hello. -MD", "*.d", 1, None), # The following test case fails under Darwin Kernel Version 8.11.0. For some # reason, gcc refuses to produce 'hello.d' when the object file is named # 'hello.D'. # ("foo.c -o hello.D -MD -MT tootoo", "hello.*d", 1, "tootoo"), ("foo.c -o hello. -MD -MT tootoo", "hello.*d", 1, "tootoo"), ("foo.c -o hello.o -MD -MT tootoo", "hello.*d", 1, "tootoo"), ("foo.c -o hello.o -MD -MF foobar", "foobar", 1, None), ] # These C++ cases fail if your gcc installation doesn't support C++. error_rc, _, _ = self.runcmd_unchecked("touch testtmp.cpp; " + self._cc + " -c testtmp.cpp -o /dev/null") if error_rc == 0: cases.extend([("foo.cpp -o hello.o", "*.d", 0, None), ("foo.cpp -o hello", "*.d", 0, None)]) def _eval(out): map_out = eval(out) return (map_out['dotd_fname'], map_out['needs_dotd'], map_out['sets_dotd_target'], map_out['dotd_target']) for (args, dep_glob, how_many, target) in cases: # Determine what gcc says. dotd_result = [] # prepare for some imperative style value passing class TempCompile_Case(Compilation_Case): def source(self): return """ int main(void) { return 0; } """ def sourceFilename(self): return args.split()[0] def compileCmd(self): return self._cc + " -c " + args def runtest(self): self.compile() glob_result = glob.glob(dep_glob) dotd_result.extend(glob_result) ret = comfychair.runtest(TempCompile_Case, 0, subtest=1) if ret: raise AssertionError( "Case (args:%s, dep_glob:%s, how_many:%s, target:%s)" % (args, dep_glob, how_many, target)) self.assert_equal(len(dotd_result), how_many) if how_many == 1: expected_dep_file = dotd_result[0] # Determine what dcc_get_dotd_info says. out, _err = self.runcmd("h_dotd dcc_get_dotd_info gcc -c %s" % args) dotd_fname, needs_dotd, sets_dotd_target, dotd_target = _eval(out) assert dotd_fname assert needs_dotd in [0,1] # Assert that "needs_dotd == 1" if and only if "how_many == 1". assert needs_dotd == how_many # Assert that "needs_dotd == 1" implies names by gcc and our routine # are the same. if needs_dotd: self.assert_equal(expected_dep_file, dotd_fname) self.assert_equal(sets_dotd_target == 1, target != None) if target: # A little convoluted: because target is set in command line, # and the command line is passed already, the dotd_target is not # set. self.assert_equal(dotd_target, "None") # Now some fun with DEPENDENCIES_OUTPUT variable. try: os.environ["DEPENDENCIES_OUTPUT"] = "xxx.d yyy" out, _err = self.runcmd("h_dotd dcc_get_dotd_info gcc -c foo.c") dotd_fname, needs_dotd, sets_dotd_target, dotd_target = _eval(out) assert dotd_fname == "xxx.d" assert needs_dotd assert not sets_dotd_target assert dotd_target == "yyy" os.environ["DEPENDENCIES_OUTPUT"] = "zzz.d" out, _err = self.runcmd("h_dotd dcc_get_dotd_info gcc -c foo.c") dotd_fname, needs_dotd, sets_dotd_target, dotd_target = _eval(out) assert dotd_fname == "zzz.d" assert needs_dotd assert not sets_dotd_target assert dotd_target == "None" finally: del os.environ["DEPENDENCIES_OUTPUT"] class Compile_c_Case(SimpleDistCC_Case): """Unit tests for source file 'compile.c.' Currently, only the functions dcc_fresh_dependency_exists() and dcc_discrepancy_filename() are tested. """ def getDep(self, line): """Parse line to yield dependency name. From say: "src/h_compile.c[21010] (dcc_fresh_dependency_exists) Checking dependency: bar_bar" return "bar_bar". """ m_obj = re.search(r"Checking dependency: ((\w|[.])*)", line) assert m_obj, line return m_obj.group(1) def runtest(self): # Test dcc_discrepancy_filename # ******************************** os.environ['INCLUDE_SERVER_PORT'] = "abc/socket" out, err = self.runcmd( "h_compile dcc_discrepancy_filename") self.assert_equal(out, "abc/discrepancy_counter") os.environ['INCLUDE_SERVER_PORT'] = "socket" out, err = self.runcmd( "h_compile dcc_discrepancy_filename") self.assert_equal(out, "(NULL)") # os.environ will be cleaned out at start of next test. # Test dcc_fresh_dependency_exists # ******************************** dotd_cases = [(""" foo.o: foo\ bar.h bar.h notthisone.h bar.h\ """, ["foobar.h", "bar.h"]), ( """foo_foo :\ bar_bar \ foo_bar""", ["bar_bar", "foo_bar"]), (":", []), ("\n", []), ("", []), ("foo.o:", []), ] for dotd_contents, deps in dotd_cases: for dep in deps: _Touch(dep) # Now postulate the time that is the beginning of build. This time # is after that of all the dependencies. time_ref = time.time() + 1 # Let real-time advance to time_ref. while time.time() < time_ref: time.sleep(1) # Create .d file now, so that it appears to be no older than # time_ref. dotd_fd = open("dotd", "w") dotd_fd.write(dotd_contents) dotd_fd.close() # Check: no fresh files here! out, err = self.runcmd( "h_compile dcc_fresh_dependency_exists dotd '%s' %i" % ("*notthis*", time_ref)) self.assert_equal(out.split()[1], "(NULL)"); checked_deps = {} for line in err.split("\n"): if re.search("[^ ]", line): # Line is non-blank checked_deps[self.getDep(line)] = 1 deps_list = deps[:] checked_deps_list = list(checked_deps.keys()) deps_list.sort() checked_deps_list.sort() self.assert_equal(checked_deps_list, deps_list) # Let's try to touch, say the last dep file. Then, we should expect # the name of that very file as the output because there's a fresh # file. if deps: _Touch(deps[-1]) out, err = self.runcmd( "h_compile dcc_fresh_dependency_exists dotd '' %i" % time_ref) self.assert_equal(out.split()[1], deps[-1]) class ImplicitCompilerScan_Case(ScanArgs_Case): '''Test understanding of commands with no compiler''' def runtest(self): cases = [("-c hello.c", "distribute", "hello.c", "hello.o"), ("hello.c -c", "distribute", "hello.c", "hello.o"), ("-o hello.o -c hello.c", "distribute", "hello.c", "hello.o"), ] for tup in cases: # NB use "apply" rather than new syntax for compatibility with # venerable Pythons. self.checkScanArgs(*tup) class ExtractExtension_Case(SimpleDistCC_Case): def runtest(self): """Test extracting extensions from filenames""" for f, e in (("hello.c", ".c"), ("hello.cpp", ".cpp"), ("hello.2.4.4.4.c", ".c"), (".foo", ".foo"), ("gcc", "(NULL)")): out, err = self.runcmd("h_exten '%s'" % f) assert out == e class DaemonBadPort_Case(SimpleDistCC_Case): def runtest(self): """Test daemon invoked with invalid port number""" self.runcmd(self.distccd() + "--log-file=distccd.log --lifetime=10 --port 80000 " "--allow 127.0.0.1 --enable-tcp-insecure", EXIT_BAD_ARGUMENTS) self.assert_no_file("daemonpid.tmp") class InvalidHostSpec_Case(SimpleDistCC_Case): def runtest(self): """Test various invalid DISTCC_HOSTS See also test_parse_host_spec, which tests valid specifications.""" for spec in ["", " ", "\t", " @ ", ":", "mbp@", "angry::", ":4200"]: self.runcmd(("DISTCC_HOSTS=\"%s\" " % spec) + self.valgrind() + "h_hosts -v", EXIT_BAD_HOSTSPEC) class ParseHostSpec_Case(SimpleDistCC_Case): def runtest(self): """Check operation of dcc_parse_hosts_env. Passes complex environment variables to h_hosts, which is a C wrapper that calls the appropriate tests.""" spec="""localhost 127.0.0.1 @angry ted@angry \t@angry:/home/mbp/bin/distccd angry:4204 ipv4-localhost angry/44 angry:300/44 angry/44:300 angry,lzo angry:3000,lzo # some comment angry/44,lzo @angry,lzo#asdasd # oh yeah nothing here @angry:/usr/sbin/distccd,lzo localhostbutnotreally """ expected="""16 2 LOCAL 4 TCP 127.0.0.1 3632 4 SSH (no-user) angry (no-command) 4 SSH ted angry (no-command) 4 SSH (no-user) angry /home/mbp/bin/distccd 4 TCP angry 4204 4 TCP ipv4-localhost 3632 44 TCP angry 3632 44 TCP angry 300 44 TCP angry 300 4 TCP angry 3632 4 TCP angry 3000 44 TCP angry 3632 4 SSH (no-user) angry (no-command) 4 SSH (no-user) angry /usr/sbin/distccd 4 TCP localhostbutnotreally 3632 """ out, err = self.runcmd(("DISTCC_HOSTS=\"%s\" " % spec) + self.valgrind() + "h_hosts") assert out == expected, "expected %s\ngot %s" % (repr(expected), repr(out)) class Compilation_Case(WithDaemon_Case): '''Test distcc by actually compiling a file''' def setup(self): WithDaemon_Case.setup(self) self.createSource() def runtest(self): self.compile() self.link() self.checkBuiltProgram() def createSource(self): filename = self.sourceFilename() f = open(filename, 'w') f.write(self.source()) f.close() filename = self.headerFilename() f = open(filename, 'w') f.write(self.headerSource()) f.close() def sourceFilename(self): return "testtmp.c" # default def headerFilename(self): return "testhdr.h" # default def headerSource(self): return "" # default def compile(self): cmd = self.compileCmd() out, err = self.runcmd(cmd) if out != '': self.fail("compiler command %s produced output:\n%s" % (repr(cmd), out)) if err != '': self.fail("compiler command %s produced error:\n%s" % (repr(cmd), err)) def link(self): cmd = self.linkCmd() out, err = self.runcmd(cmd) if out != '': self.fail("command %s produced output:\n%s" % (repr(cmd), repr(out))) if err != '': self.fail("command %s produced error:\n%s" % (repr(cmd), repr(err))) def compileCmd(self): """Return command to compile source""" return self.distcc_without_fallback() + \ self._cc + " -o testtmp.o " + self.compileOpts() + \ " -c %s" % (self.sourceFilename()) def compileOpts(self): """Returns any extra options to pass when compiling""" return "" def linkCmd(self): """Return command to link object files""" return self.distcc() + \ self._cc + " -o testtmp testtmp.o " + self.libraries() def libraries(self): """Returns any '-l' options needed to link the program.""" return "" def checkCompileMsgs(self, msgs): if len(msgs) > 0: self.fail("expected no compiler messages, got \"%s\"" % msgs) def checkBuiltProgram(self): '''Check compile/link results. By default, just try to execute.''' msgs, errs = self.runcmd("./testtmp") self.checkBuiltProgramMsgs(msgs) self.assert_equal(errs, '') def checkBuiltProgramMsgs(self, msgs): pass class CompileHello_Case(Compilation_Case): """Test the simple case of building a program that works properly""" def headerSource(self): return """ #define HELLO_WORLD "hello world" """ def source(self): return """ #include #include "%s" int main(void) { puts(HELLO_WORLD); return 0; } """ % self.headerFilename() def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello world\n") class CommaInFilename_Case(CompileHello_Case): def headerFilename(self): return 'foo1,2.h' class ComputedInclude_Case(CompileHello_Case): def source(self): return """ #include #define MAKE_HEADER(header_name) STRINGIZE(header_name.h) #define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE2(x) #x #define HEADER MAKE_HEADER(testhdr) #include HEADER int main(void) { puts(HELLO_WORLD); return 0; } """ class BackslashInMacro_Case(ComputedInclude_Case): def source(self): return """ #include #if FALSE #define HEADER MAKE_HEADER(testhdr) #define MAKE_HEADER(header_name) STRINGIZE(foobar\) #define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE2(x) #x #else #define HEADER "testhdr.h" #endif #include HEADER int main(void) { puts(HELLO_WORLD); return 0; } """ class BackslashInFilename_Case(ComputedInclude_Case): def headerFilename(self): # On Windows, this filename will be in a subdirectory. # On Unix, it will be a filename with an embedded backslash. try: os.mkdir("subdir") except: pass return 'subdir\\testhdr.h' def source(self): return """ #include #define HEADER MAKE_HEADER(testhdr) #define MAKE_HEADER(header_name) STRINGIZE(subdir\header_name.h) #define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE2(x) #x #include HEADER int main(void) { puts(HELLO_WORLD); return 0; } """ class LanguageSpecific_Case(Compilation_Case): """Abstract base class to test building non-C programs.""" def runtest(self): # Don't try to run the test if the language's compiler is not installed source = self.sourceFilename() lang = self.languageGccName() error_rc, _, _ = self.runcmd_unchecked( "touch " + source + "; " + "rm -f testtmp.o; " + self._cc + " -x " + lang + " " + self.compileOpts() + " -c " + source + " " + self.libraries() + " && " + "test -f testtmp.o" ) if error_rc != 0: raise comfychair.NotRunError ('GNU ' + self.languageName() + ' not installed') else: Compilation_Case.runtest (self) def sourceFilename(self): return "testtmp" + self.extension() def languageGccName(self): """Language name suitable for use with 'gcc -x'""" raise NotImplementedError def languageName(self): """Human-readable language name.""" raise NotImplementedError def extension(self): """Filename extension, with leading '.'.""" raise NotImplementedError class CPlusPlus_Case(LanguageSpecific_Case): """Test building a C++ program.""" def languageName(self): return "C++" def languageGccName(self): return "c++" def extension(self): return ".cpp" # Could also use ".cc", ".cxx", etc. def libraries(self): return "-lstdc++" def headerSource(self): return """ #define MESSAGE "hello c++" """ def source(self): return """ #include #include "testhdr.h" int main(void) { std::cout << MESSAGE << std::endl; return 0; } """ def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello c++\n") class ObjectiveC_Case(LanguageSpecific_Case): """Test building an Objective-C program.""" def languageName(self): return "Objective-C" def languageGccName(self): return "objective-c" def extension(self): return ".m" def headerSource(self): return """ #define MESSAGE "hello objective-c" """ def source(self): return """ #import #import "testhdr.h" /* TODO: use objective-c features. */ int main(void) { puts(MESSAGE); return 0; } """ class ObjectiveCPlusPlus_Case(LanguageSpecific_Case): """Test building an Objective-C++ program.""" def languageName(self): return "Objective-C++" def languageGccName(self): return "objective-c++" def extension(self): return ".mm" def libraries(self): return "-lstdc++" def headerSource(self): return """ #define MESSAGE "hello objective-c++" """ def source(self): return """ #import #import "testhdr.h" /* TODO: use Objective-C features. */ int main(void) { std::cout << MESSAGE << std::endl; return 0; } """ def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello objective-c++\n") class SystemIncludeDirectories_Case(Compilation_Case): """Test -I/usr/include/sys""" def compileOpts(self): if os.path.exists("/usr/include/sys/types.h"): return "-I/usr/include/" else: raise comfychair.NotRunError ( "This test requires /usr/include/sys/types.h") def headerSource(self): return """ #define HELLO_WORLD "hello world" """ def source(self): return """ #include "sys/types.h" /* Should resolve to /usr/include/sys/types.h. */ #include #include "testhdr.h" int main(void) { uint val = 1u; puts(HELLO_WORLD); return val == 1 ? 0 : 1; } """ def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello world\n") class CPlusPlus_SystemIncludeDirectories_Case(CPlusPlus_Case): """Test -I/usr/include/sys for a C++ program""" def compileOpts(self): if os.path.exists("/usr/include/sys/types.h"): return "-I/usr/include/sys" else: raise comfychair.NotRunError ( "This test requires /usr/include/sys/types.h") def headerSource(self): return """ #define MESSAGE "hello world" """ def source(self): return """ #include "types.h" /* Should resolve to /usr/include/sys/types.h. */ #include "testhdr.h" #include int main(void) { puts(MESSAGE); return 0; } """ def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello world\n") class Gdb_Case(CompileHello_Case): """Test that distcc generates correct debugging information.""" def sourceFilename(self): try: os.mkdir("src") except: pass return "src/testtmp.c" def compiler(self): """Command for compiling and linking.""" return self._cc + " -g "; def compileCmd(self): """Return command to compile source""" os.mkdir("obj") return self.distcc_without_fallback() + self.compiler() + \ " -o obj/testtmp.o -I. -c %s" % (self.sourceFilename()) def link(self): """ We do the linking in a subdirectory, so that the 'compilation directory' field of the debug info set by the link step (which will be done locally, not remotely) does NOT influence the behaviour of gdb. We want gdb to use the 'compilation directory' value set by the compilation. """ os.mkdir('link') cmd = (self.distcc() + self.compiler() + self.build_id + " -o link/testtmp obj/testtmp.o") out, err = self.runcmd(cmd) if out != '': self.fail("command %s produced output:\n%s" % (repr(cmd), repr(out))) if err != '': self.fail("command %s produced error:\n%s" % (repr(cmd), repr(err))) def runtest(self): # Don't try to run the test if gdb is not installed error_rc, _, _ = self.runcmd_unchecked("gdb --help") if error_rc != 0: raise comfychair.NotRunError ('gdb could not be found on path') # Test if the compiler supports --build-id=0xNNN. # If so, we need to use it for this test. # If not, try the alternative syntax -Wl,--build-id=0xNNN instead. self.build_id = " --build-id=0x12345678 " error_rc, _, _ = self.runcmd_unchecked(self.compiler() + (self.build_id + " -o junk -I. %s" % self.sourceFilename())) if error_rc != 0: self.build_id = " -Wl,--build-id=0x12345678 " error_rc, _, _ = self.runcmd_unchecked(self.compiler() + (self.build_id + " -o junk -I. %s" % self.sourceFilename())) if error_rc != 0: self.build_id = "" CompileHello_Case.runtest (self) def checkBuiltProgram(self): # On windows, the binary may be called testtmp.exe. Check both if os.path.exists('link/testtmp.exe'): testtmp_exe = 'testtmp.exe' else: testtmp_exe = 'testtmp' # Run gdb and verify that it is able to correctly locate the # testtmp.c source file. We write the gdb commands to a file # and run them via gdb --command. (The alternative, to specify # the gdb commands directly on the commandline using gdb --ex, # is not as portable since only newer gdb's support it.) f = open('gdb_commands', 'w') f.write('break main\nrun\nnext\n') f.close() out, errs = self.runcmd("gdb -nh --batch --command=gdb_commands " "link/%s /dev/null" % self.sourceFilename()) gcc_preprocessing_preserves_pwd = (error_rc == 0); if ((pump_mode and _IsElf('./%s' % testtmp_exe)) or ((not pump_mode) and gcc_preprocessing_preserves_pwd)): out, errs = self.runcmd("gdb -nh --batch --command=../gdb_commands " "./%s acceptable_diffbytes)): # Just do the cmp again to give a good error message self.runcmd("cmp link/%s run/%s" % (testtmp_exe, testtmp_exe)) class GdbOpt1_Case(Gdb_Case): def compiler(self): """Command for compiling and linking.""" return self._cc + " -g -O1 "; class GdbOpt2_Case(Gdb_Case): def compiler(self): """Command for compiling and linking.""" return self._cc + " -g -O2 "; class GdbOpt3_Case(Gdb_Case): def compiler(self): """Command for compiling and linking.""" return self._cc + " -g -O3 "; class CompressedCompile_Case(CompileHello_Case): """Test compilation with compression. The source needs to be moderately large to make sure compression and mmap is turned on.""" def source(self): return """ #include #include #include #include "testhdr.h" int main(void) { printf("%s\\n", HELLO_WORLD); return 0; } """ def setupEnv(self): Compilation_Case.setupEnv(self) os.environ['DISTCC_HOSTS'] = '127.0.0.1:%d,lzo' % self.server_port class DashONoSpace_Case(CompileHello_Case): def compileCmd(self): return self.distcc_without_fallback() + \ self._cc + " -otesttmp.o -c %s" % (self.sourceFilename()) def runtest(self): if sys.platform == 'sunos5': raise comfychair.NotRunError ('Sun assembler wants space after -o') elif sys.platform.startswith ('osf1'): raise comfychair.NotRunError ('GCC mips-tfile wants space after -o') else: CompileHello_Case.runtest (self) class WriteDevNull_Case(CompileHello_Case): def runtest(self): self.compile() def compileCmd(self): return self.distcc_without_fallback() + self._cc + \ " -c -o /dev/null -c %s" % (self.sourceFilename()) class MultipleCompile_Case(Compilation_Case): """Test compiling several files from one line""" def setup(self): WithDaemon_Case.setup(self) open("test1.c", "w").write("const char *msg = \"hello foreigner\";") open("test2.c", "w").write("""#include int main(void) { extern const char *msg; puts(msg); return 0; } """) def runtest(self): self.runcmd(self.distcc() + self._cc + " -c test1.c test2.c") self.runcmd(self.distcc() + self._cc + " -o test test1.o test2.o") class CppError_Case(CompileHello_Case): """Test failure of cpp""" def source(self): return '#error "not tonight dear"\n' def runtest(self): cmd = self.distcc() + self._cc + " -c testtmp.c" msgs, errs = self.runcmd(cmd, expectedResult=1) self.assert_re_search("not tonight dear", errs) self.assert_equal(msgs, '') class BadInclude_Case(Compilation_Case): """Handling of error running cpp""" def source(self): return """#include """ def runtest(self): if _server_options.find('cpp') != -1: # Annoyingly, different versions of gcc are inconsistent # in how they treat a non-existent #include file when # invoked with "-MMD": some versions treat it as an error # (rc 1), some as a warning (rc 0). When distcc is # responsible for preprocessing (_server_options includes # 'cpp'), we need to figure out which our gcc does, in # order to verify distcc is doing the same thing. # FIXME(klarlund): this is arguably a bug in gcc, and it # is exacerbated by distcc's pump mode because we always # pass -MMD, even when the user didn't. TODO(klarlund): # change error_rc back to 1 once that FIXME is fixed. error_rc, _, _ = self.runcmd_unchecked(self._cc + " -MMD -E testtmp.c") else: error_rc = 1 self.runcmd(self.distcc() + self._cc + " -o testtmp.o -c testtmp.c", error_rc) class PreprocessPlainText_Case(Compilation_Case): """Try using cpp on something that's not C at all""" def setup(self): self.stripEnvironment() self.createSource() self.initCompiler() def source(self): return """#define FOO 3 #if FOO < 10 small foo! #else large foo! #endif /* comment ca? */ """ def runtest(self): # -P means not to emit linemarkers self.runcmd(self.distcc() + self._cc + " -E testtmp.c -o testtmp.out") out = open("testtmp.out").read() # It's a bit hard to know the exact value, because different versions of # GNU cpp seem to handle the whitespace differently. self.assert_re_search("small foo!", out) def teardown(self): # no daemon is run for this test pass class NoDetachDaemon_Case(CompileHello_Case): """Test the --no-detach option.""" def startDaemon(self): # FIXME: This does not work well if it happens to get the same # port as an existing server, because we can't catch the error. cmd = (self.distccd() + "--no-detach --daemon --verbose --log-file %s --pid-file %s " "--port %d --allow 127.0.0.1 --enable-tcp-insecure" % (_ShellSafe(self.daemon_logfile), _ShellSafe(self.daemon_pidfile), self.server_port)) self.pid = self.runcmd_background(cmd) self.add_cleanup(self.killDaemon) # Wait until the server is ready for connections. time.sleep(0.2) # Give distccd chance to start listening on the port sock = socket.socket() while sock.connect_ex(('127.0.0.1', self.server_port)) != 0: time.sleep(0.2) def killDaemon(self): os.kill(self.pid, signal.SIGTERM) pid, ret = os.wait() self.assert_equal(self.pid, pid) class ImplicitCompiler_Case(CompileHello_Case): """Test giving no compiler works""" def compileCmd(self): return self.distcc() + "-c testtmp.c" def linkCmd(self): # FIXME: Mozilla uses something like "distcc testtmp.o -o testtmp", # but that's broken at the moment. return self.distcc() + "-o testtmp testtmp.o " def runtest(self): if sys.platform == 'hp-ux10': raise comfychair.NotRunError ('HP-UX bundled C compiler non-ANSI') # We can't run if cc is not installed on the system (maybe only gcc is) error_rc, _, _ = self.runcmd_unchecked("cc -c testtmp.c") self.runcmd_unchecked("rm -f testtmp.o") # clean up the 'cc' output if error_rc != 0: raise comfychair.NotRunError ('Cannot find working "cc"') else: CompileHello_Case.runtest (self) class DashD_Case(Compilation_Case): """Test preprocessor arguments""" def source(self): return """ #include int main(void) { printf("%s\\n", MESSAGE); return 0; } """ def compileOpts(self): # quoting is hairy because this goes through the shell return "'-DMESSAGE=\"hello DashD\"'" def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello DashD\n") class DashMD_DashMF_DashMT_Case(CompileHello_Case): """Test -MD -MFfoo -MTbar""" def compileOpts(self): return "-MD -MFdotd_filename -MTtarget_name_42" def runtest(self): try: os.remove('dotd_filename') except OSError: pass self.compile(); dotd_contents = open("dotd_filename").read() self.assert_re_search("target_name_42", dotd_contents) class DashWpMD_Case(CompileHello_Case): """Test -Wp,-MD,depfile""" def compileOpts(self): return "-Wp,-MD,depsfile" def runtest(self): try: os.remove('depsfile') except OSError: pass self.compile() deps = open('depsfile').read() self.assert_re_search(r"testhdr\.h", deps) self.assert_re_search(r"stdio\.h", deps) class ScanIncludes_Case(CompileHello_Case): """Test --scan-includes""" def createSource(self): CompileHello_Case.createSource(self) self.runcmd("mv testhdr.h test_header.h") self.runcmd("ln -s test_header.h testhdr.h") self.runcmd("mkdir test_subdir") self.runcmd("touch test_another_header.h") def headerSource(self): return """ #define HELLO_WORLD "hello world" #include "test_subdir/../test_another_header.h" """ def compileCmd(self): return self.distcc_without_fallback() + "--scan-includes " + \ self._cc + " -o testtmp.o " + self.compileOpts() + \ " -c %s" % (self.sourceFilename()) def runtest(self): cmd = self.compileCmd() rc, out, err = self.runcmd_unchecked(cmd) log = open('distcc.log').read() pump_mode = _server_options.find('cpp') != -1 if pump_mode: if err != '': self.fail("distcc command %s produced stderr:\n%s" % (repr(cmd), err)) if rc != 0: self.fail("distcc command %s failed:\n%s" % (repr(cmd), rc)) self.assert_re_search( r"FILE /.*/ScanIncludes_Case/testtmp.c", out); self.assert_re_search( r"FILE /.*/ScanIncludes_Case/test_header\.h", out); self.assert_re_search( r"FILE /.*/ScanIncludes_Case/test_another_header\.h", out); self.assert_re_search( r"SYMLINK /.*/ScanIncludes_Case/testhdr\.h", out); self.assert_re_search( r"DIRECTORY /.*/ScanIncludes_Case/test_subdir", out); self.assert_re_search( r"SYSTEMDIR /.*", out); else: self.assert_re_search(r"ERROR: '--scan_includes' specified, but " "distcc wouldn't have used include server " ".make sure hosts list includes ',cpp' option", log) self.assert_equal(rc, 100) self.assert_equal(out, '') self.assert_equal(err, '') class AbsSourceFilename_Case(CompileHello_Case): """Test remote compilation of files with absolute names.""" def compileCmd(self): return (self.distcc() + self._cc + " -c -o testtmp.o %s/testtmp.c" % _ShellSafe(os.getcwd())) class HundredFold_Case(CompileHello_Case): """Try repeated simple compilations. This used to be a ThousandFold_Case -- but that slowed down testing significantly. It's unclear that testing a 1000 times is much better than doing it a 100 times. """ def daemon_lifetime(self): return 120 def runtest(self): for unused_i in range(100): self.runcmd(self.distcc() + self._cc + " -o testtmp.o -c testtmp.c") class Concurrent_Case(CompileHello_Case): """Try many compilations at the same time""" def daemon_lifetime(self): return 120 def runtest(self): # may take about a minute or so pids = {} for unused_i in range(50): kid = self.runcmd_background(self.distcc() + self._cc + " -o testtmp.o -c testtmp.c") pids[kid] = kid while len(pids): pid, status = os.wait() if status: self.fail("child %d failed with status %#x" % (pid, status)) del pids[pid] class BigAssFile_Case(Compilation_Case): """Test compilation of a really big C file This will take a while to run""" def createSource(self): """Create source file""" f = open("testtmp.c", 'wt') # We want a file of many, which will be a few megabytes of # source. Picking the size is kind of hard -- something that # will properly exercise distcc may be too big for small/old # machines. f.write("int main() {}\n") for i in range(200000): f.write("int i%06d = %d;\n" % (i, i)) f.close() def runtest(self): self.runcmd(self.distcc() + self._cc + " -c %s" % "testtmp.c") self.runcmd(self.distcc() + self._cc + " -o testtmp testtmp.o") def daemon_lifetime(self): return 300 class BinFalse_Case(Compilation_Case): """Compiler that fails without reading input. This is an interesting case when the server is using fifos, because it has to cope with the open() on the fifo being interrupted. distcc doesn't know that 'false' is not a compiler, but it does need a command line that looks like a compiler invocation. We have to use a .i file so that distcc does not try to preprocess it. """ def createSource(self): open("testtmp.i", "wt").write("int main() {}") def runtest(self): # On Solaris and IRIX 6, 'false' returns exit status 255 if sys.platform == 'sunos5' or \ sys.platform.startswith ('irix6'): self.runcmd(self.distcc() + "false -c testtmp.i", 255) else: self.runcmd(self.distcc() + "false -c testtmp.i", 1) class BinTrue_Case(Compilation_Case): """Compiler that succeeds without reading input. This is an interesting case when the server is using fifos, because it has to cope with the open() on the fifo being interrupted. distcc doesn't know that 'true' is not a compiler, but it does need a command line that looks like a compiler invocation. We have to use a .i file so that distcc does not try to preprocess it. """ def createSource(self): open("testtmp.i", "wt").write("int main() {}") def runtest(self): self.runcmd(self.distcc() + "true -c testtmp.i", 0) class SBeatsC_Case(CompileHello_Case): """-S overrides -c in gcc. If both options are given, we have to make sure we imply the output filename in the same way as gcc.""" # XXX: Are other compilers the same? def runtest(self): self.runcmd(self.distcc() + self._cc + " -c -S testtmp.c") if os.path.exists("testtmp.o"): self.fail("created testtmp.o but should not have") if not os.path.exists("testtmp.s"): self.fail("did not create testtmp.s but should have") class NoServer_Case(CompileHello_Case): """Invalid server name""" def setup(self): self.stripEnvironment() os.environ['DISTCC_HOSTS'] = 'no.such.host.here' self.distcc_log = 'distcc.log' os.environ['DISTCC_LOG'] = self.distcc_log self.createSource() self.initCompiler() def runtest(self): self.runcmd(self.distcc() + self._cc + " -c -o testtmp.o testtmp.c") msgs = open(self.distcc_log, 'r').read() self.assert_re_search(r'failed to distribute.*running locally instead', msgs) class ImpliedOutput_Case(CompileHello_Case): """Test handling absence of -o""" def compileCmd(self): return self.distcc() + self._cc + " -c testtmp.c" class SyntaxError_Case(Compilation_Case): """Test building a program containing syntax errors, so it won't build properly.""" def source(self): return """not C source at all """ def compile(self): rc, msgs, errs = self.runcmd_unchecked(self.compileCmd()) self.assert_notequal(rc, 0) self.assert_re_search(r'testtmp.c:1:.*error', errs) self.assert_equal(msgs, '') def runtest(self): self.compile() if os.path.exists("testtmp") or os.path.exists("testtmp.o"): self.fail("compiler produced output, but should not have done so") class NoHosts_Case(CompileHello_Case): """Test running with no hosts defined. We expect compilation to succeed, but with a warning that it was run locally.""" def runtest(self): # WithDaemon_Case sets this to point to the local host, but we # don't want that. Note that you cannot delete environment # keys in Python1.5, so we need to just set them to the empty # string. os.environ['DISTCC_HOSTS'] = '' os.environ['DISTCC_LOG'] = '' self.runcmd('env') msgs, errs = self.runcmd(self.compileCmd()) # We expect only one message, a warning from distcc self.assert_re_search(r"Warning.*\$DISTCC_HOSTS.*can't distribute work", errs) def compileCmd(self): """Return command to compile source and run tests""" return self.distcc_with_fallback() + \ self._cc + " -o testtmp.o -c %s" % (self.sourceFilename()) class MissingCompiler_Case(CompileHello_Case): """Test compiler missing from server.""" # Another way to test this would be to break the server's PATH def sourceFilename(self): # must be preprocessed, so that we don't need to run the compiler # on the client return "testtmp.i" def source(self): return """int foo;""" def runtest(self): msgs, errs = self.runcmd(self.distcc_without_fallback() + "nosuchcc -c testtmp.i", expectedResult=EXIT_COMPILER_MISSING) self.assert_re_search(r'failed to exec', errs) class RemoteAssemble_Case(WithDaemon_Case): """Test remote assembly of a .s file.""" # We have a rather tricky method for testing assembly code when we # don't know what platform we're on. I think this one will work # everywhere, though perhaps not. # We don't use @ because that starts comments for ARM. asm_source = """ .file "foo.c" .globl msg .section .rodata .LC0: .string "hello world" .data .align 4 .type msg,object .size msg,4 msg: .long .LC0 """ asm_filename = 'test2.s' def setup(self): WithDaemon_Case.setup(self) open(self.asm_filename, 'wt').write(self.asm_source) def compile(self): # Need to build both the C file and the assembly file self.runcmd(self.distcc() + self._cc + " -o test2.o -c test2.s") class PreprocessAsm_Case(WithDaemon_Case): """Run preprocessor locally on assembly, then compile locally.""" asm_source = """ #define MSG "hello world" gcc2_compiled.: .globl msg .section .rodata .LC0: .string MSG .data .align 4 .type msg,object .size msg,4 msg: .long .LC0 """ def setup(self): WithDaemon_Case.setup(self) open('test2.S', 'wt').write(self.asm_source) def compile(self): if sys.platform == 'linux2': self.runcmd(self.distcc() + "-o test2.o -c test2.S") else: raise comfychair.NotRunError ('this test is system-specific') def runtest(self): self.compile() class ModeBits_Case(CompileHello_Case): """Check distcc obeys umask""" def runtest(self): self.runcmd("umask 0; distcc " + self._cc + " -c testtmp.c") self.assert_equal(S_IMODE(os.stat("testtmp.o")[ST_MODE]), 0o666) class CheckRoot_Case(SimpleDistCC_Case): """Stub case that checks this is run by root. Not used by default.""" def setup(self): self.require_root() class EmptySource_Case(Compilation_Case): """Check compilation of empty source file It must be treated as preprocessed source, otherwise cpp will insert a # line, which will give a false pass. This test fails with an internal compiler error in GCC 3.4.x for x < 5 (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20239 [3.4 Regression] ICE on empty preprocessed input). But that's gcc's problem, not ours, so we make this test pass if gcc gets an ICE.""" def source(self): return '' def runtest(self): self.compile() def compile(self): rc, out, errs = self.runcmd_unchecked(self.distcc() + self._cc + " -c %s" % self.sourceFilename()) if not re.search("internal compiler error", errs): self.assert_equal(rc, 0) def sourceFilename(self): return "testtmp.i" class BadLogFile_Case(CompileHello_Case): def runtest(self): self.runcmd("touch distcc.log") self.runcmd("chmod 0 distcc.log") msgs, errs = self.runcmd("DISTCC_LOG=distcc.log " + \ self.distcc() + \ self._cc + " -c testtmp.c", expectedResult=0) self.assert_re_search("failed to open logfile", errs) class AccessDenied_Case(CompileHello_Case): """Run the daemon, but don't allow access from this host. Make sure that compilation falls back to localhost with a warning.""" def daemon_command(self): return (self.distccd() + "--verbose --lifetime=%d --daemon --log-file %s " "--pid-file %s --port %d --allow 127.0.0.2 --enable-tcp-insecure" % (self.daemon_lifetime(), _ShellSafe(self.daemon_logfile), _ShellSafe(self.daemon_pidfile), self.server_port)) def compileCmd(self): """Return command to compile source and run tests""" return self.distcc_with_fallback() + \ self._cc + " -o testtmp.o -c %s" % (self.sourceFilename()) def runtest(self): self.compile() errs = open('distcc.log').read() self.assert_re_search(r'failed to distribute', errs) class ParseMask_Case(comfychair.TestCase): """Test code for matching IP masks.""" values = [ ('127.0.0.1', '127.0.0.1', 0), ('127.0.0.1', '127.0.0.0', EXIT_ACCESS_DENIED), ('127.0.0.1', '127.0.0.2', EXIT_ACCESS_DENIED), ('127.0.0.1/8', '127.0.0.2', 0), ('10.113.0.0/16', '10.113.45.67', 0), ('10.113.0.0/16', '10.11.45.67', EXIT_ACCESS_DENIED), ('10.113.0.0/16', '127.0.0.1', EXIT_ACCESS_DENIED), ('1.2.3.4/0', '4.3.2.1', 0), ('1.2.3.4/40', '4.3.2.1', EXIT_BAD_ARGUMENTS), ('1.2.3.4.5.6.7/8', '127.0.0.1', EXIT_BAD_ARGUMENTS), ('1.2.3.4/8', '4.3.2.1', EXIT_ACCESS_DENIED), ('192.168.1.64/28', '192.168.1.70', 0), ('192.168.1.64/28', '192.168.1.7', EXIT_ACCESS_DENIED), ] def runtest(self): for mask, client, expected in ParseMask_Case.values: cmd = "h_parsemask %s %s" % (mask, client) ret, msgs, err = self.runcmd_unchecked(cmd) if ret != expected: self.fail("%s gave %d, expected %d" % (cmd, ret, expected)) class HostFile_Case(CompileHello_Case): def setup(self): CompileHello_Case.setup(self) del os.environ['DISTCC_HOSTS'] self.save_home = os.environ['HOME'] os.environ['HOME'] = os.getcwd() # DISTCC_DIR is set to 'distccdir' open(os.environ['DISTCC_DIR'] + '/hosts', 'w').write('127.0.0.1:%d%s' % (self.server_port, _server_options)) def teardown(self): os.environ['HOME'] = self.save_home CompileHello_Case.teardown(self) class Lsdistcc_Case(WithDaemon_Case): """Check lsdistcc""" def lsdistccCmd(self): """Return command to run lsdistcc""" return "lsdistcc -r%d" % self.server_port def runtest(self): lsdistcc = self.lsdistccCmd() # Test "lsdistcc --help" output is reasonable. # (Note: "lsdistcc --help" ought to return exit status 0, really, # but currently it returns 1, so that's what we test for.) rc, out, err = self.runcmd_unchecked(lsdistcc + " --help") self.assert_re_search("Usage:", out) self.assert_equal(err, "") self.assert_equal(rc, 1) # On some systems, 127.0.0.* are all loopback addresses. # On other systems, only 127.0.0.1 is a loopback address. # The lsdistcc test is more effective if we can use 127.0.0.2 etc. # but that only works on some systems, so we need to check whether # if will work. The ping command is not very portable, but that # doesn't matter; if it fails, we just won't test quite as much as # we would if it succeeds. So long as it succeeds on Linux, we'll # get good enough test coverage. rc, out, err = self.runcmd_unchecked("ping -c 3 -i 0.2 -w 1 127.0.0.2") multiple_loopback_addrs = (rc == 0) # Test "lsdistcc host1 host2 host3". out, err = self.runcmd(lsdistcc + " localhost 127.0.0.1 127.0.0.2 " + " anInvalidHostname") out_list = out.split() out_list.sort() expected = ["%s:%d" % (host, self.server_port) for host in ["127.0.0.1", "127.0.0.2", "localhost"]] if multiple_loopback_addrs: self.assert_equal(out_list, expected) else: # It may be that 127.0.0.2 isn't a loopback address, or it # may be that it is, but ping doesn't support -c or -i or # -w. So be happy if 127.0.0.2 is there, or if it's not. if out_list != expected: del expected[1] # remove 127.0.0.2 self.assert_equal(out_list, expected) self.assert_equal(err, "") # Test "lsdistcc host%d". out, err = self.runcmd(lsdistcc + " 127.0.0.%d") self.assert_equal(err, "") self.assert_re_search("127.0.0.1:%d\n" % self.server_port, out) if multiple_loopback_addrs: self.assert_re_search("127.0.0.2:%d\n" % self.server_port, out) self.assert_re_search("127.0.0.3:%d\n" % self.server_port, out) self.assert_re_search("127.0.0.4:%d\n" % self.server_port, out) self.assert_re_search("127.0.0.5:%d\n" % self.server_port, out) class Getline_Case(comfychair.TestCase): """Test getline().""" values = [ # Input, Line, Rest, Retval ('', '', '', -1), ('\n', '\n', '', 1), ('\n\n', '\n', '\n', 1), ('\n\n\n', '\n', '\n\n', 1), ('a', 'a', '', 1), ('a\n', 'a\n', '', 2), ('foo', 'foo', '', 3), ('foo\n', 'foo\n', '', 4), ('foo\nbar\n', 'foo\n', 'bar\n', 4), ('foobar\nbaz', 'foobar\n', 'baz', 7), ('foo bar\nbaz', 'foo bar\n', 'baz', 8), ] def runtest(self): for input, line, rest, retval in Getline_Case.values: for bufsize in [None, 0, 1, 2, 3, 4, 64, 10000]: if bufsize: cmd = "printf '%s' | h_getline %s | cat -v" % (input, bufsize) n = bufsize else: cmd = "printf '%s' | h_getline | cat -v" % input n = 0 ret, msgs, err = self.runcmd_unchecked(cmd) self.assert_equal(ret, 0); self.assert_equal(err, ''); msg_parts = msgs.split(','); self.assert_equal(msg_parts[0], "original n = %s" % n); self.assert_equal(msg_parts[1], " returned %s" % retval); self.assert_equal(msg_parts[2].startswith(" n = "), True); self.assert_equal(msg_parts[3], " line = '%s'" % line); self.assert_equal(msg_parts[4], " rest = '%s'\n" % rest); # All the tests defined in this suite tests = [ CompileHello_Case, CommaInFilename_Case, ComputedInclude_Case, BackslashInMacro_Case, BackslashInFilename_Case, CPlusPlus_Case, ObjectiveC_Case, ObjectiveCPlusPlus_Case, SystemIncludeDirectories_Case, CPlusPlus_SystemIncludeDirectories_Case, Gdb_Case, GdbOpt1_Case, GdbOpt2_Case, GdbOpt3_Case, Lsdistcc_Case, BadLogFile_Case, ScanArgs_Case, ParseMask_Case, DotD_Case, DashMD_DashMF_DashMT_Case, Compile_c_Case, ImplicitCompilerScan_Case, StripArgs_Case, StartStopDaemon_Case, CompressedCompile_Case, DashONoSpace_Case, WriteDevNull_Case, CppError_Case, BadInclude_Case, PreprocessPlainText_Case, NoDetachDaemon_Case, SBeatsC_Case, DashD_Case, DashWpMD_Case, BinFalse_Case, BinTrue_Case, VersionOption_Case, HelpOption_Case, BogusOption_Case, MultipleCompile_Case, CompilerOptionsPassed_Case, IsSource_Case, ExtractExtension_Case, ImplicitCompiler_Case, DaemonBadPort_Case, AccessDenied_Case, NoServer_Case, InvalidHostSpec_Case, ParseHostSpec_Case, ImpliedOutput_Case, SyntaxError_Case, NoHosts_Case, MissingCompiler_Case, RemoteAssemble_Case, PreprocessAsm_Case, ModeBits_Case, EmptySource_Case, HostFile_Case, AbsSourceFilename_Case, Getline_Case, # slow tests below here Concurrent_Case, HundredFold_Case, BigAssFile_Case] if __name__ == '__main__': while len(sys.argv) > 1 and sys.argv[1].startswith("--"): if sys.argv[1] == "--valgrind": _valgrind_command = "valgrind --quiet " del sys.argv[1] elif sys.argv[1].startswith("--valgrind="): _valgrind_command = sys.argv[1][len("--valgrind="):] + " " del sys.argv[1] elif sys.argv[1] == "--lzo": _server_options = ",lzo" del sys.argv[1] elif sys.argv[1] == "--pump": _server_options = ",lzo,cpp" del sys.argv[1] # Some of these tests need lots of file descriptors (especially to fork), # but sometimes the os only supplies a few. Try to raise that if we can. try: import resource (_, hard_limit) = resource.getrlimit(resource.RLIMIT_NOFILE) resource.setrlimit(resource.RLIMIT_NOFILE, (hard_limit, hard_limit)) except (ImportError, ValueError): pass comfychair.main(tests) distcc-3.4/update-distcc-symlinks.py000077500000000000000000000042271404653710500176200ustar00rootroot00000000000000#!/usr/bin/env python3 import subprocess, string, os, stat, re distcc_dir = "/usr/lib/distcc" gcc_dir = "/usr/lib/gcc" gcccross_dir = "/usr/lib/gcc-cross" old_symlinks = set() new_symlinks = set() standard_names = ["cc", "c++", "c89", "c99"] if not os.access(distcc_dir, os.X_OK): os.mkdir(distcc_dir) def consider(name): if os.access("/usr/bin/%(name)s" % vars(), os.X_OK): new_symlinks.add(name) print(name) def consider_gcc(prefix, suffix): consider("%(prefix)sgcc%(suffix)s" % vars()) consider("%(prefix)sg++%(suffix)s" % vars()) def consider_clang(suffix): consider("clang%(suffix)s" % vars()) consider("clang++%(suffix)s" % vars()) for x in standard_names: consider(x) consider_gcc("", "") consider_gcc("c89-", "") consider_gcc("c99-", "") try: for gnu_host in os.listdir(gcc_dir): consider_gcc("%(gnu_host)s-" % vars(), "") for version in os.listdir(gcc_dir + "/" + gnu_host): consider_gcc("", "-%(version)s" % vars()) consider_gcc("%(gnu_host)s-" % vars(), "-%(version)s" % vars()) except FileNotFoundError: pass except NotADirectoryError: pass try: for gnu_host in os.listdir(gcccross_dir): consider_gcc("%(gnu_host)s-" % vars(), "") for version in os.listdir(gcccross_dir + "/" + gnu_host): consider_gcc("", "-%(version)s" % vars()) consider_gcc("%(gnu_host)s-" % vars(), "-%(version)s" % vars()) except FileNotFoundError: pass except NotADirectoryError: pass consider_clang("") for ent in os.listdir("/usr/lib"): if ent.startswith("llvm-"): version = ent.split("-")[1] consider_clang("-%(version)s" % vars()) for name in os.listdir(distcc_dir): mode = os.lstat(distcc_dir + "/" + name).st_mode if stat.S_ISLNK(mode): if os.access(distcc_dir + "/" + name, os.X_OK): old_symlinks.add(name) else: os.unlink(distcc_dir + "/" + name) for link in old_symlinks: if link not in new_symlinks: os.unlink(distcc_dir + "/" + link) for link in new_symlinks: if link not in old_symlinks: if os.access("/usr/bin/distcc", os.X_OK): os.symlink("../../bin/distcc", distcc_dir + "/" + link) else: os.symlink("../../local/bin/distcc", distcc_dir + "/" + link)