summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYING340
-rw-r--r--INSTALL39
-rw-r--r--Makefile.in111
-rw-r--r--README55
-rwxr-xr-xbuild-distcc.sh92
-rw-r--r--configure.ac11
-rw-r--r--distcc.spec398
-rw-r--r--distcc/AUTHORS6
-rw-r--r--distcc/COPYING340
-rw-r--r--distcc/ChangeLog2428
-rw-r--r--distcc/ChangeLog.old16140
-rw-r--r--distcc/INSTALL190
-rw-r--r--distcc/Makefile.in669
-rw-r--r--distcc/NEWS2144
-rw-r--r--distcc/README39
-rw-r--r--distcc/README.packaging75
-rw-r--r--distcc/TODO1112
-rwxr-xr-xdistcc/autogen.sh24
-rwxr-xr-xdistcc/bench/Build.py151
-rwxr-xr-xdistcc/bench/Project.py114
-rwxr-xr-xdistcc/bench/ProjectDefs.py100
-rwxr-xr-xdistcc/bench/Summary.py76
-rwxr-xr-xdistcc/bench/actions.py51
-rwxr-xr-xdistcc/bench/benchmark.py176
-rwxr-xr-xdistcc/bench/buildutil.py49
-rwxr-xr-xdistcc/bench/compiler.py63
-rwxr-xr-xdistcc/bench/statistics.py47
-rwxr-xr-xdistcc/config.guess1400
-rwxr-xr-xdistcc/config.sub1469
-rw-r--r--distcc/configure.ac455
-rw-r--r--distcc/contrib/distcc-absolutify47
-rw-r--r--distcc/contrib/distcc.sh40
-rw-r--r--distcc/contrib/distccd-init70
-rwxr-xr-xdistcc/contrib/distccd-on-servers145
-rw-r--r--distcc/contrib/dmake16
-rw-r--r--distcc/contrib/make-j21
-rw-r--r--distcc/contrib/netpwd26
-rw-r--r--distcc/contrib/redhat/init83
-rw-r--r--distcc/contrib/redhat/logrotate5
-rw-r--r--distcc/contrib/redhat/sysconfig8
-rw-r--r--distcc/contrib/redhat/xinetd17
-rw-r--r--distcc/contrib/stage-cc-wrapper.patch81
-rw-r--r--distcc/doc/example/init80
-rw-r--r--distcc/doc/example/init-suse96
-rw-r--r--distcc/doc/example/logrotate12
-rw-r--r--distcc/doc/example/xinetd26
-rw-r--r--distcc/doc/protocol-1.txt213
-rw-r--r--distcc/doc/protocol-2.txt38
-rw-r--r--distcc/doc/protocol-3-impl.txt61
-rw-r--r--distcc/doc/protocol-3.txt82
-rw-r--r--distcc/doc/reporting-bugs.txt73
-rw-r--r--distcc/doc/status-1.txt64
-rw-r--r--distcc/gnome/distccmon-gnome-icon.pngbin0 -> 4795 bytes
-rw-r--r--distcc/gnome/distccmon-gnome.desktop13
-rwxr-xr-xdistcc/install-sh251
-rw-r--r--distcc/lzo/.stamp-conf.in1
-rw-r--r--distcc/lzo/lzoconf.h451
-rw-r--r--distcc/lzo/minilzo.c2935
-rw-r--r--distcc/lzo/minilzo.h100
-rw-r--r--distcc/man/distcc.1725
-rw-r--r--distcc/man/distccd.1295
-rw-r--r--distcc/man/distccmon-text.156
-rwxr-xr-xdistcc/mkinstalldirs40
-rw-r--r--distcc/packaging/RedHat/init.d/distcc287
-rw-r--r--distcc/packaging/RedHat/logrotate.d/distcc13
-rw-r--r--distcc/packaging/RedHat/xinetd.d/distcc15
-rw-r--r--distcc/popt/.stamp-conf.in1
-rw-r--r--distcc/popt/README.popt12
-rw-r--r--distcc/popt/findme.c50
-rw-r--r--distcc/popt/findme.h20
-rw-r--r--distcc/popt/popt.c1236
-rw-r--r--distcc/popt/popt.h541
-rw-r--r--distcc/popt/poptconfig.c190
-rw-r--r--distcc/popt/popthelp.c742
-rw-r--r--distcc/popt/poptint.h116
-rw-r--r--distcc/popt/poptparse.c227
-rw-r--r--distcc/popt/system.h76
-rw-r--r--distcc/src/access.c125
-rw-r--r--distcc/src/access.h35
-rw-r--r--distcc/src/arg.c390
-rw-r--r--distcc/src/argutil.c165
-rw-r--r--distcc/src/backoff.c110
-rw-r--r--distcc/src/bulk.c367
-rw-r--r--distcc/src/bulk.h51
-rw-r--r--distcc/src/cleanup.c163
-rw-r--r--distcc/src/climasq.c131
-rw-r--r--distcc/src/clinet.c201
-rw-r--r--distcc/src/clinet.h33
-rw-r--r--distcc/src/clirpc.c281
-rw-r--r--distcc/src/compile.c687
-rw-r--r--distcc/src/compile.h46
-rw-r--r--distcc/src/compress.c254
-rw-r--r--distcc/src/cpp.c103
-rw-r--r--distcc/src/daemon.c306
-rw-r--r--distcc/src/daemon.h56
-rw-r--r--distcc/src/distcc.c221
-rw-r--r--distcc/src/distcc.h336
-rw-r--r--distcc/src/dopt.c278
-rw-r--r--distcc/src/dopt.h44
-rw-r--r--distcc/src/dotd.c251
-rwxr-xr-xdistcc/src/dotd.h9
-rw-r--r--distcc/src/dparent.c353
-rw-r--r--distcc/src/dsignal.c138
-rw-r--r--distcc/src/emaillog.c130
-rw-r--r--distcc/src/emaillog.h11
-rw-r--r--distcc/src/exec.c459
-rw-r--r--distcc/src/exec.h50
-rw-r--r--distcc/src/exitcode.h61
-rw-r--r--distcc/src/filename.c315
-rw-r--r--distcc/src/fix_debug_info.c450
-rw-r--r--distcc/src/fix_debug_info.h26
-rw-r--r--distcc/src/h_argvtostr.c59
-rw-r--r--distcc/src/h_compile.c106
-rw-r--r--distcc/src/h_dotd.c73
-rw-r--r--distcc/src/h_exten.c60
-rw-r--r--distcc/src/h_hosts.c111
-rw-r--r--distcc/src/h_issource.c59
-rw-r--r--distcc/src/h_parsemask.c66
-rw-r--r--distcc/src/h_sa2str.c75
-rw-r--r--distcc/src/h_scanargs.c72
-rw-r--r--distcc/src/h_strip.c63
-rw-r--r--distcc/src/help.c74
-rw-r--r--distcc/src/history.c68
-rw-r--r--distcc/src/hostfile.c67
-rw-r--r--distcc/src/hosts.c654
-rw-r--r--distcc/src/hosts.h87
-rw-r--r--distcc/src/implicit.c95
-rw-r--r--distcc/src/implicit.h25
-rw-r--r--distcc/src/include_server_if.c161
-rwxr-xr-xdistcc/src/include_server_if.h21
-rw-r--r--distcc/src/io.c272
-rw-r--r--distcc/src/loadfile.c113
-rw-r--r--distcc/src/lock.c271
-rw-r--r--distcc/src/lock.h36
-rw-r--r--distcc/src/lsdistcc.c1034
-rw-r--r--distcc/src/mon-gnome.c673
-rw-r--r--distcc/src/mon-notify.c125
-rw-r--r--distcc/src/mon-text.c115
-rw-r--r--distcc/src/mon.c368
-rw-r--r--distcc/src/mon.h266
-rw-r--r--distcc/src/ncpus.c154
-rw-r--r--distcc/src/netutil.c214
-rw-r--r--distcc/src/netutil.h37
-rw-r--r--distcc/src/prefork.c195
-rw-r--r--distcc/src/pump.c152
-rw-r--r--distcc/src/remote.c301
-rw-r--r--distcc/src/renderer.c299
-rw-r--r--distcc/src/renderer.h48
-rw-r--r--distcc/src/rpc.c343
-rw-r--r--distcc/src/rpc.h48
-rw-r--r--distcc/src/rslave.c166
-rw-r--r--distcc/src/rslave.h65
-rw-r--r--distcc/src/safeguard.c81
-rw-r--r--distcc/src/sendfile.c212
-rw-r--r--distcc/src/serve.c781
-rw-r--r--distcc/src/setuid.c138
-rw-r--r--distcc/src/snprintf.c1016
-rw-r--r--distcc/src/snprintf.h30
-rw-r--r--distcc/src/srvnet.c290
-rw-r--r--distcc/src/srvnet.h28
-rw-r--r--distcc/src/srvrpc.c181
-rw-r--r--distcc/src/ssh.c228
-rw-r--r--distcc/src/state.c257
-rw-r--r--distcc/src/state.h91
-rw-r--r--distcc/src/stats.c415
-rw-r--r--distcc/src/stats.h46
-rw-r--r--distcc/src/stringmap.c116
-rw-r--r--distcc/src/stringmap.h27
-rw-r--r--distcc/src/strip.c178
-rw-r--r--distcc/src/tempfile.c412
-rw-r--r--distcc/src/timefile.c159
-rw-r--r--distcc/src/timefile.h33
-rw-r--r--distcc/src/timeval.c36
-rw-r--r--distcc/src/timeval.h4
-rw-r--r--distcc/src/trace.c433
-rw-r--r--distcc/src/trace.h230
-rw-r--r--distcc/src/traceenv.c93
-rw-r--r--distcc/src/types.h36
-rw-r--r--distcc/src/util.c769
-rw-r--r--distcc/src/util.h55
-rw-r--r--distcc/src/where.c197
-rw-r--r--distcc/src/where.h29
-rw-r--r--distcc/survey.txt35
-rwxr-xr-xdistcc/test/comfychair.py445
-rwxr-xr-xdistcc/test/onetest.py37
-rwxr-xr-xdistcc/test/testdistcc.py1708
-rw-r--r--include_server/Makefile.in114
-rwxr-xr-xinclude_server/__init__.py0
-rwxr-xr-xinclude_server/basics.py339
-rwxr-xr-xinclude_server/basics_test.py65
-rw-r--r--include_server/c_extensions/distcc_pump_c_extensions_module.c381
-rwxr-xr-xinclude_server/c_extensions_test.py132
-rwxr-xr-xinclude_server/cache_basics.py858
-rwxr-xr-xinclude_server/compiler_defaults.py180
-rwxr-xr-xinclude_server/compress_files.py112
-rw-r--r--include_server/configure.ac10
-rwxr-xr-xinclude_server/include_analyzer.py362
-rwxr-xr-xinclude_server/include_analyzer_memoizing_node.py641
-rwxr-xr-xinclude_server/include_analyzer_memoizing_node_test.py233
-rwxr-xr-xinclude_server/include_analyzer_test.py508
-rwxr-xr-xinclude_server/include_server.py723
-rwxr-xr-xinclude_server/include_server_test.py187
-rwxr-xr-xinclude_server/macro_eval.py437
-rwxr-xr-xinclude_server/macro_eval_test.py233
-rwxr-xr-xinclude_server/mirror_path.py113
-rwxr-xr-xinclude_server/mirror_path_test.py145
-rwxr-xr-xinclude_server/parse_command.py464
-rwxr-xr-xinclude_server/parse_command_test.py196
-rwxr-xr-xinclude_server/parse_file.py342
-rwxr-xr-xinclude_server/parse_file_test.py154
-rwxr-xr-xinclude_server/run.py106
-rwxr-xr-xinclude_server/setup.py83
-rwxr-xr-xinclude_server/statistics.py121
-rwxr-xr-xinclude_server/test_data/abc_post.c1
-rwxr-xr-xinclude_server/test_data/abc_pre.c1
-rwxr-xr-xinclude_server/test_data/computed_includes.c10
-rw-r--r--include_server/test_data/contains_abs_include.c1
-rw-r--r--include_server/test_data/dbar/dbar1/bar.h1
-rwxr-xr-xinclude_server/test_data/dbar/foo.h1
-rwxr-xr-xinclude_server/test_data/dfoo/foo.h2
-rw-r--r--include_server/test_data/dfoo/foo2.h3
-rw-r--r--include_server/test_data/dfoo/i_am_perhaps_a_directory.h0
-rw-r--r--include_server/test_data/dfoo/include_dotdot_foo1
-rwxr-xr-xinclude_server/test_data/dfoo/include_next_foo.h1
-rw-r--r--include_server/test_data/dfoo/stat_triggers.h0
-rw-r--r--include_server/test_data/distcc/README1
-rw-r--r--include_server/test_data/distcc/src/bulk.h51
-rw-r--r--include_server/test_data/distcc/src/compile.h38
-rw-r--r--include_server/test_data/distcc/src/config.h256
-rw-r--r--include_server/test_data/distcc/src/distcc.c221
-rw-r--r--include_server/test_data/distcc/src/distcc.h336
-rw-r--r--include_server/test_data/distcc/src/emaillog.h10
-rw-r--r--include_server/test_data/distcc/src/exitcode.h61
-rw-r--r--include_server/test_data/distcc/src/hosts.h87
-rw-r--r--include_server/test_data/distcc/src/implicit.h25
-rw-r--r--include_server/test_data/distcc/src/include_me.h0
-rw-r--r--include_server/test_data/distcc/src/state.h91
-rw-r--r--include_server/test_data/distcc/src/trace.h230
-rw-r--r--include_server/test_data/distcc/src/util.h55
-rw-r--r--include_server/test_data/func_macro.c1
-rw-r--r--include_server/test_data/gws-main.o.cmd1
-rw-r--r--include_server/test_data/i_am_perhaps_a_directory.h/empty_file0
-rwxr-xr-xinclude_server/test_data/include_include_next_foo.h1
-rw-r--r--include_server/test_data/maps/foo.tpl.varnames.h1
-rw-r--r--include_server/test_data/more_macros.c14
-rwxr-xr-xinclude_server/test_data/p1.h1
-rw-r--r--include_server/test_data/parse.c8
-rw-r--r--include_server/test_data/stat_triggers.c1
-rw-r--r--include_server/test_data/stat_triggers.h0
l---------include_server/test_data/symlink_farm/abc_post.c1
l---------include_server/test_data/symlink_farm/abc_pre.c1
l---------include_server/test_data/symlink_farm/computed_includes.c1
l---------include_server/test_data/symlink_farm/dbar1
l---------include_server/test_data/symlink_farm/dfoo1
-rw-r--r--include_server/test_data/symlink_farm/foo1
l---------include_server/test_data/symlink_farm/p1.h1
l---------include_server/test_data/symlink_farm/parse.c1
l---------include_server/test_data/symlink_farm/sub_farm/link_to_dotdot_dotdot_dfoo_include_dotdot_foo1
l---------include_server/test_data/symlink_farm/test_directory_probing.c1
l---------include_server/test_data/symlink_farm/test_include_next1
-rw-r--r--include_server/test_data/test_computed_includes/helper.c1
-rw-r--r--include_server/test_data/test_computed_includes/incl.h1
-rw-r--r--include_server/test_data/test_computed_includes/inclA.h1
-rw-r--r--include_server/test_data/test_computed_includes/src.c9
-rw-r--r--include_server/test_data/test_computed_includes/srcA.c9
-rw-r--r--include_server/test_data/test_directory_probing.c4
-rwxr-xr-xinclude_server/test_data/test_include_next/bar/x.h3
-rwxr-xr-xinclude_server/test_data/test_include_next/bar/y.h3
-rwxr-xr-xinclude_server/test_data/test_include_next/baz/start_x.c2
-rwxr-xr-xinclude_server/test_data/test_include_next/baz/start_y.c2
-rwxr-xr-xinclude_server/test_data/test_include_next/baz/x.h3
-rwxr-xr-xinclude_server/test_data/test_include_next/baz/y.h6
-rwxr-xr-xinclude_server/test_data/test_include_next/biz/x.h1
-rwxr-xr-xinclude_server/test_data/test_include_next/foo/x.h2
-rwxr-xr-xinclude_server/test_data/test_include_next/foo/y.h2
-rwxr-xr-xpump.in444
-rwxr-xr-xrun_all_autoconf.sh20
-rw-r--r--version.sh10
278 files changed, 70099 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..800e3c3
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,39 @@
+
+To build: the simple way is to just do
+
+ run_all_autoconf.sh # invokes autoconf and autoheader using
+ # version info in the file version.sh
+ configure # creates distcc/config.h and makefiles
+ make # build
+
+but the recommended way is to build in a different directory tree
+than the source tree:
+
+ run_all_autoconf.sh
+ mkdir obj
+ cd obj
+ ../configure
+ make
+
+Either of these methods will:
+
+ - compile distcc
+ - compile Python C extensions
+
+To test:
+
+ make check
+
+To test installation using your own machine as a distcc compilation server:
+
+ - start daemon (in one window):
+
+ distcc/distccd --wizard --allow 127.0.0.1
+
+ - compile (in another):
+
+ DISTCC_POTENTIAL_HOSTS=127.0.0.1 pump BUILDCOMMAND
+
+See the shell script pump in this directory.
+
+
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..a0a7b78
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,111 @@
+# This Makefile just delegates all the work to the Makefiles
+# in the subdirectories.
+#
+SUBDIRS = distcc include_server
+INSTALL_TARGETS = $(SUBDIRS:%=install-%)
+CHECK_TARGETS = $(SUBDIRS:%=check-%)
+CLEAN_TARGETS = $(SUBDIRS:%=clean-%)
+MAINTAINER_CHECK_TARGETS = $(SUBDIRS:%=maintainer-check-%)
+
+# A timestamp file to reliably tell us when autoreconf was last run.
+AUTOCONF_STAMP = @srcdir@/autoconf_stamp
+
+# A stamp file AUTOCONF_SANITY that tells us the last time either:
+#
+# - autoreconf was run, or
+#
+# - configure was run.
+#
+# AUTORECONF cannot be a phony target. Below we make the Makefile itself
+# dependent on AUTOCONF_SANITY. After the Makefile is regenerated, as part of
+# GNU make's feature of remaking the current Makefile if it is out of date, a
+# dependency on a phony target would make 'make' make the Makefile again. An
+# infinite regression would result. So, we must record the time of
+# AUTOCONF_SANITY in a file.
+AUTOCONF_SANITY = autoconf_sanity
+# TODO(klarlund): substitute autoconf_sanity for AUTOCONF_SANITY? Same for
+# AUTOCONF_STAMP.
+
+# Autoconf configuration variables.
+# DESTDIR is for building rpm's. It's a temporary filesystem root
+# where the rpm bulding process puts all its files.
+DESTDIR =
+prefix = $(DESTDIR)@prefix@
+exec_prefix = $(DESTDIR)@exec_prefix@
+bindir = $(DESTDIR)@bindir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+INSTALL = @INSTALL@
+PYTHON = @PYTHON@
+
+# I swear, this is the code that Python's distutils uses.
+PYTHON_VERSION = $(shell $(PYTHON) -c \
+ 'import sys; import string; print string.split(sys.version)[0][:3]')
+
+# TODO(klarlund,fergus):
+# - invoke distcc/configure before make in distcc/
+
+.PHONY: all $(SUBDIRS)
+all: $(AUTOCONF_SANITY) $(SUBDIRS) pump
+$(SUBDIRS): %:
+ $(MAKE) --directory=$@
+
+.PHONY: install $(INSTALL_TARGETS)
+install: $(AUTOCONF_SANITY) $(INSTALL_TARGETS) install-local
+$(INSTALL_TARGETS): install-%:
+ $(MAKE) --directory=$* install
+
+.PHONY: check $(CHECK_TARGETS)
+check: $(AUTOCONF_SANITY) $(CHECK_TARGETS)
+$(CHECK_TARGETS): check-%:
+ $(MAKE) --directory=$* check
+
+.PHONY: maintainer-check $(MAINTAINER_CHECK_TARGETS)
+maintainer-check: $(AUTOCONF_SANITY) $(MAINTAINER_CHECK_TARGETS)
+$(MAINTAINER_CHECK_TARGETS): maintainer-check-%:
+ $(MAKE) --directory=$* maintainer-check
+
+.PHONY: clean $(CLEAN_TARGETS)
+clean: $(CLEAN_TARGETS)
+$(CLEAN_TARGETS): clean-%:
+ $(MAKE) --directory=$* clean
+
+.PHONY: install-local
+install-local: pump
+ $(INSTALL) -d $(bindir)
+ $(INSTALL) pump $(bindir)
+
+pump: $(AUTOCONF_SANITY) pump.in
+ ./config.status
+
+Makefile: $(AUTOCONF_SANITY) Makefile.in
+ ./config.status
+
+# SANITY CHECKS
+
+# Here we set up AUTOCONF_SANITY so that it works as described. It verifies
+# that
+#
+# - autoconf has been run after its dependencies have changed (see rule for
+# $(AUTOCONF_STAMP)) below, and
+#
+# - the time of this event, recorded by AUTOCONF_STAMP, is before that of
+# config.status (see rule for config.status below).
+#
+# We need the touch: without it 'make' will invoke itself in an infinite loop,
+# because the Makefile is dependent on AUTOCONF_SANITY.
+
+$(AUTOCONF_SANITY): $(AUTOCONF_STAMP) config.status
+ touch $(AUTOCONF_SANITY)
+
+# Check that autoreconf was run after changes to version.sh or
+# config.status. This regenerates distcc/src/config.h.in.
+$(AUTOCONF_STAMP): version.sh configure.ac
+ @echo "Please run ./run_all_autoconf.sh now."
+ @exit 1
+
+# Check that the generated configure was run after autoreconf. The modification
+# time of the configure.status file is updated by configure.
+config.status: $(AUTOCONF_STAMP)
+ @echo "Please run ./configure now."
+ @exit 1
diff --git a/README b/README
new file mode 100644
index 0000000..ea8501c
--- /dev/null
+++ b/README
@@ -0,0 +1,55 @@
+
+ distcc-pump -- a free distributed C/C++ compiler system
+
+ originally by Martin Pool <mbp@samba.org>
+
+ extended at Google Inc.
+
+ by Fergus Henderson, Nils Klarlund, Manos Renieris, and Craig Silverstein
+
+
+distcc-pump improves on distcc by distributing not only compilation but also
+preprocessing to distcc servers. For an introduction to distcc, see
+distcc/README.
+
+The distcc-pump contributes an include server process that exists during the
+build. The include server parses and analyzes source and header files. It runs
+on the workstation that initiates the build. The include server analyzes each
+header file only a few times, sometimes just once. In contrast, ordinary distcc
+invokes the preprocessor hundreds of times on average for each header file of a
+large build.
+
+With the distcc-pump, a static analysis algorithm inspects includes and computes
+their possible values according to an overapproximation semantics. The resulting
+dependency graph among header files is stored in 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 in such
+cases to inform the preprocessor that the real location is /absolute/path.
+
+The distcc-pump 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-pump server. The distcc-pump 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
+returned to the distcc-pump client.
+
+The distcc-pump is able to distribute compilations up to 10X faster than distcc.
+But because building also involves linking and perhaps generation of source
+files the overall speed-up of the build time is variable.
+
+The distcc-pump was developed to be used with large clusters of distcc servers,
+providing hundreds of CPUs. With versions of gcc >= 4.1.1, the distcc-pump will
+probably not show performance gains using clusters of say only ten CPUs. The
+preprocessor running on the workstation is fast enough to keep that many
+machines busy.
diff --git a/build-distcc.sh b/build-distcc.sh
new file mode 100755
index 0000000..0002b09
--- /dev/null
+++ b/build-distcc.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+# Simple shell script to build distcc SRPM and RPM from sources
+
+# When releasing a new version, you need to do four things:
+# 1. edit the 'Release' field of the spec file
+# 2. add a comment to the %changelog section of the spec file
+# 3. edit the 'DISTCC_VERSION' and 'PUMP_SUBVERSION' variables in version.sh.
+# It would be better if this was easier, but that's how it is right now.
+
+source version.sh
+
+PKG=distcc
+TOP=`pwd`
+
+# Check if we have a bad kernel + RPM combination.
+# 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/
+#
+# See if running on a kernel with the virtual dso.
+HAS_VSDO=0
+cat /proc/self/maps | grep -q vdso
+if [ $? -eq 0 ]; then
+ HAS_VSDO=1
+fi
+# See if we have incompatible RPM tools.
+if [ $HAS_VSDO -eq 0 ]; then
+ grep -q 'linux-gate' /usr/lib/rpm/find-requires
+ if [ $? -ne 0 ]; 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
+
+set -xe
+
+rm -rf tmp
+mkdir tmp
+cd tmp
+
+# Set up rpm build environment
+RPM_SOURCE_DIR=$TOP
+RPM_BUILD_DIR=$TOP
+RPM_RPM_DIR=$TOP/tmp/rpms
+RPM_SRPM_DIR=$TOP/tmp/srpms
+# lifted from gboilerplate
+USERNAME="$(whoami)"
+PACKAGER="$(ldapsearch -x -LLL -b 'ou=People,dc=google,dc=com' "uid=$USERNAME" cn|grep '^cn'|colrm 1 4) <$USERNAME@google.com>"
+
+# Temporary directories
+rm -rf $RPM_RPM_DIR
+mkdir $RPM_RPM_DIR
+rm -rf $RPM_SRPM_DIR
+mkdir $RPM_SRPM_DIR
+rm -rf /tmp/$PKG-$DISTCC_VERSION-root
+mkdir /tmp/$PKG-$DISTCC_VERSION-root
+
+
+CROSS=${CROSS-}
+CC=${CROSS}gcc \
+CXX=${CROSS}g++ \
+AR=${CROSS}ar \
+RANLIB=${CROSS}ranlib \
+rpmbuild -bb $TOP/$PKG.spec \
+ --define "_sourcedir $RPM_SOURCE_DIR" \
+ --define "_builddir $RPM_BUILD_DIR" \
+ --define "_rpmdir $RPM_RPM_DIR" \
+ --define "_srcrpmdir $RPM_SRPM_DIR" \
+ --define "name $PKG" \
+ --define "version $DISTCC_VERSION" \
+ --define "release $PUMP_SUBVERSION" \
+ --define "packager $PACKAGER" \
+ --define "bundle_dir $TOP"
+# Determine the name of the directory where the package went
+RPMARCH=`rpmbuild --showrc $TOP/$PKG.spec | grep "^build arch.*:" | sed -e 's/^build arch[[:space:]]*:[[:space:]]*//'`
+
+find . -type f | xargs chmod 644
+find . -type d | xargs chmod 755
+
+echo Results in $RPM_SRPM_DIR and $RPM_RPM_DIR/${RPMARCH} :
+ls -l $RPM_SRPM_DIR $RPM_RPM_DIR/$RPMARCH
+
+# Convert RPMs to DEBs for goobuntu.
+fakeroot alien -c -k -v $RPM_RPM_DIR/$RPMARCH/*.rpm
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..367e336
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,11 @@
+AC_INIT(distcc_pump,
+ esyscmd(source version.sh && echo -n $DISTCC_PUMP_VERSION),
+ distcc-pump@google.com)
+AC_CHECK_PROGS(PYTHON, [python2.4 python2.3 python-2.3 python2.2 python-2.2 python])
+AC_ARG_VAR(PYTHON, [Python interpreter])
+AC_CONFIG_AUX_DIR(distcc)
+AC_CONFIG_SUBDIRS(include_server distcc)
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([pump], [chmod +x pump])
+AC_PROG_INSTALL
+AC_OUTPUT
diff --git a/distcc.spec b/distcc.spec
new file mode 100644
index 0000000..5ac5647
--- /dev/null
+++ b/distcc.spec
@@ -0,0 +1,398 @@
+Summary: Client side program for distributed C/C++ compilations.
+Name: %{name}
+Version: %{version}
+Release: %{release}
+License: GPL + Google Internal
+Group: Development/Languages
+BuildRoot: %{_tmppath}/%{name}-buildroot
+Provides: distcc
+Url: https://www.corp.google.com/eng/designdocs/google3/distcc-intra-build.html
+Obsoletes: crosstool-distcc
+
+%define _prefix /usr
+%define _bindir %{_prefix}/bin
+%define _datadir %{_prefix}/share
+%define _docdir %{_datadir}/doc/%{name}
+%define _libdir %{_prefix}/lib
+# TODO grhat wants versioned doc dirs, but goobuntu apparently doesn't. Which
+# should we use?
+# %define _docdir %{_datadir}/doc/%{name}-%{version}
+%define _mandir %{_datadir}/man
+%define _sysconfdir /etc
+
+%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
+
+%build
+./run_all_autoconf.sh
+# 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
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d
+install -m 644 distcc/packaging/RedHat/logrotate.d/distcc $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/distcc
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d
+install -m 644 distcc/packaging/RedHat/xinetd.d/distcc $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d/distcc
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/init.d
+install -m 755 distcc/packaging/RedHat/init.d/distcc $RPM_BUILD_ROOT%{_sysconfdir}/init.d/distcc
+# TODO(mtm) Does grhat really need these links for something?
+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
+%defattr(-, root, root, 0755)
+%{_bindir}/distcc
+%{_bindir}/distccmon-text
+%{_bindir}/lsdistcc
+# TODO(mtm) Do we need the libdir stuff for grhat (see %install TODO above)?
+%{_libdir}/distcc
+%doc %{_mandir}/man1/distcc.1.gz
+%doc %{_mandir}/man1/distccmon-text.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
+%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
+ update-rc.d distcc defaults 95 05 >/dev/null
+ if [ -x /usr/sbin/invoke-rc.d ]; then
+ invoke-rc.d distcc start || exit 0
+ else
+ /etc/init.d/distcc start || exit 0
+ fi
+ 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
+
+
+%package include_server
+Summary: Include server for distcc-pump
+Group: Development/Languages
+
+%description include_server
+The include server is part of the distcc-pump project, as described in
+<https://www.corp.google.com/eng/designdocs/google3/distcc-intra-build.html>.
+
+# The python_record_install file contains a list of the files installed
+# by the python install process.
+%files include_server -f include_server/python_install_record
+%{_bindir}/pump
+%defattr(-,root,root)
+
+
+%changelog
+* Thu Jun 14 2007 Manos Renieris <manos@google.com> 2.18.3-17gg1-pump1
+- Added all the distcc-pump related parts.
+- Changed the way the package is built.
+- Remove source package generation.
+- Man pages are now unzipped.
+
+* Mon May 29 2007 Dongmin Zhang <zhangdm@google.com> 2.18.3-17gg1
+- Integrate changes and bug fix from Fergus's changes. Quote from his description:
+ Add -r<PORT> 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.
+
+* Mon May 21 2007 Dongmin Zhang <zhangdm@google.com> 2.18.3-16gg1
+- Change the package name to 2.18.3-16gg1 to make the goobuntu and grhat be
+ able to pick up the newest version of distcc.
+
+* Mon Feb 8 2007 Dongmin Zhang <zhangdm@google.com> 2.18.3-16gg
+- 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 <zhangdm@google.com> 2.18.3-15gg
+- Added _libdir definition.
+- 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 <ahyun@google.com>.
+
+* Mon Jan 22 2007 Dongmin Zhang <zhangdm@google.com> 2.18.3-14gg
+- 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.
+
+%changelog
+* Fri Dec 1 2006 Ollie Wild <aaw@google.com> 2.18.3-13gg
+- 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.
+
+%changelog
+* Fri Sep 8 2006 Michael Moss <mmoss@google.com> 2.18.3-12gg
+- 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 <dank@kegel.com> 2.18.3-11
+- removed cache again
+
+* Mon Feb 20 2006 Dan Kegel <dank@kegel.com> 2.18.3-10
+- added cache
+
+* Mon Feb 6 2006 Dan Kegel <dank@kegel.com> 2.18.3-9
+- 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 <dank@kegel.com> 2.18.3-8
+- 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 <dank@kegel.com> 2.18.3-7
+- 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 <dank@kegel.com> 2.18.3-6
+- 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 <dank@kegel.com> 2.18.3-5
+- 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
+- Changes copyright 2005 Google. GPL.
+
+* Thu Oct 13 2005 Dan Kegel <dank@kegel.com> 2.18.3-4
+- 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
+- Changes copyright 2005 Google. GPL.
+
+* Fri Sep 16 2005 Dan Kegel <dank@kegel.com> 2.18.3-3
+- 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
+- Changes copyright 2005 Google. GPL.
+
+* Sat Sep 3 2005 Dan Kegel <dank@kegel.com> 2.18.3-2
+- now reads /etc/distcc/hosts instead of /usr/etc/distcc/hosts
+- applied distcc-domain-2.patch
+- Changes copyright 2005 Google. GPL.
+
+* Thu Jun 15 2005 Dan Kegel <dank@kegel.com> 2.18.3-1
+- 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)
+- Changes copyright 2005 Google. GPL.
+
+* Sat May 31 2003 Terry Griffin <terryg@axian.com> 2.5-2
+- Updated to 2.5
+
+* Sat May 24 2003 Terry Griffin <terryg@axian.com> 2.4.2-2
+- Updated to 2.4.2
+
+* Sat May 17 2003 Terry Griffin <terryg@axian.com> 2.3-2
+- Updated to 2.3
+
+* Sun May 04 2003 Terry Griffin <terryg@axian.com> 2.1-2
+- Updated to 2.1
+- Added symbolic links for masquerade mode
+
+* Fri Mar 28 2003 Terry Griffin <terryg@axian.com> 2.0.1-2
+- Updated to 2.0.1
+- Removed info file from document list.
+
+* Tue Feb 25 2003 Terry Griffin <terryg@axian.com> 1.2.1-2
+- Updated to 1.2.1
+
+* Mon Jan 27 2003 Terry Griffin <terryg@axian.com> 1.1-2
+- Updated to 1.1
+- Minor improvements to the RPM spec file
+
+* Mon Dec 16 2002 Terry Griffin <terryg@axian.com> 0.15-2
+- Changed server user back to 'nobody'
+
+* Fri Dec 13 2002 Terry Griffin <terryg@axian.com> 0.15-2
+- Updated to 0.15
+- Changed port number in server configs to 3632
+
+* Sat Nov 23 2002 Terry Griffin <terryg@axian.com> 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 <terryg@axian.com> 0.12-1
+- Updated to 0.12
+
+* Thu Oct 10 2002 Terry Griffin <terryg@axian.com> 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 <terryg@axian.com> 0.11-2
+- Moved distccd back to /usr/bin from /usr/sbin.
+
+* Sat Sep 28 2002 Terry Griffin <terryg@axian.com> 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
diff --git a/distcc/AUTHORS b/distcc/AUTHORS
new file mode 100644
index 0000000..3b2edab
--- /dev/null
+++ b/distcc/AUTHORS
@@ -0,0 +1,6 @@
+Author and maintainer of distcc:
+
+ Martin Pool <mbp@sourcefrog.net>
+
+
+See NEWS for credits of other contributors.
diff --git a/distcc/COPYING b/distcc/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/distcc/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/distcc/ChangeLog b/distcc/ChangeLog
new file mode 100644
index 0000000..4c26684
--- /dev/null
+++ b/distcc/ChangeLog
@@ -0,0 +1,2428 @@
+# do not edit -- automatically generated by arch changelog
+# arch-tag: automatic-ChangeLog--mbp@sourcefrog.net--2004/distcc--devel--2
+#
+
+2004-12-15 00:11:05 GMT Martin Pool <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> patch-119
+
+ Summary:
+ doc
+ Revision:
+ distcc--devel--2--patch-119
+
+
+ modified files:
+ ChangeLog TODO
+
+
+2004-09-25 09:57:52 GMT Martin Pool <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> patch-68
+
+ Summary:
+ note leak fixes
+ Revision:
+ distcc--devel--2--patch-68
+
+
+ modified files:
+ ChangeLog
+
+
+2004-07-08 05:56:54 GMT Martin Pool <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> patch-60
+
+ Summary:
+ Rephrase news
+ Revision:
+ distcc--devel--2--patch-60
+
+
+ modified files:
+ ChangeLog NEWS
+
+
+2004-07-07 05:49:15 GMT Martin Pool <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@hp.com> 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 <mbp@hp.com> 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 <mbp@hp.com> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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 <mbp@sourcefrog.net> 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
+
+
diff --git a/distcc/ChangeLog.old b/distcc/ChangeLog.old
new file mode 100644
index 0000000..90580f1
--- /dev/null
+++ b/distcc/ChangeLog.old
@@ -0,0 +1,16140 @@
+2004-04-10 Martin Pool <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <china@thewrittenword.com>
+
+ * 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 <china@thewrittenword.com>
+
+ 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 <sys/socket.h> 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 <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <shri@urbyte.com>
+
+ * man/distccmon-text.1: New manpage.
+
+2003-12-15 Martin Pool <mbp@sourcefrog.net>
+
+ * man/distccd.1: Mention TMPDIR.
+
+ * man/distcc.1: We don't use a subdirectory of TMPDIR anymore.
+
+2003-11-28 Harold L Hunt II <huntharo@msu.edu>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <lionel.sausin@free.fr>
+
+ * man/fr/distcc.1, man/fr/distccd.1: French translations of the
+ manual pages.
+
+2003-11-17 Martin Pool <mbp@sourcefrog.net>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * sendfile.c: Documentation updates.
+
+2003-11-17 Allan Saddi <allan@saddi.com>
+
+ * 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 <mbp@sourcefrog.net>
+
+ * 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 <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-10-28 11:38 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version.
+
+2003-10-23 13:36 Martin Pool <mbp@samba.org>
+
+ * autogen.sh: Remove check on autoconf version because it breaks
+ on non-numeric versions like "2.57a".
+
+2003-10-23 10:50 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Add some description of search paths.
+
+2003-10-23 10:44 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Add some description of search paths.
+
+2003-10-23 10:14 Martin Pool <mbp@samba.org>
+
+ * TODO: More tasks to do.
+
+2003-10-23 09:56 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Prepare for 2.11.2 release
+
+2003-10-14 14:23 Martin Pool <mbp@samba.org>
+
+ * gnome/distccmon-gnome.desktop, NEWS: Desktop file corrections
+ from Dag Wieers.
+
+2003-10-13 23:57 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes on current bugs.
+
+2003-10-13 20:05 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Don't trim the path at all when our invocation
+ name is "distcc".
+
+2003-10-13 19:52 Martin Pool <mbp@samba.org>
+
+ * src/util.c: dcc_trim_path: Trace the compiler name.
+
+2003-10-13 19:51 Martin Pool <mbp@samba.org>
+
+ * src/util.c: dcc_trim_path: Doc.
+
+2003-10-13 19:39 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc.
+
+2003-10-13 19:24 Martin Pool <mbp@samba.org>
+
+ * src/climasq.c: Doc.
+
+2003-10-13 19:03 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Doc typo
+
+2003-10-13 18:39 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c, dsignal.c: Use AC_TYPE_SIGNAL to set signal
+ handler return type for portability.
+
+2003-10-13 18:38 Martin Pool <mbp@samba.org>
+
+ * doc/example/xinetd, NEWS: Add type = UNLISTED to cope without
+ an /etc/services entry.
+
+2003-10-13 18:34 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Doc
+
+ * Add check for signal return type.
+
+2003-10-13 17:56 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Bump date.
+
+2003-10-13 17:56 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1, NEWS: Clear up meaning of UNCACHED_ERR_FD.
+
+2003-10-13 17:37 Martin Pool <mbp@samba.org>
+
+ * README.packaging: Suggest adding to /etc/services.
+
+2003-10-13 17:06 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Clarifications/corrections to --allow
+ description.
+
+2003-10-13 16:52 Martin Pool <mbp@samba.org>
+
+ * NEWS: IRIX fixes.
+
+2003-10-13 16:42 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: dcc_check_compiler_masq: Remove dead variable.
+
+2003-10-13 16:40 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: Notes on better scheduling.
+
+2003-10-13 16:26 Martin Pool <mbp@samba.org>
+
+ * NEWS: Remove dependency on libglade.
+
+ * Fix --without-gnome.
+
+2003-10-13 16:24 Martin Pool <mbp@samba.org>
+
+ * gnome/: distccmon-gnome.glade, distccmon-gnome.gladep: Remove
+ Glade packages.
+
+2003-10-13 16:20 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Set icon on monitor window from png file.
+
+2003-10-13 16:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Don't require libglade.
+
+2003-10-13 16:09 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Bump version
+
+2003-10-08 15:47 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Prepare for 2.11.1 release.
+
+2003-10-08 15:45 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/bulk.c: dcc_x_file_lzo1x should return any errors that
+ occur.
+
+2003-10-07 16:07 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: dcc_inside_child should be void and should never
+ return.
+
+2003-10-07 16:01 Martin Pool <mbp@samba.org>
+
+ * src/: util.c, util.h: dcc_exit can be void.
+
+2003-10-07 15:52 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Typo fix from Lionel Sausin.
+
+2003-10-01 13:56 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * INSTALL: Give dependencies for --with-gtk.
+
+2003-09-30 09:54 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * man/distcc.1: Set datestamp.
+
+2003-09-29 22:21 Martin Pool <mbp@samba.org>
+
+ * NEWS: Fix for state.h
+
+2003-09-29 22:19 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Documentation corrections from Lionel Sausin.
+
+2003-09-29 16:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon.h: Doc rename to dcc_history.
+
+2003-09-29 16:44 Martin Pool <mbp@samba.org>
+
+ * src/mon.h: Explain why dnotify is cut out.
+
+2003-09-29 16:33 Martin Pool <mbp@samba.org>
+
+ * NEWS: stdint.h is not on iricks or sloaris either.
+
+2003-09-29 16:30 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Make it just --with-gtk.
+
+2003-09-29 16:15 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Fix help string for --with-gtk+.
+
+2003-09-29 16:13 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Add support for building with either GNOME
+ or plain GTK+.
+
+2003-09-29 16:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/state.h: Fix state.h for use with C++. Patch from Frerich
+ Raabe.
+
+2003-09-27 19:42 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version.
+
+2003-09-25 13:39 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Include GTK as well.
+
+2003-09-24 15:33 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Change for new log archiving method.
+
+2003-09-23 16:12 Martin Pool <mbp@samba.org>
+
+ * NEWS: Prepare for release.
+
+2003-09-23 15:58 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Run tests for GNOME packages when --with-gnome is
+ set.
+
+2003-09-23 15:51 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump to version 2.11.
+
+2003-09-23 15:43 Martin Pool <mbp@samba.org>
+
+ * NEWS, src/distcc.c: Client catches SIGINT, SIGHUP and SIGTERM
+ and cleans up temporary files before terminating.
+
+2003-09-23 15:26 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Distribute and install GNOME data files.
+
+2003-09-23 15:00 Martin Pool <mbp@samba.org>
+
+ * NEWS: Change to --with-gnome for consistency with other
+ packages.
+
+2003-09-23 14:57 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: The access mask 1.2.3.4/0 should match
+ anything.
+
+2003-09-23 14:53 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Fix bad bug in main() that caused us to exit
+ through the wrong path.
+
+2003-09-23 14:38 Martin Pool <mbp@samba.org>
+
+ * configure.ac, INSTALL: Change to --with-gnome for consistency
+ with other packages.
+
+2003-09-23 14:28 Martin Pool <mbp@samba.org>
+
+ * configure.ac: LINUXDOC is no longer a special variable.
+
+2003-09-23 14:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Doc.
+
+2003-09-23 14:00 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon.c: Check structure size when loading binary state
+ files.
+
+2003-09-22 17:32 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: Remove done items.
+
+2003-09-22 17:24 Martin Pool <mbp@samba.org>
+
+ * src/state.h: Add a size field to the state struct.
+
+2003-09-22 17:22 Martin Pool <mbp@samba.org>
+
+ * src/mon.h: Don't need dcc_timeval_to_double
+
+2003-09-22 17:13 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Don't need sys/time.h
+
+2003-09-22 17:12 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Don't need state.h anymore.
+
+2003-09-22 17:10 Martin Pool <mbp@samba.org>
+
+ * src/: compile.c, distcc.c: Don't use STARTUP state anymore.
+
+2003-09-22 16:50 Martin Pool <mbp@samba.org>
+
+ * INSTALL: Note gnome dependencies.
+
+2003-09-22 15:53 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Doc
+
+2003-09-22 14:51 Martin Pool <mbp@samba.org>
+
+ * src/remote.c: Store hostname in state file, not the host
+ definition string.
+
+2003-09-20 19:36 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Add menu option to show chart key.
+
+2003-09-19 17:21 Martin Pool <mbp@samba.org>
+
+ * src/: renderer.c, renderer.h: Set bar width so that the whole
+ history cell is filled.
+
+2003-09-19 16:53 Martin Pool <mbp@samba.org>
+
+ * gnome/.cvsignore: Rename icon PNG
+
+2003-09-19 16:51 Martin Pool <mbp@samba.org>
+
+ * gnome/distccmon-gnome.glade: Rename icon png.
+
+2003-09-19 16:35 Martin Pool <mbp@samba.org>
+
+ * gnome/distccmon-gnome.desktop: Add draft FreeDesktop .desktop
+ definition.
+
+2003-09-19 16:02 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Choose bar width such that the complete history
+ roughly fills the cell.
+
+2003-09-19 15:40 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: Quieten warnings when polling state files.
+
+2003-09-19 15:39 Martin Pool <mbp@samba.org>
+
+ * src/state.c: Change state name to "Preprocess".
+
+2003-09-19 15:15 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Doc.
+
+2003-09-19 14:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Add --enable-profile option.
+
+ * Cleanup CPPFLAGS generation.
+
+2003-09-19 14:29 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Manpage updates.
+
+2003-09-19 12:44 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Suggest using SCons.
+
+2003-09-19 12:41 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: [no log message]
+
+2003-09-19 12:35 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: More explanation of Make and compiler errors.
+
+2003-09-19 12:30 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: More discussion of where to place localhost in
+ the list.
+
+2003-09-19 12:21 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: [no log message]
+
+2003-09-19 12:06 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-09-19 12:03 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-09-18 19:53 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Retain history of 100 states.
+
+2003-09-18 18:58 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Draw "DONE" states as empty.
+
+2003-09-18 18:32 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Render the slot history as a set of state
+ stripes. This looks great!
+
+2003-09-18 18:18 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Kill dead code.
+
+2003-09-18 18:01 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Trim the history queue length every time we
+ add to it.
+
+2003-09-18 17:58 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Fix pointer error in prepending to an existing
+ history queue.
+
+2003-09-18 17:55 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Fix up code to insert at end.
+
+2003-09-18 17:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Fix number of columns.
+
+2003-09-18 17:04 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Add textual State column.
+
+2003-09-18 17:00 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: Don't sort localhost specially. I think this was
+ buggy.
+
+2003-09-18 16:28 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: After we finish the task list, clear any rows
+ remaining in the table.
+
+2003-09-18 16:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/renderer.c: Silently ignore NULL "history" properties.
+
+2003-09-18 16:12 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Typo
+
+2003-09-18 15:38 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * gnome/distccmon-gnome.glade: Vertical scrollbar auto;
+ horizontal scrollbar never.
+
+2003-09-18 15:20 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/renderer.c: Render the state cell solidly filled with the
+ color for the current state.
+
+2003-09-18 15:02 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Remove dead code.
+
+2003-09-18 14:59 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Show file name in the table too.
+
+2003-09-18 14:54 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * AUTHORS: [no log message]
+
+2003-09-18 10:20 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note portability fixes.
+
+2003-09-18 10:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/ncpus.c: If we failed to determine the number of CPUs using
+ sysconf, then assume 1.
+
+2003-09-18 10:14 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon.c: Files only 60s old are now considered too old.
+
+2003-09-17 15:41 Martin Pool <mbp@samba.org>
+
+ * NEWS, autogen.sh: Fix autogen.sh for recent versions of GNU
+ coreutils. Reported by Lisa Seelye.
+
+2003-09-17 15:36 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Skip tasks on no host
+
+ * Draw labels again
+
+ * Refresh every 300ms
+
+2003-09-17 12:24 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: GtkCellRenderer is no longer needed
+
+2003-09-17 12:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * man/distcc.1: Set date.
+
+2003-09-17 12:14 Martin Pool <mbp@samba.org>
+
+ * man/: distccd.1, distcc.1: Add no-warranty statement.
+
+2003-09-17 12:11 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: COPYING.FDL is no longer included, because the
+ manpages are GPL'd.
+
+2003-09-16 19:27 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Only draw rectangles of >=1 width.
+
+2003-09-16 19:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * patches/lisa--recursive-mkdir-uid-distccdir.patch: Patch from
+ Lisa.
+
+2003-09-16 19:00 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Better attempt at drawing current and previous
+ tasks.
+
+2003-09-16 18:38 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Make a better attempt at always recording DONE
+ when we are.
+
+2003-09-16 18:13 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/state.h: Add a pointer to the next on this slot.
+
+2003-09-16 15:55 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon.c: Sort localhost to the front of the list of tasks.
+
+2003-09-16 15:04 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon.c: Don't need signal.c
+
+2003-09-16 14:23 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note that we should now work on BSD/OS.
+
+2003-09-16 14:20 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exec.c: Call getpgrp() rather than getpgid(), because it's
+ the POSIX.1 standard function.
+
+2003-09-16 13:56 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Draw host names on left. (Not very well. :-)
+
+2003-09-16 13:24 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Fix up rollback.
+
+2003-09-16 13:07 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * gnome/distccmon-gnome.glade: Merge back to DrawingArea in
+ 1.1.2.14. No other changes.
+
+2003-09-15 17:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/renderer.c: Fix horizontal gaps between stripes.
+
+2003-09-15 17:30 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Update every 200ms
+
+2003-09-15 17:23 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Draw tasks as multiple strips for each state.
+
+2003-09-15 17:18 Martin Pool <mbp@samba.org>
+
+ * src/: mon-gnome.c, mon.h: Remove old GCs
+
+ * Make dcc_timeval_to_double global
+
+2003-09-15 17:14 Martin Pool <mbp@samba.org>
+
+ * src/mon-fake.c: Split out code for fake monitor data; currently
+ not used.
+
+2003-09-15 17:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/renderer.c: Fix unused params.
+
+2003-09-15 16:36 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/renderer.c: Draw state color and filename from the history
+ record.
+
+2003-09-15 16:29 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/where.c: Only enter BLOCKED state when we need to sleep
+ waiting for a slot.
+
+2003-09-15 16:03 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Sleep only 1s when bored.
+
+2003-09-15 16:02 Martin Pool <mbp@samba.org>
+
+ * src/state.h: Expose client state.
+
+2003-09-15 16:01 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-text.c: Show slot number in text display.
+
+2003-09-15 15:33 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/renderer.c: Make the colored region fill the whole strip.
+
+2003-09-15 14:46 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Draw text for jobs vertically centered within
+ their rectangle.
+
+2003-09-15 00:41 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Draw text into the task blocks.
+
+2003-09-14 20:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Cosmetic
+
+2003-09-14 19:24 Martin Pool <mbp@samba.org>
+
+ * src/: mon-gnome.c, renderer.c: Renderer now draws process
+ states in something like the right color.
+
+2003-09-14 17:43 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Add get/set code for history property.
+
+2003-09-14 17:40 Martin Pool <mbp@samba.org>
+
+ * src/: renderer.c, renderer.h: The implementation structures for
+ the cell renderer can be more private.
+
+2003-09-14 17:38 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Add release header.
+
+2003-09-14 17:09 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Doc
+
+2003-09-12 17:23 Martin Pool <mbp@samba.org>
+
+ * src/renderer.h: Add state field to _DccCellRendererChart
+
+2003-09-12 17:16 Martin Pool <mbp@samba.org>
+
+ * src/renderer.c: Implement dcc_cell_renderer_chart_get_size
+
+2003-09-12 17:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/renderer.c: Implement the get_property and set_property
+ methods.
+
+2003-09-12 15:49 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: renderer.c, renderer.h: Add GTK Type boilerplate to
+ create a new GtkCellRenderer.
+
+2003-09-12 13:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in, src/mon-gnome.c, src/renderer.c: Split out draft
+ GtkCellRenderer into its own file.
+
+2003-09-11 19:07 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Start adding a custom renderer. Doesn't do
+ anything yet.
+
+2003-09-11 18:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Put hostname and state into the tree model as
+ they're updated.
+
+2003-09-11 18:47 Martin Pool <mbp@samba.org>
+
+ * gnome/distccmon-gnome.glade: Turn off rules_hint on table.
+
+2003-09-11 18:23 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Add a task column.
+
+2003-09-11 18:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Cut out trace messages.
+
+2003-09-11 17:31 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Cut out expose trace events.
+
+2003-09-10 22:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in, configure.ac: We need Pango as well for GNOME.
+
+2003-09-10 18:27 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Start adding support for fake monitor data for
+ testing.
+
+2003-09-10 17:03 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Draw tasks from the task list.
+
+2003-09-10 16:25 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Draw tasks by creating a new PangoLayout each
+ time using the GTK+ helper.
+
+2003-09-10 16:13 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Draw labels onto file rectangles using Pango.
+ How cool!
+
+2003-09-10 15:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Allocate GCs for all states.
+
+ * Draw nice gray outlines around all task rectangles.
+
+2003-09-10 15:05 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Invalidate/repaint the chart widget every time
+ we update the list.
+
+2003-09-10 15:00 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Stub for on_chart_drawing_expose().
+
+2003-09-10 14:19 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/state.h: States must be listed in the order in which
+ they're run.
+
+2003-09-09 18:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/compile.c: Record input filename as soon as it is known.
+
+2003-09-09 17:53 Martin Pool <mbp@samba.org>
+
+ * src/state.c: Don't update state times that are already
+ recorded.
+
+2003-09-09 17:52 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: compile.c, distcc.c: Go into STARTUP state earlier in the
+ client process.
+
+2003-09-09 17:09 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/compile.c: Please do use DCC_STATE_STARTUP so that we know
+ when we started.
+
+2003-09-09 16:43 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Factor out code to create canvas items for the
+ task
+
+2003-09-09 16:21 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Color task bars according to current state.
+
+2003-09-08 21:12 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Check for glade definition file in ., ./gnome,
+ and DATADIR.
+
+2003-09-08 21:10 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Fix Make syntax
+
+2003-09-08 21:09 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Pass in DATADIR (e.g. /usr/local/share) when
+ installing.
+
+2003-09-08 18:11 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: More experiments in drawing.
+
+2003-09-08 18:10 Martin Pool <mbp@samba.org>
+
+ * gnome/distccmon-gnome.glade: Try a Canvas in a GtkAlignment
+
+2003-09-08 17:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Fix up (mostly renames) for new monitor
+ interface.
+
+2003-09-08 16:21 Martin Pool <mbp@samba.org>
+
+ * src/mon-text.c: Skip display of Done tasks.
+
+2003-09-08 16:20 Martin Pool <mbp@samba.org>
+
+ * src/state.c: Add missing state names.
+
+2003-09-08 16:19 Martin Pool <mbp@samba.org>
+
+ * src/state.c: Make sure to actually record our state!
+
+2003-09-08 16:12 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon.c: Processes that have exited can still be returned.
+
+2003-09-08 16:01 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/state.c: Put the client pid into the state file.
+
+2003-09-08 15:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/state.c: Store history of state transitions in the state
+ file.
+
+2003-09-08 15:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: util.h, util.c: Add strlcpy() if missing.
+
+2003-09-08 15:29 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Add check for strlcpy().
+
+2003-09-08 13:17 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Draw rectangles onto the canvas for each job
+ that's currently running.
+
+2003-09-08 13:11 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Set canvas scroll region at startup.
+
+2003-09-08 13:04 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Rename setup_proc_view -> setup_table_view.
+
+ * Doc.
+
+2003-09-08 12:44 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Document design of chart view.
+
+2003-09-07 22:54 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Draw a rectangle onto the chart to see it
+ working.
+
+2003-09-07 19:09 Martin Pool <mbp@samba.org>
+
+ * gnome/distccmon-gnome.glade: Swich from a DrawingArea to a
+ Canvas for the chart view.
+
+2003-09-07 19:04 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Swich from a DrawingArea to a Canvas for the
+ chart view.
+
+2003-09-07 19:03 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * gnome/mon-gnome.c, src/mon-gnome.c: Move mon-gnome.c back to
+ src/
+
+2003-09-05 17:01 Martin Pool <mbp@samba.org>
+
+ * gnome/mon-gnome.c: Abort if we can't find the glade XML file.
+
+2003-09-04 15:20 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Clear up explanation of --allow option.
+
+ * Note that "gcc hello.c" is not split.
+
+2003-09-03 12:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * gnome/: distccmon-gnome.glade, mon-gnome.c: Draw big black
+ ellipse in the chart area.
+
+2003-09-01 23:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * gnome/distccmon-gnome.glade: Put tabs on the notebook just for
+ the time being.
+
+2003-09-01 23:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * gnome/: distccmon-gnome.glade, mon-gnome.c: Get load bar hooked
+ up for Gnome monitor.
+
+2003-09-01 22:04 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * gnome/mon-gnome.c: Merge in all the GNOME monitor code from
+ HEAD.
+
+2003-09-01 21:23 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Check for other necessary libraries when
+ --enable-gnome is given.
+
+ * Bump version.
+
+2003-09-01 13:33 Martin Pool <mbp@samba.org>
+
+ * TODO: Idea of using gkrellm
+
+2003-09-01 11:30 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Add a little more explanation of --allow.
+
+2003-08-28 15:05 Martin Pool <mbp@samba.org>
+
+ * TODO: Update for done tasks.
+
+2003-08-28 15:02 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Note that ccache can't be called from distccd.
+
+2003-08-28 14:33 Martin Pool <mbp@samba.org>
+
+ * NEWS, man/distcc.1: Note about problems with no_subtree_check.
+
+2003-08-28 14:31 Martin Pool <mbp@samba.org>
+
+ * TODO: DEPENDENCIES_OUTPUT is not directly a problem for distcc.
+
+2003-08-28 12:48 Martin Pool <mbp@samba.org>
+
+ * cases/mmaptest.c: Bug has been isolated; no longer need this
+ test case.
+
+2003-08-28 12:45 Martin Pool <mbp@samba.org>
+
+ * cases/mmaptest.c: More tests for NFS bug.
+
+2003-08-26 15:56 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * cases/: .cvsignore, mmaptest.c: Add test for mmap-on-NFS
+ problems
+
+2003-08-25 16:06 Martin Pool <mbp@samba.org>
+
+ * src/pump.c: Doc
+
+2003-08-25 12:48 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c, compile.c, compress.c, serve.c: Patch from Wayne
+ Davison to fix Solaris warnings
+
+2003-08-25 11:55 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * man/distcc.1, man/distccd.1, NEWS: Document DISTCC_MMAP.
+
+2003-08-15 14:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Move gnome monitor into its own directory.
+
+2003-08-14 18:12 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: Note problem with DEPENDENCIES_OUTPUT.
+
+2003-08-13 12:57 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version.
+
+2003-08-12 13:34 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Update manpage date.
+
+2003-08-12 13:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Note "make clean" problem is fixed.
+
+2003-08-12 13:09 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version to 2.10.1
+
+2003-08-12 11:42 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Fix "make clean" problem in lzo. Reported by Lisa
+ Marie Seelye.
+
+2003-08-11 16:09 Martin Pool <mbp@samba.org>
+
+ * cases/hello.c: Make hello actually say hello
+
+2003-08-11 16:07 Martin Pool <mbp@samba.org>
+
+ * distcc-check: Allow the compiler to be changed.
+
+2003-08-11 16:05 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Prepare for release.
+
+2003-08-11 15:51 Martin Pool <mbp@samba.org>
+
+ * TODO: Suggestions from Lisa on the monitor.
+
+2003-08-11 15:46 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Fix from wayned for crash when DISTCC_DIR is
+ set.
+
+2003-08-11 15:43 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Doc.
+
+2003-08-11 15:40 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: [no log message]
+
+2003-08-11 15:33 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-08-11 15:32 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Corrections from Frerich Raabe.
+
+2003-08-11 15:18 Martin Pool <mbp@samba.org>
+
+ * src/exec.c, NEWS: For simple compile failures, don't say "with
+ exit code 1".
+
+2003-08-11 15:15 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Doc.
+
+2003-08-07 15:42 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-08-05 12:09 Martin Pool <mbp@samba.org>
+
+ * src/exitcode.h: Add include guard.
+
+2003-08-05 11:56 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove roadmap page, because it's now largely
+ complete.
+
+2003-08-05 11:53 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Make sure examples get installed into doc/example.
+
+2003-08-05 11:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/results.txt: [no log message]
+
+2003-07-25 17:25 Martin Pool <mbp@samba.org>
+
+ * bench/Summary.py: Show summary table properly.
+
+2003-07-25 15:50 Martin Pool <mbp@samba.org>
+
+ * src/state.c, NEWS: Roll back to writing state into temporary
+ files.
+
+2003-07-25 15:36 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc
+
+2003-07-25 15:35 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: If the daemon fails to bind to the desired
+ port, keep trying other ones.
+
+2003-07-25 15:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/state.c: Fix state file names.
+
+2003-07-25 15:14 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-07-25 14:53 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Make temp filenames more random.
+
+2003-07-25 14:51 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Check return code when closing the temporary
+ file after creating it.
+
+2003-07-25 14:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/tempfile.c: dcc_make_tmpnam: Fix the case where the chosen
+ name already exists.
+
+2003-07-25 14:34 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: cpp.c, serve.c: Better template names for temporary
+ files.
+
+2003-07-25 14:08 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Check for gettimeofday
+
+2003-07-25 13:52 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Temporary directory is no longer used.
+
+2003-07-25 12:35 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: cleanup.c is also needed by monitors.
+
+2003-07-25 11:53 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Daemon runs from root directory, not the
+ temporary directory.
+
+ * Doc.
+
+2003-07-25 11:51 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c, src/tempfile.h, NEWS: Daemon runs from root
+ directory, not the temporary directory.
+
+2003-07-24 18:58 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Doc
+
+2003-07-24 18:46 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Remove dead fifo code.
+
+2003-07-24 18:45 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * patches/ccache-uncached-err.diff: Patch to ccache to avoid
+ caching network errors.
+
+2003-07-24 18:20 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note about tmpdir fixes.
+
+2003-07-24 18:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-07-23 16:56 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Doc.
+
+2003-07-23 16:11 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Don't check that TMPDIR starts with '/'.
+
+ * dcc_setup_tempdir can be static.
+
+2003-07-23 16:11 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.h: dcc_setup_tempdir can be static.
+
+2003-07-23 16:09 Martin Pool <mbp@samba.org>
+
+ * NEWS: Don't check that TMPDIR starts with '/'.
+
+2003-07-22 18:02 Martin Pool <mbp@samba.org>
+
+ * src/pump.c: Doc.
+
+2003-07-22 17:36 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Be strict about enums.
+
+2003-07-22 17:35 Martin Pool <mbp@samba.org>
+
+ * src/: clirpc.c, rpc.c, rpc.h: waitstatus is not unsigned.
+
+2003-07-22 17:34 Martin Pool <mbp@samba.org>
+
+ * src/filename.c: dcc_output_from_source: Remove dead variable.
+
+2003-07-22 17:33 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Remove doubled CFLAG.
+
+2003-07-22 17:30 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: waitstatus is not unsigned.
+
+2003-07-22 17:25 Martin Pool <mbp@samba.org>
+
+ * src/: exec.h, distcc.h: waitstatus is not unsigned.
+
+2003-07-22 17:24 Martin Pool <mbp@samba.org>
+
+ * src/compile.c: Signedness warning correction; reported by
+ Dimitri Papadopoulos.
+
+2003-07-22 17:21 Martin Pool <mbp@samba.org>
+
+ * src/remote.c: timeval.h is not needed.
+
+2003-07-22 17:19 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Snip out dcc_mkfifo
+
+2003-07-22 16:58 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-07-22 16:57 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Document UNCACHED_ERR_FD.
+
+2003-07-22 16:55 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Note that ccache doesn't handle compilation from
+ .i files.
+
+2003-07-22 16:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-07-22 16:35 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Remove duplicated dcc_find_basename().
+
+2003-07-22 14:16 Martin Pool <mbp@samba.org>
+
+ * distcc-check: Doc
+
+2003-07-22 14:13 Martin Pool <mbp@samba.org>
+
+ * NEWS: Default niceness is 5.
+
+2003-07-22 14:11 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, dopt.c, dopt.h, util.c: Increment niceness by 5
+ by default.
+
+2003-07-22 14:08 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Clarify that niceness is an increment not an
+ absolute value.
+
+ * Default niceness is 5.
+
+2003-07-22 13:58 Martin Pool <mbp@samba.org>
+
+ * NEWS: Nasty note about SCO.
+
+2003-07-22 13:53 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: SSH results.
+
+2003-07-22 12:43 Martin Pool <mbp@samba.org>
+
+ * README.packaging: More suggestions about cross compiling from
+ Dag Wieers.
+
+2003-07-21 17:37 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Note about finding the right compiler on the volunteer.
+
+2003-07-21 17:14 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc.
+
+2003-07-21 16:35 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c: Doc.
+
+2003-07-21 16:31 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: distcc/main: Rename variable.
+
+2003-07-21 16:25 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Bump version.
+
+2003-07-21 15:50 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Remove PP
+
+2003-07-21 15:24 Martin Pool <mbp@samba.org>
+
+ * configure.ac, NEWS: 2.9 release.
+
+2003-07-21 15:14 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Make sure GNOME_BIN actually gets set.
+
+2003-07-21 15:10 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: lzoconf.h needs to be distributed.
+
+2003-07-21 15:07 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: [no log message]
+
+2003-07-21 14:59 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * man/distccd.1: Suggest inetd limit be raised to 6000
+
+2003-07-21 14:42 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-07-21 14:40 Martin Pool <mbp@samba.org>
+
+ * src/compress.c: dcc_compress_lzo1x_alloc can be static.
+
+2003-07-21 14:20 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: dcc_compress_lzo1x_alloc can be static.
+
+2003-07-21 12:45 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note about documentation.
+
+2003-07-21 12:35 Martin Pool <mbp@samba.org>
+
+ * src/compress.c: Trace message for use of mmap.
+
+2003-07-21 12:31 Martin Pool <mbp@samba.org>
+
+ * src/pump.c: Trace message for receipt using mmap.
+
+2003-07-21 12:23 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Tweak daemon startup message.
+
+2003-07-21 12:21 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Show gnu-host in daemon startup message.
+
+2003-07-21 12:13 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-07-21 12:02 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Update host grammar from manpage.
+
+2003-07-21 12:01 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * man/distcc.1: Add ccache URL
+
+ * Cleanup
+
+2003-07-21 11:56 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Some cleanups from Tim and myself.
+
+2003-07-21 11:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Note mmap support.
+
+ * Delete trailing whitespace.
+
+2003-07-21 11:17 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Add information about compression.
+
+2003-07-18 16:50 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/results.txt: [no log message]
+
+2003-07-18 16:39 Martin Pool <mbp@samba.org>
+
+ * src/pump.c: Start implementing dcc_r_bulk_plain
+
+2003-07-18 16:32 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Fix silly error in ParseHostSpec_Case.
+
+2003-07-18 15:59 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Fix VersionOption_Case for new version
+ string that mentions two protocols.
+
+2003-07-18 15:58 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add partial test for parsing host
+ specifications with the LZO option.
+
+2003-07-18 15:57 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: ',' should also terminate TCP hostnames.
+
+2003-07-18 15:48 Martin Pool <mbp@samba.org>
+
+ * NEWS: More about compression.
+
+2003-07-18 15:45 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add support for ",lzo" option at the end of host
+ specifications.
+
+2003-07-18 15:43 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: ',' should also terminate SSH hostnames.
+
+2003-07-18 15:42 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Add support for ",lzo" option at the end of host
+ specifications.
+
+2003-07-18 15:02 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: Results from 3.4 snapshot.
+
+2003-07-18 13:16 Martin Pool <mbp@samba.org>
+
+ * src/: rpc.h, rpc.c: Remove obsolete dcc_compr_for_proto()
+
+2003-07-18 13:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.h: Reorder enums to top.
+
+2003-07-18 12:18 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: Make dcc_compress values not be 0-based.
+
+2003-07-18 12:01 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, src/clirpc.c, src/clirpc.h, src/distcc.h,
+ src/remote.c: Remove clirpc.h.
+
+2003-07-18 11:35 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/hosts.c: Document upcoming compression option for host
+ specifications.
+
+2003-07-17 22:01 Martin Pool <mbp@samba.org>
+
+ * doc/protocol-2.txt: [no log message]
+
+2003-07-17 22:00 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include description of protocol version 2.
+
+2003-07-17 21:59 Martin Pool <mbp@samba.org>
+
+ * doc/protocol-2.txt: Description of protocol version 2.
+
+2003-07-17 17:18 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Doc.
+
+2003-07-17 17:16 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/compress.c: Doc.
+
+ * Only use mmap for buffers larger than 64k.
+
+2003-07-17 17:04 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-07-17 17:03 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Add hostspec grammar
+
+ * Some formatting changes.
+
+2003-07-17 17:00 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Fix grammar nit.
+
+2003-07-17 16:39 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1, src/dopt.c: Document --wizard.
+
+2003-07-17 16:35 Martin Pool <mbp@samba.org>
+
+ * NEWS, man/distccd.1: Change to starting 2+NCPUS jobs by
+ default.
+
+2003-07-17 16:31 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Change to starting 2+NCPUS jobs by default.
+
+2003-07-17 16:24 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Clean lzo/ directory. Patch from Wayne Davison.
+
+2003-07-17 15:52 Martin Pool <mbp@samba.org>
+
+ * distcc-check: Doc
+
+2003-07-17 10:37 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Remove the "tested" page.
+
+2003-07-15 19:00 Martin Pool <mbp@samba.org>
+
+ * src/mapfile.c: Remove mapfile; mmap is now called directly.
+
+2003-07-15 18:51 Martin Pool <mbp@samba.org>
+
+ * src/compress.c: Quieten warning.
+
+2003-07-15 18:50 Martin Pool <mbp@samba.org>
+
+ * src/compress.c: Doc
+
+ * dcc_receive_lzo1x: Pass the right value to munmap().
+
+2003-07-15 18:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/compile.c: Disable "startup" state.
+
+2003-07-15 18:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/results.txt: Results from compilation on 10Mbps network.
+
+2003-07-15 18:18 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: mapfile is no longer needed -- we just mmap as
+ necessary.
+
+2003-07-15 18:10 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Check for mmap()
+
+2003-07-15 18:02 Martin Pool <mbp@samba.org>
+
+ * src/: bulk.c, compress.c, compress.h: Factor out code to
+ compress from a file.
+
+2003-07-15 17:57 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: dcc_calc_rate: Guard against division by zero
+ (which never seems to happen).
+
+ * Doc.
+
+2003-07-15 17:51 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note compression.
+
+2003-07-15 17:40 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.h, dopt.h, srvnet.c: Clean up dopt headers.
+
+2003-07-15 17:38 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: Notes on testing compression.
+
+2003-07-15 17:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Make columns in the GNOME monitor resizable,
+ as well as auto-resizing.
+
+2003-07-15 11:32 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: dcc_r_file: Doc. Fix uninitialized variable for
+ 0-length files.
+
+2003-07-14 22:02 Martin Pool <mbp@samba.org>
+
+ * src/compress.c: Show decompression ratio as small:large.
+
+2003-07-14 21:51 Martin Pool <mbp@samba.org>
+
+ * src/pump.c: dcc_pump_in: Handle 0-byte optimization too.
+
+2003-07-14 21:45 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Add optimization of not doing any compression for
+ 0-byte files.
+
+2003-07-14 21:39 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/io.h: compress.h: New header.
+
+2003-07-14 21:38 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Fix --wizard.
+
+2003-07-14 21:38 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/dopt.c: Rename to --wizard.
+
+2003-07-14 21:22 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Add -X, --maintainer option that adds all settings
+ for running under gdb.
+
+2003-07-14 18:10 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/compress.c: Doc
+
+2003-07-14 17:35 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: [no log message]
+
+2003-07-14 17:35 Martin Pool <mbp@samba.org>
+
+ * man/.cvsignore: Ignore built HTML files.
+
+2003-07-14 16:56 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: [no log message]
+
+2003-07-14 16:52 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Don't install README.packaging or SuSE example
+ init script.
+
+2003-07-14 16:49 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Strip out linuxdoc, because all the information
+ there has been merged into the manpages.
+
+2003-07-14 16:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * man/: distccd.1, distcc.1: Credit other people.
+
+2003-07-14 16:35 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Document DISTCC_SAVE_TEMPS
+
+2003-07-14 16:34 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Merge option descriptions and other things.
+
+2003-07-14 16:15 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Merge more information.
+
+2003-07-14 15:50 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Merge more information.
+
+2003-07-14 15:44 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Merge more information.
+
+2003-07-14 15:16 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Merge more information.
+
+2003-07-14 14:54 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add targets to build HTML from manpages.
+
+2003-07-14 14:47 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Start adding more details about the server.
+
+2003-07-14 14:46 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Merge stuff about cross-compiling.
+
+ * More about security.
+
+2003-07-14 14:41 Martin Pool <mbp@samba.org>
+
+ * INSTALL: More about how to install distccd.
+
+2003-07-14 14:33 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: More manpage documentation.
+
+2003-07-14 13:45 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Put a lot more useful information into the manual
+ page.
+
+2003-07-14 12:42 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Information on reporting bugs has been
+ merged into a separate file.
+
+2003-07-14 12:35 Martin Pool <mbp@samba.org>
+
+ * doc/reporting-bugs.txt: Merge more information on reporting
+ problems from the SGML manual.
+
+2003-07-14 12:32 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include information on how to report bugs
+ effectively.
+
+2003-07-14 12:31 Martin Pool <mbp@samba.org>
+
+ * doc/reporting-bugs.txt: Information on how to report bugs
+ effectively.
+
+2003-07-14 12:20 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include example-init in package.
+
+2003-07-14 12:14 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: Increase allowable age of state files to 300s.
+
+2003-07-14 12:09 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: mon-notify.o is not currently used by the
+ monitors.
+
+2003-07-14 11:53 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: mon-gnome.c, mon-notify.c, mon.c: Fix header ordering.
+
+2003-07-14 10:47 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Remove standard GTK test macros because we don't
+ use them.
+
+2003-07-13 18:40 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Clean up files which were duplicated in dist_files
+ and pkgdoc_DOCS.
+
+2003-07-13 18:09 Martin Pool <mbp@samba.org>
+
+ * patches/.cvsignore: Add built program.
+
+2003-07-13 18:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Doc
+
+2003-07-13 17:57 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-07-13 17:55 Martin Pool <mbp@samba.org>
+
+ * DEPENDENCIES, Makefile.in: Remove DEPENDENCIES file, which is
+ being merged into INSTALL.
+
+2003-07-13 17:30 Martin Pool <mbp@samba.org>
+
+ * INSTALL: Rewrite installation instructions to be specific to
+ distcc and to cover all the main steps.
+
+2003-07-13 12:44 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * man/distcc.1: Correction for duplicated word by Tobias
+ Stoeckmann.
+
+2003-07-12 17:04 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc.
+
+2003-07-12 16:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c, NEWS: Add checks for -Wa options that produce an
+ assembler listing file.
+
+2003-07-12 11:45 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add tests for new -o and -Wa,-al handling.
+
+2003-07-12 01:31 Martin Pool <mbp@samba.org>
+
+ * src/compress.c: Add implementation of LZO decompression.
+
+2003-07-12 01:30 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-07-12 00:58 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2003-07-11 18:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/ProjectDefs.py: Add other definitions needed for building
+ firebird.
+
+2003-07-11 18:18 Martin Pool <mbp@samba.org>
+
+ * cases/simple.c: Simple test with no header files.
+
+2003-07-11 17:27 Martin Pool <mbp@samba.org>
+
+ * bench/compiler.py: New/better naming of build directories: now
+ just 'dist,2'.
+
+2003-07-11 17:26 Martin Pool <mbp@samba.org>
+
+ * bench/ProjectDefs.py: Comment out Mozilla, which is having
+ trouble on Debian.
+
+ * Add MozillaFirebird.
+
+2003-07-11 17:25 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/ProjectDefs.py: Fix unpacked_subdir for Mozilla
+
+2003-07-11 15:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/Project.py: We need wget --continue to get the intended
+ behaviour.
+
+2003-07-11 15:10 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/results.txt: More benchmark stuff.
+
+2003-07-11 14:50 Martin Pool <mbp@samba.org>
+
+ * bench/Summary.py: Fix uname usage.
+
+2003-07-11 14:50 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/benchmark.py: Show -a in help.
+
+2003-07-11 14:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: filename.h, distcc.h, implicit.c: Move declarations for
+ filename.c into filename.h.
+
+2003-07-11 14:18 Martin Pool <mbp@samba.org>
+
+ * src/filename.h: dcc_is_object: New function.
+
+2003-07-11 14:17 Martin Pool <mbp@samba.org>
+
+ * src/filename.c: dcc_is_object: New function.
+
+ * filename.c: Doesn't need sys/stat.h.
+
+ * Doc.
+
+2003-07-11 14:13 Martin Pool <mbp@samba.org>
+
+ * Doxyfile: Don't produce LaTeX
+
+2003-07-11 14:10 Martin Pool <mbp@samba.org>
+
+ * src/filename.c: Doc
+
+2003-07-11 14:09 Martin Pool <mbp@samba.org>
+
+ * patches/.cvsignore: Ignore built programs.
+
+2003-07-11 13:34 Martin Pool <mbp@samba.org>
+
+ * src/: exec.c, exec.h: dcc_execvp() can be static
+
+2003-07-09 18:30 Martin Pool <mbp@samba.org>
+
+ * src/compress.c, TODO: Start a decompressor.
+
+2003-07-09 18:06 Martin Pool <mbp@samba.org>
+
+ * src/compress.c: First cut at implementation of dcc_send_lzo1x1.
+
+2003-07-09 18:05 Martin Pool <mbp@samba.org>
+
+ * src/mapfile.c: Finish implementing dcc_map_input_file.
+
+2003-07-09 17:52 Martin Pool <mbp@samba.org>
+
+ * src/mapfile.c, Makefile.in, src/io.h: Add simple mmap routine
+ for reading input files.
+
+2003-07-09 17:42 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Check for sys/mman.h
+
+2003-07-09 17:39 Martin Pool <mbp@samba.org>
+
+ * src/pump.c: Call dcc_send_lzo1x1 for compressed mode.
+
+2003-07-09 17:38 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * patches/trylzo.c: Simple test harness to measure lzo1x1
+ compression.
+
+2003-07-09 16:49 Martin Pool <mbp@samba.org>
+
+ * src/compress.c: Stub file for doing bulk compression.
+
+2003-07-09 16:28 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/timebuild: Remove 'timebuild' script because it's replaced
+ by a better benchmark script.
+
+2003-07-09 15:54 Martin Pool <mbp@samba.org>
+
+ * src/sendfile.c: Handle EINTR from sendfile().
+
+2003-07-09 15:44 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Remove check for poptGetContext that made us get
+ an unnecessary second -lpopt option.
+
+2003-07-09 15:39 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Doc
+
+2003-07-09 15:38 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Bump version.
+
+2003-07-09 14:31 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes on distcc-check and globally visible state.
+
+2003-07-09 14:17 Martin Pool <mbp@samba.org>
+
+ * TODO: Update for current progress.
+
+2003-07-09 13:41 Martin Pool <mbp@samba.org>
+
+ * TODO: 0-length output files are now handled OK.
+
+2003-07-09 13:13 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Credit Marcelo Matus.
+
+2003-07-09 12:46 Martin Pool <mbp@samba.org>
+
+ * NEWS: Bump version to 2.8
+
+2003-07-09 12:01 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version to 2.8
+
+2003-07-08 17:02 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: More results from SSH
+
+2003-07-08 16:58 Martin Pool <mbp@samba.org>
+
+ * src/md.c, Makefile.in: Remove md.c because we can't do anything
+ very useful here.
+
+2003-07-08 16:49 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2003-07-08 16:49 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, src/cpp.h: Remove md.c
+
+2003-07-08 16:45 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add security page.
+
+2003-07-08 16:11 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-07-08 15:59 Martin Pool <mbp@samba.org>
+
+ * src/cpp.c: Doc.
+
+2003-07-08 15:45 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.h, Makefile.in: arg.h: new file.
+
+2003-07-08 15:17 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2003-07-08 15:11 Martin Pool <mbp@samba.org>
+
+ * src/md.c: Doc
+
+2003-07-08 15:05 Martin Pool <mbp@samba.org>
+
+ * src/cpp.c: dcc_cpp_maybe: Call dcc_fudge_md.
+
+2003-07-08 15:03 Martin Pool <mbp@samba.org>
+
+ * src/: md.c, cpp.h: md.c: new file for dependency generation.
+
+2003-07-08 14:59 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: md.c: new file.
+
+2003-07-08 14:53 Martin Pool <mbp@samba.org>
+
+ * src/strip.c: Doc.
+
+2003-07-08 14:49 Martin Pool <mbp@samba.org>
+
+ * src/cpp.c: Doc.
+
+2003-07-08 14:44 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2003-07-08 14:36 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/argutil.c: New file containing argv[] utilities.
+
+2003-07-08 14:24 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add test for distcc cc -otesttmp.o
+
+2003-07-08 14:01 Martin Pool <mbp@samba.org>
+
+ * NEWS: dcc_set_output: Add support for -ofoo.o. Based on a
+ patch from Tsutomu Yasuda.
+
+2003-07-08 13:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * distcc-check: Simple sanity-check script.
+
+2003-07-08 13:23 Martin Pool <mbp@samba.org>
+
+ * doc/example-init: Example Red Hat init file from Andrew Morton.
+
+2003-07-08 13:20 Martin Pool <mbp@samba.org>
+
+ * NEWS: Example xinetd configuration from akpm.
+
+2003-07-08 13:19 Martin Pool <mbp@samba.org>
+
+ * doc/example.xinetd: Doc
+
+2003-07-08 13:16 Martin Pool <mbp@samba.org>
+
+ * doc/example.xinetd, Makefile.in: Example xinetd configuration
+ from akpm.
+
+2003-07-08 13:06 Martin Pool <mbp@samba.org>
+
+ * src/remote.c: Doc.
+
+2003-07-08 12:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-07-08 12:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/remote.c: dcc_remote_connect: Factor out code to open a
+ connection from dcc_compile_remote.
+
+2003-07-07 23:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/io.c: Handle EINTR from read and write.
+
+2003-07-07 23:44 Martin Pool <mbp@samba.org>
+
+ * src/io.c: dcc_select_for_write: Handle EINTR.
+
+ * Doc.
+
+2003-07-07 23:37 Martin Pool <mbp@samba.org>
+
+ * src/io.c, NEWS: dcc_select_for_read: Fix silly parameter
+ ordering mistake.
+
+2003-07-07 23:31 Martin Pool <mbp@samba.org>
+
+ * src/io.c: dcc_select_for_read: Fix warning.
+
+2003-07-07 23:27 Martin Pool <mbp@samba.org>
+
+ * src/io.c: dcc_select_for_read: Better trace messages.
+
+2003-07-07 23:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Don't give a warning about linuxdoc, because we
+ do it during installation.
+
+2003-07-07 23:03 Martin Pool <mbp@samba.org>
+
+ * src/: serve.c: Doc.
+
+2003-07-07 22:57 Martin Pool <mbp@samba.org>
+
+ * NEWS: If Linuxdoc was not detected, just give a small warning
+ and not an error while installing.
+
+2003-07-07 22:25 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/protocol-1.txt: Document the changes to support 0-byte
+ output.
+
+2003-07-07 18:34 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-07-07 18:33 Martin Pool <mbp@samba.org>
+
+ * test/badcc: Add mode to generate empty output.
+
+2003-07-07 18:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/remote.c: Doc.
+
+2003-07-07 17:59 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2003-07-07 17:48 Martin Pool <mbp@samba.org>
+
+ * src/: bulk.h, bulk.c: Be more careful about treating token
+ parameters as unsigned.
+
+2003-07-07 17:28 Martin Pool <mbp@samba.org>
+
+ * configure.ac, NEWS: Better test for vararg macro support that
+ correctly identifies apple gcc brokenness. From Matt Watson
+ <mwatson@apple.com>.
+
+2003-07-07 16:44 Martin Pool <mbp@samba.org>
+
+ * NEWS: distccmon-text: Output should always be line-buffered,
+ even if not writing to a terminal.
+
+2003-07-07 15:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Doc.
+
+2003-07-07 13:50 Martin Pool <mbp@samba.org>
+
+ * src/state.c: dcc_note_state: Quote strings in trace message.
+
+2003-07-07 12:55 Martin Pool <mbp@samba.org>
+
+ * src/mon.h, NEWS: Protect against repeated inclusion.
+ Suggestion from Fr'ed'eric Forjan.
+
+2003-07-07 12:53 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Doc.
+
+2003-06-25 17:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Increase niceness at startup.
+
+2003-06-25 17:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Prepare for 2.7.1
+
+2003-06-25 11:28 Martin Pool <mbp@samba.org>
+
+ * patches/state-in-home.diff: Store rolled-back ~/.distcc/state
+ patch.
+
+2003-06-25 11:27 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Fix EXEEXT on gnome binaries.
+
+2003-06-25 11:26 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Prepare for 2.7.1
+
+ * Fix EXEEXT on gnome binaries.
+
+2003-06-25 10:59 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * patches/hosts-from-file-raabe.diff: hosts-from-file-raabe.diff
+ Has been merged
+
+2003-06-21 14:21 Martin Pool <mbp@samba.org>
+
+ * DEPENDENCIES: Note that libgnome is no longer required.
+
+2003-06-21 13:45 Martin Pool <mbp@samba.org>
+
+ * TODO: Updates based on work done recently.
+
+2003-06-21 13:42 Martin Pool <mbp@samba.org>
+
+ * NEWS, src/state.c: State files now in ~/.distcc/state
+
+2003-06-21 13:13 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Fix constness.
+
+2003-06-20 17:32 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Doc.
+
+2003-06-20 17:29 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: stdint.h is not needed.
+
+2003-06-20 17:23 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, NEWS: distccmon-gnome now depends only on gtk+-2.0
+
+2003-06-20 17:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Add some other necessary headers.
+
+2003-06-20 17:14 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Update to use just the GTK+ 2.0 API, and
+ nothing from libgnomeui.
+
+2003-06-16 18:40 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove stupid autom4te.cache from distclean
+
+2003-06-16 18:36 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/cpp.c: Doc
+
+2003-06-16 18:30 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version
+
+2003-06-16 17:51 Martin Pool <mbp@samba.org>
+
+ * configure.ac, NEWS: Release 2.7.
+
+2003-06-16 17:50 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc
+
+2003-06-16 17:39 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-06-16 17:06 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes on dnotify.
+
+2003-06-16 16:59 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-06-16 16:50 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Need to link LIBS in to get functions like
+ inet_ntoa on Solaris, etc.
+
+2003-06-16 16:31 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Make the tree sortable.
+
+2003-06-16 14:39 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Doc.
+
+2003-06-16 14:38 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Put commas in load average line.
+
+2003-06-16 14:37 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Add a callback to update the load indicator.
+
+2003-06-16 14:26 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Fix up load indicator.
+
+2003-06-16 14:17 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Start adding a load indicator at the bottom of
+ the window.
+
+2003-06-16 13:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/tempfile.c: Doc
+
+2003-06-16 13:07 Martin Pool <mbp@samba.org>
+
+ * NEWS: Check for sys/select.h, which is not present on HP-UX.
+
+2003-06-16 13:03 Martin Pool <mbp@samba.org>
+
+ * configure.ac, src/io.c: Check for sys/select.h, which is not
+ present on HP-UX.
+
+2003-06-16 12:48 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Doc.
+
+2003-06-16 12:43 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: Doc.
+
+2003-06-16 12:33 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: dcc_note_compiled: Fix constness.
+
+2003-06-16 12:25 Martin Pool <mbp@samba.org>
+
+ * src/util.c: snprintf.h is needed.
+
+2003-06-16 12:24 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: Change dcc_trace_argv macro to try to quieten
+ warnings on Sun.
+
+2003-06-16 12:21 Martin Pool <mbp@samba.org>
+
+ * src/trace.h: Add RS_STMT_START macros from glib, to quieten
+ warnings on Sun.
+
+2003-06-16 12:19 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: snprintf.h is needed.
+
+2003-06-16 12:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/tempfile.c: Doc
+
+2003-06-16 12:05 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Fix configure messages.
+
+2003-06-16 12:04 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Only check for libgnomeui-2.0 if --enable-gnome
+ was specified.
+
+2003-06-16 11:27 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: Notes on performance of monitor with dnotify.
+
+2003-06-14 20:09 Martin Pool <mbp@samba.org>
+
+ * TODO: IPv6 is now done.
+
+2003-06-14 20:08 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes on nicely handling gcc -MD.
+
+2003-06-13 17:30 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Doc.
+
+2003-06-13 14:57 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Change default size
+
+ * Print out a star when we reread the directory.
+
+2003-06-13 14:39 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Attach to dnotify prompts from mon.c and drain
+ them as they arrive.
+
+2003-06-13 14:28 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Fix spelling mistake.
+
+2003-06-13 12:18 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: Dnotify stuff now actually writes to the dummy pipe
+ when the state changes.
+
+2003-06-13 12:14 Martin Pool <mbp@samba.org>
+
+ * src/: mon.c, state.c: Doc.
+
+2003-06-12 22:02 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: Doc
+
+2003-06-12 21:58 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: Fix up half-committed code.
+
+2003-06-12 21:55 Martin Pool <mbp@samba.org>
+
+ * configure.ac, src/mon-gnome.c: Fix up half-committed code.
+
+2003-06-12 18:13 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Fix distccmon-gnome
+
+2003-06-12 18:00 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Make sure to use the right cpp flags when building
+ distccmon-gnome
+
+2003-06-12 17:56 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: distccmon-gnome needs nonblocking routines from
+ netutil.o
+
+2003-06-12 17:50 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Refactor
+
+2003-06-12 17:37 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Doc.
+
+2003-06-12 17:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: If --enable-gnome was specified, then check that
+ libgnomeui is actually present.
+
+2003-06-12 16:52 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version
+
+ * If --enable-gnome was specified, then check that libgnomeui is
+ actually present.
+
+2003-06-12 16:38 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Doc
+
+2003-06-12 16:27 Martin Pool <mbp@samba.org>
+
+ * DEPENDENCIES: Describe dependencies for GNOME.
+
+2003-06-12 16:25 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Reindent only.
+
+2003-06-12 16:06 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Add a callback every 0.5s. At the moment it
+ does nothing.
+
+2003-06-12 15:56 Martin Pool <mbp@samba.org>
+
+ * TODO: More small updates.
+
+2003-06-12 15:51 Martin Pool <mbp@samba.org>
+
+ * TODO: Remove many done TODO items, and add notes on some
+ continuing ones.
+
+2003-06-12 15:40 Martin Pool <mbp@samba.org>
+
+ * src/clirpc.c: Doc
+
+2003-06-12 13:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: clirpc.c, remote.c, state.c: Remove infrequently-hit
+ states.
+
+2003-06-12 13:42 Martin Pool <mbp@samba.org>
+
+ * src/compile.c: Remove "Startup" state because it's very
+ unlikely to be hit.
+
+2003-06-12 12:53 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Prepare for 2.6 release.
+
+2003-06-12 12:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Get ready for 2.66 release.
+
+2003-06-12 12:04 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include doc/status-1.txt in distribution.
+
+2003-06-12 12:00 Martin Pool <mbp@samba.org>
+
+ * doc/status-1.txt: Update to describe the implemented monitor
+ design.
+
+2003-06-12 09:53 Martin Pool <mbp@samba.org>
+
+ * NEWS: Reorder items
+
+2003-06-12 09:30 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note changed tmpdir name.
+
+2003-06-12 00:34 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: Skip state files for which the process no longer
+ exists.
+
+2003-06-12 00:29 Martin Pool <mbp@samba.org>
+
+ * src/state.c: Call the blocked state "starved".
+
+2003-06-12 00:28 Martin Pool <mbp@samba.org>
+
+ * src/state.c: Call the blocked state "bored"
+
+2003-06-12 00:26 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: Doc.
+
+2003-06-12 00:17 Martin Pool <mbp@samba.org>
+
+ * src/clirpc.c: Doc.
+
+2003-06-12 00:15 Martin Pool <mbp@samba.org>
+
+ * src/clirpc.c: Add more states: distinguish more states: waiting
+ for preprocessor, sending source, and receiving object.
+
+2003-06-12 00:12 Martin Pool <mbp@samba.org>
+
+ * src/: state.h, state.c: Add more states.
+
+2003-06-12 00:09 Martin Pool <mbp@samba.org>
+
+ * src/mon-text.c: Clip columns to appropriate widths.
+
+2003-06-12 00:04 Martin Pool <mbp@samba.org>
+
+ * src/: compile.c: Note input filename as soon as it has been
+ determined.
+
+2003-06-12 00:03 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: compile.c, state.c, state.h: Show another state during
+ startup.
+
+2003-06-11 22:38 Martin Pool <mbp@samba.org>
+
+ * src/state.c: Doc
+
+2003-06-11 22:37 Martin Pool <mbp@samba.org>
+
+ * src/clirpc.c: dcc_retrieve_results: Try to keep the right file
+ name when updating state.
+
+2003-06-11 22:36 Martin Pool <mbp@samba.org>
+
+ * TODO: Thoughts on -MD support.
+
+2003-06-11 22:36 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-06-11 22:34 Martin Pool <mbp@samba.org>
+
+ * src/remote.c: Doc
+
+2003-06-11 22:31 Martin Pool <mbp@samba.org>
+
+ * src/remote.c: dcc_compile_remote: Try to keep the right file
+ name when updating state.
+
+2003-06-11 22:30 Martin Pool <mbp@samba.org>
+
+ * src/where.c: dcc_lock_pause: Set state notification when
+ blocked.
+
+2003-06-11 22:29 Martin Pool <mbp@samba.org>
+
+ * src/: state.c, state.h: dcc_note_state: constness
+
+2003-06-11 22:29 Martin Pool <mbp@samba.org>
+
+ * src/: filename.h, filename.c: dcc_find_basename: constness
+
+2003-06-11 22:26 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: state.c, state.h: Add STATE_BLOCKED.
+
+2003-06-11 22:21 Martin Pool <mbp@samba.org>
+
+ * src/state.h: Delete garbage comment.
+
+2003-06-11 17:22 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: Doc.
+
+2003-06-11 17:20 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove done todo
+
+2003-06-11 17:19 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: Measurements with state notes turned on.
+
+2003-06-11 17:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/remote.c: dcc_compile_remote: xmit_lock_fd is unused for
+ now.
+
+2003-06-11 17:14 Martin Pool <mbp@samba.org>
+
+ * src/remote.c: Doc.
+
+2003-06-11 17:07 Martin Pool <mbp@samba.org>
+
+ * src/mon-text.c: Doc.
+
+2003-06-11 17:02 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-06-11 16:59 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon.c: dcc_mon_poll: Fix memory scribble.
+
+2003-06-11 16:53 Martin Pool <mbp@samba.org>
+
+ * src/state.c: Doc.
+
+2003-06-11 16:46 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-06-11 16:29 Martin Pool <mbp@samba.org>
+
+ * src/state.c: Only unlink file before replacing on cygwin.
+
+2003-06-11 16:24 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon.c: Reduce max age to 30s.
+
+2003-06-11 15:06 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Include hostname in tempdir name, to avoid
+ problems when /tmp is shared.
+
+2003-06-11 15:03 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note distccmon-text.
+
+2003-06-11 15:00 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-text.c: Dump out the monitor list in a simple text
+ table form.
+
+2003-06-11 14:50 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon.c: Read host and file variabels from state.
+
+2003-06-11 14:22 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: rpc.c, rpc.h, srvrpc.c: dcc_r_token_string: New function
+ factored out.
+
+2003-06-11 14:06 Martin Pool <mbp@samba.org>
+
+ * src/exitcode.h: Add EXIT_GONE
+
+2003-06-11 12:41 Martin Pool <mbp@samba.org>
+
+ * src/mon-text.c: distccmon-gnome: Emit blank at end.
+
+2003-06-11 12:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: state.c, state.h: dcc_state_prefix: Export identifying
+ prefix for state files.
+
+2003-06-11 12:35 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: dcc_mon_do_file: New function. Skip everything but
+ state files.
+
+2003-06-11 12:31 Martin Pool <mbp@samba.org>
+
+ * src/mon.c: dcc_mon_poll: Partial implementation that just
+ traverses the directory.
+
+2003-06-11 12:30 Martin Pool <mbp@samba.org>
+
+ * src/mon-text.c: Set trace level from environment.
+
+2003-06-11 12:30 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * .cvsignore: Ignore distccmon-text binary.
+
+2003-06-11 12:24 Martin Pool <mbp@samba.org>
+
+ * src/trace.c: Default trace should get all messages allowed by
+ log level.
+
+2003-06-11 12:22 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Build and install distccmon-text
+
+2003-06-11 12:19 Martin Pool <mbp@samba.org>
+
+ * src/trace.c: Typo
+
+2003-06-11 12:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon.h: Declare part of the monitor API
+
+2003-06-11 12:13 Martin Pool <mbp@samba.org>
+
+ * src/mon-text.c: Hook in to trace code.
+
+2003-06-11 12:11 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: More routines are needed for monitors
+
+2003-06-11 12:06 Martin Pool <mbp@samba.org>
+
+ * src/mon-text.c: Hook in to trace code.
+
+ * Doc.
+
+2003-06-11 12:04 Martin Pool <mbp@samba.org>
+
+ * src/: exec.c, util.c: dcc_remove_if_exists: Move to util.c
+
+2003-06-11 12:04 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add mon_obj variable for building monitor
+ programs.
+
+2003-06-11 11:58 Martin Pool <mbp@samba.org>
+
+ * src/mon-text.c: src/mon-text.c: New file.
+
+2003-06-11 11:57 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include src/mon-gnome.c in distribution
+
+ * src/mon-text.c: New file.
+
+2003-06-11 11:51 Martin Pool <mbp@samba.org>
+
+ * src/state.c: dcc_note_state: Put client pid in state.
+
+2003-06-11 11:50 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, src/mon.c, src/mon.h: src/mon.c, src/mon.h: New
+ files.
+
+2003-06-11 11:48 Martin Pool <mbp@samba.org>
+
+ * src/: clirpc.c, remote.c: Add more calls to publish state.
+
+2003-06-11 11:43 Martin Pool <mbp@samba.org>
+
+ * src/state.c: dcc_note_state: Handle null file or host names.
+
+2003-06-11 11:39 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c, state.c, state.h: Call dcc_remove_state_file
+ from atexit in client.
+
+2003-06-11 11:37 Martin Pool <mbp@samba.org>
+
+ * src/state.c: dcc_remove_state_file: Implement.
+
+2003-06-11 11:35 Martin Pool <mbp@samba.org>
+
+ * src/state.c: dcc_open_state_file: Release memory after use.
+
+2003-06-11 11:32 Martin Pool <mbp@samba.org>
+
+ * src/: rpc.c, rpc.h: dcc_x_token_string: Make buffer const.
+
+2003-06-11 11:31 Martin Pool <mbp@samba.org>
+
+ * src/state.c: dcc_note_state: Include file and host too.
+
+2003-06-11 11:28 Martin Pool <mbp@samba.org>
+
+ * src/state.c: dcc_note_state: Include state string as well.
+
+2003-06-11 11:26 Martin Pool <mbp@samba.org>
+
+ * src/clirpc.c: dcc_x_argv: Call dcc_x_token_string rather than
+ doing it inline.
+
+2003-06-11 11:22 Martin Pool <mbp@samba.org>
+
+ * src/: rpc.h, rpc.c: dcc_x_token_string: New function factored
+ out.
+
+2003-06-11 11:06 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Subst in LINUXDOC.
+
+2003-06-11 11:02 Martin Pool <mbp@samba.org>
+
+ * configure.ac: AC_ARG_VAR LINUXDOC
+
+2003-06-11 11:00 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Add a check for existence of linuxdoc.
+
+2003-06-11 10:47 Martin Pool <mbp@samba.org>
+
+ * src/snprintf.h: snprintf.h needs to include stdarg.h to get
+ va_list. Possibly fixes IRIX.
+
+2003-06-10 18:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exec.c: Doc.
+
+2003-06-10 18:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-06-10 18:00 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note new state files.
+
+2003-06-10 17:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/stat.h: dcc_remove_state_file: New function.
+
+2003-06-10 17:56 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/compile.c: Update state directory when compiling locally.
+
+2003-06-10 17:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: stat.c, stat.h: dcc_note_state only logs the basename of
+ the file.
+
+2003-06-10 17:39 Martin Pool <mbp@samba.org>
+
+ * src/stat.c: dcc_note_state: Trim filename down to basename.
+
+2003-06-10 17:37 Martin Pool <mbp@samba.org>
+
+ * NEWS: Try to fix UTF-8 coding, which seemed to be mangled by
+ CVS.
+
+2003-06-10 17:31 Martin Pool <mbp@samba.org>
+
+ * NEWS: In compilation log message, just show the basename of the
+ file to make it more compact.
+
+2003-06-10 17:23 Martin Pool <mbp@samba.org>
+
+ * src/: stat.h, stat.c: Add compile state constants.
+
+2003-06-10 17:16 Martin Pool <mbp@samba.org>
+
+ * src/: filename.h, filename.c: dcc_find_basename: New function.
+
+2003-06-10 16:57 Martin Pool <mbp@samba.org>
+
+ * src/compile.c: Remove unneeded header.
+
+2003-06-10 16:55 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: bulk.c, distcc.h: Move O_BINARY ifdef to distcc.h
+
+2003-06-10 15:56 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: New file stat.h
+
+2003-06-10 15:55 Martin Pool <mbp@samba.org>
+
+ * src/: stat.c, stat.h: New file stat.h
+
+ * Add routine to open a state file.
+
+2003-06-10 15:55 Martin Pool <mbp@samba.org>
+
+ * .cvsignore: Ignore distccmon-gnome.
+
+2003-06-10 15:49 Martin Pool <mbp@samba.org>
+
+ * src/stat.c: Doc
+
+ * Add function to create/return state directory.
+
+2003-06-10 15:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/mon-gnome.c: Set a more reasonable default size.
+
+2003-06-10 15:09 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Start adding a GNOME-based monitor.
+
+2003-06-10 14:58 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: make clean: Remove distccmon-gnome, even if it's
+ currently not configured on.
+
+2003-06-10 14:57 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, configure.ac: Add --enable-gnome configure option.
+ When set, build and install distccmon-gnome.
+
+2003-06-09 23:09 Martin Pool <mbp@samba.org>
+
+ * src/mon-gnome.c: Add more sample data.
+
+2003-06-09 23:07 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add hardcoded rule for distccmon-gnome.
+
+2003-06-09 23:05 Martin Pool <mbp@samba.org>
+
+ * doc/status-1.txt: Update status indicator notes.
+
+2003-06-09 23:03 Martin Pool <mbp@samba.org>
+
+ * src/stat.c: Stub for status indicator.
+
+2003-06-09 19:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: mon-gnome.c, mon-gtk.c: Stub implementation of GNOME
+ monitor.
+
+2003-06-09 18:35 Martin Pool <mbp@samba.org>
+
+ * src/: netutil.c, netutil.h: Add implementation of hstrerror()
+ for systems that don't have it.
+
+2003-06-09 18:28 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: src/stat.c: New file.
+
+2003-06-09 15:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Note that hstrerror() is now supplied.
+
+2003-06-09 12:47 Martin Pool <mbp@samba.org>
+
+ * src/remote.c: Remove more unneeded headers.
+
+2003-06-09 12:43 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c, compile.c: Remove more unneeded headers.
+
+2003-06-09 12:36 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Remove more unneeded headers.
+
+2003-06-09 12:33 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Remove unneeded headers.
+
+2003-06-08 20:05 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py, NEWS: Fix silly typo that made
+ maintainer-check fail in ParseHostSpec_Case.
+
+2003-06-08 19:52 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: Multiple updates to TODO file.
+
+2003-06-08 19:19 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: OpenMOSIX autodiscovery
+
+2003-06-05 17:44 Martin Pool <mbp@samba.org>
+
+ * TODO: Rearrange comments on DNS A and SRV records.
+
+ * Move question about --enable-final to web.
+
+2003-06-05 17:34 Martin Pool <mbp@samba.org>
+
+ * TODO: 2.5 bug is fixed.
+
+2003-06-05 17:26 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include doc/protocol-1.txt in distribution.
+
+2003-06-05 17:21 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version back to 2.6cvs
+
+2003-06-05 17:03 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note connection timeout added in 2.5.1.
+
+2003-06-05 16:53 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Prepare for 2.5.1 release.
+
+2003-06-05 16:48 Martin Pool <mbp@samba.org>
+
+ * src/io.c, NEWS: sys/time.h might be needed for select on SuSE
+ 7.1 (spe158).
+
+2003-06-05 16:45 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Get out these fixes in 2.5.1.
+
+2003-06-05 16:42 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py, NEWS: Add check for support of old
+ multiplier format. (angry/44:300)
+
+2003-06-05 16:41 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc
+
+2003-06-05 16:39 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Get out these fixes in 2.5.1.
+
+2003-06-05 16:36 Martin Pool <mbp@samba.org>
+
+ * NEWS: Get out these fixes in 2.5.1.
+
+2003-06-05 16:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Fix IRIX.
+
+2003-06-05 16:09 Martin Pool <mbp@samba.org>
+
+ * NEWS: Recode as UTF-8.
+
+2003-06-05 16:08 Martin Pool <mbp@samba.org>
+
+ * NEWS: Solaris fixes from Tomas.
+
+2003-06-05 16:08 Martin Pool <mbp@samba.org>
+
+ * src/daemon.h: dcc_master_pid is really a pid_t.
+
+2003-06-05 16:07 Martin Pool <mbp@samba.org>
+
+ * src/netutil.c: Can't use "sun" as an identifier on gcc Solaris
+ 8.
+
+2003-06-05 16:03 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-06-04 23:19 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Doc.
+
+2003-06-04 11:22 Martin Pool <mbp@samba.org>
+
+ * doc/status-1.txt: Notes on design possibilities.
+
+2003-06-03 08:37 Martin Pool <mbp@samba.org>
+
+ * doc/noent.txt: Transient bug while compiling.
+
+2003-06-03 08:23 Martin Pool <mbp@samba.org>
+
+ * doc/status-1.txt: Notes on status reporting
+
+2003-06-02 15:48 Martin Pool <mbp@samba.org>
+
+ * src/netutil.c: This file needs snprintf.h
+
+ * AF_LOCAL might be missing on Solaris.
+
+2003-06-02 15:45 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-06-02 14:46 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-06-02 13:20 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * survey.txt: Clarify privacy clause for survey.
+
+2003-06-02 13:11 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-05-31 00:29 Martin Pool <mbp@samba.org>
+
+ * doc/protocol-1.txt: Start handling empty output files.
+
+2003-05-31 00:29 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-05-30 23:49 Martin Pool <mbp@samba.org>
+
+ * src/: bulk.c, distcc.h: dcc_open_read can be static.
+
+2003-05-30 23:47 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Remove dead code.
+
+2003-05-30 12:58 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add section about Mailing lists.
+
+2003-05-30 12:45 Martin Pool <mbp@samba.org>
+
+ * src/dsignal.c: Doc.
+
+2003-05-29 09:00 Martin Pool <mbp@samba.org>
+
+ * src/access.c: Doc
+
+2003-05-28 17:34 Martin Pool <mbp@samba.org>
+
+ * src/: clinet.c, io.c: Increase timeout to 15s.
+
+ * Move select() check into dcc_select_for_read
+
+2003-05-28 17:28 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: dcc_connect_timed: Add trace.
+
+2003-05-28 17:16 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Doc
+
+2003-05-28 17:13 Martin Pool <mbp@samba.org>
+
+ * TODO, doc/results.txt: [no log message]
+
+2003-05-28 17:01 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-05-28 16:11 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Include hostdef string in "failed to distribute"
+ warning.
+
+2003-05-28 16:03 Martin Pool <mbp@samba.org>
+
+ * src/: netutil.h, ssh.c, netutil.c: dcc_set_nonblocking,
+ dcc_set_blocking: Move to netutil.h
+
+2003-05-28 15:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/serve.c: dcc_run_job: Split some code out into
+ dcc_input_tmpnam.
+
+2003-05-28 15:50 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: [no log message]
+
+2003-05-28 15:46 Martin Pool <mbp@samba.org>
+
+ * TODO: Preforking is now done.
+
+2003-05-28 15:45 Martin Pool <mbp@samba.org>
+
+ * TODO: Thoughts on boredom and temporary file extensions.
+
+2003-05-28 15:29 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml, NEWS: Document use from inetd.
+
+ * Document -j option.
+
+2003-05-28 15:08 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Notes on running daemon from init and
+ standalone.
+
+2003-05-28 14:51 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Bump version
+
+2003-05-28 14:13 Martin Pool <mbp@samba.org>
+
+ * NEWS: Need types.h
+
+2003-05-28 14:03 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Need types.h
+
+2003-05-27 19:18 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Tweak trace message.
+
+2003-05-27 19:17 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Disable dcc_x_file_timed, which is no longer
+ called.
+
+2003-05-27 19:12 Martin Pool <mbp@samba.org>
+
+ * configure.ac, NEWS, doc/release-names.txt: Prepare for 2.5
+ release.
+
+2003-05-27 19:11 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Doc.
+
+ * If getpeername() fails on a socket then continue anyhow.
+
+2003-05-27 19:08 Martin Pool <mbp@samba.org>
+
+ * TODO: SSH child is now collected by the client.
+
+2003-05-27 18:55 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-05-27 18:54 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Only collect SSH child if we actually started
+ one. (How embarrassing.)
+
+2003-05-27 18:48 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Log elapsed time for whole compilation.
+
+2003-05-27 18:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-05-27 18:35 Martin Pool <mbp@samba.org>
+
+ * TODO: Note on handling SIGCHLD from cpp.
+
+2003-05-27 18:17 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c: Doc.
+
+2003-05-27 18:16 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Add pointer to manual in usage message.
+
+2003-05-27 17:54 Martin Pool <mbp@samba.org>
+
+ * src/netutil.c: dcc_sockaddr_to_string: Remove "INET" from IP
+ address.
+
+2003-05-27 17:54 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: dcc_connect_by_addr: Print sockaddr in raw form.
+
+2003-05-27 15:11 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: ParseMask_Case: Better error message.
+
+2003-05-27 14:58 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: Notes on prefork mode.
+
+2003-05-27 14:43 Martin Pool <mbp@samba.org>
+
+ * src/daemon.h: Fix decl.
+
+2003-05-27 14:42 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Fix C syntax.
+
+2003-05-27 14:41 Martin Pool <mbp@samba.org>
+
+ * TODO: Update notes on fsh/ssh.
+
+2003-05-27 12:26 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Tweak log messages.
+
+2003-05-27 11:44 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Recommend using log files.
+
+2003-05-27 11:41 Martin Pool <mbp@samba.org>
+
+ * src/prefork.c: dcc_preforked_child can be static.
+
+2003-05-27 11:07 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: dcc_critique_status: Tweak log output.
+
+2003-05-27 11:05 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: dcc_critique_status: Better message for termination
+ by signal.
+
+2003-05-27 11:00 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Show lock fd in trace messages.
+
+2003-05-27 10:59 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: dcc_sockaddr_to_ip now indicates which AF it is.
+
+2003-05-27 10:58 Martin Pool <mbp@samba.org>
+
+ * src/netutil.c: Better description of AF_UNIX sockets.
+
+2003-05-27 10:54 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: netutil.c, netutil.h, srvnet.c: dcc_sockaddr_to_ip:
+ Rename to dcc_sockaddr_to_string.
+
+2003-05-27 10:46 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Doc
+
+2003-05-27 10:43 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Tweak trace message.
+
+2003-05-27 10:42 Martin Pool <mbp@samba.org>
+
+ * src/sendfile.c: Doc.
+
+2003-05-27 10:28 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c, where.c: Disable XMIT locks for the moment.
+
+2003-05-26 18:43 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: More testing.
+
+2003-05-26 18:39 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: More testing.
+
+2003-05-26 18:09 Martin Pool <mbp@samba.org>
+
+ * NEWS: Client no longer considers NCPUs.
+
+2003-05-26 18:08 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Tweak trace message.
+
+2003-05-26 17:53 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-05-26 17:45 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Fix warning.
+
+2003-05-26 17:44 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/srvnet.c, src/dparent.c, NEWS: Log full passive sockaddr in
+ listen message.
+
+2003-05-26 17:36 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Shuffle startup messages.
+
+2003-05-26 17:34 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/serve.c: dcc_service_job: Split off code for checking
+ access control.
+
+2003-05-26 17:13 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: dcc_listen_by_addr: Show sockaddr if bind fails.
+
+2003-05-26 16:58 Martin Pool <mbp@samba.org>
+
+ * src/netutil.c: dcc_sockaddr_to_ip: sin_port is in network byte
+ order.
+
+2003-05-26 16:57 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: Fix silly typo.
+
+2003-05-26 16:56 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: dcc_listen_by_addr: Show sockaddr if bind fails.
+
+2003-05-26 16:53 Martin Pool <mbp@samba.org>
+
+ * src/netutil.c: dcc_sockaddr_to_ip: Show port number as well as
+ IP address.
+
+2003-05-26 16:46 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: Split out "address family" part from "connection
+ from" message.
+
+2003-05-26 16:35 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Fix syntax problem and missing header.
+
+2003-05-26 16:34 Martin Pool <mbp@samba.org>
+
+ * NEWS: Move daemon into temporary directory during startup.
+
+2003-05-26 16:33 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Doc.
+
+2003-05-26 16:32 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: main: Refactor error handling.
+
+ * Move daemon into temporary directory during startup.
+
+2003-05-26 16:29 Martin Pool <mbp@samba.org>
+
+ * src/: tempfile.c, tempfile.h: dcc_enter_tempdir: New function.
+
+2003-05-26 16:27 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c, NEWS: Just use decimal userid rather than
+ username in temporary directory.
+
+2003-05-26 16:22 Martin Pool <mbp@samba.org>
+
+ * src/setuid.c: Undo 1.3
+
+2003-05-26 16:21 Martin Pool <mbp@samba.org>
+
+ * src/setuid.c: Move opt_user to somewhere it can be reached by
+ tmpfile.
+
+2003-05-26 16:19 Martin Pool <mbp@samba.org>
+
+ * NEWS: Use username or decimal userid for temporary directory
+ name.
+
+2003-05-26 15:55 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2003-05-26 15:54 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Fix naming of stdout, stderr temporary files.
+
+ * Call server object file .o.
+
+2003-05-26 15:51 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/trace.c: rs_remove_logger: New function to allow turning
+ off loggers without shutting everything down.
+
+2003-05-26 15:42 Martin Pool <mbp@samba.org>
+
+ * src/trace.h: rs_remove_logger: New function.
+
+2003-05-26 15:38 Martin Pool <mbp@samba.org>
+
+ * src/prefork.c: Message when child exits.
+
+2003-05-26 15:13 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add tests for new host multiplicity
+ specifications.
+
+2003-05-26 15:12 Martin Pool <mbp@samba.org>
+
+ * src/dsignal.c: Remove unneeded headers.
+
+2003-05-26 15:07 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/h_hosts.c: Log to stderr.
+
+2003-05-26 14:54 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: dcc_parse_multiplier: Remove unnecessary string
+ copy.
+
+2003-05-26 14:51 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Doc.
+
+2003-05-26 14:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Run tests in prefork mode.
+
+2003-05-26 14:46 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Call server-side output object files .o, not .out. Patch
+ from rishikesh shetty.
+
+2003-05-26 14:28 Martin Pool <mbp@samba.org>
+
+ * src/prefork.c: Doc.
+
+2003-05-26 14:24 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Assume localhost has one CPU when checking
+ host parsing.
+
+2003-05-26 14:20 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/tempfile.c: Fix warning
+
+2003-05-26 13:14 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: tmpfile list must be volatile.
+
+2003-05-26 13:10 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: dcc_standalone_server: Even in --no-detach mode,
+ create a new process group.
+
+2003-05-26 13:09 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exec.c: Doc.
+
+2003-05-26 12:15 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: h_hosts now needs ncpus.c
+
+2003-05-26 12:08 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note prefork support.
+
+2003-05-26 12:06 Martin Pool <mbp@samba.org>
+
+ * src/: srvrpc.c, serve.c: Split server-specific RPC code into
+ its own file.
+
+2003-05-26 12:05 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, src/rpc.h: src/srvrpc.c: New file.
+
+2003-05-26 12:00 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Doc.
+
+2003-05-26 11:53 Martin Pool <mbp@samba.org>
+
+ * NEWS: Kill process group on termination signal.
+
+2003-05-26 11:50 Martin Pool <mbp@samba.org>
+
+ * src/: prefork.c, dparent.c: "up to n children" is only a debug
+ message.
+
+2003-05-26 11:49 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/daemon.c: Doc
+
+2003-05-26 11:44 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/prefork.c: Doc
+
+2003-05-25 17:29 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Bump version to 2.5.
+
+ * Add descriptions of some new error codes.
+
+2003-05-23 19:19 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Doc
+
+2003-05-23 19:15 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c, NEWS: Make sure that the right syslog facility is
+ opened.
+
+2003-05-23 19:04 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: No more recursive Make.
+
+2003-05-23 18:33 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Bump version to 2.5cvs
+
+2003-05-23 15:48 Martin Pool <mbp@samba.org>
+
+ * README.libiberty: Remove libiberty stuff
+
+2003-05-23 14:54 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Remove quote.
+
+2003-05-23 14:51 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/dparent.c: Rename /_loop/_parent/
+
+2003-05-23 14:29 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: max_kids: New variable to impose a limit on
+ concurrent servers.
+
+2003-05-23 14:21 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Fix prototype
+
+2003-05-23 14:20 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/hosts.c: Doc
+
+2003-05-23 14:04 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Set default local task limit to twice the number
+ of CPUs.
+
+2003-05-23 13:38 Martin Pool <mbp@samba.org>
+
+ * TODO: Remove done items.
+
+2003-05-23 13:02 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Prepare for 2.4.2 release
+
+2003-05-23 12:58 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2003-05-23 12:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/results.txt: [no log message]
+
+2003-05-22 19:05 Martin Pool <mbp@samba.org>
+
+ * TODO: More notes on feeding from a FIFO.
+
+2003-05-22 17:39 Martin Pool <mbp@samba.org>
+
+ * src/sendfile.c: Doc.
+
+2003-05-22 16:40 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: libiberty is no longer used by distcc.
+
+2003-05-22 16:24 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * cases/fooey.c: Another developer scratch test.
+
+2003-05-22 16:09 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Fix /dev/null test.
+
+2003-05-22 15:51 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add test case for "-o /dev/null", reported
+ by Hal Duston. Currently fails.
+
+2003-05-22 15:48 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Update to 2.5cvs
+
+2003-05-22 15:24 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Update to 2.4.1
+
+2003-05-22 15:21 Martin Pool <mbp@samba.org>
+
+ * NEWS: Patch from Frerich Raabe:
+
+ * Add strndup on platforms that don't have it.
+
+2003-05-22 11:25 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c, NEWS: Patch from Frerich Raabe:
+
+ * Add strndup on platforms that don't have it.
+
+2003-05-22 11:13 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version to 2.4.1cvs
+
+ * Check for function and declaration of strndup.
+
+2003-05-22 10:03 Martin Pool <mbp@samba.org>
+
+ * man/: distcc.1, distccd.1: Add email addresses.
+
+2003-05-21 16:57 Martin Pool <mbp@samba.org>
+
+ * TODO: Note on waking up bored clients.
+
+2003-05-21 16:47 Martin Pool <mbp@samba.org>
+
+ * configure.ac, NEWS: Get ready for 2.4 release
+
+2003-05-21 16:45 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: NoHosts_Case needs to reset
+ DISTCC_FALLBACK=1 to test the desired behaviour.
+
+2003-05-21 16:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/results.txt: Notes on backoff.
+
+2003-05-21 16:30 Martin Pool <mbp@samba.org>
+
+ * src/timefile.c: dcc_remove_timefile: Better messages.
+
+2003-05-21 16:26 Martin Pool <mbp@samba.org>
+
+ * src/h_hosts.c: Renamed to dcc_get_hostlist
+
+2003-05-21 16:25 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-05-21 16:24 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Doc.
+
+2003-05-21 16:16 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exitcode.h: New code EXIT_NO_HOSTS
+
+2003-05-21 16:07 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/where.c: If removing disliked hosts leaves us with nothing,
+ then use localhost instead.
+
+2003-05-21 15:55 Martin Pool <mbp@samba.org>
+
+ * src/backoff.c: Doc
+
+2003-05-21 15:55 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: [no log message]
+
+2003-05-21 15:54 Martin Pool <mbp@samba.org>
+
+ * src/: backoff.c, backoff.h, hosts.c, where.c: Backoff from
+ disliked hosts for 60 seconds.
+
+2003-05-21 15:53 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note sleep changes and backoff.
+
+2003-05-21 15:38 Martin Pool <mbp@samba.org>
+
+ * src/: hosts.h, hosts.c: dcc_free_hostdef: New function.
+
+2003-05-21 15:25 Martin Pool <mbp@samba.org>
+
+ * src/: hosts.h, hosts.c, where.c: Rename dcc_preferred_hosts to
+ dcc_get_hostlist.
+
+2003-05-21 15:23 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Sleep for just 2s if a host is not free.
+
+2003-05-21 14:09 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/lock.c: Doc.
+
+2003-05-21 14:00 Martin Pool <mbp@samba.org>
+
+ * src/timefile.c: dcc_mark_timefile: Fix error check
+
+2003-05-21 13:57 Martin Pool <mbp@samba.org>
+
+ * src/: backoff.c, distcc.c: backoff.c, backoff.h: New files.
+
+2003-05-21 13:56 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: dcc_build_somewhere: Remember when a server
+ failed or not.
+
+2003-05-21 13:55 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: backoff.c, backoff.h: New files.
+
+2003-05-21 13:44 Martin Pool <mbp@samba.org>
+
+ * src/timefile.c: dcc_remove_timefile, dcc_check_timefile: Cope
+ with timestamp files that don't exist.
+
+2003-05-21 13:35 Martin Pool <mbp@samba.org>
+
+ * src/timefile.c: dcc_mark_timefile, dcc_remove_timefile: add
+ trace messages.
+
+2003-05-21 13:34 Martin Pool <mbp@samba.org>
+
+ * src/: timefile.c, timefile.h: dcc_remove_timefile,
+ dcc_check_timefile: New functions.
+
+2003-05-21 13:30 Martin Pool <mbp@samba.org>
+
+ * src/timefile.h, Makefile.in, src/lock.h: timefile.h: New header
+ for timefile.c
+
+2003-05-21 13:22 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-05-21 13:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/climasq.c: Doc
+
+2003-05-21 13:14 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc.
+
+2003-05-21 11:49 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-05-20 22:35 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-05-20 12:00 Martin Pool <mbp@samba.org>
+
+ * survey.txt: Add request to send misconfigurations to the list
+ rather than to the survey.
+
+2003-05-19 18:21 Martin Pool <mbp@samba.org>
+
+ * TODO: Describe use of SSH.
+
+ * Notes about localhost scheduling.
+
+2003-05-19 18:17 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Bump version.
+
+2003-05-19 18:16 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml, NEWS: Describe use of SSH.
+
+2003-05-19 18:02 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: Results from SSH.
+
+2003-05-19 17:50 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: dcc_lock_host: Use hostdef_string, not hostname.
+
+2003-05-19 17:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exec.c: dcc_critique_status: Don't print function name in
+ errors.
+
+2003-05-19 17:39 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/hosts.h: Add verbatim name to hostdef struct.
+
+2003-05-19 17:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * cases/bad.c: Test case for errors.
+
+2003-05-19 17:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2003-05-19 16:58 Martin Pool <mbp@samba.org>
+
+ * src/: filename.c: Doc.
+
+2003-05-19 16:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/results.txt: Notes on getaddrinfo vs gethostinfo.
+
+2003-05-19 16:08 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Add --enable-rfc2553 configuration option.
+
+2003-05-19 16:08 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes on name handling and statistics.
+
+2003-05-19 16:07 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/filename.c: Doc.
+
+2003-05-16 17:43 Martin Pool <mbp@samba.org>
+
+ * src/cpp.c: dcc_cpp_maybe: Doc, add trace.
+
+2003-05-16 17:40 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Fix upload-dist.
+
+2003-05-16 17:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/results.txt: Update from experiments today on kernel.
+
+2003-05-16 17:16 Martin Pool <mbp@samba.org>
+
+ * NEWS: Bump to 2.4cvs.
+
+ * Merge patch to recognize Objective C files, by Dara Hazeghi.
+
+2003-05-16 17:14 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump to 2.4cvs.
+
+2003-05-16 17:10 Martin Pool <mbp@samba.org>
+
+ * cases/hello-objc.m: Add compile-command.
+
+2003-05-16 17:09 Martin Pool <mbp@samba.org>
+
+ * cases/hello-objc.m: Example case for Objective C, from Dara
+ Hazeghi.
+
+2003-05-16 15:15 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Fix typo in usage message.
+
+2003-05-16 15:07 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-05-16 14:46 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Prepare for 2.3 release.
+
+2003-05-16 14:09 Martin Pool <mbp@samba.org>
+
+ * NEWS: Prepare for 2.3 release.
+
+2003-05-16 13:43 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Prepare for 2.3 release.
+
+2003-05-15 15:14 Martin Pool <mbp@samba.org>
+
+ * src/util.c: Update trace message.
+
+2003-05-14 10:47 Martin Pool <mbp@samba.org>
+
+ * src/util.c: dcc_trim_path: More trace information.
+
+2003-05-13 15:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Doc updates.
+
+2003-05-13 11:46 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-05-11 12:31 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Update status of IPv6.
+
+2003-05-11 12:17 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: Coallesce log entries.
+
+ * Doc.
+
+2003-05-11 12:04 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-05-09 14:05 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Remove chapter on "internals", because
+ this is covered in the protocol documentation file, etc.
+
+2003-05-08 18:02 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Document DISTCC_SSH, host list files, and
+ execution over SSH.
+
+2003-05-08 17:17 Martin Pool <mbp@samba.org>
+
+ * NEWS: Updates to manual.
+
+2003-05-08 17:13 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Better description of how --help and
+ --version work with the client.
+
+ * Document DISTCC_FALLBACK.
+
+2003-05-08 17:05 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Update section about security to describe
+ ssh and new options.
+
+2003-05-08 16:52 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: Restore access control checking for IPv4
+ connections.
+
+2003-05-08 16:51 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: AccessDenied_Case depends on falling back
+ to local compilation.
+
+2003-05-08 16:44 Martin Pool <mbp@samba.org>
+
+ * src/h_hosts.c: dcc_parse_hosts_env renamed to
+ dcc_preferred_hosts.
+
+2003-05-08 16:43 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: non-GETADDRINFO version of dcc_connect_by_name:
+ Pass the right socklen.
+
+2003-05-08 16:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/clinet.c: Remove unused vars.
+
+2003-05-07 17:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/srvnet.c: dcc_check_client: Update to be AF-indepedent.
+ Does not do checks yet.
+
+2003-05-07 16:58 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Check for inet_ntop and inet_ntoa
+
+2003-05-07 16:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/clinet.c: Doc.
+
+2003-05-07 15:57 Martin Pool <mbp@samba.org>
+
+ * doc/dietlibc-distcc.trace: strace using dietlibc, just for
+ interest.
+
+2003-05-07 15:56 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Check for getaddrinfo, getnameinfo, and struct
+ sockaddr_storage.
+
+2003-05-07 15:20 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: hostlist.c fix
+
+ * snprintf.c fixes.
+
+2003-05-07 12:21 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Add check from Samba for va_copy, which is needed
+ for building our snprintf.
+
+2003-05-07 12:21 Martin Pool <mbp@samba.org>
+
+ * cases/.cvsignore: Ignore built programs.
+
+2003-05-07 12:20 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-05-07 12:07 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/hosts.c: dcc_parse_hosts_env: Remove obsolete function.
+
+2003-05-07 11:52 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Trace messages when reading in host lists.
+
+2003-05-07 11:50 Martin Pool <mbp@samba.org>
+
+ * src/hostfile.c: Remove unnecessary recursion protection.
+
+ * Trace message when reading a file.
+
+2003-05-07 11:49 Martin Pool <mbp@samba.org>
+
+ * src/loadfile.c: Fix silly pointer error when loading a host
+ file.
+
+2003-05-07 11:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * README.packaging: Note about using ./configure options to set
+ directories, and DESTDIR.
+
+2003-05-07 10:23 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: "for 2.2"
+
+2003-05-07 10:23 Martin Pool <mbp@samba.org>
+
+ * NEWS, linuxdoc/distcc.sgml: Document --listen, plus other
+ cleanups. Patch from Frerich Raabe.
+
+2003-05-07 10:13 Martin Pool <mbp@samba.org>
+
+ * cases/lzotest.c: Hacky test to examine efficiency of minilzo.
+
+2003-05-06 18:21 Martin Pool <mbp@samba.org>
+
+ * TODO: Merge some stuff.
+
+2003-05-06 18:18 Martin Pool <mbp@samba.org>
+
+ * doc/scheduling.txt: Merge into TODO
+
+2003-05-06 18:16 Martin Pool <mbp@samba.org>
+
+ * doc/new-scheduler.txt: Merged into doc/results.txt
+
+2003-05-06 18:16 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: Move "new-scheduler.txt" results (from
+ February) into the results.txt file.
+
+2003-05-06 17:36 Martin Pool <mbp@samba.org>
+
+ * doc/protocol-3.txt: Only a draft
+
+2003-05-06 17:34 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/protocol-3.txt: Describe input and output files.
+
+ * Start updating request and response descriptions.
+
+2003-05-06 16:54 Martin Pool <mbp@samba.org>
+
+ * doc/protocol-3.txt: Describe handshaking on reused connections.
+
+ * Describe compression.
+
+2003-05-06 16:02 Martin Pool <mbp@samba.org>
+
+ * doc/protocol-3.txt: More updates towards version 3 protocol.
+
+2003-05-06 14:55 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-05-06 13:12 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/trace.h: Doc
+
+2003-05-05 22:31 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/rpc.c: Fix printf formatting error.
+
+2003-05-05 18:46 Martin Pool <mbp@samba.org>
+
+ * src/trace.h: Doc
+
+2003-05-05 18:40 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: Doc
+
+2003-05-05 18:07 Martin Pool <mbp@samba.org>
+
+ * TODO: Remove page marks
+
+2003-05-05 18:01 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes on feeding from fifo.
+
+2003-05-05 17:56 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes on streaming output
+
+2003-05-05 17:49 Martin Pool <mbp@samba.org>
+
+ * doc/protocol-3.txt: Start writing notes about a version 3
+ protocol.
+
+2003-05-05 17:44 Martin Pool <mbp@samba.org>
+
+ * NEWS: Better description of network error detection.
+
+2003-05-05 17:36 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/clirpc.c: Doc.
+
+2003-05-05 16:54 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Bump version.
+
+2003-05-05 16:28 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Prepare for 2.2 release.
+
+2003-05-05 16:27 Martin Pool <mbp@samba.org>
+
+ * src/hosts.h: Remove CVS tag.
+
+2003-05-05 16:23 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-05-05 16:21 Martin Pool <mbp@samba.org>
+
+ * TODO: Add a basic --listen option, based on a patch by Neil
+ Mansilla.
+
+2003-05-05 16:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * patches/andresen-gcc-wrapper-r2.tbz2: Remove Gentoo-only patch.
+
+2003-05-05 15:54 Martin Pool <mbp@samba.org>
+
+ * TODO: Update TODO list.
+
+2003-05-05 15:30 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py, NEWS: Test host file support.
+
+2003-05-05 15:15 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note about support for host files.
+
+2003-05-05 15:14 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: h_hosts: Now needs hostfile.o and io.o
+
+2003-05-05 15:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/hostfile.c: Doc
+
+2003-05-05 15:01 Martin Pool <mbp@samba.org>
+
+ * cases/empty.s: Empty assembler file for testing.
+
+2003-05-05 15:01 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: SYSCONFDIR must be quoted for C.
+
+2003-05-05 14:37 Martin Pool <mbp@samba.org>
+
+ * src/: hosts.c, hosts.h, util.c, util.h: (dcc_dup_part): Move to
+ util.c.
+
+2003-05-05 14:35 Martin Pool <mbp@samba.org>
+
+ * TODO: Build .debs or .rpms?
+
+2003-05-05 14:24 Martin Pool <mbp@samba.org>
+
+ * TODO: Build .debs or .rpms?
+
+2003-05-05 14:19 Martin Pool <mbp@samba.org>
+
+ * src/hostfile.c: (dcc_parse_hosts_file): New function.
+
+2003-05-05 12:59 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: (SRC): Sort.
+
+2003-05-05 12:53 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * patches/hosts-from-file-raabe.diff: Old patch from Frerich to
+ read hosts from a file.
+
+2003-05-04 22:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: More spacing in output.
+
+2003-05-04 22:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Bump version to 2.2cvs
+
+2003-05-04 22:29 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes about compression and reading hosts from a file.
+
+2003-05-04 21:38 Martin Pool <mbp@samba.org>
+
+ * doc/protocol-1.txt: Suggestions from Brad Hards:
+
+ * Correction about SOUT.
+
+ * Explain a bit more about waitstatus.
+
+2003-05-04 17:24 Martin Pool <mbp@samba.org>
+
+ * NEWS, linuxdoc/distcc.sgml: Add documentation for --allow and
+ --user, by Frerich Raabe.
+
+2003-05-04 12:01 Martin Pool <mbp@samba.org>
+
+ * TODO: Update todo list.
+
+2003-05-04 11:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, configure.ac: Prepare for 2.1 release.
+
+2003-05-03 17:56 Martin Pool <mbp@samba.org>
+
+ * doc/protocol-1.txt: Ask for questions.
+
+ * Describe all the packets in the request and the response.
+
+2003-05-03 13:39 Martin Pool <mbp@samba.org>
+
+ * TODO: Note about preprocessing remotely.
+
+2003-05-03 12:05 Martin Pool <mbp@samba.org>
+
+ * TODO: Note about never running locally.
+
+2003-04-30 12:17 Martin Pool <mbp@samba.org>
+
+ * TODO: Link to API for async name lookups.
+
+2003-04-27 00:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-04-14 13:05 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-04-14 13:02 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-04-13 19:00 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes from UML.
+
+2003-04-13 17:35 Martin Pool <mbp@samba.org>
+
+ * TODO: Note about setting listen address.
+
+2003-04-13 17:18 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes about DISTCC_HOSTS syntax.
+
+2003-04-10 16:42 Martin Pool <mbp@samba.org>
+
+ * src/help.c: Add quote.
+
+2003-04-08 16:23 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-04-08 13:58 Martin Pool <mbp@samba.org>
+
+ * patches/n_cpus.txt: n_cpus.txt Remove merged code
+
+2003-04-04 17:39 Martin Pool <mbp@samba.org>
+
+ * patches/: distcc-path.patch, distccd-path.patch:
+ distcc-path.patch distccd-path.patch Delete merged patches
+
+2003-04-04 17:38 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-04-04 17:32 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-04-04 17:28 Martin Pool <mbp@samba.org>
+
+ * src/io.c: tcp_cork_sock: Don't complain about ENOTSUPP when
+ uncorking.
+
+2003-04-04 17:24 Martin Pool <mbp@samba.org>
+
+ * src/: rpc.c, io.h: dcc_read_int: Remove dead function.
+
+2003-04-04 17:20 Martin Pool <mbp@samba.org>
+
+ * src/: io.c: Doc.
+
+2003-04-04 17:19 Martin Pool <mbp@samba.org>
+
+ * src/io.c: dcc_pump_readwrite: Increase transfer buffer to
+ 256kB, and move it off the stack.
+
+2003-04-04 17:16 Martin Pool <mbp@samba.org>
+
+ * src/io.c: dcc_pump_readwrite: Doc.
+
+2003-04-04 17:12 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Note about nonblocking support.
+
+2003-04-04 16:59 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Patch from Wayne Davison to document
+ DISTCCD_PATH.
+
+2003-04-04 15:51 Martin Pool <mbp@samba.org>
+
+ * cases/hello.m: Example ObjC program from Dara Hazeghi
+
+2003-04-04 12:19 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-04-04 12:06 Martin Pool <mbp@samba.org>
+
+ * src/util.c: dcc_abspath: Memory overflow ought to be fatal.
+
+2003-04-04 12:00 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/daemon.c: Factor out code for checking whether to be inetd.
+
+2003-04-04 10:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-04-04 10:32 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: NoDetachDaemon_Case: Specify --daemon to
+ suppress diagnostic message.
+
+2003-04-04 10:19 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: distcc.c, distcc.h, help.c: Show version in log at client
+ startup.
+
+2003-04-04 09:43 Martin Pool <mbp@samba.org>
+
+ * patches/distcc-path.patch: Patch from Wayne to clean path of
+ masquerade links.
+
+2003-04-03 16:21 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note rusage format fix.
+
+2003-04-03 14:39 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-04-03 14:37 Martin Pool <mbp@samba.org>
+
+ * test/comfychair.py: Better log message.
+
+2003-04-03 14:29 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Factor out code to find basename from argv.
+
+2003-04-03 10:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/util.c: dcc_exit: Remove silly printf bug that made all
+ rusage messages inaccurate.
+
+2003-04-02 17:16 Martin Pool <mbp@samba.org>
+
+ * patches/: distcc-hostopt.patch, distccd-path.patch,
+ distccd-version.patch: Patches from Wayne
+
+2003-04-02 17:12 Martin Pool <mbp@samba.org>
+
+ * TODO: More protocol wonderings.
+
+2003-04-02 16:43 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Update todos.
+
+2003-04-02 16:37 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/sendfile.c: dcc_pump_sendfile: Check for select() failure.
+
+2003-04-02 16:27 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Doc
+
+2003-04-02 15:25 Martin Pool <mbp@samba.org>
+
+ * src/: climasq.c, distcc.c, distcc.h: Make
+ dcc_support_masquerade() return standard error codes.
+
+2003-04-02 15:16 Martin Pool <mbp@samba.org>
+
+ * src/: util.c, arg.c: Remove incorrect EXIT_FAULURE
+
+2003-04-02 15:10 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, src/climasq.c, src/distcc.c, src/distcc.h: Split
+ masquerade support into climasq.c
+
+2003-04-02 15:10 Martin Pool <mbp@samba.org>
+
+ * src/safeguard.c: Doc
+
+2003-04-02 15:05 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc
+
+2003-04-02 14:57 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Remove one more old "-1" error code. Patch from
+ Wayne Davison.
+
+2003-04-02 14:54 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc
+
+2003-04-02 14:49 Martin Pool <mbp@samba.org>
+
+ * src/: io.c, rpc.c: Move rpc-specific functions from io.c into
+ rpc.c.
+
+2003-04-02 14:46 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Make --no-fork undocumented.
+
+2003-04-02 14:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/io.c: Trace message when select()ing
+
+2003-04-02 14:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/results.txt: SSH results.
+
+2003-04-02 12:27 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note removal of "return -1".
+
+2003-04-02 11:55 Martin Pool <mbp@samba.org>
+
+ * NEWS: Update SSH news.
+
+2003-04-02 11:00 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes on DISTCC_SSH.
+
+2003-04-02 10:58 Martin Pool <mbp@samba.org>
+
+ * src/ssh.c: Doc
+
+2003-04-02 10:46 Martin Pool <mbp@samba.org>
+
+ * TODO: Note about documenting SSH.
+
+2003-04-01 13:59 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Split binary downloads onto their own page.
+
+2003-03-31 23:16 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Show more precision when printing transfer rates.
+
+2003-03-31 18:48 Martin Pool <mbp@samba.org>
+
+ * src/sendfile.c: Check network is ready to write before
+ attempting sendfile.
+
+2003-03-31 18:47 Martin Pool <mbp@samba.org>
+
+ * src/: io.h, io.c: Export select_for_*
+
+2003-03-31 18:46 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/ssh.c: Don't send server log to stderr by default.
+
+2003-03-31 18:36 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2003-03-31 18:36 Martin Pool <mbp@samba.org>
+
+ * src/io.c: dcc_readx: Handle reading from nonblocking
+ socketpairs/pipes.
+
+2003-03-31 18:34 Martin Pool <mbp@samba.org>
+
+ * src/ssh.c: Use nonblocking pipes to ssh.
+
+ * Add --log-stderr when invoking the remote daemon.
+
+2003-03-31 18:30 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Doc.
+
+2003-03-31 18:18 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version
+
+2003-03-31 18:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Preliminary support for ssh.
+
+2003-03-31 18:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/io.c: dcc_readx: Stub handler for EAGAIN.
+
+2003-03-31 18:00 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Reindent only.
+
+2003-03-31 17:55 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Fix silly Python bug.
+
+2003-03-31 17:49 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Giving a bogus port number now gives you
+ EXIT_BAD_ARGUMENTS.
+
+2003-03-31 17:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Allow default daemon lifetime of 60s, and
+ 300s for BigAssFile.
+
+2003-03-31 17:42 Martin Pool <mbp@samba.org>
+
+ * patches/.cvsignore: Ignore built test programs.
+
+2003-03-31 17:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Doc
+
+2003-03-31 17:22 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py, NEWS: Test invalid --allow masks.
+
+2003-03-31 17:00 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.h, ssh.c: dcc_ssh_connect: Fix const-ness of
+ strings.
+
+2003-03-31 17:00 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Undo constness of argv[] arguments, it just doesn't
+ work well in gcc.
+
+2003-03-31 16:55 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: More notes on new scheduler.
+
+2003-03-31 16:54 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-03-31 16:45 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: dcc_trace_argv: Fix constness of parameter.
+
+ * dcc_ssh_connect: Export prototype.
+
+2003-03-31 16:44 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: dcc_trace_argv: Fix constness of parameter.
+
+2003-03-31 16:39 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include ssh.o in client build.
+
+2003-03-31 16:38 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: Many more notes about single-queue multi-server
+ scheduler.
+
+2003-03-31 15:59 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Remove dead code.
+
+2003-03-31 15:37 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: Update
+
+2003-03-31 14:54 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc.
+
+2003-03-31 14:53 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add new case exercising dcc_check_address
+ and h_parsemask.
+
+2003-03-31 14:48 Martin Pool <mbp@samba.org>
+
+ * src/access.c: Doc
+
+2003-03-31 14:34 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: NoDetachDaemon_Case: prevent logs from
+ background process getting into build process's stderr.
+
+2003-03-31 14:28 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, test/testdistcc.py: Add test that --allow does in fact
+ deny connections as it should.
+
+2003-03-31 14:14 Martin Pool <mbp@samba.org>
+
+ * TODO, doc/ssh-notes.txt, doc/to-test.txt: Move notes on future
+ design options into ./TODO.
+
+2003-03-31 14:14 Martin Pool <mbp@samba.org>
+
+ * doc/lock-deadlock.txt: Remove old bug report.
+
+2003-03-31 14:10 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Remove done TODOs
+
+2003-03-31 14:09 Martin Pool <mbp@samba.org>
+
+ * patches/prefork-sample.c: Doc
+
+2003-03-29 11:06 Martin Pool <mbp@samba.org>
+
+ * NEWS: Retrospective release name.
+
+2003-03-28 18:57 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes about preforking.
+
+2003-03-28 18:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/interceptor.txt: interceptor.txt Remove old file
+
+2003-03-28 18:12 Martin Pool <mbp@samba.org>
+
+ * configure.ac, NEWS: Prepare for 2.0.1 release.
+
+2003-03-28 18:12 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Dereference symbolic files when producing tarball.
+
+2003-03-28 17:33 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Masquerade came out in 2.0, not 1.3.
+
+2003-03-28 16:47 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-03-28 16:17 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Get ready for 2.0 release.
+
+2003-03-28 16:13 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Get ready for 2.0 release.
+
+2003-03-28 16:11 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove old doc/ files from the distribution.
+
+2003-03-28 16:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, test/testdistcc.py: Test DISTCC_LOG being set to an
+ unwriteable file.
+
+2003-03-28 15:55 Martin Pool <mbp@samba.org>
+
+ * NEWS: Test suite now works with Python 1.5 or later.
+
+2003-03-28 15:53 Martin Pool <mbp@samba.org>
+
+ * test/comfychair.py: Remove dependency on os.spawnvp, which is
+ not in Python1.5
+
+2003-03-28 15:52 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c, NEWS: If DISTCC_LOG is an empty string, treat as
+ undefined.
+
+2003-03-28 15:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/comfychair.py: Remove list comprehension, which is not
+ available in Python 1.5.
+
+2003-03-28 13:54 Martin Pool <mbp@samba.org>
+
+ * TODO: Note on static linking.
+
+2003-03-28 13:51 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py, NEWS: On BSD, 'true' and 'false' are in
+ /usr/bin (?) not /bin.
+
+2003-03-28 13:44 Martin Pool <mbp@samba.org>
+
+ * NEWS: Notes on test improvments.
+
+2003-03-28 13:40 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Remove redundant setting of $(LIBS): autoconf puts
+ -lpopt in there if it's needed.
+
+2003-03-28 11:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: Note on DNS timeouts.
+
+2003-03-27 15:58 Martin Pool <mbp@samba.org>
+
+ * src/rpc.h: dcc_x_token_int: Token parameters are unsigned.
+
+2003-03-27 15:54 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-03-27 15:45 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: io.c, io.h: dcc_write_int: Remove dead function.
+
+2003-03-27 15:31 Martin Pool <mbp@samba.org>
+
+ * src/: io.h, io.c: dcc_write_str: Remove dead function.
+
+2003-03-27 15:29 Martin Pool <mbp@samba.org>
+
+ * src/clirpc.c: dcc_x_argv: Avoid redundant strlen() computation.
+
+2003-03-27 15:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Don't install linuxdoc-info by default, either from CVS
+ or distributions.
+
+2003-03-27 10:37 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Don't install linuxdoc-info by default, either
+ from CVS or distributions.
+
+2003-03-27 10:30 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Manual is for 1.3cvs.
+
+2003-03-23 12:18 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Don't ship unmerged patches in the tarball.
+
+2003-03-23 12:17 Martin Pool <mbp@samba.org>
+
+ * patches/resolver-timeout.diff: resolver-timeout.diff Resolver
+ timeout draft patch from Jonas Jensen
+
+2003-03-22 09:44 Martin Pool <mbp@samba.org>
+
+ * patches/connect-timeout.diff: Remove old draft patch.
+
+2003-03-21 19:02 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Get rid of Python 2 ism.
+
+2003-03-21 18:59 Martin Pool <mbp@samba.org>
+
+ * src/ncpus.c: Try looking for the predefined "__hpux" or
+ "__hpux__" not "hpux".
+
+2003-03-21 18:47 Martin Pool <mbp@samba.org>
+
+ * NEWS, test/testdistcc.py: Use randomly chosen TCP port for the
+ server when running tests.
+
+2003-03-21 18:46 Martin Pool <mbp@samba.org>
+
+ * NEWS: Use --allow=127.0.0.1 when starting daemon
+
+2003-03-21 18:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: NoDetachDaemon_Case: Shouldn't need
+ --lifetime for this test.
+
+2003-03-21 18:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/dsignal.c: Also print a message when terminating on
+ SIGALRM.
+
+2003-03-21 18:11 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: NoHosts_Case: Cleanup to get it working
+ with the new framework.
+
+2003-03-21 16:27 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: NoHosts_Case: Better log message.
+
+2003-03-21 16:24 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: NoDetachDaemon_Case: Make sure daemon is
+ killed off.
+
+2003-03-21 16:21 Martin Pool <mbp@samba.org>
+
+ * test/comfychair.py: Update from Subversion
+
+2003-03-21 16:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: CCACHE_ERR_FD
+
+2003-03-21 13:56 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove "=distcheck" directory on successful
+ completion.
+
+2003-03-21 13:55 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include types.h in distribution.
+
+2003-03-21 13:54 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/comfychair.py: Doc.
+
+2003-03-21 12:58 Martin Pool <mbp@samba.org>
+
+ * src/sendfile.c: printf type correctness.
+
+2003-03-21 12:51 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-03-21 12:34 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/types.h: in_addr_t should perhaps be ulong by default.
+
+2003-03-21 12:31 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Check for existence of sys/socket.h
+
+ * Check for in_addr_t
+
+2003-03-21 12:20 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: If socklen_t is missing, make it a size_t.
+
+2003-03-21 12:14 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Should build on IRIX.
+
+2003-03-21 11:58 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/ncpus.c: Try to fix BSD dcc_ncpus().
+
+2003-03-18 21:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Check whether the C compiler supports inlining,
+ etc. Needed for popt.
+
+2003-03-18 17:47 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Cast to int when calling printf.
+
+2003-03-18 17:46 Martin Pool <mbp@samba.org>
+
+ * src/snprintf.h: Add conditional declaration of vsnprintf.
+
+2003-03-18 17:45 Martin Pool <mbp@samba.org>
+
+ * src/ncpus.c: Add FreeBSD/OpenBSD/NetBSD implementation.
+
+2003-03-18 17:36 Martin Pool <mbp@samba.org>
+
+ * src/ncpus.c: Fix includes.
+
+2003-03-18 17:35 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/ncpus.c: Include prototypes for this file.
+
+2003-03-18 17:20 Martin Pool <mbp@samba.org>
+
+ * NEWS: Clean up some warnings on IRIX.
+
+2003-03-18 17:20 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/tempfile.c: Cast mode_t to int when passing to printf.
+
+2003-03-18 17:17 Martin Pool <mbp@samba.org>
+
+ * src/: rpc.c, tempfile.c: Include snprintf.h for systems that
+ don't have these functions.
+
+2003-03-18 17:15 Martin Pool <mbp@samba.org>
+
+ * src/: exec.c: Cast pid_t to long when passing to printf.
+
+2003-03-18 17:13 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, src/dparent.c: Print number of online CPUs when daemon
+ starts up.
+
+2003-03-18 17:09 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: Add prototype for dcc_ncpus.
+
+2003-03-18 17:04 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Reorder news items.
+
+2003-03-18 15:21 Martin Pool <mbp@samba.org>
+
+ * TODO: Add note to try out masquerade with make-kpkg.
+
+2003-03-18 14:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/comfychair.py: Decode waitstatus values when a command
+ fails.
+
+2003-03-17 22:25 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-03-14 15:49 Martin Pool <mbp@samba.org>
+
+ * TODO: Update status:
+
+ * Kernel 2.5 bug
+
+ * SQMS scheduler
+
+ * --allow is done
+
+ * Distributed caching
+
+2003-03-13 17:33 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note that SIGTERM handling race for server is now fixed.
+
+2003-03-13 17:31 Martin Pool <mbp@samba.org>
+
+ * test/comfychair.py: Merge from svn r30
+
+2003-03-13 17:29 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * patches/: compression.patch, swhite-lzo-compress.diff: Updated
+ draft patch from Stephen White to do LZO compression.
+
+2003-03-13 17:27 Martin Pool <mbp@samba.org>
+
+ * patches/distcc-ethereal.diff: Draft patch to Ethereal
+ <ethereal.com> to decode/dissect distcc connections.
+
+2003-03-12 19:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: assert_regexp renamed to assert_re_search
+
+2003-03-12 17:09 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Fix incorrect regexp assertion
+
+2003-03-12 16:51 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Many internal updates to ComfyChair framework.
+
+2003-03-12 16:11 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Change to using new ComfyChair.main()
+ method, rather than implementing it by hand.
+
+2003-03-12 15:43 Martin Pool <mbp@samba.org>
+
+ * test/comfychair.py: Import updated ComfyChair from Subversion:
+ renamed methods, new main() method, etc.
+
+2003-03-12 15:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-03-10 15:34 Martin Pool <mbp@samba.org>
+
+ * src/util.c: IRIX might need sys/time.h before sys/resource.h
+
+2003-03-10 15:13 Martin Pool <mbp@samba.org>
+
+ * src/util.c: Check for sys/resource.h
+
+2003-03-10 15:10 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Check for sys/resource.h
+
+2003-03-10 15:08 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Check for getrusage.
+
+2003-03-10 14:12 Martin Pool <mbp@samba.org>
+
+ * NEWS: Give credit for masquerade mode.
+
+2003-03-10 13:46 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Test for getwd and getcwd
+
+2003-03-10 10:58 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove ssh.o from client for the time being.
+
+2003-03-10 10:16 Martin Pool <mbp@samba.org>
+
+ * patches/: distcc-1.2.1-masquerade.patch, masquerade.patch:
+ Remove merged 'masquerade' patch.
+
+2003-03-10 10:07 Martin Pool <mbp@samba.org>
+
+ * src/io.c: sendfile.h no longer needed here. Thanks to Wayne
+ Davison.
+
+2003-03-09 20:28 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Re-add "if your disks are too empty".
+
+2003-03-09 10:43 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Advance version to 1.3cvs.
+
+2003-03-09 10:14 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add ssh module to build.
+
+2003-03-08 22:48 Martin Pool <mbp@samba.org>
+
+ * .cvsignore: Ignore =distcheck directory
+
+2003-03-08 21:53 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note about merged masquerade mode.
+
+ * Reindent stuff.
+
+2003-03-08 21:47 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-03-08 10:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/implicit.c: Doc
+
+2003-03-08 10:29 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-03-02 10:31 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Update for release.
+
+2003-03-02 09:52 Martin Pool <mbp@samba.org>
+
+ * NEWS: Update for release.
+
+2003-03-01 23:54 Martin Pool <mbp@samba.org>
+
+ * README.popt: URL for popt.
+
+2003-03-01 23:49 Martin Pool <mbp@samba.org>
+
+ * src/: setuid.c, setuid.h: Fix constness of opt_user.
+
+2003-03-01 09:12 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac, NEWS: Check existence of ctype.h. Pointed out by
+ Tom Matelich.
+
+2003-02-28 14:15 Martin Pool <mbp@samba.org>
+
+ * patches/masquerade.patch: Masquerade patch from Wayne Davison
+
+2003-02-28 10:45 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/lock.c: Doxygen janitor
+
+2003-02-28 08:02 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Fix unreachable trace message. Thanks to Dimitri
+ Papadopoulos-Orfanos.
+
+2003-02-27 16:07 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: analog-resolve: Tweak jdresolve invocation
+
+2003-02-27 15:58 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: analog-resolve: Tweak jdresolve invocation
+
+2003-02-27 13:23 Martin Pool <mbp@samba.org>
+
+ * patches/n_cpus.txt: n_cpus.txt Notes on determining NCPUs, from
+ Dimitri PAPADOPOULOS
+
+2003-02-27 13:14 Martin Pool <mbp@samba.org>
+
+ * patches/connect-timeout-02.diff: connect-timeout-02.diff
+ Connection timeout patch from Oscar Esteban
+
+2003-02-27 13:09 Martin Pool <mbp@samba.org>
+
+ * patches/connect-timeout.diff: connect-timeout.diff Connection
+ timeout patch from Oscar Esteban
+
+2003-02-27 12:52 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, OLDNEWS: Remove empty/dead OLDNEWS file.
+
+2003-02-27 12:36 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add missing release comments.
+
+2003-02-27 12:32 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add release date.
+
+2003-02-27 12:20 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc
+
+2003-02-27 12:18 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Be more selective in uploading linuxdoc files.
+
+2003-02-27 11:52 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Make distcheck should use $MAKE.
+
+2003-02-27 11:50 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: clirpc.h: New header
+
+2003-02-27 11:14 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, NEWS: Add a simple distcheck target.
+
+2003-02-27 11:10 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove deleted tests from $(test_SOURCE)
+
+2003-02-27 11:06 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Fix command to remove dist dir before building.
+
+2003-02-27 10:25 Martin Pool <mbp@samba.org>
+
+ * src/access.c: The FreeBSD manual suggests <sys/types.h> might
+ be needed here to make in_addr_t work.
+
+2003-02-27 10:20 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Check for stdint.h
+
+2003-02-27 10:18 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-02-27 10:17 Martin Pool <mbp@samba.org>
+
+ * NEWS: Call this release 1.2.2.
+
+ * Note about updated Makefile.
+
+2003-02-26 16:36 Martin Pool <mbp@samba.org>
+
+ * test/: basecases.py, testdistcc.py: Move basecases back into
+ testdistcc
+
+2003-02-26 12:35 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/ScanArgs.py: Remove RunCmd_Case, whose functionality has
+ now migrated up into ComfyChair.
+
+2003-02-26 12:27 Martin Pool <mbp@samba.org>
+
+ * test/.cvsignore: Ignore ./testtmp/ if it happens to be here.
+
+2003-02-26 12:27 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Remove RunCmd_Case, whose functionality has
+ now migrated up into ComfyChair.
+
+ * Add GPL.
+
+2003-02-26 12:25 Martin Pool <mbp@samba.org>
+
+ * test/basecases.py: Remove RunCmd_Case, whose functionality has
+ now migrated up into ComfyChair.
+
+2003-02-26 12:22 Martin Pool <mbp@samba.org>
+
+ * test/comfychair.py: runCmdNoWait: add missing "import os"
+
+2003-02-26 12:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: ./configure should not be removed by distclean, only by
+ maintainer-clean.
+
+ * Make Makefile work with pmake
+
+2003-02-26 11:51 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove '$^' variable, which doesn't work with
+ pmake.
+
+2003-02-26 11:47 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: ./configure should not be removed by distclean,
+ only by maintainer-clean.
+
+2003-02-26 11:44 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/ssh.c: More cleanups/merges. Still not working.
+
+2003-02-25 23:14 Martin Pool <mbp@samba.org>
+
+ * src/ssh.c: Merge more code from rsync. Still not working.
+
+2003-02-25 23:10 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Add socketpair test from rsync.
+
+2003-02-25 22:50 Martin Pool <mbp@samba.org>
+
+ * src/ssh.c: ssh.c Check in non-working skeleton ssh code from
+ rsync and cvs
+
+2003-02-25 22:37 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Doc
+
+2003-02-25 22:36 Martin Pool <mbp@samba.org>
+
+ * src/trace.h: Don't use __FUNCTION__ if not building on gnuc.
+
+2003-02-25 22:26 Martin Pool <mbp@samba.org>
+
+ * configure.ac, NEWS: Check for inet_aton in libresolv, which
+ might fix Solaris 2.6.
+
+2003-02-25 22:23 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Clear up unused vars
+
+ * Doc
+
+2003-02-25 22:22 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Typo
+
+2003-02-25 22:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * patches/distcc-1.2.1-masquerade.patch: Patch from Wayne Davison
+ to masquerade as cc.
+
+2003-02-25 22:01 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc
+
+2003-02-25 21:49 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version to 1.3cvs
+
+2003-02-25 21:26 Martin Pool <mbp@samba.org>
+
+ * .cvsignore: Ignore linbot-report.
+
+2003-02-25 21:25 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Delete directory used to make distribution tarball
+ before starting to build it.
+
+2003-02-25 21:23 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes about asprintf and Linuxdoc.
+
+2003-02-25 16:59 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note about libiberty redaction.
+
+2003-02-25 16:57 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Update for 1.2.1 release.
+
+2003-02-25 16:51 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Fix typo
+
+2003-02-25 16:48 Martin Pool <mbp@samba.org>
+
+ * src/snprintf.c: Quieten compiler warning.
+
+2003-02-25 16:47 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Also check for snprintf
+
+2003-02-25 16:38 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Fix small memory leak.
+
+2003-02-25 16:33 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Remove dead function dcc_close_extra_fds.
+
+2003-02-25 16:28 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Print Python version before running tests to help
+ in debugging remote problems.
+
+2003-02-25 16:08 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Remove unnecessary 'unittest' import
+
+2003-02-25 16:07 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py, NEWS: Return code from running the tests
+ now indicates whether they worked or not.
+
+2003-02-25 16:06 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Remove += operator not supported in old
+ Pythons.
+
+2003-02-25 15:22 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Don't worry about -Winline, because nothing in
+ distcc is explicitly inlined.
+
+2003-02-25 15:14 Martin Pool <mbp@samba.org>
+
+ * DEPENDENCIES: We need autoconf >=2.53
+
+2003-02-25 15:13 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Check for vsnprintf as well.
+
+2003-02-25 15:06 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Make sure snprintf.o actually gets linked in.
+
+2003-02-25 11:28 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Include local declarations for asprintf if
+ necessary.
+
+2003-02-25 11:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: snprintf.c, snprintf.h: Add *printf implementation from
+ Samba HEAD.
+
+2003-02-24 16:39 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Remove -Wredundant-decls, because it causes noise
+ with some system headers.
+
+2003-02-24 16:35 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Remove -W options that are implied by -Wall.
+
+2003-02-24 16:29 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include %.o target for Makes that have a wierd
+ built-in definition.
+
+2003-02-24 16:24 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add ansidecl.h from libiberty (from gdb-5.3)
+
+2003-02-24 16:20 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add ansidecl.h from libiberty (from gdb-5.3)
+
+2003-02-24 16:15 Martin Pool <mbp@samba.org>
+
+ * NEWS: Update NEWS
+
+2003-02-24 16:12 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Remove redundant inclusion of assert.h
+
+2003-02-24 16:10 Martin Pool <mbp@samba.org>
+
+ * configure.ac, Makefile.in: Try to find Python during
+ configuration.
+
+2003-02-24 15:56 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Allow installation to complete even if the tools
+ to build Linuxdoc are missing.
+
+2003-02-24 15:05 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Add "installcheck" target that can be called by
+ the buildfarm.
+
+2003-02-24 14:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: FIXME
+
+2003-02-24 13:59 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: foo
+
+2003-02-24 13:19 Martin Pool <mbp@samba.org>
+
+ * NEWS: foo
+
+2003-02-24 13:15 Martin Pool <mbp@samba.org>
+
+ * NEWS: Dummy checkin to test build farm.
+
+2003-02-24 11:54 Martin Pool <mbp@samba.org>
+
+ * NEWS: Dummy checkin to test build farm.
+
+2003-02-24 09:52 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Update version to 1.2.1cvs.
+
+2003-02-22 20:29 Martin Pool <mbp@samba.org>
+
+ * NEWS: Get ready for 1.2 release.
+
+2003-02-22 20:22 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Set bug report address to the list, not me.
+
+2003-02-22 20:21 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Get ready for 1.2 release.
+
+2003-02-22 12:55 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove Docbook from distribution.
+
+2003-02-22 12:53 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: filename.h: New file.
+
+2003-02-22 12:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.h: Remove redundant decls.
+
+2003-02-22 12:19 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Turn on more compiler warnings.
+
+2003-02-22 12:16 Martin Pool <mbp@samba.org>
+
+ * TODO: Turn on more compiler warnings.
+
+ * Note about statistics.
+
+2003-02-22 12:07 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Refactor code into new function
+ dcc_parse_localhost.
+
+2003-02-22 11:58 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Fix comments
+
+2003-02-22 11:56 Martin Pool <mbp@samba.org>
+
+ * NEWS: Roll back to Linuxdoc for the manual.
+
+2003-02-22 11:37 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Ask people to report bugs to the mailing
+ list, not to me.
+
+2003-02-22 11:35 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: distcc.sgml Resurrect Linuxdoc manual
+
+2003-02-22 11:25 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Use rsync --delete when uploading manual to delete
+ unneeded files.
+
+2003-02-22 11:12 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Roll back to Linuxdoc for the manual. Docbook
+ tools seem to be still too unstable.
+
+2003-02-21 11:54 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add "links" web page
+
+2003-02-21 10:13 Martin Pool <mbp@samba.org>
+
+ * patches/distcc-line3.diff: Patch from Tim Janik to absolutize
+ #line directives.
+
+2003-02-21 10:08 Martin Pool <mbp@samba.org>
+
+ * doc/lca2003/slides/.cvsignore: Ignore built Postscript
+
+2003-02-21 10:05 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include additional Python files in distribution.
+
+2003-02-19 13:09 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: By default only one job is run locally now.
+
+2003-02-18 17:55 Martin Pool <mbp@samba.org>
+
+ * NEWS: Postscript and PDF turned off for now.
+
+2003-02-18 17:44 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add target to build "nochunks" (one big page)
+ manual.
+
+2003-02-18 17:22 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add upload-usermanual target.
+
+2003-02-18 15:15 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Put usermanual files correctly into distribution.
+
+2003-02-18 15:14 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add targets/rules to build, distribute and install
+ the Docbook-XML manual.
+
+2003-02-18 14:37 Martin Pool <mbp@samba.org>
+
+ * doc/aoss2002/slides/: README.aoss2002, aoss4.mgp, flow.dia,
+ flow.png: Move AOSS2002 slides
+
+2003-02-14 15:40 Martin Pool <mbp@samba.org>
+
+ * TODO: Add note about slow networks.
+
+2003-02-13 18:10 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Don't use XMIT locks for localhost, because there
+ is no transmission phase.
+
+2003-02-13 18:00 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/hosts.c: Add HOST/NSLOTS syntax to limit number of tasks.
+ Patch from Rusty.
+
+2003-02-13 16:50 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/where.c: Typo: didn't set CPU slot properly.
+
+2003-02-13 16:19 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: Add compiler warnings from Daniel Veilard
+
+2003-02-12 18:24 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Import new setuidcases module.
+
+2003-02-12 18:12 Martin Pool <mbp@samba.org>
+
+ * test/setuidcases.py: New file to check --user option.
+
+2003-02-12 18:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/comfychair.py: Merge from comfychair CVS
+
+2003-02-11 11:18 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Fixme.
+
+2003-02-07 21:17 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c, where.c, where.h: Rename dcc_pick_buildhost to
+ dcc_pick_host_from_env
+
+2003-02-05 23:11 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-02-05 23:07 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/bulk.c, NEWS: Add O_BINARY bit needed for Cygwin. Based on
+ a patch from Helind.
+
+2003-02-05 22:43 Martin Pool <mbp@samba.org>
+
+ * DEPENDENCIES: Note about dietlibc.
+
+2003-02-05 22:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: Note about manpages.
+
+2003-02-05 19:14 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: opt_allowed needs to be declared extern. Found
+ by tcc.
+
+2003-02-05 19:11 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-02-05 19:10 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Change assert to trace call to make dietlibc happy
+
+2003-02-05 19:08 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: fixme
+
+2003-02-04 23:02 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Cleanup comments.
+
+2003-02-04 22:58 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: timeval.c, timeval.h: Add GNU function for calculating
+ the difference between timevals.
+
+2003-02-04 19:29 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-02-04 19:21 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Add ./lib to include path so libiberty.h can be
+ found.
+
+2003-02-03 12:50 Martin Pool <mbp@samba.org>
+
+ * src/rpc.h: Doc
+
+2003-02-03 12:49 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-02-03 01:15 Martin Pool <mbp@samba.org>
+
+ * doc/new-scheduler.txt: Notes on new scheduler
+
+2003-02-03 00:59 Martin Pool <mbp@samba.org>
+
+ * NEWS: Describe new scheduling algorithm.
+
+2003-02-03 00:44 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Better message
+
+2003-02-03 00:43 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Fixme
+
+2003-02-03 00:28 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Doc
+
+2003-02-03 00:27 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Hold transmit lock only while sending request.
+
+2003-02-03 00:27 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Doc
+
+2003-02-03 00:27 Martin Pool <mbp@samba.org>
+
+ * src/: lock.c, lock.h: (dcc_unlock): New function.
+
+2003-02-03 00:13 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/lock.h: Add lock_fd parameter to dcc_lock_host and
+ dcc_lock_local functions
+
+2003-02-03 00:04 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Doc
+
+2003-02-03 00:04 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Remove redundant dcc_get_tempdir call.
+
+2003-02-03 00:03 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Split lockfile creation into dcc_open_lockfile
+
+2003-02-03 00:01 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-02-02 23:31 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add README.libiberty to distributed files.
+
+2003-02-02 23:31 Martin Pool <mbp@samba.org>
+
+ * README.libiberty: Check in some files from libiberty.
+
+2003-02-02 23:30 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exitcode.h: Add EXIT_BUSY.
+
+2003-02-02 22:56 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-02-02 22:48 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include libiberty source in distribution.
+
+2003-02-02 22:48 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Add lib/ directory
+
+ * Check for asprintf() and vasprintf() and replace them if not
+ present.
+
+2003-02-02 22:06 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes on Docbook.
+
+ * Notes on a minimal gcc for clients.
+
+2003-02-02 16:30 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/: distcc.sgml, footer.html: Remove Linuxdoc
+ documentation now that it's been converted to Docbook XML
+
+2003-02-02 16:30 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note conversion of user manual.
+
+2003-02-02 16:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/.cvsignore: Don't ignore .d and .i files, since they
+ shouldn't be generated anymore.
+
+2003-02-02 14:37 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/where.c: Doc
+
+2003-01-31 11:48 Martin Pool <mbp@samba.org>
+
+ * analog/.cvsignore: Ignore generated files.
+
+2003-01-31 11:17 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes on corks, scheduling, and tcp options.
+
+2003-01-31 10:56 Martin Pool <mbp@samba.org>
+
+ * TODO: Notes about scheduling from BBQ
+
+2003-01-31 10:42 Martin Pool <mbp@samba.org>
+
+ * TODO: Note about #pragma implementation
+
+2003-01-29 15:52 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Grammar fixes.
+
+2003-01-29 12:14 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Typo
+
+2003-01-29 00:50 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: TODO
+
+2003-01-29 00:49 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Note new --allow option.
+
+2003-01-29 00:19 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in, .cvsignore: Add new h_parsemask test harness.
+
+2003-01-29 00:02 Martin Pool <mbp@samba.org>
+
+ * doc/lca2003/slides/: .cvsignore, distcc-lca2003.mgp, flow.dia,
+ flow.png: Add LCA2003 slides.
+
+2003-01-28 23:14 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add access.c and access.h
+
+2003-01-28 19:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: TODO
+
+2003-01-28 01:24 Martin Pool <mbp@samba.org>
+
+ * src/access.c: Empty file
+
+2003-01-28 01:21 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Doc
+
+2003-01-28 01:19 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Fix string syntax problem.
+
+2003-01-28 01:18 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Version to 1.2cvs
+
+2003-01-28 01:18 Martin Pool <mbp@samba.org>
+
+ * src/help.c: Please send bugs to the mailing list
+
+2003-01-28 01:17 Martin Pool <mbp@samba.org>
+
+ * src/help.c: Update copyright
+
+2003-01-28 01:06 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add missing Python source.
+
+2003-01-28 01:05 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-01-28 01:01 Martin Pool <mbp@samba.org>
+
+ * src/: dparent.c, daemon.c: srvnet.h: new header
+
+2003-01-28 00:56 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Update for 1.1
+
+2003-01-28 00:52 Martin Pool <mbp@samba.org>
+
+ * NEWS: Updates to manual
+
+2003-01-28 00:21 Martin Pool <mbp@samba.org>
+
+ * analog/extract_version_downloads.py: Simple script to show the
+ number of downloads of each version.
+
+2003-01-27 23:23 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Doc
+
+2003-01-27 23:19 Martin Pool <mbp@samba.org>
+
+ * TODO: Note about taking host list from a file.
+
+2003-01-27 23:16 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: New srvnet.h header
+
+2003-01-27 23:16 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Doxygen cleanups
+
+2003-01-27 23:11 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: exec.h, exec.c: Doc
+
+2003-01-27 23:01 Martin Pool <mbp@samba.org>
+
+ * src/exitcode.h: Give the exitcode enum a name
+
+ * Add EXIT_SETUID_FAILED and EXIT_ACCESS_DENIED
+
+2003-01-27 22:59 Martin Pool <mbp@samba.org>
+
+ * src/hosts.h: Fix Doxygen glitch
+
+2003-01-27 22:58 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Split sendfile wrappers out into src/sendfile.c
+
+2003-01-27 22:55 Martin Pool <mbp@samba.org>
+
+ * src/: setuid.c, setuid.h: New code for discarding privileges
+ when run by root.
+
+2003-01-27 22:54 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/trace.h: Update Doxygen.
+
+2003-01-27 22:50 Martin Pool <mbp@samba.org>
+
+ * src/util.h: Move srvnet functions to srvnet.h
+
+2003-01-27 22:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/srvnet.c: src/srvnet.h: New header
+
+ * Doc
+
+ * Prepare for IP access-control checks
+
+2003-01-27 22:35 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.h: src/srvnet.h: New header
+
+2003-01-27 22:33 Martin Pool <mbp@samba.org>
+
+ * src/sendfile.c: Move sendfile support into sendfile.c
+
+ * Doc
+
+ * Better handling of unsupported systems
+
+2003-01-27 22:30 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/daemon.c: Update Doxygen tags
+
+ * Remove unneeded headers
+
+ * Discard root privileges if we have them.
+
+2003-01-27 22:27 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c, clinet.c: Update Doxygen tags
+
+2003-01-27 22:25 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/: Build.py, Project.py: Better messages while build is in
+ progress.
+
+2003-01-27 22:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-01-27 22:21 Martin Pool <mbp@samba.org>
+
+ * README.packaging: Please use shlibs
+
+ * Please use proper gcc names
+
+2003-01-27 22:18 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Doc
+
+ * Fix help string for --with-included-popt
+
+ * Some cleanups
+
+ * Look for setgroups()
+
+2003-01-27 22:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * README: Update performance for current project status
+
+2003-01-27 22:12 Martin Pool <mbp@samba.org>
+
+ * TODO: Many TODO updates.
+
+2003-01-27 22:06 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc
+
+2003-01-27 21:49 Martin Pool <mbp@samba.org>
+
+ * .cvsignore, Doxyfile: Add Doxygen configuration. Not called
+ from Makefile.
+
+2003-01-27 21:35 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/buildutil.py: Better error message for command failures
+
+2003-01-24 19:54 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add check for inadvertent recursion
+
+2003-01-24 19:52 Martin Pool <mbp@samba.org>
+
+ * TODO: Many updates to TODO
+
+2003-01-24 19:51 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, configure.ac: Fix configure test for hstrerror().
+ (Frerich Raabe)
+
+2003-01-19 20:50 Martin Pool <mbp@samba.org>
+
+ * bench/Summary.py: Fix bugs in printing statistics.
+
+2003-01-19 20:29 Martin Pool <mbp@samba.org>
+
+ * bench/buildutil.py: Better formatting time messages.
+
+2003-01-19 20:27 Martin Pool <mbp@samba.org>
+
+ * bench/Summary.py: Better handling of statistics generation or
+ build failures.
+
+2003-01-19 18:45 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2003-01-19 18:43 Martin Pool <mbp@samba.org>
+
+ * test/: ScanArgs.py, basecases.py, testdistcc.py: Split some
+ Python classes out into separate files.
+
+2003-01-19 18:19 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2003-01-19 15:10 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Remove ifdef'd code.
+
+2003-01-18 23:57 Martin Pool <mbp@samba.org>
+
+ * configure.ac: TODO about finding Python.
+
+2003-01-18 23:55 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Roll back change to version number format.
+
+2003-01-18 23:48 Martin Pool <mbp@samba.org>
+
+ * src/: .cvsignore, config.h.in: Build config.h.in, rather than
+ storing in CVS.
+
+2003-01-18 23:46 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Fix text formatting.
+
+2003-01-18 23:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * .cvsignore: Ignore files produced by autoconf.
+
+2003-01-18 22:51 Martin Pool <mbp@samba.org>
+
+ * bench/benchmark.py, NEWS: Projects can now be selected by
+ unambiguous name prefix
+
+2003-01-18 22:39 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Update copyright
+
+2003-01-18 22:38 Martin Pool <mbp@samba.org>
+
+ * config.guess, config.sub: Update from Debian autotools-dev
+
+2003-01-18 22:27 Martin Pool <mbp@samba.org>
+
+ * config.sub: Resurrect
+
+2003-01-18 22:22 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * aclocal.m4, config.guess, config.sub, configure: Stop storing
+ autoconf junk in CVS
+
+2003-01-18 22:19 Martin Pool <mbp@samba.org>
+
+ * TODO: Need to document benchmark.
+
+2003-01-18 22:10 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Invite people to pass BENCH_ARGS to Make to
+ control the benchmark.
+
+2003-01-18 22:02 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include bench/statistics.py in distribution.
+
+2003-01-18 22:00 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Roll over news
+
+2003-01-18 21:49 Martin Pool <mbp@samba.org>
+
+ * OLDNEWS: Put in correct version of old news file.
+
+2003-01-18 21:36 Martin Pool <mbp@samba.org>
+
+ * OLDNEWS: Roll over NEWS.
+
+2003-01-17 12:05 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac: Bump version to 1.1cvs
+
+2003-01-17 12:00 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: FIXME about running as root.
+
+2003-01-17 11:37 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: fixme
+
+2003-01-16 11:36 Martin Pool <mbp@samba.org>
+
+ * configure: Prepare for 1.0 release.
+
+2003-01-16 11:32 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Prepare for 1.0 release.
+
+2003-01-16 11:28 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure.ac: Prepare for 1.0 release.
+
+2003-01-16 11:06 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/benchmark.py: Doc
+
+2003-01-14 16:25 Martin Pool <mbp@samba.org>
+
+ * NEWS: Build .bz2 tarball rather than .tgz
+
+ * Remove PS and PDF from tarball.
+
+2003-01-14 16:03 Martin Pool <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2003-01-14 15:46 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Resolve logfile lines in order.
+
+2003-01-14 15:01 Martin Pool <mbp@samba.org>
+
+ * bench/.cvsignore: Ignore bench.log
+
+2003-01-14 00:54 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Correct calling of sendfile on BSD
+
+2003-01-13 14:47 Martin Pool <mbp@samba.org>
+
+ * TODO: [no log message]
+
+2003-01-13 12:24 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Benchmark must be run from bench/ directory.
+
+2003-01-12 23:59 Martin Pool <mbp@samba.org>
+
+ * bench/Summary.py: Show uname in summary.
+
+2003-01-12 23:51 Martin Pool <mbp@samba.org>
+
+ * bench/Summary.py: Show uname in summary.
+
+2003-01-12 23:40 Martin Pool <mbp@samba.org>
+
+ * bench/Project.py: Doc snarf bug.
+
+2003-01-12 23:24 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/Summary.py: Store results into Summary in the order in
+ which they are generated.
+
+2003-01-12 23:05 Martin Pool <mbp@samba.org>
+
+ * bench/: Build.py, actions.py: Add action to "make clean" if
+ desired. Off by default.
+
+2003-01-12 22:58 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/Summary.py: Print a heading on the results, plus the date
+ and the host list.
+
+2003-01-12 22:37 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/: Summary.py, buildutil.py: Show all times in %.4f format
+ -- about the right amount of precision.
+
+2003-01-12 22:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/CompilerSpec.py: Don't use commas in directory names
+ because it causes trouble with some Makefiles.
+
+2003-01-12 21:43 Martin Pool <mbp@samba.org>
+
+ * bench/Project.py: Doc
+
+2003-01-12 21:38 Martin Pool <mbp@samba.org>
+
+ * bench/: CompilerSpec.py, benchmark.py: Split CompilerSpec into
+ its own file.
+
+2003-01-12 21:32 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/.cvsignore: Ignore download directory and .pyc files.
+
+2003-01-09 11:06 Martin Pool <mbp@samba.org>
+
+ * bench/benchmark.py: Run snarf quietly
+
+ * Doc
+
+2003-01-08 18:28 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/benchmark.py: Push mainline code into a main() routine.
+
+2003-01-08 18:01 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/benchmark.py: Doc
+
+2003-01-06 11:24 Martin Pool <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2003-01-06 11:24 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Split old news items out into a separate page.
+
+2003-01-02 19:52 Martin Pool <mbp@samba.org>
+
+ * NEWS: Doc macrobenchmark.
+
+2003-01-02 16:31 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * DEPENDENCIES: Add notes about macrobenchmark.
+
+2003-01-01 10:01 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/: benchmark, benchmark.py: Rename bench/benchmark to
+ bench/benchmark.py.
+
+2003-01-01 09:19 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Use a $(PYTHON) variable so that it can be
+ overridden if the name varies.
+
+2002-12-17 17:17 Martin Pool <mbp@samba.org>
+
+ * news.el, news.emacs: Store settings in elisp rather than as
+ mode variables.
+
+2002-12-17 10:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/benchmark: Doc
+
+ * Better link for kernel
+
+2002-12-16 21:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/benchmark: b* Project._rm_files: Do this silently and only
+ as necessary.
+
+2002-12-16 21:12 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/benchmark: Rename /SourceTree/Project/
+
+2002-12-16 21:07 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/benchmark: Doc
+
+2002-12-16 20:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/benchmark: Doc.
+
+ * Try to make shell commands more readable.
+
+ * Add GIMP URL.
+
+2002-12-16 20:24 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/.cvsignore: Ignore output files.
+
+2002-12-16 19:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * bench/benchmark: (SourceTree): Cleaner handling of directories.
+
+2002-12-16 19:11 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * lzo/.cvsignore: Ignore built files for minilzo
+
+2002-12-16 14:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2002-12-16 11:56 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: h_scanargs.c, h_argvtostr.c: Reindent to java / 4-space
+ style.
+
+2002-12-16 11:32 Martin Pool <mbp@samba.org>
+
+ * patches/README.patches: Disclaim warranty on these patches.
+
+2002-12-13 12:06 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Bump version to 0.16cvs.
+
+2002-12-13 12:04 Martin Pool <mbp@samba.org>
+
+ * NEWS, linuxdoc/distcc.sgml: (Cross-Compilation): The
+ recommended convention for gcc names is <target>-gcc-<version>,
+ and GCC 3.3 will install itself under this name. (Alexandre
+ Oliva, Claes Wallin)
+
+2002-12-13 11:06 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac: Bump version to 0.16cvs.
+
+2002-12-13 09:58 Martin Pool <mbp@samba.org>
+
+ * NEWS, OLDNEWS: Roll over NEWS.
+
+2002-12-12 20:57 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure, configure.ac: Bump version to 0.15.
+
+2002-12-12 20:45 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: Current linux-2.4.19 benchmark results.
+
+2002-12-12 20:40 Martin Pool <mbp@samba.org>
+
+ * configure: Run autoconf.
+
+2002-12-12 20:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in, NEWS: Rename TARGET_ROOT variable to the more
+ standard name of DESTDIR. (Alexandre Oliva)
+
+2002-12-12 20:03 Martin Pool <mbp@samba.org>
+
+ * doc/irc/openprojects-distcc-20020807.txt: Random notes about
+ distcc
+
+2002-12-12 19:45 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py, src/help.c: (dcc_show_version,
+ VersionOption_Case): --version now shows default port.
+
+2002-12-12 19:38 Martin Pool <mbp@samba.org>
+
+ * doc/flood.txt: flood.txt: Notes on network performance.
+
+2002-12-12 19:38 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * aclocal.m4: Rerun autoconf.
+
+2002-12-12 19:33 Martin Pool <mbp@samba.org>
+
+ * TODO: TODO: New file. Many random notes about things to do,
+ moved from the user manual.
+
+2002-12-12 19:31 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * analog/.cvsignore: Ignore generated files.
+
+2002-12-12 19:29 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * analog/day.gnuplot: day.gnuplot: New gnuplot file to plot daily
+ traffic.
+
+2002-12-12 18:59 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: (Author): Rephrase.
+
+2002-12-12 18:56 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Move "Reporting Bugs" and "Test Suite"
+ sections into the introduction chapter.
+
+2002-12-12 18:43 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Remove empty <appendix> tag.
+
+2002-12-12 18:41 Martin Pool <mbp@samba.org>
+
+ * NEWS: Only show non-maintainer names in the NEWS file, as in
+ Subversion.
+
+2002-12-12 18:38 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml, NEWS: Move "Bugs" chapter into TODO.
+ (Martin Pool)
+
+2002-12-12 18:36 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2002-12-12 18:09 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: (dist_files): Add TODO to distribution.
+
+2002-12-12 17:39 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/lock.c: lock.c: Add quotation.
+
+2002-12-06 11:32 Martin Pool <mbp@samba.org>
+
+ * analog/traffic.gnuplot: traffic.gnuplot: Use log y scale.
+
+2002-12-06 11:29 Martin Pool <mbp@samba.org>
+
+ * analog/traffic.py: traffic.py: New utility to produce weekly
+ counts of downloads and accesses.
+
+2002-12-06 11:07 Martin Pool <mbp@samba.org>
+
+ * analog/traffic.gnuplot: Simple plot of traffic
+
+2002-12-06 10:19 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/release-names.txt: [no log message]
+
+2002-12-05 14:07 Martin Pool <mbp@samba.org>
+
+ * doc/interceptor.txt: Notes on using an external interceptor
+
+2002-12-05 10:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: [no log message]
+
+2002-11-28 04:48 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: We now use ComfyChair not PyUnit
+
+2002-11-28 04:45 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add section on how to report bugs well
+
+2002-11-28 04:40 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add section on how to report bugs well
+
+2002-11-28 04:20 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Say that --no-fork is for debugging ONLY
+
+2002-11-23 04:35 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add TODO
+
+ Bump version to 0.14
+
+2002-11-22 19:00 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add note about -MF
+
+2002-11-21 18:53 Martin Pool <mbp@samba.org>
+
+ * src/cpp.c: Doc
+
+2002-11-21 18:50 Martin Pool <mbp@samba.org>
+
+ * src/cpp.c: Doc
+
+2002-11-21 18:46 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Doc
+
+2002-11-21 18:24 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: DaemonBadPort_Case: avoid polluting system
+ log files.
+
+2002-11-21 18:06 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc
+
+2002-11-21 18:02 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove obsolete/uncalled dist-python target
+
+ Move comfychair into test/
+
+2002-11-21 17:21 Martin Pool <mbp@samba.org>
+
+ * analog/.cvsignore: Ignore generated refererlog
+
+2002-11-21 17:16 Martin Pool <mbp@samba.org>
+
+ * test/: .cvsignore, comfychair.py: Move comfychair into test/
+
+2002-11-21 17:06 Martin Pool <mbp@samba.org>
+
+ * cases/empty.i: empty .i file
+
+2002-11-21 17:05 Martin Pool <mbp@samba.org>
+
+ * DEPENDENCIES: popt is now included in package
+
+2002-11-21 17:02 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc
+
+2002-11-21 12:04 Martin Pool <mbp@samba.org>
+
+ * doc/to-test.txt: Add list of trees that would be interesting to
+ test
+
+2002-11-20 11:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Add badly-behaved compiler drop-in for use in testing.
+
+2002-11-19 14:23 Martin Pool <mbp@samba.org>
+
+ * test/badcc: Add badly-behaved compiler drop-in for use in
+ testing.
+
+2002-11-19 13:11 Martin Pool <mbp@samba.org>
+
+ * NEWS, src/exec.c: * Fix waitpid() takes three options.
+ Required for Irix. (Michael Santy)
+
+2002-11-19 12:49 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove obsolete comment.
+
+2002-11-19 12:42 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: OK, now we use install-sh
+
+2002-11-19 09:09 Martin Pool <mbp@samba.org>
+
+ * analog/print_referers: Better line parser
+
+2002-11-19 08:57 Martin Pool <mbp@samba.org>
+
+ * analog/distcc.analog: Show more search words.
+
+2002-11-19 08:54 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Copy new EmptySource.py file into distribution
+
+2002-11-19 08:52 Martin Pool <mbp@samba.org>
+
+ * test/.cvsignore: Ignore .pyc files.
+
+2002-11-19 08:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: todo
+
+2002-11-18 13:05 Martin Pool <mbp@samba.org>
+
+ * analog/report/.cvsignore: Ignore built files
+
+2002-11-18 13:03 Martin Pool <mbp@samba.org>
+
+ * NEWS, test/EmptySource.py, test/testdistcc.py: Add test case for
+ transmission of a zero-byte file.
+
+2002-11-18 13:01 Martin Pool <mbp@samba.org>
+
+ * configure: autoconf
+
+2002-11-16 12:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * analog/print_referers: Python script to print web referers
+
+2002-11-16 12:22 Martin Pool <mbp@samba.org>
+
+ * analog/distcc.analog: Get ready to include bar images in cvs
+
+2002-11-16 12:19 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version to 0.16cvs
+
+2002-11-16 12:18 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include Scenarios page
+
+2002-11-16 11:13 Martin Pool <mbp@samba.org>
+
+ * OLDNEWS, NEWS: roll over news
+
+2002-11-16 09:57 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac: Bump version to 0.14
+
+2002-11-15 18:10 Martin Pool <mbp@samba.org>
+
+ * contrib/distccd-init: distccd Debian init.d script contributed by
+ Jason Thomas. (Debian #161136)
+
+2002-11-15 18:07 Martin Pool <mbp@samba.org>
+
+ * NEWS: reformat only
+
+2002-11-15 18:07 Martin Pool <mbp@samba.org>
+
+ * NEWS: distccd Debian init.d script contributed by Jason Thomas.
+ (Debian #161136)
+
+2002-11-15 18:06 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include contrib files in distribution.
+
+2002-11-15 10:06 Martin Pool <mbp@samba.org>
+
+ * src/trace.h: Doc
+
+2002-11-14 14:09 Martin Pool <mbp@samba.org>
+
+ * NEWS: Make sure PreprocessPlainText_Case runs in the right
+ directory.
+
+2002-11-14 14:09 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: TODO (thanks Oscar)
+
+2002-11-14 14:00 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Make sure PreprocessPlainText_Case runs in
+ the right directory.
+
+2002-11-14 12:58 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac, NEWS: Test for wait4 and wait3, which are missing
+ on IRIX (Mike Santy)
+
+2002-11-13 08:46 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Fix parameter type (suggestion from Dimitri
+ Papadopoulos)
+
+2002-11-13 07:47 Martin Pool <mbp@samba.org>
+
+ * configure: autoconf
+
+2002-11-13 07:44 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, NEWS: Fix silly bug that caused HTML documentation
+ to be missing from the tarball
+
+2002-11-13 07:43 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version to 0.14
+
+2002-11-13 07:14 Martin Pool <mbp@samba.org>
+
+ * NEWS: Bump version to 0.14
+
+2002-11-13 07:11 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Take lock on localhost only when compiling locally,
+ not for all compilations.
+
+2002-11-13 07:03 Martin Pool <mbp@samba.org>
+
+ * OLDNEWS, NEWS: Roll over news
+
+2002-11-13 07:01 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Remove dead code.
+
+2002-11-13 06:02 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version to 0.13.1cvs
+
+2002-11-12 18:40 Martin Pool <mbp@samba.org>
+
+ * README: Update README
+
+2002-11-12 18:38 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac: Prepare for 0.13 release
+
+2002-11-12 18:34 Martin Pool <mbp@samba.org>
+
+ * NEWS: Prepare for release.
+
+2002-11-12 18:25 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: More ComfyChair merges.
+
+2002-11-12 18:24 Martin Pool <mbp@samba.org>
+
+ * configure: autoconf
+
+2002-11-12 18:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: If popt is missing and not specified, get it
+
+2002-11-12 18:14 Martin Pool <mbp@samba.org>
+
+ * configure.ac: If popt is missing and not specified, get it
+
+2002-11-12 18:11 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: doh
+
+2002-11-12 18:10 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Clean popt, binaries, and testtmp from "clean"
+ target.
+
+2002-11-12 17:53 Martin Pool <mbp@samba.org>
+
+ * NEWS: Merge tpot's comfychair patch
+
+2002-11-12 17:47 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure, configure.ac, src/config.h.in: Add config
+ options for included popt
+
+2002-11-12 17:39 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Add --with-included-popt option
+
+2002-11-12 17:37 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Make 'all' the default
+
+2002-11-12 17:36 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include other necessary files in distribution
+
+2002-11-12 17:33 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Clean up some Makefile targets
+
+ Remove GNU makeisms
+
+ Include popt in tarball
+
+2002-11-12 17:17 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Make MissingCompiler_Case actually test what
+ it's meant to test.
+
+ Doc.
+
+2002-11-12 17:11 Martin Pool <mbp@samba.org>
+
+ * NEWS: Update news
+
+2002-11-12 17:08 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add new exit codes.
+
+ Bump version to 0.13.
+
+2002-11-12 17:03 Martin Pool <mbp@samba.org>
+
+ * src/: exitcode.h, exec.c: Add EXIT_COMPILER_MISSING
+
+2002-11-12 16:28 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Doc
+
+2002-11-12 08:16 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Fix prototypes
+
+2002-11-08 18:51 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Doc
+
+2002-11-08 18:50 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * cases/: cpp-set-path.c, foo.h, hello.c: Add small files for
+ exploring gcc behaviour
+
+2002-11-05 05:47 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: BSD needs signal.h. Thanks to Ajay Agrawalla.
+
+2002-11-01 19:12 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: MissingCompiler_Case: Fix function name
+
+2002-11-01 19:11 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: dcc_accept_job: Fix little prototype consistency
+ mistake
+
+2002-11-01 19:08 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc
+
+2002-11-01 19:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: io.c, rpc.c: Use error codes more consistently
+
+2002-11-01 19:06 Martin Pool <mbp@samba.org>
+
+ * src/exitcode.h: Add EXIT_TRUNCATED and EXIT_PROTOCOL_ERROR
+
+2002-11-01 19:05 Martin Pool <mbp@samba.org>
+
+ * src/: exec.c, exec.h: Add new utilities: dcc_reset_signal, and
+ dcc_setpgid
+
+ Doc
+
+2002-11-01 19:03 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Better doc and messages
+
+2002-11-01 19:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/bulk.c: Tidyup
+
+2002-11-01 18:58 Martin Pool <mbp@samba.org>
+
+ * README: Mention DISTCC_LOG and possible future ssh support
+
+2002-11-01 18:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * samples/: bad.c, badcpp.c, hello.c: Add small sample source files
+
+2002-11-01 17:54 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/daemon.c: Doc
+
+2002-10-31 13:40 Martin Pool <mbp@samba.org>
+
+ * NEWS: More news
+
+2002-10-31 13:28 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add TARGET_ROOT Makefile variable for installation,
+ when building binary packages.
+
+2002-10-31 13:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/tempfile.c: Show trace message when temporary files are
+ deleted
+
+2002-10-31 13:11 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.h: Define true and false for clarity
+
+2002-10-31 12:33 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include autogen.sh in dist
+
+2002-10-31 12:32 Martin Pool <mbp@samba.org>
+
+ * configure.ac, src/distcc.c: Doc
+
+2002-10-31 12:32 Martin Pool <mbp@samba.org>
+
+ * news.emacs: No tabs please
+
+2002-10-21 20:33 Martin Pool <mbp@samba.org>
+
+ * analog/distcc.analog: Exclude distcc.samba.org from referrer
+ calculations
+
+2002-10-18 16:45 Martin Pool <mbp@samba.org>
+
+ * DEPENDENCIES: Add URL for popt
+
+2002-10-18 11:58 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note Makefile fixes
+
+2002-10-18 11:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Check that programs have been built before trying to
+ install them
+
+2002-10-18 11:53 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Put back pkgdoc_DOCS, which somehow got lost
+
+ Distribute pkgdocs as well
+
+2002-10-18 11:46 Martin Pool <mbp@samba.org>
+
+ * aclocal.m4, configure: Run autoconf
+
+2002-10-18 11:45 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * README.popt: Start adding included popt
+
+2002-10-18 11:38 Martin Pool <mbp@samba.org>
+
+ * README.packaging, Makefile.in: Add note to packagers
+
+2002-10-18 11:29 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, configure.ac: Remove reference to src/Makefile.in
+
+2002-10-18 11:29 Martin Pool <mbp@samba.org>
+
+ * NEWS, src/Makefile.in: Get rid of Makefile recursion; build all
+ source from the toplevel Makefile
+
+2002-10-18 11:22 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Better message for object or output files
+
+2002-10-17 18:32 Martin Pool <mbp@samba.org>
+
+ * NEWS, test/testdistcc.py: Add test case for invocations like
+ "distcc -c test1.c test2.c".
+
+2002-10-17 18:22 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc
+
+2002-10-17 18:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Add test case for #error directive
+
+2002-10-17 13:40 Martin Pool <mbp@samba.org>
+
+ * NEWS, linuxdoc/distcc.sgml: More Gentoo notes from Ernesto
+
+2002-10-17 13:29 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml, NEWS: Add Gentoo documentation from Dean
+ Bailey
+
+2002-10-16 11:00 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, test/testdistcc.py: Split out tests for implied compiler
+ name into their own class
+
+2002-10-11 11:40 Martin Pool <mbp@samba.org>
+
+ * doc/lock-deadlock.txt: Doc deadlock observed in 0.13cvs
+
+2002-10-10 12:56 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include where.h
+
+2002-10-10 12:56 Martin Pool <mbp@samba.org>
+
+ * src/Makefile.in: Cope when there are no .d files
+
+2002-10-10 12:52 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Clean up the dist targets; include new patches
+
+2002-10-10 12:33 Martin Pool <mbp@samba.org>
+
+ * packaging/SuSE/init.d/distcc, NEWS: SuSE init.d script from
+ Brandon Forehand
+
+2002-10-10 11:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Add FIXME
+
+2002-10-10 00:33 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Doc
+
+2002-10-07 23:13 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Add trace
+
+2002-10-07 23:03 Martin Pool <mbp@samba.org>
+
+ * src/lock.c: Fix parameters for fcntl locks
+
+2002-10-07 23:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/Makefile.in: Include generated dependencies
+
+2002-10-07 18:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Nicer handling of ^C while running tests: print "INTERRUPT"
+ and terminate the whole test
+
+2002-10-07 14:36 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: New runCmdNoWait function needs argument as
+ string, not list
+
+2002-10-07 14:28 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, src/dopt.c, src/dparent.c, src/opt.h: Add --no-detach
+ option
+
+2002-10-07 13:52 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, OLDNEWS, configure, configure.ac: Advance version to
+ 0.13cvs
+
+2002-10-07 12:39 Martin Pool <mbp@samba.org>
+
+ * NEWS, aclocal.m4, configure, configure.ac: Bump version to 0.12
+
+2002-10-07 12:34 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Doc
+
+2002-10-07 12:29 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Bump to version 0.12
+
+2002-10-07 12:16 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Note on adaptive scheduling
+
+2002-10-07 11:35 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Doc
+
+2002-10-07 11:15 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Doc about handling host list.
+
+2002-10-07 11:04 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add note about performance test suite.
+
+2002-10-06 21:37 Martin Pool <mbp@samba.org>
+
+ * aclocal.m4, configure, configure.ac: Bump version to 0.12cvs
+
+2002-10-04 11:53 Martin Pool <mbp@samba.org>
+
+ * NEWS: foo
+
+2002-10-02 15:03 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Add fixme
+
+2002-10-02 14:55 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Add fixme
+
+2002-10-02 13:03 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Note about starting the daemon
+
+2002-10-02 12:47 Martin Pool <mbp@samba.org>
+
+ * doc/irc/: slashnet-distcc-20020919.txt,
+ slashnet-distcc-20021002.txt: Check in IRC logs
+
+2002-09-30 23:06 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, src/arg.c, test/testdistcc.py: Add tests for "gcc -S -o -
+ foo.c"
+
+2002-09-30 14:04 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Update version to 0.11
+
+2002-09-30 14:00 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Remove done TODO
+
+2002-09-30 13:46 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add roadmap
+
+2002-09-27 14:50 Martin Pool <mbp@samba.org>
+
+ * NEWS, src/arg.c: Handle "gcc -S foo.c -o -", which ought to write
+ assembly to stdout.
+
+2002-09-27 14:20 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Add fixme
+
+2002-09-27 14:03 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add results page
+
+2002-09-27 13:55 Martin Pool <mbp@samba.org>
+
+ * survey.txt: Add qn about distcc version
+
+2002-09-26 16:19 Martin Pool <mbp@samba.org>
+
+ * NEWS, OLDNEWS: Roll over NEWS
+
+2002-09-25 16:36 Martin Pool <mbp@samba.org>
+
+ * src/implicit.c: Doc
+
+2002-09-25 11:54 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure, configure.ac: Bump version to 0.11
+
+2002-09-25 11:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Include patches in distributed tarball
+
+2002-09-25 11:37 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: GNU Info can't handle having two sections
+ with the same heading
+
+2002-09-24 18:18 Martin Pool <mbp@samba.org>
+
+ * NEWS, src/strip.c: Fix (non-exploitable) buffer overrun bug.
+
+2002-09-23 22:47 Martin Pool <mbp@samba.org>
+
+ * NEWS: Update news
+
+2002-09-23 22:31 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/strip.c: Strip -MF -MT -MQ options that are followed by a
+ filename
+
+2002-09-23 22:24 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Add support for gcc-3.2 new -M options (-MG, etc)
+
+2002-09-23 15:25 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Update todo list.
+
+ Add section discussing ccache and distcc
+
+2002-09-23 15:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * doc/scheduling.txt: More notes
+
+2002-09-20 12:37 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc
+
+2002-09-20 11:39 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Doc
+
+2002-09-20 10:14 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2002-09-19 00:33 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Mode on received files should be 0666&~umask
+
+2002-09-19 00:06 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc
+
+2002-09-18 22:58 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc
+
+2002-09-18 21:36 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: distcc.c, h_scanargs.c, implicit.c, implicit.h: Reduce
+ too-long function name
+
+2002-09-18 16:42 Martin Pool <mbp@samba.org>
+
+ * src/implicit.c: Doc.
+
+2002-09-18 16:39 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add implicit linker test: "distcc testtmp.o
+ -o testtmp"
+
+2002-09-18 16:36 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Fix doc.
+
+2002-09-18 13:29 Martin Pool <mbp@samba.org>
+
+ * NEWS: Release name
+
+2002-09-18 10:45 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: Add results on building inside VMWare
+
+2002-09-17 18:49 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Doc.
+
+2002-09-17 13:59 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: resolv.h might need sys/types.h on BSD?
+
+2002-09-17 13:58 Martin Pool <mbp@samba.org>
+
+ * src/implicit.c: Might need sys/types.h on BSD?
+
+2002-09-16 18:14 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Fix docs
+
+2002-09-16 11:02 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Upload "tested" page
+
+2002-09-16 11:01 Martin Pool <mbp@samba.org>
+
+ * README: Update readme text
+
+2002-09-14 19:02 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: Cope without hstrerror(). Thanks to Richard
+ Zidlicky
+
+2002-09-14 18:59 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/srvnet.c: Cope without socklen_t. Thanks to Richard Zidlicky
+
+2002-09-14 18:53 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac, src/config.h.in: Check for socklen_t
+
+2002-09-14 18:46 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c, NEWS: Remove unnecessary sa_family_t cast.
+ (Richard Zidlicky)
+
+2002-09-14 13:35 Martin Pool <mbp@samba.org>
+
+ * NEWS: Doc
+
+2002-09-14 13:20 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac: Doc
+
+2002-09-14 10:52 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-09-14 10:38 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-09-14 10:11 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/lock.c, NEWS: Fix leakage of fds when trying to get a lock.
+
+2002-09-14 09:51 Martin Pool <mbp@samba.org>
+
+ * src/util.c: Doc.
+
+2002-09-14 09:50 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Move lock prototypes to lock.h
+
+2002-09-14 09:48 Martin Pool <mbp@samba.org>
+
+ * src/: lock.h, distcc.h: Rearrange prototypes
+
+2002-09-14 09:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Run daemon with --verbose
+
+2002-09-14 09:33 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: dcc_execvp doesn't return
+
+2002-09-14 09:32 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exec.c: dcc_inside_child: Take a lock on localhost for all
+ executed commands
+
+2002-09-14 09:08 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc
+
+2002-09-14 08:42 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc
+
+2002-09-14 08:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exec.c: dcc_redirect_fds: If any redirection fails, return
+ that error.
+
+2002-09-14 08:32 Martin Pool <mbp@samba.org>
+
+ * src/util.c: Needs exitcode.h
+
+2002-09-14 08:31 Martin Pool <mbp@samba.org>
+
+ * src/util.c: dcc_redirect_fd: Return EXIT_IO_ERROR not -1 for
+ error
+
+2002-09-14 08:30 Martin Pool <mbp@samba.org>
+
+ * src/util.c: dcc_redirect_fd: Remove calls to rs_fatal() in favour
+ of returning an error.
+
+2002-09-14 08:28 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Doc
+
+2002-09-14 08:26 Martin Pool <mbp@samba.org>
+
+ * OLDNEWS, NEWS: Roll over NEWS
+
+2002-09-14 08:25 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/serve.c: Doc
+
+2002-09-13 17:52 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Update libtool situation.
+
+2002-09-13 15:40 Martin Pool <mbp@samba.org>
+
+ * doc/ssh-notes.txt: Back-of-envelope calculations on using SSH.
+
+2002-09-13 13:08 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c: Doc.
+
+2002-09-13 13:02 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2002-09-13 12:58 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-09-13 12:55 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Remove done todo
+
+2002-09-13 12:29 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Remove done TODO
+
+2002-09-13 12:28 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Include new header file
+
+2002-09-13 12:27 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac: Bump version to 0.10.1
+
+2002-09-13 12:24 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Define W_EXITCODE with standard Unix meaning if it
+ is missing.
+
+2002-09-13 12:22 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure, configure.ac: Bump version to 0.10.1cvs
+
+2002-09-12 21:38 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml, src/distcc.c: Update for new syntax,
+ 'distcc -c hello.c'
+
+2002-09-12 21:28 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac: Bump version to 0.10.
+
+2002-09-12 21:20 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add release name.
+
+2002-09-12 21:00 Martin Pool <mbp@samba.org>
+
+ * NEWS: Strip emacs stuff.
+
+2002-09-12 20:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Doc.
+
+2002-09-12 14:30 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c: Note about difficulties of included files in .s and
+ .S.
+
+2002-09-12 12:14 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Update regexp to handle new "cannot
+ distribute" message format.
+
+2002-09-12 11:20 Martin Pool <mbp@samba.org>
+
+ * src/strip.c: Remove dumb overoptimization that mangled command
+ lines
+
+2002-09-12 11:17 Martin Pool <mbp@samba.org>
+
+ * src/strip.c, NEWS: Strip -M* from remote command lines as well.
+
+2002-09-12 11:13 Martin Pool <mbp@samba.org>
+
+ * configure.ac: If using gcc, use -MMD for dependency files.
+
+2002-09-12 11:03 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/implicit.c: Document design tradeoffs about implicit compiler
+ names.
+
+2002-09-12 10:34 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: distcc.c, arg.c: Remove done todos.
+
+2002-09-11 16:44 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, test/testdistcc.py: Add test case that uses -D on the
+ compiler command line
+
+2002-09-11 16:00 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add test cases for scanning -Mfoo
+
+2002-09-11 15:56 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add test case for arg stripping
+
+2002-09-11 15:37 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Doc
+
+2002-09-11 12:43 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc from tpot
+
+2002-09-09 22:44 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py, NEWS: Add a test for running 100 compilations
+ simultaneously.
+
+2002-09-09 18:56 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-09-09 18:31 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Doc.
+
+2002-09-09 16:13 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Log info message giving length after receiving files.
+
+2002-09-09 16:09 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Fix docs.
+
+2002-09-09 13:19 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Add todo
+
+2002-09-09 11:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Doc
+
+2002-09-08 18:13 Martin Pool <mbp@samba.org>
+
+ * NEWS, test/testdistcc.py: Test many simple compilations, in case
+ there is an infrequent error.
+
+2002-09-08 17:17 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Actually run CppError_Case
+
+2002-09-08 17:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/serve.c: Factor out code for trapping child exit into new
+ routine.
+
+2002-09-08 17:08 Martin Pool <mbp@samba.org>
+
+ * NEWS: update news
+
+2002-09-08 17:08 Martin Pool <mbp@samba.org>
+
+ * src/util.h: dcc_remove_if_exists: new function
+
+2002-09-08 17:07 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/tempfile.c: dcc_remove_if_exists: new common function
+
+2002-09-08 16:56 Martin Pool <mbp@samba.org>
+
+ * src/: util.h, exec.c: dcc_redirect_fd: Make name consistent.
+
+2002-09-08 16:56 Martin Pool <mbp@samba.org>
+
+ * src/util.c: dcc_redirect_fd: Make name consistent. Better error
+ messages.
+
+2002-09-08 15:54 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-09-08 15:01 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/serve.c: remove done todo
+
+2002-09-08 14:48 Martin Pool <mbp@samba.org>
+
+ * NEWS, test/testdistcc.py: Test compiler that succeeds without
+ reading input.
+
+2002-09-08 14:29 Martin Pool <mbp@samba.org>
+
+ * NEWS, test/testdistcc.py: Test handling of a file that causes a
+ preprocessor error.
+
+2002-09-08 14:19 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Don't upload Latte source.
+
+2002-09-06 14:39 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Add fixmes.
+
+2002-09-05 17:56 Martin Pool <mbp@samba.org>
+
+ * src/zip.c: Doc.
+
+2002-09-05 11:05 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: todo
+
+2002-09-05 10:07 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Doc waitstatus requirements.
+
+2002-09-04 16:14 Martin Pool <mbp@samba.org>
+
+ * NEWS: Modified patch from Alexandre Oliva to handle "distcc -c -S
+ testtmp.c".
+
+2002-09-04 16:11 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Test case for "distcc -c -S testtmp.c",
+ reported by Alexandre Oliva
+
+2002-09-04 16:08 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Modified patch from Alexandre Oliva to handle "distcc
+ -c -S testtmp.c".
+
+2002-09-04 15:53 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Test case for "distcc -c -S testtmp.c",
+ reported by Alexandre Oliva
+
+2002-09-04 13:48 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-09-04 13:46 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Notes on getloadavg()
+
+2002-09-04 12:59 Martin Pool <mbp@samba.org>
+
+ * doc/lzo-notes.txt: Notes on LZO compression
+
+2002-09-04 12:53 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: Use additional headers possibly required on
+ Solaris.
+
+2002-09-04 12:52 Martin Pool <mbp@samba.org>
+
+ * src/config.h.in: Check for -lresolv
+
+2002-09-04 12:51 Martin Pool <mbp@samba.org>
+
+ * NEWS: Solaris portability fixes
+
+2002-09-04 12:49 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * analog/.cvsignore: Ignore downloaded logs
+
+2002-09-04 12:40 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Patch from Dimitri PAPADOPOULOS-ORFANOS to fix
+ signedness warning.
+
+2002-09-04 10:06 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Note that server log messages stay on the
+ server.
+
+2002-09-03 18:13 Martin Pool <mbp@samba.org>
+
+ * NEWS, OLDNEWS: Roll over NEWS
+
+2002-09-03 18:12 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: troff fix
+
+2002-09-03 18:12 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Tiny troff fix
+
+2002-09-03 18:09 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Set version to 0.10cvs
+
+2002-09-03 18:02 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2002-09-03 18:00 Martin Pool <mbp@samba.org>
+
+ * analog/distcc.analog: Turn on weekly report.
+
+ Adjust floors.
+
+2002-09-03 17:49 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: analog-download: Get archived log files
+
+2002-09-03 15:45 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure, configure.ac: Bump version to 0.9
+
+2002-09-03 14:03 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: More results.
+
+2002-09-03 14:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Doc.
+
+2002-09-03 13:49 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Change .gz rule to compress "in-place"
+
+2002-09-03 13:48 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add new header files to list of things to
+ distribute!
+
+2002-09-03 13:40 Martin Pool <mbp@samba.org>
+
+ * news.emacs: emacs stub to set up NEWS file.
+
+2002-09-03 10:55 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add RFC for DNS SRV.
+
+2002-09-02 10:32 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: More todo notes.
+
+2002-09-02 09:21 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Apache logs have moved on new samba.org machine
+
+2002-09-02 09:17 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add analog-all target
+
+2002-09-02 07:38 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc.
+
+2002-09-02 07:16 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Set up a distcc client log file for all
+ tests.
+
+2002-09-02 07:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Doc recent changes
+
+2002-09-01 15:30 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Better message for the case where the compile command
+ exits without opening the fifo.
+
+2002-09-01 15:27 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Fix message
+
+2002-09-01 15:26 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: dcc_compile_remote: Split into smaller functions.
+
+2002-09-01 15:02 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Doc.
+
+2002-09-01 14:28 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add common routine for setting SIGPIPE handling.
+
+2002-09-01 14:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, src/exec.c: Set SIGPIPE handler back to default before
+ starting compiler tasks.
+
+2002-09-01 14:06 Martin Pool <mbp@samba.org>
+
+ * src/: clinet.c, serve.c, util.c, util.h: Add common routine for
+ setting SIGPIPE handling.
+
+2002-09-01 14:05 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Send distccd log to a file while testing --
+ easier for postmortems.
+
+2002-09-01 13:56 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-09-01 09:18 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-09-01 09:09 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-09-01 09:07 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: dcc_compile_remote: Better log message
+
+2002-09-01 09:06 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: dcc_accept_job: Better log message
+
+2002-09-01 09:05 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Fix silly parameter order bug.
+
+2002-09-01 08:55 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Get rid of cloexec, just close fds by hand.
+
+2002-09-01 08:52 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Typo
+
+2002-09-01 08:50 Martin Pool <mbp@samba.org>
+
+ * src/exec.c, NEWS: Close extra file descriptors before starting
+ the compiler.
+
+2002-09-01 08:46 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Set close-on-exec flags on listen and accepted
+ fds.
+
+2002-09-01 08:43 Martin Pool <mbp@samba.org>
+
+ * src/: util.c, util.h: set_cloexec_flag: new function
+
+2002-09-01 08:39 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc
+
+2002-09-01 08:38 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/daemon.c: tempfile.h: new header
+
+2002-09-01 08:34 Martin Pool <mbp@samba.org>
+
+ * NEWS: Doc mkfifo changes and BigAssFile_Case
+
+2002-09-01 08:31 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: rpc.h, bulk.h: bulk.h: new header
+
+2002-09-01 08:28 Martin Pool <mbp@samba.org>
+
+ * src/io.c: needs exitcode.h
+
+2002-09-01 08:27 Martin Pool <mbp@samba.org>
+
+ * src/: bulk.c, dparent.c, where.c: tempfile.h: new header
+
+2002-09-01 07:52 Martin Pool <mbp@samba.org>
+
+ * src/: tempfile.h, distcc.h: Split out tempfile.c routines into
+ their own header
+
+2002-09-01 07:49 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/io.c: dcc_close: make return code consistent (EXIT_IO_ERROR,
+ not errno)
+
+2002-09-01 07:39 Martin Pool <mbp@samba.org>
+
+ * src/exitcode.h: Add EXIT_IO_ERROR
+
+2002-09-01 07:37 Martin Pool <mbp@samba.org>
+
+ * src/io.c: dcc_close: log file descriptor correctly.
+
+2002-08-31 14:50 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Doc
+
+2002-08-31 14:45 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py, src/clinet.c: Doc
+
+2002-08-31 14:43 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Doc.
+
+ Make variables consistent.
+
+2002-08-31 14:31 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc.
+
+2002-08-31 14:23 Martin Pool <mbp@samba.org>
+
+ * src/: bulk.c, serve.c: Doc.
+
+2002-08-31 14:13 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/rpc.c: Doc.
+
+2002-08-31 13:58 Martin Pool <mbp@samba.org>
+
+ * src/: io.c, io.h: dcc_write_token: remove dead function
+
+2002-08-31 13:56 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Cleanup sendfile code somewhat.
+
+2002-08-31 13:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/rpc.c: Fix prototype
+
+ Use dcc_x_token_int in one case I missed before
+
+2002-08-31 12:41 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/io.c: Doc.
+
+2002-08-30 10:53 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Doc.
+
+2002-08-30 10:51 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Put cork in correct hole.
+
+2002-08-29 11:43 Martin Pool <mbp@samba.org>
+
+ * src/trace.c: Doc.
+
+2002-08-29 11:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, src/distcc.c: Message for completion of local cpp now gives
+ the correct hostname.
+
+2002-08-29 10:21 Martin Pool <mbp@samba.org>
+
+ * src/Makefile.in: Include $CFLAGS when linking so that profiling
+ works
+
+2002-08-29 10:17 Martin Pool <mbp@samba.org>
+
+ * NEWS: Display test names while they're running so that long tests
+ are easier to follow.
+
+2002-08-29 10:06 Martin Pool <mbp@samba.org>
+
+ * NEWS: Doc
+
+2002-08-29 10:05 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/dparent.c: Turn on signal handlers in parent. Why were they
+ off?
+
+2002-08-29 08:50 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add missing newline
+
+2002-08-29 08:50 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add test for compilation of a large file
+ (200,000 lines)
+
+2002-08-29 08:13 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Uncork sock before exiting.
+
+2002-08-29 06:50 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: quote
+
+2002-08-28 11:33 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc.
+
+2002-08-28 10:35 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/Makefile.in: Remove 'check' target because it must be run
+ from the parent
+
+2002-08-26 09:37 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Notes about Cygwin and LNX-BBC volunteers
+ into TODO list.
+
+2002-08-26 08:52 Martin Pool <mbp@samba.org>
+
+ * NEWS, configure, configure.ac: On FreeBSD, the sa_family_t type
+ is defined in <sys/socket.h> (Patch from Dennis Taylor)
+
+2002-08-26 08:48 Martin Pool <mbp@samba.org>
+
+ * aclocal.m4, configure, configure.ac, NEWS: Bump version to 0.9cvs
+
+2002-08-26 08:43 Martin Pool <mbp@samba.org>
+
+ * NEWS, OLDNEWS: roll over news
+
+2002-08-15 18:51 Martin Pool <mbp@samba.org>
+
+ * configure: autoconf
+
+2002-08-15 18:41 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Set version
+
+2002-08-15 14:39 Martin Pool <mbp@samba.org>
+
+ * NEWS: Ready for release.
+
+2002-08-15 12:56 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Tweak message
+
+2002-08-15 12:45 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/tempfile.c: Add headers, remove dead variable
+
+2002-08-15 12:03 Martin Pool <mbp@samba.org>
+
+ * src/filename.c: Doc
+
+2002-08-15 11:59 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure: Run autoconf
+
+2002-08-12 06:36 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Fix quoting.
+
+2002-08-10 15:28 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Doc.
+
+ Don't truncate lock files, open them with open().
+
+2002-08-10 15:26 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Doc.
+
+2002-08-10 15:19 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c, exec.c: Doc.
+
+2002-08-10 15:13 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Explain that we don't keep trying if we
+ fail to connect.
+
+2002-08-10 15:11 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc.
+
+2002-08-10 15:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/tempfile.c: dcc_getenv_bool(): new function to make behaviour
+ of DISTCC_VERBOSE etc consistent.
+
+2002-08-10 15:05 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c, dparent.c: Adjust error severity levels.
+
+2002-08-10 15:04 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/trace.c: Make notice messages have a "Notice: " prefix.
+
+2002-08-10 14:50 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Doc
+
+2002-08-10 14:39 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Put all scratch directories under 'testtmp'
+ to keep things tidy.
+
+2002-08-10 14:19 Martin Pool <mbp@samba.org>
+
+ * configure: Run autoconf
+
+2002-08-09 18:10 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Clearer text about env vars.
+
+2002-08-09 18:08 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add doc for DISTCC_SAVE_TEMPS
+
+2002-08-09 18:02 Martin Pool <mbp@samba.org>
+
+ * survey.txt: Better text.
+
+2002-08-09 17:59 Martin Pool <mbp@samba.org>
+
+ * survey.txt: Better text.
+
+2002-08-09 17:56 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Upload survey.
+
+2002-08-09 17:55 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Install survey.txt into docs
+
+2002-08-09 17:53 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * README: Add survey
+
+2002-08-09 17:33 Martin Pool <mbp@samba.org>
+
+ * src/survey.txt: Add survey
+
+2002-08-09 16:43 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add documentation for --no-fifo and --log-stderr.
+
+2002-08-09 16:29 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add documentation for --no-fifo and
+ --log-stderr.
+
+2002-08-09 16:15 Martin Pool <mbp@samba.org>
+
+ * NEWS: Show host specification syntax in --help
+
+2002-08-09 16:13 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Better --help message
+
+2002-08-09 16:11 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Show host specification syntax in --help
+
+2002-08-09 16:02 Martin Pool <mbp@samba.org>
+
+ * NEWS, OLDNEWS: Roll over NEWS
+
+2002-08-09 16:01 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Document that $DISTCC_HOSTS can now specify
+ ports.
+
+2002-08-08 12:27 Martin Pool <mbp@samba.org>
+
+ * contrib/dmake: Example script contributed by Luke Gorrie
+
+2002-08-05 23:33 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: There's always one.
+
+2002-08-05 23:25 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure, configure.ac: Bump version to 0.7; run autoconf.
+
+2002-08-05 23:19 Martin Pool <mbp@samba.org>
+
+ * README: Note that it probably works on Cygwin now.
+
+2002-08-05 23:07 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Another attempt at packaging and installing the
+ manual, but coping on machines without linuxdoc.
+
+2002-08-05 19:46 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-08-05 19:39 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Make 'all' the default target again.
+
+2002-08-05 19:28 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Fix packaging of Linuxdoc html.
+
+2002-08-05 19:22 Martin Pool <mbp@samba.org>
+
+ * NEWS: Set version for release.
+
+2002-08-05 15:44 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Make all latte HTML files depend on style.latte
+
+2002-08-05 15:15 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add todo
+
+2002-08-03 23:31 Martin Pool <mbp@samba.org>
+
+ * NEWS: Doc
+
+2002-08-03 23:29 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add release name
+
+2002-08-03 23:28 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note that documentation is shipped.
+
+2002-08-03 18:21 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: We could strip -D and -I from command
+ lines.
+
+2002-08-02 15:00 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Remove debugging stub
+
+2002-08-02 14:58 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Remove old message
+
+2002-08-02 14:56 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Don't try to link file which is expected not
+ to compile.
+
+2002-08-02 14:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: host:port syntax now supported.
+
+2002-08-02 14:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Doc
+
+2002-08-02 11:59 Martin Pool <mbp@samba.org>
+
+ * NEWS: --log-stderr
+
+2002-08-02 11:56 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, dopt.c, opt.h: Add --log-stderr option, intended
+ mainly for testing/debugging
+
+2002-08-02 11:39 Martin Pool <mbp@samba.org>
+
+ * .cvsignore: Ignore *.tmp
+
+2002-08-02 11:36 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Run all test cases within their own scratch
+ directory.
+
+2002-08-01 23:58 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: daemon.c, dparent.c, serve.c: dcc_accept_job: return
+ standard exit code
+
+2002-08-01 23:34 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, src/dopt.c, src/opt.h: Add --no-fifo option. Doesn't do
+ anything yet.
+
+2002-08-01 23:19 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Fix cvsplot target.
+
+2002-08-01 23:17 Martin Pool <mbp@samba.org>
+
+ * NEWS: Doc
+
+2002-08-01 23:12 Martin Pool <mbp@samba.org>
+
+ * contrib/distcc.sh: This file, contributed by Dimitri
+ PAPADOPOULOS-ORFANOS <papadopo@shfj.cea.fr> 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exec.c: Doc.
+
+2002-08-01 22:07 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Cygwin needs <signal.h> not <sys/signal.h>
+
+2002-08-01 21:44 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Cope without WCOREDUMP, which is missing on Cygwin.
+
+2002-08-01 21:34 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: daemon.c, dopt.c, opt.h: Make errors from command-line
+ options go to stderr.
+
+2002-08-01 17:14 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Remove file that's no longer in CVS from distro.
+
+2002-07-25 17:11 Martin Pool <mbp@samba.org>
+
+ * doc/results.txt: Add results file; not much here yet.
+
+2002-07-25 16:58 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure, configure.ac: Bump version
+
+2002-07-24 19:03 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * DEPENDENCIES, Makefile.in: Test case now requires python 2.2 for
+ proper unsetenv() semantics
+
+2002-07-24 18:50 Martin Pool <mbp@samba.org>
+
+ * NEWS: foo
+
+2002-07-24 18:49 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Avoid using asprintf() because it's missing on
+ Solaris
+
+2002-07-24 18:49 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exitcode.h: Doc
+
+2002-07-24 17:57 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: remove pid file if daemon exits on signal
+
+2002-07-24 17:55 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c, NEWS: Log pid even if running with --no-fork.
+ Remove pid file on exit.
+
+2002-07-24 14:39 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * OLDNEWS, NEWS: Roll over news
+
+2002-07-23 11:36 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add the start of an FAQ, and the AOSS4 slides.
+
+2002-07-22 16:45 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Doc.
+
+2002-07-12 11:46 Martin Pool <mbp@samba.org>
+
+ * configure: Rerun autoconf
+
+2002-07-12 11:44 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: "make install" doesn't imply install-linuxdoc
+
+2002-07-12 11:38 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: "make install" doesn't imply install-linuxdoc
+
+2002-07-12 11:34 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Correct message for "distcc --bad-option"
+
+2002-07-12 10:51 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Set version for release.
+
+2002-07-12 10:45 Martin Pool <mbp@samba.org>
+
+ * NEWS: Update news for release.
+
+2002-07-12 10:39 Martin Pool <mbp@samba.org>
+
+ * DEPENDENCIES: Clarify requirements for libpopt
+
+2002-07-12 10:37 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Install info files into the right directory
+
+2002-07-10 15:37 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Add page with current problems
+
+2002-07-09 12:06 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add target to run Linbot to check for broken links.
+
+2002-07-08 17:20 Martin Pool <mbp@samba.org>
+
+ * configure: autogen
+
+2002-07-08 17:18 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, distcc.h: Fix prototypes
+
+2002-07-08 17:17 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: distccd_show_usage: Document new options
+
+2002-07-08 17:16 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Document more distccd command-line options
+
+2002-07-08 17:00 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Syntax fix
+
+2002-07-08 16:57 Martin Pool <mbp@samba.org>
+
+ * DEPENDENCIES: Clarify dependencies
+
+2002-07-08 16:54 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Clarify that distcc returns the same value
+ as the compiler.
+
+2002-07-08 16:53 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Clarify description how to get environment
+ variables set properly.
+
+2002-07-08 16:50 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Doc.
+
+2002-07-07 22:23 Martin Pool <mbp@samba.org>
+
+ * NEWS: Works on FreeBSD?
+
+2002-07-07 22:12 Martin Pool <mbp@samba.org>
+
+ * src/Makefile.in: Have to respect $LDFLAGS so we can build on BSD.
+ Thanks Lauri!
+
+2002-07-07 22:11 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: SyntaxError_Case: Be less fussy about the
+ exact compiler error message
+
+2002-07-07 21:58 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Doc.
+
+2002-07-07 21:52 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: --version output has changed to include build
+ date and to just say "protocol 1"
+
+2002-07-07 21:46 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Temporary fix for "distcc -c hello.c"
+
+2002-07-07 21:43 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note about valgrind fix
+
+2002-07-07 21:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.h: Add missing prototype
+
+2002-07-07 19:40 Martin Pool <mbp@samba.org>
+
+ * src/: .cvsignore, h_argvtostr.c: Start new test case h_argvtostr
+
+2002-07-07 19:38 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Get ready to handle command lines with implied
+ compiler.
+
+2002-07-06 18:24 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc about the idea of handling "distcc -c hello.c"
+
+2002-07-06 18:11 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Remove old docs.
+
+2002-07-06 18:07 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Document --ping option.
+
+2002-07-06 18:00 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: The log now shows execution time; remove
+ this from the todo list.
+
+2002-07-06 16:49 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: daemon.c, dparent.c: Include build date/time in daemon
+ startup message
+
+2002-07-06 16:41 Martin Pool <mbp@samba.org>
+
+ * src/help.c: dcc_show_version: Include build date/time
+
+2002-07-06 16:32 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Notes about distcc with autoconf.Doc.
+
+2002-07-06 16:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Rename dcc_run_remote and dcc_build_locally to
+ dcc_compile_* to be consistent.
+
+2002-07-06 15:57 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Doc.
+
+2002-07-06 15:56 Martin Pool <mbp@samba.org>
+
+ * NEWS: dcc_exit: Show self and children's CPU time usage when
+ exiting.
+
+2002-07-06 15:54 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: More detail on handling of invalid
+ hostspecs.
+
+2002-07-06 15:46 Martin Pool <mbp@samba.org>
+
+ * src/util.c: dcc_exit: Show self and children's CPU time usage
+ when exiting.
+
+2002-07-05 17:12 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Note about libtool.
+
+2002-07-05 16:48 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add note about Makefiles which don't use
+ $(CC).
+
+2002-07-05 12:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/dparent.c: Need sys/ioctl.h
+
+2002-07-05 11:31 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac: Put docs in $prefix/share/doc
+
+2002-07-05 11:21 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Add "make showpaths" target to show where "make
+ install" will put things.
+
+2002-07-04 23:42 Martin Pool <mbp@samba.org>
+
+ * NEWS: Show CPU usage of compiler, cpp, etc
+
+2002-07-04 23:39 Martin Pool <mbp@samba.org>
+
+ * .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 <mbp@samba.org>
+
+ * Makefile.in: Fix "make install"
+
+2002-07-04 23:23 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Shush linuxdoc
+
+2002-07-04 23:10 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Doc.
+
+2002-07-04 23:06 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Better trace message.
+
+2002-07-04 23:06 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Doc.
+
+2002-07-04 23:05 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Fix inverted test on waitpid() result.
+
+ Doc.
+
+2002-07-04 23:01 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc (passing server errors back to client)
+
+2002-07-04 22:56 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Note about tcpwrappers.
+
+ Note that you can now set the server port number.
+
+2002-07-04 22:46 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Doc.
+
+2002-07-04 22:15 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: distclean removes config.log
+
+ Better maintainer-clean rules
+
+2002-07-04 22:12 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc.
+
+2002-07-04 22:03 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in, configure, configure.ac, linuxdoc/Makefile.in: Move
+ linuxdoc stuff into top-level Makefile too
+
+2002-07-04 21:31 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, configure, configure.ac, man/Makefile.in: Move man/
+ makefile into top level
+
+2002-07-03 23:11 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: New design of the web site, now using Latte.
+
+2002-07-03 20:31 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, analog/Makefile, analog/distcc.analog: Fiddle analog
+ Make rules; use jdresolve to do DNS resolution.
+
+2002-07-03 19:58 Martin Pool <mbp@samba.org>
+
+ * analog/.cvsignore: Ignore more stuff
+
+2002-07-03 16:57 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Further Makefile fudging
+
+2002-07-03 16:54 Martin Pool <mbp@samba.org>
+
+ * analog/.cvsignore: Ignore built files.
+
+2002-07-03 16:47 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Move web/latte rules into top-level Makefile.
+
+ Add more maintainer-clean rules
+
+2002-07-02 17:14 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: We now have proper C++ support, so s/C/C or
+ C++/ where appropriate.
+
+2002-07-02 17:11 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add bug.
+
+2002-07-01 19:39 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Clearer explanation of multiprocessor
+ scheduling.
+
+2002-07-01 19:36 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add CVS revision.
+
+2002-07-01 19:35 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add new error codes 105, 106
+
+2002-07-01 19:32 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Make titles consistent
+
+2002-07-01 19:31 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Remove redundant SMP section
+
+2002-07-01 19:27 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: "Leaky buckets" explanation of scheduling
+ algorithm.
+
+2002-07-01 09:38 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc
+
+2002-07-01 09:34 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Fix small syntax error
+
+2002-07-01 09:34 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Add --verbose option for daemon
+
+2002-07-01 09:23 Martin Pool <mbp@samba.org>
+
+ * NEWS: emacs-fu
+
+2002-07-01 09:22 Martin Pool <mbp@samba.org>
+
+ * NEWS: Reformat
+
+2002-07-01 09:15 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Improved quick-start guide.
+
+2002-06-30 22:01 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/: distcc.sgml: Better URL link.
+
+2002-06-30 21:59 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add link to ccache.
+
+2002-06-30 21:59 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Clarify bug about compilers which touch
+ local files.
+
+2002-06-30 21:58 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Clarify large-file message.
+
+2002-06-30 21:55 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Substantially improved section on
+ cross-compilation; give more details on how to use -b.
+
+2002-06-30 17:32 Martin Pool <mbp@samba.org>
+
+ * analog/distcc.analog: Show more referers
+
+2002-06-30 17:32 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Fix regexp for new error message.
+
+2002-06-30 17:31 Martin Pool <mbp@samba.org>
+
+ * src/: .cvsignore, Makefile.in, hosts.c, where.c: Change to new
+ hostspec parser
+
+2002-06-30 00:34 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: All tests now moved across to new framework
+
+2002-06-30 00:26 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Go back to purely object-based definitions of
+ test cases
+
+2002-06-30 00:02 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Fiddle with comfychair interface
+
+2002-06-30 00:00 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/dopt.c: Add --log-file option
+
+2002-06-29 23:58 Martin Pool <mbp@samba.org>
+
+ * src/: dparent.c, distcc.h: Make dcc_become_daemon private
+
+2002-06-29 23:57 Martin Pool <mbp@samba.org>
+
+ * analog/Makefile: Fix Makefile
+
+2002-06-29 23:28 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Make comfychair more OO.
+
+2002-06-29 23:14 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Refuse to run daemon as root.
+
+2002-06-29 23:13 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Doc.
+
+2002-06-29 23:00 Martin Pool <mbp@samba.org>
+
+ * doc/scheduling.txt: Notes on scheduling
+
+2002-06-29 16:39 Martin Pool <mbp@samba.org>
+
+ * src/OLDNEWS: Moved
+
+2002-06-29 01:49 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add more host parser cases.
+
+2002-06-29 01:44 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Correctly handle ssh tokens with command specified.
+
+2002-06-29 01:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * test/testdistcc.py: Better hosts parser test
+
+2002-06-29 01:37 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Fix parser bug in tcp with specified port.
+
+2002-06-29 01:32 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Doc.
+
+2002-06-29 01:25 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add test case for host specification parser.
+
+2002-06-29 01:24 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Hosts parser that works better with missing
+ components.
+
+2002-06-29 00:53 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Move more tests from pyunit to comfychair.
+ It's definitely more comfortable!
+
+2002-06-29 00:39 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Move more tests from pyunit to comfychair.
+ It's definitely more comfortable!
+
+2002-06-28 23:23 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: Also show numeric client address in connection
+ message
+
+2002-06-28 23:19 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/Makefile.in: Fix Makefile a bit more
+
+2002-06-28 23:15 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/Makefile.in: Fix Makefile
+
+2002-06-28 23:14 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Bump version.
+
+ Note about IPv6
+
+2002-06-28 23:03 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Doc.
+
+2002-06-28 23:01 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: When in no-fork mode, clean up files after each
+ job
+
+2002-06-28 22:59 Martin Pool <mbp@samba.org>
+
+ * src/Makefile.in: Drop sbin install target.
+
+2002-06-28 22:49 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Doc.
+
+2002-06-28 22:14 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * man/distcc.1: Add newline
+
+2002-06-28 21:50 Martin Pool <mbp@samba.org>
+
+ * man/distccd.1: Make a slightly more useful distccd manpage
+
+2002-06-28 21:41 Martin Pool <mbp@samba.org>
+
+ * analog/Makefile: Create report/ subdir if it doesn't exist.
+
+2002-06-28 21:40 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/Makefile.in: Create html/ subdir if it doesn't exist.
+
+2002-06-28 18:35 Martin Pool <mbp@samba.org>
+
+ * README: Make it clear that we do C++ too!
+
+ Try to explain relationship to gcc.
+
+2002-06-28 18:20 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: test_option_version: Handle host triples like
+ i386-unknown-freebsd4.4 (Claes Wallin)
+
+2002-06-28 16:57 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Doc.
+
+2002-06-28 16:53 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in: Add target to run old (currently broken) pyunit
+ tests
+
+2002-06-28 16:47 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: Add prototypes for hosts.c
+
+2002-06-28 16:33 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-06-28 16:19 Martin Pool <mbp@samba.org>
+
+ * src/: io.c: Better message.
+
+2002-06-28 16:13 Martin Pool <mbp@samba.org>
+
+ * src/Makefile.in: distccd ought to be in bin/; add rationale.
+
+2002-06-28 16:04 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/Makefile.in: Makefile must properly inherit configured
+ variables
+
+2002-06-28 16:01 Martin Pool <mbp@samba.org>
+
+ * man/Makefile.in: Remove old Makefile target to do with
+ pre-processed manpages
+
+2002-06-28 16:00 Martin Pool <mbp@samba.org>
+
+ * configure: foo
+
+2002-06-28 15:59 Martin Pool <mbp@samba.org>
+
+ * man/Makefile.in: distccd can be run by ordinary users, so
+ arguably belongs in section 1.
+
+2002-06-28 13:20 Martin Pool <mbp@samba.org>
+
+ * NEWS: Foo
+
+2002-06-28 13:18 Martin Pool <mbp@samba.org>
+
+ * README: Update README.
+
+2002-06-28 13:12 Martin Pool <mbp@samba.org>
+
+ * src/Makefile.in: Make directories before installing into them.
+
+2002-06-28 13:08 Martin Pool <mbp@samba.org>
+
+ * OLDNEWS: Merge news from 0.5 and make format consistent.
+
+2002-06-28 13:07 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Also install top-level documentation (e.g. README)
+
+2002-06-28 13:05 Martin Pool <mbp@samba.org>
+
+ * configure.ac, linuxdoc/Makefile.in, man/Makefile.in,
+ src/Makefile.in: More work on 'make install'
+
+2002-06-28 12:49 Martin Pool <mbp@samba.org>
+
+ * configure.ac, analog/distcc.analog, man/Makefile.in: More
+ automake removal, mostly for man/
+
+2002-06-28 12:48 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: If any sub-make fails, the top-level one should fail
+ too.
+
+2002-06-28 12:06 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, configure, configure.ac, linuxdoc/.cvsignore,
+ src/Makefile.in: More work on conversion away from automake
+
+2002-06-28 11:56 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/Makefile.in: Cleanup.
+
+ Only remove documents with maintainer-clean.
+
+2002-06-28 11:50 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/Makefile.in: Remove automake cruft.
+
+2002-06-28 11:42 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Merge fixup
+
+2002-06-28 11:41 Martin Pool <mbp@samba.org>
+
+ * patches/ChangeLog: kill changelogs
+
+2002-06-28 11:40 Martin Pool <mbp@samba.org>
+
+ * missing: remove automake cruft
+
+2002-06-28 11:38 Martin Pool <mbp@samba.org>
+
+ * .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 <mbp@samba.org>
+
+ * analog/: Makefile, distcc.analog: Add analog config.
+
+2002-06-27 22:45 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Also test hostspec parser.
+
+2002-06-27 22:43 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Better messages for EXIT_BAD_HOSTSPEC
+
+2002-06-27 22:41 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: dcc_parse_hosts() needs to return EXIT_BAD_HOSTSPEC
+ if no hosts are defined.
+
+2002-06-27 22:29 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Port more tests from PyUnit.
+
+2002-06-27 22:27 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Run tests against just-built executables.
+
+2002-06-27 22:12 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Add a slightly nontrivial test that we can
+ call --version on distcc and distccd.
+
+2002-06-27 21:59 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Don't run pyunit by default any more.
+
+2002-06-27 21:58 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Call comfy chair and pyunit tests
+
+2002-06-27 21:57 Martin Pool <mbp@samba.org>
+
+ * test/testdistcc.py: Start of conversion of Python tests to use
+ comfy chair
+
+2002-06-27 21:45 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, aclocal.m4: Start getting 'make check' working
+ without automake.
+
+2002-06-27 21:45 Martin Pool <mbp@samba.org>
+
+ * src/Makefile.in: Add non-automake rules to build test harnesses.
+
+2002-06-27 21:34 Martin Pool <mbp@samba.org>
+
+ * src/exitcode.h: Cleanup.
+
+2002-06-27 21:33 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, dparent.c: Fixes for removal of automake.
+
+2002-06-27 21:29 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: Add a new host specification string parser (not
+ called yet except from test case.)
+
+2002-06-27 21:28 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Reindent.
+
+ Emit trace messages when (un)corking sockets.
+
+2002-06-27 21:25 Martin Pool <mbp@samba.org>
+
+ * src/trace.h: Change rs_log_critical to rs_log_crit to be
+ consistent.
+
+2002-06-27 21:24 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: Doc
+
+2002-06-27 21:24 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/exitcode.h: Add additional exit codes: compiler crashed, out
+ of memory, bad hostspec.
+
+ Doc.
+
+2002-06-27 21:20 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Log an info message when standalone daemon starts,
+ including version.
+
+2002-06-27 21:20 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Log an info message when inetd daemon starts.
+
+2002-06-27 20:36 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac: Bump version to 0.5
+
+2002-06-27 20:32 Martin Pool <mbp@samba.org>
+
+ * NEWS: Add date, etc.
+
+2002-06-27 20:28 Martin Pool <mbp@samba.org>
+
+ * NEWS: Update NEWS
+
+2002-06-27 20:25 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Doc.
+
+2002-06-27 14:34 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac: Bump version.
+
+2002-06-27 13:46 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Set version.
+
+2002-06-26 21:58 Martin Pool <mbp@samba.org>
+
+ * autogen.sh, .cvsignore: ChangeLogs no longer stored in CVS.
+
+2002-06-26 21:56 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Handle EINTR from waitpid(), which is expected on
+ FreeBSD.
+
+2002-06-26 14:49 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Document EXIT_COMPILER_CRASHED.
+
+2002-06-26 14:44 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc.
+
+ Clearer message for remote compiler failure.
+
+2002-06-26 14:35 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure, configure.ac: Set version to 0.5rc1
+
+2002-06-26 14:19 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: t_exten, t_issource, t_version: Remove unused sh-based
+ tests.
+
+2002-06-22 03:58 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/trace.h: Doc.
+
+2002-06-21 19:48 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.h, h_hosts.c, hosts.c, where.c: Make everything
+ build again :)
+
+2002-06-21 19:46 Martin Pool <mbp@samba.org>
+
+ * src/hosts.c: Doc.
+
+2002-06-21 19:34 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/Makefile.in: Keep Makefile.in to allow building without
+ automake.
+
+2002-06-13 15:42 Martin Pool <mbp@samba.org>
+
+ * src/: trace.c, trace.h: Cope without varargs macros. All trace
+ routines are redirected to plain functions.
+
+2002-06-13 15:41 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, configure, src/config.h.in: Run autoconf
+
+2002-06-13 15:22 Martin Pool <mbp@samba.org>
+
+ * src/: h_exten.c, h_issource.c, h_scanargs.c: - cope without
+ varargs macros or __attribute__
+
+2002-06-13 15:14 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in, man/Makefile.in: run automake
+
+2002-06-13 15:01 Martin Pool <mbp@samba.org>
+
+ * README: Remove old performance numbers
+
+ Add supported platforms
+
+2002-06-13 15:00 Martin Pool <mbp@samba.org>
+
+ * patches/freebsd-mknod.diff: committed
+
+2002-06-13 14:58 Martin Pool <mbp@samba.org>
+
+ * NEWS, src/serve.c: FreeBSD mknod/mkfifo fix. (Claes Wallin)
+
+2002-06-13 14:54 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Doc.
+
+2002-06-12 02:44 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * packaging/: README.rpm, distcc.spec: RPM spec file from Ben
+ Elliston.
+
+2002-06-12 01:53 Martin Pool <mbp@samba.org>
+
+ * NEWS, OLDNEWS: Roll over NEWS
+
+2002-06-12 01:52 Martin Pool <mbp@samba.org>
+
+ * src/: bulk.c, distcc.h: Refactor bulk file transfer code in
+ preparation for gzip compressiong.
+
+2002-06-12 01:51 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Doc.
+
+2002-06-12 01:47 Martin Pool <mbp@samba.org>
+
+ * src/zip.c: Skeleton of zip compression. Not used yet.
+
+2002-06-12 01:39 Martin Pool <mbp@samba.org>
+
+ * man/: .cvsignore, Makefile.in: Keep files generated by automake,
+ but not by configure.
+
+2002-06-12 01:39 Martin Pool <mbp@samba.org>
+
+ * patches/freebsd-mknod.diff: Patch from Claes Wallin for FreeBSD.
+
+2002-06-12 01:37 Martin Pool <mbp@samba.org>
+
+ * man/.cvsignore: Ignore autoconf generated files.
+
+2002-06-12 01:36 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/.cvsignore: Ignore generated files.
+
+2002-06-09 02:58 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Bump version to 0.4
+
+2002-06-09 02:53 Martin Pool <mbp@samba.org>
+
+ * ChangeLog, contrib/ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog,
+ man/ChangeLog, patches/ChangeLog, src/ChangeLog: update
+ ChangeLogs
+
+2002-06-09 02:51 Martin Pool <mbp@samba.org>
+
+ * configure, linuxdoc/Makefile, linuxdoc/Makefile.am, man/Makefile,
+ man/Makefile.am, src/Makefile.in: Shuffle Makefiles
+
+2002-06-09 02:50 Martin Pool <mbp@samba.org>
+
+ * NEWS: Update news
+
+2002-06-09 02:40 Martin Pool <mbp@samba.org>
+
+ * src/Makefile.am: Add missing file
+
+2002-06-09 02:38 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Bump version to 0.4 Get rid of old test scripts Add
+ new Makefiles
+
+2002-06-09 02:34 Martin Pool <mbp@samba.org>
+
+ * NEWS: Doc.
+
+2002-06-09 02:32 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Hide --tasks from help since it does nothing.
+
+2002-06-09 02:09 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add section on SMP.
+
+2002-06-09 02:02 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Doc.
+
+2002-06-09 01:58 Martin Pool <mbp@samba.org>
+
+ * ChangeLog, contrib/ChangeLog, linuxdoc/ChangeLog,
+ patches/ChangeLog, src/ChangeLog: update changelog
+
+2002-06-09 01:50 Martin Pool <mbp@samba.org>
+
+ * src/dparent.c: Factor out code to collect children. Keep track
+ of how many are running.
+
+2002-06-09 01:44 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/Makefile.in: Run autoconf
+
+2002-06-09 01:42 Martin Pool <mbp@samba.org>
+
+ * NEWS: Doc
+
+2002-06-09 00:23 Martin Pool <mbp@samba.org>
+
+ * NEWS: .S and .s probably works now.
+
+2002-06-09 00:21 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Note that network errors will not be
+ detected.
+
+2002-06-09 00:05 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Doc.
+
+2002-06-09 00:03 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Server should log input and output filename too.
+
+2002-06-08 23:54 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c: Log input and output filename.
+
+2002-06-08 23:45 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/daemon.c: Lots of doc updates.
+
+2002-06-08 23:30 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Update docs.
+
+2002-06-08 23:24 Martin Pool <mbp@samba.org>
+
+ * NEWS: Note --pid-file.
+
+2002-06-08 23:10 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Add log message for stdin being a socket
+
+2002-06-08 23:09 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: open_socket_in: check that port number is
+ reasonable
+
+2002-06-08 22:54 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/: .cvsignore, Makefile: Fix Plucker filename
+
+2002-06-08 22:49 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/.cvsignore: Add Plucker-ized manual
+
+2002-06-08 22:48 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/Makefile: Better name for Plucker file.
+
+2002-06-08 22:40 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/util.h: Fix function attributes.
+
+2002-06-08 22:16 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: Clean up prototypes.
+
+2002-06-08 22:11 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Detect invocations like "distcc -c"
+
+2002-06-08 22:00 Martin Pool <mbp@samba.org>
+
+ * src/exitcode.h, linuxdoc/distcc.sgml: Renumber exit codes so that
+ 100 is a generic distcc failure.
+
+2002-06-08 21:44 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Fix help message for --pid-file
+
+2002-06-08 21:43 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, dopt.c, opt.h: Add --pid-file option to save
+ daemon's pid.
+
+2002-06-08 21:42 Martin Pool <mbp@samba.org>
+
+ * Makefile.in: Update autoconf stuff
+
+2002-06-08 14:24 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/Makefile: Don't build Linuxdoc by default because many
+ machines won't have the tools.
+
+2002-06-08 13:49 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Fix overzealous memory mistake.
+
+2002-06-07 16:17 Martin Pool <mbp@samba.org>
+
+ * ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, man/ChangeLog,
+ src/ChangeLog: auto-update ChangeLog
+
+2002-06-07 11:09 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Improve cross-compile section.
+
+2002-06-06 17:52 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Update doc: test suite has now been
+ written.
+
+2002-06-06 00:22 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/dopt.c: Fix mostly-harmless leaks of poptContext. Detected
+ by valgrind -- how cool!
+
+2002-06-05 18:53 Martin Pool <mbp@samba.org>
+
+ * NEWS, src/tempfile.c: Add support for TMPDIR. Not tested.
+
+2002-06-05 17:22 Martin Pool <mbp@samba.org>
+
+ * src/: bulk.c, daemon.c, distcc.c, exec.c, where.c: Doc.
+
+2002-06-02 15:02 Martin Pool <mbp@samba.org>
+
+ * NEWS: Test cvs
+
+2002-06-02 14:28 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/Makefile, man/Makefile: Fix recursive make targets
+
+2002-06-02 14:18 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/Makefile, man/Makefile: Fix recursive make targets
+
+2002-06-02 14:10 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, linuxdoc/Makefile: automake
+
+2002-06-02 14:09 Martin Pool <mbp@samba.org>
+
+ * src/: Makefile.in, daemon.c, exitcode.h: Start using consistent
+ return codes across all programs.
+
+2002-06-02 14:07 Martin Pool <mbp@samba.org>
+
+ * contrib/make-j: make-j script from Alexandre Oliva
+ <aoliva@redhat.com> for use with distcc
+
+ Tests which machines are up, and runs Make with concurrency set
+ appropriately.
+
+2002-06-02 13:59 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * autogen.sh: Don't configure from autogen.sh
+
+2002-06-02 13:54 Martin Pool <mbp@samba.org>
+
+ * Makefile.am, Makefile.in: Also descend into linuxdoc, pyunit and
+ man directories.
+
+2002-06-02 13:51 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: More documentation, especially about bugs.
+
+2002-06-02 13:50 Martin Pool <mbp@samba.org>
+
+ * NEWS, OLDNEWS: Roll over news.
+
+2002-05-31 16:36 Martin Pool <mbp@samba.org>
+
+ * configure, configure.ac: Apparently FreeBSD needs sys/types.h
+ before netinet/in.h. From Frerich Raabe.
+
+2002-05-31 16:20 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add distcc link.
+
+2002-05-31 16:10 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/Makefile: Move to distcc.samba.org.
+
+2002-05-31 16:09 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Manual is now current for 0.3
+
+2002-05-31 16:08 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/footer.html: Fix distcc homepage link.
+
+2002-05-30 08:31 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Documentation from ben
+
+2002-05-29 14:35 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: More notes from recent discussions.
+
+2002-05-29 14:21 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc.
+
+2002-05-28 23:11 Martin Pool <mbp@samba.org>
+
+ * ChangeLog, Makefile.am, Makefile.in, linuxdoc/ChangeLog,
+ src/ChangeLog: Commit Makefile rule
+
+2002-05-28 23:09 Martin Pool <mbp@samba.org>
+
+ * Makefile.am: Need to distribute ChangeLogs across directories
+
+2002-05-28 23:04 Martin Pool <mbp@samba.org>
+
+ * ChangeLog: Update ChangeLog from CVS
+
+2002-05-28 23:00 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, aclocal.m4, src/Makefile.in: autoconf
+
+2002-05-28 22:58 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, src/Makefile.in: update autoconf
+
+2002-05-28 22:58 Martin Pool <mbp@samba.org>
+
+ * src/NEWS: Moved to parent directory
+
+2002-05-28 22:56 Martin Pool <mbp@samba.org>
+
+ * NEWS: Go ahead and release.
+
+2002-05-28 22:38 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile.in, configure, src/Makefile.in: rerun autoconf
+
+2002-05-28 19:32 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Suggestion from Frerich to fix check for *bsd*.
+
+2002-05-28 15:38 Martin Pool <mbp@samba.org>
+
+ * src/.cvsignore: Ignore temp file.
+
+2002-05-28 15:29 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * aclocal.m4: Silly autoconf
+
+2002-05-28 14:24 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: .cvsignore, Makefile.in, config.h.in: Check in extra
+ autoconf-generated files.
+
+2002-05-28 14:17 Martin Pool <mbp@samba.org>
+
+ * src/timebuild: Very primitive script for timing tests.
+
+2002-05-28 13:52 Martin Pool <mbp@samba.org>
+
+ * src/: h_exten.c, h_issource.c: Additional fixes for
+ rs_program_name.
+
+2002-05-28 13:48 Martin Pool <mbp@samba.org>
+
+ * Makefile.in, configure, configure.ac, src/serve.c: BSD needs
+ sys/signal.h.
+
+2002-05-28 12:43 Martin Pool <mbp@samba.org>
+
+ * .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 <mbp@samba.org>
+
+ * ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, man/ChangeLog:
+ Regenerate ChangeLogs
+
+2002-05-28 12:28 Martin Pool <mbp@samba.org>
+
+ * src/: ChangeLog, daemon.c, distcc.c, trace.c, trace.h: Clean up
+ rs_program_name shmozlle
+
+2002-05-27 00:58 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: Doc
+
+2002-05-27 00:14 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Doc
+
+2002-05-26 01:44 Martin Pool <mbp@samba.org>
+
+ * .cvsignore, src/.cvsignore: Ignore extra garbage
+
+2002-05-26 01:38 Martin Pool <mbp@samba.org>
+
+ * configure.ac: Need to also look in sys/types.h for in_port_t on
+ BSD.
+
+2002-05-26 01:35 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS, src/serve.c: Ignore SIGPIPE in daemon as well as client.
+
+ Thanks to Ben Elliston.
+
+2002-05-26 01:21 Martin Pool <mbp@samba.org>
+
+ * configure.ac, src/clinet.c, NEWS: Try to cope without in_port_t.
+
+ Thanks to Luke Gorrie.
+
+2002-05-26 01:11 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * configure.ac, src/help.c: Ignore strange new automake variables,
+ just use PACKAGE and VERSION
+
+2002-05-26 00:47 Martin Pool <mbp@samba.org>
+
+ * NEWS: Fix Ian's name.
+
+2002-05-26 00:46 Martin Pool <mbp@samba.org>
+
+ * NEWS: M-/ strikes again :-)
+
+2002-05-26 00:42 Martin Pool <mbp@samba.org>
+
+ * src/io.c: If there are no corks on this computer, don't try to
+ use them.
+
+2002-05-26 00:32 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * autogen.sh: Don't say "make all", because on some platforms you
+ might really need gmake.
+
+2002-05-26 00:08 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * NEWS: Note help with automake
+
+2002-05-26 00:01 Martin Pool <mbp@samba.org>
+
+ * autogen.sh: Handle ChangeLog
+
+2002-05-25 23:57 Martin Pool <mbp@samba.org>
+
+ * src/.cvsignore: More test cases
+
+2002-05-25 23:55 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: Makefile.am, h_issource.c, t_issource: Add another test
+
+2002-05-25 19:23 Martin Pool <mbp@samba.org>
+
+ * configure.ac: chmod test files
+
+2002-05-25 18:57 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Recognize the .ii extension that ccache uses for
+ preprocessed C++ code.
+
+2002-05-25 18:50 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/GNUmakefile: This Makefile is no longer needed because we
+ have automake.
+
+2002-05-25 18:33 Martin Pool <mbp@samba.org>
+
+ * .cvsignore, src/.cvsignore: Ignore automake-generated files
+
+2002-05-25 16:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * .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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add GNU FDL stuff.
+
+2002-05-24 15:17 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Doc.
+
+2002-05-24 15:11 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * Makefile: Add always_ChangeLog target
+
+2002-05-24 13:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/NEWS: Support C++ compilation by correctly detecting
+ prefixes.
+
+2002-05-24 13:22 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Fix little syntax error.
+
+2002-05-24 13:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Fix SGML.
+
+2002-05-23 16:17 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Texinfo can't handle having two headings
+ with the same name.
+
+2002-05-23 16:12 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add explanation of special meaning of
+ "localhost" in DISTCC_HOSTS.
+
+ Move results around.
+
+2002-05-21 18:17 Martin Pool <mbp@samba.org>
+
+ * src/: NEWS, OLDNEWS: Roll over NEWS
+
+2002-05-21 18:10 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Set version to 0.2.99
+
+2002-05-21 17:20 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Doc.
+
+2002-05-20 16:00 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Fix SGML
+
+2002-05-20 15:57 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add section about libtool.
+
+ Add results for building glib-1.2.
+
+2002-05-20 14:38 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: linuxdoc/ subdir is no longer here.
+
+2002-05-20 14:30 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Cleaner CVS stuff.
+
+2002-05-20 14:26 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Cleaner CVS stuff.
+
+2002-05-20 14:25 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Better explanation of issues around SSH.
+
+2002-05-20 14:06 Martin Pool <mbp@samba.org>
+
+ * src/trace.c: Doc.
+
+2002-05-20 14:02 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Clarify handling of compiler error
+ messages.
+
+2002-05-20 13:54 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/.cvsignore: Better exclude specification
+
+2002-05-20 13:54 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/: Makefile, footer.html: Add HTML footer
+
+2002-05-20 13:46 Martin Pool <mbp@samba.org>
+
+ * Makefile, cvs2cl.ufile: Add top-level makefile
+
+2002-05-20 13:35 Martin Pool <mbp@samba.org>
+
+ * src/NEWS: News for something that happened last week!
+
+2002-05-20 13:23 Martin Pool <mbp@samba.org>
+
+ * src/HACKING: Cleanup
+
+2002-05-20 13:21 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/distcc.sgml: Add results.
+
+2002-05-19 18:09 Martin Pool <mbp@samba.org>
+
+ * linuxdoc/: .cvsignore, Makefile, distcc.sgml: Move directory
+
+2002-05-17 15:45 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Set version to 0.2
+
+2002-05-17 14:10 Martin Pool <mbp@samba.org>
+
+ * src/help.c: Add email address
+
+2002-05-17 14:09 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/daemon.c: Doc.
+
+2002-05-16 17:56 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * .cvsignore, src/GNUmakefile: Add a nice simple user manual
+
+2002-05-16 13:48 Martin Pool <mbp@samba.org>
+
+ * src/HACKING: Note about cpp performance.
+
+2002-05-15 23:13 Martin Pool <mbp@samba.org>
+
+ * src/HACKING: Doc.
+
+2002-05-15 18:19 Martin Pool <mbp@samba.org>
+
+ * src/: HACKING, tempfile.c, where.c: Doc.
+
+2002-05-15 17:45 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Better trace msg
+
+2002-05-15 17:44 Martin Pool <mbp@samba.org>
+
+ * man/.cvsignore: Ignore generated
+
+2002-05-15 17:44 Martin Pool <mbp@samba.org>
+
+ * doc/distcc-irc.txt: Rough notes from irc
+
+2002-05-15 17:38 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.h, tempfile.c, where.c: Use simple file locks to
+ spread work across hosts
+
+2002-05-15 17:23 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/HACKING: Scratch numbers on compression
+
+2002-05-15 15:57 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Use correct proto version
+
+2002-05-15 15:54 Martin Pool <mbp@samba.org>
+
+ * src/: bulk.c, distcc.c, io.h, rpc.h, serve.c: zlevel is passed
+ everywhere but ignored
+
+2002-05-15 15:51 Martin Pool <mbp@samba.org>
+
+ * src/: GNUmakefile, distcc.c, serve.c: Server accepts GZIP token
+
+2002-05-15 15:45 Martin Pool <mbp@samba.org>
+
+ * src/HACKING: Note about server-side error handling
+
+2002-05-15 15:42 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: distcc.c, distcc.h, where.c: Parse zlevel out of _HOSTS
+
+2002-05-15 15:27 Martin Pool <mbp@samba.org>
+
+ * src/: bulk.c, io.c, io.h: Factor out common methods of bulk
+ transfer
+
+2002-05-15 15:26 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Bump version
+
+2002-05-15 15:20 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Note about mtimes
+
+2002-05-15 15:13 Martin Pool <mbp@samba.org>
+
+ * src/bulk.c: Doc
+
+2002-05-15 15:10 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Set version to 1.0
+
+2002-05-15 15:09 Martin Pool <mbp@samba.org>
+
+ * .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 <mbp@samba.org>
+
+ * src/: GNUmakefile, bulk.c, rpc.c: Split out file transfer code
+
+2002-05-15 14:56 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Add quote
+
+2002-05-15 14:56 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Handle --help
+
+2002-05-15 14:56 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: Add more links
+
+2002-05-15 14:55 Martin Pool <mbp@samba.org>
+
+ * man/Makefile: Add PDF target
+
+2002-05-15 14:50 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Show environment variables in usage message for
+ distcc
+
+2002-05-13 13:30 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Add "install" target.
+
+2002-05-13 13:27 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Fix dumb "break" mistake in option parsing.
+
+2002-05-06 09:10 Martin Pool <mbp@samba.org>
+
+ * src/dopt.c: Add --nice option
+
+2002-05-05 19:23 Martin Pool <mbp@samba.org>
+
+ * src/: GNUmakefile, daemon.c, distcc.h, dopt.c: Start adding
+ daemon command-line handling
+
+2002-05-05 19:22 Martin Pool <mbp@samba.org>
+
+ * src/trace.c: Better formatting when not using the pid.
+
+2002-05-05 19:21 Martin Pool <mbp@samba.org>
+
+ * README: Note library dependencies
+
+2002-05-02 15:17 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: More stuff.
+
+2002-05-02 14:25 Martin Pool <mbp@samba.org>
+
+ * man/distcc.1: More manpage updates.
+
+2002-05-02 13:26 Martin Pool <mbp@samba.org>
+
+ * man/: Makefile, distcc.1: Add the start of a man page.
+
+2002-05-01 12:42 Martin Pool <mbp@samba.org>
+
+ * src/io.c: "i've always wanted to use sendfile(), but never had a
+ reason until now"
+
+2002-05-01 12:31 Martin Pool <mbp@samba.org>
+
+ * README: Add author name.
+
+2002-04-30 20:48 Martin Pool <mbp@samba.org>
+
+ * README, src/README: Rearrange
+
+2002-04-30 18:15 Martin Pool <mbp@samba.org>
+
+ * src/: exec.c: Doc.
+
+2002-04-30 18:06 Martin Pool <mbp@samba.org>
+
+ * src/serve.c: Make file sizes correct even if compilation fails.
+
+2002-04-30 18:05 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.h, serve.c, srvnet.c: daemon logs client names
+
+2002-04-30 18:04 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Doc
+
+2002-04-30 17:50 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: serve.c, exec.c: Log job completion
+
+2002-04-30 17:45 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Log opening of port
+
+2002-04-30 17:38 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: If compiler finished OK, that's an INFO level message
+
+2002-04-30 17:34 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c, rpc.c, rpc.h, serve.c: Record size of files
+ transferred
+
+2002-04-30 17:31 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, trace.c, trace.h: More flexible trace formatting
+
+2002-04-30 17:22 Martin Pool <mbp@samba.org>
+
+ * src/trace.c: Fix stderr logging.
+
+2002-04-30 17:19 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, trace.c, trace.h: distccd logs to syslog/daemon.
+
+2002-04-30 17:13 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/srvnet.c: Delete dead code
+
+2002-04-30 15:46 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Don't ever just exit
+
+2002-04-30 15:45 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Don't abort if accept() fails.
+
+2002-04-30 15:29 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Make cleanup code reusable.
+
+2002-04-30 15:28 Martin Pool <mbp@samba.org>
+
+ * src/srvnet.c: Need to listen() on socket before accept()
+
+2002-04-30 15:20 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Fix silly pointer bug
+
+2002-04-30 15:17 Martin Pool <mbp@samba.org>
+
+ * src/: GNUmakefile, daemon.c, srvnet.c, util.h: Really simple
+ standalone mode.
+
+2002-04-30 14:43 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/io.c: Cast from gcc warning
+
+2002-04-30 14:41 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Trace
+
+2002-04-30 14:22 Martin Pool <mbp@samba.org>
+
+ * src/: README, distcc.c: Add DISTCC_VERBOSE env var
+
+2002-04-30 14:09 Martin Pool <mbp@samba.org>
+
+ * src/rpc.c: Add necessary cast, thanks to gcc.
+
+2002-04-30 14:09 Martin Pool <mbp@samba.org>
+
+ * src/HACKING: Doc.
+
+2002-04-30 14:04 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: daemon.c, distcc.c: Don't send the .o file unless
+ compilation succeeded.
+
+2002-04-30 13:54 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: If no build hosts are set, just run here.
+
+2002-04-30 13:53 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Add targets to run cflow.
+
+2002-04-30 13:50 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc.
+
+2002-04-30 13:02 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Do clean up temporary files.
+
+2002-04-30 13:00 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Better help message.
+
+2002-04-30 12:58 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Turn on more warnings
+
+2002-04-30 12:54 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Fix gcc warning.
+
+2002-04-29 20:08 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Note from Huxley
+
+2002-04-29 15:28 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Doc.
+
+2002-04-29 15:23 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Doc.
+
+2002-04-29 15:20 Martin Pool <mbp@samba.org>
+
+ * src/: clinet.c, distcc.c: Doc.
+
+2002-04-29 15:17 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Handle EPIPE as a regular error
+
+2002-04-29 14:52 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Clean up temp files if build is successful
+
+2002-04-29 14:50 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Docs about better performance.
+
+2002-04-29 14:45 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Docs about better methods of choosing compile hosts.
+
+2002-04-28 23:46 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c, clinet.c, daemon.c, io.c, where.c: Clean up
+
+2002-04-28 23:43 Martin Pool <mbp@samba.org>
+
+ * src/README: Notes on building the kernel
+
+2002-04-28 23:05 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Change version to 0.1cvs
+
+2002-04-28 22:50 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Better messages
+
+2002-04-28 22:50 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Better quoting for commands
+
+2002-04-28 22:45 Martin Pool <mbp@samba.org>
+
+ * src/: README, distcc.c, distcc.h, exec.c: Make the magic name
+ localhost
+
+ Better execution messages
+
+2002-04-28 22:32 Martin Pool <mbp@samba.org>
+
+ * src/: README, distcc.c: Make the magic name LOCALHOST, not LOCAL
+
+2002-04-28 22:30 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/io.c: Fix headers
+
+2002-04-28 20:54 Martin Pool <mbp@samba.org>
+
+ * src/README: Add title.
+
+2002-04-28 20:41 Martin Pool <mbp@samba.org>
+
+ * src/: clinet.c, daemon.c, distcc.h, io.c, io.h: Also cork
+ response from the server
+
+2002-04-28 20:41 Martin Pool <mbp@samba.org>
+
+ * src/trace.c: Larger log buffer for chunky gcc lines
+
+2002-04-28 20:37 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Cork and uncork socket around request.
+
+2002-04-28 20:36 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Cope properly when not running cpp.
+
+2002-04-28 20:35 Martin Pool <mbp@samba.org>
+
+ * src/: clinet.c, distcc.h: Add code to cork a socket
+
+2002-04-28 20:26 Martin Pool <mbp@samba.org>
+
+ * src/: exec.c, rpc.c: Better trace
+
+2002-04-28 20:15 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, distcc.c: Fiddle debug and tempfile stuff to
+ better support debugging.
+
+2002-04-28 20:13 Martin Pool <mbp@samba.org>
+
+ * src/README: Some initial numbers on performance building rsync.
+
+2002-04-28 19:38 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Fix messages
+
+2002-04-28 19:31 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Quieten trace
+
+2002-04-28 19:27 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/io.c: Fix nasty bug that caused us to read much more than we
+ wanted.
+
+2002-04-28 19:16 Martin Pool <mbp@samba.org>
+
+ * src/rpc.c: More trace
+
+2002-04-28 19:16 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Fix tempfile names.
+
+2002-04-28 19:07 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Better messages.
+
+2002-04-28 19:04 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Typo.
+
+2002-04-28 19:03 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Better error message.
+
+2002-04-28 19:02 Martin Pool <mbp@samba.org>
+
+ * src/: clinet.c, distcc.c, distcc.h: Actually try to use a random
+ remote host.
+
+2002-04-28 18:58 Martin Pool <mbp@samba.org>
+
+ * src/where.c: Add routine to pick a random build host
+
+2002-04-28 18:58 Martin Pool <mbp@samba.org>
+
+ * src/trace.h: Add rs_log_warning
+
+2002-04-28 18:57 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Quieten warning
+
+2002-04-28 18:55 Martin Pool <mbp@samba.org>
+
+ * src/README: Doc
+
+2002-04-28 17:02 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: distcc.c, rpc.c, rpc.h: Receive and display remote
+ stdout/stderr.
+
+2002-04-28 16:52 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Capture and send compiler's stdout/stderr.
+
+2002-04-28 16:47 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Show proto ver in version info.
+
+2002-04-28 15:19 Martin Pool <mbp@samba.org>
+
+ * src/: clinet.c, distcc.c, daemon.c: Doc.
+
+2002-04-28 15:15 Martin Pool <mbp@samba.org>
+
+ * src/: GNUmakefile, where.c: Add where.c
+
+2002-04-28 15:14 Martin Pool <mbp@samba.org>
+
+ * src/: README, distcc.c, distcc.h, exec.c: Run cpp in background
+ while trying to connect.
+
+2002-04-28 15:13 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Should use CFLAGS to link too
+
+2002-04-28 13:22 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Better message when compiler fails.
+
+2002-04-28 13:19 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c, distcc.h, exec.c: Get ready for async subcommands
+
+2002-04-28 13:14 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Better message
+
+2002-04-28 13:12 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/tempfile.c: Check permissions on temporary dir
+
+2002-04-28 12:33 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Automatically set up temp dir when needed
+
+ Fix temp dir permissions
+
+2002-04-28 12:32 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Turn off dynamic dependencies for the moment
+
+2002-04-28 12:29 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/trace.h: Remove broken non-gcc stuff
+
+2002-04-28 12:15 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Add SPLINT target
+
+2002-04-28 12:08 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.h, tempfile.c: Add routine to cleanup temporary
+ files.
+
+2002-04-28 12:03 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, distcc.c, distcc.h, io.c, tempfile.c: Better
+ (secure?) temporary name routine.
+
+2002-04-28 12:03 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Doc
+
+2002-04-25 20:03 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Doc.
+
+2002-04-25 20:00 Martin Pool <mbp@samba.org>
+
+ * src/io.c: Use a larger copy buffer.
+
+2002-04-25 19:59 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Be quiet by default
+
+2002-04-25 19:32 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c, daemon.c: Fix filename substitution code.
+
+2002-04-25 19:26 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Fix message
+
+2002-04-25 19:24 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, exec.c, io.c, io.h: Split out code for reading
+ length-preceded strings.
+
+2002-04-25 19:11 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Properly nul-terminate argv strings
+
+2002-04-25 19:07 Martin Pool <mbp@samba.org>
+
+ * src/distcc.h: Fix header
+
+2002-04-25 19:05 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: arg.c, distcc.h: Drop dead code
+
+2002-04-25 18:57 Martin Pool <mbp@samba.org>
+
+ * src/rpc.c: Better log
+
+2002-04-25 18:56 Martin Pool <mbp@samba.org>
+
+ * src/: io.h, rpc.c: Rename to dcc_r_token
+
+2002-04-25 18:54 Martin Pool <mbp@samba.org>
+
+ * src/io.c: IO errors need not cause us to abort.
+
+2002-04-25 18:52 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Generate our slightly more proper temporary names.
+
+2002-04-25 18:51 Martin Pool <mbp@samba.org>
+
+ * src/trace.h: Add rs_log_critical convenience.
+
+2002-04-25 18:48 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/trace.c: Show pid in log messages.
+
+2002-04-25 18:43 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c, distcc.h: Add dcc_set_input
+
+2002-04-25 18:37 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/arg.c: Better log messages from arg scanner
+
+2002-04-25 18:18 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Actually go ahead and run cpp if necessary.
+
+2002-04-25 18:07 Martin Pool <mbp@samba.org>
+
+ * src/exec.c: Doc.
+
+2002-04-25 18:06 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, distcc.h, exec.c: Cleanup dcc_run_child
+
+2002-04-25 18:01 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c, distcc.h, exec.c: Show whole command being executed.
+
+2002-04-25 17:50 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: log message
+
+2002-04-25 17:42 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Sketchy routines to build temporary filenames
+
+2002-04-25 17:38 Martin Pool <mbp@samba.org>
+
+ * src/tempfile.c: Sketchy routines to build temporary filenames
+
+2002-04-25 17:38 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Get closer to running cpp locally
+
+2002-04-25 17:37 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c, distcc.h: Add more argv[] utilities
+
+2002-04-25 17:09 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Fix harmless glitch. Better message.
+
+2002-04-25 17:07 Martin Pool <mbp@samba.org>
+
+ * src/util.c: Fix inverted sense in str_startswith
+
+2002-04-25 16:59 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c, daemon.c, distcc.c, distcc.h, exec.c: Prepare to run
+ preprocessor on client
+
+2002-04-25 15:46 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Better handle the case of being passed a
+ non-preprocessed file.
+
+2002-04-25 14:12 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Fix headers.
+
+2002-04-25 14:12 Martin Pool <mbp@samba.org>
+
+ * src/: util.c, util.h: Add str_startswith
+
+2002-04-25 14:08 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c, distcc.h: Start adding support for running cpp
+ ourselves before going across the network.
+
+2002-04-25 14:07 Martin Pool <mbp@samba.org>
+
+ * src/daemon.c: Error out if we somehow get a request to run cpp on
+ the server.
+
+2002-04-25 14:04 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Parse out -o options; also work out whether we ought
+ to call cpp.
+
+2002-04-25 13:34 Martin Pool <mbp@samba.org>
+
+ * src/: arg.c, daemon.c, distcc.c, distcc.h: Start refactoring
+ argument scanner.
+
+2002-04-25 13:15 Martin Pool <mbp@samba.org>
+
+ * src/rpc.c: Must truncate temp file as we start receiving.
+
+2002-04-25 12:00 Martin Pool <mbp@samba.org>
+
+ * src/GNUmakefile: Doc.
+
+2002-04-25 11:59 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/Makefile: Add rpc.c
+
+ Make clean cleans .d files
+
+2002-04-25 00:27 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.h, exec.c: Examine and remember the cc exit code.
+
+2002-04-25 00:18 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: arg.c, daemon.c, distcc.c, distcc.h: Improve server-side
+ argument argument parsing
+
+2002-04-24 23:52 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Better debug for server-side substitution
+
+2002-04-24 23:44 Martin Pool <mbp@samba.org>
+
+ * src/util.c: fix file-style
+
+2002-04-24 23:44 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: message when sending is complete
+
+2002-04-24 23:43 Martin Pool <mbp@samba.org>
+
+ * src/: daemon.c, util.h: redirect stderr to prevent fouling socket
+
+2002-04-24 23:30 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Clean up; add error checks.
+
+2002-04-24 23:30 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Clean up imported code, and in particular log
+ messages
+
+2002-04-24 23:29 Martin Pool <mbp@samba.org>
+
+ * src/arg.c: Fix comment
+
+2002-04-24 23:29 Martin Pool <mbp@samba.org>
+
+ * src/Makefile: Store version in Makefile
+
+2002-04-24 23:17 Martin Pool <mbp@samba.org>
+
+ * src/clinet.c: Copy in network code from rsync. Currently
+ hardcoded to localhost:4200.
+
+2002-04-24 18:05 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Doc
+
+2002-04-24 16:13 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/Makefile: Fix 'make clean'
+
+2002-04-24 00:49 Martin Pool <mbp@samba.org>
+
+ * src/.cvsignore: Ignore any .i files that might be around
+
+2002-04-24 00:21 Martin Pool <mbp@samba.org>
+
+ * src/: Makefile, distcc.c, distcc.h, exec.c: Split out code to run
+ the compiler
+
+2002-04-24 00:10 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/: .cvsignore, Makefile, distcc.c, distcc.h, trace.c, util.c:
+ Split utilities into their own file
+
+2002-04-23 14:44 Martin Pool <mbp@samba.org>
+
+ * 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 <mbp@samba.org>
+
+ * src/distcc.c: Put arguments into a jobinfo_t struct.
+
+2002-04-23 14:14 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Try to detect .i and .o files
+
+2002-04-23 13:47 Martin Pool <mbp@samba.org>
+
+ * src/distcc.c: Handle empty command line.
+
+2002-04-23 13:25 Martin Pool <mbp@samba.org>
+
+ * src/.cvsignore: Ignore built files
+
+2002-04-23 13:24 Martin Pool <mbp@samba.org>
+
+ * src/: trace.c, trace.h: Copy trace routines from librsync
+
+2002-04-23 13:22 Martin Pool <mbp@samba.org>
+
+ * src/: distcc.c, .cvsignore, HACKING, Makefile: Copy very simple
+ code into public samba cvs
+
diff --git a/distcc/INSTALL b/distcc/INSTALL
new file mode 100644
index 0000000..2a09826
--- /dev/null
+++ b/distcc/INSTALL
@@ -0,0 +1,190 @@
+Installation 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.
+
+If you find distcc useful, please consider donating to the Samba
+Foundation to help cover our costs in publishing free
+software. (Please mention distcc in your donation.)
+
+Please report any problems to distcc@lists.samba.org.
+
+
+Prerequisites
+-------------
+
+To build distcc you need
+
+ GNU Make
+ A C compiler
+
+You can optionally have
+
+ libpopt
+
+ If this is not found on your system, it will be statically linked in.
+
+ Python >=2.0
+
+ To run the test suite with "make maintainer-check" or the
+ benchmark.
+
+ 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.
+
+
+Compiling distcc
+----------------
+
+Compilation follows the standard GNU pattern:
+
+ $ ./configure --help
+ $ ./configure
+ $ make
+ # make install
+
+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.
+
+
+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.
+
+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.
+
+
+Set up the host list
+--------------------
+
+On the client machines, store a list of servers names in
+~/.distcc/hosts. 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 signficantly slower than
+another machine.
+
+See the manual for more information.
+
+
+Create 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/bin
+and populate it with links.
+
+# 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++
+
+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.
+
+
+Complete the survey
+-------------------
+
+Once you have distcc working for your own application, please complete
+and mail in the survey in survyey.txt.
diff --git a/distcc/Makefile.in b/distcc/Makefile.in
new file mode 100644
index 0000000..c7c1d43
--- /dev/null
+++ b/distcc/Makefile.in
@@ -0,0 +1,669 @@
+# 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.
+
+# Remember that a CVS checkout of this project contains some
+# directories that will not be present in a tarball distribution.
+# So, those directories must not be built by regular
+# commands (make all, make clean, make distclean), only by
+# maintainer-* or explicit invocations.
+
+## 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@
+POPT_CFLAGS = @POPT_CFLAGS@
+
+LDFLAGS = @LDFLAGS@
+CC = @CC@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@ ${DIR_DEFS} -Isrc -I$(srcdir)/lzo
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+docdir = @docdir@
+pkgdatadir = $(datadir)/@PACKAGE_NAME@
+
+# These must be done from here, not from autoconf, because they can
+# contain variable expansions written in Make syntax. Ew.
+DIR_DEFS = -DSYSCONFDIR="\"${sysconfdir}\"" -DPKGDATADIR="\"${pkgdatadir}\""
+
+# 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@
+
+# You might need to override this depending on the name under which
+# Python is installed here.
+PYTHON = @PYTHON@
+
+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) \
+ $(test_SOURCE) \
+ $(bench_PY) \
+ $(dist_extra) \
+ $(gnome_data)
+
+dist_lzo = lzo/minilzo.c lzo/minilzo.h lzo/lzoconf.h lzo/.stamp-conf.in
+
+dist_contrib = contrib/distcc-absolutify \
+ contrib/distcc.sh \
+ contrib/distccd-init \
+ contrib/dmake \
+ contrib/make-j \
+ contrib/netpwd \
+ contrib/stage-cc-wrapper.patch \
+ contrib/redhat/init \
+ contrib/redhat/logrotate \
+ contrib/redhat/sysconfig \
+ contrib/redhat/xinetd
+
+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 \
+ INSTALL \
+ TODO \
+ doc/protocol-1.txt doc/status-1.txt \
+ doc/protocol-2.txt \
+ doc/reporting-bugs.txt \
+ survey.txt
+
+example_DOCS = \
+ doc/example/init doc/example/init-suse \
+ doc/example/logrotate \
+ doc/example/xinetd \
+
+# These are included in the distribution but not installed into the
+# doc dir.
+dist_extra = \
+ README.packaging ChangeLog ChangeLog.old
+
+mkinstalldirs = $(SHELL) $(srcdir)/mkinstalldirs
+man1dir = $(mandir)/man1
+man8dir = $(mandir)/man8
+
+test_SOURCE = test/comfychair.py \
+ test/testdistcc.py
+
+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 = gzip
+GZIP_OPT = -9v
+
+BZIP2 = bzip2
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+distdir = $(PACKAGE_TARNAME)-$(VERSION)
+tarball = $(PACKAGE_TARNAME)-$(VERSION).tar
+tarball_bz2 = $(tarball).bz2
+tarball_sig = $(tarball_bz2).asc
+distnews = $(PACKAGE_TARNAME)-$(VERSION).NEWS
+
+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
+
+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 \
+ 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 \
+ $(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 \
+ 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.c 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
+
+# All source files, for the purposes of building the distribution
+SRC = src/stats.c \
+ 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/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/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
+
+
+HEADERS = src/stats.h \
+ src/access.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
+
+man1_MEN = man/distcc.1 man/distccd.1 man/distccmon-text.1
+man_HTML = man/distcc_1.html man/distccd_1.html man/distccmon_text_1.html
+MEN = $(man1_MEN)
+
+gnome_data = gnome/distccmon-gnome-icon.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@
+
+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@
+
+## OVERALL targets
+
+## IMPLICIT BUILD rules
+
+.SUFFIXES: .html .latte .o .c
+
+.c.o:
+ $(CC) $(CPPFLAGS) $(WERROR_CFLAGS) $(CFLAGS) -o $@ -c $<
+
+## OVERALL targets
+
+## NOTE: "all" must be the first (default) rule, aside from patterns.
+
+all: $(bin_PROGRAMS)
+
+# 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
+ ./config.status
+ touch src/config.h.stamp
+
+# 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)
+
+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)
+
+
+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) $(LIBS) \
+ $(GNOME_CFLAGS) $(GNOME_LIBS) \
+ $(mon_obj) $(gnome_obj)
+
+
+## Dist targets
+
+# 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 :-/
+
+dist:
+ -rm -fr $(distdir)
+ $(MAKE) dist-files
+ $(TAR) cfh $(tarball) $(distdir)
+ $(BZIP2) -vf $(tarball)
+ rm -r $(distdir)
+ cp NEWS $(distnews)
+
+distcheck: dist
+ rm -rf '+distcheck'
+ mkdir '+distcheck'
+ cd '+distcheck' && bunzip2 < ../$(tarball_bz2) | $(TAR) xv && \
+ cd $(distdir) && ./configure --prefix=`pwd`/prefix && \
+ $(MAKE) && $(MAKE) install && $(MAKE) maintainer-check && \
+ $(MAKE) clean
+ rm -rf '+distcheck'
+
+dist-sign:
+ gpg -a --detach-sign $(tarball_bz2)
+
+# the sort function removes duplicates
+dist-files: $(dist_files)
+ for f in $(dist_files); do mkdir -p $(distdir)/`dirname $$f` || exit 1; \
+ cp -a $(srcdir)/$$f $(distdir)/$$f || exit 1; done
+
+## BUILD manual targets
+man/distcc_1.html: man/distcc.1
+ troff2html -man man/distcc.1 > $@
+
+man/distccd_1.html: man/distccd.1
+ troff2html -man man/distccd.1 > $@
+
+man/distccmon_text_1.html: man/distccmon-text.1
+ troff2html -man man/distccmon-text.1 > $@
+
+
+######################################################################
+## CHECK targets
+
+check_programs: $(check_PROGRAMS) $(bin_PROGRAMS)
+
+TESTDISTCC_OPTS =
+
+# WARNING: This resets the path to avoid any confusion caused by
+# having distcc masquerades already on the path. If you have gcc
+# installed elsewhere this won't work....
+maintainer-check: check_programs
+ if test x$(PYTHON) != x; then \
+ $(PYTHON) -c 'import sys; print sys.version'; \
+ PATH=`pwd`:/usr/local/bin:/bin:/usr/bin \
+ $(PYTHON) $(srcdir)/test/testdistcc.py $(TESTDISTCC_OPTS); \
+ else echo "WARNING: python not found; tests skipped"; \
+ fi
+
+# NB: This does not depend upon install; you might want to test another version.
+maintainer-installcheck: check_programs
+ if test x$(PYTHON) != x; then \
+ $(PYTHON) -c 'import sys; print sys.version'; \
+ PATH="$(bindir):`pwd`:$$PATH" $(PYTHON) $(srcdir)/test/testdistcc.py; \
+ else echo "WARNING: python not found; tests skipped"; \
+ fi
+
+check:
+ @echo Please try 'make maintainer-check' instead.
+installcheck:
+ @echo Please try 'make maintainer-check' instead.
+
+# 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
+
+# This is an integration test which runs the distcc tests
+# using distcc-pump. So you need to build distcc-pump first.
+# Run "make" in the distcc_pump directory before running this test.
+pump-check:
+ $(srcdir)/../pump $(MAKE) TESTDISTCC_OPTS=--pump maintainer-check
+# TODO(fergus): Move this rule to ../Makefile.in.
+
+# The following target is useful for running a single test at a time.
+# Sample usage:
+# make TESTNAME=Lsdistcc_Case singletest
+# make TESTNAME=Lsdistcc_Case TESTDISTCC_OPTS=--valgrind singletest
+TESTNAME = NoDetachDaemon_Case # Override this with the desired test.
+single-test: check_programs
+ PATH=`pwd`:/usr/local/bin:/bin:/usr/bin \
+ $(PYTHON) $(srcdir)/test/onetest.py $(TESTDISTCC_OPTS) $(TESTNAME)
+
+######################################################################
+## BENCHMARK targets
+benchmark:
+ @echo "The distcc macro-benchmark uses your existing distcc installation"
+ @if [ "$$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
+
+# Also clean binaries which are optionally built. Also remove .d files; old ones
+# may confuse 'make'.
+clean: clean-autoconf clean-lzo
+ rm -f src/*.[od] popt/*.[od]
+ rm -f $(check_PROGRAMS) $(bin_PROGRAMS)
+ rm -f distccmon-gnome
+ rm -rf testtmp
+
+clean-autoconf:
+ rm -f config.cache config.log
+
+clean-lzo:
+ rm -f lzo/*.[od] lzo/testmini
+
+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 config.status config.cache config.log
+ rm -rf autom4te.cache
+
+distclean: distclean-autoconf clean
+
+
+## MAINTAINER targets
+
+upload-man: $(man_HTML)
+ rsync -avz $(man_HTML) \
+ --exclude CVS --exclude '*~' --exclude '*.latte' \
+ samba.org:/home/httpd/distcc/man/
+
+upload-dist:
+ rsync -avP $(tarball_bz2) $(distnews) $(tarball_sig) samba.org:/home/ftp/pub/distcc/
+
+
+
+### INSTALL targets
+
+# 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 " system configuration $(DESTDIR)$(sysconfdir)"
+ @echo " shared data files $(DESTDIR)$(pkgdatadir)"
+
+
+# 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-example @INSTALL_GNOME@
+
+install-programs: $(bin_PROGRAMS)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ for p in $^; do \
+ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir) || exit 1; \
+ done
+
+install-man: $(man1_MEN)
+ $(mkinstalldirs) $(DESTDIR)$(man1dir)
+ for p in $^; do \
+ $(INSTALL_DATA) $$p $(DESTDIR)$(man1dir) || exit 1; \
+ done
+
+install-doc: $(pkgdoc_DOCS)
+ $(mkinstalldirs) $(DESTDIR)$(docdir)
+ for p in $^; do \
+ $(INSTALL_DATA) $$p $(DESTDIR)$(docdir) || exit 1; \
+ done
+
+install-example: $(example_DOCS)
+ $(mkinstalldirs) $(DESTDIR)$(docdir)/example
+ for p in $^; do \
+ $(INSTALL_DATA) $$p $(DESTDIR)$(docdir)/example || exit 1; \
+ done
+
+install-gnome-data: $(gnome_data)
+ $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
+ for p in $^; do \
+ $(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir) || exit 1; \
+ done
+
+# For distcc-pump
+
+.PHONY: echo_common_obj
+echo_common_obj:
+ echo $(common_obj)
+
+.PHONY: echo_srcdir
+echo_srcdir:
+ cd $(srcdir) && pwd
+
+.PHONY: echo_srcdir_parent
+echo_srcdir_parent:
+ cd $(srcdir)/.. && pwd
diff --git a/distcc/NEWS b/distcc/NEWS
new file mode 100644
index 0000000..8548c3b
--- /dev/null
+++ b/distcc/NEWS
@@ -0,0 +1,2144 @@
+distcc-pump-1.0 "My prices are insane." 2008-??-??
+
+ FEATURES:
+
+ * New protocol, version 3, allowing for preprocessing on distcc servers.
+
+ * New component: an include server for incremental static analysis of include
+ dependencies. This software is written in Python 2.4.
+
+ BUG FIXES (TODO: include all kegel, manos, dongmin, et al patches):
+
+
+ PORTABILITY:
+
+ * 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.
+
+
+
+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 <joshh@google.com>).
+
+ 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 <target>-gcc-<version>, 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 <http://marc.theaimsgroup.com/?l=linux-netdev&r=1&b=200209&w=2>.
+ (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 <sys/socket.h> (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<anything> 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:
diff --git a/distcc/README b/distcc/README
new file mode 100644
index 0000000..e8ed7ee
--- /dev/null
+++ b/distcc/README
@@ -0,0 +1,39 @@
+
+ distcc -- a free distributed C/C++ compiler system
+
+ http://distcc.samba.org/
+
+ by Martin Pool <mbp@samba.org>
+
+
+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.
+
+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), 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.
+
+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.
diff --git a/distcc/README.packaging b/distcc/README.packaging
new file mode 100644
index 0000000..1b35ccd
--- /dev/null
+++ b/distcc/README.packaging
@@ -0,0 +1,75 @@
+$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 heterogenous 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.
diff --git a/distcc/TODO b/distcc/TODO
new file mode 100644
index 0000000..0d3b23c
--- /dev/null
+++ b/distcc/TODO
@@ -0,0 +1,1112 @@
+TODO list for distcc
+
+See also TODO comments in source files and doc/todo/
+
+
+
+convert web site from latte to say php
+
+ Latte is nice, but seems to be gradually becoming unmaintained;
+ not in Ubuntu or Gentoo.
+
+
+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 heterogenous 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.
+
+
+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.
+
+
+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
+
+ Perhaps build RPMS and .debs?
+
+ Is it easy to build a static (or LSB-compliant?) .rpm on Debian?
+
+ 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.
+
+
+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.
+
+ 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
+
+ It would be nice to have a <tt>--ping</tt> 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 <tt>$COMPILER_PATH</tt> and
+ <tt>$GCC_EXEC_PREFIX</tt> 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
+ <http://www.opengroup.org/onlinepubs/007904975/functions/wait.html>,
+ 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?
+
+
+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 exmaple, 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.
+
+
+preprocess remotely
+
+ 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.
+
+
+Local variables:
+mode: indented-text
+indent-tabs-mode: nil
+End:
diff --git a/distcc/autogen.sh b/distcc/autogen.sh
new file mode 100755
index 0000000..d18d318
--- /dev/null
+++ b/distcc/autogen.sh
@@ -0,0 +1,24 @@
+#! /bin/sh
+
+# Run this script to build distcc from CVS.
+
+## first try the default names
+AUTOHEADER="autoheader"
+AUTOCONF="autoconf"
+
+if which $AUTOCONF > /dev/null
+then
+ :
+else
+ echo "$0: need autoconf 2.53 or later to build distcc from CVS" >&2
+ exit 1
+fi
+
+echo "$0: running $AUTOHEADER"
+$AUTOHEADER || exit 1
+
+echo "$0: running $AUTOCONF"
+$AUTOCONF || exit 1
+
+echo "Now run ./configure and then make."
+exit 0
diff --git a/distcc/bench/Build.py b/distcc/bench/Build.py
new file mode 100755
index 0000000..67d2817
--- /dev/null
+++ b/distcc/bench/Build.py
@@ -0,0 +1,151 @@
+# distcc/benchmark -- automated system for testing distcc correctness
+# and performance on various source trees.
+
+# 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
+
+from Project import Project
+from compiler import CompilerSpec
+import buildutil
+from buildutil import make_dir, run_cmd, rm_files
+import re, os, sys, time
+
+
+
+class Build:
+ """A Build is a combination of a Project and CompilerSpec.
+
+ """
+ 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
+
+ def __repr__(self):
+ return "Build(%s, %s)" % (`self.project`, `self.compiler`)
+
+
+ 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, compiler):
+ """Run configuration command for this tree, if any."""
+ self.compiler = compiler
+
+ 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))
+
+ print "** Configuring..."
+ run_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))
+
+
+ def build(self, sum):
+ """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))
+
+ 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))
+ run_cmd(cmd)
+
+ cmd = ("cd %s && \\\n%s \\\nDISTCC_LOG='%s' \\\nCC='%s' \\\nCXX='%s' \\\n%s \\\n>%s 2>&1" %
+ (self.build_dir, self.project.build_cmd, distcc_log,
+ self.compiler.cc,
+ self.compiler.cxx,
+ self.compiler.make_opts,
+ build_log))
+ result, elapsed = run_cmd(cmd)
+ return elapsed
+
+
+ def clean(self):
+ clean_log = os.path.join(self.log_dir, "bench-clean.log")
+ print "** Cleaning build directory"
+ cmd = "cd %s && make clean >%s 2>&1" % (self.build_dir, clean_log)
+ run_cmd(cmd)
+
+
+ def scrub(self):
+ print "** Removing build directory"
+ run_cmd("rm -rf %s" % self.unpacked_dir)
+
+
+ def build_actions(self, actions, summary):
+ """Carry out selected actions.
+
+ Catch exceptions and handle."""
+ try:
+ times = []
+ if 'sweep' in actions:
+ self.scrub()
+ if 'unpack' in actions:
+ self.unpack()
+ if 'configure' in actions:
+ self.configure(self.compiler)
+ for i in range(self.n_repeats):
+ if 'build' in actions:
+ times.append(self.build(summary))
+ if 'clean' in actions:
+ self.clean()
+ if 'scrub' in actions:
+ self.scrub()
+ summary.store(self.project, self.compiler, times)
+ except KeyboardInterrupt:
+ raise
+ except:
+ apply(sys.excepthook, sys.exc_info()) # print traceback
+ summary.store(self.project, self.compiler, 'FAIL')
diff --git a/distcc/bench/Project.py b/distcc/bench/Project.py
new file mode 100755
index 0000000..9551917
--- /dev/null
+++ b/distcc/bench/Project.py
@@ -0,0 +1,114 @@
+# distcc/benchmark -- automated system for testing distcc correctness
+# and performance on various source trees.
+
+# 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
+
+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,
+ md5=None,
+ name=None,
+ configure_cmd=None,
+ pre_build_cmd = None,
+ build_cmd=None,
+ unpacked_subdir=None,
+ build_subdir=None,
+ source_name=None):
+ 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.source_name = source_name or name
+ 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".
+ self.unpacked_subdir = unpacked_subdir or self.source_name
+ self.build_subdir = build_subdir
+
+
+ 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 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()
+
diff --git a/distcc/bench/ProjectDefs.py b/distcc/bench/ProjectDefs.py
new file mode 100755
index 0000000..ec66490
--- /dev/null
+++ b/distcc/bench/ProjectDefs.py
@@ -0,0 +1,100 @@
+# distcc/benchmark -- automated system for testing distcc correctness
+# and performance on various source trees.
+
+# 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
+
+__doc__ = """distcc benchmark project definitions"""
+
+from Project import Project
+
+# Would like to test glibc, but it needs a separate source and build
+# directory, and this tool doesn't support that yet.
+
+# 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.3.2.tar.bz2',
+# configure_cmd = './configure --disable-sanity-checks'
+# ).register()
+
+#Project(url='http://mirror.aarnet.edu.au/pub/gnu/libc/glibc-2.3.tar.bz2',
+# configure_cmd='./configure --disable-sanity-checks',
+# md5='fd20b4a9feeb2b2f0f589b1a9ae8a5e2 glibc-2.3.tar.bz2').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='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://us3.samba.org/samba/ftp/old-versions/samba-2.2.7.tar.gz',
+ build_subdir='source',
+ ).register()
+
+Project(url='http://ftp.gnu.org/gnu/make/make-3.80.tar.bz2',
+ md5='0bbd1df101bc0294d440471e50feca71 *make-3.80.tar.bz2'
+ ).register()
+
+# failed: "make: *** No rule to make target `defconfig'. Stop."
+#Project(url='http://public.ftp.planetmirror.com/pub/linux/kernel/v2.4/linux-2.4.20.tar.bz2',
+# configure_cmd='make defconfig',
+# build_cmd='make bzImage',
+# ).register()
+
+Project(url='http://www.kernel.org/pub/linux/kernel/v2.5/linux-2.5.51.tar.bz2',
+ md5='2300b7b7d2ce4c017fe6dae49717fd9a *linux-2.5.51.tar.bz2',
+ configure_cmd='make defconfig',
+ build_cmd='make bzImage'
+ ).register()
+
+Project(url='http://sources-redhat.oc1.mirrors.redwire.net/gdb/old-releases/gdb-5.3.tar.gz',
+ ).register()
+
+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='http://ibiblio.org/pub/linux/system/emulators/wine/wine-0.9.3.tar.bz2',
+ ).register()
+
+Project(url='http://public.planetmirror.com.au/pub/gnu/hello/hello-2.1.1.tar.gz',
+ md5='70c9ccf9fac07f762c24f2df2290784d *hello-2.1.1.tar.gz',
+ ).register()
+
+
+# XXX: Does not build on Debian at the moment, problem with libIDL-config
+
+# Project(url='http://mirror.aarnet.edu.au/pub/mozilla/releases/mozilla1.4/src/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()
+
+Project(url='http://ftp.azc.uam.mx/mirrors/samba/samba-3.0.7.tar.gz',
+ name='samba-3.0.7',
+ build_subdir='source',
+ configure_cmd='./configure',
+ pre_build_cmd = 'make proto',
+ ).register()
diff --git a/distcc/bench/Summary.py b/distcc/bench/Summary.py
new file mode 100755
index 0000000..33c8111
--- /dev/null
+++ b/distcc/bench/Summary.py
@@ -0,0 +1,76 @@
+# distcc/benchmark -- automated system for testing distcc correctness
+# and performance on various source trees.
+
+# 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
+
+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, elapsed_times):
+ """
+ elapsed_times is a sequence of elapsed times to build the project.
+ A sequence because we can build projects repeatedly.
+ """
+ self._table.append((project.name, compiler.name, elapsed_times))
+
+ def print_raw(self):
+ from pprint import pprint
+ pprint(self._table)
+
+ 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()
+ print "DISTCC_HOSTS: %s" % `os.getenv('DISTCC_HOSTS')`
+ sys.stdout.flush()
+ os.system("uname -a")
+
+ print "%-20s %-30s %8s %8s" % ('project', 'compiler', 'time', 's.d.')
+
+ for row in self._table:
+ print "%-20s %-30s " % row[:2],
+ times = row[2]
+ if times == 'FAIL':
+ print '%9s' % 'FAIL'
+ else:
+ mean = statistics.mean(times)
+ sd = statistics.std(times)
+ print "%8.4fs" % mean,
+ if sd is None:
+ print "%9s" % "n/a"
+ else:
+ print "%8.4fs" % sd
+
diff --git a/distcc/bench/actions.py b/distcc/bench/actions.py
new file mode 100755
index 0000000..d6c3544
--- /dev/null
+++ b/distcc/bench/actions.py
@@ -0,0 +1,51 @@
+# distcc/benchmark -- automated system for testing distcc correctness
+# and performance on various source trees.
+
+# 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
+
+# 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, ''),
+ ('clean', True, 'run "make clean" or equivalent'),
+ ('build', True, ''),
+ ('scrub', True, 'remove build directory')]
+
+
+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):
+ import sys
+ 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
diff --git a/distcc/bench/benchmark.py b/distcc/bench/benchmark.py
new file mode 100755
index 0000000..a4f80b3
--- /dev/null
+++ b/distcc/bench/benchmark.py
@@ -0,0 +1,176 @@
+#! /usr/bin/python
+
+# distcc/benchmark -- automated system for testing distcc correctness
+# and performance on various source trees.
+
+# 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
+
+
+# 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: Try building something large in C++.
+
+# TODO: Set CXX as well.
+
+# TODO: Add option to run tests repeatedly and show mean and std. dev.
+
+# 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 re, os, sys, 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
+ -c, --compiler=COMPILER specify one compiler to use
+ -n N repeat compilation N times
+ -a, --actions=ACTIONS comma-separated list of action phases
+ to perform
+
+Compilers can be specified as either "local,N" to run N copies of gcc,
+or dist,N to run N copies of distcc. Multiple -c options specify
+different scenarios to measure. The default is to run a nonparallel
+local compile and a parallel distributed compile.
+"""
+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"""
+ sum = Summary()
+ options, args = getopt(sys.argv[1:], 'a:c:n:',
+ ['list-projects', 'actions=', 'help', 'compiler='])
+ opt_actions = actions.default_actions
+ set_compilers = []
+ opt_repeats = 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 == '--compiler' or opt == '-c':
+ set_compilers.append(compiler.parse_opt(optarg))
+ elif opt == '-n':
+ opt_repeats = int(optarg)
+
+ if not set_compilers:
+ set_compilers = compiler.default_compilers()
+
+ # 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:
+ proj.pre_actions(opt_actions)
+ for comp in set_compilers:
+ build = Build(proj, comp, opt_repeats)
+ build.build_actions(opt_actions, sum)
+
+ sum.print_table()
+
+if __name__ == '__main__':
+ main()
+
diff --git a/distcc/bench/buildutil.py b/distcc/bench/buildutil.py
new file mode 100755
index 0000000..8a43353
--- /dev/null
+++ b/distcc/bench/buildutil.py
@@ -0,0 +1,49 @@
+# distcc/benchmark -- automated system for testing distcc correctness
+# and performance on various source trees.
+
+# 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
+
+
+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)
+
diff --git a/distcc/bench/compiler.py b/distcc/bench/compiler.py
new file mode 100755
index 0000000..3cc9d1d
--- /dev/null
+++ b/distcc/bench/compiler.py
@@ -0,0 +1,63 @@
+# distcc/benchmark -- automated system for testing distcc correctness
+# and performance on various source trees.
+
+# 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
+
+class CompilerSpec:
+ """Describes a compiler/make setup.
+
+ Used to define different situations such as local compilation, and
+ various degrees of parallelism."""
+
+ def __init__(self, cc=None, cxx=None, make_opts=None, name=None):
+ self.cc = cc or 'gcc'
+ self.cxx = cxx or 'c++'
+ self.make_opts = make_opts or ''
+ self.name = name or (self.cc + "__" + self.make_opts).replace(' ', '_')
+
+
+def default_compilers():
+ return [parse_opt('local,1'),
+ parse_opt('dist,8'),
+ ]
+
+def parse_opt(optarg):
+ """Parse command-line specification of a compiler
+
+ XXX: I don't really know what the best syntax for this is. For
+ the moment, it is "local" or "dist", followed by a comma and a
+ -j number. Perhaps we need to be able to specify host lists here
+ too.
+ """
+ where, howmany = optarg.split(',')
+ howmany = int(howmany)
+ if where == 'local':
+ return CompilerSpec(name='local_%02d' % howmany,
+ cc='cc',
+ cxx='c++',
+ make_opts='-j%d' % howmany)
+ elif where == 'dist':
+ return CompilerSpec(name='dist_%02d' % howmany,
+ cxx='distcc c++',
+ cc='distcc cc',
+ make_opts='-j%d' % howmany)
+ else:
+ raise ValueError, ("don't understand %s" % `where`)
+
+
+
diff --git a/distcc/bench/statistics.py b/distcc/bench/statistics.py
new file mode 100755
index 0000000..1565752
--- /dev/null
+++ b/distcc/bench/statistics.py
@@ -0,0 +1,47 @@
+#! /usr/bin/env python2.2
+
+# distcc/benchmark -- automated system for testing distcc correctness
+# and performance on various source trees.
+
+# 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
+
+
+# Based in part on http://starship.python.net/crew/jhauser/NumAdd.py.html by Janko Hauser
+
+
+import Numeric
+
+def var(m):
+ """
+ Variance of m.
+ """
+ if len(m) < 2:
+ return None
+ mu = Numeric.average(m)
+ return (Numeric.add.reduce(Numeric.power(Numeric.ravel(m)-mu, 2))
+ / (len(m)-1.))
+
+def std(m):
+ """
+ Standard deviation of m.
+ """
+ v = var(m)
+ return v and Numeric.sqrt(v)
+
+def mean(m):
+ return Numeric.average(m)
diff --git a/distcc/config.guess b/distcc/config.guess
new file mode 100755
index 0000000..9b1384b
--- /dev/null
+++ b/distcc/config.guess
@@ -0,0 +1,1400 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-11-30'
+
+# 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 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.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+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 <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+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 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # 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.
+
+# This shell variable is my proudest work .. or something. --bje
+
+set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ;
+(old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old)
+ || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ;
+dummy=$tmpdir/dummy ;
+files="$dummy.c $dummy.o $dummy.rel $dummy" ;
+trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ;
+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 ;
+ rm -f $files ;
+ 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 ;
+unset files'
+
+# 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
+
+# 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 tupples: *-*-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=`(/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 ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ 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
+ # 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/[-_].*/\./'`
+ ;;
+ 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}"
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mipseb-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # 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.
+ eval $set_cc_for_build
+ cat <<EOF >$dummy.s
+ .data
+\$Lformat:
+ .byte 37,100,45,37,120,10,0 # "%d-%x\n"
+
+ .text
+ .globl main
+ .align 4
+ .ent main
+main:
+ .frame \$30,16,\$26,0
+ ldgp \$29,0(\$27)
+ .prologue 1
+ .long 0x47e03d80 # implver \$0
+ lda \$2,-1
+ .long 0x47e20c21 # amask \$2,\$1
+ lda \$16,\$Lformat
+ mov \$0,\$17
+ not \$1,\$18
+ jsr \$26,printf
+ ldgp \$29,0(\$26)
+ mov 0,\$16
+ jsr \$26,exit
+ .end main
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null
+ if test "$?" = 0 ; then
+ case `$dummy` in
+ 0-0)
+ UNAME_MACHINE="alpha"
+ ;;
+ 1-0)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 1-1)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 1-101)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 2-303)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ 2-307)
+ UNAME_MACHINE="alphaev67"
+ ;;
+ 2-1307)
+ UNAME_MACHINE="alphaev68"
+ ;;
+ 3-1307)
+ UNAME_MACHINE="alphaev7"
+ ;;
+ esac
+ fi
+ rm -f $dummy.s $dummy && rmdir $tmpdir
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ 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 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ 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 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ 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 0 ;;
+ 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 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ 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 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # 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 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* 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 \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
+ rm -f $dummy.c $dummy && rmdir $tmpdir
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ 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 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????: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 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ 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 0 ;;
+ *: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 <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
+ rm -f $dummy.c $dummy && rmdir $tmpdir
+ echo rs6000-ibm-aix3.2.5
+ 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 0 ;;
+ *:AIX:*:[45])
+ 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/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 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 <stdlib.h>
+ #include <unistd.h>
+
+ 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`
+ if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+ rm -f $dummy.c $dummy && rmdir $tmpdir
+ fi ;;
+ esac
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ 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 && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
+ rm -f $dummy.c $dummy && rmdir $tmpdir
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ 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 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3D:*:*:*)
+ echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ 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 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ # Determine whether the default compiler uses glibc.
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #if __GLIBC__ >= 2
+ LIBC=gnu
+ #else
+ LIBC=
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ rm -f $dummy.c && rmdir $tmpdir
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:3*)
+ echo i586-pc-interix3
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit 0 ;;
+ 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 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ rm -f $dummy.c && rmdir $tmpdir
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ rm -f $dummy.c && rmdir $tmpdir
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ 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 ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ 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-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ rm -f $dummy.c && rmdir $tmpdir
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ 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 0 ;;
+ 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 0 ;;
+ 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 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ 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 0 ;;
+ i*86:*:5:[78]*)
+ 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 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/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 0 ;;
+ 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 i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ 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 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*: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)
+ 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 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *: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 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ 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 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ echo `uname -p`-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *: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 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *: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 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
+rm -f $dummy.c $dummy && rmdir $tmpdir
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 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:
diff --git a/distcc/config.sub b/distcc/config.sub
new file mode 100755
index 0000000..f0675aa
--- /dev/null
+++ b/distcc/config.sub
@@ -0,0 +1,1469 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-11-30'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# 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 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.
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# 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.
+
+# 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
+ $0 [OPTION] 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 <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+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 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # 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 0;;
+
+ * )
+ 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* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ 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)
+ os=
+ basic_machine=$1
+ ;;
+ -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
+ ;;
+ -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/'`
+ ;;
+ -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*)
+ 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 \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k \
+ | m32r | m68000 | m68k | m88k | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # 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-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \
+ | clipper-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* \
+ | m32r-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39 | mipstx39el \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # 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
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ 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
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ 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
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ 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'm not sure what "Sysv32" means. Should this be sysv3.2?
+ 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
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ 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
+ ;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ 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
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ 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
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2)
+ basic_machine=i686-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-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ 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 | ppc64-le | powerpc64-little)
+ 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
+ ;;
+ 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
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ 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
+ ;;
+ 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
+ ;;
+ t3d)
+ basic_machine=alpha-cray
+ os=-unicos
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic4x | c4x*)
+ basic_machine=tic4x-unknown
+ os=-coff
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ 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
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-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
+ ;;
+ 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
+ ;;
+ sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv9 | sparcv9b)
+ 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.
+ -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* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -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*)
+ # 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* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -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
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -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
+ ;;
+ -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
+ ;;
+ -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
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ # 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
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ 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
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-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
+ ;;
+ -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
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -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 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/distcc/configure.ac b/distcc/configure.ac
new file mode 100644
index 0000000..f93fab3
--- /dev/null
+++ b/distcc/configure.ac
@@ -0,0 +1,455 @@
+dnl 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.53)
+AC_INIT(distcc,
+ esyscmd(source ../version.sh && echo -n $DISTCC_PUMP_VERSION),
+ [distcc-pump@google.com])
+
+AC_CONFIG_HEADERS(src/config.h)
+AC_CANONICAL_HOST
+
+# 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.
+
+##### defaults
+
+dnl --with-docdir
+AC_DEFUN([DISTCC_WITH_DOCDIR],
+[AC_ARG_WITH(docdir,
+ AC_HELP_STRING([--with-docdir=DIR],
+ [Use DIR to store documentation files (default ${datadir}/doc/distcc)]),
+ [with_docdir=$withval])
+if test "x$with_docdir" = "x" ; then
+ docdir='${datadir}/doc/distcc'
+else
+ docdir=$with_docdir
+fi
+AC_SUBST(docdir)
+])
+
+dnl Run the check for --with-docdir
+DISTCC_WITH_DOCDIR
+
+# Check for socklen_t, and do something appropiate 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 *" or
+ # "void *" as the second argument to getpeername
+ dcc_cv_socklen_t_equiv=
+ for arg2 in "struct sockaddr" void; do
+ for t in int size_t unsigned long "unsigned long"; do
+ AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/socket.h>
+
+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 <sys/types.h>
+#include <sys/socket.h>])
+
+# 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(rfc2553,
+ AC_HELP_STRING([--enable-rfc2553], [use getaddrinfo, getnameinfo, etc]),
+ AC_DEFINE(ENABLE_RFC2553,1,[Use getaddrinfo(), getnameinfo(), etc]))
+
+
+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
+
+
+# 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+-2.0 libgnome-2.0 libgnomeui-2.0 pango"
+elif test "x${with_gtk}" = xyes
+then
+ GNOME_PACKAGES="gtk+-2.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"
+ 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)
+
+dnl Checks for programs
+AC_PROG_CC
+POPT_CFLAGS=""
+WERROR_CFLAGS=""
+if test x"$GCC" = xyes
+then
+ CFLAGS="$CFLAGS -MD \
+-W -Wall -Wimplicit -Wuninitialized \
+-Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings \
+-Waggregate-return -Wstrict-prototypes -Wmissing-prototypes \
+-Wnested-externs -Wpointer-arith -Wmissing-declarations"
+ # Would like -Wunreachable-code here, but it generates too many false
+ # positives.
+
+ # We want warnings to be treated as errors.
+ # Note that we can't include this in CFLAGS,
+ # because that would effect the configure tests,
+ # causing some of the tests to fail when they should succeed.
+ WERROR_CFLAGS="-Werror"
+
+ # For popt/*.c, we disable unused variable warnings.
+ POPT_CFLAGS="-Wno-unused"
+
+ AC_MSG_NOTICE([Adding gcc options: $CFLAGS])
+fi
+AC_SUBST(POPT_CFLAGS)
+AC_SUBST(WERROR_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 popt.
+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
+
+# TODO: Perhaps try to find a command name that invokes Python2.2, and
+# write that in to the makefile for use in running benchmarks, etc.
+# Perhaps it's reasonable to count on it always being "python2.2", but
+# that will break when we're on to a later version.
+
+AC_CHECK_PROGS(PYTHON, [python2.4 python2.3 python-2.3 python2.2 python-2.2 python])
+AC_ARG_VAR(PYTHON, [Python interpreter to use for running tests])
+# NB: Cannot use AC_CONFIG_LIBOBJ_DIR here, because it's not present
+# in autoconf 2.53.
+
+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 sys/signal.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 <sys/types.h>
+#endif
+])
+AC_CHECK_HEADERS([arpa/nameser.h], [], [],
+[#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+])
+AC_CHECK_HEADERS([resolv.h], [], [],
+[#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#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 <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#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_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)'
+ CPPFLAGS="$CPPFLAGS -I$srcdir/popt"
+else
+ LIBS="$LIBS -lpopt"
+ AC_MSG_RESULT(no)
+fi
+
+
+
+########################################################################
+# Check for types
+AC_TYPE_SIGNAL
+
+
+########################################################################
+# Checks for library functions, using libraries discovered above
+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 getcwd])
+AC_CHECK_FUNCS([snprintf vsnprintf vasprintf asprintf getcwd getwd])
+AC_CHECK_FUNCS([getrusage strsignal gettimeofday])
+AC_CHECK_FUNCS([getaddrinfo getnameinfo inet_ntop inet_ntoa])
+AC_CHECK_FUNCS([strndup mmap strlcpy])
+
+AC_CHECK_FUNCS([getloadavg])
+
+AC_CHECK_DECLS([snprintf, vsnprintf, vasprintf, asprintf, strndup])
+
+AC_MSG_CHECKING([if mmap() supports MAP_FAILED])
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif],[
+#ifdef HAVE_MMAP
+if (mmap (NULL, 0, 0, 0, 0, 0) == MAP_FAILED)
+ return 0;
+#else
+#error mmap unavailable
+#endif], ,[
+ AC_DEFINE([MAP_FAILED], [(void *)-1L],
+ [Define if MAP_FAILED constant not available])
+])
+AC_MSG_RESULT()
+
+
+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],samba_cv_HAVE_VA_COPY,[
+AC_TRY_LINK([#include <stdarg.h>
+va_list ap1,ap2;], [__va_copy(ap1,ap2);],
+samba_cv_HAVE_VA_COPY=yes,samba_cv_HAVE_VA_COPY=no)])
+if test x"$samba_cv_HAVE_VA_COPY" = x"yes"; then
+ AC_DEFINE(HAVE_VA_COPY,1,[Whether __va_copy() is available])
+fi
+
+AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <stdarg.h>
+void 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) exit(1);
+
+ if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(1);
+
+ exit(0);
+}
+main() { 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 <sys/types.h>
+#include <sys/socket.h>
+
+main() {
+ int fd[2];
+ exit((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 <sys/socket.h>])
+
+dnl ##### Output
+AC_SUBST(docdir)
+AC_SUBST(CFLAGS)
+AC_SUBST(LDFLAGS)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(BUILD_POPT)
+AC_SUBST(GNOME_BIN)
+dnl AC_DEFINE_UNQUOTED(PACKAGE, $PACKAGE, [Package name])
+dnl AC_DEFINE_UNQUOTED(VERSION, $VERSION, [Package version])
+AC_DEFINE_UNQUOTED(GNU_HOST, ["$host"], [Your gnu-style host triple])
+AC_OUTPUT([Makefile] popt/.stamp-conf lzo/.stamp-conf )
+
+
+##### Finalization
+
+# Display success, installation paths, and GPL licence statement.
+echo ' '
+${MAKE-make} showpaths
+echo ' '
+cat <<EOF
+
+ $PACKAGE_NAME $PACKAGE_VERSION configured
+
+ Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
+
+ 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. Unauthorized redistribution is
+ prohibited by law.
+
+ 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
+
+
+After installing distcc, please complete the survey in the file "survey.txt".
+
+EOF
diff --git a/distcc/contrib/distcc-absolutify b/distcc/contrib/distcc-absolutify
new file mode 100644
index 0000000..a3d2beb
--- /dev/null
+++ b/distcc/contrib/distcc-absolutify
@@ -0,0 +1,47 @@
+#! /bin/sh
+# Copyright 2002 Free Software Foundation
+# by Alexandre Oliva <aoliva@redhat.com>
+
+# 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+"$@"}
diff --git a/distcc/contrib/distcc.sh b/distcc/contrib/distcc.sh
new file mode 100644
index 0000000..b6b3307
--- /dev/null
+++ b/distcc/contrib/distcc.sh
@@ -0,0 +1,40 @@
+#! /bin/sh
+
+# This file, contributed by Dimitri PAPADOPOULOS-ORFANOS <papadopo@shfj.cea.fr>
+# 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
diff --git a/distcc/contrib/distccd-init b/distcc/contrib/distccd-init
new file mode 100644
index 0000000..46938a2
--- /dev/null
+++ b/distcc/contrib/distccd-init
@@ -0,0 +1,70 @@
+#! /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 <miquels@cistron.nl>.
+# Modified for Debian GNU/Linux
+# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
+#
+# 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
+
+
diff --git a/distcc/contrib/distccd-on-servers b/distcc/contrib/distccd-on-servers
new file mode 100755
index 0000000..437171c
--- /dev/null
+++ b/distcc/contrib/distccd-on-servers
@@ -0,0 +1,145 @@
+#! /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
+
+
diff --git a/distcc/contrib/dmake b/distcc/contrib/dmake
new file mode 100644
index 0000000..8e0ac85
--- /dev/null
+++ b/distcc/contrib/dmake
@@ -0,0 +1,16 @@
+#! /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 "$@"
+
diff --git a/distcc/contrib/make-j b/distcc/contrib/make-j
new file mode 100644
index 0000000..013484f
--- /dev/null
+++ b/distcc/contrib/make-j
@@ -0,0 +1,21 @@
+#! /bin/sh
+
+# make-j script from Alexandre Oliva <aoliva@redhat.com> 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+"$@"}
diff --git a/distcc/contrib/netpwd b/distcc/contrib/netpwd
new file mode 100644
index 0000000..863cb6e
--- /dev/null
+++ b/distcc/contrib/netpwd
@@ -0,0 +1,26 @@
+#! /bin/sh
+# Copyright 2002 Free Software Foundation
+# by Alexandre Oliva <aoliva@redhat.com>
+
+# 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
diff --git a/distcc/contrib/redhat/init b/distcc/contrib/redhat/init
new file mode 100644
index 0000000..4df2f6e
--- /dev/null
+++ b/distcc/contrib/redhat/init
@@ -0,0 +1,83 @@
+#!/bin/sh
+#
+# Init file for Distccd - A distributed compilation front-end.
+# WARNING: Don't enable on untrusted networks
+#
+# Written by Dag Wieers <dag@wieers.com>.
+#
+# 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
diff --git a/distcc/contrib/redhat/logrotate b/distcc/contrib/redhat/logrotate
new file mode 100644
index 0000000..edbecae
--- /dev/null
+++ b/distcc/contrib/redhat/logrotate
@@ -0,0 +1,5 @@
+/var/log/distccd.log {
+ missingok
+ copytruncate
+ notifempty
+}
diff --git a/distcc/contrib/redhat/sysconfig b/distcc/contrib/redhat/sysconfig
new file mode 100644
index 0000000..a5ad5bd
--- /dev/null
+++ b/distcc/contrib/redhat/sysconfig
@@ -0,0 +1,8 @@
+### 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"
diff --git a/distcc/contrib/redhat/xinetd b/distcc/contrib/redhat/xinetd
new file mode 100644
index 0000000..023f390
--- /dev/null
+++ b/distcc/contrib/redhat/xinetd
@@ -0,0 +1,17 @@
+# 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
+}
diff --git a/distcc/contrib/stage-cc-wrapper.patch b/distcc/contrib/stage-cc-wrapper.patch
new file mode 100644
index 0000000..cb3d004
--- /dev/null
+++ b/distcc/contrib/stage-cc-wrapper.patch
@@ -0,0 +1,81 @@
+Index: 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 <<EOF
+ s:^TARGET_CONFIGDIRS[ ]*=.*$:TARGET_CONFIGDIRS = ${target_configdirs}:
+ s%^TARGET_CONFIGARGS[ ]*=.*$%TARGET_CONFIGARGS = ${targargs}%
+ s%^FLAGS_FOR_TARGET[ ]*=.*$%FLAGS_FOR_TARGET = ${FLAGS_FOR_TARGET}%
+-s%^CC_FOR_TARGET[ ]*=.*$%CC_FOR_TARGET = ${CC_FOR_TARGET}%
+-s%^GCJ_FOR_TARGET[ ]*=.*$%GCJ_FOR_TARGET = ${GCJ_FOR_TARGET}%
+-s%^CXX_FOR_TARGET[ ]*=.*$%CXX_FOR_TARGET = ${qCXX_FOR_TARGET}%
+-s%^CXX_FOR_TARGET_FOR_RECURSIVE_MAKE[ ]*=.*$%CXX_FOR_TARGET_FOR_RECURSIVE_MAKE = ${qqCXX_FOR_TARGET}%
++s%^CC_FOR_TARGET[ ]*=.*$%CC_FOR_TARGET = \$(STAGE_CC_WRAPPER) ${CC_FOR_TARGET}%
++s%^GCJ_FOR_TARGET[ ]*=.*$%GCJ_FOR_TARGET = \$(STAGE_CC_WRAPPER) ${GCJ_FOR_TARGET}%
++s%^CXX_FOR_TARGET[ ]*=.*$%CXX_FOR_TARGET = \$(STAGE_CC_WRAPPER) ${qCXX_FOR_TARGET}%
++s%^CXX_FOR_TARGET_FOR_RECURSIVE_MAKE[ ]*=.*$%CXX_FOR_TARGET_FOR_RECURSIVE_MAKE = \$(STAGE_CC_WRAPPER) ${qqCXX_FOR_TARGET}%
+ s%^TARGET_SUBDIR[ ]*=.*$%TARGET_SUBDIR = ${target_subdir}%
+ s%^BUILD_SUBDIR[ ]*=.*$%BUILD_SUBDIR = ${build_subdir}%
+ s%^BUILD_CONFIGARGS[ ]*=.*$%BUILD_CONFIGARGS = ${buildargs}%
+Index: gcc/Makefile.in
+===================================================================
+RCS file: /cvs/gcc/egcs/gcc/Makefile.in,v
+retrieving revision 1.933
+diff -u -p -r1.933 Makefile.in
+--- gcc/Makefile.in 13 Aug 2002 23:11:37 -0000 1.933
++++ gcc/Makefile.in 14 Aug 2002 02:49:43 -0000
+@@ -175,7 +175,7 @@ USER_H = $(srcdir)/ginclude/stdarg.h $(s
+ # The GCC to use for compiling libgcc.a and crt*.o.
+ # Usually the one we just built.
+ # Don't use this as a dependency--use $(GCC_PASSES) or $(GCC_PARTS).
+-GCC_FOR_TARGET = ./xgcc -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include
++GCC_FOR_TARGET = $(STAGE_CC_WRAPPER) ./xgcc -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include
+
+ # This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
+ # It omits XCFLAGS, and specifies -B./.
+@@ -3330,7 +3330,7 @@ stage1_copy: stage1_build
+ echo stage2_build > 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
diff --git a/distcc/doc/example/init b/distcc/doc/example/init
new file mode 100644
index 0000000..e6ff03a
--- /dev/null
+++ b/distcc/doc/example/init
@@ -0,0 +1,80 @@
+#! /bin/sh
+#
+# chkconfig: - 60 20
+# description: The distcc deamon
+# http://distcc.samba.org
+#
+# 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 $?
diff --git a/distcc/doc/example/init-suse b/distcc/doc/example/init-suse
new file mode 100644
index 0000000..cf9665f
--- /dev/null
+++ b/distcc/doc/example/init-suse
@@ -0,0 +1,96 @@
+#! /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
diff --git a/distcc/doc/example/logrotate b/distcc/doc/example/logrotate
new file mode 100644
index 0000000..2bfe1eb
--- /dev/null
+++ b/distcc/doc/example/logrotate
@@ -0,0 +1,12 @@
+# 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
+} \ No newline at end of file
diff --git a/distcc/doc/example/xinetd b/distcc/doc/example/xinetd
new file mode 100644
index 0000000..096dcf4
--- /dev/null
+++ b/distcc/doc/example/xinetd
@@ -0,0 +1,26 @@
+# default: off
+
+# 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
+}
diff --git a/distcc/doc/protocol-1.txt b/distcc/doc/protocol-1.txt
new file mode 100644
index 0000000..37f9aed
--- /dev/null
+++ b/distcc/doc/protocol-1.txt
@@ -0,0 +1,213 @@
+description 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 futher 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 <version>
+
+ Greeting from client, followed by the protocol version, which is
+ always 1.
+
+ARGC <nargs>
+
+ Specifies the number of arguments in the command, including the
+ compiler name.
+
+ARGV <len> <bytes>
+
+ Repeated <nargs> times. Specifies the string value of one element
+ of the command.
+
+DOTI <len> <bytes>
+
+ The contents of the preprocessed source (.i) file.
+
+
+response
+--------
+
+The following packets comprise the response:
+
+DONE <version>
+
+ Introduces the response. The version must be 1.
+
+STAT <status>
+
+ 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 <sys/wait.h> or a POSIX standard for a full definition.)
+
+SERR <len> <bytes>
+
+ Contains messages sent to stderr by the compiler.
+
+SOUT <len> <bytes>
+
+ Contains messages sent to stdout by the compiler. Normally empty
+ -- errors and warnings for most compilers go to stderr instead.
+
+DOTO <len> <bytes>
+
+ 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.
diff --git a/distcc/doc/protocol-2.txt b/distcc/doc/protocol-2.txt
new file mode 100644
index 0000000..ab13860
--- /dev/null
+++ b/distcc/doc/protocol-2.txt
@@ -0,0 +1,38 @@
+description 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.
diff --git a/distcc/doc/protocol-3-impl.txt b/distcc/doc/protocol-3-impl.txt
new file mode 100644
index 0000000..3f7196b
--- /dev/null
+++ b/distcc/doc/protocol-3-impl.txt
@@ -0,0 +1,61 @@
+A 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, making functions from static into
+global, all around the code; a bug fix in argutil.c, etc.
+
+ - 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 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 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, 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. 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 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.
+ - clirpc.c Changed dcc_retrieve_results to retrieve
+ the dotd file.
+
diff --git a/distcc/doc/protocol-3.txt b/distcc/doc/protocol-3.txt
new file mode 100644
index 0000000..33a879e
--- /dev/null
+++ b/distcc/doc/protocol-3.txt
@@ -0,0 +1,82 @@
+description 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>
+
+ Version is 3.
+
+CDIR <len> <bytes>
+
+ The working directory on the client side. Sent just like any ARGV in
+ protocol versions 1/2.
+
+ARGC <nargs>
+ Just like in protocol versions 1/2.
+
+ARGV <len> <bytes>
+ Just like in protocol versions 1/2.
+
+NFIL <nfiles>
+ How many files or links will be sent. Similar to ARGC.
+
+NAME <len> <bytes>
+ The (absolute, crossing-no-symlinks) name of the next file/link to be
+ sent. Similar to any ARGV.
+
+FILE <len> <bytes>
+ The contents of the file. Similar to DOTI in protocol version 2.
+
+LINK <len> <bytes>
+ The contents of (the file name pointed to by) a link. Similar to any
+ ARGV.
+
+response
+--------
+
+Exactly as for protocol version 2, but with the following addition at the
+end.
+
+DOTD <len> <bytes>
+ The contents of the result .d file. Similar to DOTO.
+
+Notes
+-----
+
+This protocol is most useful in conjuction 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 CWD 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.
diff --git a/distcc/doc/reporting-bugs.txt b/distcc/doc/reporting-bugs.txt
new file mode 100644
index 0000000..11726d2
--- /dev/null
+++ b/distcc/doc/reporting-bugs.txt
@@ -0,0 +1,73 @@
+How 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.
diff --git a/distcc/doc/status-1.txt b/distcc/doc/status-1.txt
new file mode 100644
index 0000000..9c1e2c5
--- /dev/null
+++ b/distcc/doc/status-1.txt
@@ -0,0 +1,64 @@
+description 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.
+
diff --git a/distcc/gnome/distccmon-gnome-icon.png b/distcc/gnome/distccmon-gnome-icon.png
new file mode 100644
index 0000000..fe2db53
--- /dev/null
+++ b/distcc/gnome/distccmon-gnome-icon.png
Binary files differ
diff --git a/distcc/gnome/distccmon-gnome.desktop b/distcc/gnome/distccmon-gnome.desktop
new file mode 100644
index 0000000..e5bb319
--- /dev/null
+++ b/distcc/gnome/distccmon-gnome.desktop
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Version=0.9.4
+Encoding=UTF-8
+Exec=distccmon-gnome
+Name=distcc monitor
+GenericName=Distributed Compile Monitor
+Comment=Graphical view of distributed compile tasks
+Icon=distccmon-gnome-icon.png
+TryExec=distccmon-gnome
+Terminal=false
+Type=Application
+Categories=GNOME;Application;Development;
+StartupNotify=true
diff --git a/distcc/install-sh b/distcc/install-sh
new file mode 100755
index 0000000..e9de238
--- /dev/null
+++ b/distcc/install-sh
@@ -0,0 +1,251 @@
+#!/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
diff --git a/distcc/lzo/.stamp-conf.in b/distcc/lzo/.stamp-conf.in
new file mode 100644
index 0000000..e48829e
--- /dev/null
+++ b/distcc/lzo/.stamp-conf.in
@@ -0,0 +1 @@
+@src_dir@
diff --git a/distcc/lzo/lzoconf.h b/distcc/lzo/lzoconf.h
new file mode 100644
index 0000000..96db180
--- /dev/null
+++ b/distcc/lzo/lzoconf.h
@@ -0,0 +1,451 @@
+/* lzoconf.h -- configuration for the LZO real-time data compression library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 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.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __LZOCONF_H
+#define __LZOCONF_H
+
+#define LZO_VERSION 0x1080
+#define LZO_VERSION_STRING "1.08"
+#define LZO_VERSION_DATE "Jul 12 2002"
+
+/* internal Autoconf configuration file - only used when building LZO */
+#if defined(LZO_HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <limits.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+// LZO requires a conforming <limits.h>
+************************************************************************/
+
+#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
+# error "invalid CHAR_BIT"
+#endif
+#if !defined(UCHAR_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
+
+/* workaround a cpp bug under hpux 10.20 */
+#define LZO_0xffffffffL 4294967295ul
+
+#if !defined(LZO_UINT32_C)
+# if (UINT_MAX < LZO_0xffffffffL)
+# define LZO_UINT32_C(c) c ## UL
+# else
+# define LZO_UINT32_C(c) c ## U
+# endif
+#endif
+
+
+/***********************************************************************
+// architecture defines
+************************************************************************/
+
+#if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2)
+# if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)
+# define __LZO_WIN
+# elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
+# define __LZO_WIN
+# elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__)
+# define __LZO_WIN
+# elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS)
+# define __LZO_DOS
+# elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2)
+# define __LZO_OS2
+# elif defined(__palmos__)
+# define __LZO_PALMOS
+# elif defined(__TOS__) || defined(__atarist__)
+# define __LZO_TOS
+# endif
+#endif
+
+#if (UINT_MAX < LZO_0xffffffffL)
+# if defined(__LZO_WIN)
+# define __LZO_WIN16
+# elif defined(__LZO_DOS)
+# define __LZO_DOS16
+# elif defined(__LZO_PALMOS)
+# define __LZO_PALMOS16
+# elif defined(__LZO_TOS)
+# define __LZO_TOS16
+# elif defined(__C166__)
+# else
+ /* porting hint: for pure 16-bit architectures try compiling
+ * everything with -D__LZO_STRICT_16BIT */
+# error "16-bit target not supported - contact me for porting hints"
+# endif
+#endif
+
+#if !defined(__LZO_i386)
+# if defined(__LZO_DOS) || defined(__LZO_WIN16)
+# define __LZO_i386
+# elif defined(__i386__) || defined(__386__) || defined(_M_IX86)
+# define __LZO_i386
+# endif
+#endif
+
+#if defined(__LZO_STRICT_16BIT)
+# if (UINT_MAX < LZO_0xffffffffL)
+# include <lzo16bit.h>
+# endif
+#endif
+
+/* memory checkers */
+#if !defined(__LZO_CHECKER)
+# if defined(__BOUNDS_CHECKING_ON)
+# define __LZO_CHECKER
+# elif defined(__CHECKER__)
+# define __LZO_CHECKER
+# elif defined(__INSURE__)
+# define __LZO_CHECKER
+# elif defined(__PURIFY__)
+# define __LZO_CHECKER
+# endif
+#endif
+
+
+/***********************************************************************
+// integral and pointer types
+************************************************************************/
+
+/* Integral types with 32 bits or more */
+#if !defined(LZO_UINT32_MAX)
+# if (UINT_MAX >= LZO_0xffffffffL)
+ typedef unsigned int lzo_uint32;
+ typedef int lzo_int32;
+# define LZO_UINT32_MAX UINT_MAX
+# define LZO_INT32_MAX INT_MAX
+# define LZO_INT32_MIN INT_MIN
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+ typedef unsigned long lzo_uint32;
+ typedef long lzo_int32;
+# define LZO_UINT32_MAX ULONG_MAX
+# define LZO_INT32_MAX LONG_MAX
+# define LZO_INT32_MIN LONG_MIN
+# else
+# error "lzo_uint32"
+# endif
+#endif
+
+/* lzo_uint is used like size_t */
+#if !defined(LZO_UINT_MAX)
+# if (UINT_MAX >= LZO_0xffffffffL)
+ typedef unsigned int lzo_uint;
+ typedef int lzo_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_UINT_MAX ULONG_MAX
+# define LZO_INT_MAX LONG_MAX
+# define LZO_INT_MIN LONG_MIN
+# else
+# error "lzo_uint"
+# endif
+#endif
+
+typedef int lzo_bool;
+
+
+/***********************************************************************
+// memory models
+************************************************************************/
+
+/* Memory model for the public code segment. */
+#if !defined(__LZO_CMODEL)
+# if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define __LZO_CMODEL __far
+# elif defined(__LZO_i386) && defined(__WATCOMC__)
+# define __LZO_CMODEL __near
+# else
+# define __LZO_CMODEL
+# endif
+#endif
+
+/* Memory model for the public data segment. */
+#if !defined(__LZO_DMODEL)
+# if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define __LZO_DMODEL __far
+# elif defined(__LZO_i386) && defined(__WATCOMC__)
+# define __LZO_DMODEL __near
+# else
+# define __LZO_DMODEL
+# endif
+#endif
+
+/* Memory model that allows to access memory at offsets of lzo_uint. */
+#if !defined(__LZO_MMODEL)
+# if (LZO_UINT_MAX <= UINT_MAX)
+# define __LZO_MMODEL
+# elif defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define __LZO_MMODEL __huge
+# define LZO_999_UNSUPPORTED
+# elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16)
+# define __LZO_MMODEL
+# else
+# error "__LZO_MMODEL"
+# endif
+#endif
+
+/* no typedef here because of const-pointer issues */
+#define lzo_byte unsigned char __LZO_MMODEL
+#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_uint32p lzo_uint32 __LZO_MMODEL *
+#define lzo_int32p lzo_int32 __LZO_MMODEL *
+#define lzo_uintp lzo_uint __LZO_MMODEL *
+#define lzo_intp lzo_int __LZO_MMODEL *
+#define lzo_voidpp lzo_voidp __LZO_MMODEL *
+#define lzo_bytepp lzo_bytep __LZO_MMODEL *
+
+#ifndef lzo_sizeof_dict_t
+# define lzo_sizeof_dict_t sizeof(lzo_bytep)
+#endif
+
+
+/***********************************************************************
+// calling conventions and function types
+************************************************************************/
+
+/* linkage */
+#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)
+# if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define __LZO_CDECL __LZO_CMODEL __cdecl
+# elif defined(__LZO_i386) && defined(_MSC_VER)
+# define __LZO_CDECL __LZO_CMODEL __cdecl
+# elif defined(__LZO_i386) && defined(__WATCOMC__)
+# define __LZO_CDECL __LZO_CMODEL __cdecl
+# else
+# define __LZO_CDECL __LZO_CMODEL
+# endif
+#endif
+#if !defined(__LZO_ENTRY)
+# define __LZO_ENTRY __LZO_CDECL
+#endif
+
+/* C++ exception specification for extern "C" function types */
+#if !defined(__cplusplus)
+# undef LZO_NOTHROW
+# define LZO_NOTHROW
+#elif !defined(LZO_NOTHROW)
+# define LZO_NOTHROW
+#endif
+
+
+typedef int
+(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem,
+ const lzo_byte *dict, lzo_uint dict_len );
+
+typedef int
+(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem,
+ const lzo_byte *dict, lzo_uint dict_len );
+
+
+/* assembler versions always use __cdecl */
+typedef int
+(__LZO_CDECL *lzo_compress_asm_t)( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_CDECL *lzo_decompress_asm_t)( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+
+/* a progress indicator callback function */
+typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint);
+
+
+/***********************************************************************
+// export information
+************************************************************************/
+
+/* DLL export information */
+#if !defined(__LZO_EXPORT1)
+# define __LZO_EXPORT1
+#endif
+#if !defined(__LZO_EXPORT2)
+# define __LZO_EXPORT2
+#endif
+
+/* exported calling convention for C functions */
+#if !defined(LZO_PUBLIC)
+# define LZO_PUBLIC(_rettype) \
+ __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY
+#endif
+#if !defined(LZO_EXTERN)
+# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype)
+#endif
+#if !defined(LZO_PRIVATE)
+# define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY
+#endif
+
+/* exported __cdecl calling convention for assembler functions */
+#if !defined(LZO_PUBLIC_CDECL)
+# define LZO_PUBLIC_CDECL(_rettype) \
+ __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
+#endif
+#if !defined(LZO_EXTERN_CDECL)
+# define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype)
+#endif
+
+/* exported global variables (LZO currently uses no static variables and
+ * is fully thread safe) */
+#if !defined(LZO_PUBLIC_VAR)
+# define LZO_PUBLIC_VAR(_type) \
+ __LZO_EXPORT1 _type __LZO_EXPORT2 __LZO_DMODEL
+#endif
+#if !defined(LZO_EXTERN_VAR)
+# define LZO_EXTERN_VAR(_type) extern LZO_PUBLIC_VAR(_type)
+#endif
+
+
+/***********************************************************************
+// 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) /* not used right now */
+#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)
+
+
+/* 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_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
+ (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
+ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
+ (int)sizeof(lzo_compress_t))
+LZO_EXTERN(int) __lzo_init2(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 _s1, const lzo_voidp _s2, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memset(lzo_voidp _s, int _c, lzo_uint _len);
+
+/* checksum functions */
+LZO_EXTERN(lzo_uint32)
+lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len);
+LZO_EXTERN(lzo_uint32)
+lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len);
+
+/* misc. */
+LZO_EXTERN(lzo_bool) lzo_assert(int _expr);
+LZO_EXTERN(int) _lzo_config_check(void);
+typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
+typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
+typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } 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 _ptr, lzo_uint _size);
+#define LZO_PTR_ALIGN_UP(_ptr,_size) \
+ ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size)))
+
+/* deprecated - only for backward compatibility */
+#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size)
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
diff --git a/distcc/lzo/minilzo.c b/distcc/lzo/minilzo.c
new file mode 100644
index 0000000..85771eb
--- /dev/null
+++ b/distcc/lzo/minilzo.c
@@ -0,0 +1,2935 @@
+/* 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) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 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.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ 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
+#define LZO_BUILD
+
+#ifdef MINILZO_HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#undef LZO_HAVE_CONFIG_H
+#include "minilzo.h"
+
+#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x1080)
+# error "version mismatch in miniLZO source files"
+#endif
+
+#ifdef MINILZO_HAVE_CONFIG_H
+# define LZO_HAVE_CONFIG_H
+#endif
+
+#if !defined(LZO_NO_SYS_TYPES_H)
+# include <sys/types.h>
+#endif
+#include <stdio.h>
+
+#ifndef __LZO_CONF_H
+#define __LZO_CONF_H
+
+#if !defined(__LZO_IN_MINILZO)
+# ifndef __LZOCONF_H
+# include <lzoconf.h>
+# endif
+#endif
+
+#if defined(__BOUNDS_CHECKING_ON)
+# include <unchecked.h>
+#else
+# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt
+# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr)
+#endif
+
+#if !defined(LZO_HAVE_CONFIG_H)
+# include <stddef.h>
+# include <string.h>
+# if !defined(NO_STDLIB_H)
+# include <stdlib.h>
+# endif
+# define HAVE_MEMCMP
+# define HAVE_MEMCPY
+# define HAVE_MEMMOVE
+# define HAVE_MEMSET
+#else
+# include <sys/types.h>
+# if defined(HAVE_STDDEF_H)
+# include <stddef.h>
+# endif
+# if defined(STDC_HEADERS)
+# include <string.h>
+# include <stdlib.h>
+# endif
+#endif
+
+#if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define HAVE_MALLOC_H
+# define HAVE_HALLOC
+#endif
+
+#undef NDEBUG
+#if !defined(LZO_DEBUG)
+# define NDEBUG
+#endif
+#if defined(LZO_DEBUG) || !defined(NDEBUG)
+# if !defined(NO_STDIO_H)
+# include <stdio.h>
+# endif
+#endif
+#include <assert.h>
+
+#if !defined(LZO_COMPILE_TIME_ASSERT)
+# define LZO_COMPILE_TIME_ASSERT(expr) \
+ { typedef int __lzo_compile_time_assert_fail[1 - 2 * !(expr)]; }
+#endif
+
+#if !defined(LZO_UNUSED)
+# if 1
+# define LZO_UNUSED(var) ((void)&var)
+# elif 0
+# define LZO_UNUSED(var) { typedef int __lzo_unused[sizeof(var) ? 2 : 1]; }
+# else
+# define LZO_UNUSED(parm) (parm = parm)
+# endif
+#endif
+
+#if !defined(__inline__) && !defined(__GNUC__)
+# if defined(__cplusplus)
+# define __inline__ inline
+# else
+# define __inline__
+# endif
+#endif
+
+#if defined(NO_MEMCMP)
+# undef HAVE_MEMCMP
+#endif
+
+#if !defined(HAVE_MEMCMP)
+# undef memcmp
+# define memcmp lzo_memcmp
+#endif
+#if !defined(HAVE_MEMCPY)
+# undef memcpy
+# define memcpy lzo_memcpy
+#endif
+#if !defined(HAVE_MEMMOVE)
+# undef memmove
+# define memmove lzo_memmove
+#endif
+#if !defined(HAVE_MEMSET)
+# undef memset
+# define memset lzo_memset
+#endif
+
+#if 0
+# 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_LSIZE(bits) (1ul << (bits))
+#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1)
+
+#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits))
+#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1)
+
+#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2)))
+#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1)))
+
+#if !defined(SIZEOF_UNSIGNED)
+# if (UINT_MAX == 0xffff)
+# define SIZEOF_UNSIGNED 2
+# elif (UINT_MAX == LZO_0xffffffffL)
+# define SIZEOF_UNSIGNED 4
+# elif (UINT_MAX >= LZO_0xffffffffL)
+# define SIZEOF_UNSIGNED 8
+# else
+# error "SIZEOF_UNSIGNED"
+# endif
+#endif
+
+#if !defined(SIZEOF_UNSIGNED_LONG)
+# if (ULONG_MAX == LZO_0xffffffffL)
+# define SIZEOF_UNSIGNED_LONG 4
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+# define SIZEOF_UNSIGNED_LONG 8
+# else
+# error "SIZEOF_UNSIGNED_LONG"
+# endif
+#endif
+
+#if !defined(SIZEOF_SIZE_T)
+# define SIZEOF_SIZE_T SIZEOF_UNSIGNED
+#endif
+#if !defined(SIZE_T_MAX)
+# define SIZE_T_MAX LZO_UTYPE_MAX(SIZEOF_SIZE_T)
+#endif
+
+#if 1 && defined(__LZO_i386) && (UINT_MAX == LZO_0xffffffffL)
+# if !defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX == 0xffff)
+# define LZO_UNALIGNED_OK_2
+# endif
+# if !defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX == LZO_0xffffffffL)
+# define LZO_UNALIGNED_OK_4
+# endif
+#endif
+
+#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4)
+# if !defined(LZO_UNALIGNED_OK)
+# define LZO_UNALIGNED_OK
+# endif
+#endif
+
+#if defined(__LZO_NO_UNALIGNED)
+# undef LZO_UNALIGNED_OK
+# undef LZO_UNALIGNED_OK_2
+# undef LZO_UNALIGNED_OK_4
+#endif
+
+#if defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX != 0xffff)
+# error "LZO_UNALIGNED_OK_2 must not be defined on this system"
+#endif
+#if defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL)
+# error "LZO_UNALIGNED_OK_4 must not be defined on this system"
+#endif
+
+#if defined(__LZO_NO_ALIGNED)
+# undef LZO_ALIGNED_OK_4
+#endif
+
+#if defined(LZO_ALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL)
+# error "LZO_ALIGNED_OK_4 must not be defined on this system"
+#endif
+
+#define LZO_LITTLE_ENDIAN 1234
+#define LZO_BIG_ENDIAN 4321
+#define LZO_PDP_ENDIAN 3412
+
+#if !defined(LZO_BYTE_ORDER)
+# if defined(MFX_BYTE_ORDER)
+# define LZO_BYTE_ORDER MFX_BYTE_ORDER
+# elif defined(__LZO_i386)
+# define LZO_BYTE_ORDER LZO_LITTLE_ENDIAN
+# elif defined(BYTE_ORDER)
+# define LZO_BYTE_ORDER BYTE_ORDER
+# elif defined(__BYTE_ORDER)
+# define LZO_BYTE_ORDER __BYTE_ORDER
+# endif
+#endif
+
+#if defined(LZO_BYTE_ORDER)
+# if (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \
+ (LZO_BYTE_ORDER != LZO_BIG_ENDIAN)
+# error "invalid LZO_BYTE_ORDER"
+# endif
+#endif
+
+#if defined(LZO_UNALIGNED_OK) && !defined(LZO_BYTE_ORDER)
+# error "LZO_BYTE_ORDER is not defined"
+#endif
+
+#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY
+
+#if defined(NDEBUG) && !defined(LZO_DEBUG) && !defined(__LZO_CHECKER)
+# if defined(__GNUC__) && defined(__i386__)
+# if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY)
+# define LZO_OPTIMIZE_GNUC_i386
+# endif
+# endif
+#endif
+
+__LZO_EXTERN_C int __lzo_init_done;
+__LZO_EXTERN_C const lzo_byte __lzo_copyright[];
+LZO_EXTERN(const lzo_byte *) lzo_copyright(void);
+__LZO_EXTERN_C const lzo_uint32 _lzo_crc32_table[256];
+
+#define _LZO_STRINGIZE(x) #x
+#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x)
+
+#define _LZO_CONCAT2(a,b) a ## b
+#define _LZO_CONCAT3(a,b,c) a ## b ## c
+#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d
+#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
+
+#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b)
+#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c)
+#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d)
+#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e)
+
+#if 0
+
+#define __LZO_IS_COMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w))
+#define __LZO_QUERY_COMPRESS(i,il,o,ol,w,n,s) \
+ (*ol = (n)*(s), LZO_E_OK)
+
+#define __LZO_IS_DECOMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w))
+#define __LZO_QUERY_DECOMPRESS(i,il,o,ol,w,n,s) \
+ (*ol = (n)*(s), LZO_E_OK)
+
+#define __LZO_IS_OPTIMIZE_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w))
+#define __LZO_QUERY_OPTIMIZE(i,il,o,ol,w,n,s) \
+ (*ol = (n)*(s), LZO_E_OK)
+
+#endif
+
+#ifndef __LZO_PTR_H
+#define __LZO_PTR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# include <dos.h>
+# if 1 && defined(__WATCOMC__)
+# include <i86.h>
+ __LZO_EXTERN_C unsigned char _HShift;
+# define __LZO_HShift _HShift
+# elif 1 && defined(_MSC_VER)
+ __LZO_EXTERN_C unsigned short __near _AHSHIFT;
+# define __LZO_HShift ((unsigned) &_AHSHIFT)
+# elif defined(__LZO_WIN16)
+# define __LZO_HShift 3
+# else
+# define __LZO_HShift 12
+# endif
+# if !defined(_FP_SEG) && defined(FP_SEG)
+# define _FP_SEG FP_SEG
+# endif
+# if !defined(_FP_OFF) && defined(FP_OFF)
+# define _FP_OFF FP_OFF
+# endif
+#endif
+
+#if !defined(lzo_ptrdiff_t)
+# if (UINT_MAX >= LZO_0xffffffffL)
+ typedef ptrdiff_t lzo_ptrdiff_t;
+# else
+ typedef long lzo_ptrdiff_t;
+# endif
+#endif
+
+#if !defined(__LZO_HAVE_PTR_T)
+# if defined(lzo_ptr_t)
+# define __LZO_HAVE_PTR_T
+# endif
+#endif
+#if !defined(__LZO_HAVE_PTR_T)
+# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG)
+# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG)
+ typedef unsigned long lzo_ptr_t;
+ typedef long lzo_sptr_t;
+# define __LZO_HAVE_PTR_T
+# endif
+# endif
+#endif
+#if !defined(__LZO_HAVE_PTR_T)
+# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED)
+# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED)
+ typedef unsigned int lzo_ptr_t;
+ typedef int lzo_sptr_t;
+# define __LZO_HAVE_PTR_T
+# endif
+# endif
+#endif
+#if !defined(__LZO_HAVE_PTR_T)
+# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT)
+# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT)
+ typedef unsigned short lzo_ptr_t;
+ typedef short lzo_sptr_t;
+# define __LZO_HAVE_PTR_T
+# endif
+# endif
+#endif
+#if !defined(__LZO_HAVE_PTR_T)
+# if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P)
+# error "no suitable type for lzo_ptr_t"
+# else
+ typedef unsigned long lzo_ptr_t;
+ typedef long lzo_sptr_t;
+# define __LZO_HAVE_PTR_T
+# endif
+#endif
+
+#if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+#define PTR(a) ((lzo_bytep) (a))
+#define PTR_ALIGNED_4(a) ((_FP_OFF(a) & 3) == 0)
+#define PTR_ALIGNED2_4(a,b) (((_FP_OFF(a) | _FP_OFF(b)) & 3) == 0)
+#else
+#define PTR(a) ((lzo_ptr_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) ((lzo_ptrdiff_t) (PTR(a) - PTR(b)))
+#define pd(a,b) ((lzo_uint) ((a)-(b)))
+
+LZO_EXTERN(lzo_ptr_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_int32 a_lzo_int32;
+ lzo_uint32 a_lzo_uint32;
+ ptrdiff_t a_ptrdiff_t;
+ lzo_ptrdiff_t a_lzo_ptrdiff_t;
+ lzo_ptr_t a_lzo_ptr_t;
+ lzo_voidp a_lzo_voidp;
+ void * a_void_p;
+ lzo_bytep a_lzo_bytep;
+ lzo_bytepp a_lzo_bytepp;
+ lzo_uintp a_lzo_uintp;
+ lzo_uint * a_lzo_uint_p;
+ lzo_uint32p a_lzo_uint32p;
+ lzo_uint32 * a_lzo_uint32_p;
+ unsigned char * a_uchar_p;
+ char * a_char_p;
+}
+lzo_full_align_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#define LZO_DETERMINISTIC
+
+#define LZO_DICT_USE_PTR
+#if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT)
+# undef LZO_DICT_USE_PTR
+#endif
+
+#if defined(LZO_DICT_USE_PTR)
+# define lzo_dict_t const lzo_bytep
+# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
+#else
+# define lzo_dict_t lzo_uint
+# define lzo_dict_p lzo_dict_t __LZO_MMODEL *
+#endif
+
+#if !defined(lzo_moff_t)
+#define lzo_moff_t lzo_uint
+#endif
+
+#endif
+
+LZO_PUBLIC(lzo_ptr_t)
+__lzo_ptr_linear(const lzo_voidp ptr)
+{
+ lzo_ptr_t p;
+
+#if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+ p = (((lzo_ptr_t)(_FP_SEG(ptr))) << (16 - __LZO_HShift)) + (_FP_OFF(ptr));
+#else
+ p = PTR_LINEAR(ptr);
+#endif
+
+ return p;
+}
+
+LZO_PUBLIC(unsigned)
+__lzo_align_gap(const lzo_voidp ptr, lzo_uint size)
+{
+ lzo_ptr_t p, s, n;
+
+ assert(size > 0);
+
+ p = __lzo_ptr_linear(ptr);
+ s = (lzo_ptr_t) (size - 1);
+#if 0
+ assert((size & (size - 1)) == 0);
+ n = ((p + s) & ~s) - p;
+#else
+ n = (((p + s) / size) * size) - p;
+#endif
+
+ assert((long)n >= 0);
+ assert(n <= s);
+
+ return (unsigned)n;
+}
+
+#ifndef __LZO_UTIL_H
+#define __LZO_UTIL_H
+
+#ifndef __LZO_CONF_H
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if 1 && defined(HAVE_MEMCPY)
+#if !defined(__LZO_DOS16) && !defined(__LZO_WIN16)
+
+#define MEMCPY8_DS(dest,src,len) \
+ memcpy(dest,src,len); \
+ dest += len; \
+ src += len
+
+#endif
+#endif
+
+#if 0 && !defined(MEMCPY8_DS)
+
+#define MEMCPY8_DS(dest,src,len) \
+ { do { \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ len -= 8; \
+ } while (len > 0); }
+
+#endif
+
+#if !defined(MEMCPY8_DS)
+
+#define MEMCPY8_DS(dest,src,len) \
+ { register lzo_uint __l = (len) / 8; \
+ do { \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ *dest++ = *src++; \
+ } while (--__l > 0); }
+
+#endif
+
+#define MEMCPY_DS(dest,src,len) \
+ do *dest++ = *src++; \
+ while (--len > 0)
+
+#define MEMMOVE_DS(dest,src,len) \
+ do *dest++ = *src++; \
+ while (--len > 0)
+
+#if 0 && defined(LZO_OPTIMIZE_GNUC_i386)
+
+#define BZERO8_PTR(s,l,n) \
+__asm__ __volatile__( \
+ "movl %0,%%eax \n" \
+ "movl %1,%%edi \n" \
+ "movl %2,%%ecx \n" \
+ "cld \n" \
+ "rep \n" \
+ "stosl %%eax,(%%edi) \n" \
+ : \
+ :"g" (0),"g" (s),"g" (n) \
+ :"eax","edi","ecx", "memory", "cc" \
+)
+
+#elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET)
+
+#if 1
+#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n))
+#else
+#define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n))
+#endif
+
+#else
+
+#define BZERO8_PTR(s,l,n) \
+ lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n))
+
+#endif
+
+#if 0
+#if defined(__GNUC__) && defined(__i386__)
+
+unsigned char lzo_rotr8(unsigned char value, int shift);
+extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift)
+{
+ unsigned char result;
+
+ __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0"
+ : "=a"(result) : "g"(value), "c"(shift));
+ return result;
+}
+
+unsigned short lzo_rotr16(unsigned short value, int shift);
+extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift)
+{
+ unsigned short result;
+
+ __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0"
+ : "=a"(result) : "g"(value), "c"(shift));
+ return result;
+}
+
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+LZO_PUBLIC(lzo_bool)
+lzo_assert(int expr)
+{
+ return (expr) ? 1 : 0;
+}
+
+/* If you use the LZO library in a product, you *must* keep this
+ * copyright string in the executable of your product.
+ */
+
+const lzo_byte __lzo_copyright[] =
+#if !defined(__LZO_IN_MINLZO)
+ LZO_VERSION_STRING;
+#else
+ "\n\n\n"
+ "LZO real-time data compression library.\n"
+ "Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer\n"
+ "<markus.oberhumer@jk.uni-linz.ac.at>\n"
+ "http://www.oberhumer.com/opensource/lzo/\n"
+ "\n"
+ "LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE "\n"
+ "LZO build date: " __DATE__ " " __TIME__ "\n\n"
+ "LZO special compilation options:\n"
+#ifdef __cplusplus
+ " __cplusplus\n"
+#endif
+#if defined(__PIC__)
+ " __PIC__\n"
+#elif defined(__pic__)
+ " __pic__\n"
+#endif
+#if (UINT_MAX < LZO_0xffffffffL)
+ " 16BIT\n"
+#endif
+#if defined(__LZO_STRICT_16BIT)
+ " __LZO_STRICT_16BIT\n"
+#endif
+#if (UINT_MAX > LZO_0xffffffffL)
+ " UINT_MAX=" _LZO_MEXPAND(UINT_MAX) "\n"
+#endif
+#if (ULONG_MAX > LZO_0xffffffffL)
+ " ULONG_MAX=" _LZO_MEXPAND(ULONG_MAX) "\n"
+#endif
+#if defined(LZO_BYTE_ORDER)
+ " LZO_BYTE_ORDER=" _LZO_MEXPAND(LZO_BYTE_ORDER) "\n"
+#endif
+#if defined(LZO_UNALIGNED_OK_2)
+ " LZO_UNALIGNED_OK_2\n"
+#endif
+#if defined(LZO_UNALIGNED_OK_4)
+ " LZO_UNALIGNED_OK_4\n"
+#endif
+#if defined(LZO_ALIGNED_OK_4)
+ " LZO_ALIGNED_OK_4\n"
+#endif
+#if defined(LZO_DICT_USE_PTR)
+ " LZO_DICT_USE_PTR\n"
+#endif
+#if defined(__LZO_QUERY_COMPRESS)
+ " __LZO_QUERY_COMPRESS\n"
+#endif
+#if defined(__LZO_QUERY_DECOMPRESS)
+ " __LZO_QUERY_DECOMPRESS\n"
+#endif
+#if defined(__LZO_IN_MINILZO)
+ " __LZO_IN_MINILZO\n"
+#endif
+ "\n\n"
+ "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__
+#if defined(__GNUC__) && defined(__VERSION__)
+ " by gcc " __VERSION__
+#elif defined(__BORLANDC__)
+ " by Borland C " _LZO_MEXPAND(__BORLANDC__)
+#elif defined(_MSC_VER)
+ " by Microsoft C " _LZO_MEXPAND(_MSC_VER)
+#elif defined(__PUREC__)
+ " by Pure C " _LZO_MEXPAND(__PUREC__)
+#elif defined(__SC__)
+ " by Symantec C " _LZO_MEXPAND(__SC__)
+#elif defined(__TURBOC__)
+ " by Turbo C " _LZO_MEXPAND(__TURBOC__)
+#elif defined(__WATCOMC__)
+ " by Watcom C " _LZO_MEXPAND(__WATCOMC__)
+#endif
+ " $\n"
+ "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer $\n";
+#endif
+
+LZO_PUBLIC(const lzo_byte *)
+lzo_copyright(void)
+{
+ return __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)
+lzo_adler32(lzo_uint32 adler, const lzo_byte *buf, lzo_uint len)
+{
+ lzo_uint32 s1 = adler & 0xffff;
+ lzo_uint32 s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == NULL)
+ return 1;
+
+ while (len > 0)
+ {
+ k = len < LZO_NMAX ? (int) 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;
+}
+
+LZO_PUBLIC(int)
+lzo_memcmp(const lzo_voidp s1, const lzo_voidp s2, lzo_uint len)
+{
+#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCMP)
+ return memcmp(s1,s2,len);
+#else
+ const lzo_byte *p1 = (const lzo_byte *) s1;
+ const lzo_byte *p2 = (const lzo_byte *) s2;
+ int d;
+
+ if (len > 0) do
+ {
+ d = *p1 - *p2;
+ if (d != 0)
+ return d;
+ p1++;
+ p2++;
+ }
+ while (--len > 0);
+ return 0;
+#endif
+}
+
+LZO_PUBLIC(lzo_voidp)
+lzo_memcpy(lzo_voidp dest, const lzo_voidp src, lzo_uint len)
+{
+#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCPY)
+ return memcpy(dest,src,len);
+#else
+ lzo_byte *p1 = (lzo_byte *) dest;
+ const lzo_byte *p2 = (const lzo_byte *) src;
+
+ if (len <= 0 || p1 == p2)
+ return dest;
+ do
+ *p1++ = *p2++;
+ while (--len > 0);
+ return dest;
+#endif
+}
+
+LZO_PUBLIC(lzo_voidp)
+lzo_memmove(lzo_voidp dest, const lzo_voidp src, lzo_uint len)
+{
+#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMMOVE)
+ return memmove(dest,src,len);
+#else
+ lzo_byte *p1 = (lzo_byte *) dest;
+ const lzo_byte *p2 = (const lzo_byte *) src;
+
+ if (len <= 0 || p1 == p2)
+ return dest;
+
+ if (p1 < p2)
+ {
+ do
+ *p1++ = *p2++;
+ while (--len > 0);
+ }
+ else
+ {
+ p1 += len;
+ p2 += len;
+ do
+ *--p1 = *--p2;
+ while (--len > 0);
+ }
+ return dest;
+#endif
+}
+
+LZO_PUBLIC(lzo_voidp)
+lzo_memset(lzo_voidp s, int c, lzo_uint len)
+{
+#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET)
+ return memset(s,c,len);
+#else
+ lzo_byte *p = (lzo_byte *) s;
+
+ if (len > 0) do
+ *p++ = LZO_BYTE(c);
+ while (--len > 0);
+ return s;
+#endif
+}
+
+#if 0
+# define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0)
+# define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0)
+#else
+# define IS_SIGNED(type) (((type) (-1)) < ((type) 0))
+# define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0))
+#endif
+
+#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
+
+static lzo_bool schedule_insns_bug(void);
+static lzo_bool strength_reduce_bug(int *);
+
+#if 0 || defined(LZO_DEBUG)
+#include <stdio.h>
+static lzo_bool __lzo_assert_fail(const char *s, unsigned line)
+{
+#if defined(__palmos__)
+ printf("LZO assertion failed in line %u: '%s'\n",line,s);
+#else
+ fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s);
+#endif
+ return 0;
+}
+# define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__))
+#else
+# define __lzo_assert(x) ((x) ? 1 : 0)
+#endif
+
+#undef COMPILE_TIME_ASSERT
+#if 0
+# define COMPILE_TIME_ASSERT(expr) r &= __lzo_assert(expr)
+#else
+# define COMPILE_TIME_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr)
+#endif
+
+static lzo_bool basic_integral_check(void)
+{
+ lzo_bool r = 1;
+
+ COMPILE_TIME_ASSERT(CHAR_BIT == 8);
+ COMPILE_TIME_ASSERT(sizeof(char) == 1);
+ COMPILE_TIME_ASSERT(sizeof(short) >= 2);
+ COMPILE_TIME_ASSERT(sizeof(long) >= 4);
+ COMPILE_TIME_ASSERT(sizeof(int) >= sizeof(short));
+ COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(int));
+
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint) == sizeof(lzo_int));
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == sizeof(lzo_int32));
+
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= 4);
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= sizeof(unsigned));
+#if defined(__LZO_STRICT_16BIT)
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint) == 2);
+#else
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= 4);
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= sizeof(unsigned));
+#endif
+
+#if (USHRT_MAX == 65535u)
+ COMPILE_TIME_ASSERT(sizeof(short) == 2);
+#elif (USHRT_MAX == LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(short) == 4);
+#elif (USHRT_MAX >= LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(short) > 4);
+#endif
+#if (UINT_MAX == 65535u)
+ COMPILE_TIME_ASSERT(sizeof(int) == 2);
+#elif (UINT_MAX == LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(int) == 4);
+#elif (UINT_MAX >= LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(int) > 4);
+#endif
+#if (ULONG_MAX == 65535ul)
+ COMPILE_TIME_ASSERT(sizeof(long) == 2);
+#elif (ULONG_MAX == LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(long) == 4);
+#elif (ULONG_MAX >= LZO_0xffffffffL)
+ COMPILE_TIME_ASSERT(sizeof(long) > 4);
+#endif
+
+#if defined(SIZEOF_UNSIGNED)
+ COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED == sizeof(unsigned));
+#endif
+#if defined(SIZEOF_UNSIGNED_LONG)
+ COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long));
+#endif
+#if defined(SIZEOF_UNSIGNED_SHORT)
+ COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short));
+#endif
+#if !defined(__LZO_IN_MINILZO)
+#if defined(SIZEOF_SIZE_T)
+ COMPILE_TIME_ASSERT(SIZEOF_SIZE_T == sizeof(size_t));
+#endif
+#endif
+
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned char));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned short));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned long));
+ COMPILE_TIME_ASSERT(IS_SIGNED(short));
+ COMPILE_TIME_ASSERT(IS_SIGNED(int));
+ COMPILE_TIME_ASSERT(IS_SIGNED(long));
+
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint32));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint));
+ COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int32));
+ COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int));
+
+ COMPILE_TIME_ASSERT(INT_MAX == LZO_STYPE_MAX(sizeof(int)));
+ COMPILE_TIME_ASSERT(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned)));
+ COMPILE_TIME_ASSERT(LONG_MAX == LZO_STYPE_MAX(sizeof(long)));
+ COMPILE_TIME_ASSERT(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long)));
+ COMPILE_TIME_ASSERT(SHRT_MAX == LZO_STYPE_MAX(sizeof(short)));
+ COMPILE_TIME_ASSERT(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short)));
+ COMPILE_TIME_ASSERT(LZO_UINT32_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint32)));
+ COMPILE_TIME_ASSERT(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint)));
+#if !defined(__LZO_IN_MINILZO)
+ COMPILE_TIME_ASSERT(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t)));
+#endif
+
+ r &= __lzo_assert(LZO_BYTE(257) == 1);
+
+ return r;
+}
+
+static lzo_bool basic_ptr_check(void)
+{
+ lzo_bool r = 1;
+
+ COMPILE_TIME_ASSERT(sizeof(char *) >= sizeof(int));
+ COMPILE_TIME_ASSERT(sizeof(lzo_byte *) >= sizeof(char *));
+
+ COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_byte *));
+ COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_voidpp));
+ COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_bytepp));
+ COMPILE_TIME_ASSERT(sizeof(lzo_voidp) >= sizeof(lzo_uint));
+
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_voidp));
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_sptr_t));
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) >= sizeof(lzo_uint));
+
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= 4);
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t));
+
+ COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t));
+ COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(lzo_uint));
+
+#if defined(SIZEOF_CHAR_P)
+ COMPILE_TIME_ASSERT(SIZEOF_CHAR_P == sizeof(char *));
+#endif
+#if defined(SIZEOF_PTRDIFF_T)
+ COMPILE_TIME_ASSERT(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t));
+#endif
+
+ COMPILE_TIME_ASSERT(IS_SIGNED(ptrdiff_t));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(size_t));
+ COMPILE_TIME_ASSERT(IS_SIGNED(lzo_ptrdiff_t));
+ COMPILE_TIME_ASSERT(IS_SIGNED(lzo_sptr_t));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_ptr_t));
+ COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_moff_t));
+
+ return r;
+}
+
+static lzo_bool ptr_check(void)
+{
+ lzo_bool r = 1;
+ int i;
+ char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_full_align_t)];
+ lzo_bytep wrkmem;
+ lzo_bytepp dict;
+ unsigned char x[4 * sizeof(lzo_full_align_t)];
+ long d;
+ lzo_full_align_t a;
+ lzo_full_align_t u;
+
+ for (i = 0; i < (int) sizeof(x); i++)
+ x[i] = LZO_BYTE(i);
+
+ wrkmem = LZO_PTR_ALIGN_UP((lzo_byte *)_wrkmem,sizeof(lzo_full_align_t));
+
+#if 0
+ dict = (lzo_bytepp) wrkmem;
+#else
+
+ u.a_lzo_bytep = wrkmem; dict = u.a_lzo_bytepp;
+#endif
+
+ d = (long) ((const lzo_bytep) dict - (const lzo_bytep) _wrkmem);
+ r &= __lzo_assert(d >= 0);
+ r &= __lzo_assert(d < (long) sizeof(lzo_full_align_t));
+
+ memset(&a,0,sizeof(a));
+ r &= __lzo_assert(a.a_lzo_voidp == NULL);
+
+ memset(&a,0xff,sizeof(a));
+ r &= __lzo_assert(a.a_ushort == USHRT_MAX);
+ r &= __lzo_assert(a.a_uint == UINT_MAX);
+ r &= __lzo_assert(a.a_ulong == ULONG_MAX);
+ r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX);
+ r &= __lzo_assert(a.a_lzo_uint32 == LZO_UINT32_MAX);
+
+ if (r == 1)
+ {
+ for (i = 0; i < 8; i++)
+ r &= __lzo_assert((const lzo_voidp) (&dict[i]) == (const lzo_voidp) (&wrkmem[i * sizeof(lzo_byte *)]));
+ }
+
+ memset(&a,0,sizeof(a));
+ r &= __lzo_assert(a.a_char_p == NULL);
+ r &= __lzo_assert(a.a_lzo_bytep == NULL);
+ r &= __lzo_assert(NULL == (void *)0);
+ if (r == 1)
+ {
+ for (i = 0; i < 10; i++)
+ dict[i] = wrkmem;
+ BZERO8_PTR(dict+1,sizeof(dict[0]),8);
+ r &= __lzo_assert(dict[0] == wrkmem);
+ for (i = 1; i < 9; i++)
+ r &= __lzo_assert(dict[i] == NULL);
+ r &= __lzo_assert(dict[9] == wrkmem);
+ }
+
+ if (r == 1)
+ {
+ unsigned k = 1;
+ const unsigned n = (unsigned) sizeof(lzo_uint32);
+ lzo_byte *p0;
+ lzo_byte *p1;
+
+ k += __lzo_align_gap(&x[k],n);
+ p0 = (lzo_bytep) &x[k];
+#if defined(PTR_LINEAR)
+ r &= __lzo_assert((PTR_LINEAR(p0) & (n-1)) == 0);
+#else
+ r &= __lzo_assert(n == 4);
+ r &= __lzo_assert(PTR_ALIGNED_4(p0));
+#endif
+
+ r &= __lzo_assert(k >= 1);
+ p1 = (lzo_bytep) &x[1];
+ r &= __lzo_assert(PTR_GE(p0,p1));
+
+ r &= __lzo_assert(k < 1+n);
+ p1 = (lzo_bytep) &x[1+n];
+ r &= __lzo_assert(PTR_LT(p0,p1));
+
+ if (r == 1)
+ {
+ lzo_uint32 v0, v1;
+#if 0
+ v0 = * (lzo_uint32 *) &x[k];
+ v1 = * (lzo_uint32 *) &x[k+n];
+#else
+
+ u.a_uchar_p = &x[k];
+ v0 = *u.a_lzo_uint32_p;
+ u.a_uchar_p = &x[k+n];
+ v1 = *u.a_lzo_uint32_p;
+#endif
+ r &= __lzo_assert(v0 > 0);
+ r &= __lzo_assert(v1 > 0);
+ }
+ }
+
+ return r;
+}
+
+LZO_PUBLIC(int)
+_lzo_config_check(void)
+{
+ lzo_bool r = 1;
+ int i;
+ union {
+ lzo_uint32 a;
+ unsigned short b;
+ lzo_uint32 aa[4];
+ unsigned char x[4*sizeof(lzo_full_align_t)];
+ } u;
+
+ COMPILE_TIME_ASSERT( (int) ((unsigned char) ((signed char) -1)) == 255);
+ COMPILE_TIME_ASSERT( (((unsigned char)128) << (int)(8*sizeof(int)-8)) < 0);
+
+#if 0
+ r &= __lzo_assert((const void *)&u == (const void *)&u.a);
+ r &= __lzo_assert((const void *)&u == (const void *)&u.b);
+ r &= __lzo_assert((const void *)&u == (const void *)&u.x[0]);
+ r &= __lzo_assert((const void *)&u == (const void *)&u.aa[0]);
+#endif
+
+ r &= basic_integral_check();
+ r &= basic_ptr_check();
+ if (r != 1)
+ return LZO_E_ERROR;
+
+ u.a = 0; u.b = 0;
+ for (i = 0; i < (int) sizeof(u.x); i++)
+ u.x[i] = LZO_BYTE(i);
+
+#if defined(LZO_BYTE_ORDER)
+ if (r == 1)
+ {
+# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL);
+ unsigned short b = (unsigned short) (u.b & 0xffff);
+ r &= __lzo_assert(a == 0x03020100L);
+ r &= __lzo_assert(b == 0x0100);
+# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN)
+ lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32);
+ unsigned short b = u.b >> (8 * sizeof(u.b) - 16);
+ r &= __lzo_assert(a == 0x00010203L);
+ r &= __lzo_assert(b == 0x0001);
+# else
+# error "invalid LZO_BYTE_ORDER"
+# endif
+ }
+#endif
+
+#if defined(LZO_UNALIGNED_OK_2)
+ COMPILE_TIME_ASSERT(sizeof(short) == 2);
+ if (r == 1)
+ {
+ unsigned short b[4];
+
+ for (i = 0; i < 4; i++)
+ b[i] = * (const unsigned short *) &u.x[i];
+
+# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ r &= __lzo_assert(b[0] == 0x0100);
+ r &= __lzo_assert(b[1] == 0x0201);
+ r &= __lzo_assert(b[2] == 0x0302);
+ r &= __lzo_assert(b[3] == 0x0403);
+# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN)
+ r &= __lzo_assert(b[0] == 0x0001);
+ r &= __lzo_assert(b[1] == 0x0102);
+ r &= __lzo_assert(b[2] == 0x0203);
+ r &= __lzo_assert(b[3] == 0x0304);
+# endif
+ }
+#endif
+
+#if defined(LZO_UNALIGNED_OK_4)
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4);
+ if (r == 1)
+ {
+ lzo_uint32 a[4];
+
+ for (i = 0; i < 4; i++)
+ a[i] = * (const lzo_uint32 *) &u.x[i];
+
+# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ r &= __lzo_assert(a[0] == 0x03020100L);
+ r &= __lzo_assert(a[1] == 0x04030201L);
+ r &= __lzo_assert(a[2] == 0x05040302L);
+ r &= __lzo_assert(a[3] == 0x06050403L);
+# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN)
+ r &= __lzo_assert(a[0] == 0x00010203L);
+ r &= __lzo_assert(a[1] == 0x01020304L);
+ r &= __lzo_assert(a[2] == 0x02030405L);
+ r &= __lzo_assert(a[3] == 0x03040506L);
+# endif
+ }
+#endif
+
+#if defined(LZO_ALIGNED_OK_4)
+ COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4);
+#endif
+
+ COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t));
+
+#if defined(__LZO_IN_MINLZO)
+ if (r == 1)
+ {
+ lzo_uint32 adler;
+ adler = lzo_adler32(0, NULL, 0);
+ adler = lzo_adler32(adler, lzo_copyright(), 200);
+ r &= __lzo_assert(adler == 0xc76f1751L);
+ }
+#endif
+
+ if (r == 1)
+ {
+ r &= __lzo_assert(!schedule_insns_bug());
+ }
+
+ if (r == 1)
+ {
+ static int x[3];
+ static unsigned xn = 3;
+ register unsigned j;
+
+ for (j = 0; j < xn; j++)
+ x[j] = (int)j - 3;
+ r &= __lzo_assert(!strength_reduce_bug(x));
+ }
+
+ if (r == 1)
+ {
+ r &= ptr_check();
+ }
+
+ return r == 1 ? LZO_E_OK : LZO_E_ERROR;
+}
+
+static lzo_bool schedule_insns_bug(void)
+{
+#if defined(__LZO_CHECKER)
+ return 0;
+#else
+ const int clone[] = {1, 2, 0};
+ const int *q;
+ q = clone;
+ return (*q) ? 0 : 1;
+#endif
+}
+
+static lzo_bool strength_reduce_bug(int *x)
+{
+ return x[0] != -3 || x[1] != -2 || x[2] != -1;
+}
+
+#undef COMPILE_TIME_ASSERT
+
+int __lzo_init_done = 0;
+
+LZO_PUBLIC(int)
+__lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5,
+ int s6, int s7, int s8, int s9)
+{
+ int r;
+
+ __lzo_init_done = 1;
+
+ 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)) &&
+ (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_compress_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)
+
+LZO_EXTERN(int)
+__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7);
+
+LZO_PUBLIC(int)
+__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7)
+{
+ if (v == 0 || v > 0x1010)
+ return LZO_E_ERROR;
+ return __lzo_init2(v,s1,s2,s3,s4,s5,-1,-1,s6,s7);
+}
+
+#endif
+
+#define do_compress _lzo1x_1_do_compress
+
+#define LZO_NEED_DICT_H
+#define D_BITS 14
+#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5)
+#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
+
+#ifndef __LZO_CONFIG1X_H
+#define __LZO_CONFIG1X_H
+
+#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z)
+# define LZO1X
+#endif
+
+#if !defined(__LZO_IN_MINILZO)
+#include <lzo1x.h>
+#endif
+
+#define LZO_EOF_CODE
+#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
+
+#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 < 8 || D_BITS > 18)
+# error "invalid D_BITS"
+#endif
+#if (DL_BITS < 8 || 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
+
+#if (DL_MIN_LEN == 3)
+# define _DV2_A(p,shift1,shift2) \
+ (((( (lzo_uint32)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2])
+# define _DV2_B(p,shift1,shift2) \
+ (((( (lzo_uint32)((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_uint32)(p[0]) << shift1) ^ p[1])
+# define _DV2_B(p,shift1,shift2) \
+ (( (lzo_uint32)(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_uint32)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0])
+#define DS2(p,s1,s2) \
+ (((((lzo_uint32)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0])
+#define DX2(p,s1,s2) \
+ (((((lzo_uint32)((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
+# 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
+# define DVAL_FIRST(dv,p) dv = _DV_A((p),5)
+# define DVAL_NEXT(dv,p) \
+ dv ^= (lzo_uint32)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2])
+# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5)
+# define DVAL_LOOKAHEAD DL_MIN_LEN
+
+#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B)
+# define __LZO_HASH_INCREMENTAL
+# define DVAL_FIRST(dv,p) dv = _DV_B((p),5)
+# define DVAL_NEXT(dv,p) \
+ dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint32)(p[2]) << (2*5)))
+# define _DINDEX(dv,p) ((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)
+static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p)
+{
+ lzo_uint32 df;
+ DVAL_FIRST(df,(p));
+ assert(DINDEX(dv,p) == DINDEX(df,p));
+}
+#else
+# define DVAL_ASSERT(dv,p) ((void) 0)
+#endif
+#endif
+
+#if defined(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_uint) ((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 defined(LZO_DICT_USE_PTR)
+
+#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
+ (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset)
+
+#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
+ (BOUNDS_CHECKING_OFF_IN_EXPR( \
+ (PTR_LT(m_pos,in) || \
+ (m_off = (lzo_moff_t) 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 = (lzo_moff_t) ((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) \
+ ((lzo_moff_t) ((ip)-(in)) <= m_off || \
+ ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \
+ (m_pos = (ip) - (m_off), 0) )
+
+#endif
+
+#if defined(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 DO_COMPRESS lzo1x_1_compress
+
+static
+lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+#if 0 && defined(__GNUC__) && defined(__i386__)
+ register const lzo_byte *ip __asm__("%esi");
+#else
+ register const lzo_byte *ip;
+#endif
+ lzo_byte *op;
+ const lzo_byte * const in_end = in + in_len;
+ const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5;
+ const lzo_byte *ii;
+ lzo_dict_p const dict = (lzo_dict_p) wrkmem;
+
+ op = out;
+ ip = in;
+ ii = ip;
+
+ ip += 4;
+ for (;;)
+ {
+#if 0 && defined(__GNUC__) && defined(__i386__)
+ register const lzo_byte *m_pos __asm__("%edi");
+#else
+ register const lzo_byte *m_pos;
+#endif
+ lzo_moff_t m_off;
+ lzo_uint m_len;
+ lzo_uint dindex;
+
+ 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 1 && defined(LZO_UNALIGNED_OK_2)
+ if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip)
+#else
+ if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
+#endif
+ {
+ }
+ else
+ {
+ if (m_pos[2] == ip[2])
+ {
+#if 0
+ if (m_off <= M2_MAX_OFFSET)
+ goto match;
+ if (lit <= 3)
+ goto match;
+ if (lit == 3)
+ {
+ assert(op - 2 > out); op[-2] |= LZO_BYTE(3);
+ *op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
+ goto code_match;
+ }
+ if (m_pos[3] == ip[3])
+#endif
+ goto match;
+ }
+ else
+ {
+#if 0
+#if 0
+ if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3)
+#else
+ if (m_off <= M1_MAX_OFFSET && lit == 3)
+#endif
+ {
+ register lzo_uint t;
+
+ t = lit;
+ assert(op - 2 > out); op[-2] |= LZO_BYTE(t);
+ do *op++ = *ii++; while (--t > 0);
+ assert(ii == ip);
+ m_off -= 1;
+ *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2));
+ *op++ = LZO_BYTE(m_off >> 2);
+ ip += 2;
+ goto match_done;
+ }
+#endif
+ }
+ }
+
+literal:
+ UPDATE_I(dict,0,dindex,ip,in);
+ ++ip;
+ if (ip >= ip_end)
+ break;
+ continue;
+
+match:
+ UPDATE_I(dict,0,dindex,ip,in);
+ if (pd(ip,ii) > 0)
+ {
+ register lzo_uint t = pd(ip,ii);
+
+ if (t <= 3)
+ {
+ assert(op - 2 > out);
+ op[-2] |= LZO_BYTE(t);
+ }
+ else if (t <= 18)
+ *op++ = LZO_BYTE(t - 3);
+ else
+ {
+ register lzo_uint tt = t - 18;
+
+ *op++ = 0;
+ while (tt > 255)
+ {
+ tt -= 255;
+ *op++ = 0;
+ }
+ assert(tt > 0);
+ *op++ = LZO_BYTE(tt);
+ }
+ do *op++ = *ii++; while (--t > 0);
+ }
+
+ assert(ii == ip);
+ ip += 3;
+ if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ ||
+ m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++
+#ifdef LZO1Y
+ || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++
+ || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++
+#endif
+ )
+ {
+ --ip;
+ m_len = ip - ii;
+ assert(m_len >= 3); assert(m_len <= M2_MAX_LEN);
+
+ if (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;
+ *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
+ goto m3_m4_offset;
+ }
+ else
+#if defined(LZO1X)
+ {
+ m_off -= 0x4000;
+ assert(m_off > 0); assert(m_off <= 0x7fff);
+ *op++ = LZO_BYTE(M4_MARKER |
+ ((m_off & 0x4000) >> 11) | (m_len - 2));
+ goto m3_m4_offset;
+ }
+#elif defined(LZO1Y)
+ goto m4_match;
+#endif
+ }
+ else
+ {
+ {
+ const lzo_byte *end = in_end;
+ const lzo_byte *m = m_pos + M2_MAX_LEN + 1;
+ while (ip < end && *m == *ip)
+ m++, ip++;
+ m_len = (ip - ii);
+ }
+ assert(m_len > M2_MAX_LEN);
+
+ if (m_off <= M3_MAX_OFFSET)
+ {
+ m_off -= 1;
+ if (m_len <= 33)
+ *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
+ else
+ {
+ m_len -= 33;
+ *op++ = M3_MARKER | 0;
+ goto m3_m4_len;
+ }
+ }
+ else
+ {
+#if defined(LZO1Y)
+m4_match:
+#endif
+ m_off -= 0x4000;
+ assert(m_off > 0); assert(m_off <= 0x7fff);
+ if (m_len <= M4_MAX_LEN)
+ *op++ = LZO_BYTE(M4_MARKER |
+ ((m_off & 0x4000) >> 11) | (m_len - 2));
+ else
+ {
+ m_len -= M4_MAX_LEN;
+ *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11));
+m3_m4_len:
+ while (m_len > 255)
+ {
+ m_len -= 255;
+ *op++ = 0;
+ }
+ assert(m_len > 0);
+ *op++ = LZO_BYTE(m_len);
+ }
+ }
+
+m3_m4_offset:
+ *op++ = LZO_BYTE((m_off & 63) << 2);
+ *op++ = LZO_BYTE(m_off >> 6);
+ }
+
+#if 0
+match_done:
+#endif
+ ii = ip;
+ if (ip >= ip_end)
+ break;
+ }
+
+ *out_len = op - out;
+ return pd(in_end,ii);
+}
+
+LZO_PUBLIC(int)
+DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+{
+ lzo_byte *op = out;
+ lzo_uint t;
+
+#if defined(__LZO_QUERY_COMPRESS)
+ if (__LZO_IS_COMPRESS_QUERY(in,in_len,out,out_len,wrkmem))
+ return __LZO_QUERY_COMPRESS(in,in_len,out,out_len,wrkmem,D_SIZE,lzo_sizeof(lzo_dict_t));
+#endif
+
+ if (in_len <= M2_MAX_LEN + 5)
+ t = in_len;
+ else
+ {
+ t = do_compress(in,in_len,op,out_len,wrkmem);
+ op += *out_len;
+ }
+
+ if (t > 0)
+ {
+ const lzo_byte *ii = in + in_len - t;
+
+ if (op == out && t <= 238)
+ *op++ = LZO_BYTE(17 + t);
+ else if (t <= 3)
+ op[-2] |= LZO_BYTE(t);
+ else if (t <= 18)
+ *op++ = LZO_BYTE(t - 3);
+ else
+ {
+ lzo_uint tt = t - 18;
+
+ *op++ = 0;
+ while (tt > 255)
+ {
+ tt -= 255;
+ *op++ = 0;
+ }
+ assert(tt > 0);
+ *op++ = LZO_BYTE(tt);
+ }
+ do *op++ = *ii++; while (--t > 0);
+ }
+
+ *op++ = M4_MARKER | 1;
+ *op++ = 0;
+ *op++ = 0;
+
+ *out_len = op - out;
+ return LZO_E_OK;
+}
+
+#undef do_compress
+#undef DO_COMPRESS
+#undef LZO_HASH
+
+#undef LZO_TEST_DECOMPRESS_OVERRUN
+#undef LZO_TEST_DECOMPRESS_OVERRUN_INPUT
+#undef LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT
+#undef LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND
+#undef DO_DECOMPRESS
+#define DO_DECOMPRESS lzo1x_decompress
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN)
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT)
+# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2
+# endif
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2
+# endif
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND
+# endif
+#endif
+
+#undef TEST_IP
+#undef TEST_OP
+#undef TEST_LOOKBEHIND
+#undef NEED_IP
+#undef NEED_OP
+#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_DECOMPRESS_OVERRUN_INPUT)
+# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1)
+# define TEST_IP (ip < ip_end)
+# endif
+# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2)
+# define NEED_IP(x) \
+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1)
+# define TEST_OP (op <= op_end)
+# endif
+# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2)
+# undef TEST_OP
+# define NEED_OP(x) \
+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun
+#else
+# define TEST_LOOKBEHIND(m_pos,op) ((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
+#else
+# define TEST_IP 1
+#endif
+#if defined(TEST_OP)
+# define HAVE_TEST_OP
+#else
+# define TEST_OP 1
+#endif
+
+#if defined(NEED_IP)
+# define HAVE_NEED_IP
+#else
+# define NEED_IP(x) ((void) 0)
+#endif
+#if defined(NEED_OP)
+# define HAVE_NEED_OP
+#else
+# define NEED_OP(x) ((void) 0)
+#endif
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+# define HAVE_ANY_IP
+#endif
+#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
+# define HAVE_ANY_OP
+#endif
+
+#undef __COPY4
+#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
+
+#undef COPY4
+#if defined(LZO_UNALIGNED_OK_4)
+# define COPY4(dst,src) __COPY4(dst,src)
+#elif defined(LZO_ALIGNED_OK_4)
+# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src))
+#endif
+
+#if defined(DO_DECOMPRESS)
+LZO_PUBLIC(int)
+DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+#endif
+{
+ register lzo_byte *op;
+ register const lzo_byte *ip;
+ register lzo_uint t;
+#if defined(COPY_DICT)
+ lzo_uint m_off;
+ const lzo_byte *dict_end;
+#else
+ register const lzo_byte *m_pos;
+#endif
+
+ const lzo_byte * const ip_end = in + in_len;
+#if defined(HAVE_ANY_OP)
+ lzo_byte * const op_end = out + *out_len;
+#endif
+#if defined(LZO1Z)
+ lzo_uint last_m_off = 0;
+#endif
+
+ LZO_UNUSED(wrkmem);
+
+#if defined(__LZO_QUERY_DECOMPRESS)
+ if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem))
+ return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0);
+#endif
+
+#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;
+
+ if (*ip > 17)
+ {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ goto first_literal_run;
+ }
+
+ while (TEST_IP && TEST_OP)
+ {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+ }
+ assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (PTR_ALIGNED2_4(op,ip))
+ {
+#endif
+ COPY4(op,ip);
+ op += 4; ip += 4;
+ if (--t > 0)
+ {
+ if (t >= 4)
+ {
+ do {
+ 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 !defined(LZO_UNALIGNED_OK_4)
+ }
+ else
+#endif
+#endif
+#if !defined(LZO_UNALIGNED_OK_4)
+ {
+ *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_LOOKBEHIND(m_pos,out); NEED_OP(3);
+ *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+ goto match_done;
+
+ while (TEST_IP && TEST_OP)
+ {
+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_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1);
+ goto copy_match;
+#endif
+ }
+ else if (t >= 32)
+ {
+ t &= 31;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+ }
+#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 defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ m_pos = op - 1;
+ m_pos -= (* (const lzo_ushortp) 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)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+ }
+#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 defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ m_pos -= (* (const lzo_ushortp) 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 = 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_LOOKBEHIND(m_pos,out); 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_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1);
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ 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
+ COPY4(op,m_pos);
+ op += 4; m_pos += 4; t -= 4 - (3 - 1);
+ do {
+ 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); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ t = *ip++;
+ }
+ }
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
+ *out_len = op - out;
+ return LZO_E_EOF_NOT_FOUND;
+#endif
+
+eof_found:
+ assert(t == 1);
+ *out_len = 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 = op - out;
+ return LZO_E_INPUT_OVERRUN;
+#endif
+
+#if defined(HAVE_NEED_OP)
+output_overrun:
+ *out_len = op - out;
+ return LZO_E_OUTPUT_OVERRUN;
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+lookbehind_overrun:
+ *out_len = op - out;
+ return LZO_E_LOOKBEHIND_OVERRUN;
+#endif
+}
+
+#define LZO_TEST_DECOMPRESS_OVERRUN
+#undef DO_DECOMPRESS
+#define DO_DECOMPRESS lzo1x_decompress_safe
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN)
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT)
+# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2
+# endif
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2
+# endif
+# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND
+# endif
+#endif
+
+#undef TEST_IP
+#undef TEST_OP
+#undef TEST_LOOKBEHIND
+#undef NEED_IP
+#undef NEED_OP
+#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_DECOMPRESS_OVERRUN_INPUT)
+# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1)
+# define TEST_IP (ip < ip_end)
+# endif
+# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2)
+# define NEED_IP(x) \
+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT)
+# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1)
+# define TEST_OP (op <= op_end)
+# endif
+# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2)
+# undef TEST_OP
+# define NEED_OP(x) \
+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
+# endif
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun
+#else
+# define TEST_LOOKBEHIND(m_pos,op) ((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
+#else
+# define TEST_IP 1
+#endif
+#if defined(TEST_OP)
+# define HAVE_TEST_OP
+#else
+# define TEST_OP 1
+#endif
+
+#if defined(NEED_IP)
+# define HAVE_NEED_IP
+#else
+# define NEED_IP(x) ((void) 0)
+#endif
+#if defined(NEED_OP)
+# define HAVE_NEED_OP
+#else
+# define NEED_OP(x) ((void) 0)
+#endif
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP)
+# define HAVE_ANY_IP
+#endif
+#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP)
+# define HAVE_ANY_OP
+#endif
+
+#undef __COPY4
+#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
+
+#undef COPY4
+#if defined(LZO_UNALIGNED_OK_4)
+# define COPY4(dst,src) __COPY4(dst,src)
+#elif defined(LZO_ALIGNED_OK_4)
+# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src))
+#endif
+
+#if defined(DO_DECOMPRESS)
+LZO_PUBLIC(int)
+DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uintp out_len,
+ lzo_voidp wrkmem )
+#endif
+{
+ register lzo_byte *op;
+ register const lzo_byte *ip;
+ register lzo_uint t;
+#if defined(COPY_DICT)
+ lzo_uint m_off;
+ const lzo_byte *dict_end;
+#else
+ register const lzo_byte *m_pos;
+#endif
+
+ const lzo_byte * const ip_end = in + in_len;
+#if defined(HAVE_ANY_OP)
+ lzo_byte * const op_end = out + *out_len;
+#endif
+#if defined(LZO1Z)
+ lzo_uint last_m_off = 0;
+#endif
+
+ LZO_UNUSED(wrkmem);
+
+#if defined(__LZO_QUERY_DECOMPRESS)
+ if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem))
+ return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0);
+#endif
+
+#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;
+
+ if (*ip > 17)
+ {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ assert(t > 0); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ goto first_literal_run;
+ }
+
+ while (TEST_IP && TEST_OP)
+ {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+ }
+ assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ if (PTR_ALIGNED2_4(op,ip))
+ {
+#endif
+ COPY4(op,ip);
+ op += 4; ip += 4;
+ if (--t > 0)
+ {
+ if (t >= 4)
+ {
+ do {
+ 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 !defined(LZO_UNALIGNED_OK_4)
+ }
+ else
+#endif
+#endif
+#if !defined(LZO_UNALIGNED_OK_4)
+ {
+ *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_LOOKBEHIND(m_pos,out); NEED_OP(3);
+ *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
+#endif
+ goto match_done;
+
+ while (TEST_IP && TEST_OP)
+ {
+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_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1);
+ goto copy_match;
+#endif
+ }
+ else if (t >= 32)
+ {
+ t &= 31;
+ if (t == 0)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+ }
+#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 defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ m_pos = op - 1;
+ m_pos -= (* (const lzo_ushortp) 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)
+ {
+ NEED_IP(1);
+ while (*ip == 0)
+ {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+ }
+#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 defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN)
+ m_pos -= (* (const lzo_ushortp) 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 = 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_LOOKBEHIND(m_pos,out); 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_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1);
+#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
+#if !defined(LZO_UNALIGNED_OK_4)
+ 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
+ COPY4(op,m_pos);
+ op += 4; m_pos += 4; t -= 4 - (3 - 1);
+ do {
+ 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); NEED_OP(t); NEED_IP(t+1);
+ do *op++ = *ip++; while (--t > 0);
+ t = *ip++;
+ }
+ }
+
+#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
+ *out_len = op - out;
+ return LZO_E_EOF_NOT_FOUND;
+#endif
+
+eof_found:
+ assert(t == 1);
+ *out_len = 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 = op - out;
+ return LZO_E_INPUT_OVERRUN;
+#endif
+
+#if defined(HAVE_NEED_OP)
+output_overrun:
+ *out_len = op - out;
+ return LZO_E_OUTPUT_OVERRUN;
+#endif
+
+#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND)
+lookbehind_overrun:
+ *out_len = op - out;
+ return LZO_E_LOOKBEHIND_OVERRUN;
+#endif
+}
+
+/***** End of minilzo.c *****/
+
diff --git a/distcc/lzo/minilzo.h b/distcc/lzo/minilzo.h
new file mode 100644
index 0000000..e3270f9
--- /dev/null
+++ b/distcc/lzo/minilzo.h
@@ -0,0 +1,100 @@
+/* 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) 2002 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 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.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus@oberhumer.com>
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+/*
+ * NOTE:
+ * the full LZO package can be found at
+ * http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#ifndef __MINILZO_H
+#define __MINILZO_H
+
+#define MINILZO_VERSION 0x1080
+
+#ifdef __LZOCONF_H
+# error "you cannot use both LZO and miniLZO"
+#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) (16384L * lzo_sizeof_dict_t))
+#define LZO1X_MEM_DECOMPRESS (0)
+
+
+/* compression */
+LZO_EXTERN(int)
+lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem );
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uintp dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* already included */
+
diff --git a/distcc/man/distcc.1 b/distcc/man/distcc.1
new file mode 100644
index 0000000..68e67f2
--- /dev/null
+++ b/distcc/man/distcc.1
@@ -0,0 +1,725 @@
+.TH distcc 1 "27 March 2008"
+.SH "NAME"
+distcc \- distributed C/C++/ObjC compiler with distcc-pump extensions
+.SH "SYNOPSIS"
+.B distcc
+.I <compiler> [COMPILER OPTIONS]
+.PP
+.B distcc
+.I [COMPILER OPTIONS]
+.PP
+.B <compiler>
+.I [COMPILER 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 enhancment called 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, 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-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 typically 25% slower because of processor overhead for
+encryption, although this can vary greatly depending on CPUs, network
+and the program being built.
+.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.
+
+The
+.B -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
+.B --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
+.B -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, with distcc-pump 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
+optionally 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 remove 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. To enjoy distcc-pump, you
+will really need 10 or more server CPUs. Wrap your build inside the pump
+command, here assuming 10 servers:
+
+.RS
+$ pump make -j20 CC=distcc
+.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"
+distcc-pump runs the prepreprocessor remotely too. To do so, the preprocessor
+must have access to all the files that it would have accessed if had been running
+locally. distcc-pump therefore gathers all of the recursively included headers,
+except the ones that are part of the compiler installation, 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, distcc-pump uses an incremental include analysis algorithm. The
+include server, which is a Python program started by the pump script wrapper,
+implements this algorithm.
+
+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 may not be
+necessary to do so again if all the include directives are unchanged (along with
+other conditions).
+
+For large builds, header files are included, on average, hundreds of times. 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 compilation on the server may
+drop by close to an order of magnitude over plain distcc. Additionally,
+compression time may drop by an order or two of magnitude over plain distcc's
+scheme of compressing the preprocessed files.
+
+As a result, distcc-pump mode is able to push out files up to about ten times
+faster than distcc. The total build time may drop 30-70% for large builds
+compared to plain distcc mode.
+.SH "OPTION SUMMARY"
+Most options passed to distcc are interpreted as compiler options.
+Two options are understood by distcc itself:
+.TP
+.B --help
+Displays summary instructions.
+.TP
+.B --version
+Displays the distcc client version.
+.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
+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.
+.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-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 machanism 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 -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
+ 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
+ OPTIONS = ,OPTION[OPTIONS]
+ OPTION = lzo | cpp
+ GLOBAL_OPTION = --randomize
+.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 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 for this host. Note: the build command must be
+wrapped in the pump script in order to start the include server.
+.TP
+.B --randomize
+Randomize the host list before execution.
+.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 distcc-pump. 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.
+.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 timeouts are not configurable at present.
+.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
+105
+Out of memory.
+.TP
+110
+Compiler not found.
+.TP
+111
+Recursive call to distcc.
+.TP
+116
+No hosts defined and fallbacks disabled.
+.PP
+(Others are listed in exitcode.h.)
+.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_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_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 "DCC_EMAILLOG_WHOM_TO_BLAME"
+The email address for discrepancy email; the default is "distcc-pump-errors".
+.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
+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. This should be fixed in gcc 3.4.
+.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
+The .o files produced by discc-pump 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
+Other known bugs may be documented on
+.I http://distcc.samba.org/
+.SH "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>.
+.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"
+distccd(1), ccache(1), gcc(1), make(1)
+.I http://distcc.samba.org/
+.I http://ccache.samba.org/
diff --git a/distcc/man/distccd.1 b/distcc/man/distccd.1
new file mode 100644
index 0000000..ee744f0
--- /dev/null
+++ b/distcc/man/distccd.1
@@ -0,0 +1,295 @@
+.TH distccd 1 "27 March 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, all clients are allowed. Unauthorized
+connections are rejected by closing the TCP connection immediately. A
+warning is logged on the server but nothing is sent ot the client.
+.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.
+.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.
+.SH "SEE ALSO"
+distcc(1), ccache(1), gcc(1), make(1)
+.I http://distcc.samba.org/
+.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 <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>.
diff --git a/distcc/man/distccmon-text.1 b/distcc/man/distccmon-text.1
new file mode 100644
index 0000000..7f7b159
--- /dev/null
+++ b/distcc/man/distccmon-text.1
@@ -0,0 +1,56 @@
+.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 <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>.
+.SH "SEE ALSO"
+.LP d
+distccd(1), ccache(1), gcc(1), make(1) http://distcc.samba.org/ http://ccache.samba.org/
diff --git a/distcc/mkinstalldirs b/distcc/mkinstalldirs
new file mode 100755
index 0000000..25a0791
--- /dev/null
+++ b/distcc/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# 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
diff --git a/distcc/packaging/RedHat/init.d/distcc b/distcc/packaging/RedHat/init.d/distcc
new file mode 100644
index 0000000..70d6d31
--- /dev/null
+++ b/distcc/packaging/RedHat/init.d/distcc
@@ -0,0 +1,287 @@
+#!/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
+ # goobuntu
+ DOMAIN=`cat /etc/sitename.install`
+ CONFIGDIR=/etc/site/current/distcc
+ NORESTART=$CONFIGDIR/no-restart
+else
+ # grhat
+ 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 /usr/bin/distccd ] || exit 0
+
+ALLOWFILE=""
+
+
+if test -f $CONFIGDIR/clients.allow; then
+ ALLOWFILE=$CONFIGDIR/clients.allow
+elif test -f $CONFIGDIR/$DOMAIN/clients.allow; then
+ ALLOWFILE=$CONFIGDIR/$DOMAIN/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
+
+
+rh_start() {
+ echo -n "Starting $PROG"
+
+ if [[ -f $NORESTART ]]
+ then
+ echo "failed -- $NORESTART present"
+ return 1
+ fi
+
+ #--- begin crosstool-specific configuration ---
+ # List directories which might contain installations of crosstool on this node
+ # This will let users compile on this node regardless of where crosstool
+ # is installed on client or server
+ # Neccessary because crosstool compilers are identified not just by
+ # a command name, but also by the directory they're in (if you have
+ # several toolchains built for a particular target).
+ COMPILERS=
+ # modern crosstool
+ test -d /usr/crosstool && COMPILERS="$COMPILERS /usr/crosstool/*/*/bin/*-[cg][+c][+c] /usr/crosstool/v*/*/*/bin/*-[cg][+c][+c] /usr/crosstool/v4/*/*/*/bin/*-[cg][+c][+c]"
+ # old crosstool (which stored everything in a directory named for the build system type)
+ test -d /opt/crosstool && COMPILERS="$COMPILERS /opt/crosstool/*/*/*/bin/*-[cg][+c][+c]"
+ test -d /home/build/buildtools/crosstool/v7 && COMPILERS="$COMPILERS /home/build/buildtools/crosstool/v7/*/*/bin/*-[cg][+c][+c]"
+ if test ! -d $CONFIGDIR; then
+ mkdir -p $CONFIGDIR
+ fi
+ CMDLIST=$CONFIGDIR/commands.allow
+ # Expand the wildcards in $COMPILERS, put one file per line, empty file if no match
+ echo $COMPILERS | tr '\040' '\012' > $CMDLIST
+ ENV="DISTCC_CMDLIST=$CMDLIST DISTCC_CMDLIST_NUMWORDS=5 TMPDIR=$TMPDIR"
+ #--- done crosstool-specific configuration ---
+
+ 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
+
+ #--- begin crosstool-specific configuration ---
+ # List directories which might contain installations of crosstool on this node
+ # This will let users compile on this node regardless of where crosstool
+ # is installed on client or server
+ # Neccessary because crosstool compilers are identified not just by
+ # a command name, but also by the directory they're in (if you have
+ # several toolchains built for a particular target).
+ COMPILERS=
+ # modern crosstool
+ test -d /usr/crosstool && COMPILERS="$COMPILERS /usr/crosstool/*/*/bin/*-[cg][+c][+c] /usr/crosstool/v*/*/*/bin/*-[cg][+c][+c] /usr/crosstool/v4/*/*/*/bin/*-[cg][+c][+c]"
+ # old crosstool (which stored everything in a directory named for the build system type)
+ test -d /opt/crosstool && COMPILERS="$COMPILERS /opt/crosstool/*/*/*/bin/*-[cg][+c][+c]"
+ test -d /home/build/buildtools/crosstool/v7 && COMPILERS="$COMPILERS /home/build/buildtools/crosstool/v7/*/*/bin/*-[cg][+c][+c]"
+ if test ! -d $CONFIGDIR; then
+ mkdir -p $CONFIGDIR
+ fi
+ CMDLIST=$CONFIGDIR/commands.allow
+ # Expand the wildcards in $COMPILERS, put one file per line, empty file if no match
+ echo $COMPILERS | tr '\040' '\012' > $CMDLIST
+ export DISTCC_CMDLIST=$CMDLIST
+ export DISTCC_CMDLIST_NUMWORDS=5
+ export TMPDIR=$TMPDIR
+
+ #--- done crosstool-specific configuration ---
+
+ start-stop-daemon --start --name distccd --pidfile $PIDFILE -m --chuid $USER --exec $EXEC -- $OPTIONS || log_end_msg 1
+ RETVAL=$?
+ log_end_msg 0
+ return $RETVAL
+}
+
+deb_stop() {
+ log_begin_msg "Shutting down $PROG..."
+ start-stop-daemon --stop --name distccd --exec $EXEC --retry 30 || \
+ log_success_msg "$PROG not running"
+ RETVAL=$?
+ log_end_msg 0
+ [ $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
+
diff --git a/distcc/packaging/RedHat/logrotate.d/distcc b/distcc/packaging/RedHat/logrotate.d/distcc
new file mode 100644
index 0000000..52429f7
--- /dev/null
+++ b/distcc/packaging/RedHat/logrotate.d/distcc
@@ -0,0 +1,13 @@
+# 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
+}
+
diff --git a/distcc/packaging/RedHat/xinetd.d/distcc b/distcc/packaging/RedHat/xinetd.d/distcc
new file mode 100644
index 0000000..ebd9bdc
--- /dev/null
+++ b/distcc/packaging/RedHat/xinetd.d/distcc
@@ -0,0 +1,15 @@
+# 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
+}
+
diff --git a/distcc/popt/.stamp-conf.in b/distcc/popt/.stamp-conf.in
new file mode 100644
index 0000000..e48829e
--- /dev/null
+++ b/distcc/popt/.stamp-conf.in
@@ -0,0 +1 @@
+@src_dir@
diff --git a/distcc/popt/README.popt b/distcc/popt/README.popt
new file mode 100644
index 0000000..baeb7fe
--- /dev/null
+++ b/distcc/popt/README.popt
@@ -0,0 +1,12 @@
+This 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.x \ No newline at end of file
diff --git a/distcc/popt/findme.c b/distcc/popt/findme.c
new file mode 100644
index 0000000..a950e50
--- /dev/null
+++ b/distcc/popt/findme.c
@@ -0,0 +1,50 @@
+/** \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;
+}
diff --git a/distcc/popt/findme.h b/distcc/popt/findme.h
new file mode 100644
index 0000000..a016b86
--- /dev/null
+++ b/distcc/popt/findme.h
@@ -0,0 +1,20 @@
+/** \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
diff --git a/distcc/popt/popt.c b/distcc/popt/popt.c
new file mode 100644
index 0000000..e9c4c17
--- /dev/null
+++ b/distcc/popt/popt.c
@@ -0,0 +1,1236 @@
+/** \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 <float.h>
+#endif
+#include <math.h>
+
+#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 <mc@bat.ru>
+ * XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
+ */
+#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);
+ strncpy(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@*/
diff --git a/distcc/popt/popt.h b/distcc/popt/popt.h
new file mode 100644
index 0000000..04c9f65
--- /dev/null
+++ b/distcc/popt/popt.h
@@ -0,0 +1,541 @@
+/** \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 <stdio.h> /* 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 paramter 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=
+ reall bad line
+ reall 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 ouput 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 ouput 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
diff --git a/distcc/popt/poptconfig.c b/distcc/popt/poptconfig.c
new file mode 100644
index 0000000..a600a92
--- /dev/null
+++ b/distcc/popt/poptconfig.c
@@ -0,0 +1,190 @@
+/** \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 "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(*line)) return;
+
+ while (*line != '\0' && isspace(*line)) line++;
+ entryType = line;
+ while (*line == '\0' || !isspace(*line)) line++;
+ *line++ = '\0';
+
+ while (*line != '\0' && isspace(*line)) line++;
+ if (*line == '\0') return;
+ opt = line;
+ while (*line == '\0' || !isspace(*line)) line++;
+ *line++ = '\0';
+
+ while (*line != '\0' && isspace(*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(*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;
+}
diff --git a/distcc/popt/popthelp.c b/distcc/popt/popthelp.c
new file mode 100644
index 0000000..e12c908
--- /dev/null
+++ b/distcc/popt/popthelp.c
@@ -0,0 +1,742 @@
+/* -*- 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 "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[16];
+
+ ch = help + lineLength - 1;
+ while (ch > help && !isspace(*ch)) ch--;
+ if (ch == help) break; /* give up */
+ while (ch > (help + 1) && isspace(*ch)) ch--;
+ ch++;
+
+ sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
+ /*@-formatconst@*/
+ fprintf(fp, format, help, " ");
+ /*@=formatconst@*/
+ help = ch;
+ while (isspace(*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 @*/
+{
+ char * s = alloca(300); /* larger then the ascii set */
+
+ s[0] = '\0';
+ /*@-branchstate@*/ /* FIX: W2DO? */
+ if (str == NULL) {
+ memset(s, 0, sizeof(s));
+ 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@*/
diff --git a/distcc/popt/poptint.h b/distcc/popt/poptint.h
new file mode 100644
index 0000000..5d308ef
--- /dev/null
+++ b/distcc/popt/poptint.h
@@ -0,0 +1,116 @@
+/** \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 <libintl.h>
+#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
diff --git a/distcc/popt/poptparse.c b/distcc/popt/poptparse.c
new file mode 100644
index 0000000..a0dea80
--- /dev/null
+++ b/distcc/popt/poptparse.c
@@ -0,0 +1,227 @@
+/** \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 "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(*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 erro
+ * 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(*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(*q)) && *q != '=')
+ q++;
+
+ if (isspace(*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(*q))
+ q++;
+ if (*q == '\0')
+ continue; /* XXX silently ignore missing value */
+
+ /* now, loop and strip all ending whitespace */
+ x = p + linelen;
+ while (isspace(*--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;
+}
diff --git a/distcc/popt/system.h b/distcc/popt/system.h
new file mode 100644
index 0000000..1d1b9da
--- /dev/null
+++ b/distcc/popt/system.h
@@ -0,0 +1,76 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined (__GLIBC__) && defined(__LCLINT__)
+/*@-declundef@*/
+/*@unchecked@*/
+extern __const __int32_t *__ctype_tolower;
+/*@unchecked@*/
+extern __const __int32_t *__ctype_toupper;
+/*@=declundef@*/
+#endif
+
+#include <ctype.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#if HAVE_MCHECK_H
+#include <mcheck.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#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 <libc.h>
+#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 <alloca.h>
+# 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"
diff --git a/distcc/src/access.c b/distcc/src/access.c
new file mode 100644
index 0000000..9b15f96
--- /dev/null
+++ b/distcc/src/access.c
@@ -0,0 +1,125 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+ /*
+ * They that forsake the law praise the wicked: but such
+ * as keep the law contend with them.
+ * -- Proverbs 28:4
+ */
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "types.h"
+#include "distcc.h"
+#include "trace.h"
+#include "access.h"
+#include "exitcode.h"
+
+/**
+ * @file
+ *
+ * Simple IP-based access-control system
+ */
+
+static const in_addr_t allones = 0xffffffffUL;
+
+
+/**
+ * Interpret a "HOST/BITS" mask specification. Return @p value and @p mask.
+ **/
+int dcc_parse_mask(const char *spec,
+ in_addr_t *value,
+ in_addr_t *mask)
+{
+ int value_len;
+ struct in_addr ia;
+ int mask_bits;
+ char *value_str;
+ int matched;
+ const char *mask_str;
+
+ value_len = strcspn(spec, "/");
+
+ /* get bit before slash */
+ value_str = strdup(spec);
+ value_str[value_len] = '\0';
+ matched = inet_pton(AF_INET, value_str, &ia);
+
+ /* extract and parse value part */
+ if (!matched) {
+ rs_log_error("can't parse internet address \"%s\"", value_str);
+ free(value_str);
+ return EXIT_BAD_ARGUMENTS;
+ }
+ free(value_str);
+ *value = ia.s_addr;
+
+ mask_str = &spec[value_len + 1];
+ if (spec[value_len] && *mask_str) {
+ /* find mask length as a number of bits */
+ mask_bits = atoi(mask_str);
+ if (mask_bits < 0 || mask_bits > 32) {
+ 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 == 32)
+ *mask = allones;
+ else
+ *mask = htonl(~(allones >> mask_bits));
+ } else {
+ *mask = allones;
+ }
+ return 0;
+}
+
+
+/**
+ * Check whether a client ought to be allowed.
+ *
+ * @returns 0 for allowed, or EXIT_ACCESS_DENIED.
+ **/
+int dcc_check_address(in_addr_t client,
+ in_addr_t value,
+ in_addr_t mask)
+{
+ if ((client & mask) == (value & mask)) {
+ rs_trace("match client %#lx, value %#lx, mask %#lx",
+ (long) client, (long) value, (long) mask);
+ return 0;
+ } else {
+ rs_trace("deny client %#lx, value %#lx, mask %#lx",
+ (long) client, (long) value, (long) mask);
+ return EXIT_ACCESS_DENIED;
+ }
+}
diff --git a/distcc/src/access.h b/distcc/src/access.h
new file mode 100644
index 0000000..fda5996
--- /dev/null
+++ b/distcc/src/access.h
@@ -0,0 +1,35 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+/* access.c */
+int dcc_parse_mask(const char *mask_spec,
+ in_addr_t *value,
+ in_addr_t *mask);
+
+int dcc_check_address(in_addr_t client,
+ in_addr_t value,
+ in_addr_t mask);
+
+struct dcc_allow_list {
+ in_addr_t addr, mask;
+ struct dcc_allow_list *next;
+};
diff --git a/distcc/src/arg.c b/distcc/src/arg.c
new file mode 100644
index 0000000..de37625
--- /dev/null
+++ b/distcc/src/arg.c
@@ -0,0 +1,390 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+ /* "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 hypen),
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+
+#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.
+ *
+ * @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, 2)) != 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_DISTCC_FAILED;
+ } 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 (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 (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")) {
+ rs_log_info("compiler will emit 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)) {
+ rs_log_info("gcc's -x handling is complex; running locally");
+ 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
+ * worthwile. 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;
+}
diff --git a/distcc/src/argutil.c b/distcc/src/argutil.c
new file mode 100644
index 0000000..1096f33
--- /dev/null
+++ b/distcc/src/argutil.c
@@ -0,0 +1,165 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+
+/*
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+
+#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;
+
+ 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");
+ exit(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);
+ 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 = (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;
+}
+
+
diff --git a/distcc/src/backoff.c b/distcc/src/backoff.c
new file mode 100644
index 0000000..45f88d4
--- /dev/null
+++ b/distcc/src/backoff.c
@@ -0,0 +1,110 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ *
+ * Keep track of hosts which are, or are not, usable.
+ **/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+
+#include <sys/stat.h>
+#include <sys/file.h>
+
+#include "distcc.h"
+#include "trace.h"
+#include "util.h"
+#include "exitcode.h"
+#include "snprintf.h"
+#include "lock.h"
+#include "timefile.h"
+#include "hosts.h"
+
+
+const 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)
+{
+ return dcc_remove_timefile("backoff", host);
+}
+
+int dcc_disliked_host(const struct dcc_hostdef *host)
+{
+ /* i hate you (but only for 60 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;
+
+ 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;
+}
diff --git a/distcc/src/bulk.c b/distcc/src/bulk.c
new file mode 100644
index 0000000..00583d0
--- /dev/null
+++ b/distcc/src/bulk.c
@@ -0,0 +1,367 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+ /* "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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#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;
+}
diff --git a/distcc/src/bulk.h b/distcc/src/bulk.h
new file mode 100644
index 0000000..7f37109
--- /dev/null
+++ b/distcc/src/bulk.h
@@ -0,0 +1,51 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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);
+
diff --git a/distcc/src/cleanup.c b/distcc/src/cleanup.c
new file mode 100644
index 0000000..8a25552
--- /dev/null
+++ b/distcc/src/cleanup.c
@@ -0,0 +1,163 @@
+/* -*- 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
+ */
+
+ /* "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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#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;
+}
diff --git a/distcc/src/climasq.c b/distcc/src/climasq.c
new file mode 100644
index 0000000..217e008
--- /dev/null
+++ b/distcc/src/climasq.c
@@ -0,0 +1,131 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+ /*
+ * And the magicians did so with their enchantments,
+ * and brought up frogs upon the land of Egypt.
+ * -- Exodus 8:7
+ */
+
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#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)
+ return ret;
+ *did_masquerade = 1;
+ }
+ else {
+ rs_trace("not modifying PATH");
+ *did_masquerade = 0;
+ }
+
+ free(buf);
+ return 0;
+}
diff --git a/distcc/src/clinet.c b/distcc/src/clinet.c
new file mode 100644
index 0000000..c817d9c
--- /dev/null
+++ b/distcc/src/clinet.c
@@ -0,0 +1,201 @@
+/* -*- 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
+ */
+
+
+ /* I just wish I could get caller-IQ on my phones...
+ -- The Purple People-Eater, NANAE */
+
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <netdb.h>
+
+#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 tries = 3;
+
+ dcc_sockaddr_to_string(sa, salen, &s);
+
+ 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;
+ }
+
+ 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;
+ }
+
+ *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 */
diff --git a/distcc/src/clinet.h b/distcc/src/clinet.h
new file mode 100644
index 0000000..81a3f3e
--- /dev/null
+++ b/distcc/src/clinet.h
@@ -0,0 +1,33 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+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);
+
+
diff --git a/distcc/src/clirpc.c b/distcc/src/clirpc.c
new file mode 100644
index 0000000..43e2fda
--- /dev/null
+++ b/distcc/src/clirpc.c
@@ -0,0 +1,281 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#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 array.
+ **/
+int dcc_x_argv(int fd, char **argv)
+{
+ int i;
+ int ret;
+ int argc;
+
+ argc = dcc_argv_len(argv);
+
+ if (dcc_x_token_int(fd, "ARGC", (unsigned) argc))
+ return EXIT_PROTOCOL_ERROR;
+
+ for (i = 0; i < argc; i++) {
+ if ((ret = dcc_x_token_string(fd, "ARGV", 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)))
+ 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);
+
+ 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 */
+static 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;
+}
+
+static 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 = ((buf.st_mode & S_IFLNK) == S_IFLNK);
+ 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;
+}
diff --git a/distcc/src/compile.c b/distcc/src/compile.c
new file mode 100644
index 0000000..1d47c1b
--- /dev/null
+++ b/distcc/src/compile.c
@@ -0,0 +1,687 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <ctype.h>
+
+#ifdef HAVE_FNMATCH_H
+ #include <fnmatch.h>
+#endif
+
+#include <sys/time.h>
+#include <time.h>
+#include <limits.h>
+#include <assert.h>
+
+#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"
+
+
+static const int max_discrepancies_before_demotion = 1;
+
+static const char *const include_server_port_suffix = "/socket";
+static const char *const discrepancy_suffix = "/discrepancy_counter";
+
+/**
+ * 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 ddc_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) + 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] == '/');
+ 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;
+ }
+ if (dcc_read_number_discrepancies(discrepancy_filename) ==
+ max_discrepancies_before_demotion) {
+ /* Give up on using distcc-pump. Print this warning just once. */
+ 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) >=
+ 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;
+ char 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");
+
+ /* 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);
+}
+
+/**
+ * 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'.
+ * Treated as read-only, because it is a pointer to the program's real
+ * argv.
+ *
+ * @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.
+ **/
+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;
+ char *server_stderr_fname = NULL;
+ int needs_dotd = 0;
+ int sets_dotd_target = 0;
+ pid_t cpp_pid = 0;
+ int cpu_lock_fd, local_cpu_lock_fd;
+ int ret;
+ int remote_ret = 0;
+ struct dcc_hostdef *host = NULL;
+ char *discrepancy_filename;
+
+ if ((ret = ddc_discrepancy_filename(&discrepancy_filename)))
+ return ret;
+
+ if (sg_level)
+ goto run_local;
+
+ /* TODO: Perhaps tidy up these gotos. */
+
+ if (dcc_scan_args(argv, &input_fname, &output_fname, &argv) != 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;
+ }
+
+ if ((ret = dcc_lock_local_cpp(&local_cpu_lock_fd)) != 0) {
+ goto fallback;
+ }
+
+ if ((ret = dcc_pick_host_from_list(&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 (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 (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 essense, 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 {
+ // done "preprocessing"
+ dcc_unlock(local_cpu_lock_fd);
+ // don't try to unlock again in dcc_compile_remote
+ local_cpu_lock_fd = 0;
+ }
+ }
+
+ 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);
+ 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. */
+ goto fallback;
+ }
+
+ dcc_enjoyed_host(host);
+
+ dcc_unlock(cpu_lock_fd);
+
+ 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;
+ }
+ 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).
+ */
+ rs_log_warning("remote compilation of '%s' failed, retrying locally",
+ input_fname);
+ remote_ret = ret;
+ goto fallback;
+ }
+
+
+ fallback:
+ if (host)
+ dcc_disliked_host(host);
+
+ if (!dcc_getenv_bool("DISTCC_FALLBACK", 1)) {
+ rs_log_warning("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_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 && 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);
+ }
+
+ clean_up:
+ free(server_side_argv);
+ free(discrepancy_filename);
+ return ret;
+}
+
+
+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 %ld.%06lds",
+ delta.tv_sec, delta.tv_usec);
+ }
+
+ return ret;
+}
diff --git a/distcc/src/compile.h b/distcc/src/compile.h
new file mode 100644
index 0000000..f2c37a4
--- /dev/null
+++ b/distcc/src/compile.h
@@ -0,0 +1,46 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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);
+
+/* 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 ddc_discrepancy_filename(char **filename);
diff --git a/distcc/src/compress.c b/distcc/src/compress.c
new file mode 100644
index 0000000..88ebdfc
--- /dev/null
+++ b/distcc/src/compress.c
@@ -0,0 +1,254 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003, 2004 by Martin Pool <mbp@sourcefrog.net>
+ *
+ * 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
+ */
+
+
+ /* I think that I can safely speak for the
+ * whole troll community when I say "I like
+ * watching train wrecks". -- AC */
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#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 straighforward 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;
+}
diff --git a/distcc/src/cpp.c b/distcc/src/cpp.c
new file mode 100644
index 0000000..f82c8a3
--- /dev/null
+++ b/distcc/src/cpp.c
@@ -0,0 +1,103 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ *
+ * Run the preprocessor. Client-side only.
+ **/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#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);
+}
+
+
diff --git a/distcc/src/daemon.c b/distcc/src/daemon.c
new file mode 100644
index 0000000..a7bdc1c
--- /dev/null
+++ b/distcc/src/daemon.c
@@ -0,0 +1,306 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+ /* "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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <syslog.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+
+#include <arpa/inet.h>
+
+
+#include "exitcode.h"
+#include "distcc.h"
+#include "trace.h"
+#include "util.h"
+#include "dopt.h"
+#include "srvnet.h"
+#include "daemon.h"
+#include "types.h"
+
+
+/* for trace.c */
+char const *rs_program_name = "distccd";
+
+
+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_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;
+ }
+}
+
+
+/**
+ * distcc daemon. May run from inetd, or standalone. Accepts
+ * requests from clients to compile files.
+ **/
+int main(int argc, char *argv[])
+{
+ int ret;
+ const char *tmp;
+
+ 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_error("--allow option is now mandatory; "
+ "you must specify which clients are allowed to connect");
+ ret = EXIT_BAD_ARGUMENTS;
+ goto out;
+ }
+
+ 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 root directory. Allows start directory to be
+ * unmounted, should make accidental writing of local files cause a
+ * failure... */
+ if ((ret = dcc_get_tmp_top(&tmp)))
+ goto out;
+
+ if (chdir(tmp) == -1) {
+ rs_log_error("failed to chdir to %s: %s", tmp, strerror(errno));
+ ret = EXIT_IO_ERROR;
+ goto out;
+ } else {
+ rs_trace("chdir to %s", tmp);
+ }
+
+ if ((ret = dcc_setup_daemon_path()))
+ goto out;
+
+ 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_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);
+
+ if (ret)
+ return ret;
+ else
+ return close_ret;
+}
+
diff --git a/distcc/src/daemon.h b/distcc/src/daemon.h
new file mode 100644
index 0000000..438e08b
--- /dev/null
+++ b/distcc/src/daemon.h
@@ -0,0 +1,56 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+/* daemon.c */
+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;
diff --git a/distcc/src/distcc.c b/distcc/src/distcc.c
new file mode 100644
index 0000000..2bf4b52
--- /dev/null
+++ b/distcc/src/distcc.c
@@ -0,0 +1,221 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+
+#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);
+}
diff --git a/distcc/src/distcc.h b/distcc/src/distcc.h
new file mode 100644
index 0000000..c0686a7
--- /dev/null
+++ b/distcc/src/distcc.h
@@ -0,0 +1,336 @@
+/* -*- 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 <sys/types.h>
+
+
+#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 {
+ /* wierd values to catch errors */
+ DCC_COMPRESS_NONE = 69,
+ DCC_COMPRESS_LZO1X
+};
+
+enum dcc_cpp_where {
+ /* wierd 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
diff --git a/distcc/src/dopt.c b/distcc/src/dopt.c
new file mode 100644
index 0000000..ed89771
--- /dev/null
+++ b/distcc/src/dopt.c
@@ -0,0 +1,278 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+/* dopt.c -- Parse and apply server options. */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <popt.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#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;
+
+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;
+
+/**
+ * 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;
+
+/**
+ * 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
+};
+
+
+const struct poptOption options[] = {
+ { "allow", 'a', POPT_ARG_STRING, 0, 'a', 0, 0 },
+ { "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 },
+ { "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 },
+ { "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 },
+ { 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"
+" -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"
+" --stats enable statistics reporting via HTTP server\n"
+" --stats-port PORT TCP port to listen on for statistics requests\n"
+" 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"
+);
+}
+
+
+int distccd_parse_options(int argc, const char **argv)
+{
+ poptContext po;
+ int po_err, exitcode;
+
+ 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. */
+ struct dcc_allow_list *new;
+ 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;
+
+ 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;
+
+ 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;
+
+ 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);
+ 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;
+ }
+ }
+
+ poptFreeContext(po);
+ return 0;
+
+ out_exit:
+ poptFreeContext(po);
+ exit(exitcode);
+}
diff --git a/distcc/src/dopt.h b/distcc/src/dopt.h
new file mode 100644
index 0000000..21cf1ea
--- /dev/null
+++ b/distcc/src/dopt.h
@@ -0,0 +1,44 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+/* dopt.c */
+extern struct dcc_allow_list *opt_allowed;
+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_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;
diff --git a/distcc/src/dotd.c b/distcc/src/dotd.c
new file mode 100644
index 0000000..2115084
--- /dev/null
+++ b/distcc/src/dotd.c
@@ -0,0 +1,251 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "distcc.h"
+#include "exitcode.h"
+#include "dotd.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 environent 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 ret;
+ 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 (strcmp(a, "-o") == 0) {
+ has_dash_o = 1;
+ }
+ }
+
+ 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;
+ ret = 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] == '.')
+ asprintf(dotd_fname, "%s%s", tmp_dotd_fname, "d");
+ else
+ asprintf(dotd_fname, "%s%s", tmp_dotd_fname, ".d");
+ if (*dotd_fname == NULL) {
+ return EXIT_OUT_OF_MEMORY;
+ }
+ free(tmp_dotd_fname);
+ }
+ return 0;
+ }
+}
diff --git a/distcc/src/dotd.h b/distcc/src/dotd.h
new file mode 100755
index 0000000..c476ea5
--- /dev/null
+++ b/distcc/src/dotd.h
@@ -0,0 +1,9 @@
+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);
diff --git a/distcc/src/dparent.c b/distcc/src/dparent.c
new file mode 100644
index 0000000..d026757
--- /dev/null
+++ b/distcc/src/dparent.c
@@ -0,0 +1,353 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+ /* 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#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"
+
+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;
+
+ 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();
+
+ /* 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);
+ } else {
+ dcc_log_daemon_started("preforking daemon");
+ return dcc_preforking_parent(listen_fd);
+ }
+}
+
+
+
+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));
+ 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;
+
+ if (unlink(arg_pid_file)) {
+ 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();
+}
diff --git a/distcc/src/dsignal.c b/distcc/src/dsignal.c
new file mode 100644
index 0000000..f887682
--- /dev/null
+++ b/distcc/src/dsignal.c
@@ -0,0 +1,138 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+ /*
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+
+#include "exitcode.h"
+#include "distcc.h"
+#include "trace.h"
+#include "util.h"
+#include "dopt.h"
+#include "exec.h"
+#include "daemon.h"
+
+
+/* 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;
+
+ if (am_parent) {
+#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);
+}
diff --git a/distcc/src/emaillog.c b/distcc/src/emaillog.c
new file mode 100644
index 0000000..91b3f4b
--- /dev/null
+++ b/distcc/src/emaillog.c
@@ -0,0 +1,130 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include "emaillog.h"
+#include "distcc.h"
+#include "util.h"
+#include "trace.h"
+#include "bulk.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;
+
+ if (never_send_email) return 0;
+
+ if (dcc_open_read(fname, &in_fd, &fsize))
+ return 1;
+
+ write(email_fileno, begin, strlen(begin));
+ write(email_fileno, description, strlen(description));
+ write(email_fileno, "\n", 1);
+
+ dcc_pump_readwrite(email_fileno, in_fd, fsize);
+
+ write(email_fileno, end, strlen(end));
+ write(email_fileno, description, strlen(description));
+ write(email_fileno, "\n", 1);
+
+ 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 *will_send_message_to;
+ char *cant_send_message_to;
+
+ if (should_send_email == 0) return;
+ if (never_send_email) return;
+
+ asprintf(&will_send_message_to, will_send_message_format, whom_to_blame);
+ asprintf(&cant_send_message_to, cant_send_message_format, whom_to_blame);
+
+ rs_log_warning(will_send_message_to);
+ free(will_send_message_to);
+
+ 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);
+}
diff --git a/distcc/src/emaillog.h b/distcc/src/emaillog.h
new file mode 100644
index 0000000..c94fc6f
--- /dev/null
+++ b/distcc/src/emaillog.h
@@ -0,0 +1,11 @@
+#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 */
diff --git a/distcc/src/exec.c b/distcc/src/exec.c
new file mode 100644
index 0000000..460c067
--- /dev/null
+++ b/distcc/src/exec.c
@@ -0,0 +1,459 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+ /* 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/poll.h>
+
+#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;
+}
+
+
+/**
+ * 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();
+
+ /* 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 %ld.%06lds, system %ld.%06lds, "
+ "%ld minflt, %ld majflt",
+ what,
+ ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
+ ru.ru_stime.tv_sec, 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 (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;
+ }
+}
diff --git a/distcc/src/exec.h b/distcc/src/exec.h
new file mode 100644
index 0000000..bab48b2
--- /dev/null
+++ b/distcc/src/exec.h
@@ -0,0 +1,50 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+/* 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
+
diff --git a/distcc/src/exitcode.h b/distcc/src/exitcode.h
new file mode 100644
index 0000000..29a595a
--- /dev/null
+++ b/distcc/src/exitcode.h
@@ -0,0 +1,61 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 */
diff --git a/distcc/src/filename.c b/distcc/src/filename.c
new file mode 100644
index 0000000..bd78f69
--- /dev/null
+++ b/distcc/src/filename.c
@@ -0,0 +1,315 @@
+/* -*- 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
+ */
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#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 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);
+ dot = dcc_find_extension((char *) 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((char *) 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((char *) 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((char *) 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);
+}
+
diff --git a/distcc/src/fix_debug_info.c b/distcc/src/fix_debug_info.c
new file mode 100644
index 0000000..e78637d
--- /dev/null
+++ b/distcc/src/fix_debug_info.c
@@ -0,0 +1,450 @@
+/* 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 "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef HAVE_ELF_H
+ #include <elf.h>
+#endif
+
+#include <sys/stat.h>
+#ifdef HAVE_SYS_MMAN_H
+ #include <sys/mman.h>
+#endif
+
+#include "trace.h"
+#include "fix_debug_info.h"
+
+#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;
+ const Elf32_Ehdr *elf32_header = (const Elf32_Ehdr *) (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 <elf.h>, 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 =
+ (const Elf32_Shdr *) (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 = &sections[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) {
+ const Elf64_Ehdr *elf_header = (const Elf64_Ehdr *) elf_base;
+ const Elf64_Shdr *sections =
+ (const Elf64_Shdr *) (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 > 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 = &sections[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) {
+ int count = replace_string((void *) desired_section, 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", desired_section_name, path);
+ }
+}
+
+/*
+ * 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 <elf.h>, 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 <filename> <client-path> <server-path>",
+ rs_program_name);
+ exit(1);
+ }
+ return dcc_fix_debug_info(argv[1], argv[2], argv[3]);
+}
+#endif
diff --git a/distcc/src/fix_debug_info.h b/distcc/src/fix_debug_info.h
new file mode 100644
index 0000000..b71ae5d
--- /dev/null
+++ b/distcc/src/fix_debug_info.h
@@ -0,0 +1,26 @@
+/* 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__
diff --git a/distcc/src/h_argvtostr.c b/distcc/src/h_argvtostr.c
new file mode 100644
index 0000000..27cca7c
--- /dev/null
+++ b/distcc/src/h_argvtostr.c
@@ -0,0 +1,59 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#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;
+}
diff --git a/distcc/src/h_compile.c b/distcc/src/h_compile.c
new file mode 100644
index 0000000..7ed6ac7
--- /dev/null
+++ b/distcc/src/h_compile.c
@@ -0,0 +1,106 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+/**
+ * Test harness for functions in compile.c. (Only one so far.)
+ **/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+
+#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 ddc_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], "ddc_discrepancy_filename") == 0) {
+ if (argc != 2) {
+ rs_log_error("dcc_discrepancy_filename expects no arguments");
+ return 1;
+ }
+ char *result;
+ int ret = ddc_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;
+}
diff --git a/distcc/src/h_dotd.c b/distcc/src/h_dotd.c
new file mode 100644
index 0000000..d689761
--- /dev/null
+++ b/distcc/src/h_dotd.c
@@ -0,0 +1,73 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ *
+ * 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
+ *
+ * Test harness for dotd.c.
+ **/
+
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#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;
+}
diff --git a/distcc/src/h_exten.c b/distcc/src/h_exten.c
new file mode 100644
index 0000000..23782c9
--- /dev/null
+++ b/distcc/src/h_exten.c
@@ -0,0 +1,60 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+
+#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;
+}
diff --git a/distcc/src/h_hosts.c b/distcc/src/h_hosts.c
new file mode 100644
index 0000000..cb7cea2
--- /dev/null
+++ b/distcc/src/h_hosts.c
@@ -0,0 +1,111 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * 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 <mbp@samba.org>
+ *
+ * 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
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#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);
+}
diff --git a/distcc/src/h_issource.c b/distcc/src/h_issource.c
new file mode 100644
index 0000000..84ce152
--- /dev/null
+++ b/distcc/src/h_issource.c
@@ -0,0 +1,59 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+
+#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;
+}
diff --git a/distcc/src/h_parsemask.c b/distcc/src/h_parsemask.c
new file mode 100644
index 0000000..90525ec
--- /dev/null
+++ b/distcc/src/h_parsemask.c
@@ -0,0 +1,66 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#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;
+ in_addr_t value, mask;
+ struct in_addr 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;
+
+ if (!inet_aton(argv[2], &client_ia)) {
+ rs_log_error("can't parse client address \"%s\"", argv[2]);
+ return EXIT_BAD_ARGUMENTS;
+ }
+
+ return dcc_check_address(client_ia.s_addr, value, mask);
+}
diff --git a/distcc/src/h_sa2str.c b/distcc/src/h_sa2str.c
new file mode 100644
index 0000000..1d3f015
--- /dev/null
+++ b/distcc/src/h_sa2str.c
@@ -0,0 +1,75 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+
+#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;
+}
diff --git a/distcc/src/h_scanargs.c b/distcc/src/h_scanargs.c
new file mode 100644
index 0000000..c6fbf33
--- /dev/null
+++ b/distcc/src/h_scanargs.c
@@ -0,0 +1,72 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+
+#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;
+}
diff --git a/distcc/src/h_strip.c b/distcc/src/h_strip.c
new file mode 100644
index 0000000..7b84ecc
--- /dev/null
+++ b/distcc/src/h_strip.c
@@ -0,0 +1,63 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+
+#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;
+}
diff --git a/distcc/src/help.c b/distcc/src/help.c
new file mode 100644
index 0000000..0e66540
--- /dev/null
+++ b/distcc/src/help.c
@@ -0,0 +1,74 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+ /*
+ * Tell me what you need, and I'll tell you how to
+ * get along without it. -- Dilbert
+ */
+
+#include "config.h"
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#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"
+"\n"
+"Please report bugs to %s\n"
+"\n"
+ ,
+ prog, PACKAGE_VERSION, GNU_HOST, DISTCC_DEFAULT_PORT,
+ __DATE__, __TIME__, PACKAGE_BUGREPORT);
+ return 0;
+}
diff --git a/distcc/src/history.c b/distcc/src/history.c
new file mode 100644
index 0000000..a36edfb
--- /dev/null
+++ b/distcc/src/history.c
@@ -0,0 +1,68 @@
+/* -*- c-file-style: "k&r"; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+#include <stdlib.h>
+
+#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;
+}
+
diff --git a/distcc/src/hostfile.c b/distcc/src/hostfile.c
new file mode 100644
index 0000000..6511d49
--- /dev/null
+++ b/distcc/src/hostfile.c
@@ -0,0 +1,67 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#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);
+
+ free(body);
+
+ return ret;
+}
diff --git a/distcc/src/hosts.c b/distcc/src/hosts.c
new file mode 100644
index 0000000..80cfc9d
--- /dev/null
+++ b/distcc/src/hosts.c
@@ -0,0 +1,654 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+/* dcc_randomize_host_list() and friends:
+ * Copyright (C) 2004 by Google
+ *
+ * Author: Josh Hyman <joshh@google.com>
+ */
+
+
+ /* The lyf so short, the craft so long to lerne.
+ * -- Chaucer */
+
+
+
+/**
+ * @file
+ *
+ * Routines to parse <tt>$DISTCC_HOSTS</tt>. 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "distcc.h"
+#include "trace.h"
+#include "util.h"
+#include "hosts.h"
+#include "exitcode.h"
+#include "snprintf.h"
+
+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.
+ **/
+static 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;
+
+ if ((env = getenv("DISTCC_HOSTS")) != NULL) {
+ rs_trace("read hosts from environment");
+ return dcc_parse_hosts(env, "$DISTCC_HOSTS", ret_list, ret_nhosts);
+ }
+
+ /* $DISTCC_DIR or ~/.distcc */
+ if ((ret = dcc_get_top_dir(&top)) == 0) {
+ /* if we failed to get it, just warn */
+
+ asprintf(&path, "%s/hosts", top);
+ if (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);
+ }
+ }
+
+ asprintf(&path, "%s/distcc/hosts", SYSCONFDIR);
+ if (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 defintion 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(**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;
+
+ 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;
+ } else {
+ rs_log_warning("unrecognized option in host specification %s",
+ started);
+ return EXIT_BAD_HOSTSPEC;
+ }
+ }
+ dcc_get_protover_from_features(host->compr, host->cpp_where,
+ &host->protover);
+
+ *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 ((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(*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;
+ }
+
+ 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)
+{
+ int ret, flag_randomize = 0;
+ struct dcc_hostdef *prev, *curr;
+
+ /* TODO: Check for '/' in places where it might cause trouble with
+ * a lock file name. */
+
+ prev = NULL;
+ *ret_list = NULL;
+ *ret_nhosts = 0;
+ /* 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(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;
+ }
+ }
+
+ /* 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 (prev) {
+ 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);
+ }
+
+ /* continue to next token if any */
+ where = token_start + token_len;
+ prev = curr;
+ (*ret_nhosts)++;
+ }
+
+ 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;
+}
diff --git a/distcc/src/hosts.h b/distcc/src/hosts.h
new file mode 100644
index 0000000..674ac85
--- /dev/null
+++ b/distcc/src/hosts.h
@@ -0,0 +1,87 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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);
+
+
diff --git a/distcc/src/implicit.c b/distcc/src/implicit.c
new file mode 100644
index 0000000..603699b
--- /dev/null
+++ b/distcc/src/implicit.c
@@ -0,0 +1,95 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+ /* "I do not trouble myself to be understood. I see
+ * that the elementary laws never apologize."
+ * -- Whitman, "Song of Myself". */
+
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#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.
+ **/
+int dcc_find_compiler(char **argv, char ***out_argv)
+{
+ if (argv[1][0] == '-'
+ || dcc_is_source(argv[1])
+ || dcc_is_object(argv[1])) {
+ dcc_copy_argv(argv, out_argv, 0);
+
+ /* change "distcc -c foo.c" -> "cc -c foo.c" */
+ (*out_argv)[0] = strdup("cc");
+ return 0;
+ } else {
+ /* skip "distcc", point to "gcc -c foo.c" */
+ *out_argv = argv+1;
+ return 0;
+ }
+}
diff --git a/distcc/src/implicit.h b/distcc/src/implicit.h
new file mode 100644
index 0000000..371657d
--- /dev/null
+++ b/distcc/src/implicit.h
@@ -0,0 +1,25 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 ***);
+
diff --git a/distcc/src/include_server_if.c b/distcc/src/include_server_if.c
new file mode 100644
index 0000000..76c557d
--- /dev/null
+++ b/distcc/src/include_server_if.c
@@ -0,0 +1,161 @@
+/* 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
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include "distcc.h"
+#include "trace.h"
+#include "rpc.h"
+#include "clinet.h"
+#include "exitcode.h"
+#include "util.h"
+#include "include_server_if.h"
+
+/* 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");
+ return 1;
+ }
+
+ if (strlen(include_server_port) >= ((int)sizeof(sa.sun_path) - 1)) {
+ rs_log_warning("$INCLUDE_SERVER_PORT is longer than %d characters",
+ (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;
+
+ /* the following code uses dcc_r_arg to receive an array of strings
+ * which are NOT command line arguments. TODO: implement dcc_r_argv
+ * on top a generic array-of-strings function */
+ if (dcc_x_cwd(fd) ||
+ dcc_x_argv(fd, argv) ||
+ dcc_r_argv(fd, 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;
+}
diff --git a/distcc/src/include_server_if.h b/distcc/src/include_server_if.h
new file mode 100755
index 0000000..3d8a893
--- /dev/null
+++ b/distcc/src/include_server_if.h
@@ -0,0 +1,21 @@
+/* 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);
diff --git a/distcc/src/io.c b/distcc/src/io.c
new file mode 100644
index 0000000..ad404b2
--- /dev/null
+++ b/distcc/src/io.c
@@ -0,0 +1,272 @@
+/* -*- 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
+ */
+
+
+/**
+ * @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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include "distcc.h"
+#include "trace.h"
+#include "util.h"
+#include "exitcode.h"
+
+
+
+/** Timeout for all IO other than opening connections. Much longer, because
+ * compiling files can take a long time. **/
+const int dcc_io_timeout = 300; /* seconds */
+
+
+/**
+ * @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 (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_io_timeout)))
+ return ret;
+ else
+ continue;
+ } else if (r == -1 && errno == EAGAIN) {
+ 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_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 if (r == 0) {
+ rs_log_error("unexpected eof on fd%d", fd);
+ return EXIT_TRUNCATED;
+ } 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 fd, int corked)
+{
+#ifdef TCP_CORK
+ if (!dcc_getenv_bool("DISTCC_TCP_CORK", 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;
+}
diff --git a/distcc/src/loadfile.c b/distcc/src/loadfile.c
new file mode 100644
index 0000000..fc4b5c9
--- /dev/null
+++ b/distcc/src/loadfile.c
@@ -0,0 +1,113 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#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 == EEXIST)
+ 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;
+}
diff --git a/distcc/src/lock.c b/distcc/src/lock.c
new file mode 100644
index 0000000..dfebf85
--- /dev/null
+++ b/distcc/src/lock.c
@@ -0,0 +1,271 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+ /* Power is nothing without control
+ * -- Pirelli tyre advertisment. */
+
+
+/**
+ * @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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+
+#include <sys/stat.h>
+#include <sys/file.h>
+
+#include "distcc.h"
+#include "trace.h"
+#include "util.h"
+#include "hosts.h"
+#include "lock.h"
+#include "exitcode.h"
+#include "snprintf.h"
+
+
+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) */
+ 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) */
+ 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)
+{
+ 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 creat %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 occured. 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;
+ }
+}
diff --git a/distcc/src/lock.h b/distcc/src/lock.h
new file mode 100644
index 0000000..64320da
--- /dev/null
+++ b/distcc/src/lock.h
@@ -0,0 +1,36 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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_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);
+
+
diff --git a/distcc/src/lsdistcc.c b/distcc/src/lsdistcc.c
new file mode 100644
index 0000000..42e8cd6
--- /dev/null
+++ b/distcc/src/lsdistcc.c
@@ -0,0 +1,1034 @@
+/*
+ * lsdistcc -- A simple distcc server discovery program
+ * Assumes all distcc servers are in DNS and are named distcc1...distccN.
+ *
+ * Copyright (C) 2005, 2006, 2007 by Google
+ *
+ * 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
+ *
+ * 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 <netdb.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+
+#include "distcc.h"
+#include "clinet.h"
+#include "netutil.h"
+#include "util.h"
+#include "trace.h"
+#include "rslave.h"
+#include "../lzo/minilzo.h"
+
+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<leftoverbits; i++)
+ mask |= (1 << (7-i));
+ /* printf("mask %x, a[%d] %x, b[%d] %x\n", mask,
+ fullbytes, a[fullbytes], fullbytes, b[fullbytes]); */
+ return ((a[fullbytes] ^ b[fullbytes]) & mask);
+ }
+ return 0;
+}
+
+#if 0
+#include <assert.h>
+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];
+ size_t 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 %ld %ld: server_handle_event: %s: state %d\n",
+ now.tv_sec, 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 %ld %ld: Connecting to %s\n",
+ now.tv_sec, 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 %ld %ld: Connecting to %s failed "
+ "with errno %d = %s\n",
+ now.tv_sec, 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 %ld %ld: %s: sending compile request\n",
+ now.tv_sec, 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 %ld %ld: Sending to %s failed, "
+ "errno %d\n",
+ now.tv_sec, now.tv_usec/1000, sp->req.hname,
+ connecterr);
+ else
+ fprintf(stderr,
+ "now %ld %ld: Sending to %s failed, "
+ "nsent %d != nsend %d\n",
+ now.tv_sec, 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);
+
+ 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);
+}
+
+/* Get the name based on the sformat. If the first element in sformat is a
+ * format, ignore the rest, and use the format to generate the series of names;
+ * otherwise, copy the name from sformat. Attach domain_name if needed.
+ */
+void get_thename(const char**sformat, const char *domain_name, int i,
+ char *thename)
+{
+ if (strstr(sformat[0], "%d") != NULL)
+ sprintf(thename, sformat[0], i);
+ else
+ strcpy(thename, sformat[i-1]);
+ if (opt_domain) {
+ strcat(thename, ".");
+ strcat(thename, domain_name);
+ }
+}
+
+/* Detect all listening distcc servers and print their names to stdout.
+ * Looks for servers numbered 1 through infinity, stops at
+ * first server that doesn't resolve in DNS, or after 'timeout' seconds,
+ * whichever comes first.
+ * On entry:
+ * sformat: format of names of distcc servers to check
+ * bigtimeout: how many seconds to terminate slow run after
+ * dnstimeout: how many milliseconds before retrying a particular
+ * gethostbyname call
+ * matchbits: top matchbits of address must match first host found,
+ else stop searching
+ * overlap: how many extra DNS queries to keep in flight normally
+ * dnsgap: how many missing DNS entries to tolerate
+ * On exit:
+ * returns number of servers found.
+ */
+int detect_distcc_servers(const char **argv, int argc, int opti,
+ int bigtimeout, int dnstimeout,
+ int matchbits, int overlap, int dnsgap)
+{
+ unsigned char firstipaddr[4];
+ int dnstimeout_usec = dnstimeout * 1000; /* how long before
+ resending gethostbyname */
+ int n = MAXHOSTS;
+ int i;
+ char thename[256];
+ struct pollfd pollfds[MAXFDS];
+
+ struct state_s states[MAXHOSTS+1];
+ int ngotaddr;
+ int nbaddns;
+ int nwithtries[MAXTRIES+1];
+ int nfds;
+
+ struct rslave_s rs;
+
+ const char **sformat;
+ const char *domain_name;
+ if (opt_domain) {
+ if (dcc_get_dns_domain(&domain_name)) {
+ fprintf(stderr, "Can't get domain name\n");
+ exit(1);
+ }
+ }
+
+ if (opti < argc) {
+ if (strstr(argv[opti], "%d") != NULL) {
+ sformat = &argv[opti++];
+ } else {
+ /* A list of host names can be given in the command line */
+ n = argc-opti;
+ sformat = &argv[opti++];
+ }
+ } else {
+ const char *format = DEFAULT_FORMAT;
+ sformat = &format;
+ }
+
+ /* 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(pollfds, 0, sizeof(pollfds));
+ 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 */
+ while (ndone < n) {
+ struct state_s *sp;
+ int nready;
+ int found;
+ struct timeval now;
+
+ /* See which sockets have any events */
+ nfds = 0;
+ 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 < n)) ? 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=1; i<=n; 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);
+ gettimeofday(&now, 0);
+
+
+ /***** Check for timeout events *****/
+ sp = NULL;
+ found = FALSE;
+ for (i=1; i<=n; 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 %ld %ld: Resending %s because "
+ "deadline was %ld %ld\n",
+ now.tv_sec, now.tv_usec/1000, sp->req.hname,
+ sp->deadline.tv_sec, 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 %ld %ld: %s timed out while connecting\n",
+ now.tv_sec, 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 %ld %ld: %s timed out while compiling\n",
+ now.tv_sec, 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=1; i<=n; 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 %ld %ld: Looking up %s\n",
+ now.tv_sec, 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 > 0 && result.id <= n);
+ 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 %ld %ld: %s not found\n",
+ now.tv_sec, 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=1; i <= n; i++)
+ if (states[i].ntries > 0)
+ highest = i;
+ assert(highest <= n);
+ if (opt_verbose && n != highest)
+ fprintf(stderr,
+ "Already searching up to host %d, "
+ "won't search any higher\n",
+ highest);
+ n = highest;
+ assert(n <= MAXHOSTS);
+ }
+ } else {
+ sp->status = STATE_CONNECT;
+ server_handle_event(sp);
+ }
+ }
+ }
+ }
+
+ /***** Grind state machine for each remote server *****/
+ for (i=2; i<nfds && i < MAXFDS; i++) {
+ sp = states + fd2state[pollfds[i].fd]; /* FIXME */
+ if (pollfds[i].revents)
+ server_handle_event(sp);
+ }
+ }
+ 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;
+}
diff --git a/distcc/src/mon-gnome.c b/distcc/src/mon-gnome.c
new file mode 100644
index 0000000..376fcc0
--- /dev/null
+++ b/distcc/src/mon-gnome.c
@@ -0,0 +1,673 @@
+/* -*- c-file-style: "k&r"; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ *
+ * 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 "config.h"
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_LOADAVG_H
+# include <sys/loadavg.h>
+#endif
+
+#ifdef WITH_GNOME
+# include <gnome.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#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,
+};
+
+
+/**
+ * Graphics contexts to be used to draw each particular state into the
+ * model.
+ **/
+GdkGC *dcc_phase_gc[DCC_PHASE_DONE];
+
+
+#if 0
+/* shades of red */
+const GdkColor task_color[] = {
+ { 0, 0x2222, 0, 0 }, /* DCC_PHASE_STARTUP, */
+ { 0, 0x4444, 0, 0 }, /* DCC_PHASE_BLOCKED, */
+ { 0, 0x6666, 0, 0 }, /* DCC_PHASE_CONNECT, */
+ { 0, 0x8888, 0, 0 }, /* DCC_PHASE_CPP, */
+ { 0, 0xaaaa, 0, 0 }, /* DCC_PHASE_SEND, */
+ { 0, 0xcccc, 0, 0 }, /* DCC_PHASE_COMPILE, */
+ { 0, 0xeeee, 0, 0 }, /* DCC_PHASE_RECEIVE, */
+ { 0, 0xffff, 0xffff, 0 }, /* DCC_PHASE_DONE */
+};
+#endif
+
+/*
+ * Colors used for drawing different state stripes. First GdkColor
+ * field is the assigned color index and zero here.
+ *
+ * These color names are from the GNOME standard palette.
+ */
+const GdkColor task_color[] = {
+ { 0, 0x9999, 0, 0 }, /* DCC_PHASE_STARTUP, accent red dark */
+ { 0, 0x9999, 0, 0 }, /* DCC_PHASE_BLOCKED, accent red dark */
+ { 0, 0xc1c1, 0x6666, 0x5a5a }, /* DCC_PHASE_CONNECT, red medium */
+ { 0, 0x8888, 0x7f7f, 0xa3a3 }, /* DCC_PHASE_CPP, purple medium*/
+ { 0, 0xe0e0, 0xc3c3, 0x9e9e }, /* DCC_PHASE_SEND, face skin medium*/
+ { 0, 0x8383, 0xa6a6, 0x7f7f }, /* DCC_PHASE_COMPILE, green medium */
+ { 0, 0x7575, 0x9090, 0xaeae }, /* DCC_PHASE_RECEIVE, blue medium*/
+ { 0, 0, 0, 0 }, /* DCC_PHASE_DONE */
+};
+
+
+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, settting 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 */
+}
+
+
+/**
+ * Initialize graphics context for drawing into a widget in the right
+ * color for each state.
+ **/
+static void
+dcc_create_state_gcs (GtkWidget *widget)
+{
+ enum dcc_phase i_state;
+
+ for (i_state = 0; i_state < DCC_PHASE_DONE; i_state++)
+ {
+ dcc_phase_gc[i_state] = gdk_gc_new (widget->window);
+ gdk_gc_set_rgb_fg_color (dcc_phase_gc[i_state],
+ (GdkColor *) &task_color[i_state]);
+
+ }
+}
+
+
+/**
+ * Configure GtkTreeView with the right columns bound to
+ * renderers, and a data model.
+ **/
+static void dcc_gnome_make_proc_view (GtkTreeModel *proc_model,
+ GtkWidget **align_return)
+{
+ GtkCellRenderer *text_renderer, *chart_renderer;
+ GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+ GtkWidget *align, *proc_scroll;
+
+ chart_treeview = gtk_tree_view_new_with_model (proc_model);
+ gtk_object_set (GTK_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);
+
+ /* we can't create the gcs until the widget is first realized */
+ g_signal_connect_after (chart_treeview, "realize",
+ G_CALLBACK (dcc_create_state_gcs), NULL);
+
+ 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);
+
+ /* Expands to fill all space */
+ align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+ gtk_container_add (GTK_CONTAINER (align), proc_scroll);
+
+ *align_return = align;
+}
+
+
+static GtkWidget * dcc_gnome_make_load_bar (void)
+{
+ GtkWidget *bar;
+ gint context_id;
+
+ bar = gtk_statusbar_new ();
+ 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 (GTK_OBJECT(mainwin), "delete-event",
+ G_CALLBACK (gtk_main_quit), NULL);
+ g_signal_connect (GTK_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),
+ PKGDATADIR "/distccmon-gnome-icon.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 vbox for the contents */
+ topbox = gtk_vbox_new (FALSE, 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_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);
+
+#if defined(WITH_GNOME)
+ gnome_program_init ("distccmon-gnome", PACKAGE_VERSION,
+ LIBGNOMEUI_MODULE,
+ argc, argv, NULL);
+#elif defined(WITH_GTK)
+ gtk_init (&argc, &argv);
+#else
+# error This program must be built with either WITH_GTK or WITH_GNOME
+#endif
+
+ /* do our own initialization */
+ dcc_gnome_make_app ();
+
+ /* Keep running until quit */
+ gtk_main ();
+
+ return 0;
+}
diff --git a/distcc/src/mon-notify.c b/distcc/src/mon-notify.c
new file mode 100644
index 0000000..8691e7f
--- /dev/null
+++ b/distcc/src/mon-notify.c
@@ -0,0 +1,125 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <dirent.h>
+
+#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 */
+}
+
diff --git a/distcc/src/mon-text.c b/distcc/src/mon-text.c
new file mode 100644
index 0000000..ed31854
--- /dev/null
+++ b/distcc/src/mon-text.c
@@ -0,0 +1,115 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#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;
+}
diff --git a/distcc/src/mon.c b/distcc/src/mon.c
new file mode 100644
index 0000000..90e5605
--- /dev/null
+++ b/distcc/src/mon.c
@@ -0,0 +1,368 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <dirent.h>
+
+#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;
+ }
+
+ asprintf(&fullpath, "%s/%s", dirname, filename);
+ 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
+ * intot he right point on the list. */
+ dcc_mon_insert_sorted(p_list, pthis);
+ }
+ }
+
+ closedir(d);
+
+ return 0;
+}
+
+
diff --git a/distcc/src/mon.h b/distcc/src/mon.h
new file mode 100644
index 0000000..c2fd331
--- /dev/null
+++ b/distcc/src/mon.h
@@ -0,0 +1,266 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003, 2004 by Martin Pool <mbp@samba.org>
+ * Copyright (C) 2003 by Frerich Raabe <raabe@kde.org>
+ *
+ * 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_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, recieves 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 */
diff --git a/distcc/src/ncpus.c b/distcc/src/ncpus.c
new file mode 100644
index 0000000..d29bcd1
--- /dev/null
+++ b/distcc/src/ncpus.c
@@ -0,0 +1,154 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+/* Thanks to Dimitri PAPADOPOULOS-ORFANOS for researching many of the methods
+ * in this file. */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#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 <sys/param.h>
+#include <sys/pstat.h>
+
+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 <module_info.h>
+
+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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+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
diff --git a/distcc/src/netutil.c b/distcc/src/netutil.c
new file mode 100644
index 0000000..a8c513e
--- /dev/null
+++ b/distcc/src/netutil.c
@@ -0,0 +1,214 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+
+#include <arpa/inet.h>
+
+#ifdef HAVE_RESOLV_H
+# include <resolv.h>
+#endif
+
+#include <netdb.h>
+
+#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 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 */
+ }
+
+ 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;
+ asprintf(p_buf, "UNIX-DOMAIN %s", sa_un->sun_path);
+ } else {
+ 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) {
+ struct sockaddr_in *sain = (struct sockaddr_in *) sa;
+
+ 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;
+ asprintf(p_buf, "UNIX-DOMAIN %s", sa_un->sun_path);
+ } else {
+ asprintf(p_buf, "UNKNOWN-FAMILY %d", sa->sa_family);
+ }
+
+ return 0;
+}
+#endif /* ndef ENABLE_RFC2553 */
diff --git a/distcc/src/netutil.h b/distcc/src/netutil.h
new file mode 100644
index 0000000..5b2ea83
--- /dev/null
+++ b/distcc/src/netutil.h
@@ -0,0 +1,37 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+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);
diff --git a/distcc/src/prefork.c b/distcc/src/prefork.c
new file mode 100644
index 0000000..2b01311
--- /dev/null
+++ b/distcc/src/prefork.c
@@ -0,0 +1,195 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+ /* The dead cry out with joy when their books are reprinted
+ */
+
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+
+#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 persistant 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);
+
+ /* Another little safety brake here: since children should not exit
+ * too quickly, pausing before starting them should be harmless. */
+ sleep(1);
+ }
+ }
+}
+
+
+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);
+ }
+
+ /* Don't start them too quickly, or we might overwhelm a machine
+ * that's having trouble. */
+ sleep(1);
+ }
+}
+
+
+
+/**
+ * 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;
+ const int child_lifetime = 50;
+
+ for (ireq = 0; ireq < 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);
+ }
+
+ rs_log_info("worn out");
+
+ return 0;
+}
diff --git a/distcc/src/pump.c b/distcc/src/pump.c
new file mode 100644
index 0000000..e8ea8c7
--- /dev/null
+++ b/distcc/src/pump.c
@@ -0,0 +1,152 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+
+/* pump.c - Transfer of bulk data (source, object code) */
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#include <sys/time.h>
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#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_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_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;
+}
+
diff --git a/distcc/src/remote.c b/distcc/src/remote.c
new file mode 100644
index 0000000..970891e
--- /dev/null
+++ b/distcc/src/remote.c
@@ -0,0 +1,301 @@
+/* -*- 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
+ */
+
+/*
+ * Send a compilation request to a remote server.
+ */
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#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"
+
+
+/*
+ * 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);
+ /* 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, 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 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.
+ */
+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);
+
+ /* 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;
+
+ dcc_note_state(DCC_PHASE_SEND, NULL, NULL);
+
+ 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 preprocessing. Unlock to allow someone else to
+ start preprocessing */
+ if(local_cpu_lock_fd) { dcc_unlock(local_cpu_lock_fd); }
+
+ 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);
+
+ /* 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:
+ /* 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;
+}
+
+
diff --git a/distcc/src/renderer.c b/distcc/src/renderer.c
new file mode 100644
index 0000000..5560921
--- /dev/null
+++ b/distcc/src/renderer.c
@@ -0,0 +1,299 @@
+/* -*- c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ *
+ * 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 "config.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#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,
+ GdkWindow *window,
+ GtkWidget *UNUSED(widget),
+ GdkRectangle *UNUSED(background_area),
+ GdkRectangle *cell_area,
+ GdkRectangle *UNUSED(expose_area),
+ GtkCellRendererState UNUSED(flags))
+{
+ const struct dcc_history *history;
+ enum dcc_phase state;
+ int x1, y1;
+ int bar_height;
+ int bar_width;
+ 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.. */
+
+ x1 = cell_area->x + cell->xpad;
+ y1 = cell_area->y + cell->ypad;
+ bar_height = cell_area->height - (2 * cell->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_draw_rectangle (window,
+ dcc_phase_gc[state],
+ TRUE, /* fill */
+ x1, y1, bar_width, bar_height);
+ }
+
+ x1 += bar_width;
+ }
+}
+
+
+
+/**
+ * Measure the size that we want to have allocated for this cell.
+ */
+static void
+dcc_cell_renderer_chart_get_size (GtkCellRenderer *UNUSED(cell),
+ GtkWidget *UNUSED (widget),
+ GdkRectangle *UNUSED (cell_area),
+ gint *UNUSED (x_offset),
+ gint *UNUSED (y_offset),
+ gint *UNUSED (width),
+ gint *UNUSED (height))
+{
+ /* default is fine */
+}
+
+
+
+
+static void
+dcc_cell_renderer_chart_class_init (DccCellRendererChartClass *class)
+{
+ 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;
+ cell_class->get_size = dcc_cell_renderer_chart_get_size;
+
+ 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)
+{
+ 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;
+}
diff --git a/distcc/src/renderer.h b/distcc/src/renderer.h
new file mode 100644
index 0000000..d74c95e
--- /dev/null
+++ b/distcc/src/renderer.h
@@ -0,0 +1,48 @@
+/* -*- c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ *
+ * 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 GdkGC *dcc_phase_gc[DCC_PHASE_DONE];
+
+extern const guint dcc_max_history_queue;
diff --git a/distcc/src/rpc.c b/distcc/src/rpc.c
new file mode 100644
index 0000000..93c1f2d
--- /dev/null
+++ b/distcc/src/rpc.c
@@ -0,0 +1,343 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+ /* 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <sys/stat.h>
+
+#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 <version>
+ **/
+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(*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;
+ }
+
+ strncpy(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[] vector from the network.
+ **/
+int dcc_r_argv(int ifd, /*@out@*/ char ***argv)
+{
+ unsigned i;
+ unsigned argc;
+ char **a;
+ int ret;
+
+ *argv = NULL;
+
+ if (dcc_r_token_int(ifd, "ARGC", &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", &a[i])))
+ return ret;
+
+ rs_trace("argv[%d] = \"%s\"", i, a[i]);
+ }
+
+ dcc_trace_argv("got arguments", a);
+
+ return 0;
+}
+
diff --git a/distcc/src/rpc.h b/distcc/src/rpc.h
new file mode 100644
index 0000000..fb47964
--- /dev/null
+++ b/distcc/src/rpc.h
@@ -0,0 +1,48 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+ /* His hand is stretched out, and who shall turn it back?
+ * -- Isaiah 14:27 */
+
+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, /*@out@*/ char ***argv);
+
diff --git a/distcc/src/rslave.c b/distcc/src/rslave.c
new file mode 100644
index 0000000..8541a93
--- /dev/null
+++ b/distcc/src/rslave.c
@@ -0,0 +1,166 @@
+/* Copyright (C) 2005 by Google
+ *
+ * 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
+ */
+
+/* don't blame me, I was in a hurry */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+
+#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; i<nslaves; i++) {
+ pid_t childpid;
+ childpid = fork();
+ switch (childpid) {
+ case -1:
+ return -1;
+ break;
+
+ case 0: /* child */
+ close(rslave->pipeToSlaves[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[] */
+
diff --git a/distcc/src/rslave.h b/distcc/src/rslave.h
new file mode 100644
index 0000000..6ed8ea2
--- /dev/null
+++ b/distcc/src/rslave.h
@@ -0,0 +1,65 @@
+/* Copyright (C) 2005 by Google
+ *
+ * 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 rslave_H
+#define rslave_H
+
+/* don't blame me, I was in a hurry */
+
+#include <unistd.h> /* 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
diff --git a/distcc/src/safeguard.c b/distcc/src/safeguard.c
new file mode 100644
index 0000000..204484e
--- /dev/null
+++ b/distcc/src/safeguard.c
@@ -0,0 +1,81 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#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;
+}
diff --git a/distcc/src/sendfile.c b/distcc/src/sendfile.c
new file mode 100644
index 0000000..794d294
--- /dev/null
+++ b/distcc/src/sendfile.c
@@ -0,0 +1,212 @@
+/* -*- 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
+ */
+
+
+ /* "I've always wanted to use sendfile(), but
+ * never had a reason until now"
+ * -- mbp */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#ifdef HAVE_SYS_SENDFILE_H
+# include <sys/sendfile.h>
+#endif /* !HAVE_SYS_SENDFILE_H */
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#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)
+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;
+ }
+}
+#else
+#warning "Please write a sendfile implementation for this system"
+static ssize_t sys_sendfile(int ofd, int ifd, off_t *offset, size_t 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 == ENOSYS || errno == EINVAL) && 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 if (errno == EAGAIN) {
+ /* Sleep until we're able to write out more data. */
+ if ((ret = dcc_select_for_write(ofd, dcc_io_timeout)) != 0)
+ return ret;
+ rs_trace("select() returned, continuing to write");
+ } else if (errno == EINTR) {
+ rs_trace("sendfile() interrupted, continuing");
+ } 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 */
+
diff --git a/distcc/src/serve.c b/distcc/src/serve.c
new file mode 100644
index 0000000..fc71235
--- /dev/null
+++ b/distcc/src/serve.c
@@ -0,0 +1,781 @@
+/* -*- 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
+ */
+
+ /* 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifdef HAVE_SYS_SIGNAL_H
+# include <sys/signal.h>
+#endif /* HAVE_SYS_SIGNAL_H */
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#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"
+
+/**
+ * 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;
+
+ 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;
+}
+
+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;
+ 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 rewritting 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 -MF 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ if ((ret = dcc_r_argv(in_fd, &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 ((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))
+ || 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:
+
+ 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, time_ms);
+ } else {
+ dcc_stats_event(job_result);
+ }
+
+ asprintf(&time_str, " exit:%d sig:%d core:%d ret:%d time:%dms ", WEXITSTATUS(status), WTERMSIG(status), WCOREDUMP(status), ret, time_ms);
+ 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;
+}
diff --git a/distcc/src/setuid.c b/distcc/src/setuid.c
new file mode 100644
index 0000000..d929a53
--- /dev/null
+++ b/distcc/src/setuid.c
@@ -0,0 +1,138 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <string.h>
+
+#include "distcc.h"
+#include "trace.h"
+#include "daemon.h"
+#include "exitcode.h"
+
+
+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;
+ }
+
+ rs_trace("discarded root privileges, changed to uid=%d gid=%d", (int) uid, (int) gid);
+ return 0;
+}
diff --git a/distcc/src/snprintf.c b/distcc/src/snprintf.c
new file mode 100644
index 0000000..f7885db
--- /dev/null
+++ b/distcc/src/snprintf.c
@@ -0,0 +1,1016 @@
+/*
+ * NOTE: If you change this file, please merge it into rsync, samba, etc.
+ */
+
+/*
+ * 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
+ */
+
+/**************************************************************
+ * 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 <blong@fiction.net> 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 <blong@fiction.net> 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, formated 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 <roessler@guug.de> 01/27/98 for mutt 0.89i
+ * The PGP code was using unsigned hexadecimal formats.
+ * Unfortunately, unsigned formats simply didn't work.
+ *
+ * Michael Elkins <me@cs.hmc.edu> 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 <ollie.oldham@metro-optix.com> for spotting it.
+ * few mods to make it easier to compile the tests.
+ * addedd 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 "config.h"
+#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 <math.h>
+#endif /* TEST_SNPRINTF */
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+#include <sys/types.h>
+#include <stdarg.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) \
+ && defined(HAVE_VASPRINTF) && defined(HAVE_ASPRINTF)
+/* This ifdef switches on or off basically the whole contents of the file. */
+/* Make the compiler happy with an empty file */
+ void dummy_snprintf(void);
+ void dummy_snprintf(void) {}
+#else
+
+#include "snprintf.h"
+
+#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
+
+#ifndef VA_COPY
+#ifdef HAVE_VA_COPY
+#define VA_COPY(dest, src) __va_copy(dest, src)
+#else
+#define VA_COPY(dest, src) (dest) = (src)
+#endif /* ! HAVE_VA_COPY */
+#endif /* ndef VA_COPY */
+
+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,
+ 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;
+ 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 *);
+ if (!strvalue) strvalue = "(NULL)";
+ if (max == -1) {
+ max = strlen(strvalue);
+ }
+ if (min > 0 && max >= 0 && min > max) max = min;
+ fmtstr (buffer, &currlen, maxlen, 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';
+ }
+
+ return currlen;
+}
+
+static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
+ 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 = "<NULL>";
+ }
+
+ 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 index;
+ 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);
+ index = (int) ((temp -intpart +0.05)* 10.0);
+ /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
+ /* printf ("%llf, %f, %x\n", temp, intpart, index); */
+ iconvert[iplace++] =
+ (caps? "0123456789ABCDEF":"0123456789abcdef")[index];
+ } 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);
+ index = (int) ((temp -fracpart +0.05)* 10.0);
+ /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */
+ /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */
+ fconvert[fplace++] =
+ (caps? "0123456789ABCDEF":"0123456789abcdef")[index];
+ } 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)++;
+}
+
+/* yes this really must be a ||. Don't muck with this (tridge) */
+#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+ 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);
+ 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);
+
+ 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 */
+
+#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 */
diff --git a/distcc/src/snprintf.h b/distcc/src/snprintf.h
new file mode 100644
index 0000000..fe3b387
--- /dev/null
+++ b/distcc/src/snprintf.h
@@ -0,0 +1,30 @@
+#include <stdarg.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
diff --git a/distcc/src/srvnet.c b/distcc/src/srvnet.c
new file mode 100644
index 0000000..4759181
--- /dev/null
+++ b/distcc/src/srvnet.c
@@ -0,0 +1,290 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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
+ */
+
+ /* "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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+
+#include <arpa/inet.h>
+
+#ifdef HAVE_RESOLV_H
+# include <resolv.h>
+#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);
+
+ /* 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);
+
+ if (listen(fd, 10)) {
+ 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) {
+ if (psa->sa_family == AF_INET) {
+ in_addr_t cli_inaddr;
+ cli_inaddr = ((struct sockaddr_in *) psa)->sin_addr.s_addr;
+
+ if ((ret = dcc_check_address(cli_inaddr, l->addr, l->mask)) == 0)
+ break;
+#ifdef ENABLE_RFC2553
+ } else if (psa->sa_family == AF_INET6) {
+ const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *) psa;
+ const struct in6_addr *a6 = &sa6->sin6_addr;
+ const in_addr_t *a4;
+
+ if (IN6_IS_ADDR_V4MAPPED(a6) || IN6_IS_ADDR_V4COMPAT(a6)) {
+ a4 = (const in_addr_t *) &a6->s6_addr[12];
+ if ((ret = dcc_check_address(*a4, l->addr, l->mask)) == 0)
+ break;
+ } else {
+ rs_log_notice("ipv6 ACLs not implemented");
+ free(client_ip);
+ return EXIT_ACCESS_DENIED;
+ }
+#endif
+ } else {
+ ret = EXIT_ACCESS_DENIED;
+ rs_log_notice("access denied from unknown address family %d",
+ psa->sa_family);
+ break;
+ }
+ }
+
+ if (ret != 0) {
+ rs_log_error("connection from client '%s' denied by access list",
+ client_ip);
+ }
+ free(client_ip);
+ return ret;
+}
diff --git a/distcc/src/srvnet.h b/distcc/src/srvnet.h
new file mode 100644
index 0000000..5a4ee90
--- /dev/null
+++ b/distcc/src/srvnet.h
@@ -0,0 +1,28 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+/* 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 *);
+
diff --git a/distcc/src/srvrpc.c b/distcc/src/srvrpc.c
new file mode 100644
index 0000000..3a3e9eb
--- /dev/null
+++ b/distcc/src/srvrpc.c
@@ -0,0 +1,181 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ *
+ * Server-specific RPC code.
+ **/
+
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "distcc.h"
+#include "trace.h"
+#include "util.h"
+#include "rpc.h"
+#include "exitcode.h"
+#include "dopt.h"
+#include "hosts.h"
+#include "bulk.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;
+ 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;
+
+ 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;
+ }
+ 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.
+ strncpy(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;
+}
diff --git a/distcc/src/ssh.c b/distcc/src/ssh.c
new file mode 100644
index 0000000..3f9809f
--- /dev/null
+++ b/distcc/src/ssh.c
@@ -0,0 +1,228 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+
+#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.
+ **/
+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;
+ char *child_argv[10];
+ int i;
+
+ /* We need to cast away constness. I promise the strings in the argv[]
+ * will not be modified. */
+
+ if (!ssh_cmd)
+ ssh_cmd = getenv("DISTCC_SSH");
+ 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;
+ if (user) {
+ child_argv[i++] = (char *) "-l";
+ child_argv[i++] = user;
+ }
+ child_argv[i++] = machine;
+ child_argv[i++] = path;
+ child_argv[i++] = (char *) "--inetd";
+ child_argv[i++] = NULL;
+
+ rs_trace("connecting to %s using %s", machine, ssh_cmd);
+
+ /* TODO: If we're verbose, perhaps make the server verbose too, and send
+ * its log to our stderr? */
+ /* child_argv[i++] = (char *) "--log-stderr"; */
+
+ ret = dcc_run_piped_cmd(child_argv, f_in, f_out, ssh_pid);
+
+ return ret;
+}
diff --git a/distcc/src/state.c b/distcc/src/state.c
new file mode 100644
index 0000000..aac34c7
--- /dev/null
+++ b/distcc/src/state.c
@@ -0,0 +1,257 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <sys/time.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+
+#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_";
+
+
+struct dcc_task_state my_state;
+
+
+/**
+ * @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)
+{
+ int fd;
+ int ret;
+ char *fname;
+ struct timeval tv;
+
+ 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)
+{
+ my_state.slot = slot;
+}
diff --git a/distcc/src/state.h b/distcc/src/state.h
new file mode 100644
index 0000000..63486fe
--- /dev/null
+++ b/distcc/src/state.h
@@ -0,0 +1,91 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 */
diff --git a/distcc/src/stats.c b/distcc/src/stats.c
new file mode 100644
index 0000000..e6a92ba
--- /dev/null
+++ b/distcc/src/stats.c
@@ -0,0 +1,415 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2005 by Google
+ *
+ * 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
+ */
+
+// Author: Thomas Kho
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/statvfs.h>
+
+#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 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 */
+} dcc_stats;
+
+struct statsdata {
+ enum stats_e type;
+
+ /* used only for STATS_COMPILE_OK */
+ 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;
+ write(dcc_statspipe[1], &sd, sizeof(sd));
+ }
+}
+
+
+/**
+ * Logs a completed job to stats server
+ **/
+void dcc_stats_compile_ok(char *compiler, char *filename, int time_usec) {
+ if (arg_stats) {
+ struct statsdata sd;
+ memset(&sd, 0, sizeof(sd));
+
+ sd.type = STATS_COMPILE_OK;
+ /* also send compiler, filename & runtime */
+ sd.time = time_usec;
+ strncpy(sd.filename, filename, MAX_FILENAME_LEN);
+ strncpy(sd.compiler, compiler, MAX_FILENAME_LEN);
+ write(dcc_statspipe[1], &sd, sizeof(sd));
+ }
+}
+
+
+/*
+ * 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;
+
+ const char replytemplate[] = "\
+HTTP/1.0 200 OK\n\
+Content-Type: text/plain\n\
+Connection: close\n\n\
+argv /distccd\n\
+<distccstats>\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_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\
+</distccstats>\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_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);
+ read(acc_fd, challenge, 1024); /* empty the receive queue */
+ write(acc_fd, reply, reply_len);
+ }
+
+ /* Don't think we need this to prevent RST anymore, since we read() now */
+ //shutdown(acc_fd, SHUT_WR); /* prevent connection reset */
+ 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:
+ /* 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);
+ }
+ 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();
+
+ 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);
+ }
+}
diff --git a/distcc/src/stats.h b/distcc/src/stats.h
new file mode 100644
index 0000000..34e4371
--- /dev/null
+++ b/distcc/src/stats.h
@@ -0,0 +1,46 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2005 by Google (Thomas Kho <tkho at google.com>)
+ *
+ * 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_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 };
+
+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, int time_usec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DISTCC_STATS_H */
diff --git a/distcc/src/stringmap.c b/distcc/src/stringmap.c
new file mode 100644
index 0000000..2c3d26f
--- /dev/null
+++ b/distcc/src/stringmap.c
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+#include "stringmap.h"
+
+#ifndef NULL
+#define NULL 0
+#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 = calloc(1, sizeof(*result));
+ FILE *fp = fopen(filename, "r");
+ char buf[2*PATH_MAX];
+ int n;
+
+ result->numFinalWordsToMatch = numFinalWordsToMatch;
+ if (!fp)
+ 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)
+ 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)
+ break;
+ }
+ }
+ for (i=0; i<map->n; 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)); } }
+
+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", NULL);
+ verifyMap(sm, "/foo/bar/bletch", "/foo/bar/bletch");
+}
+
+#endif
diff --git a/distcc/src/stringmap.h b/distcc/src/stringmap.h
new file mode 100644
index 0000000..f13fbb0
--- /dev/null
+++ b/distcc/src/stringmap.h
@@ -0,0 +1,27 @@
+#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
diff --git a/distcc/src/strip.c b/distcc/src/strip.c
new file mode 100644
index 0000000..09ce76e
--- /dev/null
+++ b/distcc/src/strip.c
@@ -0,0 +1,178 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+
+#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 wierd, 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.
+ **/
+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])) {
+ /* 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;
+}
+
+
+
diff --git a/distcc/src/tempfile.c b/distcc/src/tempfile.c
new file mode 100644
index 0000000..fb6eb2e
--- /dev/null
+++ b/distcc/src/tempfile.c
@@ -0,0 +1,412 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+ /* "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 "config.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "distcc.h"
+#include "trace.h"
+#include "util.h"
+#include "snprintf.h"
+#include "exitcode.h"
+
+
+
+/**
+ * @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 ((buf.st_mode & S_IFDIR) == S_IFDIR) {
+ 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;
+}
+
+
+/* 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 TMPTOP/randomnumber
+ * 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;
+}
+
+
+int dcc_get_tmp_top(const char **p_ret)
+{
+ const char *d;
+
+ d = getenv("TMPDIR");
+
+ if (!d || d[0] == '\0') {
+ *p_ret = "/tmp";
+ return 0;
+ } else {
+ *p_ret = d;
+ return 0;
+ }
+}
+
+/**
+ * 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.
+ **/
+static 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;
+}
diff --git a/distcc/src/timefile.c b/distcc/src/timefile.c
new file mode 100644
index 0000000..bce8c87
--- /dev/null
+++ b/distcc/src/timefile.c
@@ -0,0 +1,159 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ *
+ * @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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+
+#include <sys/stat.h>
+#include <sys/file.h>
+
+#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;
+}
diff --git a/distcc/src/timefile.h b/distcc/src/timefile.h
new file mode 100644
index 0000000..8abbfe6
--- /dev/null
+++ b/distcc/src/timefile.h
@@ -0,0 +1,33 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+/* 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);
diff --git a/distcc/src/timeval.c b/distcc/src/timeval.c
new file mode 100644
index 0000000..5106b98
--- /dev/null
+++ b/distcc/src/timeval.c
@@ -0,0 +1,36 @@
+/* from the GNU libc manual */
+
+#include <sys/time.h>
+#include <time.h>
+
+#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;
+}
diff --git a/distcc/src/timeval.h b/distcc/src/timeval.h
new file mode 100644
index 0000000..3781269
--- /dev/null
+++ b/distcc/src/timeval.h
@@ -0,0 +1,4 @@
+int
+timeval_subtract(struct timeval *result,
+ struct timeval *x,
+ struct timeval *y);
diff --git a/distcc/src/trace.c b/distcc/src/trace.c
new file mode 100644
index 0000000..9ec7858
--- /dev/null
+++ b/distcc/src/trace.c
@@ -0,0 +1,433 @@
+/*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*-
+ *
+ * ecolog - Reusable application logging library.
+ *
+ * Copyright (C) 2000 - 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/file.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <syslog.h>
+
+#include "trace.h"
+#include "snprintf.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;
+
+
+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)
+ l->fn(flags, caller_fn_name,
+ fmt, va, l->private_ptr, l->private_int);
+}
+
+
+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;
+
+ 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");
+
+ (void) write(log_fd, 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];
+void dcc_job_summary_clear(void) {
+ job_summary[0] = 0;
+}
+
+void dcc_job_summary(void) {
+ rs_log_notice("%s", job_summary);
+}
+
+void dcc_job_summary_append(const char *s) {
+ strncat(job_summary, s, 4096-strlen(job_summary));
+}
diff --git a/distcc/src/trace.h b/distcc/src/trace.h
new file mode 100644
index 0000000..0d99e0f
--- /dev/null
+++ b/distcc/src/trace.h
@@ -0,0 +1,230 @@
+/*= -*- 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 <stdarg.h>
+
+/* 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 suport. */
+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);
diff --git a/distcc/src/traceenv.c b/distcc/src/traceenv.c
new file mode 100644
index 0000000..2a60858
--- /dev/null
+++ b/distcc/src/traceenv.c
@@ -0,0 +1,93 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#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));
+ }
+}
diff --git a/distcc/src/types.h b/distcc/src/types.h
new file mode 100644
index 0000000..6f57bf5
--- /dev/null
+++ b/distcc/src/types.h
@@ -0,0 +1,36 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 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
diff --git a/distcc/src/util.c b/distcc/src/util.c
new file mode 100644
index 0000000..16c803e
--- /dev/null
+++ b/distcc/src/util.c
@@ -0,0 +1,769 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 "config.h"
+
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <netdb.h>
+#include <ctype.h>
+
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_SYS_LOADAVG_H
+#include <sys/loadavg.h>
+#endif
+
+#include <sys/param.h>
+
+#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(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));
+ *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));
+ }
+ 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 {
+#ifdef HAVE_GETCWD
+ getcwd(buf, sizeof buf);
+#else
+ getwd(buf);
+#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 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;
+}
+
+
+/* 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
+ *num_D = -1;
+ *max_RSS = -1;
+ *max_RSS_name = "none";
+#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 */
+ fscanf(f, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s");
+
+ 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 {
+ /* individual parition stats */
+ //retval = fscanf(f, " %*d %d %*d %d", &reads, &writes);
+ //if (retval == EOF || retval != 2)
+ // break;
+ /* assume the lines aren't longer that 1024 characters */
+ fgets(tmp, 1024, f);
+ }
+ }
+
+ 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
+
+/* 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(*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;
+}
diff --git a/distcc/src/util.h b/distcc/src/util.h
new file mode 100644
index 0000000..e2aefed
--- /dev/null
+++ b/distcc/src/util.h
@@ -0,0 +1,55 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 <setjmp.h>
+
+/* 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);
diff --git a/distcc/src/where.c b/distcc/src/where.c
new file mode 100644
index 0000000..de71647
--- /dev/null
+++ b/distcc/src/where.c
@@ -0,0 +1,197 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+
+ /* 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 "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+
+#include <sys/stat.h>
+#include <sys/file.h>
+
+#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);
+
+
+int dcc_pick_host_from_list(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 = 1;
+
+ dcc_note_state(DCC_PHASE_BLOCKED, NULL, NULL);
+
+ rs_trace("nothing available, sleeping %us...", pause_time);
+
+ sleep(pause_time);
+}
+
+
+/**
+ * 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 < 50; i_cpu++) {
+ for (h = hostlist; h; h = h->next) {
+ if (i_cpu >= h->n_slots)
+ continue;
+
+ ret = dcc_lock_host("cpu", h, i_cpu, 0, cpu_lock_fd);
+
+ if (ret == 0) {
+ *buildhost = h;
+ dcc_note_state_slot(i_cpu);
+ return 0;
+ } else if (ret == EXIT_BUSY) {
+ continue;
+ } else {
+ rs_log_error("failed to lock");
+ return ret;
+ }
+ }
+ }
+
+ 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);
+ dcc_note_state(DCC_PHASE_CPP, NULL, chosen->hostname);
+ return ret;
+}
+
diff --git a/distcc/src/where.h b/distcc/src/where.h
new file mode 100644
index 0000000..d4c8dcd
--- /dev/null
+++ b/distcc/src/where.h
@@ -0,0 +1,29 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78; -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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
+ */
+
+/* where.c */
+int dcc_pick_host_from_list(struct dcc_hostdef **,
+ int *cpu_lock_fd);
+
+int dcc_lock_local(int *cpu_lock_fd);
+
+int dcc_lock_local_cpp(int *cpu_lock_fd);
diff --git a/distcc/survey.txt b/distcc/survey.txt
new file mode 100644
index 0000000..5fc84d9
--- /dev/null
+++ b/distcc/survey.txt
@@ -0,0 +1,35 @@
+If you find distcc useful, please take a little time to fill out this
+survey and mail it to {mbp at samba org}.
+
+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 survery, 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!
+Martin
diff --git a/distcc/test/comfychair.py b/distcc/test/comfychair.py
new file mode 100755
index 0000000..522f9be
--- /dev/null
+++ b/distcc/test/comfychair.py
@@ -0,0 +1,445 @@
+#! /usr/bin/env python
+
+# Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+# Copyright (C) 2003 by Tim Potter <tpot@samba.org>
+#
+# 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
+
+"""comfychair: a Python-based instrument of software torture.
+
+Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+Copyright (C) 2003 by Tim Potter <tpot@samba.org>
+
+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, re
+
+
+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)
+
+
+ # --------------------------------------------------
+ # Save and restore directory
+ def _enter_rundir(self):
+ import os
+ 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')
+ os.system("rm -fr %s" % self.rundir)
+ os.makedirs(self.tmpdir)
+ os.system("mkdir -p %s" % self.rundir)
+ os.chdir(self.rundir)
+
+ def _restore_directory(self):
+ import os
+ os.chdir(self.basedir)
+
+ # --------------------------------------------------
+ # Save and restore environment
+ def _save_environment(self):
+ import os
+ self._saved_environ = os.environ.copy()
+ self.add_cleanup(self._restore_environment)
+
+ def _restore_environment(self):
+ import os
+ 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 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."""
+ import os
+ 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" % `(a, b)`)
+
+ def assert_notequal(self, a, b):
+ if a == b:
+ raise AssertionError("assertNotEqual failed: %s" % `(a, 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" % (`s`, `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" % (`s`, `pattern`))
+
+
+ def assert_no_file(self, filename):
+ import os.path
+ assert not os.path.exists(filename), ("file exists but should not: %s" % filename)
+
+
+ #############################################################
+ # Methods for running programs
+
+ def runcmd_background(self, cmd):
+ import os
+ self.test_log = self.test_log + "Run in background:\n" + `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)."""
+ import os, types
+ 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, 0666)
+ os.dup2(outfd, 1)
+ os.close(outfd)
+
+ errfd = os.open('%d.err' % pid, openmode, 0666)
+ os.dup2(errfd, 2)
+ os.close(errfd)
+
+ if isinstance(cmd, types.StringType):
+ 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)"""
+ import os
+ waitstatus, stdout, stderr = self.run_captured(cmd)
+ assert not os.WIFSIGNALED(waitstatus), \
+ ("%s terminated with signal %d" % (`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" % `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
+"""
+ import sys
+ 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 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 test_class in test_list:
+ print "%-30s" % _test_name(test_class),
+ # flush now so that long running tests are easier to follow
+ sys.stdout.flush()
+
+ obj = None
+ try:
+ try: # run test and show result
+ obj = test_class()
+ obj.setup()
+ obj.runtest()
+ print "OK"
+ except KeyboardInterrupt:
+ print "INTERRUPT"
+ _report_error(obj, debugger)
+ ret = 2
+ break
+ except NotRunError, msg:
+ print "NOTRUN, %s" % msg.value
+ except:
+ print "FAIL"
+ _report_error(obj, debugger)
+ ret = 1
+ finally:
+ while obj and obj._cleanups:
+ try:
+ apply(obj._cleanups.pop())
+ except KeyboardInterrupt:
+ print "interrupted during teardown"
+ _report_error(obj, debugger)
+ ret = 2
+ break
+ except:
+ print "error during teardown"
+ _report_error(obj, debugger)
+ ret = 1
+ # Display log file if we're verbose
+ if ret == 0 and verbose:
+ obj.explain_failure()
+
+ return ret
+
+
+def _test_name(test_class):
+ """Return a human-readable name for a test class.
+ """
+ try:
+ return test_class.__name__
+ except:
+ return `test_class`
+
+
+def print_help():
+ """Help for people running tests"""
+ import sys
+ 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.
+"""
+ from sys import argv
+ import getopt, sys
+
+ opt_verbose = 0
+ debugger = None
+
+ opts, args = getopt.getopt(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__
diff --git a/distcc/test/onetest.py b/distcc/test/onetest.py
new file mode 100755
index 0000000..ec743da
--- /dev/null
+++ b/distcc/test/onetest.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python2.4
+#
+# Copyright 2007 Google Inc. All Rights Reserved.
+
+"""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@google.com (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__)
diff --git a/distcc/test/testdistcc.py b/distcc/test/testdistcc.py
new file mode 100755
index 0000000..2d12e00
--- /dev/null
+++ b/distcc/test/testdistcc.py
@@ -0,0 +1,1708 @@
+#! /usr/bin/env python2.2
+
+# Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
+#
+# 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 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 pattens 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: Run the server in a different directory from the clients
+
+# 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: Test compiling a really large source file that produces a
+# large object file. Perhaps need to generate it at run time -- just
+# one big array?
+
+# TODO: Perhaps redirect stdout, stderr to a temporary file while
+# running? Use os.open(), os.dup2().
+
+# TODO: Test "distcc gcc -c foo.c bar.c". gcc would actually compile
+# both of them. We could split it into multiple compiler invocations,
+# but this is so rare that it's probably not worth the complexity. So
+# at the moment is just handled locally.
+
+# TODO: Test crazy option arguments like "distcc -o -output -c foo.c"
+
+# TODO: Test attempt to compile a nonexistent file.
+
+# 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: Set umask 0, then check that the files are created with mode
+# 0644.
+
+# 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: Set LANG=C before running all tests, to try to make sure that
+# localizations don't break attempts to parse error messages. Is
+# setting LANG enough, or do we also need LC_*? (Thanks to Oscar
+# Esteban.)
+
+# 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.
+
+
+import time, sys, string, os, types, re, popen2, pprint, socket
+import signal, os.path, string, glob
+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
+
+_gcc = 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".
+
+class SimpleDistCC_Case(comfychair.TestCase):
+ '''Abstract base class for distcc tests'''
+ def setup(self):
+ self.stripEnvironment()
+
+ def stripEnvironment(self):
+ """Remove all DISTCC variables from the environment, so that
+ the test is not affected by the development environment."""
+ for key in 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()
+
+
+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):
+ import random
+ 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 = 42000 # 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):
+ import signal, time
+
+ 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"
+ % (self.daemon_lifetime(),
+ self.daemon_logfile, 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):
+ import string
+ for prog in 'distcc', 'distccd':
+ out, err = self.runcmd("%s --version" % prog)
+ assert out[-1] == '\n'
+ out = out[:-1]
+ line1,line2,trash = string.split(out, '\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 1."""
+ def runtest(self):
+ self.runcmd(self.distcc() + _gcc + " --bogus-option", 1)
+ self.runcmd(self.distccd() + _gcc + " --bogus-option",
+ EXIT_BAD_ARGUMENTS)
+
+
+class GccOptionsPassed_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()
+ + _gcc + " --help")
+ if re.search('distcc', out):
+ raise ("gcc help contains \"distcc\": \"%s\"" % out)
+ self.assert_re_match(r"^Usage: gcc", out)
+
+
+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, `o`, `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"),
+ ]
+ for tup in cases:
+ apply(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 = string.split(o)
+ 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.cpp -o hello.o", "*.d", 0, None),
+ ("foo.cpp -o hello", "*.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),
+ ("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"),
+ ]
+
+ 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(char **argv) {};
+"""
+ def sourceFilename(self):
+ return args.split()[0]
+ def compileCmd(self):
+ return _gcc + " " + args
+ def runtest(self):
+ self.compile()
+ glob_result = glob.glob(dep_glob)
+ dotd_result.extend(glob_result)
+
+ comfychair.runtests([TempCompile_Case])
+
+ 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
+ ddc_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
+ return m_obj.group(1)
+
+ def makeFile(self, f):
+ fd = open(f, "w")
+ fd.close()
+
+ def makeFiles(self, files):
+ for f in files:
+ self.makeFile(f)
+
+ def runtest(self):
+
+ # Test dcc_discrepancy_filename
+ # ********************************
+ os.environ['INCLUDE_SERVER_PORT'] = "abc/socket"
+ out, err = self.runcmd(
+ "h_compile ddc_discrepancy_filename")
+ self.assert_equal(out, "abc/discrepancy_counter")
+
+ os.environ['INCLUDE_SERVER_PORT'] = "socket"
+ out, err = self.runcmd(
+ "h_compile ddc_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:
+ self.makeFiles(deps)
+ # 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 = set([])
+ for line in err.split("\n"):
+ if re.search("[^ ]", line):
+ # Line is non-blank
+ checked_deps.add(self.getDep(line))
+ self.assert_equal(checked_deps, set(deps))
+
+ # 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. We'll have to advance real time beyond time_ref before doing
+ # this.
+ while time.time() <= time_ref:
+ time.sleep(1)
+ if deps:
+ self.makeFile(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.
+ apply(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",
+ 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" % (`expected`, `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" % (`cmd`, out))
+ if err != '':
+ self.fail("compiler command %s produced error:\n%s" % (`cmd`, err))
+
+ def link(self):
+ cmd = self.linkCmd()
+ out, err = self.runcmd(cmd)
+ if out != '':
+ self.fail("command %s produced output:\n%s" % (`cmd`, `out`))
+ if err != '':
+ self.fail("command %s produced error:\n%s" % (`cmd`, `err`))
+
+ def compileCmd(self):
+ """Return command to compile source and run tests"""
+ return self.distcc_without_fallback() + \
+ _gcc + " -o testtmp.o -c %s" % (self.sourceFilename())
+
+ def linkCmd(self):
+ return self.distcc() + \
+ _gcc + " -o testtmp testtmp.o"
+
+ def checkCompileMsgs(self, msgs):
+ if msgs <> '':
+ self.fail("expected no compiler messages, got \"%s\""
+ % msgs)
+
+ def checkBuiltProgram(self):
+ '''Check compile 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 <stdio.h>
+#include "testhdr.h"
+int main(void) {
+ puts(HELLO_WORLD);
+ return 0;
+}
+"""
+
+ def checkBuiltProgramMsgs(self, msgs):
+ self.assert_equal(msgs, "hello world\n")
+
+
+class ObjectiveC_Case(Compilation_Case):
+ """Test building an Objective-C program."""
+
+ def sourceFilename(self):
+ return "testtmp.m"
+
+ def headerSource(self):
+ return """
+#define HELLO_WORLD "hello world"
+"""
+
+ def source(self):
+ return """
+#import <stdio.h>
+#import "testhdr.h"
+
+int main(void) {
+ puts(HELLO_WORLD);
+ return 0;
+}
+"""
+
+class ObjectiveCPlusPlus_Case(Compilation_Case):
+ """Test building an Objective-C++ program."""
+
+ def sourceFilename(self):
+ return "testtmp.mm"
+
+ def headerSource(self):
+ return """
+#define HELLO_WORLD "hello world"
+"""
+
+ def source(self):
+ return """
+#import <iostream>
+#import "testhdr.h"
+
+int main(void) {
+ std::cout << HELLO_WORLD << endl;
+ 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 _gcc + " -g ";
+
+ def compileCmd(self):
+ """Return command to compile source and run tests"""
+ 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() + " -o link/testtmp obj/testtmp.o"
+ out, err = self.runcmd(cmd)
+ if out != '':
+ self.fail("command %s produced output:\n%s" % (`cmd`, `out`))
+ if err != '':
+ self.fail("command %s produced error:\n%s" % (`cmd`, `err`))
+
+ def checkBuiltProgram(self):
+ # Run gdb and verify that it is able to correctly locate the
+ # testtmp.c source file.
+ out, errs = self.runcmd("gdb --batch " +
+ "-ex 'break main' -ex 'run' -ex 'step' link/testtmp </dev/null")
+ self.assert_equal(errs, '')
+ self.assert_re_search('puts\\(HELLO_WORLD\\);', out)
+ self.assert_re_search('testtmp.c:5', out)
+
+ # Now do the same, but in a subdirectory.
+ # This tests that the "compilation directory" field
+ # of the object file is set correctly.
+ os.mkdir('run')
+ os.chdir('run')
+ self.runcmd("cp ../link/testtmp ./testtmp")
+ msgs, errs = self.runcmd("gdb --batch " +
+ "-ex 'break main' -ex 'run' -ex 'step' ./testtmp </dev/null")
+ self.assert_equal(errs, '')
+ self.assert_re_search('puts\\(HELLO_WORLD\\);', out)
+ self.assert_re_search('testtmp.c:5', out)
+ os.chdir('..')
+
+ # Now recompile and relink the executable using ordinary
+ # gcc rather than distcc; strip both executables;
+ # and check that the executable generated with ordinary
+ # gcc is bit-for-bit identical to the executable that was
+ # generated by distcc. This is just to double-check
+ # that we didn't modify anything other than the ".debug_info"
+ # section.
+ self.runcmd(self.compiler() + " -o obj/testtmp.o -I. -c %s" %
+ self.sourceFilename())
+ self.runcmd(self.compiler() + " -o link/testtmp obj/testtmp.o")
+ self.runcmd("strip link/testtmp && strip run/testtmp")
+ self.runcmd("cmp link/testtmp run/testtmp")
+
+class GdbOpt1_Case(Gdb_Case):
+ def compiler(self):
+ """Command for compiling and linking."""
+ return _gcc + " -g -O1 ";
+
+class GdbOpt2_Case(Gdb_Case):
+ def compiler(self):
+ """Command for compiling and linking."""
+ return _gcc + " -g -O2 ";
+
+class GdbOpt3_Case(Gdb_Case):
+ def compiler(self):
+ """Command for compiling and linking."""
+ return _gcc + " -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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() + \
+ _gcc + " -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() + _gcc + \
+ " -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 <stdio.h>
+
+int main(void) {
+ extern const char *msg;
+ puts(msg);
+ return 0;
+}
+""")
+
+ def runtest(self):
+ self.runcmd(self.distcc()
+ + _gcc + " -c test1.c test2.c")
+ self.runcmd(self.distcc()
+ + _gcc + " -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() + _gcc + " -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 <nosuchfilehere.h>
+"""
+
+ def runtest(self):
+ self.runcmd(self.distcc() +
+ _gcc + " -o testtmp.o -c testtmp.c", 1)
+
+
+class PreprocessPlainText_Case(Compilation_Case):
+ """Try using cpp on something that's not C at all"""
+ def setup(self):
+ self.stripEnvironment()
+ self.createSource()
+
+ 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()
+ + _gcc + " -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" %
+ (self.daemon_logfile, 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.
+ sock = socket.socket()
+ while sock.connect_ex(('127.0.0.1', self.server_port)) != 0:
+ time.sleep(0.2)
+
+ def killDaemon(self):
+ import signal
+ 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':
+ CompileHello_Case.runtest (self)
+ else:
+ raise comfychair.NotRunError ('HP-UX bundled C compiler non-ANSI')
+
+
+class DashD_Case(Compilation_Case):
+ """Test preprocessor arguments"""
+ def source(self):
+ return """
+#include <stdio.h>
+
+int main(void) {
+ printf("%s\\n", MESSAGE);
+ return 0;
+}
+"""
+
+ def compileCmd(self):
+ # quoting is hairy because this goes through the shell
+ return self.distcc() + _gcc + \
+ " -c -o testtmp.o '-DMESSAGE=\"hello world\"' testtmp.c"
+
+ def checkBuiltProgramMsgs(self, msgs):
+ self.assert_equal(msgs, "hello world\n")
+
+
+class AbsSourceFilename_Case(CompileHello_Case):
+ """Test remote compilation of files with absolute names."""
+
+ def compileCmd(self):
+ return (self.distcc()
+ + _gcc
+ + " -c -o testtmp.o %s/testtmp.c"
+ % os.getcwd())
+
+
+class ThousandFold_Case(CompileHello_Case):
+ """Try repeated simple compilations"""
+ def daemon_lifetime(self):
+ return 120
+
+ def runtest(self):
+ # may take about a minute or so
+ for i in xrange(1000):
+ self.runcmd(self.distcc()
+ + _gcc + " -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 i in xrange(50):
+ kid = self.runcmd_background(self.distcc() +
+ _gcc + " -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 xrange(200000):
+ f.write("int i%06d = %d;\n" % (i, i))
+ f.close()
+
+ def runtest(self):
+ self.runcmd(self.distcc() + _gcc + " -c %s" % "testtmp.c")
+ self.runcmd(self.distcc() + _gcc + " -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() +
+ _gcc + " -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()
+
+ def runtest(self):
+ self.runcmd(self.distcc()
+ + _gcc + " -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() + _gcc + " -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)
+ # XXX: Need to also handle "syntax error" from gcc-2.95.3
+ self.assert_re_match(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):
+ import os
+
+ # 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('printenv')
+ 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() + \
+ _gcc + " -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.
+ 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() + _gcc + " -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")
+
+ def runtest(self):
+ self.compile()
+
+
+
+
+class ModeBits_Case(CompileHello_Case):
+ """Check distcc obeys umask"""
+ def runtest(self):
+ self.runcmd("umask 0; distcc " + _gcc + " -c testtmp.c")
+ self.assert_equal(S_IMODE(os.stat("testtmp.o")[ST_MODE]), 0666)
+
+
+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. """
+
+ def source(self):
+ return ''
+
+ def runtest(self):
+ self.compile()
+
+ def compile(self):
+ self.runcmd(self.distcc()
+ + _gcc + " -c %s" % self.sourceFilename())
+
+ def sourceFilename(self):
+ return "testtmp.i"
+
+class BadLogFile_Case(SimpleDistCC_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() + \
+ _gcc + " -c foo.c", expectedResult=1)
+ 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"
+ % (self.daemon_lifetime(),
+ self.daemon_logfile, self.daemon_pidfile, self.server_port))
+
+ def compileCmd(self):
+ """Return command to compile source and run tests"""
+ return self.distcc_with_fallback() + \
+ _gcc + " -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)
+
+ # 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 = ["127.0.0.1", "127.0.0.2", "localhost"]
+ 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\n", out)
+ self.assert_re_search("127.0.0.2\n", out)
+ self.assert_re_search("127.0.0.3\n", out)
+ self.assert_re_search("127.0.0.4\n", out)
+ self.assert_re_search("127.0.0.5\n", out)
+
+# When invoking compiler, use absolute path so distccd can find it
+for path in os.environ['PATH'].split (':'):
+ abs_path = os.path.join (path, 'gcc')
+
+ if os.path.isfile (abs_path):
+ _gcc = abs_path
+ break
+
+# All the tests defined in this suite
+tests = [
+ CompileHello_Case,
+ # Support for Objective C in distcc-pump is currently disabled.
+ ### ObjectiveC_Case,
+ # I couldn't test the Objective C++ case,
+ # because I couldn't figure out how to install
+ # GNU Objective C++. So this test is disabled for now.
+ ### ObjectiveCPlusPlus_Case,
+ Gdb_Case,
+ GdbOpt1_Case,
+ GdbOpt2_Case,
+ GdbOpt3_Case,
+ Lsdistcc_Case,
+ BadLogFile_Case,
+ ScanArgs_Case,
+ ParseMask_Case,
+ DotD_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,
+ BinFalse_Case,
+ BinTrue_Case,
+ VersionOption_Case,
+ HelpOption_Case,
+ BogusOption_Case,
+ MultipleCompile_Case,
+ GccOptionsPassed_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,
+ # slow tests below here
+ Concurrent_Case,
+ ThousandFold_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]
+
+ comfychair.main(tests)
diff --git a/include_server/Makefile.in b/include_server/Makefile.in
new file mode 100644
index 0000000..ad9661d
--- /dev/null
+++ b/include_server/Makefile.in
@@ -0,0 +1,114 @@
+distcc_srcdir := $(shell make --directory=../distcc --no-print-directory \
+ --silent echo_srcdir)
+srcdir := $(shell cd $(distcc_srcdir)/../include_server && pwd)
+builddir := $(shell pwd)/build
+
+# Autoconf configuration variables.
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datadir = @datadir@
+testdir = $(builddir)/testdir
+INSTALL = @INSTALL@
+DESTDIR = /
+PYTHON = @PYTHON@
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build:
+ cd $(srcdir) && \
+ BUILDDIR=$(builddir) $(PYTHON) ./setup.py \
+ build \
+ --build-base=$(builddir) \
+ --build-temp=$(builddir)
+
+.PHONY: install
+install:
+ cd $(srcdir) && \
+ BUILDDIR=$(builddir) $(PYTHON) ./setup.py \
+ build \
+ --build-base=$(builddir) \
+ --build-temp=$(builddir) \
+ install \
+ --prefix=$(prefix) \
+ --record=$(PYTHON_INSTALL_RECORD) \
+ --root=$(DESTDIR)
+
+# Below we delete the link and then we recreate it. Otherwise, a second link
+# will be created the second time install-for-tests is run! That's because the
+# link name would now be resolved as a target directory (third form according to
+# 'man ln'). As a result a link to the test_data directory would be inserted
+# into the test_data directory under the name 'test_data'.
+.PHONY: install-for-tests
+install-for-tests:
+ mkdir -p $(testdir)
+ if [ -h $(testdir)/test_data ]; then \
+ rm -f $(testdir)/test_data; \
+ fi
+ ln -s $(realpath $(srcdir)/test_data) \
+ $(testdir)/test_data
+ cd $(srcdir) && \
+ BUILDDIR=$(builddir) $(PYTHON) ./setup.py \
+ build -f \
+ --build-base=$(testdir) \
+ --build-temp=$(testdir) \
+ install \
+ --install-lib=$(testdir)/python \
+ --install-scripts=$(testdir)/python
+
+
+.PHONY: check maintainer-check
+check maintainer-check: test
+
+.PHONY: test
+test: install-for-tests \
+ c_extensions_test include_server_test macro_eval_test mirror_path_test\
+ parse_command_test parse_file_test \
+ include_analyzer_test include_analyzer_memoizing_node_test \
+ basics_test
+
+.PHONY: c_extensions_test
+c_extensions_test: install-for-tests
+ cd $(testdir) && PYTHONPATH=$(testdir)/python/include_server $(PYTHON) $(testdir)/python/include_server/c_extensions_test.py \
+ > c_extensions_test.out 2>&1
+ @echo Filtering c_extensions_test.out
+ @cd $(testdir) && cat c_extensions_test.out \
+ | grep -v 'distcc_include_server\[.*\] (dcc_r_token_int) ERROR: protocol derailment: expected token "XXXX"' \
+ | grep -v 'distcc_include_server\[.*\] (dcc_explain_mismatch) ERROR: error context: "ARGC 2ARGV 6tomatoARGV 7potatos"'
+.PHONY: include_server_test
+include_server_test: install-for-tests
+ cd $(testdir) && PYTHONPATH=$(testdir)/python/include_server $(PYTHON) $(testdir)/python/include_server/include_server_test.py
+.PHONY: macro_eval_test
+macro_eval_test: install-for-tests
+ cd $(testdir) && PYTHONPATH=$(testdir)/python/include_server $(PYTHON) $(testdir)/python/include_server/macro_eval_test.py
+.PHONY: mirror_path_test
+mirror_path_test: install-for-tests
+ cd $(testdir) && PYTHONPATH=$(testdir)/python/include_server $(PYTHON) $(testdir)/python/include_server/mirror_path_test.py
+.PHONY: parse_command_test
+parse_command_test: install-for-tests
+ cd $(testdir) && PYTHONPATH=$(testdir)/python/include_server $(PYTHON) $(testdir)/python/include_server/parse_command_test.py
+.PHONY: parse_file_test
+parse_file_test: install-for-tests
+ cd $(testdir) && PYTHONPATH=$(testdir)/python/include_server $(PYTHON) $(testdir)/python/include_server/parse_file_test.py
+.PHONY: include_analyzer_test
+include_analyzer_test: install-for-tests
+ cd $(testdir) && PYTHONPATH=$(testdir)/python/include_server $(PYTHON) $(testdir)/python/include_server/include_analyzer_test.py
+.PHONY: include_analyzer_memoizing_node_test
+include_analyzer_memoizing_node_test: install-for-tests
+ cd $(testdir) && PYTHONPATH=$(testdir)/python/include_server $(PYTHON) $(testdir)/python/include_server/include_analyzer_memoizing_node_test.py
+.PHONY: basics_test
+basics_test: install-for-tests
+ cd $(testdir) && PYTHONPATH=$(testdir)/python/include_server $(PYTHON) $(testdir)/python/include_server/basics_test.py
+
+Makefile: Makefile.in config.status
+ ./config.status
+
+.PHONY: clean
+clean:
+ $(PYTHON) $(srcdir)/setup.py clean \
+ --build-base=$(builddir) \
+ --build-temp=$(builddir)
+ rm -rf $(testdir)
+
diff --git a/include_server/__init__.py b/include_server/__init__.py
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/include_server/__init__.py
diff --git a/include_server/basics.py b/include_server/basics.py
new file mode 100755
index 0000000..597313d
--- /dev/null
+++ b/include_server/basics.py
@@ -0,0 +1,339 @@
+#! /usr/bin/python2.4
+#
+# 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.
+#
+
+"""Common and low-level stuff for include server."""
+
+__author__ = "Nils Klarlund"
+
+import sys
+import tempfile
+import os.path
+import signal
+import resource
+
+# MISCELLANEOUS CONSTANTS
+
+# Place for creation of temporary directories.
+client_tmp = None
+# And, the current such temporary directory.
+client_root = None
+
+# This constant is embedded in names of client root directories.
+INCLUDE_SERVER_NAME = "include_server"
+
+def InitializeClientTmp():
+ """Determine the tmp directory to use.
+
+ Use the RAM disk-like /dev/shm as default place to store compressed files if
+ available."""
+
+ global client_tmp
+ if "DISTCC_CLIENT_TMP" in os.environ:
+ client_tmp = os.environ["DISTCC_CLIENT_TMP"]
+ elif os.path.isdir("/dev/shm") and os.access("/dev/shm",
+ os.X_OK + os.W_OK + os.R_OK):
+ client_tmp = "/dev/shm"
+ else:
+ client_tmp = "/tmp"
+ if not client_tmp or client_tmp[0] != '/':
+ sys.exit("DISTCC_CLIENT_TMP must start with '/'.")
+ client_tmp = client_tmp.rstrip('/')
+ # The protocol between the include server and distcc client stipulates
+ # that the top three directories constitute the prefix prepended to absolute
+ # file paths. To have room to make a temp directory, we'll need to have less
+ # than two levels at this point.
+ # Note: "/a/b".split('/') == ["", "a", "b'].
+ if len(client_tmp.split('/')) > 3:
+ sys.exit("DISTCC_CLIENT_TMP must have at most two directory levels.")
+
+
+def InitializeClientRoot(generation):
+ """Make a 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.
+ """
+ assert client_tmp
+ global client_root
+ 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.
+ client_root = tempfile.mkdtemp(".%s-%s-%d" %
+ (INCLUDE_SERVER_NAME,
+ os.getpid(), generation),
+ dir=client_tmp)
+ number_missing_levels = 3 - len(client_tmp.split('/'))
+ # Stuff client_root path until we have exactly three levels in all.
+ for i in range(number_missing_levels):
+ client_root = client_root + "/padding"
+ os.mkdir(client_root)
+ except (IOError, OSError), why:
+ sys.exit("Could not create client root directory %s: %s" %
+ (client_root, why))
+
+
+# For automated emails, see also distcc/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
+
+# 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 ]
+
+
+# FLAGS FOR COMMAND LINE OPTIONS
+
+opt_debug_pattern = 1 # see DEBUG below
+opt_verify = False # whether to compare calculated include closure to that
+ # produced by compiler
+opt_exact_analysis = False # use CPP instead of include analyzer
+opt_write_include_closure = False # write include closures to file
+opt_statistics = False
+opt_algorithm = MEMOIZING
+opt_stat_reset_triggers = {}
+opt_simple_algorithm = False
+opt_print_times = False
+opt_send_email = False
+opt_email_bound = MAX_EMAILS_TO_SEND
+opt_realpath_warning_re = None
+
+
+# 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
+
+
+# REALPATH WARNINGS
+
+BAD_REALPATH_WARNING_MSG = (
+ "For translation unit '%s' while processing '%s': lookup of file '%s' "
+ + "resolved to '%s' whose realpath is '%s'.")
+
+
+# LANGUAGES AND FILE EXTENSIONS
+
+# The languages that we recognize.
+#
+# TODO: add "objective-c" and "objective-c++".
+# Currently we try to compute the default include path for all
+# languages at startup, and barf if it fails. We need to fix that
+# before enabling objective-c or objective-c++.
+# So Objective C and Objective C++ support is disabled for now.
+#
+# (Also, I couldn't test the Objective C++ case, because I couldn't figure
+# out how to install GNU Objective C++. We need to test it before
+# enabling it.)
+# To enable, uncomment the code below and the test case
+# ObjectiveC(PlusPlus)_Case in ../distcc/test/testdistcc.py.)
+
+LANGUAGES = set(["c", "c++"])
+#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):
+ triggered = opt_debug_pattern & trigger_pattern
+ if triggered:
+ i = 1
+ for unused_j in range(DEBUG_NUM_BITS):
+ if i & DEBUG_WARNING & triggered:
+ print >> sys.stderr, "WARNING include server:", message % params
+ if i & DEBUG_TRACE & triggered:
+ print >> sys.stderr, "TRACE:", message % params
+ elif i & DEBUG_TRACE1 & triggered:
+ print >> sys.stderr, "TRACE1:", message % params
+ elif i & DEBUG_TRACE2 & triggered:
+ print >> sys.stderr, "TRACE2:", message % params
+ elif i & DEBUG_DATA & triggered:
+ print >> sys.stderr, "DATA:", message % params
+ i *= 2
+ sys.stderr.flush()
+
+
+# EXCEPTIONS
+
+class Error(Exception):
+ 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):
+ """An instance of this class is raised when the include server has spent too
+ much time analyzing dependencies."""
+ pass
+
+
+class IncludeAnalyzerTimer(object):
+ """Start a timer that limits the amount of CPU time the include analyzer may
+ spend 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, _sig_number, _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(*_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.
+
+ 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("/")
diff --git a/include_server/basics_test.py b/include_server/basics_test.py
new file mode 100755
index 0000000..7b7308c
--- /dev/null
+++ b/include_server/basics_test.py
@@ -0,0 +1,65 @@
+#! /usr/bin/python2.4
+
+# 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 unittest
+
+import basics
+
+class BasicsTest(unittest.TestCase):
+
+ def setUp(self):
+
+ basics.opt_debug_pattern = 1
+
+ def tearDown(self):
+ pass
+
+ def test_InitializeClientTmp(self):
+ os.environ['DISTCC_CLIENT_TMP'] = 'to/be'
+ self.assertRaises(SystemExit, basics.InitializeClientTmp)
+ os.environ['DISTCC_CLIENT_TMP'] = '/to/be/or'
+ self.assertRaises(SystemExit, basics.InitializeClientTmp)
+ try:
+ os_mkdir = os.mkdir
+
+ def Mock_os_mkdir(f, *args):
+ if not f.startswith('/to/'):
+ raise Exception, f
+ os.mkdir = Mock_os_mkdir
+
+ os.environ['DISTCC_CLIENT_TMP'] = '/to/be'
+ basics.InitializeClientTmp()
+ basics.InitializeClientRoot(1)
+ self.assertEqual(os.path.dirname(basics.client_root), "/to/be")
+ os.environ['DISTCC_CLIENT_TMP'] = '/to'
+ basics.InitializeClientTmp()
+ basics.InitializeClientRoot(2)
+ self.assertEqual(os.path.dirname(
+ os.path.dirname(basics.client_root)), "/to")
+ self.assertEqual(os.path.basename(basics.client_root), "padding")
+ self.assertEqual(len(
+ [ None for ch in basics.client_root if ch == '/' ]), 3)
+ finally:
+ os.mkdir = os_mkdir
+
+unittest.main()
diff --git a/include_server/c_extensions/distcc_pump_c_extensions_module.c b/include_server/c_extensions/distcc_pump_c_extensions_module.c
new file mode 100644
index 0000000..e7477dd
--- /dev/null
+++ b/include_server/c_extensions/distcc_pump_c_extensions_module.c
@@ -0,0 +1,381 @@
+/* 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 char *version = ".01";
+
+/* To suppress compiler warnings */
+#define UNUSED(v) ((void)&v)
+
+char *rs_program_name = "distcc_include_server";
+
+#include "distcc.h"
+#include "rpc.h"
+
+static PyObject *distcc_pump_c_extensionsError;
+
+
+/***********************************************************************
+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 = PyString_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 PyString_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 PyString_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, &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 = PyString_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 */
+ argv[i] = PyString_AsString(string_object); /* does not increase
+ ref count */
+ }
+ ret = dcc_x_argv(ifd, 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;
+ char *res;
+ PyObject *result_str;
+
+ UNUSED(dummy);
+ if (!PyArg_ParseTuple(args, "s", &in))
+ return NULL;
+ res = realpath(in, NULL);
+ if (res) {
+ result_str = PyString_FromStringAndSize(res, strlen(res));
+ if (result_str == NULL)
+ return PyErr_NoMemory();
+ return result_str;
+ }
+ else
+ return PyString_FromStringAndSize(in, strlen(in));
+}
+
+
+
+/***********************************************************************
+Bindings
+************************************************************************/
+
+static PyMethodDef 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 /* const */ char module_documentation[]=
+"Various utilities for distcc-pump.\n"
+;
+
+void initdistcc_pump_c_extensions(void) {
+ PyObject *module;
+ PyObject *py_str;
+ distcc_pump_c_extensionsError = PyErr_NewException(
+ "distcc_pump_c_extensions.Error", NULL, NULL);
+
+ module = Py_InitModule4("distcc_pump_c_extensions",
+ methods,
+ module_documentation,
+ NULL,
+ PYTHON_API_VERSION);
+
+ py_str = PyString_FromString("Nils Klarlund");
+ PyModule_AddObject(module, "__author__", py_str);
+ py_str = PyString_FromString(version);
+ PyModule_AddObject(module, "__version__", py_str);
+ /* Make the exception class accessible */
+ PyModule_AddObject(module, "Error",
+ distcc_pump_c_extensionsError);
+
+}
diff --git a/include_server/c_extensions_test.py b/include_server/c_extensions_test.py
new file mode 100755
index 0000000..abb9414
--- /dev/null
+++ b/include_server/c_extensions_test.py
@@ -0,0 +1,132 @@
+#!/usr/bin/python2.4
+
+# 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 sys
+import os.path
+import time
+import traceback
+import struct
+import random
+
+import distcc_pump_c_extensions
+
+
+def main():
+
+ # Module tempfile doesn't work with distcc. Work-around follows.
+ random_filename = "distcc-pump" + str(random.random() * time.time())
+ if os.path.exists(random_filename):
+ print sys.stderr >> (
+ """"For unfathomably unlikely reasons, this test failed: '%s' exists."""
+ % random_filename)
+ sys.exit(1)
+ 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
+ pack = struct.pack
+ fd = _MakeTempFile('wb')
+ fd.write("ARGC 2")
+ fd.write("ARGV 6")
+ fd.write("tomato")
+ fd.write("ARGV 7")
+ fd.write("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 i in range(10000):
+ distcc_pump_c_extensions.OsPathExists(f);
+ print 'Stat', time.time() - t
+ t = time.time()
+ for i in range(10000):
+ os.path.exists(f);
+ print 'os.path.exists', time.time() - t
+ for i in range(10000):
+ distcc_pump_c_extensions.Realpath(f);
+ print 'c_realpath', time.time() - t
+ t = time.time()
+ for i in range(10000):
+ os.path.realpath(f);
+ print 'os.path.realpath', time.time() - t
+
+ print "Test passed"
+
+try:
+ main()
+except:
+ traceback.print_exc()
+ sys.exit("c_extensions_test.py failed.")
diff --git a/include_server/cache_basics.py b/include_server/cache_basics.py
new file mode 100755
index 0000000..7be7507
--- /dev/null
+++ b/include_server/cache_basics.py
@@ -0,0 +1,858 @@
+#! /usr/bin/python2.4
+
+# 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 <foo/bar.h>" 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 <foo/bar.h>", 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 <ipath1>
+ cache[os.path.join(currdir, searchdir2, includepath1)] # #include <ipath1>
+ cache[os.path.join(currdir, searchdir3, includepath1)] # #include <ipath1>
+ [etc...until the cache-lookup returns True]
+ cache[os.path.join(currdir, searchdir1, includepath2)] # #include <ipath2>
+ cache[os.path.join(currdir, searchdir2, includepath2)] # #include <ipath2>
+ cache[os.path.join(currdir, searchdir3, includepath2)] # #include <ipath2>
+ [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 Represenation 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
+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 xrange(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 +.
+ """
+
+ def Index(self, relpath):
+ """Return index d > 0 of relative path.
+ Argument:
+ directory: a string not starting with /.
+ """
+ if os.path.isabs(relpath):
+ raise NotCoveredError("Filepath must be relative but isn't: '%s'." %
+ 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.bad_realpath_tuples = []
+
+ 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 </usr/include/string.h>"??), 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 GetAndClearBadResolutions(self):
+ """Return descriptions of resolutions matching realpath warning regexp.
+ Returns:
+ a list of tuples of the form
+ (include_path, resolved_path, real_path)
+ where include_path is the argument of an #include (or an initial file),
+ resolved_path is the concatenation of the searchdir where the
+ include_path is found with this include_path, and real_path is the
+ realpath of this location (relative to the current directory).
+ The list is reset to [] with this operation. Thus the items returned are
+ those that occcurred since the last time this method was invoked.
+ """
+ bad_realpath_tuples = self.bad_realpath_tuples
+ self.bad_realpath_tuples = []
+ return bad_realpath_tuples
+
+ 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 <foo>"
+ 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]
+ 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], (
+ "'%s/' != '%s'" % (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 explictly 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
+ # abspath_warning option. See documentation for method
+ # GetAndClearBadResolutions.
+ if basics.opt_realpath_warning_re:
+ realpath = self.realpath_map.string[realpath_idx]
+ if basics.opt_realpath_warning_re.search(realpath):
+ self.bad_realpath_tuples.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
+
+ IsFilepathIndex: test for filepath index
+ IsDirectoryIndex: test for director index
+ IsRealpathIndex: test for realpath index
+ IsFilepathPair: test for filepath pair
+ """
+
+ def __init__(self):
+ # 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)
+ 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())
diff --git a/include_server/compiler_defaults.py b/include_server/compiler_defaults.py
new file mode 100755
index 0000000..2e039ae
--- /dev/null
+++ b/include_server/compiler_defaults.py
@@ -0,0 +1,180 @@
+#! /usr/bin/python2.4
+
+# 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 re
+import sys
+import basics
+import subprocess
+
+Debug = basics.Debug
+DEBUG_TRACE = basics.DEBUG_TRACE
+DEBUG_DATA = basics.DEBUG_DATA
+NotCoveredError = basics.NotCoveredError
+
+
+def _SystemSearchdirsGCC(compiler, language, canonical_lookup):
+ """Run gcc on empty file; parse output to figure out default paths.
+
+ Arguments:
+ compiler: a filepath (the first argument on the distcc command line)
+ 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, "-x", language, "-v", "-c", "/dev/null", "-o",
+ "/dev/null"]
+
+ try:
+ # We annul 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.)
+ p = subprocess.Popen(command,
+ shell=False,
+ stdin=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ env={})
+ out = p.communicate()[0]
+ except (IOError, OSError), 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(
+ r"%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 directory in match_obj.group(1).split() ]
+
+
+class CompilerDefaults(object):
+ """Records and caches the default searchdirs, aka include directories
+ or search-path. The 'default' searchdirs are those built in to the
+ preprocessor, as opposed to being set on the commandline via -I et al.
+
+ This scheme works only for gcc, and only some versions at that.
+ """
+
+ def __init__(self, canonical_lookup):
+ """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
+ """
+ self.canonical_lookup = canonical_lookup
+ self.system_dirs_default_all = set([])
+ self.system_dirs_default = {}
+
+
+ def SetSystemDirsDefaults(self, compiler, timer=None):
+ """Set instance variables according to compiler.
+
+ Arguments:
+ compiler: a string "c", "c++",...
+ 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 constructor documentation for this class.
+ """
+ assert isinstance(compiler, str)
+ Debug(DEBUG_TRACE, "SetSystemDirsDefauls with CC: %s" % compiler)
+ if compiler in self.system_dirs_default: return
+ 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] = {}
+ # Try 'c', 'c++', ...
+ for language in basics.LANGUAGES:
+ self.system_dirs_default[compiler][language] = (
+ _SystemSearchdirsGCC(compiler, language, self.canonical_lookup))
+ Debug(DEBUG_DATA,
+ "system_dirs_default[%s][%s]: %s" %
+ (compiler, language,
+ self.system_dirs_default[compiler][language]))
+ # Now summarize what we know and add to system_dirs_default_all.
+ self.system_dirs_default_all |= set(
+ [ _default
+ for _compiler in self.system_dirs_default
+ for _language in self.system_dirs_default[_compiler]
+ for _default in self.system_dirs_default[_compiler][_language] ])
+ finally:
+ if timer:
+ timer.Start()
diff --git a/include_server/compress_files.py b/include_server/compress_files.py
new file mode 100755
index 0000000..133eb5f
--- /dev/null
+++ b/include_server/compress_files.py
@@ -0,0 +1,112 @@
+#! /usr/bin/python2.4
+
+# 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):
+ """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
+ # The realpath_map indices of files that have been compressed already.
+ self.files_compressed = set([])
+
+ def Compress(self, include_closure, client_root):
+ """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: a directory name, see basics.py, the directory to which
+ compressed files are mirrored
+ 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. 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, realpath)
+ else:
+ new_filepath = "%s%s.lzo" % (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):
+ os.makedirs(dirname)
+ except (IOError, OSError), 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")
+ except (IOError, OSError), why:
+ sys.exit("Could not open '%s' for reading: %s" % (realpath, why))
+ try:
+ new_filepath_fd = open(new_filepath, "wb")
+ except (IOError, OSError), 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), why:
+ sys.exit("Could not write to '%s': %s" % (new_filepath, why))
+ new_filepath_fd.close()
+ real_file_fd.close()
+ return files
diff --git a/include_server/configure.ac b/include_server/configure.ac
new file mode 100644
index 0000000..e9cdbe7
--- /dev/null
+++ b/include_server/configure.ac
@@ -0,0 +1,10 @@
+AC_INIT(distcc_pump_include_server,
+ esyscmd(source ../version.sh && echo -n $DISTCC_PUMP_VERSION),
+ distcc-pump@google.com)
+AC_CHECK_PROGS(PYTHON, [python2.4 python2.3 python-2.3 python2.2 python-2.2 python])
+AC_ARG_VAR(PYTHON, [Python interpreter])
+AC_CONFIG_AUX_DIR(../distcc)
+AC_CONFIG_FILES([Makefile])
+AC_PROG_INSTALL
+AC_OUTPUT
+
diff --git a/include_server/include_analyzer.py b/include_server/include_analyzer.py
new file mode 100755
index 0000000..4706d14
--- /dev/null
+++ b/include_server/include_analyzer.py
@@ -0,0 +1,362 @@
+#! /usr/bin/python2.4
+
+# 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()
+
+ # 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)
+ # 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)
+ # 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, stat_reset_triggers={}):
+ self.generation = 1
+ basics.InitializeClientRoot(self.generation)
+ self.client_root = basics.client_root
+ 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, 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)
+ 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)
+ 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],
+ "include file",
+ self.quote_dirs))
+ total_closure.update(self._ProcessFileFromCommandLine(translation_unit,
+ "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):
+ """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))
+ (_, _, _, source_file, result_file_prefix, _) = 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.
+ links = self.mirror_path.Links()
+ files = self.compress_files.Compress(include_closure, basics.client_root)
+ realpath_map = self.realpath_map
+
+ files_and_links = files + links
+
+ 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 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 "<cwd>/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, "<cwd>/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.
+ basics.InitializeClientRoot(self.generation)
+ self.client_root = basics.client_root
+ self._InitializeAllCaches()
diff --git a/include_server/include_analyzer_memoizing_node.py b/include_server/include_analyzer_memoizing_node.py
new file mode 100755
index 0000000..7a917b4
--- /dev/null
+++ b/include_server/include_analyzer_memoizing_node.py
@@ -0,0 +1,641 @@
+#! /usr/bin/python2.4
+
+# 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, stat_reset_triggers={}):
+ """Constructor."""
+ include_analyzer.IncludeAnalyzer.__init__(self,
+ 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 previosly 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)
+
+ # 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 <foo.h>.
+ 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 <foo.h>.
+ 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)
diff --git a/include_server/include_analyzer_memoizing_node_test.py b/include_server/include_analyzer_memoizing_node_test.py
new file mode 100755
index 0000000..898c921
--- /dev/null
+++ b/include_server/include_analyzer_memoizing_node_test.py
@@ -0,0 +1,233 @@
+#! /usr/bin/python2.4
+
+# 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
+ basics.InitializeClientTmp()
+ self.include_analyzer = (
+ include_analyzer_memoizing_node.IncludeAnalyzerMemoizingNode())
+
+ 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()
diff --git a/include_server/include_analyzer_test.py b/include_server/include_analyzer_test.py
new file mode 100755
index 0000000..d784eac
--- /dev/null
+++ b/include_server/include_analyzer_test.py
@@ -0,0 +1,508 @@
+#! /usr/bin/python2.4
+
+# 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 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
+ basics.InitializeClientTmp()
+ if algorithm == basics.MEMOIZING:
+ self.include_analyzer = (
+ include_analyzer_memoizing_node.IncludeAnalyzerMemoizingNode())
+ 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(../TEST_DATA/dfoo/P)" """
+ + """-DTEST_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_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.failUnless(re.match(r"/dev/shm/.+[.]include_server[-][0-9]+[-]%s"
+ % 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):
+ # 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())
+
+ # 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):
+ 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.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):
+ 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())
+
+ # 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_dotdot_dotdot_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_dotdot_dotdot_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_dotdot_dotdot_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##_pre.c>'), (['a'], '<a##_post.c>')]})
+
+
+ # 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
diff --git a/include_server/include_server.py b/include_server/include_server.py
new file mode 100755
index 0000000..a0a9c21
--- /dev/null
+++ b/include_server/include_server.py
@@ -0,0 +1,723 @@
+#!/usr/bin/python2.4
+
+# 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 os
+import re
+import sys
+import glob
+import signal
+import getopt
+import tempfile
+import traceback
+import SocketServer
+
+# Include server imports
+import basics
+import statistics
+import include_analyzer_memoizing_node
+import distcc_pump_c_extensions
+
+# 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 """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:
+ --pid_file FILEPATH The pid of the include server is written to file
+ FILEPATH.
+ -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.
+ --no-email Do not send email.
+ --email_bound NUMBER Maximal number of emails to send (in addition to
+ a final email). Default: 3.
+ --realpath_warning_re=RE Write a warning to stderr whenever a filename is
+ resolved to a realpath that is matched by RE,
+ which is a regular expression in Python syntax.
+ (Warnings must be enabled with at least -d1.)
+ --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.
+ -x, --exact_analysis Use CPP instead, do not omit system headers files.
+ -v, --verify Verify that files in CPP closure are contained in
+ closure calculated by include processor.
+ -s, --statistics Print information to stdout about include analysis.
+ -t, --time Print elapsed, user, and system time to stderr.
+ -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.
+"""
+
+# TODO(klarlund)
+# --simple_algorithm not currently implemented
+
+
+# UTILITIES
+
+def _PrintStackTrace(fd):
+ """Print stacktrace to file object."""
+ print >> fd, '------- Include server stack trace -----------'
+ # Limit is 1000 entries.
+ traceback.print_exc(1000, fd)
+ print >> 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()
+
+
+def _RemoveDirectoryTree(tree_top):
+ """Recursively remove everything.
+
+ Ignore filesystem errors, because this function may be called as a last resort
+ and it does its job on a best-effort basis.
+ """
+ # Copied, more or less, from Python 2.4 Library Reference.
+ if not os.access(tree_top, os.W_OK):
+ return
+ for root, dirs, files in os.walk(tree_top, topdown=False):
+ for name in files:
+ try:
+ os.remove(os.path.join(root, name))
+ except (IOError, OSError): # should not happen
+ pass
+ for name in dirs:
+ try:
+ if os.path.islink(os.path.join(root, name)):
+ os.remove(os.path.join(root, name))
+ else:
+ os.rmdir(os.path.join(root, name))
+ except (IOError, OSError): # should not happen
+ pass
+ try:
+ os.rmdir(root)
+ except (IOError, OSError): # should not happen
+ pass
+
+
+def _CleanOutClientRoots(client_root):
+ """Delete client root directory and everything below, for all generations.
+ Argument:
+ client_root: a directory path ending in "*distcc-*-*"
+ """
+ # Determine all generations of this directory.
+ hyphen_ultimate_position = client_root.rfind('-')
+ client_roots = glob.glob("%s-*" % client_root[:hyphen_ultimate_position])
+ assert client_root in client_roots
+ for client_root_ in client_roots:
+ _RemoveDirectoryTree(client_root_)
+
+
+def _CleanOutOthers():
+ """Search for left-overs from include servers that have passed away."""
+ # Find all distcc-pump directories whether abandoned or not.
+ distcc_directories = glob.glob("%s/*.%s-*-*" % (basics.client_tmp,
+ basics.INCLUDE_SERVER_NAME))
+ 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[:hyphen_ultimate_position].rfind(
+ '-')
+ 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)
+ _CleanOutClientRoots(directory)
+
+
+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")
+ # 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), 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)
+ 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, inst:
+ # Warn user. The 'Preprocessing locally' message is meant to
+ # assure the user that the build process is otherwise intact.
+ fd = os.tmpfile()
+ print >> fd, (
+ "Preprocessing locally. Include server not covering: %s for "
+ + "translation unit '%s'") % (
+ (inst.args and inst.args[0] or "unknown reason",
+ include_analyzer.translation_unit)),
+ # 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, 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 = os.tmpfile()
+ print >> fd, (
+ ("Preprocessing locally. Include server fatal error: '%s' for "
+ + "translation unit '%s'") % (
+ (inst.args, include_analyzer.translation_unit))),
+ _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, 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 = os.tmpfile()
+ print >> fd, (
+ ("Preprocessing locally. Include server internal error: '%s: %s' "
+ + "for translation unit '%s'") % (
+ (inst.__class__, inst.args, include_analyzer.translation_unit))),
+ _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)
+ # 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:estvw",
+ ["port=",
+ "pid_file=",
+ "debug_pattern=",
+ "email",
+ "no-email",
+ "email_bound=",
+ "exact_analysis",
+ "stat_reset_triggers=",
+ "simple_algorithm",
+ "realpath_warning_re=",
+ "statistics",
+ "time",
+ "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 ("--realpath_warning_re",):
+ basics.opt_realpath_warning_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 ("-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 >> sys.stderr, "INCLUDE_SERVER_PORT not provided. Aborting."
+ print >> sys.stderr, "-------------------------------------------"
+ print >> 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 >> sys.stderr, "Include server timing. ",
+ print >> sys.stderr, (
+ "Elapsed: %3.1fs User: %3.1fs System: %3.1fs User + System: %3.1fs" %
+ (total_e, total_u, total_s, total_cpu))
+
+
+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) != '\n':
+ sys.exit("Include server: _IncludeServerPortReady.Acquire failed.")
+
+ def Release(self):
+ """Release the semaphore after fork."""
+ if os.write(self.write_fd, '\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.")
+
+ # Determine basics.client_tmp now.
+ basics.InitializeClientTmp()
+ # So that we can call this function --- to sweep out possible junk. Also, this
+ # will allow the include analyzer to call InitializeClientRoot.
+ _CleanOutOthers()
+
+ Debug(DEBUG_TRACE, "Starting socketserver %s" % include_server_port)
+
+ # Create the analyser.
+ include_analyzer = (
+ include_analyzer_memoizing_node.IncludeAnalyzerMemoizingNode(
+ 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:
+ _CleanOutClientRoots(include_analyzer.client_root)
+ 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_fd, pid
+ 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:
+ server.serve_forever()
+ except KeyboardInterrupt:
+ print >> sys.stderr, (
+ "Include server: keyboard interrupt, quitting after cleaning up.")
+ _CleanOut(include_analyzer, include_server_port)
+ except SignalSIGTERM:
+ Debug(DEBUG_TRACE, "Include server shutting down.")
+ _CleanOut(include_analyzer, include_server_port)
+ except:
+ print >> sys.stderr, (
+ "Include server: exception occurred, quitting after cleaning up.")
+ _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()
diff --git a/include_server/include_server_test.py b/include_server/include_server_test.py
new file mode 100755
index 0000000..c115106
--- /dev/null
+++ b/include_server/include_server_test.py
@@ -0,0 +1,187 @@
+#!/usr/bin/python2.4
+
+# 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 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):
+ try:
+ self_test = self
+ basics.InitializeClientTmp()
+ 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())
+
+ 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.assert_(
+ "Include server not covering: " +
+ "Could not find translation unit 'parse.c'" in 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):
+
+ self_test.assert_(
+ "Include server internal error: 'exceptions.AssertionError" in txt)
+
+ self_test.assert_("""for translation unit 'parse.c'""" in txt)
+
+ # This email should be sent.
+ self_test.assertEqual(never, False)
+
+ got_here.append(True)
+
+ 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.assert_(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.assert_(
+ "Filepath must be relative but isn't: '/love/of/my/life'."
+ in 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
+
+ finally:
+ 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()
diff --git a/include_server/macro_eval.py b/include_server/macro_eval.py
new file mode 100755
index 0000000..a4f4293
--- /dev/null
+++ b/include_server/macro_eval.py
@@ -0,0 +1,437 @@
+#! /usr/bin/python2.4
+
+# 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 evalution 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 consiting 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)
+ sub_re = re.compile(r"\b%s\b" % re.escape(x))
+ Debug(DEBUG_TRACE2,
+ """_SubstituteSymbolInString (result): "%s" """, sub_re.sub(y, str))
+ return sub_re.sub(y, str)
+
+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):
+ """Reevalute 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
+ descriping 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 <filepath> 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)
+ 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))
diff --git a/include_server/macro_eval_test.py b/include_server/macro_eval_test.py
new file mode 100755
index 0000000..be9508a
--- /dev/null
+++ b/include_server/macro_eval_test.py
@@ -0,0 +1,233 @@
+#! /usr/bin/python2.4
+
+# 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 unittest
+
+NotCoveredError = basics.NotCoveredError
+
+class MacroEvalTest(unittest.TestCase):
+
+ def setUp(self):
+
+ basics.opt_debug_pattern = 1
+
+ caches = cache_basics.SetUpCaches()
+
+ 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):
+ pass
+
+
+ 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'], "<a##_post.c>" )] }),
+ set(['m(abc)', '<abc_post.c>']))
+
+ 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()
+ 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()
diff --git a/include_server/mirror_path.py b/include_server/mirror_path.py
new file mode 100755
index 0000000..3be5062
--- /dev/null
+++ b/include_server/mirror_path.py
@@ -0,0 +1,113 @@
+#!/usr/bin/python2.4
+
+# 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."""
+
+ def __init__(self,
+ simple_build_stat,
+ canonical_path):
+ """Constructor.
+
+ Arguments:
+ simple_build_stat: object of type SimpleBuildStat
+ canonical_path: function of type CanonicalPath
+ """
+ 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
+
+ def Links(self):
+ """Return the list of symbolic links created."""
+ return self.links
+
+ 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 root_prefix_real is there
+ if not lookup(root_prefix_real):
+ if not os.path.isdir(root_prefix_real):
+ os.makedirs(root_prefix_real)
+ 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
diff --git a/include_server/mirror_path_test.py b/include_server/mirror_path_test.py
new file mode 100755
index 0000000..81c64c1
--- /dev/null
+++ b/include_server/mirror_path_test.py
@@ -0,0 +1,145 @@
+#! /usr/bin/python2.4
+
+# 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 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
+
+ caches = cache_basics.SetUpCaches()
+
+ 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)
+
+ 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):
+ pass
+
+ 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' startd 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.assert_(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()
diff --git a/include_server/parse_command.py b/include_server/parse_command.py
new file mode 100755
index 0000000..87bec61
--- /dev/null
+++ b/include_server/parse_command.py
@@ -0,0 +1,464 @@
+#! /usr/bin/python2.4
+
+# 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 basics
+import cache_basics
+
+Debug = basics.Debug
+DEBUG_TRACE = basics.DEBUG_TRACE
+NotCoveredError = basics.NotCoveredError
+
+# TODO(klarlund): Make mechanism for handling -D, -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 = None
+ self.sysroot = None
+ 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 _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: _RaiseNotImplemented('-MF'),
+ '-MT': lambda ps, arg: None,
+ '-MQ': 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),
+ '-isysroot': lambda ps, arg: _RaiseNotImplemented('-isysroot'),
+ '-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),
+# '--sysroot=': lambda ps, arg: ps.set_sysroot(arg),
+ '--sysroot=': lambda ps, arg: None,
+}
+CPP_OPTIONS_MAYBE_TWO_WORDS_FIRST_LETTERS = ('M', 'i', '-')
+# 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
+
+# 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,
+}
+
+# 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 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,
+ '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'(?<!\\)"') # backtracking, could also be improved
+ESC_QUOTE_RE = re.compile(r'\\"')
+
+def ParseCommandLineSlowly(line):
+ """Parse line as if it were issued in a shell.
+
+ Split the line into a list of string arguments indicated by spaces,
+ except that doubly quoted substrings are treated atomically. Also,
+ do allow backslash escaped quotes; they are turned into regular
+ quotes. This function is written for efficiency; only very simple
+ regular expressions are used in main loop.
+
+ The parser is not needed when the include server is driven by
+ distcc, because the distcc client passes the argv vector. It is used
+ as part of a faster parser.
+ """
+
+ if "'" in line:
+ raise NotCoveredError("Single-quotes not accepted in command line.")
+ args = []
+ # Set position of first quote if it exists.
+ m_unesc_q = NONESC_QUOTE_RE.search(line, 0)
+ if m_unesc_q:
+ unesc_q = m_unesc_q.end() - 1
+ else:
+ unesc_q = sys.maxint
+ m_nonspc = NONSPACE_RE.search(line, 0)
+ if not m_nonspc:
+ return args
+ start = m_nonspc.start()
+ end = start + 1
+ while True:
+ # Invariant: (1) start is at the beginning of the next argument
+ # (perhaps at a quote, which will later be removed). (2) end is
+ # such that line[start:end] is a prefix of the argument.
+ assert start <= unesc_q
+ assert start < end <= len(line), (start, end, len(line))
+ assert not SPACE_RE.match(line, start)
+ assert unesc_q == sys.maxint or line[unesc_q] == '"'
+ try:
+ end = SPACE_RE.search(line, end).start()
+ except AttributeError:
+ end = len(line)
+ if end < unesc_q:
+ # We're good: no quotes found, we have an argument.
+ args.append(ESC_QUOTE_RE.sub(
+ '"',
+ QUOTE_RE.sub(
+ '',
+ line[start:end])))
+ # Search for beginning of next argument.
+ try:
+ start = NONSPACE_RE.search(line, end).start()
+ except AttributeError:
+ return args
+ # We have one character so far.
+ end = start + 1
+ continue
+ # We found a quote. Look for its counterpart.
+ assert start <= unesc_q < end
+ if unesc_q == len(line) - 1:
+ raise NotCoveredError("""Unexpected '"' at end of line.""")
+ m_unesc_q = NONESC_QUOTE_RE.search(line, unesc_q + 1)
+ if not m_unesc_q:
+ raise NotCoveredError("""Missing '"', could not parse command line.""")
+ assert m_unesc_q.end() - 1 > 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.maxint
+
+
+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<suffix>%s)$" %
+ '|'.join([re.escape(ext)
+ for ext in basics.TRANSLATION_UNIT_MAP.keys()])))
+
+
+def ParseCommandArgs(args, current_dir, fp_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
+ fp_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 fp_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(fp_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 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
+
+ # 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)
+ parse_state.language = language_match.group('suffix')
+ assert parse_state.language in basics.TRANSLATION_UNIT_MAP
+
+ compiler_defaults.SetSystemDirsDefaults(compiler, 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:
+ angle_dirs.extend(
+ IndexDirs(compiler_defaults.system_dirs_default
+ [compiler][basics.TRANSLATION_UNIT_MAP[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 = tuple([fp_map.Index(basics.SafeNormPath(f))
+ 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)
diff --git a/include_server/parse_command_test.py b/include_server/parse_command_test.py
new file mode 100755
index 0000000..fd5db01
--- /dev/null
+++ b/include_server/parse_command_test.py
@@ -0,0 +1,196 @@
+#! /usr/bin/python2.4
+
+# 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 unittest
+
+NotCoveredError = basics.NotCoveredError
+
+class ParseCommandUnitTest(unittest.TestCase):
+
+ def setUp(self):
+
+ basics.opt_debug_pattern = 1
+
+ caches = cache_basics.SetUpCaches()
+
+ 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
+
+ def Mock_SetSystemDirsDefaults(compiler, timer=None):
+ if compiler != mock_compiler:
+ raise Exception, "compiler: %s, mock_compiler: %s" % (
+ compiler, mock_compiler)
+
+ 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 = {}
+ self.compiler_defaults.system_dirs_default[mock_compiler] = {}
+ self.compiler_defaults.system_dirs_default[mock_compiler]['c'] = []
+ self.compiler_defaults.system_dirs_default[mock_compiler]['c++'] = []
+
+ def tearDown(self):
+ pass
+
+
+ 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 + " -isystem system -Imice -iquote/and -I/men a.c "
+ " -include included_A.h "
+ " -includeincluded_B.h "
+ "-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"],
+ 'a.c'))
+
+
+ self.assertRaises(NotCoveredError,
+ parse_command.ParseCommandArgs,
+ parse_command.ParseCommandLine(
+ self.mock_compiler +" -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"
+ + " -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'))
+
+ def test_time_ParseCommandArgs(self):
+ """Time ParseCommandArgs."""
+ fd = open("test_data/gws-main.o.cmd", "r")
+ whopper = fd.read()
+ fd.close()
+ # TODO(klarlund): make this into a fail/pass test as well.
+ t = time.time()
+ for unused_i in range(100):
+ (quote_dirs, angle_dirs, include_files, filepath,
+ _include_closure_file, _d_opts) = (
+ parse_command.ParseCommandArgs(
+ parse_command.ParseCommandLine(whopper),
+ os.getcwd(),
+ self.includepath_map,
+ self.directory_map,
+ self.compiler_defaults))
+ print "100 iterations of ParseCommandArgs takes %3.1fs" % (time.time() - t)
+ return True
+
+
+unittest.main()
diff --git a/include_server/parse_file.py b/include_server/parse_file.py
new file mode 100755
index 0000000..c13d27e
--- /dev/null
+++ b/include_server/parse_file.py
@@ -0,0 +1,342 @@
+#! /usr/bin/python2.4
+
+# 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<directive> # 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<symbol>\w+) # the symbol, named 'symbol'
+ ( \s*
+ [(] \s* # beginning parenthesis
+ (?P<args> # 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> include_next | include | import)
+ \s*
+ ( "(?P<quote> (\w|[_/.+-])*)" | # "bar/foo.h"
+ <(?P<angle> (\w|[_/.+-])*)> | # <stdio.h>
+ (?P<expr> .*?)) # expr, match . minimally
+ )
+ |
+ (?P<define> define \s+ (?P<lhs> %s) # insert MACRO_EXPR here
+ \s* (?P<rhs> .*?)) # 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<quote> (\w|[_/.+-])*)\s*" |
+ <\s*(?P<angle> (\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, 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.clock()
+ statistics.parse_file_counter += 1
+
+ includepath_map_index = self.includepath_map.Index
+
+ try:
+ fd = open(filepath, "r")
+ except IOError, 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 <stdio.h>
+ # # 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.clock() - parse_file_start_time
+
+ return (quote_includes, angle_includes, expr_includes, next_includes)
diff --git a/include_server/parse_file_test.py b/include_server/parse_file_test.py
new file mode 100755
index 0000000..b42e7f8
--- /dev/null
+++ b/include_server/parse_file_test.py
@@ -0,0 +1,154 @@
+#! /usr/bin/python2.4
+
+# 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
+ basics.InitializeClientTmp()
+ include_server.write_include_closure_file = True
+ self.include_analyzer = include_analyzer.IncludeAnalyzer()
+
+ 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.assert_(parse_file.DIRECTIVE_RE.match(
+ """ # include <a.c>""").group('angle') == 'a.c')
+ self.assert_(parse_file.DIRECTIVE_RE.match(
+ """ # include mac(a.c, mic)""").group('expr') == 'mac(a.c, mic)')
+ self.assert_(parse_file.DIRECTIVE_RE.match(
+ """ # include "a.c" """).group('quote') == 'a.c')
+ self.assert_(parse_file.DIRECTIVE_RE.match(
+ """ #include "a.c" """).group('quote') == 'a.c')
+ self.assert_(parse_file.DIRECTIVE_RE.match(
+ """ #include"a.c" """).group('quote') == 'a.c')
+
+ self.assertEqual(parse_file.DIRECTIVE_RE.match(
+ """ #define m(a) <a##_post.c> """).group('rhs'),
+ '<a##_post.c>')
+
+ 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)'], []))
+ self.assertEqual(symbol_table.keys(),
+ ['ILLFORMED', 'AS_STRING_INTERNAL',
+ 'TEMPLATE_VARNAME', 'AS_STRING'])
+ [([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()
diff --git a/include_server/run.py b/include_server/run.py
new file mode 100755
index 0000000..db9ad59
--- /dev/null
+++ b/include_server/run.py
@@ -0,0 +1,106 @@
+#! /usr/bin/python2.4
+
+# 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 >> sys.stderr, (
+ "Could not run: '%s' with arguments: %s" %
+ (os.path.join(directory, sys.argv[1]),
+ sys.argv[1:]))
diff --git a/include_server/setup.py b/include_server/setup.py
new file mode 100755
index 0000000..cad0b5c
--- /dev/null
+++ b/include_server/setup.py
@@ -0,0 +1,83 @@
+#! /usr/bin/python2.4
+
+# 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"""
+
+__author__ = "Manos Renieris"
+
+import distutils
+import os
+from distutils.core import setup
+from distutils.extension import Extension
+
+ext = Extension(
+ name="include_server.distcc_pump_c_extensions",
+ sources=[
+ '../distcc/src/clirpc.c',
+ '../distcc/src/clinet.c',
+ '../distcc/src/state.c',
+ '../distcc/src/srvrpc.c',
+ '../distcc/src/pump.c',
+ '../distcc/src/rpc.c',
+ '../distcc/src/io.c',
+ '../distcc/src/include_server_if.c',
+ '../distcc/src/trace.c',
+ '../distcc/src/util.c',
+ '../distcc/src/tempfile.c',
+ '../distcc/src/filename.c',
+ '../distcc/src/bulk.c',
+ '../distcc/src/sendfile.c',
+ '../distcc/src/compress.c',
+ '../distcc/src/argutil.c',
+ '../distcc/src/cleanup.c',
+ '../distcc/src/emaillog.c',
+ '../distcc/src/timeval.c',
+ '../distcc/src/netutil.c',
+ '../distcc/lzo/minilzo.c',
+ 'c_extensions/distcc_pump_c_extensions_module.c',
+ ],
+ include_dirs = ["../distcc/src",
+ "../distcc/lzo",
+ os.path.join(os.getenv("BUILDDIR") or "",
+ "../distcc/src"),
+ os.path.join(os.getenv("BUILDDIR") or "",
+ "../../distcc/src"),
+ ],
+ define_macros = [('_GNU_SOURCE', 1)],
+ library_dirs = [],
+ libraries = [],
+ runtime_library_dirs = [],
+ extra_objects = [],
+ extra_compile_args = ['-Wall', '-Wextra', '-Werror'],
+ extra_link_args = ['-Wall', '-Wextra', '-Werror'],
+)
+
+args = {
+ 'name': "include_server",
+ 'package_dir': {'include_server':'.'},
+ 'version': '1.00',
+ 'description': "Include server for distcc-pump",
+ 'author': "Nils Klarlund",
+ 'author_email': "opensource@google.com",
+ 'url': 'http://code.google.com/p/distcc-pump',
+ 'long_description': """The include server is part of distcc-pump.""",
+ 'packages': ["include_server"],
+ 'ext_modules': [ext],
+}
+
+setup(**args)
diff --git a/include_server/statistics.py b/include_server/statistics.py
new file mode 100755
index 0000000..2dc002a
--- /dev/null
+++ b/include_server/statistics.py
@@ -0,0 +1,121 @@
+#! /usr/bin/python2.4
+#
+# 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.clock()
+
+
+def EndTiming():
+ """Mark the end of an include closure calculation."""
+ global translation_unit_time, min_time, max_time, total_time
+ translation_unit_time = time.clock() - 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
diff --git a/include_server/test_data/abc_post.c b/include_server/test_data/abc_post.c
new file mode 100755
index 0000000..5934e6c
--- /dev/null
+++ b/include_server/test_data/abc_post.c
@@ -0,0 +1 @@
+/* Used by computed_includes.c */
diff --git a/include_server/test_data/abc_pre.c b/include_server/test_data/abc_pre.c
new file mode 100755
index 0000000..c9e98a6
--- /dev/null
+++ b/include_server/test_data/abc_pre.c
@@ -0,0 +1 @@
+/* Used by computed_includes.c */
diff --git a/include_server/test_data/computed_includes.c b/include_server/test_data/computed_includes.c
new file mode 100755
index 0000000..11b18f5
--- /dev/null
+++ b/include_server/test_data/computed_includes.c
@@ -0,0 +1,10 @@
+#define A "p1.h"
+#include A
+
+#ifdef C
+ #define m(a) <a##_pre.c>
+#else
+ #define m(a) <a##_post.c>
+#endif
+#include m(abc) // <abc_post.c>
+
diff --git a/include_server/test_data/contains_abs_include.c b/include_server/test_data/contains_abs_include.c
new file mode 100644
index 0000000..a442e31
--- /dev/null
+++ b/include_server/test_data/contains_abs_include.c
@@ -0,0 +1 @@
+#include "/love/of/my/life"
diff --git a/include_server/test_data/dbar/dbar1/bar.h b/include_server/test_data/dbar/dbar1/bar.h
new file mode 100644
index 0000000..91bb28c
--- /dev/null
+++ b/include_server/test_data/dbar/dbar1/bar.h
@@ -0,0 +1 @@
+#define dbar_dbar1_bar_h
diff --git a/include_server/test_data/dbar/foo.h b/include_server/test_data/dbar/foo.h
new file mode 100755
index 0000000..692ba26
--- /dev/null
+++ b/include_server/test_data/dbar/foo.h
@@ -0,0 +1 @@
+#include "foo2.h"
diff --git a/include_server/test_data/dfoo/foo.h b/include_server/test_data/dfoo/foo.h
new file mode 100755
index 0000000..018d262
--- /dev/null
+++ b/include_server/test_data/dfoo/foo.h
@@ -0,0 +1,2 @@
+#include "foo2.h"
+#include "../dbar/dbar1/bar.h"
diff --git a/include_server/test_data/dfoo/foo2.h b/include_server/test_data/dfoo/foo2.h
new file mode 100644
index 0000000..9db0ee1
--- /dev/null
+++ b/include_server/test_data/dfoo/foo2.h
@@ -0,0 +1,3 @@
+#define dfoo_foo2_h
+// The include below is not valid syntax and should be ignored.
+#include ../dbar/foo.h
diff --git a/include_server/test_data/dfoo/i_am_perhaps_a_directory.h b/include_server/test_data/dfoo/i_am_perhaps_a_directory.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include_server/test_data/dfoo/i_am_perhaps_a_directory.h
diff --git a/include_server/test_data/dfoo/include_dotdot_foo b/include_server/test_data/dfoo/include_dotdot_foo
new file mode 100644
index 0000000..ec77c1d
--- /dev/null
+++ b/include_server/test_data/dfoo/include_dotdot_foo
@@ -0,0 +1 @@
+#include "../foo"
diff --git a/include_server/test_data/dfoo/include_next_foo.h b/include_server/test_data/dfoo/include_next_foo.h
new file mode 100755
index 0000000..caf8d79
--- /dev/null
+++ b/include_server/test_data/dfoo/include_next_foo.h
@@ -0,0 +1 @@
+#include_next <foo.h>
diff --git a/include_server/test_data/dfoo/stat_triggers.h b/include_server/test_data/dfoo/stat_triggers.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include_server/test_data/dfoo/stat_triggers.h
diff --git a/include_server/test_data/distcc/README b/include_server/test_data/distcc/README
new file mode 100644
index 0000000..5474801
--- /dev/null
+++ b/include_server/test_data/distcc/README
@@ -0,0 +1 @@
+This is just part of the distcc code, used for testing.
diff --git a/include_server/test_data/distcc/src/bulk.h b/include_server/test_data/distcc/src/bulk.h
new file mode 100644
index 0000000..7f37109
--- /dev/null
+++ b/include_server/test_data/distcc/src/bulk.h
@@ -0,0 +1,51 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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);
+
diff --git a/include_server/test_data/distcc/src/compile.h b/include_server/test_data/distcc/src/compile.h
new file mode 100644
index 0000000..6876bab
--- /dev/null
+++ b/include_server/test_data/distcc/src/compile.h
@@ -0,0 +1,38 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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);
diff --git a/include_server/test_data/distcc/src/config.h b/include_server/test_data/distcc/src/config.h
new file mode 100644
index 0000000..975565e
--- /dev/null
+++ b/include_server/test_data/distcc/src/config.h
@@ -0,0 +1,256 @@
+/* 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 <alloca.h> header file. */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if you have the <arpa/nameser.h> 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 <ctype.h> 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 <float.h> 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 <inttypes.h> 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 <mcheck.h> header file. */
+#define HAVE_MCHECK_H 1
+
+/* Define to 1 if you have the <memory.h> 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 <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <resolv.h> 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 <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> 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 <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> 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 <sys/loadavg.h> header file. */
+/* #undef HAVE_SYS_LOADAVG_H */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/sendfile.h> header file. */
+#define HAVE_SYS_SENDFILE_H 1
+
+/* Define to 1 if you have the <sys/signal.h> header file. */
+#define HAVE_SYS_SIGNAL_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> 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 */
diff --git a/include_server/test_data/distcc/src/distcc.c b/include_server/test_data/distcc/src/distcc.c
new file mode 100644
index 0000000..2bf4b52
--- /dev/null
+++ b/include_server/test_data/distcc/src/distcc.c
@@ -0,0 +1,221 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+
+#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);
+}
diff --git a/include_server/test_data/distcc/src/distcc.h b/include_server/test_data/distcc/src/distcc.h
new file mode 100644
index 0000000..c0686a7
--- /dev/null
+++ b/include_server/test_data/distcc/src/distcc.h
@@ -0,0 +1,336 @@
+/* -*- 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 <sys/types.h>
+
+
+#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 {
+ /* wierd values to catch errors */
+ DCC_COMPRESS_NONE = 69,
+ DCC_COMPRESS_LZO1X
+};
+
+enum dcc_cpp_where {
+ /* wierd 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
diff --git a/include_server/test_data/distcc/src/emaillog.h b/include_server/test_data/distcc/src/emaillog.h
new file mode 100644
index 0000000..3b1c33a
--- /dev/null
+++ b/include_server/test_data/distcc/src/emaillog.h
@@ -0,0 +1,10 @@
+#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 */
diff --git a/include_server/test_data/distcc/src/exitcode.h b/include_server/test_data/distcc/src/exitcode.h
new file mode 100644
index 0000000..29a595a
--- /dev/null
+++ b/include_server/test_data/distcc/src/exitcode.h
@@ -0,0 +1,61 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 */
diff --git a/include_server/test_data/distcc/src/hosts.h b/include_server/test_data/distcc/src/hosts.h
new file mode 100644
index 0000000..674ac85
--- /dev/null
+++ b/include_server/test_data/distcc/src/hosts.h
@@ -0,0 +1,87 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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);
+
+
diff --git a/include_server/test_data/distcc/src/implicit.h b/include_server/test_data/distcc/src/implicit.h
new file mode 100644
index 0000000..371657d
--- /dev/null
+++ b/include_server/test_data/distcc/src/implicit.h
@@ -0,0 +1,25 @@
+/* -*- 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 <mbp@samba.org>
+ *
+ * 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 ***);
+
diff --git a/include_server/test_data/distcc/src/include_me.h b/include_server/test_data/distcc/src/include_me.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include_server/test_data/distcc/src/include_me.h
diff --git a/include_server/test_data/distcc/src/state.h b/include_server/test_data/distcc/src/state.h
new file mode 100644
index 0000000..63486fe
--- /dev/null
+++ b/include_server/test_data/distcc/src/state.h
@@ -0,0 +1,91 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 */
diff --git a/include_server/test_data/distcc/src/trace.h b/include_server/test_data/distcc/src/trace.h
new file mode 100644
index 0000000..0d99e0f
--- /dev/null
+++ b/include_server/test_data/distcc/src/trace.h
@@ -0,0 +1,230 @@
+/*= -*- 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 <stdarg.h>
+
+/* 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 suport. */
+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);
diff --git a/include_server/test_data/distcc/src/util.h b/include_server/test_data/distcc/src/util.h
new file mode 100644
index 0000000..e2aefed
--- /dev/null
+++ b/include_server/test_data/distcc/src/util.h
@@ -0,0 +1,55 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil -*-
+ *
+ * distcc -- A simple distributed compiler system
+ *
+ * Copyright (C) 2002, 2003 by Martin Pool <mbp@samba.org>
+ *
+ * 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 <setjmp.h>
+
+/* 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);
diff --git a/include_server/test_data/func_macro.c b/include_server/test_data/func_macro.c
new file mode 100644
index 0000000..9eef80d
--- /dev/null
+++ b/include_server/test_data/func_macro.c
@@ -0,0 +1 @@
+#include FINCLUDE(foo.h)
diff --git a/include_server/test_data/gws-main.o.cmd b/include_server/test_data/gws-main.o.cmd
new file mode 100644
index 0000000..0b0cc28
--- /dev/null
+++ b/include_server/test_data/gws-main.o.cmd
@@ -0,0 +1 @@
+/usr/crosstool/v8/gcc-4.1.0-glibc-2.2.2/blah/gcc -Wall -Werror -Wwrite-strings -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 -Wno-sign-compare -Wno-char-subscripts -DXP_UNIX -D_REENTRANT -DHAS_vsnprintf -DPOSIX_MALLOC_THRESHOLD=10 -DMAX_DUPLENGTH=100000 -DSUPPORT_UTF8 -DSUPPORT_UCP -DHAVE_OPENSSL -D_REENTRANT -DHASH_NAMESPACE=__gnu_cxx -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/musicsearch/frontend -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/musicsearch/frontend -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/musicsearch/onebox -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/musicsearch/onebox -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/web/manybox -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/web/manybox -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/web/onebox -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/web/onebox -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/freshness/queryclassifier/public/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/freshness/queryclassifier/public/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/blogsearch/parsers/feedparser/protos -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/blogsearch/parsers/feedparser/protos -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/extern_js -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/extern_js -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/images -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/images -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/one_google -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/one_google -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/web -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/web -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/webserver -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/webserver -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/wireless -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates/wireless -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/image/daily/mustang/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/image/daily/mustang/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/extractor/client/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/extractor/client/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/extractor/server/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/extractor/server/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/repos_www/ftb/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/repos_www/ftb/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox/quicklinks/public/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox/quicklinks/public/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/search/learning/booster -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/search/learning/booster -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ratings/reviews/mustang/servlets -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ratings/reviews/mustang/servlets -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/superroot/corpusroot/web/extras -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/superroot/corpusroot/web/extras -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/tv/showings/frontend/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/tv/showings/frontend/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/index/personalizedsearch/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/index/personalizedsearch/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/stats/relatedvideos/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/stats/relatedvideos/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/weboftrust/prose/data_analysis/video -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/weboftrust/prose/data_analysis/video -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/wireless/sms/frontend/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/wireless/sms/frontend/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/adsearch/servlets -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/adsearch/servlets -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/experiments/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/experiments/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/messenger/adsnapshots -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/messenger/adsnapshots -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/messenger/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/messenger/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/proto/creatives -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/proto/creatives -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/chubby/lib/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/chubby/lib/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/chubby/svelte/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/chubby/svelte/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/classifier/phil/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/classifier/phil/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/commerce/shoppinglist/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/commerce/shoppinglist/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/community/introductions/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/community/introductions/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/contentads/cat2/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/contentads/cat2/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/crawler/analysis/javascript -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/crawler/analysis/javascript -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/crawler/sitemaps/common -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/crawler/sitemaps/common -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/crawler/sitemaps/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/crawler/sitemaps/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/enterprise/onebox/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/enterprise/onebox/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/enterprise/superroot/ent_search_params -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/enterprise/superroot/ent_search_params -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/file/gfs/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/file/gfs/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googlebase/mustang/protos -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googlebase/mustang/protos -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googledata/html/templates -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/i18n/segmenter/common -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/i18n/segmenter/common -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/image/mustang/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/image/mustang/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/image/search/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/image/search/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/learning/rephil/api -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/learning/rephil/api -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/frontend/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/frontend/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/geomap_server/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/geomap_server/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/mustang/servlet -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/mustang/servlet -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/oblocalsearch/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/oblocalsearch/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/waldo/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/waldo/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/waldo/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/waldo/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/wireless/mobilegw -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/wireless/mobilegw -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/maps/soprano/client -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/maps/soprano/client -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/aggregation/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/aggregation/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/repos_www/navboost -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/repos_www/navboost -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/servlets/commerce -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/servlets/commerce -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/servlets/mobile -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/servlets/mobile -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/servlets/querycount -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/servlets/querycount -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/servlets/video -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/servlets/video -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/proto/xml2proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/proto/xml2proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/news/frontend/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/news/frontend/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/news/personalization/nps -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/news/personalization/nps -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ocean/data/docinfo -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ocean/data/docinfo -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ocean/metadata/ids -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ocean/metadata/ids -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox/scholar/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox/scholar/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox/showtimes/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox/showtimes/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox/weather/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox/weather/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/persist/framework/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/persist/framework/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/gws_ui/profiles -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/gws_ui/profiles -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/recommend/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/recommend/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/recommend/util -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/recommend/util -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/zipit/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/zipit/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/zipit/st -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/zipit/st -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/chameleon/interface -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/chameleon/interface -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/labels/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/labels/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/local/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/local/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/manybox/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/manybox/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/manybox/video -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/manybox/video -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/prose/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/prose/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/sitemap/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/sitemap/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ratings/mustang/servlets -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ratings/mustang/servlets -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ratings/reviews/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ratings/reviews/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ratings/reviews/movies -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ratings/reviews/movies -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/repository/docchart/extraction -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/repository/docchart/extraction -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/universal/naming/constants -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/universal/naming/constants -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/universal/naming/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/universal/naming/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/util/encryption/docid -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/util/encryption/docid -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/cdb/common -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/cdb/common -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/index/builder -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/index/builder -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/onebox/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/onebox/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/weboftrust/prose/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/weboftrust/prose/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/frontend/modules -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/frontend/modules -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/util/feature_tabs -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/util/feature_tabs -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/util/match_criteria -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/util/match_criteria -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/util/one_google -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/util/one_google -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/util/url_factory -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/util/url_factory -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/wireless/mmp/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/wireless/mmp/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/wireless/mobile_restrict/indexer -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/wireless/mobile_restrict/indexer -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/wireless/msisdndictionary/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/wireless/msisdndictionary/proto -iquote third_party/Inso/common/unix -Ithird_party/Inso/common/unix -iquote third_party/openssl/gcc-3.4-glibc-2.2.2-piii-linux-dbg/include -Ithird_party/openssl/gcc-3.4-glibc-2.2.2-piii-linux-dbg/include -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/adsearch -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/adsearch -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/clickencoding -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/clickencoding -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/demographics -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/demographics -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/events -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/events -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/experiments -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/experiments -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/phil -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/phil -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/promos -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/promos -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/snapshot -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/snapshot -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/strategy -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/strategy -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/supermessenger -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ads/supermessenger -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/attributesearch/gwsbackend -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/attributesearch/gwsbackend -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/blog/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/blog/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/blogsearch/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/blogsearch/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/borg/borgletlib -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/borg/borgletlib -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/cacheserving/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/cacheserving/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/caribou/ads -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/caribou/ads -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/commerce/offer -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/commerce/offer -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/commerce/onebox -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/commerce/onebox -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/contentads/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/contentads/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/contentads/vertical -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/contentads/vertical -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/coupons/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/coupons/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/daffie/annotations -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/daffie/annotations -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/daffie/annotations2 -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/daffie/annotations2 -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/daffie/metadata -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/daffie/metadata -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/daffie/search -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/daffie/search -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/directory/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/directory/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/docserving/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/docserving/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/file/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/file/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/file/fileset -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/file/fileset -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/file/logging -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/file/logging -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/file/sstablefile -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/file/sstablefile -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/finance/onebox -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/finance/onebox -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/finance/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/finance/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/finance/quoteserver -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/finance/quoteserver -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/froogle/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/froogle/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/froogle/currency -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/froogle/currency -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gaia/data -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gaia/data -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gaia/insclient -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gaia/insclient -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gaia/insfriend -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gaia/insfriend -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/geostore/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/geostore/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/groups2/browsefe -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/groups2/browsefe -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gws/config -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gws/config -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gws/gws -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gws/gws -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gws/onebox -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gws/onebox -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/i18n/langenc_detect -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/i18n/langenc_detect -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/i18n/localization -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/i18n/localization -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/igoogle/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/igoogle/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/indexer/perdocdata -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/indexer/perdocdata -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/indexserving/elephant_info -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/indexserving/elephant_info -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/indexserving/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/indexserving/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/kansas/datatype -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/kansas/datatype -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/kansas/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/kansas/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/kansas/showmyhistory -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/kansas/showmyhistory -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/linkserver/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/linkserver/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/i18n -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/i18n -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/kml -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/localsearch/kml -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/country -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/location/country -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/bigindex -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/bigindex -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/eventid -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/eventid -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/gws -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/gws -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/java -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/java -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/maps -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/maps -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/superroot -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/superroot -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/transit -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/transit -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/zwieback -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs/zwieback -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/maps/wiki_lite -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/maps/wiki_lite -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/music/clients -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/music/clients -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/music/images -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/music/images -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/repos_querycount -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/repos_querycount -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/repos_www -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/repos_www -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/servlets -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang/servlets -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/ecatcher -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/ecatcher -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/httpsconnection -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/httpsconnection -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/sslagent -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/sslagent -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/util -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/net/util -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/nlp/ngrams -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/nlp/ngrams -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ocean/acqbase -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ocean/acqbase -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ocean/mustangproto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/ocean/mustangproto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox/glossary -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox/glossary -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/partnerservices/distributiontracking -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/partnerservices/distributiontracking -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/profiles -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/profiles -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/util -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/personalization/util -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/premiumcontent/common -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/premiumcontent/common -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/premiumcontent/onebox -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/premiumcontent/onebox -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/production/cert_auth -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/production/cert_auth -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/navboost -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/navboost -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/rescoring -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/rescoring -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/twiddler -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/quality/twiddler -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/queryrefinement/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/queryrefinement/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/queryrewrite/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/queryrewrite/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/repository/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/repository/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/repository/docchart -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/repository/docchart -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/reviews/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/reviews/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/science_search/citation -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/science_search/citation -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/security/keymaster -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/security/keymaster -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/security/loas -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/security/loas -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/smartass/logexpansion -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/smartass/logexpansion -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/smartass/predictionmodel -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/smartass/predictionmodel -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/smartass/server -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/smartass/server -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/sortedmap/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/sortedmap/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/spelling/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/spelling/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/sstable/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/sstable/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/stats/io -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/stats/io -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/structuredsearch/client -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/structuredsearch/client -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/superroot/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/superroot/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/third_party/libidn -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/third_party/libidn -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/transportation/dateparser -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/transportation/dateparser -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/transportation/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/transportation/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/universalsearch/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/universalsearch/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/urlscheduler/rpc -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/urlscheduler/rpc -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/util/callback -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/util/callback -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/captioncrunch -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/captioncrunch -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/personalization -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/personalization -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/vcsdb -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/video/vcsdb -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/frontend -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webserver/frontend -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webutil/http -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webutil/http -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webutil/url -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/webutil/url -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/wireless/handset -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/wireless/handset -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/zwieback/proto -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/zwieback/proto -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/includes/third_party/openssl -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/includes/third_party/openssl -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/includes/third_party/stl -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/includes/third_party/stl -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/includes/third_party/zlib -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/includes/third_party/zlib -iquote third_party/SpiderMonkey/src -Ithird_party/SpiderMonkey/src -iquote third_party/htm/include -Ithird_party/htm/include -iquote third_party/icu/current -Ithird_party/icu/current -iquote third_party/pcre/pcre-6.7 -Ithird_party/pcre/pcre-6.7 -iquote third_party/zlib/v1_2_3 -Ithird_party/zlib/v1_2_3 -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/base -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/base -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/borg -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/borg -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/calculator -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/calculator -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/daffie -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/daffie -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googlebot -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/googlebot -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gws -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/gws -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/indexer -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/indexer -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/logs -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/mustang -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/onebox -iquote obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/sortedmap -Iobj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/genfiles/sortedmap -iquote . -Wno-non-virtual-dtor -isystem obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/includes/third_party/stl/third_party/stl -isystem obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/includes/third_party/stl -Wno-deprecated -Woverloaded-virtual -ftemplate-depth-40 -c gws/gws-main.cc -o obj/gcc-4.1.1-glibc-2.2.2-piii-linux-g0-dbg/bin/gws/gws-main.o
diff --git a/include_server/test_data/i_am_perhaps_a_directory.h/empty_file b/include_server/test_data/i_am_perhaps_a_directory.h/empty_file
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include_server/test_data/i_am_perhaps_a_directory.h/empty_file
diff --git a/include_server/test_data/include_include_next_foo.h b/include_server/test_data/include_include_next_foo.h
new file mode 100755
index 0000000..f7469fe
--- /dev/null
+++ b/include_server/test_data/include_include_next_foo.h
@@ -0,0 +1 @@
+#include "include_next_foo.h"
diff --git a/include_server/test_data/maps/foo.tpl.varnames.h b/include_server/test_data/maps/foo.tpl.varnames.h
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/include_server/test_data/maps/foo.tpl.varnames.h
@@ -0,0 +1 @@
+
diff --git a/include_server/test_data/more_macros.c b/include_server/test_data/more_macros.c
new file mode 100644
index 0000000..28dd506
--- /dev/null
+++ b/include_server/test_data/more_macros.c
@@ -0,0 +1,14 @@
+
+#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)
diff --git a/include_server/test_data/p1.h b/include_server/test_data/p1.h
new file mode 100755
index 0000000..8b13789
--- /dev/null
+++ b/include_server/test_data/p1.h
@@ -0,0 +1 @@
+
diff --git a/include_server/test_data/parse.c b/include_server/test_data/parse.c
new file mode 100644
index 0000000..956d282
--- /dev/null
+++ b/include_server/test_data/parse.c
@@ -0,0 +1,8 @@
+#includenext "incnext.h"
+#include <angle.c>
+#include "quote.c"
+ # include \
+ /* comment */ "quote1\
+.c"
+#include "foo.h" // in dfoo
+
diff --git a/include_server/test_data/stat_triggers.c b/include_server/test_data/stat_triggers.c
new file mode 100644
index 0000000..5c32f98
--- /dev/null
+++ b/include_server/test_data/stat_triggers.c
@@ -0,0 +1 @@
+#include "stat_triggers.h"
diff --git a/include_server/test_data/stat_triggers.h b/include_server/test_data/stat_triggers.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include_server/test_data/stat_triggers.h
diff --git a/include_server/test_data/symlink_farm/abc_post.c b/include_server/test_data/symlink_farm/abc_post.c
new file mode 120000
index 0000000..4fcd3a9
--- /dev/null
+++ b/include_server/test_data/symlink_farm/abc_post.c
@@ -0,0 +1 @@
+../abc_post.c \ No newline at end of file
diff --git a/include_server/test_data/symlink_farm/abc_pre.c b/include_server/test_data/symlink_farm/abc_pre.c
new file mode 120000
index 0000000..4e864a5
--- /dev/null
+++ b/include_server/test_data/symlink_farm/abc_pre.c
@@ -0,0 +1 @@
+../abc_pre.c \ No newline at end of file
diff --git a/include_server/test_data/symlink_farm/computed_includes.c b/include_server/test_data/symlink_farm/computed_includes.c
new file mode 120000
index 0000000..2a694d0
--- /dev/null
+++ b/include_server/test_data/symlink_farm/computed_includes.c
@@ -0,0 +1 @@
+../computed_includes.c \ No newline at end of file
diff --git a/include_server/test_data/symlink_farm/dbar b/include_server/test_data/symlink_farm/dbar
new file mode 120000
index 0000000..a261f21
--- /dev/null
+++ b/include_server/test_data/symlink_farm/dbar
@@ -0,0 +1 @@
+../dbar \ No newline at end of file
diff --git a/include_server/test_data/symlink_farm/dfoo b/include_server/test_data/symlink_farm/dfoo
new file mode 120000
index 0000000..97fa2d0
--- /dev/null
+++ b/include_server/test_data/symlink_farm/dfoo
@@ -0,0 +1 @@
+../dfoo \ No newline at end of file
diff --git a/include_server/test_data/symlink_farm/foo b/include_server/test_data/symlink_farm/foo
new file mode 100644
index 0000000..cd9390c
--- /dev/null
+++ b/include_server/test_data/symlink_farm/foo
@@ -0,0 +1 @@
+#include "sub_farm/link_to_dotdot_dotdot_dfoo_include_dotdot_foo"
diff --git a/include_server/test_data/symlink_farm/p1.h b/include_server/test_data/symlink_farm/p1.h
new file mode 120000
index 0000000..58fa3b8
--- /dev/null
+++ b/include_server/test_data/symlink_farm/p1.h
@@ -0,0 +1 @@
+../p1.h \ No newline at end of file
diff --git a/include_server/test_data/symlink_farm/parse.c b/include_server/test_data/symlink_farm/parse.c
new file mode 120000
index 0000000..cf5775d
--- /dev/null
+++ b/include_server/test_data/symlink_farm/parse.c
@@ -0,0 +1 @@
+../parse.c \ No newline at end of file
diff --git a/include_server/test_data/symlink_farm/sub_farm/link_to_dotdot_dotdot_dfoo_include_dotdot_foo b/include_server/test_data/symlink_farm/sub_farm/link_to_dotdot_dotdot_dfoo_include_dotdot_foo
new file mode 120000
index 0000000..3f08d7c
--- /dev/null
+++ b/include_server/test_data/symlink_farm/sub_farm/link_to_dotdot_dotdot_dfoo_include_dotdot_foo
@@ -0,0 +1 @@
+../../dfoo/include_dotdot_foo \ No newline at end of file
diff --git a/include_server/test_data/symlink_farm/test_directory_probing.c b/include_server/test_data/symlink_farm/test_directory_probing.c
new file mode 120000
index 0000000..0af39d3
--- /dev/null
+++ b/include_server/test_data/symlink_farm/test_directory_probing.c
@@ -0,0 +1 @@
+../test_directory_probing.c \ No newline at end of file
diff --git a/include_server/test_data/symlink_farm/test_include_next b/include_server/test_data/symlink_farm/test_include_next
new file mode 120000
index 0000000..9aa56db
--- /dev/null
+++ b/include_server/test_data/symlink_farm/test_include_next
@@ -0,0 +1 @@
+../test_include_next \ No newline at end of file
diff --git a/include_server/test_data/test_computed_includes/helper.c b/include_server/test_data/test_computed_includes/helper.c
new file mode 100644
index 0000000..02221a6
--- /dev/null
+++ b/include_server/test_data/test_computed_includes/helper.c
@@ -0,0 +1 @@
+#include INCL
diff --git a/include_server/test_data/test_computed_includes/incl.h b/include_server/test_data/test_computed_includes/incl.h
new file mode 100644
index 0000000..1e29313
--- /dev/null
+++ b/include_server/test_data/test_computed_includes/incl.h
@@ -0,0 +1 @@
+#define MSG "hello"
diff --git a/include_server/test_data/test_computed_includes/inclA.h b/include_server/test_data/test_computed_includes/inclA.h
new file mode 100644
index 0000000..43ad022
--- /dev/null
+++ b/include_server/test_data/test_computed_includes/inclA.h
@@ -0,0 +1 @@
+#define MSG "hello A"
diff --git a/include_server/test_data/test_computed_includes/src.c b/include_server/test_data/test_computed_includes/src.c
new file mode 100644
index 0000000..a361343
--- /dev/null
+++ b/include_server/test_data/test_computed_includes/src.c
@@ -0,0 +1,9 @@
+#define INCL "incl.h"
+#include "helper.c"
+
+#include<stdio.h>
+int main() {
+ printf(MSG);
+ printf("\n");
+ return 0;
+}
diff --git a/include_server/test_data/test_computed_includes/srcA.c b/include_server/test_data/test_computed_includes/srcA.c
new file mode 100644
index 0000000..075a898
--- /dev/null
+++ b/include_server/test_data/test_computed_includes/srcA.c
@@ -0,0 +1,9 @@
+#define INCL "inclA.h"
+#include "helper.c"
+#include <stdio.h>
+
+int main() {
+ printf(MSG);
+ printf("\n");
+ return 0;
+}
diff --git a/include_server/test_data/test_directory_probing.c b/include_server/test_data/test_directory_probing.c
new file mode 100644
index 0000000..edadb76
--- /dev/null
+++ b/include_server/test_data/test_directory_probing.c
@@ -0,0 +1,4 @@
+// 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"
diff --git a/include_server/test_data/test_include_next/bar/x.h b/include_server/test_data/test_include_next/bar/x.h
new file mode 100755
index 0000000..8f6876d
--- /dev/null
+++ b/include_server/test_data/test_include_next/bar/x.h
@@ -0,0 +1,3 @@
+Now bar/x.h
+#include_next "x.h"
+
diff --git a/include_server/test_data/test_include_next/bar/y.h b/include_server/test_data/test_include_next/bar/y.h
new file mode 100755
index 0000000..f44afac
--- /dev/null
+++ b/include_server/test_data/test_include_next/bar/y.h
@@ -0,0 +1,3 @@
+Now bar/y.h
+#include_next "y.h"
+
diff --git a/include_server/test_data/test_include_next/baz/start_x.c b/include_server/test_data/test_include_next/baz/start_x.c
new file mode 100755
index 0000000..44a0921
--- /dev/null
+++ b/include_server/test_data/test_include_next/baz/start_x.c
@@ -0,0 +1,2 @@
+Now baz/start_x.h
+#include "x.h"
diff --git a/include_server/test_data/test_include_next/baz/start_y.c b/include_server/test_data/test_include_next/baz/start_y.c
new file mode 100755
index 0000000..1e6a9c8
--- /dev/null
+++ b/include_server/test_data/test_include_next/baz/start_y.c
@@ -0,0 +1,2 @@
+Now baz/start_y.h
+#include "../foo/y.h"
diff --git a/include_server/test_data/test_include_next/baz/x.h b/include_server/test_data/test_include_next/baz/x.h
new file mode 100755
index 0000000..69218e4
--- /dev/null
+++ b/include_server/test_data/test_include_next/baz/x.h
@@ -0,0 +1,3 @@
+Now in baz/x.h
+#include_next "x.h"
+
diff --git a/include_server/test_data/test_include_next/baz/y.h b/include_server/test_data/test_include_next/baz/y.h
new file mode 100755
index 0000000..50ca3e8
--- /dev/null
+++ b/include_server/test_data/test_include_next/baz/y.h
@@ -0,0 +1,6 @@
+Now baz/y.h
+#ifndef baz_y_h
+ #define baz_y_h
+ #include y.h
+#endif
+
diff --git a/include_server/test_data/test_include_next/biz/x.h b/include_server/test_data/test_include_next/biz/x.h
new file mode 100755
index 0000000..fcb7a34
--- /dev/null
+++ b/include_server/test_data/test_include_next/biz/x.h
@@ -0,0 +1 @@
+Now biz/x.h
diff --git a/include_server/test_data/test_include_next/foo/x.h b/include_server/test_data/test_include_next/foo/x.h
new file mode 100755
index 0000000..c9be0ed
--- /dev/null
+++ b/include_server/test_data/test_include_next/foo/x.h
@@ -0,0 +1,2 @@
+Now: foo/x.h
+#include_next "x.h"
diff --git a/include_server/test_data/test_include_next/foo/y.h b/include_server/test_data/test_include_next/foo/y.h
new file mode 100755
index 0000000..965bf4e
--- /dev/null
+++ b/include_server/test_data/test_include_next/foo/y.h
@@ -0,0 +1,2 @@
+Now: foo/y.h
+#include_next "y.h"
diff --git a/pump.in b/pump.in
new file mode 100755
index 0000000..3a4a976
--- /dev/null
+++ b/pump.in
@@ -0,0 +1,444 @@
+#! /bin/bash
+#
+# Copyright 2007 Google Inc. All Rights Reserved.
+#
+# Authors: klarlund@google.com, fergus@google.com
+#
+# 'pump': a script for using distcc-pump with build commands.
+
+# This file is processed by configure,
+# which substitutes in the right value for @PYTHON@.
+PYTHON=@PYTHON@
+
+usage_string=\
+'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_PUMP_LOCATION The location of distcc-pump '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_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
+'
+
+# 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
+ link=$(readlink "$0")
+ linkdir=$(dirname "$link")
+ case $linkdir in
+ /*) echo "$linkdir" ;;
+ *) echo "$(dirname "$0")/$linkdir"
+ esac
+ else
+ dirname "$0"
+ fi
+}
+
+# Variables inherited from the environment of the caller.
+DISTCC_PUMP_LOCATION=${DISTCC_PUMP_LOCATION-$(GetScriptDir "$0")}
+
+# 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_started_successfully=0
+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.
+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() {
+ mktemp $2 /tmp/$1.XXXXXX || \
+ { echo "$program_name: Could not make temp \"$1\"" 1>&2; exit 1; }
+}
+
+CheckUsage() {
+ if [ "$1" = "" -o "$1" = '-h' -o "$1" = '--help' ]; then
+ echo "$usage_string"
+ exit 0
+ 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="../lib/$PYTHON/site-packages/include_server"
+
+ # We use a little heuristic to determine whether this pump script is part of
+ # an installation. Specifically, we check whether we're a bin directory, and
+ # more importantly, we look for the include_server.py script. If we're running
+ # out of the distcc_pump source directory, both conditions below will fail.
+ if [ $(basename $DISTCC_PUMP_LOCATION) = 'bin' ] \
+ && [ -f "$DISTCC_PUMP_LOCATION/$include_server_relative/\
+include_server.py" ]; \
+ then
+ # Running from installed directory.
+ is_in_installation=true
+ else
+ # Running from configured directory, usually the source directory.
+ is_in_installation=""
+ fi
+
+ if [ $is_in_installation ]; then
+ distcc_location="$DISTCC_PUMP_LOCATION"
+ else
+ distcc_location="$DISTCC_PUMP_LOCATION/distcc"
+ fi
+
+ # 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
+}
+
+Announce() {
+ echo "__________Using distcc-pump from $(readlink -f $DISTCC_PUMP_LOCATION)"
+}
+
+# Starts up the include server.
+# Sets $socket, $socket_dir, $include_server_pid, and
+# $include_server_started_successfully.
+# If successful, sets exported variable $INCLUDE_SERVER_PORT
+# to the socket file ($socket), to tell the distcc clients
+# where to find the include server.
+shopt -s extglob # allow +(...) construct below
+StartIncludeServer() {
+ # Locate include server depending on whether in installation.
+ if [ $is_in_installation ]; then
+ local include_server_location="$DISTCC_PUMP_LOCATION/\
+$include_server_relative"
+ local pythonpath=$include_server_location
+ else
+ # When run from the source code directory (assuming that we configured in
+ # the distcc_pump top-level directory) we pick up .py files from the
+ # include_server directory and pick up the .so file from the
+ # include_server/build/libXXX/include_server directory. When configured in a
+ # separate directory, we pick up .py files also from include_server/build.
+ local include_server_location=${DISTCC_PUMP_LOCATION}/include_server
+ # 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_files=$(ls ${DISTCC_PUMP_LOCATION}/include_server/\
+build/lib.*/include_server/distcc_pump_c_extensions.so)
+ if echo $so_files | grep -q ' '; then
+ include_server_started_successfully=0
+ echo \
+ '__________Shared libraries for multiple architectures discovered.'
+ echo \
+ "__________Cannot determine which one to use among: $so_files"
+ echo \
+ '__________Could not start distcc-pump include server'
+ return 0
+ else
+ # There was only one such file.
+ local so_dir=$(dirname $so_files)
+ fi
+ local pythonpath="${DISTCC_PUMP_LOCATION}/include_server:$so_dir"
+ fi
+
+ # Create a temporary directory $socket_dir.
+ socket_dir=$(MakeTmpFile "distcc-pump" -d)
+
+ # 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")
+
+ # 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
+
+ PYTHONOPTIMIZE=${PYTHONOPTIMIZE-1} \
+ PYTHONPATH=$pythonpath \
+ $PYTHON \
+ $include_server_location/include_server.py \
+ --port $socket \
+ --pid_file "$tmp_pid_file" \
+ --email \
+ --email_bound=5 \
+ -d1 \
+ $INCLUDE_SERVER_ARGS
+ )
+
+ include_server_pid=$(cat $tmp_pid_file)
+ rm $tmp_pid_file
+
+ if [ ! -S "$socket" ]; then
+ include_server_started_successfully=0
+ else
+ case $include_server_pid in
+ +([0-9]))
+ # That's what we expect: a number.
+ include_server_started_successfully=1
+ # Tell the distcc clients where to find it.
+ INCLUDE_SERVER_PORT=$socket
+ export INCLUDE_SERVER_PORT
+ ;;
+ *)
+ # This indicates that the socket is not working.
+ include_server_pid=''
+ include_server_started_successfully=0
+ ;;
+ esac
+ fi
+ if [ "$verbose" = 1 ]; then
+ if [ "$include_server_started_successfully" = 1 ]; then
+ echo '__________Started distcc-pump include server'
+ else
+ echo '__________Could not start distcc-pump include server' 1>&2
+ fi
+ fi
+}
+
+ShutDown() {
+ # Always -- at exit -- shut down include_server and remove $socket_dir
+ if [ "$include_server_pid" ] && \
+ ps --pid "$include_server_pid" > /dev/null; then
+ echo '__________Shutting down distcc-pump include server'
+ kill $include_server_pid
+ 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 [ "$socket_dir" ]; then
+ rm -rf "$socket_dir"
+ fi
+ if [ "$tmp_pid_file" ]; then
+ rm -f "$tmp_pid_file"
+ fi
+ if [ "$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() {
+ local available_hosts=$1
+ local lsdistcc=$DISTCC_PUMP_LOCATION/distcc/lsdistcc
+ if [ ! -x $lsdistcc ]; then
+ lsdistcc=$DISTCC_PUMP_LOCATION/lsdistcc
+ if [ ! -x $lsdistcc ]; then
+ echo "$0: error: can't find lsdistcc (looked in $DISTCC_PUMP_LOCATION" \
+ " and $DISTCC_PUMP_LOCATION/distcc)" 1>&2
+ exit 1
+ fi
+ 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 global variables
+# - $include_server_started_successfully and
+# - $available_hosts_file.
+ExportDISTCC_HOSTS() {
+ local opts=''
+ if [ "$include_server_started_successfully" = 1 ]; 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 "$(...)").
+ 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() {
+ if [ "$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")
+ AvailableHosts $available_hosts_file &
+
+ # The include server goes in the foreground so variables can be set.
+ StartIncludeServer
+
+ # Await for AvailableHosts to finish.
+ wait
+ ExportDISTCC_HOSTS $available_hosts_file
+ 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 "/etc/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 \"/etc/distcc/hosts\"." \
+ 1>&2
+ exit 1
+ fi
+ StartIncludeServer
+ fi
+}
+
+# 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 [ "$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
+ trap '' EXIT
+ if [ $include_server_started_successfully = 1 ]; 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
+ # 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 "$@"
diff --git a/run_all_autoconf.sh b/run_all_autoconf.sh
new file mode 100755
index 0000000..bfa352d
--- /dev/null
+++ b/run_all_autoconf.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+
+# Run autoconfig and autoheader in a safe way. Running these commands directly
+# will likely not work because of caching mechanisms: the information in
+# version.sh will not be propagated correctly.
+
+# We need a stamp file to compare version.sh against, see the Makefile.
+AUTOCONF_STAMP=autoconf_stamp
+
+if ! [ $(basename $(pwd)) = "distcc_pump" ]; then
+ echo "Must be in distcc_pump directory" 1>&2;
+ exit 1
+fi
+
+# Now run autoconf and autoheader through autoreconf -f. This way autoconf is
+# apparently not getting confused by old configure files and m4 caches.
+echo "Now running autoreconf in order to run autoconf and autoheader."
+autoreconf -f -v && touch $AUTOCONF_STAMP
+
+echo "System must be configured. Run: ./configure."
diff --git a/version.sh b/version.sh
new file mode 100644
index 0000000..a9a3498
--- /dev/null
+++ b/version.sh
@@ -0,0 +1,10 @@
+# To be source'ed from run_all_autoconf.sh and build-distcc.sh.
+
+DISTCC_VERSION=2.18.3
+PUMP_SUBVERSION=17gg1.pump20
+
+DISTCC_PUMP_VERSION=$DISTCC_VERSION-$PUMP_SUBVERSION
+PACKAGE_NAME='distcc'
+
+
+