distcc-3.1/0000750000175000017500000000000011216333443011635 5ustar wolffwolffdistcc-3.1/source/0000755000175000017500000000000011216333443013142 5ustar wolffwolffdistcc-3.1/source/INSTALL0000640000175000017500000002432411115326647014202 0ustar wolffwolffInstallation instructions for distcc -*- indented-text -*- distcc is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. distcc comes with ABSOLUTELY NO WARRANTY, for details see the licence. Please report any problems to distcc@lists.samba.com. QUICK SUMMARY ============= 1. Build and install ./autogen.sh # If "configure" does not already exist. ./configure make make check # Optional! Should have python >= 2.4 installed. make install # You may need to use "sudo" for this command. make installcheck # Optional! Should have python >= 2.4 installed. Repeat installation for each server machine. 2. Run distccd on each server machine, with --allow options to limit access. 3. On your client machine, set DISTCC_POTENTIAL_HOSTS to the list of distcc server machines: export DISTCC_POTENTIAL_HOSTS='localhost red green blue' 4. Build your software using distcc: cd ~/my_sources/my_project pump make -j40 CC="distcc gcc" DETAILED INSTRUCTIONS ===================== Prerequisites ------------- To build distcc you need GNU Make A C compiler It is also highly desireable to have Python >=2.4 To use "pump" mode, or to run the full test suite with "make check", or to run the benchmarks. You can optionally have Python >=2.2 To run a partial test suite with "make check" (it leaves out the pump-mode functionality, which requires Python 2.4). libpopt If this is not found on your system, the popt version that is part of the distcc distribution will be statically linked in. linuxdoc SGML tools To rebuild the documentation from its SGML source. autoconf >=2.5 To rebuild the configure scripts if you edit configure.ac. To build the optional GNOME monitor (--with-gnome), you need the GNOME2 development libraries, and in particular gtk+ >=2.0 libgnome >=2.0 libgnomeui >= 2.0 libglade >= 2.0 libpango The monitor can also be built without GNOME desktop integration (--with-gtk), in which case you need only gtk+ >=2.0 libglade >= 2.0 Preliminaries ------------- distcc can be installed and used without requiring root access. Adjust directories appropriately when installing. Configuring distcc ------------------ Note that the default GNU "sysconfdir" is /usr/local/etc. You may want to change this to /etc. $ ./configure --sysconfdir=/etc You can set an installation prefix if you want to put distcc in /opt: $ ./configure --prefix=/opt/distcc/ distcc needs to be installed on all client and server machines. If you would like a graphical client-side monitor to show running jobs, you can choose either --with-gnome or --with-gtk. If you would like to try running distcc over IPv6, use --enable-rfc2553. You must have a reasonably recent operating system or this is likely to fail in complex ways. Building distcc --------------- The simple way to build distcc is to just do ./autogen.sh # if "configure" does not already exist in this directory ./configure && make but the recommended way is to build in a different directory tree than the source tree: mkdir obj cd obj ../autogen.sh ../configure && make You can optionally run "make check" afterwards to verify that everything built OK. Installing distcc ----------------- If your system supports RPM packages, you can build RPMs with "make rpm" and then install them with "rpm -i packaging/*.rpm". If your system supports Debian packages, you can build them with "make deb" and then install them with "make install-deb". Otherwise, you can use the regular "make install". But it is preferable to install via an RPM or Debian package if possible, because those methods will do a bit more of the setup work. You can optionally run "make installcheck" afterwards to verify that was installed OK. This works regardless of which installation method you used. Starting the daemon ------------------- This stage is only required if you want to run distcc over TCP sockets, rather than SSH connections. TCP is faster but less secure and should only be used on trusted networks. In TCP mode distccd can run either from inetd or as a standalone daemon. Running standalone is recommended. If you installed via the debian or RPM package, then the daemon will be installed as a service, running as a standalone daemon, and it should get started up automatically, so you can skip the rest of this section "Starting the daemon". The rest of this section only applies if you installed via "make install". To run standalone, run a command like this, either from the command line or from the system startup scripts. distccd --daemon If the daemon is started from an rc script, then make sure that it sees a PATH setting which can find any compilers installed in nonstandard directories. You should create a "distcc" account on server machines so that distcc can run with minimal privilege. It is not necessary for this account to own any files or have a home directory. If this account doesn't exist, distccd uses the "nobody" account. By default distccd writes messages to the "daemon" syslog, which typically ends up in /var/log/messages or /var/log/daemon. You can set IP-based access control using the --allow and --listen options, in either inetd or daemon mode: distccd --allow 10.4.20.0/24 distccd does not need to run on machines that will only act as clients. See the manual for more information. Editing the daemon configuration files -------------------------------------- If you installed via the RPM or Debian package, then you will have an /etc/init.d/distcc script which reads several configuration files to decide if and how to invoke distccd. These configuration files are /etc/default/distcc /etc/distcc/clients.allow /etc/distcc/commands.allow.sh If you installed via the RPM or Debian package, then you should edit those configuration files, especially the clients.allow file. If you installed via "make install", then those configuration files will be installed, but they will NOT be used, unless you manually install the init.d/distcc script from packaging/RedHat/init.d/distcc and tailor it for your system. If you start distccd manually, rather than via the init.d/distcc script, then distccd won't use any configuration files; the allowed client IP addresses will be determined by the --allow options that you pass to distccd and the allowed commands will be determined by the DISTCC_CMDLIST environment variable; see the distccd(1) man page for details. See also the doc/example directory and its README file, which has examples of the configuration files that you need. Setting up the host list ------------------------ On the client machines, store a list of servers names in ~/.distcc/hosts or /etc/hosts, or in the DISTCC_HOSTS environment variable. If you're using TCP connections, it should look like this: localhost red green blue For SSH connections localhost @red @green @blue The hosts should be listed in descending order of speed. localhost should normally be first, unless it is signficantly slower than another machine. If you many hosts (say ten or more), it's probably better to leave localhost out of the list. The host list also needs ",cpp,lzo" after each host if you're using pump mode - see README.pump for details. Another alternative if you're using pump mode is to set the DISTCC_POTENTIAL_HOSTS environment variable; in that case, the pump script will use "lsdistcc" to set DISTCC_HOSTS, automatically eliminating hosts that are down or inaccessible or that don't have distccd running. See the distcc(1) manual and the pump(1) manual for more information. Using distcc ------------ Distcc will only improve performance if your build is parallelized. So you need to use the "-j" option to make, or its equivalent with your build tools. If your build contains too many sequential steps, e.g. if your Makefile contains all: for subdir in $(SUBDIRS); do make -C $$subdir all; done then you may need to rewrite your Makefile to get better parallelism. This is especially important if you're using pump mode. Using pump mode --------------- To use pump mode, invoke your build command via the "pump" script, e.g. export DISTCC_POTENTIAL_HOSTS="localhost red blue green" cd ~/my_sources/my_project pump make -j40 CC="distcc gcc" my_target Pump mode assumes that source files are not modified during the build. If this assumption does not hold, you should not use pump mode. You can disable pump mode by not using the pump script. In that case, you need to set DISTCC_HOSTS rather than DISTCC_POTENTIAL_HOSTS. export DISTCC_HOSTS="localhost red blue green" cd ~/my_sources/my_project make -j40 CC="distcc gcc" my_target Creating the masquerade directories ----------------------------------- The easiest way to use distcc is in "masquerade" mode, where it is installed on the PATH to "catch" calls to the compiler and redirect them over the network. Other options are discussed in the manual. For instance, you could create the directory named /usr/lib/distcc and populate it with links. # mkdir /usr/lib/distcc # cd /usr/lib/distcc # ln -s /usr/bin/distcc gcc # ln -s /usr/bin/distcc cc # ln -s /usr/bin/distcc g++ # ln -s /usr/bin/distcc c++ If you installed via the RedHat or Debian package, then this masquerade directory is already set up automatically in /usr/lib/distcc. Do this for all compiler names that you use. Then, to use distcc, a user just needs to put the directory /usr/lib/distcc/bin early in the PATH and distcc will handle the rest. export PATH=/usr/lib/distcc/bin:$PATH Use with ccache --------------- The best way to use is to set up a similar masquerade directory for ccache and put it on the PATH before distcc. NOTE: This use of ccache is incompatible with use of distcc's "pump" mode. (If you're using "pump" mode, it might be possible to use ccache on the distcc server machines. But we haven't tried that setup.) Complete the survey ------------------- Once you have distcc working for your own application, please complete and mail in the survey in survey.txt. distcc-3.1/source/TODO0000640000175000017500000011157411115326647013645 0ustar wolffwolffTODO list for distcc --> See also TODO and FIXME comments in source files and doc/todo/ should rewrite non-ELF, non-DWARF2 object files The existing include-server code will rewrite ELF files to refer to source-file names (in the DWARF2 sections) as they would appear on the client machine, rather than as they appear when rewritten on the server machine. We should enhance that functionality to work with other object formats, such as Mach-O (used by OS X). should probably actually check the number of CPUs for use on localhost failing to resolve a host should be a soft failure State files depend on host byte order and break when DISTCC_DIR is shared between 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. Masquerade It might be nice to automatically create the directory and symlinks. However we don't know what compiler names they'll want to hook... Probably the best that we can do is provide clear instructions for users or package distributors to set this up. Packaging What about an apt repository? Statistics Accumulate statistics on how many jobs are built on various machines. Want to be able to do something like "watch ccache -s". Perhaps just dump files into a status directory where they can be examined? Ignore (or delete) files over ~60s old. This avoids problems with files hanging around from interrupted compilations. refactor name handling Common function that looks at file extensions and returns information about them - what is the preprocessed form of this extension? - does this need preprocessing? - is this a source file? check that EINTR is handled in all cases check that all lengths are unsigned 32-bit I think this is done, but it's worth checking a bit more. in plain (non-pump) mode, abort when cpp fails The same SIGCHLD handling approach used to feed the compiler from a fifo might be used to abort early if the preprocessor fails. This will happen reasonably often, whenever there is a problem with an include, ifdef, comment, etc. It might save waiting for a long connection to complete. One complication is that we know the compiler ought to consume all its input but we don't know when cpp ought to finish. So the sigchld handler will have to check if it failed or not. If it failed, then abort compilation. If it did not fail, then keep going with the connection or whatever. This is probably not worthwhile at the moment because connections generally seem faster than waiting for cpp. feed compiler from fifo Probably quite desirable, because it allows the compiler to start work sooner. This was originally removed because of some hitches to do with process termination. I think it can be put back in reliably, but only if this is fixed. Perhaps we need to write to the compiler in nonblocking mode? Perhaps it would be better to talk to both the compiler and network in nonblocking mode? It is pretty desirable to pull information from the network as soon as possible, so that the TCP windows and buffers can open right up. Check CVS to remember what originally went wrong here. Events that we need to consider: Client forks Compiler opens pipe Client exits Server opens pipe There are a few possibilities here: Client opens fifo, reads all input, and exits. The normal success case. Client never reads from fifo and just exits. Would happen if the compiler command line was wrong. Client reads from fifo but not the whole thing, and then exits. Opening the fifo is a synchronization point: in blocking mode neither the compiler or server can proceed past here until the other one opens it. If the compiler exits, then the server ought to be broken out of it by a SIGCHLD. But there is a race condition here: the SIGCHLD might happen just before the open() call. We need to either jump out of the signal handler and abort the compilation, or use a non-blocking open and a dummy pipe to break the select(). If we jump out with longjmp then this makes the code a bit convoluted. Alternatively the signal handler could just do a nonblocking open on the pipe, which would allow the open to complete, if it had not already. This was last supported in 0.12. That version doesn't handle the compiler exiting without opening the pipe though. streaming input output We could start sending the preprocessed source out before it is complete. This would require a protocol that allows us to send little chunks from various streams, followed by an EOF. This can certainly be done -- fsh and ssh do it. However, particularly if we want to allow for streaming more than one thing at a time, then getting all the timing conditions right to avoid deadlock caused by bubbles of data in TCP pipes. rsync has had trouble with this. It's even more hairy when running over ssh. So on the whole I am very skeptical about doing this. Even when refactored into a general 'distexec', this is more about batch than interactive processing. assemble on client May be useful if there is a cross compiler but no cross assembler, as is supposed to be the case for PPC AIX. See thread by Stuart D Gathman. Would also allow piping output back to client, if the protocol was changed to support that. web site http://user-mode-linux.sourceforge.net/thanks.html sendfile perhaps try sendfile to receive as well, if this works on any platforms. static linking cachegrind shows that a large fraction of client runtime is spent in the dynamic linker, which is kind of a waste. In principle using dietlibc might reduce the fixed overhead of the client. However, the nsswitch functions are always dynamically linked: even if we try to produce a static client it will include dlopen and eventually indirectly get libc, so it's probably not practical. testing How to use Debian's make-kpkg with distcc? Does it work with the masquerade feature? http://moin.conectiva.com.br/files/AptRpm/attachments/apt-0.5.5cnc4.1.tar.bz2 coverage Try running with gcov. May require all tests to be run from the same directory (no chdir) so that the .da files can accumulate properly. slow networks Use Linux Traffic Control to simulate compilation across a slow network. scheduling onto localhost Where does local execution fit into the picture? Perhaps we could talk to a daemon on localhost to coordinate with other processes, though that's a bit yucky. However the client should use the same information and shared state as the daemon when deciding whether it can take on another job. At the moment we just use a fixed number of slots, by default 4, and this seems to work adequately. make "localhost" less magic Recognizing this magic string and treating it differently from 127.0.0.1 or the canonical name of the host is perhaps a bit strange. People do seem to get it wrong. I can't think of a better simple solution though. blacklist/lock by IP, not by name Means we need reliable addr-to-string for IPv4 and IPv6. Any downside to this? Would fix Zygo's open Debian bug. DNS multi-A-records build.foo.com expands to a list of all IP addresses for building. Need to choose an appropriate target that has the right compilers. Probably not a good idea. If we go to using DNS roundrobin records, or if people have the same HOSTS set on different machines, then we can't rely on the ordering of hosts. Perhaps we should always shuffle them? ssh is an interesting case because we probably want to open the connection using the hostname, so that the ssh config's "Host" sections can have the proper effect. Sometimes people use multi A records for machines with several routeable interfaces. In that case it would be bad to assume the machine can run multiple jobs, and it is better to let the resolver work out which address to use. DNS SRV records Can only be updated by zone administrator -- unless you have dynamic DNS, which is quite possible. better scheduler What's the best way to schedule jobs? Multiprocessor machines present a considerable complication, because we ought to schedule to them even if they're already busy. We don't know how many more jobs will arrive in the future. This might be the first of many, or it might be the last, or all jobs might be sequenced in this stage of compilation. Generic OS scheduling theory suggests (??) that we should schedule a job in the place where it is likely to complete fastest. In other words, we should put it on the fastest CPU that's not currently busy. We can't control the overall amount of concurrency -- that's down to Make. I think all we really want is to keep roughly the same number of jobs running on each machine. I would rather not require all clients to know the capabilities of the machines they might like to use, but it's probably acceptable. We could also take the current load of the CPUs into account, but I'm not sure if we could get the information back fast enough for it to make a difference. Note that loadavg on Linux includes processes stuck in D state, which are not necessarily using any CPU. We want to approximate all tasks on the network being in a single queue, from which the servers invite tasks as cycles become available. However, we also want to preserve the classic-TCP model of clients opening connections to servers, because this makes the security model straightforward, works over plain TCP, and also can work over SSH. http://www.cs.panam.edu/~meng/Course/CS6354/Notes/meng/master/node4.html Research this more. We "commit" to using a particular server at the last possible moment: when we start sending a job to it. This is almost certainly preferable to queueing up on a particular server when we don't know that it will be the next one free. One analogy for this is patients waiting in a medical center to see one of several doctors. They all wait in a common waiting room (the queue) until a doctor (server) is free. Normally the doctors would come into the waiting room to say "who's next?", but the constraint of running over TCP means that in our case the doctors cannot initiate the transaction. One approach would be to have a central controller (ie receptionist), who knows which clients are waiting and which servers are free, but I don't really think the complexity is justified at this stage. Imagine if the clients sat so that they could see which doctor had their door open and was ready to accept a new patient. The first client who sees that then gets up to go through that door. There is a possibility of a race when two patients head for the door at the same time, but we just need to make sure that only one of them wins, and that the other returns to her seat and keeps looking rather than getting stuck. Ideally this will be built on top of some mechanism that does not rely on polling. I had wondered whether it would work to use refused TCP connections to indicate that a server's door is closed, but I think that is no good. It seems that at least on Linux, and probably on other platforms, you cannot set the TCP SYN backlog down to zero for a socket. The kernel will still accept new connections on behalf of the process if it is listening, even if it's asked for no backlog and if it's not accepting them yet. netstat shows these processes just in It looks like the only way to reliably have the server turn away connections is to either close its listening socket when it's too busy, or drop connections. This would work OK, but it forces the client into retrying, which is inefficient and ugly. Suppose clients connect and then wait for a prompt from the server before they begin to send. For multiple servers the client would keep opening connections to new machines until it got an invitation to send a job. This requires a change to the protocol but it can be made backward compatible if necessary, though perhaps that's not necessary. This would have the advantage of working over either TCP or SSH. The main problem is that the client will potentially need to open connections to many machines before it can proceed. We almost certainly need to do this with nonblocking IO, but that should be reasonably portable. Local compilation needs to be handled by lockfiles or some similar mechanism. So in pseudocode this will be something like looking_fds = [] while not accepted: select() on looking_fds: if any have failed, remove them if any have sent an invitation: close all others use the accepted connection open a new connection I'm not sure if connections should be opened in random order or the order they're listed. Clients are almost certainly not going to be accepted in the order in which they arrive. If the client sends its job early then it doesn't hurt anybody else. I suppose it could open a lot of connections but that sort of fairness issue is not really something that distcc needs to handle. (Just block the user if they misbehave.) We can't use select() to check for the ability to run a process locally. Perhaps the select() needs to timeout and we can then, say, check the load average. problems with new protocol Does anyone actually want this? I really need an example of somewhere where it would be useful. The server may need to know the right extension for the temporary file to make the compiler behave in the right way. In fact, knowing the acceptable temporary filenames is part of the application definition. Compression Can compression automatically be turned on, rather than requiring user configuration? I can't tell at the moment when would be the right time to do that. Is it cheap enough to always have it on? We not only pay the cost of compression, but we also need to give up on using sendfile() and therefore pay for more kernel-userspace transitions and some data copying. Therefore probably not, at least for GigE. User Manual The UML manual is very good - Add some documentation of the benchmark system. Does this belong in the manual, or in a separate manual? - FAQ: Can't you check the gcc version? No, because gcc programs which report the same versions number can have different behaviours, perhaps due to vendor/distributor patches. Just cpp and linker? Is it easy to describe how to install only the bits of gcc needed for distcc clients? Basically the driver, header, linker, and specs. Would this save much space? Certainly installing gcc is much easier than installing a full cross development environment, because you don't need headers or libraries. So if you have a target machine that is a bit slower but not terrible (or you don't have many of them) it might be convenient to do most of your builds on the target, but rely on helpers with cross-compilers to help out. -g support I'm told that gcc may fix this properly in a future release. There would then be no need to kludge around it in distcc. [Yes, this is now fixed in gcc 4.0 and later.] Perhaps detect the -g option, and then absolutify filenames passed to the compiler. This will cause absolute filenames to appear in error messages, but I don't see any easy way to have both correct stabs info and also correct error messages. Is anything else wrong with this approach? kill compiler If the client is killed, it will close the connection. The server ought to kill the compiler so as to prevent runaway processes on the server. This probably involves selecting() for read on the connection. The compilation will complete relatively soon anyhow, so it's not worth doing this unless there is a simple implementation. tcp fiddling I wonder if increasing the maximum window size (sys.net.core.wmem_default, etc) will help anything? It's probably dominated by scheduling inefficiency at the moment. The client does seem to spend time in wait_for_tcp_memory, which might be benefitted by increasing the available memory. benchmark Try aspell and xmms, which may have strange Makefiles. glibc gtk/glib glibc++ qt gcc gdb linux openoffice mozilla rsync-like distributed caching Look in the remote machine's cache as well. Perhaps use a SQUID-like broadcast of the file digest and other critical details to find out if any machine in the workgroup has the file cached. Perhaps this could be built on top of a more general file-caching mechanism that maps from hash to body. At the moment this sounds like premature optimization. Send source as an rdiff against the previous version. Needs to be able to fall back to just sending plain text of course. Perhaps use different compression for source and binary. librsync is probably not stable enough to do this very well. --ping option [Done - see "lsdistcc"] It would be nice to have a --ping client option to contact all the remote servers, and perhaps return some kind of interesting information. Output should be machine-parseable e.g. to use in removing unreachable machines from the host list. Perhaps send little fixed signatures, based on --version. Would this ever be useful? non-CC-specific Protocol Perhaps rather than getting the server to reinterpret the command line, we should mark the input and output parameters on the client. So what's sent across the network might be distcc -c @@INPUT@@ -o @@OUTPUT@@ It's probably better to add additional protocol sections to say which words should be the input and output files than to use magic values. The attraction is that this would allow a particularly knotty part of code to be included only in the client and run only once. If any bugs are fixed in this, then only the client will need to be upgraded. This might remove most of the gcc-specific knowledge from the server. Different clients might be used to support various very different distributable jobs. We ought to allow for running commands that don't take an input or output file, in case we want to run "gcc --version". The drawback is that probably new servers need to be installed to handle the new protocol version. I don't know if there's really a compelling reason to do this. If the argument parser depends on things that can only be seen on the client, such as checking whether files exist, then this may be needed. The server needs to use an appropriately-named temporary file. gcc wierdnesses: distcc needs to handle $COMPILER_PATH and $GCC_EXEC_PREFIX in some sensible way, if there is one. Not urgent because I have never heard of them being used. networking timeouts: Also we want a timeout for name resolution. The GNU resolver has a specific feature to do this. On other systems we probably need to use alarm(), but that might be more trouble than it is worth. Jonas Jensen says: Timing out the connect call could be done easier than this, just by interrupting it with a SIGALRM, but that's not enough to abort gethostbyname. This method of longjmp'ing from a signal handler is what they use in curl, so it should be ok. configurable timeout? Maybe make the various timeouts configurable? Isn't it possible to choose values that suit everyone? Maybe the initial connection timeout should be shorter? waitstatus Make sure that native waitstatus formats are the same as the Unix/Linux/BSD formats used on the wire. (See , which says they may only be interpreted by macros.) I don't know of any system where they're different. override compiler name distcc could support cross-compilation by a per-volunteer option to override the compiler name. On the local host, it might invoke gcc directly, but on some volunteers it might be necessary to specify a more detailed description of the compiler to get the appropriate cross tool. This might be insufficient for Makefiles that need to call several different compilers, perhaps gcc and g++ or different versions of gcc. Perhaps they can make do with changing the DISTCC host settings at appropriate times. I'm not convinced this complexity is justified. Rusty is doing this in ccontrol, which is possibly a better place for it. use spawn() on Windows fork() is very slow. Can we get away with only using spawn()? Installable package for Windows Also, it would be nice to have an easily installable package for Windows that makes the machine be a Cygwin-based compile volunteer. It probably needs to include cross-compilers for Linux (or whatever), or at least simple instructions for building them. autodetection (Rendezvous, etc) http://dotlocal.org/mdnsd/ The Apple licence is apparently not GPL compatible. Brad reckons SLP is a better fit. Automatic detection ("zero configuration") of compile volunteers is probably not a good idea, because it might be complicated to implement, and would possibly cause breakage by distributing to machines which are not properly configured. OpenMOSIX autodiscovery what is this? [This is probably moot now - I think ZeroConf support accomplishes the same goals?] central configuration Notwithstanding the previous point, centralized configuration for a site would be good, and probably quite practical. Setting up a list of machines centrally rather than configuring each one sounds more friendly. The most likely design is to use DNS SRV records (RFC2052), or perhaps multi-RR A records. For 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. ------------------------------------------------------------------------------- DONE TODOs ------------------------------------------------------------------------------- preprocess remotely [Done! This is distcc 3.0's "pump" mode.] Some people might like to assume that all the machines have the same headers installed, in which case we really can preprocess remotely and only ship the source. Imagine e.g. a Clearcase environment where the same filesystem view is mounted on all machines, and they're all running the exact same system release. It's probably not really a good idea, because it will be marginally faster but much more risky. It is possible, though, and perhaps people building files with enormous headers would like it. Perhaps those people should just use a different tool like dmake, etc. SSH connection hoarding It might be nice to hold open SSH connections to avoid the network and CPU overhead of opening new ones. However, fsh is far too slow, probably because of being written in Python. It's only going to work on systems which can pass file descriptors and therefore needs to be optional. Probably this only works on Unix. Building the kernel between the three x2000s seems to make localhost thrash. A few jobs (but not many) get passed out to the other machines. Perhaps for C++ or something with really large files fsh would be better because the cost of starting Python would be amortized across more work. I don't think this needs to be done in distcc. It can be a completely separate project to just rewrite fsh into C. Indeed you could even be compatible with the Python implementation and just write the short-lived client bit in C. [This has been done, in ssh itself: the -M option and the ControlMaster and ControlPath configuration settings.] Packaging Perhaps build RPMS and .debs? [DONE] Is it easy to build a static (or LSB-compliant?) .rpm on Debian? [DONE] Local variables: mode: indented-text indent-tabs-mode: nil End: distcc-3.1/source/Makefile.in0000640000175000017500000012156411115326647015222 0ustar wolffwolff# Top-level Makefile(.in) for distcc # Copyright (C) 2002, 2003, 2004 by Martin Pool # Note that distcc no longer uses automake, but this file is still # structured in a somewhat similar way. ## VARIABLES PACKAGE = @PACKAGE_NAME@ VERSION = @PACKAGE_VERSION@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ SHELL = @SHELL@ # These autoconf variables may contain recursive Make expansions, and # so they have to be done here rather than written into config.h. CFLAGS = @CFLAGS@ WERROR_CFLAGS = @WERROR_CFLAGS@ PYTHON_CFLAGS = @PYTHON_CFLAGS@ POPT_CFLAGS = @POPT_CFLAGS@ POPT_INCLUDES = @POPT_INCLUDES@ LDFLAGS = @LDFLAGS@ CC = @CC@ CPP = @CPP@ # We add a few cppflags. -Isrc is so that config.h can be found in the build # directory. It is before I"$(srcdir)/src" to reflect VPATH semantics. CPPFLAGS = @CPPFLAGS@ ${DIR_DEFS} \ -Isrc -I"$(srcdir)/src" -I"$(srcdir)/lzo" $(POPT_INCLUDES) srcdir = @srcdir@ top_srcdir = @top_srcdir@ builddir = @builddir@ top_builddir = @top_builddir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ datadir = @datadir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@ localstatedir = @localstatedir@ libdir = @libdir@ mandir = @mandir@ includedir = @includedir@ oldincludedir = /usr/include docdir = @docdir@ pkgdatadir = $(datadir)/@PACKAGE_NAME@ include_server_builddir = $(builddir)/_include_server # These must be done from here, not from autoconf, because they can # contain variable expansions written in Make syntax. Ew. DIR_DEFS = -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@ # We use python for two tasks in distcc: running the unittests, and # running the include-server. The latter requires python 2.4 or # higher, while the former only requires python 2.2. So it's possible # a particular machine will be able to run one but not the other. # Thus we have two variables. TEST_PYTHON = @TEST_PYTHON@ INCLUDESERVER_PYTHON = @INCLUDESERVER_PYTHON@ # RESTRICTED_PATH is a colon separated list of directory names. It # contains the locations of 'make', 'sh', 'gcc', and 'python' for use # in installation tests. This path is used to avoid confusion caused # by distcc masquerades on the normal path. See the # 'maintainer-check-no-set-path' target. RESTRICTED_PATH = /usr/local/bin:/bin:/usr/bin # The DISTCC_INSTALLATION variable is a colon separated list of # directory names of possible locations for the installation to be # checked. Change the value of this variable to @bindir@ to check the # installation at the location determined by 'configure'. DISTCC_INSTALLATION = $(RESTRICTED_PATH) dist_files = \ src/config.h.in \ $(dist_lzo) \ $(dist_contrib) \ $(dist_patches) \ $(dist_common) \ $(MEN) \ $(pkgdoc_DOCS) \ $(example_DOCS) \ $(popt_EXTRA) $(popt_SRC) $(popt_HEADERS) \ $(SRC) $(HEADERS) \ $(test_SOURCE) \ $(bench_PY) \ $(include_server_PY) \ $(dist_include_server_SH) \ $(include_server_SRC) \ $(check_include_server_DATA) \ $(check_include_server_PY) \ $(conf_files) \ $(default_files) \ $(dist_extra) \ $(gnome_data) dist_dirs = m4 include_server/test_data dist_lzo = lzo/minilzo.c lzo/minilzo.h lzo/lzoconf.h lzo/.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 dist_include_server_SH = \ pump.in bench_PY = bench/Build.py \ bench/Project.py \ bench/ProjectDefs.py \ bench/Summary.py \ bench/actions.py \ bench/benchmark.py \ bench/buildutil.py \ bench/compiler.py \ bench/statistics.py pkgdoc_DOCS = AUTHORS COPYING NEWS \ README README.pump \ INSTALL \ TODO \ doc/protocol-1.txt doc/status-1.txt \ doc/protocol-2.txt \ doc/reporting-bugs.txt \ survey.txt example_DOCS = \ doc/example/init doc/example/init-suse \ doc/example/logrotate \ doc/example/xinetd \ include_server_PY = \ include_server/__init__.py \ include_server/basics.py \ include_server/cache_basics.py \ include_server/compiler_defaults.py \ include_server/compress_files.py \ include_server/include_analyzer.py \ include_server/include_analyzer_memoizing_node.py \ include_server/include_server.py \ include_server/macro_eval.py \ include_server/mirror_path.py \ include_server/parse_command.py \ include_server/parse_file.py \ include_server/run.py \ include_server/setup.py \ include_server/statistics.py include_server_SRC = \ include_server/c_extensions/distcc_pump_c_extensions_module.c # These are included in the distribution but not installed anywhere. dist_extra = \ README.packaging ChangeLog \ packaging/RedHat/rpm.spec \ packaging/RedHat/logrotate.d/distcc \ packaging/RedHat/init.d/distcc \ packaging/RedHat/xinetd.d/distcc \ packaging/deb.sh \ packaging/rpm.sh \ packaging/googlecode_upload.py mkinstalldirs = $(SHELL) $(srcdir)/mkinstalldirs man1dir = $(mandir)/man1 man8dir = $(mandir)/man8 test_SOURCE = test/comfychair.py \ test/onetest.py \ test/testdistcc.py \ find_c_extension.sh dist_common = Makefile.in install-sh configure configure.ac \ config.guess config.sub mkinstalldirs autogen.sh # It seems a bit unnecessary to ship patches in the released tarballs. # People who are so keen as to apply unsupported patches ought to use # CVS, or at least get them from the list. dist_patches = TAR = tar GZIP_BIN = gzip # This is set on the environment, and automatically read by gzip. # This way we always get best compression, even when gzip is run in a # script we call, rather than being called by us directly. GZIP = -9v BZIP2_BIN = bzip2 distdir = $(PACKAGE_TARNAME)-$(VERSION) tarball = $(PACKAGE_TARNAME)-$(VERSION).tar tarball_bz2 = $(tarball).bz2 tarball_gz = $(tarball).gz tarball_sig_bz2 = $(tarball_bz2).asc tarball_sig_gz = $(tarball_gz).asc distnews = $(PACKAGE_TARNAME)-$(VERSION).NEWS rpm_glob_pattern = "$(PACKAGE)"*[-_.]"$(VERSION)"[-_.]*.deb deb_glob_pattern = "$(PACKAGE)"*[-_.]"$(VERSION)"[-_.]*.rpm common_obj = src/arg.o src/argutil.o \ src/cleanup.o src/compress.o \ src/trace.o src/util.o src/io.o src/exec.o \ src/rpc.o src/tempfile.o src/bulk.o src/help.o src/filename.o \ src/lock.o \ src/netutil.o \ src/pump.o \ src/sendfile.o \ src/safeguard.o src/snprintf.o src/timeval.o \ src/dotd.o \ src/hosts.o src/hostfile.o \ src/implicit.o src/loadfile.o \ lzo/minilzo.o \ @ZEROCONF_COMMON_OBJS@ distcc_obj = src/backoff.o \ src/climasq.o src/clinet.o src/clirpc.o \ src/compile.o src/cpp.o \ src/distcc.o \ src/remote.o \ src/ssh.o src/state.o src/strip.o \ src/timefile.o src/traceenv.o \ src/include_server_if.o \ src/where.o \ @ZEROCONF_DISTCC_OBJS@ \ src/emaillog.o \ $(common_obj) distccd_obj = src/access.o \ src/daemon.o src/dopt.o src/dparent.o src/dsignal.o \ src/ncpus.o \ src/prefork.o \ src/stringmap.o \ src/serve.o src/setuid.o src/srvnet.o src/srvrpc.o src/state.o \ src/stats.o \ src/fix_debug_info.o \ @ZEROCONF_DISTCCD_OBJS@ \ $(common_obj) @BUILD_POPT@ lsdistcc_obj = src/lsdistcc.o \ src/clinet.o src/io.o src/netutil.o src/trace.o src/util.o \ src/rslave.o src/snprintf.o \ lzo/minilzo.o # Objects that need to be linked in to build monitors mon_obj = \ src/cleanup.o \ src/filename.o \ src/io.o \ src/mon.o \ src/netutil.o \ src/argutil.o \ src/rpc.o \ src/snprintf.o src/state.o \ src/tempfile.o src/trace.o src/traceenv.o \ src/util.o gnome_obj = src/history.o src/mon-gnome.o \ src/renderer.o h_exten_obj = src/h_exten.o $(common_obj) h_issource_obj = src/h_issource.o $(common_obj) h_scanargs_obj = src/h_scanargs.o $(common_obj) h_hosts_obj = src/h_hosts.o $(common_obj) h_argvtostr_obj = src/h_argvtostr.o $(common_obj) h_strip_obj = src/h_strip.o $(common_obj) src/strip.o h_parsemask_obj = src/h_parsemask.o $(common_obj) src/access.o h_sa2str_obj = src/h_sa2str.o $(common_obj) src/srvnet.o src/access.o h_ccvers_obj = src/h_ccvers.o $(common_obj) h_dotd_obj = src/h_dotd.o $(common_obj) h_fix_debug_info = src/h_fix_debug_info.o $(common_obj) h_compile_obj = src/h_compile.o $(common_obj) src/compile.o src/timefile.o \ src/backoff.o src/emaillog.o src/remote.o src/clinet.o \ src/clirpc.o src/include_server_if.o src/state.o src/where.o \ src/ssh.o src/strip.o src/cpp.o # 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 \ src/zeroconf.c src/zeroconf-reg.c src/gcc-id.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 \ src/va_copy.h \ src/zeroconf.h conf_dir = packaging/RedHat/conf conf_files = $(conf_dir)/hosts \ $(conf_dir)/clients.allow \ $(conf_dir)/commands.allow.sh default_dir = packaging/RedHat/default default_files = $(default_dir)/distcc man1_MEN = man/distcc.1 man/distccd.1 man/distccmon-text.1 \ man/pump.1 man/include_server.1 man_HTML = man/distcc_1.html man/distccd_1.html man/distccmon_text_1.html \ man/pump_1.html man/include_server_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@ check_include_server_PY = \ include_server/c_extensions_test.py \ include_server/include_server_test.py \ include_server/macro_eval_test.py \ include_server/mirror_path_test.py \ include_server/parse_command_test.py \ include_server/parse_file_test.py \ include_server/include_analyzer_test.py \ include_server/include_analyzer_memoizing_node_test.py \ include_server/basics_test.py ###################################################################### ## IMPLICIT BUILD rules .SUFFIXES: .html .latte .o .c .c.o: $(CC) $(CPPFLAGS) $(WERROR_CFLAGS) $(CFLAGS) -o $@ -c $< ###################################################################### ## OVERALL targets .PHONY: all include-server ## NOTE: "all" must be the first (default) rule, aside from patterns. all: $(bin_PROGRAMS) pump include-server # src/config.h.in is used by config.status Makefile: Makefile.in src/config.h.in config.status ./config.status ###################################################################### ## BUILD targets # We would like to detect when config.h.in has changed: this should trigger # config.status to be rerun. But if the config.h file actually does not change # as a result of running config.status (a feature of autoconf), then # config.status will be rerun every time. That's confusing. So, the rule # # src/config.h: src/config.h.in # ./config.status # # is not sufficient. src/config.h: src/config.h.stamp src/config.h.stamp: src/config.h.in echo "path: $$PATH" ./config.status touch src/config.h.stamp pump: pump.in config.status ./config.status # Grab the dependency files generated by gcc's -MD option. -include */*.d # Disable some warnings for popt/*.c. $(popt_OBJS): CFLAGS += $(POPT_CFLAGS) distcc@EXEEXT@: $(distcc_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(distcc_obj) $(LIBS) distccd@EXEEXT@: $(distccd_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(distccd_obj) $(LIBS) distccmon-text@EXEEXT@: $(mon_obj) src/mon-text.o $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(mon_obj) src/mon-text.o $(LIBS) lsdistcc@EXEEXT@: $(lsdistcc_obj) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(lsdistcc_obj) $(LIBS) 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) \ $(mon_obj) $(gnome_obj) \ $(LIBS) $(GNOME_CFLAGS) $(GNOME_LIBS) # The include-server is a python app, so we use Python's build system. We pass # the distcc version, the source location, the CPP flags (for location of the # includes), and the build location. include-server: if test -z "$(INCLUDESERVER_PYTHON)"; then \ echo "Not building $@: No suitable python found"; \ else \ mkdir -p "$(include_server_builddir)" && \ DISTCC_VERSION="$(VERSION)" \ SRCDIR="$(srcdir)" \ CFLAGS="$(CFLAGS) $(PYTHON_CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ $(INCLUDESERVER_PYTHON) "$(srcdir)/include_server/setup.py" \ build \ --build-base="$(include_server_builddir)" \ --build-temp="$(include_server_builddir)"; \ fi ###################################################################### ## DIST TARGETS .PHONY: dist distcheck dist-sign dist-files # The sub-targets copy (and if necessary, build) various files that # have to go into the tarball. They also create necessary directories # -- bear in mind that they might be run in parallel. # This looks a bit gross to me, but it's not as bad as it might be :-/ # TODO(csilvers): add 'make rpm' and 'make deb'. dist: -rm -fr "$(distdir)" $(MAKE) dist-files $(TAR) cf "$(tarball)" "$(distdir)" $(GZIP_BIN) --help >/dev/null && \ $(GZIP_BIN) -fc "$(tarball)" > "$(tarball_gz)" $(BZIP2_BIN) --help 2>/dev/null && \ $(BZIP2_BIN) -vfc "$(tarball)" > "$(tarball_bz2)" rm -f "$(tarball)" rm -r "$(distdir)" cp "$(srcdir)/NEWS" "$(distnews)" # We create two new directories: one for the build and one to install, # and make sure we can build and install from different directories # than the source directory. Then we run a "make distclean" and # verify it got rid of everything not in the tarball by deleting every # file mentioned in the tarball, and then making sure nothing is left. distcheck: dist [ ! -d +distcheck ] || chmod -R u+w +distcheck rm -rf '+distcheck' mkdir '+distcheck' cd '+distcheck' && $(GZIP_BIN) -d < "../$(tarball_gz)" | $(TAR) xvf - mkdir "+distcheck/$(distdir)/_build" mkdir "+distcheck/$(distdir)/_inst" chmod -R a-w +distcheck chmod u+w "+distcheck/$(distdir)/_build" "+distcheck/$(distdir)/_inst" dc_install_base=`cd "+distcheck/$(distdir)/_inst" && pwd` \ && cd "+distcheck/$(distdir)/_build" \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) && $(MAKE) maintainer-check \ && $(MAKE) install \ && $(MAKE) DISTCC_INSTALLATION="$$dc_install_base/bin" \ maintainer-installcheck \ && $(MAKE) distclean chmod -R u+w +distcheck test `find "+distcheck/$(distdir)/_build" -type f -print | wc -l` -eq 0 \ || { echo "ERROR: files left in build-dir after distclean:"; \ find "+distcheck/$(distdir)/_build" -type f -print; \ rm -rf '+distcheck'; \ exit 1; } rm -rf '+distcheck' dist-sign: gpg -a --detach-sign "$(tarball_bz2)" # For the dirs we copy, we don't want to copy control files like '.cvs'. # We use find for this; if 'find' doesn't work, just don't worry about it. dist-files: $(dist_files) for f in $(dist_files) $(dist_dirs); do \ mkdir -p "$(distdir)"/`dirname "$$f"` || exit 1; \ cp -pR "$(srcdir)/$$f" "$(distdir)/$$f" 2>/dev/null || \ cp -pR "$$f" "$(distdir)/$$f" || exit 1; \ done for f in $(dist_dirs); do \ find "$(distdir)/$$f" -name '.[^.]*' -exec rm -rf \{\} \; -prune ; \ done ###################################################################### ## BUILD manual targets man/distcc_1.html: man/distcc.1 troff2html -man "$(srcdir)"/man/distcc.1 > $@ man/distccd_1.html: man/distccd.1 troff2html -man "$(srcdir)"/man/distccd.1 > $@ man/distccmon_text_1.html: man/distccmon-text.1 troff2html -man "$(srcdir)"/man/distccmon-text.1 > $@ man/pump_1.html: man/pump.1 troff2html -man "$(srcdir)"/man/pump.1 > $@ man/include_server_1.html: man/include_server.1 troff2html -man "$(srcdir)"/man/include_server.1 > $@ ###################################################################### ## CHECK targets for code that has been build. .PHONY: check_programs .PHONY: maintainer-check-no-set-path distcc-maintainer-check .PHONY: include-server-maintainer-check pump-maintainer-check .PHONY: maintainer-check .PHONY: check .PHONY: lzo-check valgrind-check single-test pump-single-test check_programs: $(check_PROGRAMS) $(bin_PROGRAMS) TESTDISTCC_OPTS = # This target is for internal use by distcc-maintainer-check and # distcc-installcheck. These rules differ only in their choice of the value of # PATH to use. PATH must be set appropriately so that python, distcc binaries, # gcc, and those of the check_PROGRAMS, can be found on PATH. This is done in # the call of this target through use of the variable RESTRICTED_PATH. # # The more prominent of these conditions are checked explicitly checked below. # # TODO(klarlund): the outermost if assumes that the include-server target may be # satisfied w/o actually building an include server (or rather the C extension); # this logic needs to be verified or amended. maintainer-check-no-set-path: @if ! $(TEST_PYTHON) -c 'import sys; print sys.version'; then \ echo "WARNING: python not found; tests skipped"; \ else \ if ! gcc --version 2>/dev/null; then \ echo "Could not find gcc on the restricted path used to avoid"; \ echo "confusion caused by distcc masquerades on the normal path."; \ echo "PATH is currently '$$PATH'."; \ echo "Please change RESTRICTED_PATH to change this PATH value."; \ exit 1; \ fi; \ $(TEST_PYTHON) "$(srcdir)/test/testdistcc.py" $(TESTDISTCC_OPTS); \ fi distcc-maintainer-check: check_programs $(MAKE) PATH="`pwd`:$(RESTRICTED_PATH)" \ TESTDISTCC_OPTS="$(TESTDISTCC_OPTS)" maintainer-check-no-set-path # If the include server extension module was built, then run the tests include # server. TODO(klarlund): the outermost if assumes that the include-server # target may be satisfied w/o actually building an include server (or rather the # C extension); this logic needs to be verified or amended. # TODO(csilvers): keep track of failures instead of exiting on the first one. include-server-maintainer-check: include-server @if ! test -d "$(include_server_builddir)"; then \ echo "Skipped include-server check"; \ else \ CURDIR=`pwd`; \ include_server_loc=`"$(srcdir)/find_c_extension.sh" "$(builddir)"`; \ test $$? = 0 || (echo 'Could not locate extension.' 1>&2 && exit 1); \ cd "$(srcdir)/include_server"; \ for p in $(check_include_server_PY); do \ p_base=`basename "$$p"`; \ echo -n "Running: "; \ echo \ "PYTHONPATH=$$CURDIR/$$include_server_loc:$$PYTHONPATH $(INCLUDESERVER_PYTHON) $$p_base"; \ if PYTHONPATH="$$CURDIR/$$include_server_loc:$$PYTHONPATH" $(INCLUDESERVER_PYTHON) "$$p_base" \ > "$$CURDIR/$(tempdir)/$$p_base.out" 2>&1; then \ echo "PASS"; \ rm "$$CURDIR/$(tempdir)/$$p_base.out"; \ else \ echo "FAIL"; cat "$$CURDIR/$(tempdir)/$$p_base.out"; exit 1; \ fi; \ done; \ fi # Do distcc-maintainer-check in pump-mode, if possible. pump-maintainer-check: pump include-server check_programs @if [ -d "$(include_server_builddir)" ]; then \ DISTCC_HOSTS=',cpp,lzo' \ "$(builddir)/pump" \ $(MAKE) \ RESTRICTED_PATH="$(RESTRICTED_PATH)" \ TESTDISTCC_OPTS="--pump $(TESTDISTCC_OPTS)" \ distcc-maintainer-check; \ fi # Do distcc-maintainer-check, for non-pumped distcc, and try the include_server # check to check the include server's behavior, if applicable. If the include # server exists, then carry out distcc-maintainer-check in pump-mode. maintainer-check: distcc-maintainer-check include-server-maintainer-check \ pump-maintainer-check check: @if test -n "$(INCLUDESERVER_PYTHON)"; then \ $(MAKE) maintainer-check; \ elif test -n "$(TEST_PYTHON)"; then \ echo "WARNING: pump-mode not being tested"; \ $(MAKE) distcc-maintainer-check; \ else \ echo "Cannot run tests: python binary not found"; \ false; \ fi # Runs the tests in lzo-mode. lzo-check: $(MAKE) TESTDISTCC_OPTS=--lzo maintainer-check # Runs the tests with valgrind. valgrind-check: $(MAKE) TESTDISTCC_OPTS=--valgrind maintainer-check # The following target is useful for running a single test at a time. # Sample usage: # make TESTNAME=Lsdistcc_Case single-test # make TESTNAME=Lsdistcc_Case TESTDISTCC_OPTS=--valgrind single-test TESTNAME = NoDetachDaemon_Case # Override this with the desired test. single-test: check_programs PATH="`pwd`:$(RESTRICTED_PATH)" \ $(TEST_PYTHON) "$(srcdir)/test/onetest.py" $(TESTDISTCC_OPTS) $(TESTNAME) # Run a single test in pump-mode. pump-single-test: pump include-server check_programs DISTCC_HOSTS=',cpp,lzo' \ "$(builddir)/pump" \ $(MAKE) \ RESTRICTED_PATH="$(RESTRICTED_PATH)" \ TESTDISTCC_OPTS="--pump $(TESTDISTCC_OPTS)" \ single-test ###################################################################### ## CHECK targets for code that has been installed. .PHONY: pump-installcheck distcc-installcheck maintainer-installcheck .PHONY: installcheck verify-binaries-installcheck daemon-installcheck # Verify that DISTCC_INSTALLATION contains the expected set of binaries. verify-binaries-installcheck: @echo -n "Locating binaries in DISTCC_INSTALLATION=" @echo "'$(DISTCC_INSTALLATION)'" @echo -n "To use installation in @bindir@, remake with" @echo " argument 'DISTCC_INSTALLATION=@bindir@'." @echo "Make sure all paths below are where you expect them to be:" @echo "**********************************************************" @for p in $(bin_PROGRAMS); do \ if ! PATH="$(DISTCC_INSTALLATION)" `which which` "$$p"; then \ echo "Binary '$$p' could not be found in DISTCC_INSTALLATION."; \ exit 1; \ fi; \ done @echo "**********************************************************" # Lookup distcc programs to be checked in $(DISTCC_INSTALLATION). The # check_PROGRAMS binaries, however, are to be found in $(builddir). distcc-installcheck: $(check_PROGRAMS) BUILDDIR=`cd "$(builddir)" && pwd`; \ PATH="$(DISTCC_INSTALLATION):$$BUILDDIR:$(RESTRICTED_PATH)" \ TESTDISTCC_OPTS="$(TESTDISTCC_OPTS)" \ $(MAKE) maintainer-check-no-set-path # Check the installation to see whether pump-mode works. pump-installcheck: which_loc=`which which`; \ pump_loc=`PATH="$(DISTCC_INSTALLATION)" "$$which_loc" pump`; \ DISTCC_HOSTS=',cpp,lzo' \ "$$pump_loc" \ $(MAKE) DISTCC_INSTALLATION="$(DISTCC_INSTALLATION)" \ RESTRICTED_PATH="$(RESTRICTED_PATH)" \ TESTDISTCC_OPTS=--pump distcc-installcheck; \ # "make maintainer-installcheck" verifies the currently installed version in # RESTRICTED_PATH. It does not have the "install" target as a dependency so # that you can can check an installation that is installed via some different # method (e.g. rpm or debian package). You must specify the location of such an # installation by overriding the value of DISTCC_INSTALLATION. # # The maintainer-installcheck does not run the include server unit tests; # but the integration tests in 'test' are run in pump mode. maintainer-installcheck: verify-binaries-installcheck distcc-installcheck \ pump-installcheck installcheck: @if test -n "$(INCLUDESERVER_PYTHON)"; then \ $(MAKE) maintainer-installcheck; \ elif test -n "$(TEST_PYTHON)"; then \ echo "WARNING: pump-mode not being tested"; \ $(MAKE) distcc-maintainer-installcheck; \ else \ echo "Cannot run install-tests: python binary not found"; \ false; \ fi # This tests that the distcc daemon is running, and that it and distcc # and the pump script have been installed correctly, by compiling a simple # hello world program with distcc and distcc-pump. # This can be used after "make install-deb". # # This uses distcc from your PATH and (for the first test) # may use DISTCC_HOSTS from your environment or /etc/distcc/hosts. # # This test might fail if the --allow options passed to distccd # (which may be set in the /etc/distcc/clients.allow file) # do not include 127.0.0.1. daemon-installcheck: mkdir -p _testtmp/daemon-installcheck && \ cd _testtmp/daemon-installcheck && \ echo '#include ' > hello.c && \ echo 'int main(void) { puts("hello world"); return 0; }' >> hello.c && \ rm -f hello.o && \ DISTCC_FALLBACK=0 distcc $(CC) $(CFLAGS) -c hello.c -o hello.o && \ test -f hello.o && \ rm -f hello.o && \ DISTCC_POTENTIAL_HOSTS=127.0.0.1 DISTCC_FALLBACK=0 \ pump distcc $(CC) $(CFLAGS) -c hello.c -o hello.o && \ test -f hello.o ###################################################################### ## BENCHMARK targets .PHONY: benchmark benchmark: @echo "The distcc macro-benchmark uses your existing distcc installation" @if [ -n "$$DISTCC_HOSTS" ]; \ then echo "DISTCC_HOSTS=\"$$DISTCC_HOSTS\""; \ else echo "You must set up servers and set DISTCC_HOSTS before running the benchmark"; \ exit 1; \ fi @echo "This benchmark may download a lot of source files, and it takes a " @echo "long time to run. Interrupt now if you want." @echo @echo "Pass BENCH_ARGS to make to specify which benchmarks to run." @echo @sleep 5 cd bench && $(TEST_PYTHON) benchmark.py $(BENCH_ARGS) ###################################################################### ## CLEAN targets .PHONY: clean clean-autoconf clean-lzo clean-include-server .PHONY: maintainer-clean maintainer-clean-autoconf distclean distclean-autoconf # Also clean binaries which are optionally built. Also remove .d files; old ones # may confuse 'make'. clean: clean-autoconf clean-lzo clean-include-server rm -f src/*.[od] popt/*.[od] rm -f test/*.pyc rm -f $(check_PROGRAMS) $(bin_PROGRAMS) rm -f $(man_HTML) rm -f distccmon-gnome rm -rf _testtmp # produced by test/testdistcc.py and daemon-installcheck rm -rf +distcheck rm -rf "$(include_server_builddir)" clean-autoconf: rm -f config.cache config.log clean-lzo: rm -f lzo/*.[od] lzo/testmini clean-include-server: if test -n "$(INCLUDESERVER_PYTHON)"; then \ DISTCC_VERSION="$(VERSION)" \ SRCDIR="$(srcdir)" \ CFLAGS="$(CFLAGS) $(PYTHON_CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ $(INCLUDESERVER_PYTHON) "$(srcdir)/include_server/setup.py" \ clean \ --build-base="$(include_server_builddir)" \ --build-temp="$(include_server_builddir)"; \ fi maintainer-clean: distclean \ maintainer-clean-autoconf clean # configure and co are distributed, but not in CVS maintainer-clean-autoconf: rm -f configure src/config.h.in distclean-autoconf: rm -f Makefile src/config.h src/config.h.stamp pump rm -f popt/.stamp-conf lzo/.stamp-conf rm -f config.status config.cache config.log aclocal.m4 rm -rf autom4te.cache distclean: distclean-autoconf clean ###################################################################### ## MAINTAINER targets .PHONY: upload-man upload-dist rpm deb install-deb upload-man: $(man_HTML) mkdir -p doc/web/man cp -f $(man_HTML) doc/web/man svn commit doc/web/man # When uploading the package, we try to update the website as well. # However, that's just best-effort, and if we can't (because, say, we # don't have troff2html installed), we just upload the tarballs. upload-dist: alldist -$(MAKE) upload-man "$(srcdir)/packaging/googlecode_upload.py" \ "$(tarball_gz)" \ "$(tarball_bz2)" \ packaging/$(rpm_glob_pattern) \ packaging/$(deb_glob_pattern) rpm: dist packaging/rpm.sh packaging/RedHat/rpm.spec cd packaging && ./rpm.sh $(PACKAGE) $(VERSION) # This uses the output of 'make rpm' to convert rpm files to deb files deb: rpm packaging/deb.sh cd packaging && ./deb.sh $(PACKAGE) $(VERSION) *.rpm # We copy .deb files to /tmp to avoid problems with NFS root_squash. install-deb: deb tmpdir=`mktemp -d /tmp/distcc-install-deb-XXXXXX` && \ cp packaging/*.deb $$tmpdir && \ cd "$$tmpdir" && \ sudo dpkg -i $(deb_glob_pattern) && \ rm -rf $$tmpdir # deb creates rpm files first, which in turn creates .gz files alldist: deb @echo dist files created: @ls -1 "$(tarball_gz)" "$(tarball_bz2)" @ls -1 packaging/$(rpm_glob_pattern) @ls -1 packaging/$(deb_glob_pattern) ### INSTALL (and UNINSTALL) targets .PHONY: showpaths install install-programs install-include-server .PHONY: install-man install-doc install-example install-gnome-data .PHONY: install-conf # TODO: Allow root directory to be overridden for use in building # packages. showpaths: @echo "'make install' will install distcc as follows:" @echo " man pages $(DESTDIR)$(man1dir)" @echo " documents $(DESTDIR)$(docdir)" @echo " programs $(DESTDIR)$(bindir)" @echo " 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-include-server install-example @INSTALL_GNOME@ install-conf install-programs: $(bin_PROGRAMS) $(mkinstalldirs) "$(DESTDIR)$(bindir)" for p in $(bin_PROGRAMS); do \ $(INSTALL_PROGRAM) "$$p" "$(DESTDIR)$(bindir)" || exit 1; \ done # See comments for the include-server target. Also, we work around an issue in # the change_root function of distutils/utils.py that turns the absolute prefix # into a relative reference if the root is the empty string: we absolutize the # destination directory in order to substitute '/' for the empty prefix (the # default) when defining the '--root' parameter. # The final complex issue involves installing pump. pump wants to # know the installed-location of include_server.py. The only way to # tell is to have setup.py install it, and then look what it says (via # the --record output). So when installing pump, we look at the # --record output and modify the installed pump to have that location. # Note: --record output is inconsistent (buggy?) and sometimes leaves out # the leading slash in $prefix, even though we require prefix start with # a slash. We use sed to add it back in at cp time. # Also, on Cygwin the --record output is in DOS text file format (CR LF # line endings), so we need to convert it from DOS text file format to # Unix text file format (LF line endings); we use sed for that too. install-include-server: include-server pump if test -z "$(INCLUDESERVER_PYTHON)"; then \ echo "Not building $@: No suitable python found"; \ else \ mkdir -p "$(include_server_builddir)" && \ DESTDIR=`cd "$(DESTDIR)/" && pwd` && \ DISTCC_VERSION="$(VERSION)" \ SRCDIR="$(srcdir)" \ CFLAGS="$(CFLAGS) $(PYTHON_CFLAGS)" \ CPPFLAGS="$(CPPFLAGS)" \ $(INCLUDESERVER_PYTHON) "$(srcdir)/include_server/setup.py" \ build \ --build-base="$(include_server_builddir)" \ --build-temp="$(include_server_builddir)" \ install \ --prefix="$(prefix)" \ --record="$(include_server_builddir)/install.log.pre" \ --root="$$DESTDIR" \ || exit 1; \ sed -e '/^[^\/]/ s,^,/,' \ -e 's/\r$$//' \ "$(include_server_builddir)/install.log.pre" \ > "$(include_server_builddir)/install.log"; \ if test -n "$(PYTHON_INSTALL_RECORD)"; then \ cp -f "$(include_server_builddir)/install.log" "$(PYTHON_INSTALL_RECORD)"; \ fi; \ $(mkinstalldirs) "$(DESTDIR)$(bindir)" && \ INCLUDE_SERVER=`grep '/include_server.py$$' "$(include_server_builddir)/install.log"` && \ sed "s,^include_server='',include_server='$$INCLUDE_SERVER'," \ pump > "$(include_server_builddir)/pump" && \ $(INSTALL_PROGRAM) "$(include_server_builddir)/pump" "$(DESTDIR)$(bindir)"; \ fi install-man: $(man1_MEN) $(mkinstalldirs) "$(DESTDIR)$(man1dir)" for p in $(man1_MEN); do \ $(INSTALL_DATA) "$(srcdir)/$$p" "$(DESTDIR)$(man1dir)" || exit 1; \ done install-doc: $(pkgdoc_DOCS) $(mkinstalldirs) "$(DESTDIR)$(docdir)" for p in $(pkgdoc_DOCS); do \ $(INSTALL_DATA) "$(srcdir)/$$p" "$(DESTDIR)$(docdir)" || exit 1; \ done install-example: $(example_DOCS) $(mkinstalldirs) "$(DESTDIR)$(docdir)/example" for p in $(example_DOCS); do \ $(INSTALL_DATA) "$(srcdir)/$$p" "$(DESTDIR)$(docdir)/example" || exit 1; \ done install-gnome-data: $(gnome_data) $(mkinstalldirs) "$(DESTDIR)$(pkgdatadir)" for p in $(gnome_data); do \ $(INSTALL_DATA) "$$p" "$(DESTDIR)$(pkgdatadir)" || exit 1; \ done install-conf: $(conf_files) $(default_files) $(mkinstalldirs) "$(DESTDIR)$(sysconfdir)/distcc" $(mkinstalldirs) "$(DESTDIR)$(sysconfdir)/default" @for p in $(conf_files); do \ base=`basename $$p`; \ target="$(DESTDIR)$(sysconfdir)/distcc/$$base"; \ if test -e "$$target"; then \ echo "******************************************"; \ echo "*** Configuration file '$$target'"; \ echo "*** already exists; not installing '$$p'."; \ else \ echo "$(INSTALL_DATA) $(srcdir)/$$p $$target"; \ $(INSTALL_DATA) "$(srcdir)/$$p" "$$target" \ || exit 1; \ fi; \ done @for p in $(default_files); do \ base=`basename $$p`; \ target="$(DESTDIR)$(sysconfdir)/default/$$base"; \ if test -e "$$target"; then \ echo "******************************************"; \ echo "*** Configuration file '$$target'"; \ echo "*** already exists; not installing '$$p'."; \ else \ echo "$(INSTALL_DATA) $(srcdir)/$$p $$target"; \ $(INSTALL_DATA) "$(srcdir)/$$p" "$$target" \ || exit 1; \ fi; \ done # For best results, uninstall-example has to run before uninstall-doc, # so we clean up the doc subdirectory before cleaning up doc itself. uninstall: uninstall-man uninstall-programs @UNINSTALL_GNOME@ \ uninstall-include-server uninstall-example uninstall-doc uninstall-conf uninstall-programs: for p in $(bin_PROGRAMS) pump; do \ file="$(DESTDIR)$(bindir)/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -[ "`basename $(bindir)`" = "$(PACKAGE)" ] && rmdir "$(DESTDIR)$(bindir)" # There's no setup.py --uninstall. :-( So I depend on # PYTHON_INSTALL_RECORD being set. If it was used at --install time, # I can use it again to uninstall. uninstall-include-server: if [ -e "$(PYTHON_INSTALL_RECORD)" ]; then \ cat "$(PYTHON_INSTALL_RECORD)" | xargs rm -fv; \ cat "$(PYTHON_INSTALL_RECORD)" | sed 's/py$/pyc/' | xargs rm -fv; \ cat "$(PYTHON_INSTALL_RECORD)" | sed 's/py$/pyo/' | xargs rm -fv; \ else \ echo "Cannot uninstall include-server: no PYTHON_INSTALL_RECORD"; \ fi uninstall-man: for p in $(man1_MEN); do \ file="$(DESTDIR)$(man1dir)/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -[ "`basename $(man1dir)`" = "$(PACKAGE)" ] && rmdir "$(DESTDIR)$(man1dir)" uninstall-doc: for p in $(pkgdoc_DOCS); do \ file="$(DESTDIR)$(docdir)/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -[ "`basename $(docdir)`" = "$(PACKAGE)" ] && rmdir "$(DESTDIR)$(docdir)" uninstall-example: for p in $(example_DOCS); do \ file="$(DESTDIR)$(docdir)/example/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -rmdir "$(DESTDIR)$(docdir)/example" uninstall-gnome-data: for p in $(gnome_data); do \ file="$(DESTDIR)$(pkgdir)/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -[ `basename $(pkgdir)` = $(PACKAGE) ] && rmdir "$(DESTDIR)$(pkgdir)" uninstall-conf: for p in $(conf_files); do \ file="$(DESTDIR)$(sysconfdir)/distcc/`basename $$p`"; \ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done -rmdir "$(DESTDIR)$(sysconfdir)/distcc" for p in $(default_files); do \ file="$(DESTDIR)$(sysconfdir)/default/`basename $$p`";\ if [ -e "$$file" ]; then rm -fv "$$file"; fi \ done tags: $(SRC) $(HEADERS) ctags --defines --globals --typedefs-and-c++ --no-warn $(SRC) $(HEADERS) distcc-3.1/source/gnome/0000750000175000017500000000000011115327757014253 5ustar wolffwolffdistcc-3.1/source/gnome/distccmon-gnome-icon.png0000640000175000017500000001127311115326643020773 0ustar wolffwolff‰PNG  IHDR77¨ÛÒFbKGDÿÿÿ ½§“pIDATxÚíšyxTå½Ç?çÌ–™ìûD$‚µ€‚,e©Ö+Xik«¶Õbíj±åÑÛǶêµôq-7 Z7J©€z¥²ÔV+´²%”°%HX"²Lf²Ìz–÷½Ì™0¤¡7p­½÷yú>ÏûœsfÎÌù}ßïoükükük|’Cù(k¢Ìò稃øSp°8 ˜€4/>!` `€Ó::¬Ï”„9hænš:õÚçç~aj~Fz&þ®vzº¼„z|xN‚0ëßü£hk•KÄ?˜ °÷`ô›¦Å $á¦Æ’ŸzøÙëçÏN9|ü µ {ðuùˆ†zIKr“îN#3«˜’q“Ct]sö#¯ ØòæÜ@êí·ßÞ:eÊ”û„÷={v °ÍÒ@¥¿z^ÜYöð’¤d•êý;in=‰¦ixl*I.»3 Å‘‚OwâÌFÃîêÉÀÀP,A>²î;< ì±~ó÷€y€ôÅ‹ŸüÁâ{H+LAÉ0™Ï|Îj9º©m'Z›¿Z«ì´Ô4¾’uO®~nòÉC'¦>ÿêsãßxåÑ+7¬øÌÆ×6Í~e­¾ìgcë¿Ò/^|ìËwÞÂOŸü1ÿ°Úu?~œÒ«JÈ*θ¼ýDç•À>Àg=W äPîÉ•kRކ‰hŠbÅÁe³ª(˜ó<¤ £="ñ“Ê?˜Å¯ï¾š¤ô €¥–³ XÓHXÉñu.r?{céË»}L]tßÄ º.¢€–°²Ÿ0ðàØmw~™gW>Íáúliäôá³4ÕœdäÈ‘L›1Q“‡·ì>Õr‚vûàf§§¦Ñxâša¢&*ùÓŸå9…T¼•÷³ûPÅy9´µžÁ4405@alÅ8|ñòrsÈÈÈ`ô˜ÑQ1îr¶~è@;k’j@¤5B0¹€ÌÜ~ðA òó¸bB%EEE1Ñ’ú‡vL¹zâr€#ÍooâøÞî;Wù»_ý¤ê~æ|n6ðçëî>ñCàq@ˆ¹¼¨®ÑÖÙŠ ºt ›ü@E¢p÷âGX0}2SÆŽ¤jÅZv××`†%ã&]I‚%ÿñ ûêê©­ÛÏÞºÔÔ7’’’B×éfügzhnÒvZ§ùp(*§OŸ¦³³¿ßO[[­­­ùð(›þðΔyóæ=P{x/£&¨–[lßõ‹{Ÿ 3-‡Ë0ÓReÇ@6wÛäÙ“ vÖíB`Ç”v„¢:õ.Cóóž-¸õ†Oa7Ï¢˜^nœ^ÎIJ"Ü8Ÿ‘“ç¡fâàŽõMNV&I$ª1mêÕìßôJû!\-;pùqw61ñŠqäædSXTİ¡Cq8¨8\.’=É´·ž™¾gÏvnÞ½Êæ®,(ÍeÒäIÌYðvoÙSì>?íº)466ÒÑìË^"ýÕò‹@n²'CÚ1¥EQÈt;Xtó5̼< [r6Šš‡¢¸"ЂР‡ÂìñÉÌ?‚…Ÿ?Ëâû~Ìö½I3‡Ì–3H`ÂÜÛе(Â4PT†AÓ5´ Î8ÃDÓ{)(Τ4 Â2‰Ò‘¥´µµÅe{¿q{Sa4ëMõqðÈ€-öú'`KwCyæáÿŒ ›×á´'ÒÉN…'ïšÂÈ’±¨®½€ ‰†´b¶ae;jÁÜYE|kr&¯¯¨âêE¯°«ê;ƒjk¬cC‡Äçà6¥/ª˜À¯OÔžò·OY¡Å5À_Ù5. øù²G—òúkñûB:ÃÆ—ò•iC™Ÿz+"[ Š-Ôd[2ŠÍƒ¢&1aì(|îNõ :n^|è;Lß·—%OiÏ,Y„¡ "RàÓ%ÓŽÓéA*vžÙ¼¿•ôp3s¿ümÆÉ²’òq$%£ô:úØ0 «òî7¡L…H󜻓zpß±˜ºàéU¿dXñe,[SÅîm5tµö6‹,¹#€>PúeZ™{Ü¥vޏîëO'‡}{úд}[_ëøYÕ÷¼ODñàíÕ1Ôd”á3PŠ&àrØ^”ÏX§ÆhçYò³òÈ*ÌÄmKFbGØÁǬ]bêwÓJ¹°wL v©§–Ó¾:iÖ£¯"̨ٓ’2þ´ýmV¿ù[w£·#pø>Ðmûæàè¦_ˉón×Õn ý>ò„¯[% ’“AÇ©æÞ°a‘]-ØôãzÜädd’V‹*ÓÁî&b³¡i1÷¦E!¨!1ívD¯†J¨”„)ϯœjþ À[o¿EkS;mǼ+­éëçAÿGp}zQ³iµ>zŒé’¢ül¼­t÷ô¢!š›H×}d«=èɧ+“‚dœIŸmi(öd4§H4 š šDtÃDSìHO‘sΡ˜RAˆsÔýå•êþ²½¼f9Ãnkö$xQi¿˜²¸ÛÛaÚT…ÉŸ®$7;ƒŽÎNœ<Éö÷%Y™ ÉËÄÐ$6’nÔ´4œR!âL‰Òp!³$š !¿ ×¦`ÓÂtœ˜“^Ÿ£ïYa#éü–Ï÷- « YçñÏBq[‹—NN˜Bê†É§ÆN °hþž^Ì-±Õ•¶l2Ý:z†TxpèÝ…¢taAÕ‰þ‘Ät+è2ŠÚmБêÀ-‚8\:n3|Îð¥Š.ÎSË€À»úŒ$ÔƒFb¬W)p¢Ë×Ù0{Î\ÞÙúÅC†‘—— @ØLÃ$3LO8Í¡£¨ ÀP§®‘ësYVCÜF¤š§Sá졲 ‹T"Ñsk-„‰>6ƒ–êuXÓ›à@‰ŒÅ0Xæ–þfÃË—m?ÔH}p,´ð›5oð•[o'5-€³íÍl — ’l(=AL¨~èñHœ‰.j"$©’^ÝEX :ünŠJ ÝN·ÚÛ÷@· 0ÃvÔWC-¡Û%ê]\Õ7ÝUpÃïœxæ£j´6¿³Jqq1n‡µ?*ûØZ^=ØD)L„¢&†(Ýš‰*8`CöbÀ-Y÷îë߬i IËEF¢(íïaJ…üü|ö}ġңÎ%¿ û=V$\›òük€°IÐ#$v)çi²ßu±à~ú“{ziØõ3K{Ït!;"¸v¤d¦§ µ‘v„”©`Hõ\Õ À±$8–3J„ˆ¦@J‰!b‰rIŽ›L» ùh ª4BÐíëˆËðÇ~2ÍÞJlÂ^*¸¿÷³o–ö*4iТ¨u¨2–ÞÛD”$42ÒÓ8z¼™´Œ,r2ӨרŒ;ÉÅèá…ì¨;Jq^&¦ BJL)0…))ÎIE´ÞˆI¼ýön˜;“3­g°I“W¬²ú}‰¯;°èþݳ˜T_ˆÅÁn„(VO0(JÊÙòܣ繌4·“!C† ¥¤Óç§éøq®¬Ï©–öî«çº¹³éèè`_ýæÌši©ªDˆk¦cH"yëÍÓ亹³Ù´µ†ãvÓp ~Ó‡Gæ% óòЕܵðÎ¾Ì ØÐFü»à”~­iÙï»÷Þ{ïw›šŽ=çr¹(˜Š ›4c6¢€ÒÏØÄ…¢Žb=A9÷$¿¿“p0HMõ®ø]_r€ÿ\ø­ïß~õÄ+W+H5¹yéS¿ ¤ÄóÉDy/e KµôýM€™3?kÍùüdfeÓåó’™M0$99™P0€'9%V¾%œ÷]§¤ô‰ÿÞï뤳ӋՉ®¶Ú俾ðÛ_¿öšI«€Dæn¶'ä”âb¶°Ê7ßf˜¦‰Ïç#3+¿¯3vìì<X(8ï¼ï:Ðï: îËTj¬@Ý |iÕŠçWí;pä •—Vü†[n½ã[À«d¿D<nP|m÷üqÏ_X6õ)@~ï'U7¼¸b•|qŪÄ{îJ€4  r)j9Ä*×þ3·WpÿÏç+ºQAòöÛZô»u¯= Œ°JžP¢c¹˜Ä¹XÐSÅò ò¶'}ß­py27VŒ*Ú2nsO'´;/9Î ~‰D"8±Nô®ê=Œ«‹Çã!‰²îÛ¸õ¦9hšÆû;ª¹~öô˜»7­xh‹u†V¯Y˵S§`šfß÷BˆóކaĽa` IÃ} ßÛ¶ea<Xã9ËþÍbÝ`Á})ñâµ×ÿ‹ììl¦N¹!áÍMï` ɼ9Sy}Ýz„|î³³Ù³w§N· EB±Ã‚ËÇU`³ÙÈÎÎÆ4MLÓäСC”•ÅòÓªª*®¼êÓ\;u †a°lù³(H^^±ISÓ±ç€ïZ±÷T¼•×?t)ƒdíTœµx?ñãMŒ,Ñ—V…B!\.B¡ .—ëü`m±$„è›1†„@×õó˜+//§®~?º®S1v BªªªØ¶mk\®g­C—*ý’éA¹Î/%6J[ZZ8|ø0#KG°Ùl${Üx;¼¤¦$“ž–Jk[;YYYddd°»º†¼¼< 9vìyyy|ðÁ”••Q^^NYYcÆŒaôèÑ}G€qc™?ïFJKK©­­ ¢¢b•%ÎëV¡oå‰þ/(ƒa- ‡q:(Š‚” „`ÇŽØív„TTTP[[‹‚ÊÊJvï®aÿþ:¾ñoP]]®ëL›6ýû÷3cÆŒ¾ÅZ¿~=cÇŽEJIaa!.—‹uëÖ1zôhLÓdÓ¦MØí6fΜ‰‚åË—³uëV¬ý‚g¬L(V î`e0ì3ò 6PRR‚ÓédüøñXù÷£¾”†ÉSO=ŬY³èééæÔ©S0bÄ„b·Û‰FciÓ4yòÉ'Y°`eeex½^{ì1|>këëëoʬŠ<0ØÜò<¹‚Á ¡Pˆ]»vqðàAf̘Áˆ#b;øuuÔÖÖöyCMÓúDÜvâÓét2mÚ4JKKBðÞ{ï¡ë:‡ƒI“&±yófü~?>Ÿ¯ï÷Á`»ï¾›ššLÓdüøñ˜¦É /¼goÐfu½.š9  ƒ}ì$ãÎ">¯ÏãÎ$ñ, with the co-operation of many scholars including Wayne Davison, Frerich Raabe, Dimitri Papadopoulos and others noted in the NEWS file. See \fBpump\fR(1) for the authors of pump mode. Please report bugs to . distcc-3.1/source/man/pump.10000640000175000017500000001143711115326647014770 0ustar wolffwolff.TH pump 1 "9 June 2008" .SH "NAME" pump \- accelerate remote compilation with distcc .SH "SYNOPSIS" .B pump .I BUILD-COMMAND [ARGS] \& ... .BR .PP eval ` .B pump --startup `; .I BUILD-COMMAND [ARGS] \& ... ; .B pump --shutdown .BR .SH "DESCRIPTION" .B pump is part of distcc. It is used for distcc's pump mode. Distcc's pump mode accelerates remote compilation with distcc by also distributing preprocessing to the servers. .PP For a detailed description of pump mode, including most notably some .B important restrictions, see the .BR distcc(1) man page, in particular the .B HOW PUMP-MODE WORKS section and the .B RESTRICTIONS ON PUMP MODE section. .PP The simplest usage is the form .RS .B pump .I COMMAND [ARG] \& ... .RE This will start an include server for distcc's "pump" mode; optionally run .B lsdistcc to compute the distcc host list; set some auxiliary environment variables; change PATH to use the distcc client in the same directory as the "pump" script; execute .I COMMAND with the specified .I ARG(s) \& ; and then shut down the include server. The .I COMMAND is typically a parallel build command, such as "make -j80", that will do many concurrent invocations of distcc. .PP An alternative way of invoking .B pump is to explicitly invoke "pump --startup" to start the include server and "pump --shutdown" to stop the include server. The "pump --startup" command will start up the include server, and will print out some environment variable settings. These environment variables are used to communicate between the pump-mode "distcc" client and the include server, and to communicate between "pump --startup" and "pump --shutdown". The caller of "pump --startup" is responsible for setting those environment variables before invoking "distcc" or "pump --shutdown". .PP For example: .RS eval `pump --startup` .br make -j80 .br pump --shutdown .RE .PP Note that distcc's pump-mode assumes that sources files will not be modified during the lifetime of the include server, so modifying source files during a build may cause inconsistent results. .SH "INVOKING LSDISTCC" When invoked in either the simple " .B pump .I COMMAND [ARG] \&... " form, or as " .B pump --startup \&", the .B pump script will invoke .B lsdistcc \& whenever DISTCC_POTENTIAL_HOSTS is set and DISTCC_HOSTS isn't. It will pass the value of DISTCC_POTENTIAL_HOSTS to .B lsdistcc and use the output of .B lsdistcc to set DISTCC_HOSTS. .SH "OPTIONS" .TP .B --help Displays summary instructions. .TP .B --startup Starts an include server, and outputs the environment variable settings needed for .BR distcc(1) or .B pump --shutdown to access it. .TP .B --shutdown Shuts down an include server started up by .B pump --startup. .SH "ENVIRONMENT VARIABLES" The following environment variables are all optional. .TP .B DISTCC_LOCATION The location of the distcc bin directory, which is normally inferred from the link-resolved dirname of argv[0]. If this location is in fact the bin directory inside an installation (as will be the case when the pump script in the installation executes), then Python executables and distcc itself will be retrieved from the parent directory of the location. .TP .B DISTCC_POTENTIAL_HOSTS The distcc servers that will be queried by lsdistcc in order to produce a value for DISTCC_HOSTS. This value may be unset or null. In such cases, lsdistcc will not be invoked, and distcc will use DISTCC_HOSTS or the distcc hosts configuration file, as described in the "Host Specifications" section of .BR distcc(1). .TP .B DISTCC_HOSTS This variable is passed through to distcc but only if DISTCC_POTENTIAL_HOSTS is not set. .TP .B LSDISTCC_ARGS Extra arguments to pass to lsdistcc. See .B lsdistcc --help for more details. .TP .B INCLUDE_SERVER_ARGS Extra arguments to pass to the include server. .TP .B PYTHONOPTIMIZE If set to "", then Python optimization is disabled. .SH "EXAMPLE" .B pump make -j20 .SH "BUGS" .\" TODO: .\" Fix inconsistency between BUGS section and bug reporting instructions .\" in the AUTHORS section, both here and in distcc.1 and elsewhere. If you think you have found a distcc bug, please see the file .I reporting-bugs.txt in the documentation directory for information on how to report it. .SH "AUTHORS" The pump script and distcc's pump mode were written by Nils Klarlund, Manos Renieris, Fergus Henderson, and Craig Silverstein. Please report bugs to . .SH "LICENCE" .B pump is part of distcc. You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warranty. A copy of the GPL is included in the file COPYING. .SH "SEE ALSO" .\" TODO: add lsdistcc(1) once we have a man page for lsdistcc. \fBdistcc\fR(1), \fBdistccd\fR(1), \fBinclude_server\fR(1), \fBgcc\fR(1), and \fBmake\fR(1) distcc-3.1/source/man/distcc.10000640000175000017500000010177411115326647015264 0ustar wolffwolff.TH distcc 1 "9 June 2008" .SH "NAME" distcc \- distributed C/C++/ObjC compiler with distcc-pump extensions .SH "SYNOPSIS" .B distcc .I [COMPILER OPTIONS] .PP .B distcc .I [COMPILER OPTIONS] .PP .B .I [COMPILER OPTIONS] .PP .B distcc .I [DISTCC OPTIONS] .SH "DESCRIPTION" .P distcc distributes compilation of C code across several machines on a network. distcc should always generate the same results as a local compile, it is simple to install and use, and it is often much faster than a local compile. .PP This version incorporates plain distcc as well as an enhancement called pump mode or distcc-pump. .PP For each job, distcc in plain mode sends the complete preprocessed source code and compiler arguments across the network from the client to a compilation server. In pump mode, distcc sends the source code and recursively included header files (excluding those from the default system header directories), so that both preprocessing and compilation can take place on the compilation servers. This speeds up the delivery of compilations by up to an order of magnitude over plain distcc. .PP Compilation is driven by a client machine, which is typically the developer's workstation or laptop. The distcc client runs on this machine, as does make, the preprocessor (if distcc's pump mode is not used), the linker, and other stages of the build process. Any number of volunteer machines act as compilation servers and help the client to build the program, by running the .B distccd(1) daemon, C compiler and assembler as required. .PP distcc can run across either TCP sockets (on port 3632 by default), or through a tunnel command such as ssh(1). For TCP connections the volunteers must run the distccd(1) daemon either directly or from inetd. For SSH connections distccd must be installed but should .B not be listening for connections. .PP TCP connections should only be used on secure networks because there is no user authentication or protection of source or object code. SSH connections are 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 .B -j, must take into account the CPU load on the client. Additional measures may be needed to curtail the client load. For example, concurrent linking should be severely curtailed using auxiliary locks. The effect of other build activity, such as Java compilation when building mixed code, should be considered. The .B --localslots_cpp parameter is by default set to 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, using pump mode and say 40 servers, a setting of .B -j80 or larger may be appropriate even for single-CPU clients. .PP It is strongly recommended that you install the same compiler version on all machines participating in a build. Incompatible compilers may cause mysterious compile or link failures. .SH "QUICKSTART" .TP 1 For each machine, download distcc, unpack, and install. .TP 2 On each of the servers, run .B distccd --daemon with .B --allow options to restrict access. .TP 3 Put the names of the servers in your environment: .RS $ export DISTCC_HOSTS='localhost red green blue' .RE .TP 4 Build! .RS $ make -j8 CC=distcc .RE .SH "QUICKSTART FOR DISTCC-PUMP MODE" Proceed as above, but in Step 3, specify that the remote hosts are to carry the burden of preprocessing and that the files sent over the network should be compressed: .RS $ export DISTCC_HOSTS='--randomize localhost red,cpp,lzo green,cpp,lzo blue,cpp,lzo' .RE The .B --randomize option enforces a uniform usage of compile servers. While you will get some benefit from distcc's pump mode with only a few servers, you get increasing benefit with more server CPUs (up to the hundreds!). Wrap your build inside the pump command, here assuming 10 servers: .RS $ pump make -j20 CC=distcc .RE .SH "HOW PLAIN (NON-PUMP) DISTCC WORKS" distcc only ever runs the compiler and assembler remotely. With plain distcc, the preprocessor must always run locally because it needs to access various header files on the local machine which may not be present, or may not be the same, on the volunteer. The linker similarly needs to examine libraries and object files, and so must run locally. .PP The compiler and assembler take only a single input file (the preprocessed source) and produce a single output (the object file). distcc ships these two files across the network and can therefore run the compiler/assembler remotely. .PP Fortunately, for most programs running the preprocessor is relatively cheap, and the linker is called relatively infrequent, so most of the work can be distributed. .PP distcc examines its command line to determine which of these phases are being invoked, and whether the job can be distributed. .SH "HOW DISTCC-PUMP MODE WORKS" In pump mode, distcc runs the preprocessor remotely too. To do so, the preprocessor must have access to all the files that it would have accessed if had been running locally. In pump mode, therefore, distcc gathers all of the recursively included headers, except the ones that are default system headers, and sends them along with the source file to the compilation server. In distcc-pump mode, the server unpacks the set of all source files in a temporary directory, which contains a directory tree that mirrors the part of the file system that is relevant to preprocessing, including symbolic links. The compiler is then run from the path in the temporary directory that corresponds to the current working directory on the client. To find and transmit the many hundreds of files that are often part of a single compilation, pump mode uses an incremental include analysis algorithm. The include server is a Python program that implements this algorithm. The pump command starts the include server so that throughout the build it can answer include queries by distcc commands. The include server uses static analysis of the macro language to deal with conditional compilation and computed includes. It uses the property that when a given header file has already been analyzed for includes, it is not necessary to do so again if all the include options (-I's) are unchanged (along with other conditions). For large builds, header files are included, on average, hundreds of times each. With distcc-pump mode each such file is analyzed only a few times, perhaps just once, instead of being preprocessed hundreds of times. Also, each source or header file is now compressed only once, because the include server memoizes the compressed files. As a result, the time used for preparing compilations may drop by up to an order of magnitude over the preprocessing of plain distcc. Because distcc in pump mode is able to push out files up to about ten times faster, build speed may increase 3X or more for large builds compared to plain distcc mode. .SH "RESTRICTIONS FOR PUMP MODE" Using pump mode requires both client and servers to use release 3.0 or later of distcc and distccd (respectively). The incremental include analysis of distc-pump mode rests on the fundamental assumption that source and header files do not change during the build process. A few complex build systems, such as that for Linux kernel 2.6, do not quite satisfy this requirement. To overcome such issues, and other corner cases such as absolute filepaths in includes, see the .BR include_server(1) man page. Another important assumption is that the include configuration of all machines must be identical. Thus the headers under the default system path must be the same on all servers and all clients. If a standard GNU compiler installation is used, then this requirement applies to all libraries whose header files are installed under /usr/include or /usr/local/include/. Note that installing software packages often lead to additional headers files being placed in subdirectories of either. If this assumption does not hold, then it is possible to break builds with distcc-pump mode, or worse, to get wrong results without warning. Presently this condition is not verified, and it is on our TODO list to address this issue. An easy way to guarantee that the include configurations are identical is to use a cross-compiler that defines a default system search path restricted to directories of the compiler installation. See the \fBinclude_server\fR(1) manual for more information on symptoms and causes of violations of distcc-pump mode assumptions. .SH "OPTION SUMMARY" Most options passed to distcc are interpreted as compiler options. The following options are understood by distcc itself. If any of these options are specified, distcc will not invoke the compiler. .TP .B --help Displays summary instructions. .TP .B --version Displays the distcc client version. .TP .B --show-hosts Displays the host list that distcc would use. See the Host Specifications section. .TP .B --scan-includes Displays the list of files that distcc would send to the remote machine, as computed by the include server. This is a conservative (over-)approximation of the files that would be read by the C compiler. This option only works in pump mode. See the "How Distcc-pump Mode Works" section for details on how this is computed. The list output by \fBdistcc --scan-includes\fR will contain one entry per line. Each line contains a category followed by a path. The category is one of FILE, SYMLINK, DIRECTORY, or SYSTEMDIR: .RS .B FILE indicates a source file or header file that would be sent to the distcc server host. .B SYMLINK indicates a symbolic link that would be sent to the distcc server host. .B DIRECTORY indicates a directory that may be needed in order to compile the source file. For example, a directory "foo" may be needed because of an include of the form #include "foo/../bar.h". Such directories would be created on the distcc server host. .B SYSTEMDIR indicates a system include directory, i.e. a directory which is on the compiler's default include path, such as "/usr/include"; such directories are assumed to be present on the distcc server host, and so would not be sent to the distcc server host. .RE .TP .B -j Displays distcc's concurrency level, as calculated from the host list; it is the maximum number of outstanding jobs issued by this client to all servers. By default this will be four times the number of hosts in the host list, unless the /LIMIT option was used in the host list. See the Host Specifications section. .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. .PP Recursion errors can be avoided by using shell scripts instead of links. For example, in /usr/lib/distcc/bin create a file cc which contains: .PP .RS .nf #!/bin/sh distcc /usr/bin/gcc "$@" .fi .RE .PP In this way, we are not dependent on distcc having to locate the real gcc by investigating the PATH variable. Instead, the compiler location is explicitly provided. .SH "USING DISTCC WITH CCACHE" ccache is a program that speeds software builds by caching the results of compilations. ccache is normally called before distcc, so that results are retrieved from a normal cache. Some experimentation may be required for idiosyncratic makefiles to make everything work together. .PP The most reliable method is to set .IP .B CCACHE_PREFIX="distcc" .PP This tells ccache to run distcc as a wrapper around the real compiler. ccache still uses the real compiler to detect compiler upgrades. .PP ccache can then be run using either a masquerade directory .I or by setting .IP .B CC="ccache gcc" .PP As of version 2.2, ccache does not cache compilation from preprocessed source and so will never get a cache hit if it is run from distccd or distcc. It must be run only on the client side and before distcc to be any use. distcc's pump mode is not compatible with ccache. .SH "HOST SPECIFICATIONS" A "host list" tells distcc which machines to use for compilation. In order, distcc looks in the .B $DISTCC_HOSTS environment variable, the user's .B $DISTCC_DIR/hosts file, and the system-wide host file. If no host list can be found, distcc emits a warning and compiles locally. .PP The host list is a simple whitespace separated list of host specifications. The simplest and most common form is a host names, such as .PP .RS .B localhost red green blue .RE .PP distcc prefers hosts towards the start of the list, so machines should be listed in descending order of speed. In particular, when only a single compilation can be run (such as from a configure script), the first machine listed is used (but see .I --randomize below). .PP Placing .I localhost at the right point in the list is important to getting good performance. Because overhead for running jobs locally is low, localhost should normally be first. However, it is important that the client have enough cycles free to run the local jobs and the distcc client. If the client is slower than the volunteers, or if there are many volunteers, then the client should be put later in the list or not at all. As a general rule, if the aggregate CPU speed of the client is less than one fifth of the total, then the client should be left out of the list. .PP If you have a large shared build cluster and a single shared hosts file, the above rules would cause the first few machines in the hosts file to be tried first even though they are likely to be busier than machines later in the list. To avoid this, place the keyword .I --randomize into the host list. This will cause the host list to be randomized, which should improve performance slightly for large build clusters. .PP There are two special host names .B --localslots and .B --localslots_cpp which are useful for adjusting load on the local machine. The .B --localslots host specifies how many jobs that cannot be run remotely that can be run concurrently on the local machine, while .B --localslots_cpp controls how many preprocessors will run in parallel on the local machine. Tuning these values can improve performance. Linking on large projects can take large amounts of memory. Running parallel linkers, which cannot be executed remotely, may force the machine to swap, which reduces performance over just running the jobs in sequence without swapping. Getting the number of parallel preprocessors just right allows you to use larger parallel factors with make, since the local machine now has some 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 .B -j factor may improve performance. .PP The syntax is .PP .nf DISTCC_HOSTS = HOSTSPEC ... HOSTSPEC = LOCAL_HOST | SSH_HOST | TCP_HOST | OLDSTYLE_TCP_HOST | GLOBAL_OPTION | ZEROCONF LOCAL_HOST = localhost[/LIMIT] | --localslots= | --localslots_cpp= SSH_HOST = [USER]@HOSTID[/LIMIT][:COMMAND][OPTIONS] TCP_HOST = HOSTID[:PORT][/LIMIT][OPTIONS] OLDSTYLE_TCP_HOST = HOSTID[/LIMIT][:PORT][OPTIONS] HOSTID = HOSTNAME | IPV4 OPTIONS = ,OPTION[OPTIONS] OPTION = lzo | cpp GLOBAL_OPTION = --randomize ZEROCONF = +zeroconf .fi .PP Here are some individual examples of the syntax: .TP .B localhost The literal word "localhost" is interpreted specially to cause compilations to be directly executed, rather than passed to a daemon on the local machine. If you do want to connect to a daemon on the local machine for testing, then give the machine's IP address or real hostname. (This will be slower.) .TP .B IPV4 A literal IPv4 address, such as .B 10.0.0.1 .TP .B HOSTNAME A hostname to be looked up using the resolver. .TP .B :PORT Connect to a specified decimal port number, rather than the default of 3632. .TP .B @HOSTID Connect to the host over SSH, rather than TCP. Options for the SSH connection can be set in .B ~/.ssh/config .TP .B USER@ Connect to the host over SSH as a specified username. .TP .B :COMMAND Connect over SSH, and use a specified path to find the distccd server. This is normally only needed if for some reason you can't install distccd into a directory on the default PATH for SSH connections. Use this if you get errors like "distccd: command not found" in SSH mode. .TP .B /LIMIT A decimal limit can be added to any host specification to restrict the number of jobs that this client will send to the machine. The limit defaults to four per host (two for localhost), but may be further restricted by the server. You should only need to increase this for servers with more than two processors. .TP .B ,lzo Enables LZO compression for this TCP or SSH host. .TP .B ,cpp Enables distcc-pump mode for this host. Note: the build command must be wrapped in the pump script in order to start the include server. .TP .B --randomize Randomize the order of the host list before execution. .TP .B +zeroconf .B This option is only available if distcc was compiled with Avahi support enabled at configure time. When this special entry is present in the hosts list, distcc will use Avahi Zeroconf DNS Service Discovery (DNS-SD) to locate any available distccd servers on the local network. This avoids the need to explicitly list the host names or IP addresses of the distcc server machines. The distccd servers must have been started with the "--zeroconf" option to distccd. An important caveat is that in the current implementation, pump mode (",cpp") and compression (",lzo") will never be used for hosts located via zeroconf. .PP Here is an example demonstrating some possibilities: .PP .RS .nf .B localhost/2 @bigman/16:/opt/bin/distccd oldmachine:4200/1 .B # cartman is down .B distant/3,lzo .fi .RE .PP Comments are allowed in host specifications. Comments start with a hash/pound sign (\fB#\fP) and run to the end of the line. .PP If a host in the list is not reachable distcc will emit a warning and ignore that host for about one minute. .SH "COMPRESSION" The .B lzo host option specifies that LZO compression should be used for data transfer, including preprocessed source, object code and error messages. Compression is usually economical on networks slower than 100Mbps, but results may vary depending on the network, processors and source tree. .PP Enabling compression makes the distcc client and server use more CPU time, but less network traffic. The added CPU time is insignificant for pump mode. The compression ratio is typically 4:1 for source and 2:1 for object code. .PP Using compression requires both client and server to use at least release 2.9 of distcc. No server configuration is required: the server always responds with compressed replies to compressed requests. .PP Pump mode requires the servers to have the lzo host option on. .SH "SEARCH PATHS" .PP If the compiler name is an absolute path, it is passed verbatim to the server and the compiler is run from that directory. For example: .PP .RS .B distcc /usr/local/bin/gcc-3.1415 -c hello.c .RE .PP If the compiler name is not absolute, or not fully qualified, distccd's PATH is searched. When distcc is run from a masquerade directory, only the base name of the compiler is used. The client's PATH is used only to run the preprocessor and has no effect on the server's path. .SH "TIMEOUTS" .PP Both the distcc client and server impose timeouts on transfer of data across the network. This is intended to detect hosts which are down or unreachable, and to prevent compiles hanging indefinitely if a server is disconnected while in use. If a client-side timeout expires, the job will be re-run locally. .PP The 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 101 Bad arguments. .TP 102 Bind failed. .TP 103 Connect failed. .TP 104 Compiler crashed. .TP 105 Out of memory. .TP 106 Bad Host SPEC .TP 107 I/O Error .TP 108 Truncated. .TP 109 Protocol Error. .TP 110 The given compiler was not found on the remote host. Check that $CC is set appropriately and that it's installed in a directory on the search path for distccd. .TP 111 Recursive call to distcc. .TP 112 Failed to discard privileges. .TP 113 Network access denied. .TP 114 In use by another process. .TP 115 No such file. .TP 116 No hosts defined and fallbacks disabled. .TP 118 Timeout. .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 gcc's .B -MD option can produce output in the wrong directory if the source and object files are in different directories and the .B -MF option is not used. There is no perfect solution because of incompatible changes between gcc versions. Explicitly specifying the dependency output file with .B -MF will fix the problem. .PP TCP mode connections should only be used on trusted networks. .PP Including slow machines in the list of volunteer hosts can slow the build down. .PP When distcc or ccache is used on NFS, the filesystem must be exported with the .B no_subtree_check option to allow reliable renames between directories. .PP The compiler can be invoked with a command line .B gcc hello.c to both compile and link. distcc doesn't split this into separate parts, but rather runs the whole thing locally. .PP distcc-pump mode reverts to plain distcc mode for source files that contain includes with absolute paths (either directly or in an included file). .PP Due to limitations in gcc, gdb may not be able to automatically find the source files for programs built using distcc in some circumstances. The gdb .B directory command can be used. For distcc's plain (non-pump) mode, this is fixed in gcc 3.4 and later. For pump mode, the fix in gcc 3.4 does not suffice; we've worked around the gcc limitation by rewriting the object files that gcc produces, but this is only done for ELF object files, but not for other object file formats. .PP The .o files produced by discc in pump mode will be different from those produced locally: for non-ELF files, the debug information will specify compile directories of the server. The code itself should be identical. .PP For the ELF-format, distcc rewrites the .o files to correct compile directory path information. While the resulting .o files are not bytewise identical to what would have been produced by compiling on the local client (due to different padding, etc), they should be functionally identical. .PP In distcc-pump mode, the include server is unable to handle certain very complicated computed includes as found in parts of the Boost library. The include server will time out and distcc will revert to plain mode. .PP In distcc-pump mode, certain assumptions are made that source and header files do not change during the build. See discussion in section DISTCC DISCREPANCY SYMPTOMS of \fBinclude_server\fR(1(). Other known bugs may be documented on .I http://code.google.com/p/distcc/ .SH "AUTHOR" distcc was written by Martin Pool , with the co-operation of many scholars including Wayne Davison, Frerich Raabe, Dimitri Papadopoulos and others noted in the NEWS file. Please report bugs to . See \fBpump\fR(1) for the authors of pump mode. .SH "LICENCE" You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warrany. A copy of the GPL is included in the file COPYING. .SH "SEE ALSO" \fBdistccd\fR(1), \fBpump\fR(1), \fBinclude_server\fR(1), \fBgcc\fR(1), \fBmake\fR(1), and \fBccache\fR(1). .I http://code.google.com/p/distcc/ .I http://ccache.samba.org/ distcc-3.1/source/man/distccmon-text.10000640000175000017500000000311611115326647016747 0ustar wolffwolff.TH distccmon-text 1 "2 October 2004" .SH "NAME" .LP distccmon\-text \- Displays current compilation jobs in text form. .SH "SYNTAX" .LP distccmon-text [DELAY] .SH "DESCRIPTION" .LP Displays current compilation jobs in text form. distccmon-text must be run on the client machine, with the same setting for .I DISTCC_DIR (or home directory) as the user running the distcc client. .SH "OPTIONS" .LP .TP \fBDELAY\fR repeatedly updates after \fIdelay\fP (fractional) seconds. .SH "OUTPUT FORMAT" .LP The output of distccmon-text contains one line for each job currently being compiled. Each line contains the following columns: .TP .I PID ID of the distcc client process. .TP .I STATE Identifies the phase of operation. In order these may be "Startup", "Blocked", "Connected", "Preprocess", "Conect", "Send", "Receive" and "Done". .TP .I FILE The input filename, if known. .TP .I HOST[SLOT] The compile hostname. May be followed in square brackets by the slot index for that host. .LP When a delay is specified, each block of output is terminated by a blank line. .SH "EXAMPLES" .LP To display currently active jobs (updated every second): .IP distccmon\-text 1 .LP To display the status once: .IP distccmon\-text .SH "AUTHORS" .LP distcc was written by Martin Pool , with the co\-operation of many scholars including Wayne Davison, Frerich Raabe, Dimitri Papadopoulos and others noted in the NEWS file. Please report bugs to . .SH "SEE ALSO" .LP d distccd(1), ccache(1), gcc(1), make(1) http://code.google.com/p/distcc/ http://ccache.samba.org/ distcc-3.1/source/man/include_server.10000640000175000017500000003243011115326647017014 0ustar wolffwolff.TH include_server 1 "9 June 2008" .SH "NAME" include_server.py \- conservative approximation of include dependencies for C/C++ .SH "SYNOPSIS" .B include_server --port .I INCLUDE_SERVER_PORT [OPTIONS] .SH "DESCRIPTION" .P include_server.py starts an include server process. This process answers queries from \fBdistcc\fR(1) clients about what files to include in C/C++ compilations. The include_server.py command itself terminates as soon as the include server has been spawned. .PP The INCLUDE_SERVER_PORT argument is the name of a socket used for all communication between distcc clients and the include server. The \fBpump\fR(1) command is responsible for creating the socket location, for passing it to this script, and for passing it to all distcc clients via the environment variable named INCLUDE_SERVER_PORT. .PP The protocol used by the include server uses distcc's RPC implementation. Each distcc request consists of (1) the current directory and (2) the list of arguments of the compilation command. .PP If the include server is able to process the request, then it answers the distcc client by sending a list of filepaths. The filepaths are those of the compressed source and header files found to be necessary for compilation through include analysis. The list also comprises symbolic links and even dummy files needed for the compilation server to construct an accurate replica of the parts of the filesystem needed for compilation. In this way, a needed header file like /path/foo.h is compressed, renamed, and stored in a temporary location, such as /dev/shm/tmpiAvfGv.include_server-9368-1/path/foo.h.lzo. The distcc client will pass these files on to a compilation server, where they will be uncompressed and mounted temporarily. .PP If the include server is not able to process the request, then it returns the empty list to the distcc client. .P There are two kinds of failures that relate to the include server. The include server may fail to compute the includes or fail in other ways, see section \fBINCLUDE SERVER SYMPTOMS\fR. Also, the compilation on the remove server may fail due to inadequacy of the calculated include closure, but then succeed when locally retried, see section \fBDISTCC DISCREPANCY SYMPTOMS\fR. .SH "OPTION SUMMARY" The following options are understood by include_server.py. .TP .B -dPAT, --debug_pattern=PAT Bit vector for turning on warnings and debugging 1 = warnings 2 = trace some functions other powers of two: see include_server/basics.py. .TP .B -e, --email Send email to 'distcc-pump-errors' or if defined, the value of enviroment variable DISTCC_EMAILLOG_WHOM_TO_BLAME, when include server gets in trouble. The default is to not send email. .TP .B --email_bound NUMBER Maximal number of emails to send (in addition to a final email). Default: 3. .TP .B --no-email Do not send email. This is the default. .TP .B --path_observation_re=RE Issue warning message whenever a filename is resolved to a realpath that is matched by RE, which is a regular expression in Python syntax. This is useful for finding out where files included actually come from. Use RE="" to find them all. Note: warnings must be enabled with at least -d1. .TP .B --pid_file FILEPATH The pid of the include server is written to file FILEPATH. This allows a script such a \fBpump\fR to tear down the include server. .TP .B -s, --statistics Print information to stdout about include analysis. .TP .B --stat_reset_triggers=LIST Flush stat caches when the timestamp of any filepath in LIST changes or the filepath comes in or out of existence. LIST is a colon separated string of filepaths, possibly containing simple globs (as allowed by Python's glob module). Print a warning whenever such a change happens (if warnings are enabled). This option allows limited exceptions to distcc_pump's normal assumption that source files are not modified during the build. .TP .B -t, --time Print elapsed, user, and system time to stderr. .TP .B --unsafe_absolute_includes Do preprocessing on the compilation server even if includes of absolute filepaths are encountered. Normally the include-server will fall back on local preprocessing if it detects any absolute includes. Thus, this flag is useful for preventing such fallbacks when the absolute includes are a false alarm, either because the absolute include is discarded during preprocessing or because the absolutely included file exists on the compilation servers. More precisely, with --unsafe_absolute_includes absolute includes are ignored for the purposes of gathering the include closure. Using this option may lead to incorrect results because (1) the header may actually be included on the compilation server and it may not be the same as on the client, (2) the include directives of the header are not further analyzed. The option is useful for compiling code that has such hardcoded absolute locations of header files inside conditional directives (e.g. "#ifdef") that render the includes irrelevant. More precisely, these includes must be eliminated during preprocessing for the actual configuration. Then the question of existence of the header file is moot and the remote compilation is sound. This is often the case if such includes are meant for unusual configurations different from the actual configuration. .TP .B -v, --verify Verify that files in CPP closure are contained in closure calculated by include processor. .TP .B -w, --write_include_closure Write a .d_approx file which lists all the included files calculated by the include server; with -x, additionally write the included files as calculated by CPP to a .d_exact file. .TP .B -x, --exact_analysis Use CPP instead, do not omit system headers files. .SH "INCLUDE SERVER SYMPTOMS AND ISSUES" The most likely messages and warnings to come from the include processor are listed below. .TP .B "Preprocessing locally. Include server not covering: Couldn't determine default system include directories" To determine the default system header directories, the include server runs the compiler once for each language needed during its session. This message indicates that the compiler specified to distcc is not present on the client. .TP .B Preprocessing locally. Include server not covering: Bailing out because include server spent more than ...s user time handling request In uncommon situations, the include server fails to analyze very complicated macro expressions. The distcc client will use plain distcc mode. .TP .B Warning: Filepath must be relative but isn't The include server does not accept absolute filepaths, such as /usr/include/stdio.h, in include directives, because there is no guarantee that this header on the compilation server machine will be the same as that on the client. The include server gives up analyzing the include closure. The distcc client cannot use pump-mode. To overcome this problem in a not always reliable way, set the environment variable INCLUDE_SERVER_ARGS='--unsafe_absolute_includes' when invoking the pump script to pass the --unsafe_absolute_includes option to the include server. .TP .B Warning: Absolute filepath ... was IGNORED The --unsafe_absolute_includes is in use. This situation happens under the same circumstances as when "Filepath must be relative but isn't" is issued, but in this case the include will provide an answer to the distcc client. .TP .B Warning: Path '/PATH/FILE' changed/came into existence/no longer exists These warnings are issued when using stat reset triggers. Because /PATH/FILE changed, the include server clears its caches; the new version of the file (or the lack of it) renders the include analysis invalid. This message can usually be ignored; it does signify a somewhat precarious use of files by the build system. It is recommended to fix the build system so that files are not rewritten. .TP .B Warning: For translation unit ..., lookup of file ... resolved to ... whose realpath is ... This warning occurs with --path_observation_re when a new realpath matching a source or header file is observed. .SH "DISTCC DISCREPANCY SYMPTOMS" The interactions between the build system, distcc, and the include server is somewhat complex. When a distcc commands receives a failing compilation from the remote server it retries the compilation locally. This section discusses the causes of discrepancies between remote and local compilation. These are flagged by the demotion message: .B __________Warning: ... pump-mode compilation(s) failed on server, .B but succeeded locally. .br .B __________Distcc-pump was demoted to plain mode. .B See the Distcc Discrepancy Symptoms section in the include_server(1) man .B page. The pump script issues this message at the end of the build. This means that for at least one distcc invocation a local compilation succeeded after the remote compilation failed. Each distcc invocation for which such a discrepancy occurred in turn also issues a message such as: .B Warning: remote compilation of '...' failed, .B retried locally and got a different result. The demotion makes subsequent distcc invocations use plain distcc mode. Thus preprocessing will take place on the local machine for the remainder of the build. This technique prevents very slow builds where all compilations end up on the local machine after failing remotely. Of course, if the local compilations fails after the remote failures, then the distcc invocation exits with the non-zero status of the local compilation. The error messages printed are also those of the local compilation. The fallback behavior for distcc-pump mode to local compilation can be disabled by setting the environment variable DISTCC_FALLBACK to 1, which makes the distcc command fail as soon as the remote compilation has failed. This setting is very useful for debugging why the remote compilation went wrong, because now the output from the server will be printed. Next we discuss the possible causes of discrepancies. .TP .B The user changed a source or header file during the build. This yields inconsistent results of course. .TP .B A source or header file changed during the build. The build system rewrites a file. For Linux kernel 2.6, this happens for 'include/linux/compile.h' and 'include/asm/asm-offsets.h'. This condition is fixed by letting the include server know that it must reset its caches when a stat of any of the files changes. Practically, this is done by gathering the files in a colon-separated list and then setting the INCLUDE_SERVER_ARGS command as in: include_server_args="--stat_reset_triggers=include/linux/compile.h:include/asm/asm-offsets.h" .TP .B A header file is potentially included, but does not exist, and is then later included. This occurs when some header foo.h includes another header file trick.h, but the trick.h file has not yet been generated and the inclusion is actually ignored because of preprocessing directives. The include server will probe for the existence of trick.h, because it overapproximates all possible ways directives actually evaluate. The file trick.h is determined not to exist. If it is later generated, and then really included, then the include server will falsely believe that the file still does not exist. The solution to this problem is to make the build system generate trick.h before the first time any header file is included that makes a syntactic reference to trick.h .TP .B The include server was started with \fB--unsafe_absolute_includes\fR. This is a problem if there are header files locally that do not exist remotely and that are actually used. Such includes are often protected by conditional directives that evaluate so that are actually used on only specific and often uncommon platforms. If you are not compiling for such a platform, then it may be correct to use \fB--unsafe_absolute_include\fR. .TP .B The include server has calculated the wrong includes. We do not know of such a situation. .SH "EXIT CODES" The exit code of include_server.py is usually 0. That the include server has been started properly is communicated through the existence of the pid_file. .SH "ENVIRONMENT VARIABLES" .B DISTCC_EMAILLOG_WHOM_TO_BLAME The email address to use for include server automated emails. The default is 'distcc-pump-errors' (which is an email address that probably will not exist in your domain). Additionally, the invocation of the compiler may use additional environment variables. .SH "BUGS" If you think you have found a distcc bug, please see the file .I reporting-bugs.txt in the documentation directory for information on how to report it. .PP In distcc-pump mode, the include server is unable to handle certain very complicated computed includes as found in parts of the Boost library. The include server will time out and distcc will revert to plain mode. .PP Other known bugs may be documented on .I http://code.google.com/p/distcc/ .SH "AUTHOR" The include server was written by Nils Klarlund, with assistance from Fergus Henderson, Manos Renieris, and Craig Silverstein. Please report bugs to . .SH "LICENCE" You are free to use distcc. distcc (including this manual) may be copied, modified or distributed only under the terms of the GNU General Public Licence version 2 or later. distcc comes with absolutely no warrany. A copy of the GPL is included in the file COPYING. .SH "SEE ALSO" \fBdistcc\fR(1), \fBdistccd\fR(1), \fBinclude_server\fR(1), and \fBgcc\fR(1). http://code.google.com/p/distcc/ http://ccache.samba.org/ distcc-3.1/source/popt/0000750000175000017500000000000011115327755014126 5ustar wolffwolffdistcc-3.1/source/popt/README.popt0000640000175000017500000000106611115326636015770 0ustar wolffwolffThis is a perfectly ordinary copy of libpopt 1.7, except that the configure scripts have been munged to make them fit with distcc. NLS support has been removed, because distcc currently does not use it. It is only used on platforms that do not have a sufficiently up-to-date copy of their own. If you build distcc on a platform which has popt, this directory should not be used. (You can control that using the --with-included-popt configure flag.) popt has no apparent home page, but the source can be retrieved from ftp://ftp.rpm.org/pub/rpm/dist/rpm-4.1.xdistcc-3.1/source/popt/system.h0000640000175000017500000000316711115326636015630 0ustar wolffwolff#ifdef HAVE_CONFIG_H #include #endif #if defined (__GLIBC__) && defined(__LCLINT__) /*@-declundef@*/ /*@unchecked@*/ extern __const __int32_t *__ctype_tolower; /*@unchecked@*/ extern __const __int32_t *__ctype_toupper; /*@=declundef@*/ #endif #include #include #include #include #if HAVE_MCHECK_H #include #endif #include #include #include #if HAVE_UNISTD_H #include #endif #ifdef __NeXT /* access macros are not declared in non posix mode in unistd.h - don't try to use posix on NeXTstep 3.3 ! */ #include #endif #if defined(__LCLINT__) /*@-declundef -incondefs -redecl@*/ /* LCL: missing annotation */ /*@only@*/ void * alloca (size_t __size) /*@ensures MaxSet(result) == (__size - 1) @*/ /*@*/; /*@=declundef =incondefs =redecl@*/ #endif /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ # if HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif #elif defined(__GNUC__) && defined(__STRICT_ANSI__) #define alloca __builtin_alloca #endif /*@-redecl -redef@*/ /*@mayexit@*/ /*@only@*/ char * xstrdup (const char *str) /*@*/; /*@=redecl =redef@*/ #if HAVE_MCHECK_H && defined(__GNUC__) #define vmefail() (fprintf(stderr, "virtual memory exhausted.\n"), exit(EXIT_FAILURE), NULL) #define xstrdup(_str) (strcpy((malloc(strlen(_str)+1) ? : vmefail()), (_str))) #else #define xstrdup(_str) strdup(_str) #endif /* HAVE_MCHECK_H && defined(__GNUC__) */ #include "popt.h" distcc-3.1/source/popt/popthelp.c0000640000175000017500000004634311115326636016135 0ustar wolffwolff/* -*- 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@*/ distcc-3.1/source/popt/poptparse.c0000640000175000017500000001213511115326636016307 0ustar wolffwolff/** \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; } distcc-3.1/source/popt/findme.c0000640000175000017500000000221411115326636015531 0ustar wolffwolff/** \ingroup popt * \file popt/findme.c */ /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #include "system.h" #include "findme.h" const char * findProgramPath(const char * argv0) { char * path = getenv("PATH"); char * pathbuf; char * start, * chptr; char * buf; if (argv0 == NULL) return NULL; /* XXX can't happen */ /* If there is a / in the argv[0], it has to be an absolute path */ if (strchr(argv0, '/')) return xstrdup(argv0); if (path == NULL) return NULL; start = pathbuf = alloca(strlen(path) + 1); buf = malloc(strlen(path) + strlen(argv0) + sizeof("/")); if (buf == NULL) return NULL; /* XXX can't happen */ strcpy(pathbuf, path); chptr = NULL; /*@-branchstate@*/ do { if ((chptr = strchr(start, ':'))) *chptr = '\0'; sprintf(buf, "%s/%s", start, argv0); if (!access(buf, X_OK)) return buf; if (chptr) start = chptr + 1; else start = NULL; } while (start && *start); /*@=branchstate@*/ free(buf); return NULL; } distcc-3.1/source/popt/poptint.h0000640000175000017500000000532711115326636016001 0ustar wolffwolff/** \ingroup popt * \file popt/poptint.h */ /* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #ifndef H_POPTINT #define H_POPTINT /** * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL. * @param p memory to free * @retval NULL always */ /*@unused@*/ static inline /*@null@*/ void * _free(/*@only@*/ /*@null@*/ const void * p) /*@modifies p @*/ { if (p != NULL) free((void *)p); return NULL; } /* Bit mask macros. */ /*@-exporttype -redef @*/ typedef unsigned int __pbm_bits; /*@=exporttype =redef @*/ #define __PBM_NBITS (8 * sizeof (__pbm_bits)) #define __PBM_IX(d) ((d) / __PBM_NBITS) #define __PBM_MASK(d) ((__pbm_bits) 1 << (((unsigned)(d)) % __PBM_NBITS)) /*@-exporttype -redef @*/ typedef struct { __pbm_bits bits[1]; } pbm_set; /*@=exporttype =redef @*/ #define __PBM_BITS(set) ((set)->bits) #define PBM_ALLOC(d) calloc(__PBM_IX (d) + 1, sizeof(__pbm_bits)) #define PBM_FREE(s) _free(s); #define PBM_SET(d, s) (__PBM_BITS (s)[__PBM_IX (d)] |= __PBM_MASK (d)) #define PBM_CLR(d, s) (__PBM_BITS (s)[__PBM_IX (d)] &= ~__PBM_MASK (d)) #define PBM_ISSET(d, s) ((__PBM_BITS (s)[__PBM_IX (d)] & __PBM_MASK (d)) != 0) struct optionStackEntry { int argc; /*@only@*/ /*@null@*/ const char ** argv; /*@only@*/ /*@null@*/ pbm_set * argb; int next; /*@only@*/ /*@null@*/ const char * nextArg; /*@observer@*/ /*@null@*/ const char * nextCharArg; /*@dependent@*/ /*@null@*/ poptItem currAlias; int stuffed; }; struct poptContext_s { struct optionStackEntry optionStack[POPT_OPTION_DEPTH]; /*@dependent@*/ struct optionStackEntry * os; /*@owned@*/ /*@null@*/ const char ** leftovers; int numLeftovers; int nextLeftover; /*@keep@*/ const struct poptOption * options; int restLeftover; /*@only@*/ /*@null@*/ const char * appName; /*@only@*/ /*@null@*/ poptItem aliases; int numAliases; int flags; /*@owned@*/ /*@null@*/ poptItem execs; int numExecs; /*@only@*/ /*@null@*/ const char ** finalArgv; int finalArgvCount; int finalArgvAlloced; /*@dependent@*/ /*@null@*/ poptItem doExec; /*@only@*/ const char * execPath; int execAbsolute; /*@only@*/ const char * otherHelp; /*@null@*/ pbm_set * arg_strip; }; #ifdef HAVE_LIBINTL_H #include #endif #if defined(HAVE_GETTEXT) && !defined(__LCLINT__) #define _(foo) gettext(foo) #else #define _(foo) foo #endif #if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__) #define D_(dom, str) dgettext(dom, str) #define POPT_(foo) D_("popt", foo) #else #define D_(dom, str) str #define POPT_(foo) foo #endif #define N_(foo) foo #endif distcc-3.1/source/popt/poptconfig.c0000640000175000017500000001110211115326636016433 0ustar wolffwolff/** \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; } distcc-3.1/source/popt/popt.c0000640000175000017500000010230611115326636015254 0ustar wolffwolff/** \ingroup popt * \file popt/popt.c */ /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist */ #undef MYDEBUG #include "system.h" #if HAVE_FLOAT_H #include #endif #include #include "findme.h" #include "poptint.h" #ifdef MYDEBUG /*@unchecked@*/ int _popt_debug = 0; #endif #ifndef HAVE_STRERROR static char * strerror(int errno) { extern int sys_nerr; extern char * sys_errlist[]; if ((0 <= errno) && (errno < sys_nerr)) return sys_errlist[errno]; else return POPT_("unknown errno"); } #endif #ifdef MYDEBUG /*@unused@*/ static void prtcon(const char *msg, poptContext con) { if (msg) fprintf(stderr, "%s", msg); fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n", con, con->os, (con->os->nextCharArg ? con->os->nextCharArg : ""), (con->os->nextArg ? con->os->nextArg : ""), con->os->next, (con->os->argv && con->os->argv[con->os->next] ? con->os->argv[con->os->next] : "")); } #endif void poptSetExecPath(poptContext con, const char * path, int allowAbsolute) { con->execPath = _free(con->execPath); con->execPath = xstrdup(path); con->execAbsolute = allowAbsolute; /*@-nullstate@*/ /* LCL: con->execPath can be NULL? */ return; /*@=nullstate@*/ } static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt) /*@globals internalState@*/ /*@modifies internalState@*/ { if (opt != NULL) for (; opt->longName || opt->shortName || opt->arg; opt++) { if (opt->arg == NULL) continue; /* XXX program error. */ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { /* Recurse on included sub-tables. */ invokeCallbacksPRE(con, opt->arg); } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && (opt->argInfo & POPT_CBFLAG_PRE)) { /*@-castfcnptr@*/ poptCallbackType cb = (poptCallbackType)opt->arg; /*@=castfcnptr@*/ /* Perform callback. */ /*@-moduncon -noeffectuncon @*/ cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip); /*@=moduncon =noeffectuncon @*/ } } } static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt) /*@globals internalState@*/ /*@modifies internalState@*/ { if (opt != NULL) for (; opt->longName || opt->shortName || opt->arg; opt++) { if (opt->arg == NULL) continue; /* XXX program error. */ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { /* Recurse on included sub-tables. */ invokeCallbacksPOST(con, opt->arg); } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && (opt->argInfo & POPT_CBFLAG_POST)) { /*@-castfcnptr@*/ poptCallbackType cb = (poptCallbackType)opt->arg; /*@=castfcnptr@*/ /* Perform callback. */ /*@-moduncon -noeffectuncon @*/ cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip); /*@=moduncon =noeffectuncon @*/ } } } static void invokeCallbacksOPTION(poptContext con, const struct poptOption * opt, const struct poptOption * myOpt, /*@null@*/ const void * myData, int shorty) /*@globals internalState@*/ /*@modifies internalState@*/ { const struct poptOption * cbopt = NULL; if (opt != NULL) for (; opt->longName || opt->shortName || opt->arg; opt++) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { /* Recurse on included sub-tables. */ if (opt->arg != NULL) /* XXX program error */ invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty); } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK && !(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) { /* Save callback info. */ cbopt = opt; } else if (cbopt != NULL && ((myOpt->shortName && opt->shortName && shorty && myOpt->shortName == opt->shortName) || (myOpt->longName && opt->longName && /*@-nullpass@*/ /* LCL: opt->longName != NULL */ !strcmp(myOpt->longName, opt->longName))) /*@=nullpass@*/ ) { /*@-castfcnptr@*/ poptCallbackType cb = (poptCallbackType)cbopt->arg; /*@=castfcnptr@*/ const void * cbData = (cbopt->descrip ? cbopt->descrip : myData); /* Perform callback. */ if (cb != NULL) { /* XXX program error */ /*@-moduncon -noeffectuncon @*/ cb(con, POPT_CALLBACK_REASON_OPTION, myOpt, con->os->nextArg, cbData); /*@=moduncon =noeffectuncon @*/ } /* Terminate (unless explcitly continuing). */ if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE)) return; } } } poptContext poptGetContext(const char * name, int argc, const char ** argv, const struct poptOption * options, int flags) { poptContext con = malloc(sizeof(*con)); if (con == NULL) return NULL; /* XXX can't happen */ memset(con, 0, sizeof(*con)); con->os = con->optionStack; con->os->argc = argc; /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */ con->os->argv = argv; /*@=dependenttrans =assignexpose@*/ con->os->argb = NULL; if (!(flags & POPT_CONTEXT_KEEP_FIRST)) con->os->next = 1; /* skip argv[0] */ con->leftovers = calloc( (argc + 1), sizeof(*con->leftovers) ); /*@-dependenttrans -assignexpose@*/ /* FIX: W2DO? */ con->options = options; /*@=dependenttrans =assignexpose@*/ con->aliases = NULL; con->numAliases = 0; con->flags = flags; con->execs = NULL; con->numExecs = 0; con->finalArgvAlloced = argc * 2; con->finalArgv = calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) ); con->execAbsolute = 1; con->arg_strip = NULL; if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER")) con->flags |= POPT_CONTEXT_POSIXMEHARDER; if (name) { char * t = malloc(strlen(name) + 1); if (t) con->appName = strcpy(t, name); } /*@-internalglobs@*/ invokeCallbacksPRE(con, con->options); /*@=internalglobs@*/ return con; } static void cleanOSE(/*@special@*/ struct optionStackEntry *os) /*@uses os @*/ /*@releases os->nextArg, os->argv, os->argb @*/ /*@modifies os @*/ { os->nextArg = _free(os->nextArg); os->argv = _free(os->argv); os->argb = PBM_FREE(os->argb); } /*@-boundswrite@*/ void poptResetContext(poptContext con) { int i; if (con == NULL) return; while (con->os > con->optionStack) { cleanOSE(con->os--); } con->os->argb = PBM_FREE(con->os->argb); con->os->currAlias = NULL; con->os->nextCharArg = NULL; con->os->nextArg = NULL; con->os->next = 1; /* skip argv[0] */ con->numLeftovers = 0; con->nextLeftover = 0; con->restLeftover = 0; con->doExec = NULL; if (con->finalArgv != NULL) for (i = 0; i < con->finalArgvCount; i++) { /*@-unqualifiedtrans@*/ /* FIX: typedef double indirection. */ con->finalArgv[i] = _free(con->finalArgv[i]); /*@=unqualifiedtrans@*/ } con->finalArgvCount = 0; con->arg_strip = PBM_FREE(con->arg_strip); /*@-nullstate@*/ /* FIX: con->finalArgv != NULL */ return; /*@=nullstate@*/ } /*@=boundswrite@*/ /* Only one of longName, shortName should be set, not both. */ /*@-boundswrite@*/ static int handleExec(/*@special@*/ poptContext con, /*@null@*/ const char * longName, char shortName) /*@uses con->execs, con->numExecs, con->flags, con->doExec, con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/ /*@modifies con @*/ { poptItem item; int i; if (con->execs == NULL || con->numExecs <= 0) /* XXX can't happen */ return 0; for (i = con->numExecs - 1; i >= 0; i--) { item = con->execs + i; if (longName && !(item->option.longName && !strcmp(longName, item->option.longName))) continue; else if (shortName != item->option.shortName) continue; break; } if (i < 0) return 0; if (con->flags & POPT_CONTEXT_NO_EXEC) return 1; if (con->doExec == NULL) { con->doExec = con->execs + i; return 1; } /* We already have an exec to do; remember this option for next time 'round */ if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) { con->finalArgvAlloced += 10; con->finalArgv = realloc(con->finalArgv, sizeof(*con->finalArgv) * con->finalArgvAlloced); } i = con->finalArgvCount++; if (con->finalArgv != NULL) /* XXX can't happen */ { char *s = malloc((longName ? strlen(longName) : 0) + 3); if (s != NULL) { /* XXX can't happen */ if (longName) sprintf(s, "--%s", longName); else sprintf(s, "-%c", shortName); con->finalArgv[i] = s; } else con->finalArgv[i] = NULL; } /*@-nullstate@*/ /* FIX: con->finalArgv[] == NULL */ return 1; /*@=nullstate@*/ } /*@=boundswrite@*/ /* Only one of longName, shortName may be set at a time */ static int handleAlias(/*@special@*/ poptContext con, /*@null@*/ const char * longName, char shortName, /*@exposed@*/ /*@null@*/ const char * nextCharArg) /*@uses con->aliases, con->numAliases, con->optionStack, con->os, con->os->currAlias, con->os->currAlias->option.longName @*/ /*@modifies con @*/ { poptItem item = con->os->currAlias; int rc; int i; if (item) { if (longName && (item->option.longName && !strcmp(longName, item->option.longName))) return 0; if (shortName && shortName == item->option.shortName) return 0; } if (con->aliases == NULL || con->numAliases <= 0) /* XXX can't happen */ return 0; for (i = con->numAliases - 1; i >= 0; i--) { item = con->aliases + i; if (longName && !(item->option.longName && !strcmp(longName, item->option.longName))) continue; else if (shortName != item->option.shortName) continue; break; } if (i < 0) return 0; if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH) return POPT_ERROR_OPTSTOODEEP; /*@-boundsread@*/ if (nextCharArg && *nextCharArg) con->os->nextCharArg = nextCharArg; /*@=boundsread@*/ con->os++; con->os->next = 0; con->os->stuffed = 0; con->os->nextArg = NULL; con->os->nextCharArg = NULL; con->os->currAlias = con->aliases + i; rc = poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv, &con->os->argc, &con->os->argv); con->os->argb = NULL; return (rc ? rc : 1); } /*@-bounds -boundswrite @*/ static int execCommand(poptContext con) /*@globals internalState @*/ /*@modifies internalState @*/ { poptItem item = con->doExec; const char ** argv; int argc = 0; int rc; if (item == NULL) /*XXX can't happen*/ return POPT_ERROR_NOARG; if (item->argv == NULL || item->argc < 1 || (!con->execAbsolute && strchr(item->argv[0], '/'))) return POPT_ERROR_NOARG; argv = malloc(sizeof(*argv) * (6 + item->argc + con->numLeftovers + con->finalArgvCount)); if (argv == NULL) return POPT_ERROR_MALLOC; /* XXX can't happen */ if (!strchr(item->argv[0], '/') && con->execPath) { char *s = alloca(strlen(con->execPath) + strlen(item->argv[0]) + sizeof("/")); sprintf(s, "%s/%s", con->execPath, item->argv[0]); argv[argc] = s; } else { argv[argc] = findProgramPath(item->argv[0]); } if (argv[argc++] == NULL) return POPT_ERROR_NOARG; if (item->argc > 1) { memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1)); argc += (item->argc - 1); } if (con->finalArgv != NULL && con->finalArgvCount > 0) { memcpy(argv + argc, con->finalArgv, sizeof(*argv) * con->finalArgvCount); argc += con->finalArgvCount; } if (con->leftovers != NULL && con->numLeftovers > 0) { #if 0 argv[argc++] = "--"; #endif memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers); argc += con->numLeftovers; } argv[argc] = NULL; #ifdef __hpux rc = setresuid(getuid(), getuid(),-1); if (rc) return POPT_ERROR_ERRNO; #else /* * XXX " ... on BSD systems setuid() should be preferred over setreuid()" * XXX sez' Timur Bakeyev * XXX from Norbert Warmuth */ #if defined(HAVE_SETUID) rc = setuid(getuid()); if (rc) return POPT_ERROR_ERRNO; #elif defined (HAVE_SETREUID) rc = setreuid(getuid(), getuid()); /*hlauer: not portable to hpux9.01 */ if (rc) return POPT_ERROR_ERRNO; #else ; /* Can't drop privileges */ #endif #endif if (argv[0] == NULL) return POPT_ERROR_NOARG; #ifdef MYDEBUG if (_popt_debug) { const char ** avp; fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc); for (avp = argv; *avp; avp++) fprintf(stderr, " '%s'", *avp); fprintf(stderr, "\n"); } #endif rc = execvp(argv[0], (char *const *)argv); return POPT_ERROR_ERRNO; } /*@=bounds =boundswrite @*/ /*@-boundswrite@*/ /*@observer@*/ /*@null@*/ static const struct poptOption * findOption(const struct poptOption * opt, /*@null@*/ const char * longName, char shortName, /*@null@*/ /*@out@*/ poptCallbackType * callback, /*@null@*/ /*@out@*/ const void ** callbackData, int singleDash) /*@modifies *callback, *callbackData */ { const struct poptOption * cb = NULL; /* This happens when a single - is given */ if (singleDash && !shortName && (longName && *longName == '\0')) shortName = '-'; for (; opt->longName || opt->shortName || opt->arg; opt++) { if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { const struct poptOption * opt2; /* Recurse on included sub-tables. */ if (opt->arg == NULL) continue; /* XXX program error */ opt2 = findOption(opt->arg, longName, shortName, callback, callbackData, singleDash); if (opt2 == NULL) continue; /* Sub-table data will be inheirited if no data yet. */ if (!(callback && *callback)) return opt2; if (!(callbackData && *callbackData == NULL)) return opt2; /*@-observertrans -dependenttrans @*/ *callbackData = opt->descrip; /*@=observertrans =dependenttrans @*/ return opt2; } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) { cb = opt; } else if (longName && opt->longName && (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) && /*@-nullpass@*/ /* LCL: opt->longName != NULL */ !strcmp(longName, opt->longName)) /*@=nullpass@*/ { break; } else if (shortName && shortName == opt->shortName) { break; } } if (!opt->longName && !opt->shortName) return NULL; /*@-modobserver -mods @*/ if (callback) *callback = NULL; if (callbackData) *callbackData = NULL; if (cb) { if (callback) /*@-castfcnptr@*/ *callback = (poptCallbackType)cb->arg; /*@=castfcnptr@*/ if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) { if (callbackData) /*@-observertrans@*/ /* FIX: typedef double indirection. */ *callbackData = cb->descrip; /*@=observertrans@*/ } } /*@=modobserver =mods @*/ return opt; } /*@=boundswrite@*/ static const char * findNextArg(/*@special@*/ poptContext con, unsigned argx, int delete_arg) /*@uses con->optionStack, con->os, con->os->next, con->os->argb, con->os->argc, con->os->argv @*/ /*@modifies con @*/ { struct optionStackEntry * os = con->os; const char * arg; do { int i; arg = NULL; while (os->next == os->argc && os > con->optionStack) os--; if (os->next == os->argc && os == con->optionStack) break; if (os->argv != NULL) for (i = os->next; i < os->argc; i++) { /*@-sizeoftype@*/ if (os->argb && PBM_ISSET(i, os->argb)) /*@innercontinue@*/ continue; if (*os->argv[i] == '-') /*@innercontinue@*/ continue; if (--argx > 0) /*@innercontinue@*/ continue; arg = os->argv[i]; if (delete_arg) { if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc); if (os->argb != NULL) /* XXX can't happen */ PBM_SET(i, os->argb); } /*@innerbreak@*/ break; /*@=sizeoftype@*/ } if (os > con->optionStack) os--; } while (arg == NULL); return arg; } /*@-boundswrite@*/ static /*@only@*/ /*@null@*/ const char * expandNextArg(/*@special@*/ poptContext con, const char * s) /*@uses con->optionStack, con->os, con->os->next, con->os->argb, con->os->argc, con->os->argv @*/ /*@modifies con @*/ { const char * a = NULL; size_t alen; char *t, *te; size_t tn = strlen(s) + 1; char c; te = t = malloc(tn);; if (t == NULL) return NULL; /* XXX can't happen */ while ((c = *s++) != '\0') { switch (c) { #if 0 /* XXX can't do this */ case '\\': /* escape */ c = *s++; /*@switchbreak@*/ break; #endif case '!': if (!(s[0] == '#' && s[1] == ':' && s[2] == '+')) /*@switchbreak@*/ break; /* XXX Make sure that findNextArg deletes only next arg. */ if (a == NULL) { if ((a = findNextArg(con, 1, 1)) == NULL) /*@switchbreak@*/ break; } s += 3; alen = strlen(a); tn += alen; *te = '\0'; t = realloc(t, tn); te = t + strlen(t); 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@*/ distcc-3.1/source/popt/.stamp-conf.in0000640000175000017500000000007311115326636016601 0ustar wolffwolff## Force popt directory to be created in build directory. distcc-3.1/source/popt/findme.h0000640000175000017500000000077011115326636015543 0ustar wolffwolff/** \ingroup popt * \file popt/findme.h */ /* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #ifndef H_FINDME #define H_FINDME /** * Return absolute path to executable by searching PATH. * @param argv0 name of executable * @return (malloc'd) absolute path to executable (or NULL) */ /*@null@*/ const char * findProgramPath(/*@null@*/ const char * argv0) /*@*/; #endif distcc-3.1/source/popt/popt.h0000640000175000017500000003715011115326636015265 0ustar wolffwolff/** \file popt/popt.h * \ingroup popt */ /* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #ifndef H_POPT #define H_POPT #include /* for FILE * */ #define POPT_OPTION_DEPTH 10 /** \ingroup popt * \name Arg type identifiers */ /*@{*/ #define POPT_ARG_NONE 0 /*!< no arg */ #define POPT_ARG_STRING 1 /*!< arg will be saved as string */ #define POPT_ARG_INT 2 /*!< arg will be converted to int */ #define POPT_ARG_LONG 3 /*!< arg will be converted to long */ #define POPT_ARG_INCLUDE_TABLE 4 /*!< arg points to table */ #define POPT_ARG_CALLBACK 5 /*!< table-wide callback... must be set first in table; arg points to callback, descrip points to callback data to pass */ #define POPT_ARG_INTL_DOMAIN 6 /*!< set the translation domain for this table and any included tables; arg points to the domain string */ #define POPT_ARG_VAL 7 /*!< arg should take value val */ #define POPT_ARG_FLOAT 8 /*!< arg will be converted to float */ #define POPT_ARG_DOUBLE 9 /*!< arg will be converted to double */ #define POPT_ARG_MASK 0x0000FFFF /*@}*/ /** \ingroup popt * \name Arg modifiers */ /*@{*/ #define POPT_ARGFLAG_ONEDASH 0x80000000 /*!< allow -longoption */ #define POPT_ARGFLAG_DOC_HIDDEN 0x40000000 /*!< don't show in help/usage */ #define POPT_ARGFLAG_STRIP 0x20000000 /*!< strip this arg from argv(only applies to long args) */ #define POPT_ARGFLAG_OPTIONAL 0x10000000 /*!< arg may be missing */ #define POPT_ARGFLAG_OR 0x08000000 /*!< arg will be or'ed */ #define POPT_ARGFLAG_NOR 0x09000000 /*!< arg will be nor'ed */ #define POPT_ARGFLAG_AND 0x04000000 /*!< arg will be and'ed */ #define POPT_ARGFLAG_NAND 0x05000000 /*!< arg will be nand'ed */ #define POPT_ARGFLAG_XOR 0x02000000 /*!< arg will be xor'ed */ #define POPT_ARGFLAG_NOT 0x01000000 /*!< arg will be negated */ #define POPT_ARGFLAG_LOGICALOPS \ (POPT_ARGFLAG_OR|POPT_ARGFLAG_AND|POPT_ARGFLAG_XOR) #define POPT_BIT_SET (POPT_ARG_VAL|POPT_ARGFLAG_OR) /*!< set arg bit(s) */ #define POPT_BIT_CLR (POPT_ARG_VAL|POPT_ARGFLAG_NAND) /*!< clear arg bit(s) */ #define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000 /*!< show default value in --help */ /*@}*/ /** \ingroup popt * \name Callback modifiers */ /*@{*/ #define POPT_CBFLAG_PRE 0x80000000 /*!< call the callback before parse */ #define POPT_CBFLAG_POST 0x40000000 /*!< call the callback after parse */ #define POPT_CBFLAG_INC_DATA 0x20000000 /*!< use data from the include line, not the subtable */ #define POPT_CBFLAG_SKIPOPTION 0x10000000 /*!< don't callback with option */ #define POPT_CBFLAG_CONTINUE 0x08000000 /*!< continue callbacks with option */ /*@}*/ /** \ingroup popt * \name Error return values */ /*@{*/ #define POPT_ERROR_NOARG -10 /*!< missing argument */ #define POPT_ERROR_BADOPT -11 /*!< unknown option */ #define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */ #define POPT_ERROR_BADQUOTE -15 /*!< error in 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 distcc-3.1/source/NEWS0000640000175000017500000020512511115326647013650 0ustar wolffwolffdistcc-3.1 "Humming along" 2008-11-21 FEATURES: * New "--scan-includes" option to distcc. This shows which headers distcc would send to the remote machine in pump mode, without actually compiling anything. This provides a simple interface to the include server. * New "--disable-Werror" option to configure. This disables the use of gcc's -Werror option when building distcc, allowing compilation of distcc to succeed even if gcc issues warnings. DOCUMENTATION: * Document all of the exit codes in the man page (Carsten Wolff , via Debian). BUG FIXES: * Handle "-Wp,-MMD,...". * Report a better error message if a host specification contains ",cpp" but not ",lzo". * Fix a bug where the "m4" directory wasn't included in the source distribution tarball, which caused it to stop working if you ran autogen.sh. PORTABILITY: * Fixed a bug where the pump script was hard-coding /etc/distcc/hosts rather than using the prefix specified to configure. * Fixed build errors on Gentoo Linux and some other systems (Matsuu Takuto). distcc-3.0 "The moment has arrived" 2008-08-06 DOCUMENTATION: * Minor improvements to the man pages. distcc-3.0rc4 "Pump up the volume" 2008-08-04 BUG FIXES: * Fixed a bug in 3.0rc3 that broke pump mode for C++ compilations that use -I options that refer to a subdirectory of one of the default system include directories, e.g. -I/usr/include/foo. distcc-3.0rc3 "Third time lucky?" 2008-07-31 FEATURES: * New "--without-avahi" option to configure (Lei Zhang). BUG FIXES: * Fixed a problem where pump mode was falling back to local compilation when compiling with -I options that refer to a subdirectory of one of the default system include directories (Nils Klarlund, Fergus Henderson). * Allow distcc to distribute commands that use "-MF" rather than "-MF ", and likewise for "-MT". PORTABILITY: * Fixed a build problem on ARM and Solaris systems. * Fixed a build problem on some Linux systems reported by Daisuke Nishikawa. * Fixed failure of "make install" on Cygwin. distcc-3.0rc2 "Anti-aliasing." 2008-06-19 BUG FIXES: * Fallback to local compilation for "-march=native" or "mtune=native" (Maks Verver). * Fix for deadlock in pump mode. distcc-3.0rc1 "My prices are insane." 2008-06-09 FEATURES: * New protocol, version 3, allowing for preprocessing on distcc servers ("pump" mode). * New component: an include server for incremental static analysis of include dependencies. This software is written in Python 2.4. * Support for getting hosts via avahi (Lennart Poettering) BUG FIXES: * gcc debug option -d must be run locally because it produces secondary files. Reported by Nadim Khemir. * Improved checking for errors on socket connection. Patch from Dan Kegel. PORTABILITY: * "Pump" code tested under Linux only. Processing of object code rewrites debug info (so server paths are replaced with client paths), but this works for ELF code only. * Fix failure of 'make maintainer-check' in non-English locales. (Niklaus Giger) * Locks taken through F_SETLK or lockf() must be explicitly released, because closing the file does not do so. (Sascha Demetrio) * Use python2.4 if available. * Execute compiler with correctly redirected output using win32 apis on Cygwin/Mingw. Place temporary files using GetTempPath. (Alex Besogonov) * Make distccmon-gnome link properly with gnu ld's new --as-needed flag. (Ben Skeggs, Lisa Seelye) OTHER CHANGES: * New web site: . * New repository: . * New maintainer: Fergus Henderson. distcc-2.18.3 "Porsche safari" 2004-11-30 BUG FIXES: * Fix for incorrect handling of -x and -specs from Michal Welnicki. TESTS: * Fix false pass in tests for -x and -specs. distcc-2.18.2 "Bees and lavender" 2004-11-12 BUG FIXES: * Fix problem in checking errno after connect(). Fix by Jean Delvare and Dan Kegel. PORTABILITY: * Fix prototype problem causing build failure on amd64. Patch from Andreas Jochens. (Debian #280399, #280644). distcc-2.18.1 "Reality-based computing" 2004-11-03 BUG FIXES: * Fix run-time warnings about gtk_tree_model_row_changed() when built with recent versions of GTK+. * gcc option -specs= must be run locally so that it can read the local spec file. Reported by Chris Yeoh. PORTABILITY: * Fix Solaris build problem reported by Dimitri Papadopoulos. * Fix problem with reading hosts files in DOS CRLF format. Reported by Sebastien Perochon. distcc-2.18 "Billionaires on stilts" 2004-10-12 BUG FIXES: * Fix longjmp() bug that can cause distcc to crash when a timeout elapses. * Fix compile-time problem with dcc_trace when configured with --enable-rfc2553. Reported by Greg Earle. * Fix warning about warn_unused_result for older versions of gcc. * No timeout on local preprocessing or on compilation. No timeouts on DNS lookups other than whatever is built in to the DNS resolver. There are timeouts on network transmission and on opening connections. * Remove mmap() for receive of uncompressed data, to avoid various problems. CHANGES: * The --allow option is now mandatory for daemon mode. As a security feature, distccd will refuse to run without an IP access control list. * conftest.* built by autoconf is always done locally, to make configure tests faster and safer. DOCUMENTATION: * Better description of use with ccache. PORTABILITY: * Fix various warnings reported by Dimitri Papadopoulos. * Fix Tru64 build problem reported by Gary V. Vaughan. distcc-2.17 "Divers Alarums" 2004-07-31 FEATURES: * Performance improvements for distccmon-gnome. * Added timeous for connection to servers, transmission of jobs and remote compilation. If the timeout expires, the job is run locally. This should make distcc cope better if some or all of the servers are unreachable or failing. * Also add timeouts in server to kick out stalled or disconnected clients. BUG FIXES: * If remote compilation fails because of a signal in a later phase of the compilation causing an exit with code >=128, retry compilation locally. Patch from Jakub Stachowski. DOCUMENTATION: * Manpage fix from Jean Delvare. PORTABILITY: * Cygwin portability fix for WCOREDUMP, reported by Eric Frias. distcc-2.16 "Salt" 2004-07-08 SECURITY: * Fix bug that might cause IP-based access control rules not to be interpreted correctly on 64-bit platforms. (CAN-2004-0601) BUG FIXES: * Fix small memory leaks in distccmon-gnome and distccmon-text. FEATURES: * Use a GNOME status bar with a grab handle for distccmon-gnome. Patch from Nathan Fredrickson. PORTABILITY: * Better detection of systems with a popt library installed but no popt.h. Reported by Sean Kelly. * Fix bug in reporting crashed daemon children that showed up on systems without strsignal, such as Mac OS 10.2. Reported by Benjamin Reed. * Update testdistcc.py to work on ia64 linux. INTERNAL: * Simplify dcc_log_child_exited. * Include copyright and licence in --version output, as suggested by GNU programs. distcc-2.15 "feel good for ten seconds" 2004-07-06 BUG FIXES: * Fix crash bug in receiving LZO compressed data into a mmapped file. Reported by Arkadiusz Miskiewicz. * Remove redundant temporary file cleanup in non-forking mode. FEATURES: * Client calculates and can display the overall throughput in preprocessed bytes per second for remote jobs. REMOVALS: * The deprecated fork-after-exec mode controlled by the --no-prefork option has been removed. * mmap is no longer used for compressed data to simplify the code. PORTABILITY: * Additional fixes to Red Hat / Fedora scripts, by Colins Walters. INTERNAL: * Daemon now chdirs to $TMPDIR at startup rather than /. This allows dumping core, among other things. distcc-2.14 "Lake Albina" 2004-05-02 FEATURES: * The host file is looked up in $DISTCC_DIR/hosts, not hardcoded to ~/.distcc/hosts. The default for $DISTCC_DIR is still ~/.distcc. Suggested by Sebastien Perochon. * Source file name is included in success/failure messages, e.g. distcc[6655] ERROR: compile ./cases/bad.c on cardhu failed * distcc can now be built with a build directory separate from the source directory. Patch from Dennis Henriksen. * Added --randomize option to host list to help spread the load across large shared clusters. From patch by Google (Josh Hyman ). DOCUMENTATION: * Add documentation of DISTCC_DIR, and other fixes. Patch from Thomas Schwinge. * Slightly improved distcc --help. BUG FIXES: * Decompression buffer can dynamically resize to allow for very gassy files. From a patch by Joe Buehler. PORTABILITY: * Add sample scripts for Red Hat / Fedora, by Colin Walters. * mmap is always disabled on HP-UX, because the inconsistent page case is a bit dangerous for the way distcc uses mmap. Suggested by Joe Buehler. distcc-2.13 "Carnal Bunt" 2004-03-02 SECURITY: * Enforce IPv4 access control lists when the daemon is listening on an IPv6 port. This only applies when the server was compiled using --enable-rfc2553 and run with --allow. FEATURES: * Hash comments are allowed in host list files. INTERNAL: * Use TCP_DEFER_ACCEPT on Linux to avoid some wasted context switching when a new connection comes in to the server. BUG FIXES: * Some fixes for connections over SSH when built using --enable-rfc2553. Reported by Jeff Rizzo. * Handle arguments like "-xcpp" and "-Wa,-xarch=v8". Suggested by Ben Scarlet. * Fix resource exhaustion when DISTCC_SAVE_TEMPS is set. Reported by Mark DeGeorge. * Fix problems in running IPv6-enabled builds on kernels without IPv6 support. Reported by Lisa Seelye. DOCUMENTATION: * More instructions for distributors/packagers. PORTABILITY: * Many portability patches from Albert Chin. These patches were tested on: AIX 4.3.2, 5.1; HP-UX 10.20, 11.00, 11i; IRIX 6.5; Redhat Linux 7.1, 9; Solaris 2.5.1, 2.6, 7, 8, 9; Tru64 UNIX 4.0D, 5.1. * Possibly fix mmap problem on HP-UX with compressed transfers. Reported by Joe Buehler. TESTING: * Add test for compilation with compression. * Testsuite portability patch from Albert Chin. The tests pass on: HP-UX 10.20, 11.00, 11i; IRIX 6.5; Redhat Linux7.1, 9; Solaris 7, 8, 9; Tru64 UNIX 4.0d, 5.1. distcc-2.12.1 "Shatner's Bassoon" 2004-01-09 BUG FIXES: * When checking if a process exists, accept EPERM as indicating it exists but isn't ours. This allows watching the directory of a different user, subject only to filesystem permissions. Reported by Ernst Bachmann. * Correct a bug introduced in 2.12 that made distccd fail to start when run by root because setgid failed. Fix from Wayne Davison. * --without-gnome, --without-gtk now turn those options off rather than on. DOCUMENTATION: * New man page for distccmon-text, by Shri Shrikumar and Martin Pool. distcc-2.12 "Figgy Pudding" 2003-12-19 FEATURES: * New --log-level feature allows logging of only errors rather than messages for each connection. * IPv6 support now works better when distcc is configured with --enable-rfc2553. The server can normally accept either IPv4 or IPv6 connections. * New --with-docdir configure option to set install location for documents. The default is the same as previously. Patch from Harold L Hunt II. INTERNAL: * GNU-style ChangeLog is now included in the package. Please keep it up to date if you make your own changes! PORTABILITY: * setgroups() was broken by Mac OS X Panther so that it will not accept setgroups(0, NULL) to clear the group list. Instead we now set the group list to our single primary gid. Suggestion from Wayne Davison. * sendfile problems on FreeBSD 4.9-RC fixed. Patch from Allan Saddi. * MAXPATHLEN is provided if it's not defined, which is the case on GNU Hurd. Reported by Santiago Vila as Debian #219600. BUG FIXES: * Check pkg-config information GNOME/GTK+ is now checked at configure time, not build time. This is a bit quicker than running the script for every file we build, and means that PKG_CONFIG_PATH only needs to be set for configure. DOCUMENTATION: * Small documentation corrections. distcc-2.11.2 "Muscovado" 2003-10-23 BUG FIXES: * Correct the handling of --without-gnome. Reported by Dimitri Papadopoulos. * Fatal signal handlers for client and daemon should reset the signal vector before doing anything else, to protect against an (unlikely) spin if the signal is re-sent. * Corrections to .desktop file from Dag Wieers. INTERNAL: * Remove dependency on libglade for GTK+ and GNOME monitor programs. PORTABILITY: * IRIX portability fixes from Dimitri Papadopoulos. * Use AC_TYPE_SIGNAL to generate correct signal handler return types. (It can be either int or void.) DOCUMENTATION: * Various manual updates. * Update to xinetd example from Dag Wieers. distcc-2.11.1 "Burnt sugar" 2003-10-08 FEATURES: * The graphical monitor can now be configured with either --with-gnome or --with-gtk. In the second case, the GNOME libraries are not used. In both cases the resulting program is called distccmon-gnome and the functional differences are fairly small. BUG FIXES: * An error message is emitted and compilation fails if distcc cannot use the specified TMPDIR. This can happen if distccd is started by root with a TMPDIR only accessible to root. Reported by Brett Dikeman. * GNOME data files are now only installed when the application is configured with --with-gnome or --with-gtk. Files are installed into a distcc/ subdirectory of the configured data directory. (By default this is /usr/local/share/distcc/). Reported by Erik Jan Tromp and Noe`l Ko"the. * Fix bug in sending compressed files where errors were ignored. * C++ compilation using -frepo must be local. Reported by Andrew Slater. PORTABILITY: * Don't use stdint.h, which is not available on FreeBSD 4-STABLE, IRIX or Solaris. Reported by Frerich Raabe. DOCUMENTATION: * Corrections to distcc manpage reported by Lionel Sausin. * Documentation of how to write monitor programs, from Frerich Raabe. INTERNAL: * Fix state.h for use with C++. Patch from Frerich Raabe. distcc-2.11 "Sugar fix" 2003-09-23 INCOMPATIBILITIES: * The GNOME monitor is now configured using --with-gnome (not --enable-gnome) to be more consistent with GNU standards. * The state file format has changed, so old distcc monitor programs will not see new compiler processes and vice versa. FEATURES: * Nice new GNOME monitor, showing strip-charts (or "scarves") of the state of each processor slot over time. * --allow 0.0.0.0/0 is accepted as meaning "allow access from anywhere". Debian #207831, suggested by Matthijs Kooijman. BUG FIXES: * If we fail to determine the number of CPUs on the machine, assume it is 1. This may fix problems on exotic machines where the detection call is almost but not quite right. * In non-forking mode, make sure to close the accepted fd after processing a request. * Use "safe" LZO1 decompression for protection against program or network errors. * Lock and state files are created with the weakest permissions permitted by the umask. This is intended to reduce problems seen when $DISTCC_DIR is shared between two users, such as when compiling as root during program installation. * Client deletes temporary files when interrupted. INTERNAL: * Add debugging option DISTCC_MMAP, which can be set to 0 to disable use of mmap for receiving files. * New --enable-profile configure option to turn on gprof. * Many changes to the representation of the client state to make it easier to draw a history. State is now stored as a natively encoded struct in a disk file, rather than using our network protocol. PERFORMANCE: * Sleep only one second when blocked waiting for a CPU, to try to reduce idle time when recovering from an overloaded period. DOCUMENTATION: * Document problems with "no_subtree_check" on NFS. * The GNU Free Documentation License is no longer distributed, because the documentation is now included under the GNU GPL. * Document bad Makefiles or mismatched compilers as common causes of failure. * Describe where to put "localhost" in the host list. PORTABILITY: * Fixes for BSD/OS (BSDi) from Nick Amato. * Fixes for portability issues in autogen.sh from Lisa Seelye and Alexandre Oliva. distcc-2.10.1 2003-08-12 BUG FIXES: * Fix problem in "make clean" reported by Lisa Seelye. distcc-2.10 "Hunger is the best sauce" 2003-08-11 SECURITY: * Fix issues in temporary file handling that could allow a local attacker to interfere with another user's distcc processes. FEATURES: * Daemon niceness is incremented by +5 by default. (This can be changed by --nice.) * The per-user configuration directory can be set by $DISTCC_DIR. It defaults to the old value of ~/.distcc/. * For regular compile failure, don't say "with exit code 1". BUG FIXES: * The server now emits warnings to the log and to the client if its PATH is set such that it will recursively run a distcc client. This check is done at run time for the requested compiler name. The server's $PATH is not modified in other ways. This may help reduce problems with finding the right remote compiler. PORTABILITY: * SCO/Caldera operating systems are no longer supported due to their recent absurd attacks against Linux and IBM. * TMPDIR is no longer required to start with '/', so that Cygwin paths starting with a drive letter may be used. Reported by Heiko Elger. DOCUMENTATION: * Various man page updates. INTERNAL: * Daemon now sits in the root directory while running, not the temporary directory. * Temporary directory is gone. Working files are created directly under $TMPDIR. * Lock files and state files are stored under DISTCC_DIR, rather than in /tmp. TESTING: * Test cases are more robust in choosing a daemon port number. distcc-2.9 "Grace under pressure" 2003-07-21 FEATURES: * Optional LZO1X compression of network traffic, to make distcc faster on slow or overloaded networks. This is turned on by appending ",lzo" to each host specification. Both client and server must be updated for this to work. Old clients and servers are supported when compression is off, which is the default. Compression is probably only worthwhile on networks slower than 100Mbps, but it will depend on the usual factors of CPU, network and code complexity. Thanks to Markus F.X.J. Oberhumer for the LZO library. BUG FIXES: * Handle invocations like "distcc foo.o -o foo", which can be generated by Mozilla. * Handle invocations like "distcc -Wa,-al=foo.lst -c foo.c", which write an assembler listing to a file and cannot be run remotely. * When trimming the path to avoid recursive invocations, stop as soon as we find one non-symlink compiler. This should help avoid the path getting trimmed down far too much on the server. Patch from Wayne Davison. PERFORMANCE: * The daemon by default allows 2+NCPUS, rather than 3*NCPUS. The two extras are to allow for some processes to be blocked on network IO, but allowing more than two of them is probably not useful on multiprocessor machines. * Larger files are sent and received using memory mappings where possible. * Use of mmap and compression makes distcc substantially faster in at least some cases. DOCUMENTATION: * Convert the documentation to a series of regular Unix manpages for easier reference and so they can be used more easily on diverse platforms. The Linuxdoc-SGML manual has been removed from the distribution. Thanks to Tim Potter for review suggestions. TESTING: * Add tests for new -o and -Wa,-al handling. distcc-2.8 "Play in the traffic" 2003-07-09 FEATURES: * Small enhancements to GNOME monitor appearance. BUG FIXES: * Fix problem with nonblocking IO for SSH connections that causes a busy spin. SSH connections are now far more efficient. Reported by Marcelo Matus. * distccmon-text flushes output after each line, even if stdout is not a terminal. This allows it to more easily be run in polling mode under another program. Suggestion from Hamish Rodda. * distccd now works properly with SSH servers that use pipes rather than socketpairs to run the daemon. Previously it would fail with an error when trying to write to stdin. Suggestion from Felix Lee. * Correctly handle invocations like "gcc -ofoo.o -c foo.c", where the output filename is run on to the -o option. Based on a patch from Tsutomu Yasuda. INTERNAL: * mon.h is now safe for inclusion in C++ programs, and protected against multiple inclusion. Suggestion from Frédérick Forjan. * Increased timeout for nonblocking network IO apart from connections to 5 minutes. PORTABILITY: * Detect and avoid Apple gcc cpp-precomp brokenness. Patch from Matt Watson. * Better handling of builds on machines which do not have the linuxdoc-sgml toolchain. Suggestion from Frerich Raabe. DOCUMENTATION: * Include an example xinetd configuration file from Andrew Morton. distcc-2.7.1 "Expedition" 2003-06-25 PORTABILITY: * distccmon-gnome now depends only on GTK+ 2.0, not on the GNOME libraries. * Fix for compilation of the GNOME monitor on BSD. * Fix for compilation of the monitor on Cygwin. distcc-2.7 "The Hard Way" 2003-06-16 FEATURES: * Graphical compile monitor for GNOME 2.x. Configure with --enable-gnome to build it. PORTABILITY: * Possible fix for compilation on HP-UX. INTERNAL: * Sanity check GNOME libraries during configuration if --enable-gnome was specified. distcc-2.6 "The Watcher in the Water" 2003-06-12 FEATURES: * New program distccmon-text shows the state of any distcc processes run by the current user. It can be run by hand or read by a shell script. Should be popular with vmstat fans. * New environment variable $UNCACHED_ERR_FD allows client errors to be redirected from stderr to another file descriptor, so that distcc errors are not cached by ccache. This is an improvment because (almost?) all distcc messages are transient things such as failure to connect to a remote host, and it is confusing to have them cached. (This needs a corresponding patch to ccache to set this, or for it to be assigned to a duplicate of stderr before invoking cccache.) * In compilation log message, just show the basename of the file to make it more compact. BUG FIXES: * If an compiler cannot be executed then try searching the path for the basename of the compiler. This can fix cases where the compiler is invoked with an absolute name but it is in a different directory on the server. Patch from Paul Russell. PORTABILITY: * Fix build on platforms that don't have hstrerror(), such as Solaris 2.6. * Handle sysconf(_SC_NPROCESSORS_ONLN) returning 0 processors, which has been observed on ARM Linux and previously threw distccd into a spin. Patch from Sean MacLennan. INTERNAL: * New mon.c interface for writing compilation monitors. * State directory name includes hostname for robustness when the temporary directory is shared. * Client writes out notes about its state to files that can be watched by external monitor programs. * Partial GNOME-based monitor interface, built when distcc is configured with --enable-gnome. TESTING * Fix silly typo that made maintainer-check give a false failure in ParseHostSpec_Case. distcc-2.5.1 "disable extra paranoia" 2003-06-05 FEATURES: * Fifteen second timeout on connection attempts. Hosts that are unreachable in this time are blacklisted for another minute. BUG FIXES: * Fix setpgid() failure when started directly from init(8). Reported by George Garvey. * Correct parsing of old-style TCP multiplier specification (e.g. "phathost/10:3600"). Patch from Wayne Davison. PORTABILITY: * Fix socklen_t compilation problem on Darwin. * Fix compilation problems on Solaris 8. Report from Tomas Ögren. * Fix compilation problems on IRIX. (IRIX cannot accept a variable named "sa_len".) Report from Peter Naulls. * Fix compilation on SuSE Linux 7.1 for Alpha. DOCUMENTATION: * Add more details about starting distccd to the user manual. TESTING: * Add test for correct parsing of old-style TCP multiplier specification (e.g. "phathost/10:3600"). distcc-2.5 "give them heaps" 2003-05-27 FEATURES: * The standalone daemon now "preforks" before accepting connections to reduce per-request overhead. Can be disabled by --no-prefork, which restores the standard Unix behaviour. * Restrict the number of jobs accepted onto the server at any time. By default this is determined automatically depending on the number of CPUs on the server, but it can be set using the --jobs, -j option. Replaces never-used --concurrent, -n option. * When the daemon is terminated, the entire process group is shut down, including any compilations in progress. * Load limits on TCP hosts can now be specified in the more consistent form of "HOST:PORT/MUL" rather than "HOST/MUL:PORT". The old form is still supported. * Better error message for "bind failed". * Better "listening on" message at startup. * More meaningful reporting of transmission and compilation times in logs. BUG FIXES: * Fix bug that caused some messages to go to the 'user' syslog facility rather than 'daemon' as presently. * Fix problem with terminating the daemon when running under Valgrind. INTERNAL: * Refactor daemon loop. * Server-side temporary object files are called .o, not .out. Suggestion from rishikesh shetty. * Temporary directory name changed to decimal userid, rather than hexadecimal userid. Easier to recognize. * Daemon changes into state directory at startup. * SSH child is collected and checked when the connection is closed. distcc-2.4.2 "hard and fast" 2003-05-23 BUG FIXES: * Fix compilation directed to /dev/null by handling output files the same way as the GNU BFD library. Reported by Hal Duston. * Better error messages if DISTCC_HOSTS or host files are empty. Patch from Wayne Davison. * Fix string allocation bug in dcc_sockaddr_to_ip that could cause a server crash. distcc-2.4.1 2003-05-22 PORTABILITY: * Add strndup() for non-GNU platforms. Patch from Frerich Raabe. distcc-2.4 "sparky will reign" 2003-05-21 FEATURES: * Preliminary support for distribution of Objective C and Objective C++ compilation. Based on a patch from Dara Hazeghi. * If remote compilation fails, give a visible error. People might want to know, particularly if something is failing on one particular machine. * Error messages report host definitions more consistently, rather than just hostnames. * Better handling of attempts to run more concurrent compilations than there are available slots. distcc now sleeps for a few seconds to avoid thrashing the client machine. * Unavailable servers are now shunned for 60 seconds so as to avoid wasting time connecting to machines that are down, not running distccd, etc. (However hosts that are simply not responding (e.g. firewalled) are not handled perfectly yet.) BUG FIXES: * If an IO error occurs while trying to get a lock, bail out rather than getting stuck. * Don't use the RFC2553 getaddrinfo/getnameinfo API by default, because it seems to be slower on OS X and possibly problematic on other systems. It can be enabled with --enable-rfc2553 if you want to use IPv6, multi-homed servers, or want to test the new API. PORTABILITY: * Preliminary STRATUS VOS portability work from Paul Green. DOCUMENTATION: * More description of execution over SSH. distcc-2.3 "come down like a ton of bricks" 2003-05-16 FEATURES: * Respond more gracefully to protocol derailments. In particular, banner messages sometimes seem to get into the stream when distcc is run from inetd, and they were previously a bit hard to diagnose. This won't fix the configuration problem that causes them, but it should make the problem obvious. * The client now tries all addresses for each server, in the order returned by the resolver. * Client and server now use IPv6 if requested, where this is supported by the system. The server still binds to an IPv4 address by default, but this can be set by the --listen option. Client access control is not supported yet for IPv6. BUG FIXES: * Fix possible bug in loading host list files. * Startup errors are now reported to stderr, unless that is a socket in which case they are sent to syslog. This should be a better tradeoff between making errors obvious and the requirements of inetd mode. DOCUMENTATION: * Add description of --listen to manual, plus other improvements. Patch from Frerich Raabe. * Various clarifications to the manual. * Add documentation of DISTCC_FALLBACK, DISTCC_SSH, execution over SSH, and host list files. PORTABILITY: * Two Mac OS X fixes from Benjamin Reed: Use the BSD method to discover the number of CPUs, and include types.h where it is needed. * Improved portability of snprintf fallback implementation. Now works again on dietlibc/Linux. Some fixes merged from Samba HEAD. distcc-2.2 "nosurname" 2003-05-05 FEATURES: * If $DISTCC_HOSTS is not set, the host list is taken from from ~/.distcc/hosts, if that exists, or otherwise ${sysconfdir}/distcc/hosts. (The location of this last one is set by the configure option --sysconfdir. It defaults to /usr/local/etc.) * Add --listen option to distccd, to control which IP address is used to listen for connections. May be useful for access control on dual-homed machines. Based on a patch by Neil Mansilla. DOCUMENTATION: * Add documentation for --allow and --user, by Frerich Raabe. TESTING: * Add test case for host list file. * Try to prevent server messages getting into syslog during testing. distcc-2.1 "Don't mind if I do!" 2003-05-03 FEATURES: * Support for execution over ssh! Hosts to be contacted over SSH should be specified as '@HOST' or 'USER@HOST'. distccd must be installed on the volunteer host, but it need not be running and there is no need to set up ssh tunnels. Compilations run under the user's account, and connections are securely authenticated and encrypted. SSH is substantially slower than plain TCP connections, but they can still be faster than local compilation. * The search path is examined in both the client and server, and directories containing distcc (and ccache, where appropriate) masquerade hooks are removed. This should help prevent distcc accidentally invoking itself recursively on either client or server. Patch from Wayne Davison. BUG FIXES: * Fix up warning about pid file being removed twice. * Better error handling when corks are not supported on a particular system or socket. * Fix incorrect display of CPU usage statistics in server log and client. * Change behaviour of distccd for log messages encountered during startup, before options are parsed. These are now written to stderr only if that is a tty, and otherwise to syslog. This is intended to prevent log messages from distccd getting mixed into the network protocol when it is run from inetd. * Correctly trap unexpected end of input when copying a file using read/write. * Test harnesses may need snprintf.o linked in as well. Reported by Joe Meslovich as broken on Solaris. TESTING: * Add test that --allow does in fact deny connections as it should. * Add tests for parsing of --allow options. * Add DISTCC_FALLBACK environment variable. If set to 0, means that failure to distribute will be considered an overall failure. By default, a networking error means that compilation will be retried locally. INTERNALS: * Many cleanups of error handling code. * Trace distcc version at startup to help with bug reporting. * Update IO code to handle nonblocking sockets, because we (may?) need to use nonblocking socketpairs to talk to SSH. distcc-2.0.1 "colorful savings on all your favorite medications" 2003-03-28 BUG FIXES: * Fix comfychair.py library missing from distribution. distcc-2.0 "shoot through like a Bondi tram" 2003-03-28 BUG FIXES: * Fix small signal handling race that would occasionally cause distccd not to exit when signalled. Pointed out by Vance Lankhaar. * If DISTCC_LOG is an empty string, treat as undefined. * If the file specified by DISTCC_LOG can't be opened, then show an error and use stderr. Previously, error messages were just lost. FEATURES: * New "masquerade" mode: distcc can be linked into a directory on the search path as 'cc'. By Wayne Davison and Martin Pool. * Detect number of online processors on the server. At the moment it is just logged but in the future it might be used to guide scheduling. Thanks to Dimitri Papadopoulos-Orfanos for describing how to do this on many operating systems. * Log signal name when terminating, on systems with strsignal(). PERFORMANCE: * Internal CPU efficiency fixes in logging and RPC code. PORTABILITY: * Apparently now builds on IRIX. Reports about whether it works would be welcome. * Fix cast in call to sprintf for platforms where ssize_t != int. Found on Alpha Linux in the hp Compaq testdrive. * Clean up some warnings on IRIX. * Fix problem with vsnprintf() declarations on Solaris 8. * Cope when in_addr_t and socklen_t are not defined, as is the case on FreeBSD 3.3. * Fix test suite to allow for 'true' and 'false' being in /usr/bin on BSD. TESTING: * Many internal updates to ComfyChair framework. * Test suite now works with Python 1.5 or later. * Add new undocumented (heh) "--lifetime" option that causes the daemon to expire after a certain period. * Specify limited lifetime when running daemon, so that if it is not cleaned up by the tests it will go away after a little while anyhow. * Use "--allow" to limit connections to localhost when running daemon for testing. * Use randomly chosen TCP port for the server when running tests. This makes repeated or concurrent invocations of the test less likely to conflict. * On machines without Python, just say "test skipped" rather than failing. * Test DISTCC_LOG being set to an unwriteable file. REMOVALS: * The GNU Info form of the manual is no longer included in the source distribution or installed by default. It can be built from SGML if desired, with "make install-linuxdoc-info". distcc-1.2.3 "stubborn tiny lights" 2003-03-02 PORTABILITY: * Don't use ':' in lock filenames, because that's a bit too tough for Windows. This only affects Cygwin clients, not servers. Pointed out by Heiko Elger. * Check existence of ctype.h. Fixes warnings when building popt. Pointed out by Tom Matelich. * Fix "access denied" errors on lock files on HP-UX and Cygwin, so clients on those platforms should work. Reported by Tom Matelich, Heiko Elger and others. distcc-1.2.2 "clustering darkness forever" 2003-02-27 BUG FIXES: * "make distclean" should not remove ./configure. PORTABILITY: * Don't assume POSIX-style reentrant file locks, which can't be supported on Cygwin. * Check for inet_aton in libresolv, which might fix Solaris 2.6. * Remove some gnudity from the Makefile in an attempt to build with non-GNU Make. * Attempted fix for header files on BSD. * Attempted sendfile implementation for HP-UX. TESTING: * Add a simple "make distcheck" target to test that the tarball is built properly. distcc-1.2.1 "you know you're right" 2003-02-25 BUG FIXES: * Better detection of python2.2 during configuration. * Allow installation from CVS on machines that don't have the Linuxdoc tools. * Check for autoconf >= 2.53 when configuring. Remove dependencies on features from later versions of autoconf to allow autogen to run on Red Hat Linux 7.2 systems. TESTING: * Add "make installcheck" target. * "make check" now fails if any of the tests fail to run. * distcc is now built on the build.samba.org build farm. Please contribute machines if you want your platform to be properly supported. PORTABILITY: * Remove libiberty, and use Samba's asprintf() implementation instead. Yay copy and paste. This should fix problems with asprintf and ansidecls.h on Solaris, BSD, and Cygwin. distcc-1.2 "lizard drinking" 2003-02-22 FEATURES: * New scheduler makes a better attempt at keeping remote machines solidly loaded by allowing only one request at a time to be in transit to remote machines, therefore letting the actual compiler start sooner. Gives about a 10% improvement in some circumstances. The new algorithm should also be a better foundation for adding compression or server-side load limiting. * New --allow option for distccd allows IP-based access control in either inetd or standalone daemon modes. * Locking mechanism now distinguishes between daemons on different ports of the same machine for the purposes of load balancing. * Print timing and estimated rate on bulk data transfers. * Open binary files in O_BINARY mode on Cygwin. May fix some corruption problems on this platform. More investigation would be appreciated. Based on a patch by Helind. PORTABILITY: * Use putenv() rather than setenv() to fit into SUSv2 and work on Solaris 8. Pointed out by Dimitri Papadopoulos. * Add some functions from libiberty to aid portability. distcc-1.1 "balls to the wall" 2003-01-28 BUGS: * Flag platforms that have a sendfile() function, but that aren't explicitly supported, because it seems to vary substantially. At the moment only FreeBSD and Linux are known. * Fix configure test for hstrerror(). Patch from Frerich Raabe. * Check for inadvertent recursion, where distcc calls itself as the compiler. Causes an exit with value 111. * Don't log client hostname, only the IP address. It's not really necessary and can slow us down. * If run by root, discard privileges rather than flagging an error. The persona to assume is set by the --user option and defaults to "distcc". The user "nobody" or uid 65534 is used as a fallback if the named user is not found. BENCHMARK: * Allow for running benchmarks repeatedly, printing the mean and standard deviation of run time. * Projects may now be selected by an unambiguous prefix of their name, so you can just say "benchmark hello" rather than "benchmark hello-2.1.1". * Print better explanatory messages while the benchmark is running. TESTING: * Update some tests to work with changed behaviour of gcc 3.2 as well as 2.95. DOCUMENTATION: * Many updates to distcc User Manual. * Comply with GNU Standards by keeping all messages in the NEWS file, not just those for the current release. distcc-1.0 "consider the oyster" 2003-01-16 BUG FIXES: * Fix sendfile() bug on FreeBSD that could cause files to be mistransmitted. Perhaps not manifest on x86? Reported by Kris Kennaway. PACKAGING: * Distribute as .tar.bz2 rather than .tar.gz. (We pay by the byte.) DOCUMENTATION: * The recommended convention for gcc names is -gcc-, and GCC 3.3 will install itself under this name. (Alexandre Oliva, Claes Wallin) BENCHMARK: * New macro-benchmark and test suite for distcc. Invoke it with "make benchmark." It takes a long time to run and causes a lot of source code to be downloaded, but should be self-contained. This is the start of a script that runs distcc to build various open source programs, as an overall test of correctness, and to measure performance of a distcc installation. It relies on the user to install and configure distcc servers and clients, but handles the work of downloading, preparing, and building packages by itself. There are still some rough edges on the script, but it may be of interest. * Add control over which phases of the benchmark are run. * Add ability to run tests repeatedly and report mean and standard deviation. REMOVALS: * Remove Plucker file: nobody seems to be downloading it, and it's easy enough for people to build if they're interested. * Remove PDF and Postscript from documentation in tarball. They are still available from the web site or may be built from source. distcc-0.15 "petrified forest" 2002-12-12 INCOMPATIBILITIES: * Change default port from 4200 to IANA-assigned standard for distcc service "3632". Compatibility with old installations can be retained by explicitly setting --port=4200 on the server, or using "HOST:PORT" on the client. * Fake-root directory for "make install" is now set by DESTDIR, not TARGET_ROOT. (Alexandre Oliva.) BUG FIXES: * Run the preprocessor with output sent to stdout and redirected to a file, rather than by using the -o option. This should fix some compilers that can't handle "-E -o". It may improve gcc behaviour with -MD, but because gcc behaviour has changed over time it may not be a complete fix. For gcc 3.2 it is recommended that -MF be used to explicitly set the dependency output filename. TESTING: * Add test case for transmission of a zero-byte file. * Add badly-behaved compiler drop-in for use in testing. PORTABILITY: * Use the correct autoconf macros to detect whether install(1) is available and working, and if not, fall back to using the included install-sh script. This should fix "make install" on Solaris. (Mike Santy) * Fix waitpid() takes three options. Required for Irix. (Michael Santy) * Fix autoconf detection of resolv.h on Solaris. (Dimitri Papadopoulos) DOCUMENTATION: * Describe information to include in a bug report. * Remove "Results" chapter from manual: there are now many more detailed results on the web site, and this information is better suited to storage there, because it will be updated on a different cycle. End-users don't really need to have it in their reference. * Remove "MOC Compatibility" section from manual because at the moment there is nothing to say. * Add a new section about the complexities of gcc -MD. * Remove "Bugs" section from the manual, and put it into a new TOOD file instead. Keep information about reporting bugs and using the test suite, but put it in a different section. distcc-0.14 "no agonizing hanging weights" 2002-11-13 BUG FIXES: * Take lock on localhost only when compiling locally, not for all compilations. This removes the accidental limit of only 4 overall jobs. (Martin Pool) * Fix Makefile bug that caused HTML documentation to be missing from the distribution tarball. (Frerich Raabe, Martin Pool) * Make PreprocessPlainText_Case run in appropriate subdirectory. (Martin Pool) PORTABILITY: * Test for wait4 and wait3, which are missing on IRIX. (Mike Santy, Martin Pool) DOCUMENTATION: * Include example init.d script. (Jason Thomas) distcc-0.13 "Armistice" 2002-11-11 FEATURES: * New --no-detach option to cause the server not to detach from its parent. It still forks normally when a connection is accepted. This may be useful with daemontools or other frameworks that prefer the daemon not to detach. (Martin Pool) * Log messages on the server of severity "warning" or higher are captured and sent back to the client. (Martin Pool) * If the local preprocessor fails, do not re-run the job locally because it would presumably fail in the same way. (Martin Pool) * By default, the client only sends "warning" or higher messages to stderr, so that nothing extra is logged unless there is possibly a failure in distcc itself. With a DISTCC_LOG file, "notices" and higher are logged. (Martin Pool) * Better messages when a compiler exits or crashes. (Martin Pool) * If the compiler because of a signal, return 128+SIGNAL, per Unix convention. (Martin Pool) * Compilers and preprocessors are now run in their own process groups, and terminated if the daemon is killed. (Martin Pool) * When the daemon parent is terminated, it does not kill all its children. Instead, they're allowed to finish whatever they're working on, and then exit. This allows for more graceful shutdown. (Martin Pool) * More specific exit codes for some error cases. Don't panic. (Martin Pool) * Include popt library and --with-included-popt configure option to aid installation on systems that don't have it. By default it is statically linked in only if the build machine does not have a suitable library and header. (Martin Pool) REMOVALS: * Remove support for feeding the compiler from a fifo. The gain from using fifos does not seem to justify the maintenance burden. (Martin Pool) - This makes the behaviour more consistent, because some platforms (Cygwin) or filesystems (NFS, strangely) can't use fifos. It removes a code path and a slightly complex autodetection. - Using fifos makes some potential scheduling improvements hard: the server can't make good decisions about how many tasks to run, because each one will only use a fraction of the CPU. The client cannot serialize file transmission, which would probably be desirable. - Using fifos makes reliably handling compiler failures slightly harder: the compiler may crash or exit at any time, which will in turn cause the server to hang if it later tries to open or write to the fifo. In previous versions, distcc tried to handle this by catching SIGCHLD when the child terminated, and aborting the operation, but I am not sure that the method is completely reliable. BUG FIXES: * Detached daemon now ignores hangup signal. (Martin Pool) * When the parent is terminated, don't kill its process group. Allow children to finish in their own time. (Martin Pool) * Detect the case where cpp claims to have succeeded, but did not actually produce any output. (Martin Pool) * Do not use atexit() to clean up temporary files, because this can cause havoc if it's ever called from a child process that forked but failed to exec. (Martin Pool) * Handle "gcc -S foo.c -o -", which ought to write assembly to stdout. (Alexandre Oliva) * Fix bug in handling IO errors (e.g. dropped connection) in the server. (Martin Pool) * If we fail to cork a socket, continue anyhow. (Martin Pool) * Make error handling for IO more consistent. (Martin Pool) * Follow Unix convention of returning 128+SIGNAL if the compiler exits with a signal. (Martin Pool) TESTING: * Add tests for parsing slot limit from host specification. (Martin Pool) * Daemon tests collect dead servers faster, so the tests run a bit faster. (Martin Pool) * Nicer handling of ^C while running tests: print "INTERRUPT" and terminate the whole test. (Martin Pool) * Add new tests for scanning command lines with an implied compiler name. (Martin Pool) * When the parent is terminated, don't kill its process group. Allow children to finish in their own time. (Martin Pool) * Detect the case where cpp claims to have succeeded, but did not actually produce any output. (Martin Pool) * Add test case for #error directive. (Martin Pool) * Add test case for preprocessing non-C text, as is done by (for example) xrdb. (Martin Pool) * Add test case for invocations like "distcc -c test1.c test2.c". (Martin Pool) * Add test for handling of a compiler missing from the server. (Martin Pool) * Allow distcc's version to be set to something like "0.13cvs-nofifo". (Martin Pool) * Add test for handling of a compiler missing from the server. (Martin Pool) * Improved ComfyChair testing framework. (Tim Potter, Martin Pool) PORTABILITY: * Includes example init.d script for SuSE 7.x and 8.0. Not installed by default. (Brandon Forehand) DOCUMENTATION: * Document use with Gentoo Linux. (Dean Bailey, Ernesto, Martin Pool) INTERNAL: * Get rid of recursive Make and fix various small Makefile bugs. (Martin Pool) * Add $(TARGET_ROOT) variable for "make install", for use in building binary packages. (Martin Pool, Nick Moffitt) * wait4() on Solaris can't handle a pid of -1, which means "any child" on Linux and BSD. Use pid of 0 instead to collect any children from the same process group. (Kevin Bailey) * Client does not abruptly drop network connection on compiler failure but rather reads the 0-byte object file token. (Martin Pool) * Rework logger library to allow multiple logger callbacks to be active at once. This is used for the server, which can write to its own log files and also send a copy of messages to a buffer to be sent to the client. (Martin Pool) distcc-0.12 "Klein, kosten- und schnörkellos" 2002-10-07 BUG FIXES: * Handle "gcc -S foo.c -o -", which ought to write assembly to stdout. (Alexandre Oliva) PORTABILITY: * wait4() on Solaris can't handle a pid of -1, which means "any child" on Linux and BSD. Use pid of 0 instead to collect any children from the same process group. (Kevin Bailey) TESTING: * Add tests for "-o -". (Martin Pool) distcc-0.11 "Nuclear Bedtime Story" 2002-09-25 FEATURES: * More helpful message explaining that popt is needed if it is missing at build time. (Martin Pool) * Better stripping of options from remote command lines. (Martin Pool) * Handle the new -MM, -MG, -MP, -MF, -MT, -MQ options for gcc 3.x. (Stephan Kulow, Martin Pool) PERFORMANCE: * Whenever a command by either the client or the server, it counts towards the load on that machine. This covers undistributed commands, cpp, and compilation. This should avoid the bias in earlier versions towards overloading the client. (Martin Pool) BUG FIXES: * IO errors should not cause the process to terminate straight away, because they are properly handled and we may have important cleanup to do. (Martin Pool) * Fix error handling in code for executing compilers. (Martin Pool) * Fix leakage of file descriptors when trying to acquire a lock. (Martin Pool) * Do not object to running as group 0, because on BSD this is "wheel" and many non-privileged users are in it. (Frerich Raabe, Martin Pool) * Fix (non-exploitable) buffer overrun bug. (Dave Zarzycki) PORTABILITY: * Fixes to build on Linux libc5. (Richard Zidlicky, Martin Pool) TESTING: * Keep $TMPDIR separate for each test case. (Martin Pool) * testdistcc.py now optionally takes arguments saying which tests to run. (Martin Pool) * Test permissions on output files are correct. (Martin Pool) * Add more test cases for implicit compiler name handling. Extend h_scanargs to exercise this. (Martin Pool) * More tests for argument stripping. (Martin Pool) distcc-0.10 "shiny fast red thing" 2002-09-12 FEATURES: * Allow distcc to be directly used with the same syntax as a compiler: "distcc -c hello.c". At the moment, always calls "cc". (Martin Pool) * If distribution fails, show the name of the server that we were trying to use. (Martin Pool) * Strip -D, -I, -L, -M* options before passing the command line across the network, for clarity (and perhaps a tiny performance improvement.) Also, this allows new clients which support -MD to be used with old servers that can't handle it. (Martin Pool) BUG FIXES: * Correctly handle "gcc -c -S hello.c", which should only assemble, not compile. (Alexandre Oliva) * If the volunteer compiler exits without reading all of its input, return the compiler's own exit code across the network, rather than EXIT_DISTCC_FAILED. (Martin Pool) * Attempt to fix a race where the compiler process could exit without opening its input before we started writing to the FIFO. In that case, the daemon would hang forever waiting for the compiler to arrive. In the new code, SIGCHLD causes a longjmp to break out of trying to feed the compiler. (Martin Pool) * If .o file is 0 bytes or not created on the server, do not create it on the client either. (Martin Pool) * Fix bug that caused compilation to fail if an old compiler output file existed. (Martin Pool) * Try to make sure to uncork client socket before closing if cpp fails, to work around Linux 2.2 bug that causes the socket to jam in FIN_WAIT1. See . (Martin Pool) * Invocations of gcc that use -MD or -MMD can be distributed, although -M cannot be. Both client and server must be updated to make this work. (Martin Pool) * It turns out that .s and .S files in fact cannot be assembled remotely, because they might use the gas '.include' pseudo op, which is resolved by the assembler and would end up reading something from the volunteer's disk. (Richard Zidlicky, Martin Pool) PORTABILITY: * Solaris portability fixes. (Dimitri PAPADOPOULOS-ORFANOS) TESTS: * Test handling of -c and -S. (Martin Pool) * Test handling of a file that causes a preprocessor error. (Martin Pool) * Test compiler that succeeds without reading input. (Martin Pool) * Test many simple compilations, in case there is an infrequent error. (Martin Pool) * Test many concurrent compilations. (Martin Pool) * Test using -D on the compiler command line. (Martin Pool) * Tests for .s and .S files. (Martin Pool) distcc-0.9 "samui desu ne?" 2002-09-03 FEATURES: * Add new environment variable for client and server, DISTCC_TCP_CORK. Defaults to on, intended mostly for performance comparison or debugging. (Martin Pool) PORTABILITY: * Properly support platforms with 32-bit pids, such as Cygwin. (Aaron Lehmann, Martin Pool) * On FreeBSD, the sa_family_t type is defined in (Dennis Taylor) BUG FIXES: * Fix bugs related to leftover fifos in the temporary directory causing occasional server hangs. (Martin Pool) * Stop the compiler from inheriting file descriptors connected to the network. This was causing the client to hang if the server abnormally terminated while the compiler was reading from a fifo. (Martin Pool) * Handle the case of sendfile() transmitting only part of the supplied data, similarly to a short write on a socket. This doesn't often happen, but can occur if a ptrace debugger attaches while sendfile is running. (Martin Pool) * When run with --daemon and not --no-fork, the parent does not detach until the pid file has been created. This removes a slight race window that sometimes confused the test scripts. (Martin Pool) * Message for completion of local cpp now gives the correct hostname. (Martin Pool) * Do not try to collect daemon children if --no-fork was specified. (Martin Pool) * Set SIGPIPE handler back to default before starting compiler tasks. (Martin Pool) * If a network error is detected while feeding input to the compiler, then it is terminated with a SIGHUP. (Martin Pool) * If transmission to the server fails, close the socket sooner rather than later so as not to make the server process wait around unnecessarily. (Martin Pool) * Better handling of the case where the compiler command exits without reading its input. (Martin Pool) * Make sure compilation children are always properly collected, even if transmission failed. (Martin Pool) PERFORMANCE: * Write token/parameters using a single write() call. May be very slightly more efficient in CPU and perhaps packets. (Martin Pool) TESTS: * Display test names while they're running so that long tests are easier to follow. (Martin Pool) * When cleaning up after running the dameon, make sure it's really dead before proceeding, so that tests don't trip over each other. (Martin Pool) * New test of compilation of a largish (~4MB) C file to a ~5MB object file. (Martin Pool) distcc-0.8 "cat and girl" 2002-08-15 FEATURES: * If for any reason a job can't be distributed, it is run locally rather than failing. This includes servers which are not running or unreachable, servers which crash, bad host specifications, etc. (Martin Pool) * --help for distcc explains more about host specifications. (Martin Pool) BUG FIXES: * Correctly handle compilation of C++ code under ccache, by properly recognizing the .ii extension. (Stephen White, Chris Halls) * Boolean environment variables (e.g. DISTCC_SAVE_TEMPS, DISTCC_VERBOSE) are now consistently required to be literally "1" to count as true. (Martin Pool) DOCUMENTATION: * Document that $DISTCC_HOSTS can now specify ports. (Martin Pool) * Document --no-fifo and --log-stderr. (Martin Pool) distcc-0.7 "Pipeline Authority" 2002-08-05 FEATURES: * Can now either use fifos for feeding the compiler or not. This can be controlled by --no-fifo to the server. By default, it tries a fifo and falls back to using regular temporarily files if that fails, as it will on Cygwin or an NFS-mounted /tmp. (Martin Pool) * --log-stderr option, intended mainly for debugging or testing. (Martin Pool) * DISTCC_HOSTS can now specify non-default port numbers using "host:port" syntax. (Martin Pool) DOCUMENTATION: * Built documentation (HTML, PS, PDF, Info) is now shipped in the distributed tarball, so that you can more easily install it on a machine lacking the Linuxdoc SGML tools. You still need them to modify and rebuild the documentation, of course. (Martin Pool) BUG FIXES: * Log pid even if running with --no-fork. Remove pid file on exit. (Martin Pool) PORTABILITY: * Try fcntl locks in addition to lockf and flock; apparently this helps portability to Cygwin. (Martin Pool, Marco Alanen) * Port to Cygwin. (Martin Pool, Marco Alanen) * Partial port to Solaris. (Dimitri PAPADOPOULOS-ORFANOS, Martin Pool) TESTABILITY: * Further internal improvements to test suite. (Martin Pool) * Test suite should now run whether or not there is a daemon listening on localhost, because it uses a non-standard port for testing. (Martin Pool) distcc-0.6 "reptilian agenda" (12 July 2002) FEATURES: * Daemon now refuses to run as root, because this is just too ridiculously insecure. (Martin Pool) * Output shows CPU time taken by distcc and programs that it runs. (Martin Pool) * distcc will now distribute jobs which use -s to compile but not assemble. Previously they were always run locally, but there's no strong reason why they must be. Unfortunately you need to upgrade both the client and server for this to work, because old servers will refuse to run gcc with -s. (Martin Pool) BUG FIXES: * -M option implies that cpp must be run locally, because it will want to write dependency information to a file. (Martin Pool) * Add --daemon and --inetd options, so that you can properly start a remote daemon with a single-line ssh command. (Martin Pool) * Fix bugs related to collecting child processes. (Probably not very user-visible.) (Martin Pool) * Fixed some Makefile-related bugs causing "make install" breakage and similar things. (Martin Pool) * If the system supports sendfile, but the particular filesystem we're on (e.g. tmpfs) doesn't, then fall back to using read/write. (Eivind Magnus Hvidevold, Martin Pool) * Change to argument analyzer to placate Valgrind. Possibly this was a memory corruption bug, but I can't see it. I think Valgrind was just too picky. (Martin Pool) PORTABILITY: * Build on FreeBSD, though you do need GNU make. (Lauri Watts, Martin Pool) DOCUMENTATION: * Better description of how to do cross-compilation. (Martin Pool) TESTING: * Improved Python test suite. (Martin Pool) INTERNAL CHANGES: * Get rid of automake; just use plain autoconf 2.53. (Martin Pool) * If $DISTCC_SAVE_TEMPS is set to "1", then files are not actually deleted -- good for debugging. (Martin Pool) distcc-0.5 "Unacceptable Behaviour" (27 June 2002) FEATURES: * Use more specific return codes when the remote compiler fails: EXIT_COMPILER_CRASHED for a signal, or the return code from the compiler if it exited non-0. FIXES: * Fix bug in h_hosts that caused us to write off the end of the real argv[], rather than a copy. Thanks to Julian Seward. (Martin Pool) PORTABILITY: * Cope on compilers without varargs macros. (Petter Reinholdtsen, Martin Pool) * Build on Solaris. (Petter Reinholdtsen, Martin Pool) * FreeBSD fixes. (Claes Wallin, Frerich Raabe, Michael Nottebrock, Martin Pool) DOCUMENTATION: * Manpages are correctly distributed and installed. (Petter Reinholdtsen) TESTING: * Test suite now runs a server on localhost and tests against it, and shuts it down on completion. (Martin Pool) * More test cases. (Martin Pool) distcc-0.4 "Wisdom Like Silence" (9 June 2002) ENHANCEMENTS: * Assembly and assembly-with-preprocessor files can now be assembled remotely. (Martin Pool) * Client now emits no messages unless there is a warning or error, or $DISTCC_VERBOSE is specified. This improves operation with ccache. (Martin Pool) * Client and server both respect $TMPDIR if set. (Martin Pool) * Standalone server puts itself in the background and detaches from controlling tty. (Martin Pool) * Server has --port option. Currently useless, since there's no corresponding option on the client. (Martin Pool) * Server has --pid-file option. (Martin Pool) * Server now allows multiple concurrent compile tasks, forking per connection. (Martin Pool) BUG FIXES: * gcc invocations with -fprofile-arcs or -ftest-coverage that would emit coverage information to a local file are always run locally. (Martin Pool) * Handle lines like "gcc -c -c hello.c". (Martin Pool) DOCUMENTATION: * Various enhancements to the user manual. (Martin Pool) INTERNAL: * Add a partial test suite based on PyUnit. Python 2 is now required to run the test suite, though not to just build or run distcc. (Martin Pool) distcc-0.3 "The Anticipation of a New Lover's Arrival" (28 May 2002) ENHANCEMENTS: * Support C++ compilation (including with ccache) by correctly detecting prefixes. (Ian Reinhart Geiser, Martin Pool) * Use a FIFO to feed preprocessed source from the daemon into the compiler, so that compilation can be overlapped with network transit. (Martin Pool) BUG FIXES: * Only fiddle with the compiler's stdin/out/err when running on the server, not on the client. This should make cpp from stdin work. (Reported by Ian Reinhart Geiser from KDE) (Martin Pool) * Prevent server crashing on aborted connectiong by using EPIPE rather than SIGPIPE in daemon as well as client. (Martin Pool, Ben Elliston.) PORTABILITY: * Builds on GNU/Linux, FreeBSD, and others if you're lucky. (Martin Pool, Frerich Raabe, Luke Gorrie) INTERNAL: * Convert to using GNU automake and autoconf, so that distcc can better handle portability, distribution and testing. (Martin Pool, Frerich Raabe, Ian Reinhart Geiser) * Start adding some "make check" tests. (Martin Pool) distcc-0.2 (17 May 2002) ENHANCEMENTS: * First public release * Correctly and usefully builds various large programs Local variables: mode: indented-text indented-tabs-mode: nil coding: utf-8 End: distcc-3.1/source/config.guess0000750000175000017500000012001111115326647015456 0ustar wolffwolff#! /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 . # Please send patches to . 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 ." 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 <$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 /* 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 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 #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` 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 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 #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 #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' /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 echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # 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 < # include #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 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 # 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 < 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: distcc-3.1/source/COPYING0000640000175000017500000004311011115326647014176 0ustar wolffwolff GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. distcc-3.1/source/find_c_extension.sh0000750000175000017500000000242511115326647017023 0ustar wolffwolff#! /bin/sh # Usage: find_c_extension.sh BUILDDIR # # Write path of directory containing C-extension of build directory. # # More precisely, locate the unique directory of the form: # # _include_server/lib.*/include_server/ # # that contains file 'distcc_pump_c_extensions.so'. Write the path of this # directory to stdout and exit with status 0. If such a path does not exist # then write error message to stderr and exit with status 1. builddir="$1" # We want to catch the file whether it's .so (unix) or .dll (cygwin). # The '[sd][ol]*' glob does that without having to worry about # unpredictable 'ls' behavior when a glob has no matches. # (Side note: there is intense internal debate about whether the # '[sd][ol]' hack is "so ugly I can't stand it" or "kinda cute".) so_files=`ls $builddir/_include_server/lib.*/include_server/\ distcc_pump_c_extensions.[sd][ol]*` if [ -z "$so_files" ]; then echo \ '__________Could not find shared libraries for distcc-pump' 1>&2 exit 1 elif [ `echo "$so_files" | wc -l` -ge 2 ]; then echo \ '__________Shared libraries for multiple architectures discovered.' \ 1>&2 echo \ "__________Cannot determine which one to use among: $so_files" \ 1>&2 exit 1 else # There was only one such file. dirname "$so_files" exit 0 fi distcc-3.1/source/configure.ac0000640000175000017500000004032711115326647015440 0ustar wolffwolffdnl 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, 3.1, distcc@lists.samba.org) 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 #include int getpeername (int, $arg2 *, $t *); ],[ $t len; getpeername(0,0,&len); ],[ dcc_cv_socklen_t_equiv="$t" break ]) done done if test "x$dcc_cv_socklen_t_equiv" = x; then AC_MSG_ERROR([Cannot find a type to use in place of socklen_t]) fi ]) AC_MSG_RESULT($dcc_cv_socklen_t_equiv) AC_DEFINE_UNQUOTED(socklen_t, $dcc_cv_socklen_t_equiv, [type to use in place of socklen_t if not defined])], [#include #include ]) # 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 AC_ARG_ENABLE(Werror, AC_HELP_STRING([--disable-Werror], [don't use gcc's -Werror option when building])) # Now get the package configuration information for whatever packages # we need. It's faster to just do it once during configuration. if test "x${with_gnome}" = xyes then GNOME_PACKAGES="gtk+-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" UNINSTALL_GNOME="uninstall-gnome-data" AC_MSG_CHECKING([GNOME/GTK+ cflags]) GNOME_CFLAGS="`pkg-config --cflags $GNOME_PACKAGES`" || AC_MSG_ERROR([failed to get cflags]) AC_MSG_RESULT([${GNOME_CFLAGS}]) AC_MSG_CHECKING([GNOME/GTK+ libraries]) GNOME_LIBS="`pkg-config --libs $GNOME_PACKAGES`" || AC_MSG_ERROR([failed to get libs]) AC_MSG_RESULT([${GNOME_LIBS}]) fi AC_SUBST(GNOME_PACKAGES) AC_SUBST(GNOME_CFLAGS) AC_SUBST(GNOME_LIBS) AC_SUBST(INSTALL_GNOME) AC_SUBST(UNINSTALL_GNOME) dnl Checks for programs AC_PROG_CC WERROR_CFLAGS="" POPT_CFLAGS="" PYTHON_CFLAGS="" if test x"$GCC" = xyes then CFLAGS="$CFLAGS -MD \ -W -Wall -Wimplicit \ -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings \ -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes \ -Wnested-externs -Wmissing-declarations" # -Wuninitialized requires -O case "$CFLAGS" in "-O"*|*" -O"*) CFLAGS="$CFLAGS -Wuninitialized" ;; esac # Would like -Wunreachable-code here, but it generates too many false # positives. # We want warnings to be treated as errors, # unless the --disable-Werror configure option was used. # Note that we can't include this in CFLAGS, # because that would affect the configure tests, # causing some of the tests to fail when they should succeed. if test x"$enable_Werror" != xno then WERROR_CFLAGS="-Werror" fi # Additional flags for compiling Python extension modules. # We disable -Wmissing-prototypes and -Wmissing-declarations, # which don't apply to python extensions (it exports global fns via a # pointer), and -Wwrite-strings, which just had too many false # positives (for Python 2.2, anyway; looks like these may be fixed # in Python 2.5). # -Wp,-U_FORTIFY_SOURCE is to turn off _FORTIFY_SOURCE on systems where # it's in the Python Makefile (and hence inherited by us). # _FORTIFY_SOURCE gives compiler errors for some distcc routines that # ignore the return value from libc functions (like getcwd). # That would cause this code to not compile, which is no good. PYTHON_CFLAGS="-Wno-missing-prototypes -Wno-missing-declarations \ -Wno-write-strings -Wp,-U_FORTIFY_SOURCE" # For popt/*.c, we disable unused variable warnings. POPT_CFLAGS="-Wno-unused" AC_MSG_NOTICE([Adding gcc options: $CFLAGS]) fi AC_SUBST(WERROR_CFLAGS) AC_SUBST(POPT_CFLAGS) AC_SUBST(PYTHON_CFLAGS) AC_ISC_POSIX # Apple's OS X gcc has a cpp-precomp "feature" that breaks standard # variadic macros. If we can disable it, do so. # This is needed for our included version of popt. # TODO(csilvers): figure out what that above comment means, and if it's true. CPPFLAGS="$CPPFLAGS -DHAVE_CONFIG_H" # Needed to get various GNU-only functions. They're all autodetected # by configure so we can cope without them, but we want them if they're # there. CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" AC_PROG_MAKE_SET AC_PROG_INSTALL # We prefer to use the latest Python, but try to find an explicit # version to make sure we don't get a really old one. # # The include server requires python 2.4 or later, but the 'make test' # routines only require python 2.2. Thus we have two separate # variables. Each variable is the empty string if the python that we # haven't isn't recent enough for that use, or the path to a python # executable if it is recent enough. # # NB: Cannot use AC_CONFIG_LIBOBJ_DIR here, because it's not present # in autoconf 2.53. AC_PATH_PROGS(PYTHON, [python2.5 python-2.5 python2.4 python-2.4 python]) AC_ARG_VAR(PYTHON, [Python interpreter]) # Python 1 doesn't even support -V if ! "$PYTHON" -V 2>&1 | grep "^Python" >/dev/null; then TEST_PYTHON="" INCLUDESERVER_PYTHON="" elif "$PYTHON" -V 2>&1 | grep "^Python 2.1" >/dev/null; then TEST_PYTHON="" INCLUDESERVER_PYTHON="" elif "$PYTHON" -V 2>&1 | grep "^Python 2.[[23]]" >/dev/null; then TEST_PYTHON="$PYTHON" INCLUDESERVER_PYTHON="" else TEST_PYTHON="$PYTHON" INCLUDESERVER_PYTHON="$PYTHON" fi AC_SUBST(TEST_PYTHON) AC_SUBST(INCLUDESERVER_PYTHON) AC_SUBST(PYTHON_RELATIVE_LIB) 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 #endif ]) AC_CHECK_HEADERS([arpa/nameser.h], [], [], [#if HAVE_SYS_TYPES_H # include #endif ]) AC_CHECK_HEADERS([resolv.h], [], [], [#if HAVE_SYS_TYPES_H # include #endif #if HAVE_NETINET_IN_H # include #endif #if HAVE_ARPA_NAMESER_H # include #endif ]) AC_CHECK_HEADERS([float.h mcheck.h alloca.h sys/mman.h sys/loadavg.h]) AC_CHECK_HEADERS([elf.h]) AC_CHECK_HEADERS([fnmatch.h]) ###################################################################### dnl Checks for types AC_CHECK_TYPES([in_port_t, in_addr_t], , , [ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_SOCKET_H # include #endif #if HAVE_NETINET_IN_H # include #endif #if HAVE_ARPA_NAMESER_H # include #endif ]) ######################################################################## ### Checks for libraries. # The following test taken from the cvs sources via Samba: # If we can't find connect, try looking in -lsocket, -lnsl, and -linet. # The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has # libsocket.so which has a bad implementation of gethostbyname (it # only looks in /etc/hosts), so we only look for -lsocket if we need # it. AC_SEARCH_LIBS(gethostent, [nsl]) AC_SEARCH_LIBS(setsockopt, [socket]) AC_SEARCH_LIBS(hstrerror, [resolv]) AC_SEARCH_LIBS(inet_aton, [resolv]) if test x"$with_included_popt" != x"yes" && test x"$with_included_popt" != xno then # If not explicitly requested, guess. # People might have the library but not the header, in which case we # still need to use the included copy. AC_CHECK_HEADER(popt.h, , [with_included_popt=yes]) fi AC_CACHE_SAVE AC_MSG_CHECKING([whether to use included libpopt]) if test x"$with_included_popt" = x"yes" then AC_MSG_RESULT($srcdir/popt) # popt_OBJS gets appended to distccd object list BUILD_POPT='$(popt_OBJS)' POPT_INCLUDES='-I"$(srcdir)/popt"' else LIBS="$LIBS -lpopt" AC_MSG_RESULT(no) POPT_INCLUDES='' fi ######################################################################## # Check for types AC_TYPE_SIGNAL ######################################################################## # Checks for library functions, using libraries discovered above # The line below was commented out: it should not be necessary for the # AC_CHECK_FUNCS, which link against libraries on the host. For the subsequent # explicit compilation tests below, no distcc libraries are used. # TODO(klarlund): remove the line. # CPPFLAGS="$CPPFLAGS -I$srcdir/src" AC_CHECK_FUNCS([getpagesize]) AC_CHECK_FUNCS([sendfile setsid flock lockf hstrerror strerror setuid setreuid]) AC_CHECK_FUNCS([getuid geteuid mcheck wait4 wait3 waitpid setgroups]) AC_CHECK_FUNCS([snprintf vsnprintf vasprintf asprintf getcwd getwd mkdtemp]) AC_CHECK_FUNCS([getrusage strsignal gettimeofday]) AC_CHECK_FUNCS([getaddrinfo getnameinfo inet_ntop inet_ntoa]) AC_CHECK_FUNCS([strndup strsep mmap strlcpy]) AC_CHECK_FUNCS([getloadavg]) AC_CHECK_DECLS([snprintf, vsnprintf, vasprintf, asprintf, strndup]) AC_MSG_CHECKING([if mmap() supports MAP_FAILED]) AC_TRY_COMPILE([ #ifdef HAVE_SYS_MMAN_H # include #endif],[ #ifdef HAVE_MMAP if (mmap (NULL, 0, 0, 0, 0, 0) == MAP_FAILED) return 0; #else #error mmap unavailable #endif], ,[ AC_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],dcc_cv_HAVE_VA_COPY,[ AC_TRY_LINK([#include va_list ap1,ap2;], [va_copy(ap1,ap2);], dcc_cv_HAVE_VA_COPY=yes,dcc_cv_HAVE_VA_COPY=no)]) if test x"$dcc_cv_HAVE_VA_COPY" = x"yes"; then AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available]) fi AC_CACHE_CHECK([for __va_copy],dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY,[ AC_TRY_LINK([#include va_list ap1,ap2;], [__va_copy(ap1,ap2);], dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY=yes,dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY=no)]) if test x"$dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY" = x"yes"; then AC_DEFINE(HAVE_UNDERSCORE_UNDERSCORE_VA_COPY,1,[Whether __va_copy() is available]) fi AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[ AC_TRY_RUN([ #include #include 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 #include 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 ]) AC_ARG_WITH(avahi, AC_HELP_STRING([--without-avahi], [build without avahi])) dnl check for avahi if test x"$with_avahi" != xno; then PKG_CHECK_MODULES(AVAHI, [avahi-client >= 0.6], [AC_DEFINE(HAVE_AVAHI, 1, [defined if Avahi is available]) CFLAGS="$CFLAGS $AVAHI_CFLAGS" LIBS="$LIBS $AVAHI_LIBS" ZEROCONF_COMMON_OBJS="src/zeroconf.o src/gcc-id.o" ZEROCONF_DISTCC_OBJS="" ZEROCONF_DISTCCD_OBJS="src/zeroconf-reg.o"], [ZEROCONF_COMMON_OBJS="" ZEROCONF_DISTCC_OBJS="" ZEROCONF_DISTCCD_OBJS=""]) AC_SUBST(ZEROCONF_COMMON_OBJS) AC_SUBST(ZEROCONF_DISTCC_OBJS) AC_SUBST(ZEROCONF_DISTCCD_OBJS) fi ACX_PTHREAD LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" dnl ##### Output AC_SUBST(docdir) AC_SUBST(CFLAGS) AC_SUBST(LDFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(POPT_INCLUDES) AC_SUBST(BUILD_POPT) AC_SUBST(GNOME_BIN) AC_DEFINE_UNQUOTED(GNU_HOST, ["$host"], [Your gnu-style host triple]) # The '.stamp-conf' files force creation of the containing directories in the # build tree. AC_CONFIG_FILES([Makefile] popt/.stamp-conf lzo/.stamp-conf) AC_CONFIG_FILES([pump], [chmod +x pump]) AC_OUTPUT ##### Finalization # Display success, installation paths, and GPL licence statement. echo ' ' ${MAKE-make} showpaths echo ' ' cat < Portions Copyright 2005 Google Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. After installing distcc, please complete the survey in the file "survey.txt". EOF distcc-3.1/source/configure0000750000175000017500000110676411115326652015065 0ustar wolffwolff#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for distcc 3.1. # # Report bugs to . # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` exec 6>&1 # # Initializations. # ac_default_prefix=/usr/local ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. # This variable seems obsolete. It should probably be removed, and # only ac_max_sed_lines should be used. : ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME='distcc' PACKAGE_TARNAME='distcc' PACKAGE_VERSION='3.1' PACKAGE_STRING='distcc 3.1' PACKAGE_BUGREPORT='distcc@lists.samba.org' # Factoring default headers for most tests. ac_includes_default="\ #include #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_STAT_H # include #endif #if STDC_HEADERS # include # include #else # if HAVE_STDLIB_H # include # endif #endif #if HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #endif #if HAVE_STRINGS_H # include #endif #if HAVE_INTTYPES_H # include #else # if HAVE_STDINT_H # include # endif #endif #if HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os docdir CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT GNOME_PACKAGES GNOME_CFLAGS GNOME_LIBS INSTALL_GNOME UNINSTALL_GNOME WERROR_CFLAGS POPT_CFLAGS PYTHON_CFLAGS SET_MAKE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA PYTHON TEST_PYTHON INCLUDESERVER_PYTHON PYTHON_RELATIVE_LIB CPP EGREP PKG_CONFIG ac_pt_PKG_CONFIG AVAHI_CFLAGS AVAHI_LIBS ZEROCONF_COMMON_OBJS ZEROCONF_DISTCC_OBJS ZEROCONF_DISTCCD_OBJS acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS POPT_INCLUDES BUILD_POPT GNOME_BIN LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_option in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` eval "enable_$ac_feature=no" ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "enable_$ac_feature='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package| sed 's/-/_/g'` case $ac_option in *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; *) ac_optarg=yes ;; esac eval "with_$ac_package='$ac_optarg'" ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/-/_/g'` eval "with_$ac_package=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` eval "$ac_envvar='$ac_optarg'" export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute paths. for ac_var in exec_prefix prefix do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* | NONE | '' ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in [\\/$]* | ?:[\\/]* ) ;; *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; };; esac done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 { (exit 1); exit 1; }; } else { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi fi (cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias ac_cv_env_build_alias_set=${build_alias+set} ac_cv_env_build_alias_value=$build_alias ac_env_host_alias_set=${host_alias+set} ac_env_host_alias_value=$host_alias ac_cv_env_host_alias_set=${host_alias+set} ac_cv_env_host_alias_value=$host_alias ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias ac_env_CC_set=${CC+set} ac_env_CC_value=$CC ac_cv_env_CC_set=${CC+set} ac_cv_env_CC_value=$CC ac_env_CFLAGS_set=${CFLAGS+set} ac_env_CFLAGS_value=$CFLAGS ac_cv_env_CFLAGS_set=${CFLAGS+set} ac_cv_env_CFLAGS_value=$CFLAGS ac_env_LDFLAGS_set=${LDFLAGS+set} ac_env_LDFLAGS_value=$LDFLAGS ac_cv_env_LDFLAGS_set=${LDFLAGS+set} ac_cv_env_LDFLAGS_value=$LDFLAGS ac_env_CPPFLAGS_set=${CPPFLAGS+set} ac_env_CPPFLAGS_value=$CPPFLAGS ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_PYTHON_set=${PYTHON+set} ac_env_PYTHON_value=$PYTHON ac_cv_env_PYTHON_set=${PYTHON+set} ac_cv_env_PYTHON_value=$PYTHON ac_env_CPP_set=${CPP+set} ac_env_CPP_value=$CPP ac_cv_env_CPP_set=${CPP+set} ac_cv_env_CPP_value=$CPP ac_env_PKG_CONFIG_set=${PKG_CONFIG+set} ac_env_PKG_CONFIG_value=$PKG_CONFIG ac_cv_env_PKG_CONFIG_set=${PKG_CONFIG+set} ac_cv_env_PKG_CONFIG_value=$PKG_CONFIG ac_env_AVAHI_CFLAGS_set=${AVAHI_CFLAGS+set} ac_env_AVAHI_CFLAGS_value=$AVAHI_CFLAGS ac_cv_env_AVAHI_CFLAGS_set=${AVAHI_CFLAGS+set} ac_cv_env_AVAHI_CFLAGS_value=$AVAHI_CFLAGS ac_env_AVAHI_LIBS_set=${AVAHI_LIBS+set} ac_env_AVAHI_LIBS_value=$AVAHI_LIBS ac_cv_env_AVAHI_LIBS_set=${AVAHI_LIBS+set} ac_cv_env_AVAHI_LIBS_value=$AVAHI_LIBS # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures distcc 3.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data [PREFIX/share] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --infodir=DIR info documentation [PREFIX/info] --mandir=DIR man documentation [PREFIX/man] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of distcc 3.1:";; esac cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-rfc2553 use getaddrinfo, getnameinfo, etc --enable-profile turn on gprof --disable-Werror don't use gcc's -Werror option when building Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-docdir=DIR Use DIR to store documentation files (default ${datadir}/doc/distcc) --with-included-popt use bundled popt library, not from system --with-gnome build GNOME-based monitor --with-gtk build GTK+-based monitor --without-avahi build without avahi Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory PYTHON Python interpreter CPP C preprocessor PKG_CONFIG path to pkg-config utility AVAHI_CFLAGS C compiler flags for AVAHI, overriding pkg-config AVAHI_LIBS linker flags for AVAHI, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d $ac_dir || continue ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. if test -f $ac_srcdir/configure.gnu; then echo $SHELL $ac_srcdir/configure.gnu --help=recursive elif test -f $ac_srcdir/configure; then echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || test -f $ac_srcdir/configure.in; then echo $ac_configure --help else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi cd "$ac_popdir" done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF distcc configure 3.1 generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit 0 fi exec 5>config.log cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by distcc $as_me 3.1, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ _ACEOF { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` 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 || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` hostinfo = `(hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. ac_sep=" " ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Be sure not to use single quotes in there, as some shells, # such as our DU 5.0 friend, will then `close' the trap. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, { (set) 2>&1 | case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------- ## ## Output files. ## ## ------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo >confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . $cache_file;; *) . ./$cache_file;; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" eval ac_new_val="\$ac_env_${ac_var}_value" case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers src/config.h" ac_aux_dir= for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do if test -f $ac_dir/install-sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f $ac_dir/install.sh; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f $ac_dir/shtool; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} { (exit 1); exit 1; }; } fi ac_config_guess="$SHELL $ac_aux_dir/config.guess" ac_config_sub="$SHELL $ac_aux_dir/config.sub" ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # Make sure we can run config.sub. $ac_config_sub sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 echo "$as_me: error: cannot run $ac_config_sub" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: checking build system type" >&5 echo $ECHO_N "checking build system type... $ECHO_C" >&6 if test "${ac_cv_build+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_build_alias=$build_alias test -z "$ac_cv_build_alias" && ac_cv_build_alias=`$ac_config_guess` test -z "$ac_cv_build_alias" && { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 echo "$as_me: error: cannot guess build type; you must specify one" >&2;} { (exit 1); exit 1; }; } ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_build" >&5 echo "${ECHO_T}$ac_cv_build" >&6 build=$ac_cv_build build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$as_me:$LINENO: checking host system type" >&5 echo $ECHO_N "checking host system type... $ECHO_C" >&6 if test "${ac_cv_host+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_host_alias=$host_alias test -z "$ac_cv_host_alias" && ac_cv_host_alias=$ac_cv_build_alias ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: result: $ac_cv_host" >&5 echo "${ECHO_T}$ac_cv_host" >&6 host=$ac_cv_host host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # 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 # Check whether --with-docdir or --without-docdir was given. if test "${with_docdir+set}" = set; then withval="$with_docdir" with_docdir=$withval fi; if test "x$with_docdir" = "x" ; then docdir='${datadir}/doc/distcc' else docdir=$with_docdir fi # Check for socklen_t, and do something appropiate on systems # that don't have it. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Find the output, starting from the most likely. This scheme is # not robust to junk in `.', hence go to wildcards (a.*) only as a last # resort. # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= # b.out is created by i960 compilers. for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; conftest.$ac_ext ) # This is the source file. ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` # FIXME: I believe we export ac_cv_exeext for Libtool, # but it would be cool to find out if it's true. Does anybody # maintain Libtool? --akim. export ac_cv_exeext break;; * ) break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6 # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6 echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` export ac_cv_exeext break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6 rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6 OBJEXT=$ac_cv_objext ac_objext=$OBJEXT echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for socklen_t" >&5 echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6 if test "${ac_cv_type_socklen_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { if ((socklen_t *) 0) return 0; if (sizeof (socklen_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_socklen_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_socklen_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5 echo "${ECHO_T}$ac_cv_type_socklen_t" >&6 if test $ac_cv_type_socklen_t = yes; then : else echo "$as_me:$LINENO: checking for socklen_t equivalent" >&5 echo $ECHO_N "checking for socklen_t equivalent... $ECHO_C" >&6 if test "${dcc_cv_socklen_t_equiv+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # 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 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int getpeername (int, $arg2 *, $t *); int main () { $t len; getpeername(0,0,&len); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then dcc_cv_socklen_t_equiv="$t" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done done if test "x$dcc_cv_socklen_t_equiv" = x; then { { echo "$as_me:$LINENO: error: Cannot find a type to use in place of socklen_t" >&5 echo "$as_me: error: Cannot find a type to use in place of socklen_t" >&2;} { (exit 1); exit 1; }; } fi fi echo "$as_me:$LINENO: result: $dcc_cv_socklen_t_equiv" >&5 echo "${ECHO_T}$dcc_cv_socklen_t_equiv" >&6 cat >>confdefs.h <<_ACEOF #define socklen_t $dcc_cv_socklen_t_equiv _ACEOF fi # TODO: Handle program transform rules by autoconf. ### Checks for configure options # Check whether --with-included-popt or --without-included-popt was given. if test "${with_included_popt+set}" = set; then withval="$with_included_popt" fi; # Check whether --enable-rfc2553 or --disable-rfc2553 was given. if test "${enable_rfc2553+set}" = set; then enableval="$enable_rfc2553" cat >>confdefs.h <<\_ACEOF #define ENABLE_RFC2553 1 _ACEOF fi; # Check whether --with-gnome or --without-gnome was given. if test "${with_gnome+set}" = set; then withval="$with_gnome" fi; if test x"$with_gnome" = xyes then GNOME_BIN=distccmon-gnome cat >>confdefs.h <<\_ACEOF #define WITH_GNOME 1 _ACEOF fi # Check whether --with-gtk or --without-gtk was given. if test "${with_gtk+set}" = set; then withval="$with_gtk" fi; if test x"$with_gtk" = xyes then GNOME_BIN=distccmon-gnome cat >>confdefs.h <<\_ACEOF #define WITH_GTK 1 _ACEOF fi # Check whether --enable-profile or --disable-profile was given. if test "${enable_profile+set}" = set; then enableval="$enable_profile" fi; if test x"$enable_profile" = xyes then CFLAGS="$CFLAGS -pg -g" fi # Check whether --enable-Werror or --disable-Werror was given. if test "${enable_Werror+set}" = set; then enableval="$enable_Werror" 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 echo "$as_me:$LINENO: checking version of $pkg" >&5 echo $ECHO_N "checking version of $pkg... $ECHO_C" >&6 if gnomevers=`pkg-config --modversion $pkg` then echo "$as_me:$LINENO: result: $gnomevers" >&5 echo "${ECHO_T}$gnomevers" >&6 else { { echo "$as_me:$LINENO: error: $pkg was not found by pkg-config" >&5 echo "$as_me: error: $pkg was not found by pkg-config" >&2;} { (exit 1); exit 1; }; } fi done if test x${with_gnome} = xyes -o x${with_gtk} = xyes then INSTALL_GNOME="install-gnome-data" UNINSTALL_GNOME="uninstall-gnome-data" echo "$as_me:$LINENO: checking GNOME/GTK+ cflags" >&5 echo $ECHO_N "checking GNOME/GTK+ cflags... $ECHO_C" >&6 GNOME_CFLAGS="`pkg-config --cflags $GNOME_PACKAGES`" || { { echo "$as_me:$LINENO: error: failed to get cflags" >&5 echo "$as_me: error: failed to get cflags" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: result: ${GNOME_CFLAGS}" >&5 echo "${ECHO_T}${GNOME_CFLAGS}" >&6 echo "$as_me:$LINENO: checking GNOME/GTK+ libraries" >&5 echo $ECHO_N "checking GNOME/GTK+ libraries... $ECHO_C" >&6 GNOME_LIBS="`pkg-config --libs $GNOME_PACKAGES`" || { { echo "$as_me:$LINENO: error: failed to get libs" >&5 echo "$as_me: error: failed to get libs" >&2;} { (exit 1); exit 1; }; } echo "$as_me:$LINENO: result: ${GNOME_LIBS}" >&5 echo "${ECHO_T}${GNOME_LIBS}" >&6 fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi CC=$ac_ct_CC else CC="$ac_cv_prog_CC" fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$ac_ct_CC" && break done CC=$ac_ct_CC fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO:" \ "checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 (eval $ac_compiler --version &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 (eval $ac_compiler -v &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 (eval $ac_compiler -V &5) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS CFLAGS="-g" echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 if test "${ac_cv_prog_cc_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std1 is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std1. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF # Don't try gcc -ansi; that turns off useful extensions and # breaks some systems' header files. # AIX -qlanglvl=ansi # Ultrix and OSF/1 -std1 # HP-UX 10.20 and later -Ae # HP-UX older versions -Aa -D_HPUX_SOURCE # SVR4 -Xc -D__EXTENSIONS__ for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_prog_cc_stdc=$ac_arg break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC fi case "x$ac_cv_prog_cc_stdc" in x|xno) echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6 ;; *) echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 CC="$CC $ac_cv_prog_cc_stdc" ;; esac # Some people use a C++ compiler to compile C. Since we use `exit', # in C++ we need to declare it. In case someone uses the same compiler # for both compiling C and C++ we need to have the C++ compiler decide # the declaration of exit, since it's the most demanding environment. cat >conftest.$ac_ext <<_ACEOF #ifndef __cplusplus choke me #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration #include int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 continue fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_declaration int main () { exit (42); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then echo '#ifdef __cplusplus' >>confdefs.h echo $ac_declaration >>confdefs.h echo '#endif' >>confdefs.h fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu WERROR_CFLAGS="" POPT_CFLAGS="" PYTHON_CFLAGS="" if test x"$GCC" = xyes then CFLAGS="$CFLAGS -MD \ -W -Wall -Wimplicit \ -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings \ -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes \ -Wnested-externs -Wmissing-declarations" # -Wuninitialized requires -O case "$CFLAGS" in "-O"*|*" -O"*) CFLAGS="$CFLAGS -Wuninitialized" ;; esac # Would like -Wunreachable-code here, but it generates too many false # positives. # We want warnings to be treated as errors, # unless the --disable-Werror configure option was used. # Note that we can't include this in CFLAGS, # because that would affect the configure tests, # causing some of the tests to fail when they should succeed. if test x"$enable_Werror" != xno then WERROR_CFLAGS="-Werror" fi # Additional flags for compiling Python extension modules. # We disable -Wmissing-prototypes and -Wmissing-declarations, # which don't apply to python extensions (it exports global fns via a # pointer), and -Wwrite-strings, which just had too many false # positives (for Python 2.2, anyway; looks like these may be fixed # in Python 2.5). # -Wp,-U_FORTIFY_SOURCE is to turn off _FORTIFY_SOURCE on systems where # it's in the Python Makefile (and hence inherited by us). # _FORTIFY_SOURCE gives compiler errors for some distcc routines that # ignore the return value from libc functions (like getcwd). # That would cause this code to not compile, which is no good. PYTHON_CFLAGS="-Wno-missing-prototypes -Wno-missing-declarations \ -Wno-write-strings -Wp,-U_FORTIFY_SOURCE" # For popt/*.c, we disable unused variable warnings. POPT_CFLAGS="-Wno-unused" { echo "$as_me:$LINENO: Adding gcc options: $CFLAGS" >&5 echo "$as_me: Adding gcc options: $CFLAGS" >&6;} fi echo "$as_me:$LINENO: checking for strerror in -lcposix" >&5 echo $ECHO_N "checking for strerror in -lcposix... $ECHO_C" >&6 if test "${ac_cv_lib_cposix_strerror+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcposix $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char strerror (); int main () { strerror (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_lib_cposix_strerror=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_cposix_strerror=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_cposix_strerror" >&5 echo "${ECHO_T}$ac_cv_lib_cposix_strerror" >&6 if test $ac_cv_lib_cposix_strerror = yes; then LIBS="$LIBS -lcposix" fi # 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. # TODO(csilvers): figure out what that above comment means, and if it's true. CPPFLAGS="$CPPFLAGS -DHAVE_CONFIG_H" # Needed to get various GNU-only functions. They're all autodetected # by configure so we can cope without them, but we want them if they're # there. CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftest.make fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 SET_MAKE= else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. We don't cache a # path for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the path is relative. INSTALL=$ac_install_sh fi fi echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6 # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # We prefer to use the latest Python, but try to find an explicit # version to make sure we don't get a really old one. # # The include server requires python 2.4 or later, but the 'make test' # routines only require python 2.2. Thus we have two separate # variables. Each variable is the empty string if the python that we # haven't isn't recent enough for that use, or the path to a python # executable if it is recent enough. # # NB: Cannot use AC_CONFIG_LIBOBJ_DIR here, because it's not present # in autoconf 2.53. for ac_prog in python2.5 python-2.5 python2.4 python-2.4 python do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_PYTHON+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $PYTHON in [\\/]* | ?:[\\/]*) ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi PYTHON=$ac_cv_path_PYTHON if test -n "$PYTHON"; then echo "$as_me:$LINENO: result: $PYTHON" >&5 echo "${ECHO_T}$PYTHON" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$PYTHON" && break done # Python 1 doesn't even support -V if ! "$PYTHON" -V 2>&1 | grep "^Python" >/dev/null; then TEST_PYTHON="" INCLUDESERVER_PYTHON="" elif "$PYTHON" -V 2>&1 | grep "^Python 2.1" >/dev/null; then TEST_PYTHON="" INCLUDESERVER_PYTHON="" elif "$PYTHON" -V 2>&1 | grep "^Python 2.[23]" >/dev/null; then TEST_PYTHON="$PYTHON" INCLUDESERVER_PYTHON="" else TEST_PYTHON="$PYTHON" INCLUDESERVER_PYTHON="$PYTHON" fi echo "$as_me:$LINENO: checking for inline" >&5 echo $ECHO_N "checking for inline... $ECHO_C" >&6 if test "${ac_cv_c_inline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_inline=$ac_kw; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done fi echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 echo "${ECHO_T}$ac_cv_c_inline" >&6 case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 if test "${ac_cv_c_bigendian+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # See if sys/param.h defines the BYTE_ORDER macro. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { #if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN bogus endian macros #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then # It does; now see whether it defined to BIG_ENDIAN or not. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_bigendian=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_bigendian=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # It does not; compile a test program. if test "$cross_compiling" = yes; then # try to guess the endianness by grepping values into an object file ac_cv_c_bigendian=unknown cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } int main () { _ascii (); _ebcdic (); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long l; char c[sizeof (long)]; } u; u.l = 1; exit (u.c[sizeof (long) - 1] == 1); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_c_bigendian=no else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_c_bigendian=yes fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 echo "${ECHO_T}$ac_cv_c_bigendian" >&6 case $ac_cv_c_bigendian in yes) cat >>confdefs.h <<\_ACEOF #define WORDS_BIGENDIAN 1 _ACEOF ;; no) ;; *) { { echo "$as_me:$LINENO: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&5 echo "$as_me: error: unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} { (exit 1); exit 1; }; } ;; esac ######################################################################## ### Checks for header files # Some of these are needed by popt (or other libraries included in the future). ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6 ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6 if test "${ac_cv_prog_egrep+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | (grep -E '(a|b)') >/dev/null 2>&1 then ac_cv_prog_egrep='grep -E' else ac_cv_prog_egrep='egrep' fi fi echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 echo "${ECHO_T}$ac_cv_prog_egrep" >&6 EGREP=$ac_cv_prog_egrep echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6 if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in unistd.h sys/types.h sys/sendfile.h sys/signal.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------- ## ## Report this to distcc@lists.samba.org ## ## ------------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in ctype.h sys/resource.h sys/socket.h sys/select.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------- ## ## Report this to distcc@lists.samba.org ## ## ------------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in netinet/in.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_SYS_TYPES_H # include #endif #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in arpa/nameser.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_SYS_TYPES_H # include #endif #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in resolv.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_NETINET_IN_H # include #endif #if HAVE_ARPA_NAMESER_H # include #endif #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in float.h mcheck.h alloca.h sys/mman.h sys/loadavg.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------- ## ## Report this to distcc@lists.samba.org ## ## ------------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in elf.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------- ## ## Report this to distcc@lists.samba.org ## ## ------------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in fnmatch.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------- ## ## Report this to distcc@lists.samba.org ## ## ------------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ###################################################################### echo "$as_me:$LINENO: checking for in_port_t" >&5 echo $ECHO_N "checking for in_port_t... $ECHO_C" >&6 if test "${ac_cv_type_in_port_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_SOCKET_H # include #endif #if HAVE_NETINET_IN_H # include #endif #if HAVE_ARPA_NAMESER_H # include #endif int main () { if ((in_port_t *) 0) return 0; if (sizeof (in_port_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_in_port_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_in_port_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_in_port_t" >&5 echo "${ECHO_T}$ac_cv_type_in_port_t" >&6 if test $ac_cv_type_in_port_t = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_IN_PORT_T 1 _ACEOF fi echo "$as_me:$LINENO: checking for in_addr_t" >&5 echo $ECHO_N "checking for in_addr_t... $ECHO_C" >&6 if test "${ac_cv_type_in_addr_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if HAVE_SYS_TYPES_H # include #endif #if HAVE_SYS_SOCKET_H # include #endif #if HAVE_NETINET_IN_H # include #endif #if HAVE_ARPA_NAMESER_H # include #endif int main () { if ((in_addr_t *) 0) return 0; if (sizeof (in_addr_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_in_addr_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_in_addr_t=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_in_addr_t" >&5 echo "${ECHO_T}$ac_cv_type_in_addr_t" >&6 if test $ac_cv_type_in_addr_t = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_IN_ADDR_T 1 _ACEOF fi ######################################################################## ### 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. echo "$as_me:$LINENO: checking for library containing gethostent" >&5 echo $ECHO_N "checking for library containing gethostent... $ECHO_C" >&6 if test "${ac_cv_search_gethostent+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_gethostent=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostent (); int main () { gethostent (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_gethostent="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_gethostent" = no; then for ac_lib in nsl; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char gethostent (); int main () { gethostent (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_gethostent="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_gethostent" >&5 echo "${ECHO_T}$ac_cv_search_gethostent" >&6 if test "$ac_cv_search_gethostent" != no; then test "$ac_cv_search_gethostent" = "none required" || LIBS="$ac_cv_search_gethostent $LIBS" fi echo "$as_me:$LINENO: checking for library containing setsockopt" >&5 echo $ECHO_N "checking for library containing setsockopt... $ECHO_C" >&6 if test "${ac_cv_search_setsockopt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_setsockopt=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char setsockopt (); int main () { setsockopt (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_setsockopt="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_setsockopt" = no; then for ac_lib in socket; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char setsockopt (); int main () { setsockopt (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_setsockopt="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_setsockopt" >&5 echo "${ECHO_T}$ac_cv_search_setsockopt" >&6 if test "$ac_cv_search_setsockopt" != no; then test "$ac_cv_search_setsockopt" = "none required" || LIBS="$ac_cv_search_setsockopt $LIBS" fi echo "$as_me:$LINENO: checking for library containing hstrerror" >&5 echo $ECHO_N "checking for library containing hstrerror... $ECHO_C" >&6 if test "${ac_cv_search_hstrerror+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_hstrerror=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char hstrerror (); int main () { hstrerror (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_hstrerror="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_hstrerror" = no; then for ac_lib in resolv; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char hstrerror (); int main () { hstrerror (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_hstrerror="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_hstrerror" >&5 echo "${ECHO_T}$ac_cv_search_hstrerror" >&6 if test "$ac_cv_search_hstrerror" != no; then test "$ac_cv_search_hstrerror" = "none required" || LIBS="$ac_cv_search_hstrerror $LIBS" fi echo "$as_me:$LINENO: checking for library containing inet_aton" >&5 echo $ECHO_N "checking for library containing inet_aton... $ECHO_C" >&6 if test "${ac_cv_search_inet_aton+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS ac_cv_search_inet_aton=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char inet_aton (); int main () { inet_aton (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_inet_aton="none required" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_search_inet_aton" = no; then for ac_lib in resolv; do LIBS="-l$ac_lib $ac_func_search_save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char inet_aton (); int main () { inet_aton (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_search_inet_aton="-l$ac_lib" break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done fi LIBS=$ac_func_search_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_search_inet_aton" >&5 echo "${ECHO_T}$ac_cv_search_inet_aton" >&6 if test "$ac_cv_search_inet_aton" != no; then test "$ac_cv_search_inet_aton" = "none required" || LIBS="$ac_cv_search_inet_aton $LIBS" fi 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. if test "${ac_cv_header_popt_h+set}" = set; then echo "$as_me:$LINENO: checking for popt.h" >&5 echo $ECHO_N "checking for popt.h... $ECHO_C" >&6 if test "${ac_cv_header_popt_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi echo "$as_me:$LINENO: result: $ac_cv_header_popt_h" >&5 echo "${ECHO_T}$ac_cv_header_popt_h" >&6 else # Is the header compilable? echo "$as_me:$LINENO: checking popt.h usability" >&5 echo $ECHO_N "checking popt.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? echo "$as_me:$LINENO: checking popt.h presence" >&5 echo $ECHO_N "checking popt.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null; then if test -s conftest.err; then ac_cpp_err=$ac_c_preproc_warn_flag ac_cpp_err=$ac_cpp_err$ac_c_werror_flag else ac_cpp_err= fi else ac_cpp_err=yes fi if test -z "$ac_cpp_err"; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: popt.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: popt.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: popt.h: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: popt.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: popt.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: popt.h: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: popt.h: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: popt.h: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: popt.h: see the Autoconf documentation" >&5 echo "$as_me: WARNING: popt.h: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: popt.h: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: popt.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: popt.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: popt.h: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: popt.h: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: popt.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ------------------------------------- ## ## Report this to distcc@lists.samba.org ## ## ------------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac echo "$as_me:$LINENO: checking for popt.h" >&5 echo $ECHO_N "checking for popt.h... $ECHO_C" >&6 if test "${ac_cv_header_popt_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_header_popt_h=$ac_header_preproc fi echo "$as_me:$LINENO: result: $ac_cv_header_popt_h" >&5 echo "${ECHO_T}$ac_cv_header_popt_h" >&6 fi if test $ac_cv_header_popt_h = yes; then : else with_included_popt=yes fi fi cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache echo "$as_me:$LINENO: checking whether to use included libpopt" >&5 echo $ECHO_N "checking whether to use included libpopt... $ECHO_C" >&6 if test x"$with_included_popt" = x"yes" then echo "$as_me:$LINENO: result: $srcdir/popt" >&5 echo "${ECHO_T}$srcdir/popt" >&6 # popt_OBJS gets appended to distccd object list BUILD_POPT='$(popt_OBJS)' POPT_INCLUDES='-I"$(srcdir)/popt"' else LIBS="$LIBS -lpopt" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 POPT_INCLUDES='' fi ######################################################################## # Check for types echo "$as_me:$LINENO: checking return type of signal handlers" >&5 echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6 if test "${ac_cv_type_signal+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #ifdef signal # undef signal #endif #ifdef __cplusplus extern "C" void (*signal (int, void (*)(int)))(int); #else void (*signal ()) (); #endif int main () { int i; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_type_signal=void else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_signal=int fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 echo "${ECHO_T}$ac_cv_type_signal" >&6 cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF ######################################################################## # Checks for library functions, using libraries discovered above # The line below was commented out: it should not be necessary for the # AC_CHECK_FUNCS, which link against libraries on the host. For the subsequent # explicit compilation tests below, no distcc libraries are used. # TODO(klarlund): remove the line. # CPPFLAGS="$CPPFLAGS -I$srcdir/src" for ac_func in getpagesize do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in sendfile setsid flock lockf hstrerror strerror setuid setreuid do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in getuid geteuid mcheck wait4 wait3 waitpid setgroups do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in snprintf vsnprintf vasprintf asprintf getcwd getwd mkdtemp do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in getrusage strsignal gettimeofday do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in getaddrinfo getnameinfo inet_ntop inet_ntoa do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in strndup strsep mmap strlcpy do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in getloadavg do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 if eval "test \"\${$as_ac_var+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" { #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else char (*f) () = $ac_func; #endif #ifdef __cplusplus } #endif int main () { return f != $ac_func; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done echo "$as_me:$LINENO: checking whether snprintf is declared" >&5 echo $ECHO_N "checking whether snprintf is declared... $ECHO_C" >&6 if test "${ac_cv_have_decl_snprintf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { #ifndef snprintf char *p = (char *) snprintf; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_have_decl_snprintf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_snprintf=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_have_decl_snprintf" >&5 echo "${ECHO_T}$ac_cv_have_decl_snprintf" >&6 if test $ac_cv_have_decl_snprintf = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SNPRINTF 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SNPRINTF 0 _ACEOF fi echo "$as_me:$LINENO: checking whether vsnprintf is declared" >&5 echo $ECHO_N "checking whether vsnprintf is declared... $ECHO_C" >&6 if test "${ac_cv_have_decl_vsnprintf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { #ifndef vsnprintf char *p = (char *) vsnprintf; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_have_decl_vsnprintf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_vsnprintf=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_have_decl_vsnprintf" >&5 echo "${ECHO_T}$ac_cv_have_decl_vsnprintf" >&6 if test $ac_cv_have_decl_vsnprintf = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_VSNPRINTF 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_VSNPRINTF 0 _ACEOF fi echo "$as_me:$LINENO: checking whether vasprintf is declared" >&5 echo $ECHO_N "checking whether vasprintf is declared... $ECHO_C" >&6 if test "${ac_cv_have_decl_vasprintf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { #ifndef vasprintf char *p = (char *) vasprintf; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_have_decl_vasprintf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_vasprintf=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_have_decl_vasprintf" >&5 echo "${ECHO_T}$ac_cv_have_decl_vasprintf" >&6 if test $ac_cv_have_decl_vasprintf = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_VASPRINTF 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_VASPRINTF 0 _ACEOF fi echo "$as_me:$LINENO: checking whether asprintf is declared" >&5 echo $ECHO_N "checking whether asprintf is declared... $ECHO_C" >&6 if test "${ac_cv_have_decl_asprintf+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { #ifndef asprintf char *p = (char *) asprintf; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_have_decl_asprintf=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_asprintf=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_have_decl_asprintf" >&5 echo "${ECHO_T}$ac_cv_have_decl_asprintf" >&6 if test $ac_cv_have_decl_asprintf = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_ASPRINTF 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_ASPRINTF 0 _ACEOF fi echo "$as_me:$LINENO: checking whether strndup is declared" >&5 echo $ECHO_N "checking whether strndup is declared... $ECHO_C" >&6 if test "${ac_cv_have_decl_strndup+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { #ifndef strndup char *p = (char *) strndup; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_have_decl_strndup=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_have_decl_strndup=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_have_decl_strndup" >&5 echo "${ECHO_T}$ac_cv_have_decl_strndup" >&6 if test $ac_cv_have_decl_strndup = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRNDUP 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRNDUP 0 _ACEOF fi echo "$as_me:$LINENO: checking if mmap() supports MAP_FAILED" >&5 echo $ECHO_N "checking if mmap() supports MAP_FAILED... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef HAVE_SYS_MMAN_H # include #endif int main () { #ifdef HAVE_MMAP if (mmap (NULL, 0, 0, 0, 0, 0) == MAP_FAILED) return 0; #else #error mmap unavailable #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >>confdefs.h <<\_ACEOF #define MAP_FAILED (void *)-1L _ACEOF fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: " >&5 echo "${ECHO_T}" >&6 echo "$as_me:$LINENO: checking for vararg macro support" >&5 echo $ECHO_N "checking for vararg macro support... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define func(a, b...) do { } while (0) int main () { func("a"); func("a", "b"); func("a", "b", "c") ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define HAVE_VARARG_MACROS _ACEOF else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: checking for va_copy" >&5 echo $ECHO_N "checking for va_copy... $ECHO_C" >&6 if test "${dcc_cv_HAVE_VA_COPY+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include va_list ap1,ap2; int main () { va_copy(ap1,ap2); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then dcc_cv_HAVE_VA_COPY=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 dcc_cv_HAVE_VA_COPY=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $dcc_cv_HAVE_VA_COPY" >&5 echo "${ECHO_T}$dcc_cv_HAVE_VA_COPY" >&6 if test x"$dcc_cv_HAVE_VA_COPY" = x"yes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_VA_COPY 1 _ACEOF fi echo "$as_me:$LINENO: checking for __va_copy" >&5 echo $ECHO_N "checking for __va_copy... $ECHO_C" >&6 if test "${dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include va_list ap1,ap2; int main () { __va_copy(ap1,ap2); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY" >&5 echo "${ECHO_T}$dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY" >&6 if test x"$dcc_cv_HAVE_UNDERSCORE_UNDERSCORE_VA_COPY" = x"yes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_UNDERSCORE_UNDERSCORE_VA_COPY 1 _ACEOF fi echo "$as_me:$LINENO: checking for C99 vsnprintf" >&5 echo $ECHO_N "checking for C99 vsnprintf... $ECHO_C" >&6 if test "${rsync_cv_HAVE_C99_VSNPRINTF+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then rsync_cv_HAVE_C99_VSNPRINTF=cross else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include 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"); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then rsync_cv_HAVE_C99_VSNPRINTF=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) rsync_cv_HAVE_C99_VSNPRINTF=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $rsync_cv_HAVE_C99_VSNPRINTF" >&5 echo "${ECHO_T}$rsync_cv_HAVE_C99_VSNPRINTF" >&6 if test x"$rsync_cv_HAVE_C99_VSNPRINTF" = x"yes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_C99_VSNPRINTF 1 _ACEOF fi echo "$as_me:$LINENO: checking for working socketpair" >&5 echo $ECHO_N "checking for working socketpair... $ECHO_C" >&6 if test "${rsync_cv_HAVE_SOCKETPAIR+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then rsync_cv_HAVE_SOCKETPAIR=cross else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include main() { int fd[2]; exit((socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != -1) ? 0 : 1); } _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then rsync_cv_HAVE_SOCKETPAIR=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) rsync_cv_HAVE_SOCKETPAIR=no fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi echo "$as_me:$LINENO: result: $rsync_cv_HAVE_SOCKETPAIR" >&5 echo "${ECHO_T}$rsync_cv_HAVE_SOCKETPAIR" >&6 if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_SOCKETPAIR 1 _ACEOF fi echo "$as_me:$LINENO: checking for struct sockaddr_storage.ss_family" >&5 echo $ECHO_N "checking for struct sockaddr_storage.ss_family... $ECHO_C" >&6 if test "${ac_cv_member_struct_sockaddr_storage_ss_family+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static struct sockaddr_storage ac_aggr; if (ac_aggr.ss_family) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_member_struct_sockaddr_storage_ss_family=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static struct sockaddr_storage ac_aggr; if (sizeof ac_aggr.ss_family) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest.$ac_objext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_member_struct_sockaddr_storage_ss_family=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_sockaddr_storage_ss_family=no fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_storage_ss_family" >&5 echo "${ECHO_T}$ac_cv_member_struct_sockaddr_storage_ss_family" >&6 if test $ac_cv_member_struct_sockaddr_storage_ss_family = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_SOCKADDR_STORAGE 1 _ACEOF fi # Check whether --with-avahi or --without-avahi was given. if test "${with_avahi+set}" = set; then withval="$with_avahi" fi; if test x"$with_avahi" != xno; then if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_PKG_CONFIG+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5 echo "${ECHO_T}$PKG_CONFIG" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then echo "$as_me:$LINENO: result: $ac_pt_PKG_CONFIG" >&5 echo "${ECHO_T}$ac_pt_PKG_CONFIG" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi PKG_CONFIG=$ac_pt_PKG_CONFIG else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 echo "$as_me:$LINENO: checking pkg-config is at least version $_pkg_min_version" >&5 echo $ECHO_N "checking pkg-config is at least version $_pkg_min_version... $ECHO_C" >&6 if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 PKG_CONFIG="" fi fi pkg_failed=no echo "$as_me:$LINENO: checking for AVAHI" >&5 echo $ECHO_N "checking for AVAHI... $ECHO_C" >&6 if test -n "$PKG_CONFIG"; then if test -n "$AVAHI_CFLAGS"; then pkg_cv_AVAHI_CFLAGS="$AVAHI_CFLAGS" else if test -n "$PKG_CONFIG" && \ { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"avahi-client >= 0.6\"") >&5 ($PKG_CONFIG --exists --print-errors "avahi-client >= 0.6") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then pkg_cv_AVAHI_CFLAGS=`$PKG_CONFIG --cflags "avahi-client >= 0.6" 2>/dev/null` else pkg_failed=yes fi fi else pkg_failed=untried fi if test -n "$PKG_CONFIG"; then if test -n "$AVAHI_LIBS"; then pkg_cv_AVAHI_LIBS="$AVAHI_LIBS" else if test -n "$PKG_CONFIG" && \ { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"avahi-client >= 0.6\"") >&5 ($PKG_CONFIG --exists --print-errors "avahi-client >= 0.6") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then pkg_cv_AVAHI_LIBS=`$PKG_CONFIG --libs "avahi-client >= 0.6" 2>/dev/null` else pkg_failed=yes fi fi else pkg_failed=untried fi if test $pkg_failed = yes; then if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then AVAHI_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "avahi-client >= 0.6"` else AVAHI_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "avahi-client >= 0.6"` fi # Put the nasty error message in config.log where it belongs echo "$AVAHI_PKG_ERRORS" >&5 ZEROCONF_COMMON_OBJS="" ZEROCONF_DISTCC_OBJS="" ZEROCONF_DISTCCD_OBJS="" elif test $pkg_failed = untried; then ZEROCONF_COMMON_OBJS="" ZEROCONF_DISTCC_OBJS="" ZEROCONF_DISTCCD_OBJS="" else AVAHI_CFLAGS=$pkg_cv_AVAHI_CFLAGS AVAHI_LIBS=$pkg_cv_AVAHI_LIBS echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define HAVE_AVAHI 1 _ACEOF CFLAGS="$CFLAGS $AVAHI_CFLAGS" LIBS="$LIBS $AVAHI_LIBS" ZEROCONF_COMMON_OBJS="src/zeroconf.o src/gcc-id.o" ZEROCONF_DISTCC_OBJS="" ZEROCONF_DISTCCD_OBJS="src/zeroconf-reg.o" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" echo "$as_me:$LINENO: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 echo $ECHO_N "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ #ifdef __cplusplus extern "C" #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char pthread_join (); int main () { pthread_join (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then acx_pthread_ok=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext echo "$as_me:$LINENO: result: $acx_pthread_ok" >&5 echo "${ECHO_T}$acx_pthread_ok" >&6 if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) echo "$as_me:$LINENO: checking whether pthreads work without any flags" >&5 echo $ECHO_N "checking whether pthreads work without any flags... $ECHO_C" >&6 ;; -*) echo "$as_me:$LINENO: checking whether pthreads work with $flag" >&5 echo $ECHO_N "checking whether pthreads work with $flag... $ECHO_C" >&6 PTHREAD_CFLAGS="$flag" ;; pthread-config) # Extract the first word of "pthread-config", so it can be a program name with args. set dummy pthread-config; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_acx_pthread_config+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$acx_pthread_config"; then ac_cv_prog_acx_pthread_config="$acx_pthread_config" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_acx_pthread_config="yes" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no" fi fi acx_pthread_config=$ac_cv_prog_acx_pthread_config if test -n "$acx_pthread_config"; then echo "$as_me:$LINENO: result: $acx_pthread_config" >&5 echo "${ECHO_T}$acx_pthread_config" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) echo "$as_me:$LINENO: checking for the pthreads library -l$flag" >&5 echo $ECHO_N "checking for the pthreads library -l$flag... $ECHO_C" >&6 PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then acx_pthread_ok=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" echo "$as_me:$LINENO: result: $acx_pthread_ok" >&5 echo "${ECHO_T}$acx_pthread_ok" >&6 if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. echo "$as_me:$LINENO: checking for joinable pthread attribute" >&5 echo $ECHO_N "checking for joinable pthread attribute... $ECHO_C" >&6 attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { int attr=$attr; return attr; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then attr_name=$attr; break else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done echo "$as_me:$LINENO: result: $attr_name" >&5 echo "${ECHO_T}$attr_name" >&6 if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then cat >>confdefs.h <<_ACEOF #define PTHREAD_CREATE_JOINABLE $attr_name _ACEOF fi echo "$as_me:$LINENO: checking if more special flags are required for pthreads" >&5 echo $ECHO_N "checking if more special flags are required for pthreads... $ECHO_C" >&6 flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac echo "$as_me:$LINENO: result: ${flag}" >&5 echo "${ECHO_T}${flag}" >&6 if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then for ac_prog in xlc_r cc_r do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 if test "${ac_cv_prog_PTHREAD_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PTHREAD_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then echo "$as_me:$LINENO: result: $PTHREAD_CC" >&5 echo "${ECHO_T}$PTHREAD_CC" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi test -n "$PTHREAD_CC" && break done test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}" else PTHREAD_CC=$CC fi # The next part tries to detect GCC inconsistency with -shared on some # architectures and systems. The problem is that in certain # configurations, when -shared is specified, GCC "forgets" to # internally use various flags which are still necessary. # # Prepare the flags # save_CFLAGS="$CFLAGS" save_LIBS="$LIBS" save_CC="$CC" # Try with the flags determined by the earlier checks. # # -Wl,-z,defs forces link-time symbol resolution, so that the # linking checks with -shared actually have any value # # FIXME: -fPIC is required for -shared on many architectures, # so we specify it here, but the right way would probably be to # properly detect whether it is actually required. CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CC="$PTHREAD_CC" # In order not to create several levels of indentation, we test # the value of "$done" until we find the cure or run out of ideas. done="no" # First, make sure the CFLAGS we added are actually accepted by our # compiler. If not (and OS X's ld, for instance, does not accept -z), # then we can't do this test. if test x"$done" = xno; then echo "$as_me:$LINENO: checking whether to check for GCC pthread/shared inconsistencies" >&5 echo $ECHO_N "checking whether to check for GCC pthread/shared inconsistencies... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 done=yes fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "x$done" = xyes ; then echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 else echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 fi fi if test x"$done" = xno; then echo "$as_me:$LINENO: checking whether -pthread is sufficient with -shared" >&5 echo $ECHO_N "checking whether -pthread is sufficient with -shared... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then done=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "x$done" = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi # # Linux gcc on some architectures such as mips/mipsel forgets # about -lpthread # if test x"$done" = xno; then echo "$as_me:$LINENO: checking whether -lpthread fixes that" >&5 echo $ECHO_N "checking whether -lpthread fixes that... $ECHO_C" >&6 LIBS="-lpthread $PTHREAD_LIBS $save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then done=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "x$done" = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 PTHREAD_LIBS="-lpthread $PTHREAD_LIBS" else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi # # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc # if test x"$done" = xno; then echo "$as_me:$LINENO: checking whether -lc_r fixes that" >&5 echo $ECHO_N "checking whether -lc_r fixes that... $ECHO_C" >&6 LIBS="-lc_r $PTHREAD_LIBS $save_LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; } && { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then done=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "x$done" = xyes; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 PTHREAD_LIBS="-lc_r $PTHREAD_LIBS" else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi if test x"$done" = xno; then # OK, we have run out of ideas { echo "$as_me:$LINENO: WARNING: Impossible to determine how to use pthreads with shared libraries" >&5 echo "$as_me: WARNING: Impossible to determine how to use pthreads with shared libraries" >&2;} # so it's not safe to assume that we may use pthreads acx_pthread_ok=no fi CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" CC="$save_CC" else PTHREAD_CC="$CC" fi # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then cat >>confdefs.h <<\_ACEOF #define HAVE_PTHREAD 1 _ACEOF : else acx_pthread_ok=no fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" cat >>confdefs.h <<_ACEOF #define GNU_HOST "$host" _ACEOF # The '.stamp-conf' files force creation of the containing directories in the # build tree. ac_config_files="$ac_config_files Makefile popt/.stamp-conf lzo/.stamp-conf" ac_config_files="$ac_config_files pump" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. { (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | sed ' t clear : clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; s/^[^=]*=[ ]*$//; }' fi DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # Work around bugs in pre-3.0 UWIN ksh. $as_unset ENV MAIL MAILPATH PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)$' \| \ . : '\(.\)' 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } /^X\/\(\/\/\)$/{ s//\1/; q; } /^X\/\(\/\).*/{ s//\1/; q; } s/.*/./; q'` # PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" || { # Find who we are. Look in the path if we contain no path at all # relative or not. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} { (exit 1); exit 1; }; } fi case $CONFIG_SHELL in '') as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for as_base in sh bash ksh sh5; do case $as_dir in /*) if ("$as_dir/$as_base" -c ' as_lineno_1=$LINENO as_lineno_2=$LINENO as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` test "x$as_lineno_1" != "x$as_lineno_2" && test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } CONFIG_SHELL=$as_dir/$as_base export CONFIG_SHELL exec "$CONFIG_SHELL" "$0" ${1+"$@"} fi;; esac done done ;; esac # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line before each line; the second 'sed' does the real # work. The second script uses 'N' to pair each line-number line # with the numbered line, and appends trailing '-' during # substitution so that $LINENO is not a special case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) sed '=' <$as_myself | sed ' N s,$,-, : loop s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, t loop s,-$,, s,^['$as_cr_digits']*\n,, ' >$as_me.lineno && chmod +x $as_me.lineno || { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensible to this). . ./$as_me.lineno # Exit status is that of the last command. exit } case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac if expr a : '\(a\)' >/dev/null 2>&1; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then # We could just check for DJGPP; but this test a) works b) is more generic # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). if test -f conf$$.exe; then # Don't use ln at all; we don't have any links as_ln_s='cp -p' else as_ln_s='ln -s' fi elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS # We need space, tab and new line, in precisely that order. as_nl=' ' IFS=" $as_nl" # CDPATH. $as_unset CDPATH exec 6>&1 # Open the log real soon, to keep \$[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. Logging --version etc. is OK. exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX } >&5 cat >&5 <<_CSEOF This file was extended by distcc $as_me 3.1, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ _CSEOF echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 echo >&5 _ACEOF # Files that config.status was made for. if test -n "$ac_config_files"; then echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS fi if test -n "$ac_config_headers"; then echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS fi if test -n "$ac_config_links"; then echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS fi if test -n "$ac_config_commands"; then echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS fi cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ distcc config.status 3.1 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir INSTALL="$INSTALL" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "x$1" : 'x\([^=]*\)='` ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` ac_shift=: ;; -*) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; *) # This is not an option, so the user has probably given explicit # arguments. ac_option=$1 ac_need_defaults=false;; esac case $ac_option in # Handling of the options. _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) # Conflict between --help and --header { { echo "$as_me:$LINENO: error: ambiguous option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 Try \`$0 --help' for more information." >&5 echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2;} { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_config_target in $ac_config_targets do case "$ac_config_target" in # Handling of arguments. "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "popt/.stamp-conf" ) CONFIG_FILES="$CONFIG_FILES popt/.stamp-conf" ;; "lzo/.stamp-conf" ) CONFIG_FILES="$CONFIG_FILES lzo/.stamp-conf" ;; "pump" ) CONFIG_FILES="$CONFIG_FILES pump" ;; "src/config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason to put it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "\$CONFIG_FILES"; then # Protect against being on the right side of a sed subst in config.status. sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF s,@SHELL@,$SHELL,;t t s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t s,@exec_prefix@,$exec_prefix,;t t s,@prefix@,$prefix,;t t s,@program_transform_name@,$program_transform_name,;t t s,@bindir@,$bindir,;t t s,@sbindir@,$sbindir,;t t s,@libexecdir@,$libexecdir,;t t s,@datadir@,$datadir,;t t s,@sysconfdir@,$sysconfdir,;t t s,@sharedstatedir@,$sharedstatedir,;t t s,@localstatedir@,$localstatedir,;t t s,@libdir@,$libdir,;t t s,@includedir@,$includedir,;t t s,@oldincludedir@,$oldincludedir,;t t s,@infodir@,$infodir,;t t s,@mandir@,$mandir,;t t s,@build_alias@,$build_alias,;t t s,@host_alias@,$host_alias,;t t s,@target_alias@,$target_alias,;t t s,@DEFS@,$DEFS,;t t s,@ECHO_C@,$ECHO_C,;t t s,@ECHO_N@,$ECHO_N,;t t s,@ECHO_T@,$ECHO_T,;t t s,@LIBS@,$LIBS,;t t s,@build@,$build,;t t s,@build_cpu@,$build_cpu,;t t s,@build_vendor@,$build_vendor,;t t s,@build_os@,$build_os,;t t s,@host@,$host,;t t s,@host_cpu@,$host_cpu,;t t s,@host_vendor@,$host_vendor,;t t s,@host_os@,$host_os,;t t s,@docdir@,$docdir,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t s,@CPPFLAGS@,$CPPFLAGS,;t t s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t s,@GNOME_PACKAGES@,$GNOME_PACKAGES,;t t s,@GNOME_CFLAGS@,$GNOME_CFLAGS,;t t s,@GNOME_LIBS@,$GNOME_LIBS,;t t s,@INSTALL_GNOME@,$INSTALL_GNOME,;t t s,@UNINSTALL_GNOME@,$UNINSTALL_GNOME,;t t s,@WERROR_CFLAGS@,$WERROR_CFLAGS,;t t s,@POPT_CFLAGS@,$POPT_CFLAGS,;t t s,@PYTHON_CFLAGS@,$PYTHON_CFLAGS,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t s,@PYTHON@,$PYTHON,;t t s,@TEST_PYTHON@,$TEST_PYTHON,;t t s,@INCLUDESERVER_PYTHON@,$INCLUDESERVER_PYTHON,;t t s,@PYTHON_RELATIVE_LIB@,$PYTHON_RELATIVE_LIB,;t t s,@CPP@,$CPP,;t t s,@EGREP@,$EGREP,;t t s,@PKG_CONFIG@,$PKG_CONFIG,;t t s,@ac_pt_PKG_CONFIG@,$ac_pt_PKG_CONFIG,;t t s,@AVAHI_CFLAGS@,$AVAHI_CFLAGS,;t t s,@AVAHI_LIBS@,$AVAHI_LIBS,;t t s,@ZEROCONF_COMMON_OBJS@,$ZEROCONF_COMMON_OBJS,;t t s,@ZEROCONF_DISTCC_OBJS@,$ZEROCONF_DISTCC_OBJS,;t t s,@ZEROCONF_DISTCCD_OBJS@,$ZEROCONF_DISTCCD_OBJS,;t t s,@acx_pthread_config@,$acx_pthread_config,;t t s,@PTHREAD_CC@,$PTHREAD_CC,;t t s,@PTHREAD_LIBS@,$PTHREAD_LIBS,;t t s,@PTHREAD_CFLAGS@,$PTHREAD_CFLAGS,;t t s,@POPT_INCLUDES@,$POPT_INCLUDES,;t t s,@BUILD_POPT@,$BUILD_POPT,;t t s,@GNOME_BIN@,$GNOME_BIN,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_lines=48 ac_sed_frag=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_lines # Line after last line for current file. ac_more_lines=: ac_sed_cmds= while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag else sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag fi if test ! -s $tmp/subs.frag; then ac_more_lines=false else # The purpose of the label and of the branching condition is to # speed up the sed processing (if there are no `@' at all, there # is no need to browse any of the substitutions). # These are the two extra sed commands mentioned above. (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_lines` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi fi # test -n "$CONFIG_FILES" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. if test "$ac_dir" != .; then ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A "../" for each directory in $ac_dir_suffix. ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` else ac_dir_suffix= ac_top_builddir= fi case $srcdir in .) # No --srcdir option. We are building in place. ac_srcdir=. if test -z "$ac_top_builddir"; then ac_top_srcdir=. else ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` fi ;; [\\/]* | ?:[\\/]* ) # Absolute path. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ;; *) # Relative path. ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac # Do not use `cd foo && pwd` to compute absolute paths, because # the directories may not exist. case `pwd` in .) ac_abs_builddir="$ac_dir";; *) case "$ac_dir" in .) ac_abs_builddir=`pwd`;; [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; *) ac_abs_builddir=`pwd`/"$ac_dir";; esac;; esac case $ac_abs_builddir in .) ac_abs_top_builddir=${ac_top_builddir}.;; *) case ${ac_top_builddir}. in .) ac_abs_top_builddir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; esac;; esac case $ac_abs_builddir in .) ac_abs_srcdir=$ac_srcdir;; *) case $ac_srcdir in .) ac_abs_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; esac;; esac case $ac_abs_builddir in .) ac_abs_top_srcdir=$ac_top_srcdir;; *) case $ac_top_srcdir in .) ac_abs_top_srcdir=$ac_abs_builddir;; [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; esac;; esac case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then configure_input= else configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } if test x"$ac_file" != x-; then { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} rm -f "$ac_file" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s,@configure_input@,$configure_input,;t t s,@srcdir@,$ac_srcdir,;t t s,@abs_srcdir@,$ac_abs_srcdir,;t t s,@top_srcdir@,$ac_top_srcdir,;t t s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t s,@builddir@,$ac_builddir,;t t s,@abs_builddir@,$ac_abs_builddir,;t t s,@top_builddir@,$ac_top_builddir,;t t s,@abs_top_builddir@,$ac_abs_top_builddir,;t t s,@INSTALL@,$ac_INSTALL,;t t " $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out rm -f $tmp/stdin if test x"$ac_file" != x-; then mv $tmp/out $ac_file else cat $tmp/out rm -f $tmp/out fi # Run the commands associated with the file. case $ac_file in pump ) chmod +x pump ;; esac done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # # CONFIG_HEADER section. # # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin cat >$tmp/stdin ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} # First look for the input files in the build tree, otherwise in the # src tree. ac_file_inputs=`IFS=: for f in $ac_file_in; do case $f in -) echo $tmp/stdin ;; [\\/$]*) # Absolute (can't be DOS-style, as IFS=:) test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } # Do quote $f, to prevent DOS paths from being IFS'd. echo "$f";; *) # Relative if test -f "$f"; then # Build tree echo "$f" elif test -f "$srcdir/$f"; then # Source tree echo "$srcdir/$f" else # /dev/null tree { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF # Transform confdefs.h into two sed scripts, `conftest.defines' and # `conftest.undefs', that substitutes the proper values into # config.h.in to produce config.h. The first handles `#define' # templates, and the second `#undef' templates. # And first: Protect against being on the right side of a sed subst in # config.status. Protect against being in an unquoted here document # in config.status. rm -f conftest.defines conftest.undefs # Using a here document instead of a string reduces the quoting nightmare. # Putting comments in sed scripts is not portable. # # `end' is used to avoid that the second main sed command (meant for # 0-ary CPP macros) applies to n-ary macro definitions. # See the Autoconf documentation for `clear'. cat >confdef2sed.sed <<\_ACEOF s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times # the same #defines, which is useless. Nevertheless, we may not want to # sort them, since we want the *last* AC-DEFINE to be honored. uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs rm -f confdef2sed.sed # This sed command replaces #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.defines >/dev/null do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/defines.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines echo ' fi # grep' >>$CONFIG_STATUS echo >>$CONFIG_STATUS # Break up conftest.undefs because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #undef templates' >>$CONFIG_STATUS rm -f conftest.tail while grep . conftest.undefs >/dev/null do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#undef' echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS echo 'CEOF sed -f $tmp/undefs.sed $tmp/in >$tmp/out rm -f $tmp/in mv $tmp/out $tmp/in ' >>$CONFIG_STATUS sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail rm -f conftest.undefs mv conftest.tail conftest.undefs done rm -f conftest.undefs cat >>$CONFIG_STATUS <<\_ACEOF # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ if test x"$ac_file" = x-; then echo "/* Generated by configure. */" >$tmp/config.h else echo "/* $ac_file. Generated by configure. */" >$tmp/config.h fi cat $tmp/in >>$tmp/config.h rm -f $tmp/in if test x"$ac_file" != x-; then if diff $ac_file $tmp/config.h >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` { if $as_mkdir_p; then mkdir -p "$ac_dir" else as_dir="$ac_dir" as_dirs= while test ! -d "$as_dir"; do as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| \ . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` done test ! -n "$as_dirs" || mkdir $as_dirs fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} { (exit 1); exit 1; }; }; } rm -f $ac_file mv $tmp/config.h $ac_file fi else cat $tmp/config.h rm -f $tmp/config.h fi done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi ##### Finalization # Display success, installation paths, and GPL licence statement. echo ' ' ${MAKE-make} showpaths echo ' ' cat < Portions Copyright 2005 Google Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. After installing distcc, please complete the survey in the file "survey.txt". EOF distcc-3.1/source/README.packaging0000640000175000017500000000664111115326647015756 0ustar wolffwolff$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. distcc-3.1/source/doc/0000750000175000017500000000000011115327755013711 5ustar wolffwolffdistcc-3.1/source/doc/example/0000750000175000017500000000000011115327755015344 5ustar wolffwolffdistcc-3.1/source/doc/example/init0000640000175000017500000000236611115326642016234 0ustar wolffwolff#! /bin/sh # # chkconfig: - 60 20 # description: The distcc deamon # http://code.google.com/p/distcc/ # # processname: distccd # This is a Red Hat init.d file to start distccd. To install it, copy # it into /etc/init.d/distccd, and add appropriate links into the # rc?.d directories. # It may need to be tweaked for other distributions or versions. # You may wish to accept parameters from the user to set access # control options. # Get config. . /etc/sysconfig/network # Get functions . /etc/init.d/functions # Check that networking is up. if [ ${NETWORKING} = "no" ] ; then exit 0 fi RETVAL=0 SERVICE=distccd start() { echo -n $"Starting $SERVICE: " daemon /usr/local/bin/$SERVICE --daemon RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$SERVICE return $RETVAL } stop() { echo -n $"Stopping $SERVICE: " killproc $SERVICE RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$SERVICE return $RETVAL } restart() { stop start } # See how we were called. case "$1" in start) start ;; stop) stop ;; status) status $SERVICE ;; restart) restart ;; condrestart) [ -f /var/lock/subsys/$SERVICE ] && restart || : ;; *) echo $"Usage: $0 {start|stop|status|restart}" exit 1 ;; esac exit $? distcc-3.1/source/doc/example/logrotate0000640000175000017500000000046311115326642017265 0ustar wolffwolff# logrotate.d example configuration for distcc, contributed by Dag # Wieers. # The "copytruncate" option means distcc can keep appending to the # same filehandle. You would otherwise need to shut down and restart # distccd. /var/log/distccd.log { missingok copytruncate notifempty } distcc-3.1/source/doc/example/xinetd0000640000175000017500000000167011115326642016561 0ustar wolffwolff# default: off # description: distccd serves C/C++ compilation requests from distcc clients. # WARNING: This service should ONLY be used on trusted networks. # xinetd service description for distcc, contributed by akpm, updated # by mbp. # To use this, just check the parameters below and copy this file into # /etc/xinet.d/distcc, or the appropriate location for your system, # and then restart xinetd. You should also create a 'distcc' user. # ===> Note that running from inetd is generally NOT recommended for # distcc. distccd should give better performance when it can run as a # standalone daemon and regulate its own load. service distcc { disable = yes socket_type = stream wait = no user = distcc server = /usr/local/bin/distccd server_args = --inetd # This makes xinetd cope if there is no service listed in # /etc/services type = UNLISTED } distcc-3.1/source/doc/example/init-suse0000640000175000017500000000466511115326642017215 0ustar wolffwolff#! /bin/sh # # Copyright (C) 2002 C. Brandon Forehand # # This code is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # /etc/init.d/distcc # # and symbolic link # # /usr/sbin/rcdistcc # ### BEGIN INIT INFO # Provides: distccd # Required-Start: $network # Required-Stop: $network # Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Description: Start the distcc daemon ### END INIT INFO . /etc/rc.status . /etc/rc.config # Determine the base and follow a runlevel link name. base=${0##*/} link=${base#*[SK][0-9][0-9]} DISTCC=/usr/local/bin/distccd DISTCC_OPTS=--daemon DISTCC_USER=daemon # Shell functions sourced from /etc/rc.status: # rc_check check and set local and overall rc status # rc_status check and set local and overall rc status # rc_status -v ditto but be verbose in local rc status # rc_status -v -r ditto and clear the local rc status # rc_failed set local and overall rc status to failed # rc_reset clear local rc status (overall remains) # rc_exit exit appropriate to overall rc status # First reset status of this service rc_reset case "$1" in start) echo -n "Starting distcc daemon" ## Start daemon with startproc(8). If this fails ## the echo return value is set appropriate. startproc -u $DISTCC_USER $DISTCC $DISTCC_OPTS # Remember status and be verbose rc_status -v ;; stop) echo -n "Shutting down distcc daemon:" ## Stop daemon with killproc(8) and if this fails ## set echo the echo return value. killproc -TERM $DISTCC # Remember status and be verbose rc_status -v ;; restart) ## If first returns OK call the second, if first or ## second command fails, set echo return value. $0 stop && $0 start # Remember status and be quiet rc_status ;; reload) $0 restart # Remember status and be verbose rc_status -v ;; status) echo -n "Checking for service distccd: " checkproc $DISTCC && echo OK || echo No process ;; *) echo "Usage: $0 {start|stop|status|restart|reload}" exit 1 ;; esac rc_exit distcc-3.1/source/doc/protocol-2.txt0000640000175000017500000000232211115326643016445 0ustar wolffwolffdescription of distcc protocol version 2 Copyright (C) 2003 by Martin Pool disclaimer ---------- This document is provided as explanation for people developing or debugging distcc. Discrepancies between this document and the distcc code are an error in the document. This document is intended to describe distcc 2.9. Because this program and document is licensed free of charge, there is no warranty of any kind, to the extent permitted by applicable law. If anything is unclear, please ask on the mailing list. protocol -------- Protocol 2 is a variation of protocol 1. It gets a new version number because that's the simplest way to indicate the change. The protocol number (DIST) sent by the client is set to 2. The server must respond (DONE) in version 2. The content of the "bulk" tokens (DOTI, DOTO, SERR, SOUT) are compressed using the LZO1X algorithm. The token parameter gives the length of the compressed form. As a special case, if the uncompressed form is zero bytes, then it is not compressed but rather sent directly as zero bytes. (Compression slightly expands a zero byte string.) The distcc client and server can handle either protocol 1 or 2 depending on whether the user configures compression on. distcc-3.1/source/doc/reporting-bugs.txt0000640000175000017500000000605411115326643017422 0ustar wolffwolffHow to report bugs in distcc -*- indented-text -*- If you are having trouble with distcc, please send email to distcc@lists.samba.org. Please don't send mail direct to the author: if you use the list, other people may be able to help you faster and the answers are archived to help others. * The first aim of a bug report is to let the programmer see the failure with their own eyes. If you can't be with them to make it fail in front of them, give them detailed instructions so that they can make it fail for themselves. * In case the first aim doesn't succeed, and the programmer can't see it failing themselves, the second aim of a bug report is to describe what went wrong. Describe everything in detail. State what you saw, and also state what you expected to see. Write down the error messages, especially if they have numbers in. * By all means try to diagnose the fault yourself if you think you can, but if you do, you should still report the symptoms as well. * Write clearly. Say what you mean, and make sure it can't be misinterpreted. * Above all, be precise. A good bug report for distcc should include these details: * What version of distcc you're using, e.g. "2.7.1". If you got it from a distribution package rather than building from source, please say so. * Your platform (e.g. "Red Hat 8.0", "HP-UX 11.11") and compiler "gcc 3.3" * What you're trying to do: e.g. "install distcc", "build Mozilla", "build my own program". * What went wrong: e.g. did you get an error message, did it hang, did it build a program that didn't work, did it not distribute compilation to machines that ought to get it? You'd be surprised how many people don't say what actually happened. * If you have an example of a compiler invocation that failed, quote it, e.g.: distcc gcc -DHAVE_CONFIG_H -D_GNU_SOURCE -I./src \ "-DSYSCONFDIR=\"/etc/\"" -I./lzo -g -O2 -W -Wall -W \ -Wimplicit -Wshadow -Wpointer-arith -Wcast-align \ -Wwrite-strings -Waggregate-return -Wstrict-prototypes \ -Wmissing-prototypes -Wnested-externs -o src/clirpc.o \ -c src/clirpc.c * Turn on client and server error logging. On the client, set these environment variables, and try to reproduce the problem: export DISTCC_VERBOSE=1 DISTCC_LOG=/tmp/distcc.log Start the server with the --verbose option. If the problem is intermittent, leave logging enabled and then pull out the lines from the log file when the problem recurs. * If you got an error message on stderr, quote that error exactly. Find the lines in the log files pertaining to the compile, and include all of them in your report, by looking at the process ID in square brackets. If you can't work that out, quote the last few hundred lines leading up to the failure. An error report with all the necessary details is often answered and resolved within two days or less. If you don't include enough information to know what is going wrong it can take much longer. distcc-3.1/source/doc/status-1.txt0000640000175000017500000000326011115326643016130 0ustar wolffwolffdescription of distcc status indicators, version 1 Copyright (C) 2003 by Martin Pool purpose ------- This file describes a mooted design for a mechanism for distcc to indicate its status for the benefit of a separate display program. This is an external protocol so that there can be different implementations of status monitors to suit different purposes. The protocol is supposed to stay stable for some time to allow people to write their own monitors. interface --------- The programming interface to this is through the functions in mon.c/mon.h. Monitor applications should not access the files directly. state ----- The state of a compiler process is described in a few variables cpid Process ID of the client state String describing its progress in compilation file Short source filename host Host definition being used File or host may be empty strings if they are not yet known. states ------ The following states are defined. The list may change in later releases. In 2.6 the client progresses through these states in order, although not all states may be reached by any particular process. Startup Examining command line, host definition and other settings, and finding a host to use. Starved Waiting because all defined hosts are completely busy. Connect Opening a TCP or SSH connection to the host and sending the first part of the request. Preprocessor Waiting for the preprocessor to complete. Send Sending the preprocessed source. Compile Waiting for a local or remote compiler to complete. Receive Receiving compilation results. distcc-3.1/source/doc/protocol-1.txt0000640000175000017500000001460211115326643016450 0ustar wolffwolffdescription 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 Greeting from client, followed by the protocol version, which is always 1. ARGC Specifies the number of arguments in the command, including the compiler name. ARGV Repeated times. Specifies the string value of one element of the command. DOTI The contents of the preprocessed source (.i) file. response -------- The following packets comprise the response: DONE Introduces the response. The version must be 1. STAT Gives the Unix wait status of the compiler. This 0 for success, or otherwise (EXITCODE << 8) | (TERMSIGNAL), depending on whether the compiler returned an error or was terminated by a signal. (See or a POSIX standard for a full definition.) SERR Contains messages sent to stderr by the compiler. SOUT Contains messages sent to stdout by the compiler. Normally empty -- errors and warnings for most compilers go to stderr instead. DOTO Contains the object file (.o) produced by the compiler. In very early versions, this is missing if the status code is not zero. In versions up to and including 2.7.1, zero-length output files are not supported. If compilation fails, then the server sends the file with a length of zero, but the client does not read it. From 2.8, things work as follows: regular success: status zero length nonzero succeeded, but zero-byte output: status zero length zero output file is created/touched failed: status nonzero length sent as zero This is a little complex but is compatible with earlier releases. This does mean we cannot represent a compiler that produces output and then fails, but I don't think that is very important. distcc-3.1/source/pump.in0000750000175000017500000004567511115326647014500 0ustar wolffwolff#!/bin/sh # # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # # Authors: Nils Klarlund, Fergus Henderson # # 'pump': a script for using distcc-pump with build commands. # This file is processed by configure, which substitutes in the right # value for @PYTHON@, @prefix@, etc. # NOTE: do we need to do the expansion of these variables by using sed # in Makefile.in rather than by having configure process this file? # The autoconf manual suggests that we do. Right now it doesn't seem # to be needed in practice, though. PYTHON=@PYTHON@ prefix=@prefix@ exec_prefix=@exec_prefix@ sysconfdir=@sysconfdir@ srcdir=@srcdir@ # This is where include_server.py lives. It's set to the empty string # before pump is installed into its final location. At install-time, # the 'make install' command will rewrite this line of pump to point # to the installed include_server.py. # NOTE: DO NOT CHANGE THE LINE BELOW WITHOUT CHANGING THE SED IN # Makefile.in:install-include-server. include_server='' CheckUsage() { if [ "$1" = "" -o "$1" = '-h' -o "$1" = '--help' ]; then cat <<'EOF' Usage: pump COMMAND [ARG...] or pump --startup pump --shutdown Description: Pump, also known as distcc-pump, accelerates remote compilation with distcc by also distributing preprocessing to the servers. The simplest usage is the form "pump COMMAND [ARG...]". This will start an include server for distcc-pump; set some environment variables; change PATH to use the distcc-pump "distcc" client; execute COMMAND with the specified ARG(s); and then shutdown the include server. The COMMAND is typically a parallel build command, such as "make -j80", that will do many concurrent invocations of distcc. An alternative way of invoking pump is to explicitly invoke "pump --startup" to start the include server and "pump --shutdown" to stop the include server. The "pump --startup" command will start up the include server, and will print out some environment variable settings. These environment variables are used to communicate between the distcc-pump "distcc" client and the include server, and to communicate between "pump --startup" and "pump --shutdown". The caller of "pump --startup" is responsible for setting those environment variables before invoking "distcc" or "pump --shutdown". For example: eval `pump --startup` make -j80 pump --shutdown Note that distcc-pump assumes that sources files will not be modified during the lifetime of the include server, so modifying source files during a build may cause inconsistent results. Environment variables (all optional): DISTCC_LOCATION Either the distcc 'bin' install directory (when the pump script in the installation executes) or the build directory (when the pump script is run during development). This location is normally inferred from the dirname of argv[0]. It is resolved with respect to links. If this location is the bin directory inside an installation, then Python executables and distcc itself will be retrieved from the parent directory of the location. If this location is the build directory, then Python sources are retrived from the source directory. DISTCC_POTENTIAL_HOSTS The distcc servers that will be queried by lsdistcc in order to produce a value for DISTCC_HOSTS. This value may be unset or null. In such cases, use DISTCC_HOSTS. DISTCC_HOSTS This variable is passed through to distcc but only if DISTCC_POTENTIAL_HOSTS is not set. LSDISTCC_ARGS Extra arguments to lsdistcc. INCLUDE_SERVER_ARGS Extra arguments to the include server. PYTHONOPTIMIZE If set to "", then Python optimization is disabled. Example: pump make EOF exit 0 fi } # Get the directory of a command. The argument is $0 as received from # argv[0]. If $0 is of the form /path/symlink and symlink points to # another directory than /path, then `basename $0` does not return # the directory where the executable lives. We fix this here. GetScriptDir() { if [ -h "$0" ]; then dir=`dirname "$0"` link=`readlink "$0"` linkdir=`dirname "$link"` case $linkdir in /*) echo "$linkdir" ;; *) echo "$dir/$linkdir" ;; esac else dirname "$0" fi } # Constants used by this process. # TODO(klarlund) This value must be the same as that in src/compile.c. See # comment there. max_discrepancies_before_demotion=1 # Variables inherited from the environment of the caller. if [ -z "$DISTCC_LOCATION" ]; then # Set the default for location of 'pump' script'. DISTCC_LOCATION=`GetScriptDir "$0"` fi # Variables used by this process. program_name="$0" socket_dir='' # Temporary directory created by this process. tmp_pid_file='' # Temporary file created by this process. available_hosts_file='' # Temporary file for newline separated list of hosts. socket='' # Temporary socket file, inside $socket_dir. include_server_stdout='' # Temporary file, inside $socket_dir. include_server_stderr='' # Temporary file, inside $socket_dir. include_server_pid='' include_server_relative='' # Set by Initialize(). This path is relative to # the 'bin' directory of a distcc-pump installation. distcc_location='' # Set by Initialize(). The directory of the distcc binary. DISTCC='distcc' # the name of the distcc binary verbose=1 # Print progress messages to stdout? (1 means yes.) redirect_io=0 # Redirect include server's I/O streams? (1 means yes.) # Make temp file using distinguishing prefix $1. Use optional argument # $2="-d" to make a directory. The name of the created temp file or # directory is written to stdout. MakeTmpFile() { if mktemp $2 /tmp/$1.XXXXXX; then : # mktemp prints the output we want; no need to do more else echo "$program_name: Could not make temp \"$1\"" 1>&2 exit 1 fi } Initialize() { # We know the value of $PYTHON when this function is executed. The value is # set when the 'pump' script is made from 'pump.in'. Use this value in the # formation of the relative path that takes us from the 'bin' directory of an # installation to the 'include_server' directory. include_server_relative="../$PYTHON_RELATIVE_LIB/include_server" distcc_location="$DISTCC_LOCATION" # Check that we're getting exactly the distcc client we want: the # one that is part of this build. if [ ! -x "$distcc_location/$DISTCC" ]; then echo "$0: error: can't find distcc (looked in $distcc_location)" 1>&2 exit 1 fi } PrintIncludeServerStatusMessage() { include_server_status=$1 if [ "$verbose" = 1 ]; then if [ "$include_server_status" = 0 ]; then echo '__________Started distcc-pump include server' else echo '__________Could not start distcc-pump include server' 1>&2 fi fi } Announce() { echo "__________Using distcc-pump from $DISTCC_LOCATION" } # Starts up the include server. Sets $socket, $socket_dir, and # $include_server_pid. If successful (with exit status 0), sets exported # variable $INCLUDE_SERVER_PORT to the socket file ($socket), to tell the distcc # clients where to find the include server. StartIncludeServer() { # If include_server already exists, that means we're a # installed pump (in /usr/local/bin somewhere or something), and # include_server points to the installed include_server.py. if [ -n "$include_server" ]; then pythonpath=`dirname "$include_server"` else # We assume this script is run from the build directory. We pick up .py # files from the include_server directory in the source tree, and we pick up # the .so file from the include_server/build/libXXX/include_server # directory. # # Calculate the location of the source directory. distcc_srcdir=`cd "$DISTCC_LOCATION"; cd "$srcdir"; pwd` # The source tree location must be passed. include_server="$distcc_srcdir/include_server/include_server.py" # Now locate the single directory containing the .so file from the build # directory. Possibly there may be more than one such file; first identify # them all. so_dir=`"$distcc_srcdir/find_c_extension.sh" "$DISTCC_LOCATION"` pythonpath="$so_dir" fi # Create a temporary directory $socket_dir. socket_dir=`MakeTmpFile "distcc-pump" -d` # 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 if [ -z "$PYTHONOPTIMIZE" ]; then PYTHONOPTIMIZE=1; fi # We use 'eval' so that INCLUDE_SERVER_ARGS can use shell quoting such # as in: # # INCLUDE_SERVER_ARGS='--stat_reset_triggers="*"' # # which will pass '*' to the include server (that is, the string consisting # of one asterisk) without filename expansion. eval \ "PYTHONOPTIMIZE='$PYTHONOPTIMIZE' " \ "PYTHONPATH='$pythonpath::$PYTHONPATH' " \ "'$PYTHON'" \ "'$include_server'" \ --port "'$socket'" \ --pid_file "'$tmp_pid_file'" \ -d1 \ $INCLUDE_SERVER_ARGS ) # solaris sh's built-in test does not support -S, so we need to use # the binary. if [ -x /bin/test ]; then TEST=/bin/test elif [ -x /usr/bin/test ]; then TEST=/usr/bin/test else TEST=test fi if $TEST ! -S "$socket"; then echo "__________Expected a socket at '$socket'" 1>&2 PrintIncludeServerStatusMessage 1 return 1 fi include_server_pid=`cat $tmp_pid_file` rm "$tmp_pid_file" # Make sure $include_server_pid looks like a pid if echo "$include_server_pid" | grep '^[0-9][0-9]*$' >/dev/null; then # We got a number. Tell the distcc clients where to find it. INCLUDE_SERVER_PORT="$socket" export INCLUDE_SERVER_PORT else # We got something that's not a number. This indicates the # socket is not working. include_server_pid='' PrintIncludeServerStatusMessage 1 return 1 fi } ReportDiscrepancies() { # The discrepancy_counter file is created when a pump-mode distcc invocation # failed remotely but succeeded locally. num_discrepancies=`(cat $socket_dir/discrepancy_counter 2>/dev/null | wc -c \ || echo 0)` if [ $num_discrepancies -ge $max_discrepancies_before_demotion ]; then echo -n '__________Warning: ' 1>&2 echo -n "$num_discrepancies " 1>&2 echo -n 'pump-mode compilation(s) failed on server, ' 1>&2 echo 'but succeeded locally.' 1>&2 echo -n '__________Distcc-pump was demoted to plain mode.' 1>&2 echo -n ' See the Distcc Discrepancy Symptoms section in the ' 1>&2 echo 'include_server(1) man page.' 1>&2 fi } ShutDown() { ReportDiscrepancies # Always -- at exit -- shut down include_server and remove $socket_dir if [ -n "$include_server_pid" ] && \ ps -p "$include_server_pid" > /dev/null; then echo '__________Shutting down distcc-pump include server' kill $include_server_pid # Wait until it's really dead. We need to do this because the # include server may produce output after receiving SIGTERM. # Note that while 'sleep 0.01' is relying on a feature of GNU sleep, # that's OK; on systems that don't support it, it's effectively the # same as 'sleep 0', i.e. we'll just busy-wait rather than sleeping. while kill -0 $include_server_pid; do sleep 0.01; done >/dev/null 2>&1 fi if [ -f "$include_server_stdout" ]; then cat "$include_server_stdout" fi if [ -f "$include_server_stderr" ]; then cat "$include_server_stderr" >&2 fi if [ -n "$socket_dir" ]; then rm -rf "$socket_dir" fi if [ -n "$tmp_pid_file" ]; then rm -f "$tmp_pid_file" fi if [ -n "$available_hosts_file" ]; then rm -f "$available_hosts_file" fi } # Invokes lsdistcc to find the available servers. This list is # \n-separated and written to the filepath provided as $1. AvailableHosts() { available_hosts="$1" lsdistcc="$DISTCC_LOCATION/lsdistcc" if [ ! -x "$lsdistcc" ]; then echo "$0: error: can't find lsdistcc (looked in $DISTCC_LOCATION)" 1>&2 exit 1 fi # Call lsdistcc and let it wait no more than 150ms unless overridden in # LSDISTCC_ARGS. "$lsdistcc" -c150 $LSDISTCC_ARGS $DISTCC_POTENTIAL_HOSTS > "$available_hosts" } # Exports DISTCC_HOSTS as a function of the single argument and the global # variable $available_hosts_file. ExportDISTCC_HOSTS() { include_server_status="$1" opts='' if [ "$include_server_status" = 0 ]; then # The include server is up. # Make 'cpp' mode (with lzo) the default. opts=",cpp,lzo" else # The include server is not ready. # Make 'lzo' mode the default. if [ "$?" = 1 ]; then echo "__________Warning: distcc-pump include server failed;" \ "running unpumped" 1>&2 fi opts=",lzo" fi # When calculating final value of DISTCC_HOSTS, we get rid of # newlines (thanks to "`sed ...`"). export DISTCC_HOSTS="--randomize `sed s/'$'/$opts/ $available_hosts_file`" if [ "$verbose" = 1 ]; then echo "__________Found" \ "`wc -l < $available_hosts_file` available distcc servers" fi } StartIncludeServerAndDetermineHosts() { include_server_status=1 # ie, not running (yet) if [ -n "$DISTCC_POTENTIAL_HOSTS" ]; then # Probe the distcc servers. It may take up to a second. But # starting the include server takes about 150ms. Make these # activities happen in parallel. # First, the lsdistcc command goes in the background. available_hosts_file=`MakeTmpFile "distcc-pump-hosts"` AvailableHosts "$available_hosts_file" & # Second, the include server goes in the foreground so variables can be set. StartIncludeServer && include_server_status=0 # Await for AvailableHosts to finish. wait ExportDISTCC_HOSTS "$include_server_status" rm -f "$available_hosts_file" else if [ -z "$DISTCC_HOSTS" ] && [ -z "$DISTCC_DIR" -o ! -f "$DISTCC_DIR/hosts" ] && [ -z "$HOME" -o ! -f "$HOME/.distcc/hosts" ] && [ ! -f "$sysconfdir/distcc/hosts" ] then echo "$program_name:" \ "expected environment variables \"DISTCC_HOSTS\" or" \ "\"DISTCC_POTENTIAL_HOSTS\" to be set, or to find a" \ "distcc hosts file in \"\$DISTCC_DIR/hosts\"," \ "\"\$HOME/.distcc/hosts\", or \"$sysconfdir/distcc/hosts\"." \ 1>&2 exit 1 else hosts=`$distcc_location/distcc --show-hosts` num_hosts=`echo "$hosts" | wc -l` num_pump_hosts=`echo "$hosts" | grep ',cpp' | wc -l` if [ $num_hosts -eq 0 ]; then echo "$program_name: error: distcc hosts list is empty!" 1>&2 exit 1 elif [ $num_pump_hosts -eq 0 ]; then echo "$program_name: error: pump mode requested, but distcc" \ "hosts list does not contain any hosts with ',cpp' option" 1>&2 exit 1 else if [ "$verbose" = 1 ]; then server_word="servers" if [ $num_hosts = 1 ]; then server_word="server" fi if [ $num_hosts -eq $num_pump_hosts ]; then echo "__________Using $num_hosts distcc $server_word in pump mode" else echo "__________Using $num_hosts distcc $server_word, of which" \ "only $num_pump_hosts support(s) pump mode" fi fi fi fi StartIncludeServer && include_server_status=0 fi return "$include_server_status" } # Prints out environment variable settings, for the --startup option. DumpEnvironmentVariables() { # Variables used by "pump --shutdown" echo export INCLUDE_SERVER_PID=\'$include_server_pid\' echo export INCLUDE_SERVER_DIR=\'$socket_dir\' # Variables used by the distcc client echo export INCLUDE_SERVER_PORT=\'$INCLUDE_SERVER_PORT\' if [ -n "$DISTCC_HOSTS" ]; then echo export DISTCC_HOSTS=\'$DISTCC_HOSTS\' fi echo export PATH=\'$distcc_location:$PATH\' } Main() { CheckUsage "$@" Initialize case "$*" in --startup) # Don't put ordinary progress messages on stdout, # because they interfere with the environment variable # settings that we print out. verbose=0 # Redirect the include server's stdin/stdout/stderr redirect_io=1 trap 'ShutDown' EXIT # In case we get interrupted. StartIncludeServerAndDetermineHosts include_server_status=$? trap '' EXIT if [ "$include_server_status" = 0 ]; then DumpEnvironmentVariables exit 0 else exit 1 fi ;; --shutdown) include_server_pid="$INCLUDE_SERVER_PID" socket_dir="$INCLUDE_SERVER_DIR" include_server_stdout="$socket_dir/stdout" include_server_stderr="$socket_dir/stderr" ShutDown exit 0 ;; *) trap 'ShutDown' EXIT Announce StartIncludeServerAndDetermineHosts || exit 1 # Now execute the command that is the argument of 'pump'. PATH="$distcc_location:$PATH" \ "$@" # When we exit, the ShutDown function will be called. ;; esac } Main "$@" distcc-3.1/source/README.pump0000640000175000017500000000521311115326647015005 0ustar wolffwolffSee README for basic information on distcc. Distcc's "pump" mode improves on plain distcc by distributing not only compilation but also preprocessing to distcc servers. The pump mode uses an "include server" process that runs during the build. The include server parses and analyzes source (including header) files. It runs on the workstation that initiates the build. The include server analyzes each header file only a few times during a build, sometimes just once. In contrast, during ordinary distcc operation, the preprocessor examines each header file multiple times, even hundreds of times for a large build. In pump mode, a static analysis algorithm inspects each #include directive and computes a superset of the possible values of its argument. The resulting dependency graph among header files persists during the lifetime of the include server, which then acts as a cache for include analysis. The include server compresses source files into a temporary directory as they are encountered. In this way, a given source file is compressed only once during the build. It may happen that a header file is included via an absolutely specified include directory such as -I/absolute/path. But on the compilation server the path -I/absolute/path does not exist; instead the server places foo.h under /server_temporary_path/absolute/path for some /server_temporary_path root directory. This directory has no meaning on the workstation. Before compressing foo.h, the include server therefore inserts a #line directive in foo.h, to inform the preprocessor that the real location is /absolute/path. The distcc client asks the include server for the list of compressed files that constitute the transitive closure of the source file to be compiled. It then spools these files to a distcc server. The distcc server unpacks these files in the /server_temporary_path directory before preprocessing and compiling. The server also rewrites include options, such as -I's, to reflect the new locations of the files on the server. The .d and the .o files are both rewritten as necessary to refer to client-side filenames and returned to the pump-mode client. Pump mode is able to distribute compilations up to 10X faster than plain distcc. But because building also involves linking and perhaps generation of source files, the overall speed-up of the build time is variable. The pump mode was developed to be used with large clusters of distcc servers, providing hundreds of CPUs. With versions of gcc >= 4.1.1, pump mode will probably not show major performance gains using clusters of less than ten CPUs. The preprocessor running on the workstation is fast enough to keep that many machines busy. distcc-3.1/source/m4/0000750000175000017500000000000011115327762013462 5ustar wolffwolffdistcc-3.1/source/m4/pkg.m40000640000175000017500000001312311115326636014505 0ustar wolffwolff# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # # Similar to PKG_CHECK_MODULES, make sure that the first instance of # this or PKG_CHECK_MODULES is called, or make sure to call # PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_ifval([$2], [$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$PKG_CONFIG"; then if test -n "$$1"; then pkg_cv_[]$1="$$1" else PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], [pkg_failed=yes]) fi else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` else $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD ifelse([$4], , [AC_MSG_ERROR(dnl [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT ])], [$4]) elif test $pkg_failed = untried; then ifelse([$4], , [AC_MSG_FAILURE(dnl [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])], [$4]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) ifelse([$3], , :, [$3]) fi[]dnl ])# PKG_CHECK_MODULES distcc-3.1/source/m4/acx_pthread.m40000640000175000017500000003176611115326636016223 0ustar wolffwolff# This was retrieved from # http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?revision=1277&root=avahi # See also (perhaps for new versions?) # http://svn.0pointer.de/viewvc/trunk/common/acx_pthread.m4?root=avahi # # We've rewritten the inconsistency check code (from avahi), to work # more broadly. In particular, it no longer assumes ld accepts -zdefs. # This caused a restructing of the code, but the functionality has only # changed a little. dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) dnl dnl @summary figure out how to build C programs using POSIX threads dnl dnl This macro figures out how to build C programs using POSIX threads. dnl It sets the PTHREAD_LIBS output variable to the threads library and dnl linker flags, and the PTHREAD_CFLAGS output variable to any special dnl C compiler flags that are needed. (The user can also force certain dnl compiler flags/libs to be tested by setting these environment dnl variables.) dnl dnl Also sets PTHREAD_CC to any special C compiler that is needed for dnl multi-threaded programs (defaults to the value of CC otherwise). dnl (This is necessary on AIX to use the special cc_r compiler alias.) dnl dnl NOTE: You are assumed to not only compile your program with these dnl flags, but also link it with them as well. e.g. you should link dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS dnl $LIBS dnl dnl If you are only building threads programs, you may wish to use dnl these variables in your default LIBS, CFLAGS, and CC: dnl dnl LIBS="$PTHREAD_LIBS $LIBS" dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" dnl CC="$PTHREAD_CC" dnl dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). dnl dnl ACTION-IF-FOUND is a list of shell commands to run if a threads dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the dnl default action will define HAVE_PTHREAD. dnl dnl Please let the authors know if this macro fails on any platform, or dnl if you have any other suggestions or comments. This macro was based dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros dnl posted by Alejandro Forero Cuervo to the autoconf macro repository. dnl We are also grateful for the helpful feedback of numerous users. dnl dnl @category InstalledPackages dnl @author Steven G. Johnson dnl @version 2006-05-29 dnl @license GPLWithACException dnl dnl Checks for GCC shared/pthread inconsistency based on work by dnl Marcin Owsiany AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_TRY_LINK([#include ], [int attr=$attr; return attr;], [attr_name=$attr; break]) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) else PTHREAD_CC=$CC fi # The next part tries to detect GCC inconsistency with -shared on some # architectures and systems. The problem is that in certain # configurations, when -shared is specified, GCC "forgets" to # internally use various flags which are still necessary. # # Prepare the flags # save_CFLAGS="$CFLAGS" save_LIBS="$LIBS" save_CC="$CC" # Try with the flags determined by the earlier checks. # # -Wl,-z,defs forces link-time symbol resolution, so that the # linking checks with -shared actually have any value # # FIXME: -fPIC is required for -shared on many architectures, # so we specify it here, but the right way would probably be to # properly detect whether it is actually required. CFLAGS="-shared -fPIC -Wl,-z,defs $CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CC="$PTHREAD_CC" # In order not to create several levels of indentation, we test # the value of "$done" until we find the cure or run out of ideas. done="no" # First, make sure the CFLAGS we added are actually accepted by our # compiler. If not (and OS X's ld, for instance, does not accept -z), # then we can't do this test. if test x"$done" = xno; then AC_MSG_CHECKING([whether to check for GCC pthread/shared inconsistencies]) AC_TRY_LINK(,, , [done=yes]) if test "x$done" = xyes ; then AC_MSG_RESULT([no]) else AC_MSG_RESULT([yes]) fi fi if test x"$done" = xno; then AC_MSG_CHECKING([whether -pthread is sufficient with -shared]) AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [done=yes]) if test "x$done" = xyes; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi fi # # Linux gcc on some architectures such as mips/mipsel forgets # about -lpthread # if test x"$done" = xno; then AC_MSG_CHECKING([whether -lpthread fixes that]) LIBS="-lpthread $PTHREAD_LIBS $save_LIBS" AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [done=yes]) if test "x$done" = xyes; then AC_MSG_RESULT([yes]) PTHREAD_LIBS="-lpthread $PTHREAD_LIBS" else AC_MSG_RESULT([no]) fi fi # # FreeBSD 4.10 gcc forgets to use -lc_r instead of -lc # if test x"$done" = xno; then AC_MSG_CHECKING([whether -lc_r fixes that]) LIBS="-lc_r $PTHREAD_LIBS $save_LIBS" AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [done=yes]) if test "x$done" = xyes; then AC_MSG_RESULT([yes]) PTHREAD_LIBS="-lc_r $PTHREAD_LIBS" else AC_MSG_RESULT([no]) fi fi if test x"$done" = xno; then # OK, we have run out of ideas AC_MSG_WARN([Impossible to determine how to use pthreads with shared libraries]) # so it's not safe to assume that we may use pthreads acx_pthread_ok=no fi CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" CC="$save_CC" else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl ACX_PTHREAD distcc-3.1/source/config.sub0000750000175000017500000007170411115326647015137 0ustar wolffwolff#! /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 . 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 ." 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: distcc-3.1/source/bench/0000750000175000017500000000000011115327757014225 5ustar wolffwolffdistcc-3.1/source/bench/actions.py0000750000175000017500000000613111115326635016235 0ustar wolffwolff# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # Tuples of (name, default, descr) all_actions = [('download', True, ''), ('md5check', True, 'check file was downloaded correctly'), ('sweep', True, 'remove build directory before unpacking'), ('unpack', True, 'unpack source'), ('configure', True, ''), ('build', True, ''), ('clean', True, 'run "make clean" or equivalent'), ('scrub', False, 'remove build directory')] # Actions done on a per-project (rather than a per-build) basis project_actions = ('download', 'md5check') def action_help(): print "Actions:" for action, default, descr in all_actions: default_ch = default and '*' or ' ' print " %c %-20s %s" % (default_ch, action, descr) print " (* = on by default)" # Filter out only actions where 'default' is true default_actions = [a[0] for a in all_actions if a[1]] def parse_opt_actions(optarg): opt_actions = optarg.split(',') action_names = [a[0] for a in all_actions] for oa in opt_actions: if oa not in action_names: raise ValueError, ("no such action: %s" % `oa`) return opt_actions def remove_unnecessary_actions(opt_actions, force, did_download, did_configure): """Given a list of actions (as a string), and a force value (as described in the help text for benchmark.py), and a bool indicating whether 'configure' was successfully run for this build or not, return a new list which is the actions to actually perform for this build. Returns two lists: one that can be done on a per-project basis, and one that has to be done on a per-build basis (as we build the project with various different flags). """ if force == 0 and did_configure and did_download: remove = ('download', 'md5check', 'sweep', 'unpack', 'configure') elif force <= 1 and did_download: remove = ('download', ) else: remove = () new_project_actions = [oa for oa in opt_actions if oa in project_actions and oa not in remove] new_build_actions = [oa for oa in opt_actions if oa not in project_actions and oa not in remove] return new_project_actions, new_build_actions distcc-3.1/source/bench/buildutil.py0000750000175000017500000000564111115326635016577 0ustar wolffwolff# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. def make_dir(d): import os if not os.path.isdir(d): os.makedirs(d) def run_cmd(cmd, expected=0): import time, os before = time.time() print '%% %s' % cmd result = os.system(cmd) after = time.time() elapsed = (after - before) print '%16.4fs elapsed\n' % elapsed if expected is not None: if expected != result: raise AssertionError("command failed: expected status %d, got %d", expected, result) return result, elapsed def rm_files(file_list): import os for f in file_list: if os.path.exists(f): os.unlink(f) def count_hosts(hosts): """Parse a distcc Hosts Specification and count the number of hosts.""" num_hosts = 0 for host in hosts.split(): if host == '+zeroconf': raise ValueError, "Can't count hosts when +zeroconf is in DISTCC_HOSTS" if host.startswith('-'): # Don't count options such as '--randomize', '--localslots=N', # or '--localslots_cpp=N' as hosts. continue num_hosts += 1 return num_hosts def tweak_hosts(hosts, max_hosts, opts): """ Parse a distcc Hosts Specification and construct a new one that has at most 'max_hosts' hosts in it, appending 'opts' to each host in the Hosts Specification. Arguments: hosts: the original hosts specification; a string. max_hosts: the number of hosts to allow; an integer. Returns: the new hosts specification; a string. """ num_hosts = 0 hosts_list = [] for host in hosts.split(): if host == '+zeroconf': raise ValueError, "Can't limit hosts when +zeroconf in DISTCC_HOSTS" if host.startswith('-'): # Don't count options such as '--randomize', '--localslots=N', # or '--localslots_cpp=N' as hosts; but keep them in the host list. hosts_list.append(host) continue else: hosts_list.append(host + opts) num_hosts += 1 if num_hosts >= max_hosts: break return ' '.join(hosts_list) distcc-3.1/source/bench/compiler.py0000750000175000017500000001647711115326635016425 0ustar wolffwolff# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. import commands import os import shutil import stat import sys import tempfile import buildutil STANDARD_CC_NAMES = ['cc', 'gcc'] STANDARD_CXX_NAMES = ['cxx', 'c++', 'g++' ] def _find_executable(name): (rs, output) = commands.getstatusoutput('which "%s"' % name) if rs: sys.exit("Could not determine location of '%s'" % name) return output.strip() class CompilerSpec: """Describes a compiler/make setup. Used to define different situations such as local compilation, and various degrees of parallelism.""" def __init__(self, where, cc, cxx, prefix='', make_opts='', pump_cmd='', num_hosts=1, host_opts='', name=None): """Constructor: Args: where: 'local', 'dist', 'lzo', or 'pump' cc: location of the C compiler cxx: location of the C++ prefix: a string, either 'distcc ' or '' make_opts: options to make, such as '-j120' host_opts: for appending to hosts in DISTCC_HOSTS such as ',lzo,cpp' name: a string """ self.where = where self.real_cc = _find_executable(cc) self.real_cxx = _find_executable(cxx) self.cc = prefix + self.real_cc self.cxx = prefix + self.real_cxx self.make_opts = make_opts self.host_opts = host_opts self.pump_cmd = pump_cmd self.num_hosts = num_hosts self.host_opts = host_opts self.name = name or (self.pump_cmd + self.real_cc + "__" + self.make_opts).replace(' ', '_') def prepare_shell_script_farm(self, farm_dir, masquerade): """Prepare farm directory for masquerading. Assume the compiler is not local. Each standard name, such as 'cc', is used for form a shell script, named 'cc', that contains the line 'distcc /my/path/gcc "$@"', where '/my/path/gcc' is the value of the compiler.gcc field. If the compiler is local, then the same procedure is followed except that 'distcc' is omitted from the command line. """ assert os.path.isdir(farm_dir) assert os.path.isabs(farm_dir) def make_shell_script(name, compiler_path, where): fd = open(os.path.join(farm_dir, name), 'w') fd.write('#!/bin/sh\n%s%s "$@"' % (where != 'local' and 'distcc ' or '', compiler_path)) fd.close() os.chmod(os.path.join(farm_dir, name), stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) for generic_name in STANDARD_CC_NAMES: make_shell_script(generic_name, self.real_cc, self.where) for generic_name in STANDARD_CXX_NAMES: make_shell_script(generic_name, self.real_cxx, self.where) # Make shell wrapper to help manual debugging. fd = open(masquerade, 'w') fd.write("""\ #!/bin/sh # Execute $@, but force 'cc' and 'cxx'" to be those in the farm of # masquerading scripts. Each script in turn executes 'distcc' with the actual # compiler specified with the benchmark.py command. PATH=%s:"$PATH" "$@" """ % farm_dir) fd.close() os.chmod(masquerade, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR) def default_compilers(cc, cxx): return [parse_compiler_opt('local,h1,j1', cc, cxx), parse_compiler_opt('dist,h10,j20', cc, cxx), parse_compiler_opt('dist,h10,j40', cc, cxx), parse_compiler_opt('pump,h10,j20', cc, cxx), parse_compiler_opt('pump,h10,j40', cc, cxx), ] def parse_compiler_opt(optarg, cc, cxx): """Parse command-line specification of a compiler (-c/--compiler). XXX: I don't really know what the best syntax for this is. For the moment, it is "local", "dist", "lzo", or "pump", followed by ",h" and the number of hosts to use, followed by ",j" and the number of jobs to use (for the -j option to make). """ where, hosts, jobs = optarg.split(',') if hosts.startswith("h"): hosts = int(hosts[1:]) if not os.getenv("DISTCC_HOSTS"): raise ValueError, "You must set DISTCC_HOSTS before running benchmarks" max_hosts = buildutil.count_hosts(os.getenv("DISTCC_HOSTS")) if hosts > max_hosts: print ("Warning: can't use %d hosts: DISTCC_HOSTS only has %d" % (hosts, max_hosts)) hosts = max_hosts else: raise ValueError, ("invalid compiler option: " "expecting '...,h,...', found %s" % `hosts`) if jobs.startswith("j"): jobs = int(jobs[1:]) else: raise ValueError, ("invalid compiler option: " "expecting '...,j', found %s" % `jobs`) if where == 'local': return CompilerSpec(where=where, name='local_%02d' % jobs, cc=cc, cxx=cxx, num_hosts=1, make_opts='-j%d' % jobs) elif where == 'dist': return CompilerSpec(where=where, name='dist_h%02d_j%02d' % (hosts, jobs), cc=cc, cxx=cxx, prefix='distcc ', num_hosts=hosts, make_opts='-j%d' % jobs) elif where == 'lzo': return CompilerSpec(where=where, name='lzo_h%02d_j%02d' % (hosts, jobs), cc=cc, cxx=cxx, prefix='distcc ', num_hosts=hosts, host_opts=",lzo", make_opts='-j%d' % jobs) elif where == 'pump': return CompilerSpec(where=where, name='pump_h%02d_j%02d' % (hosts, jobs), cc=cc, cxx=cxx, prefix='distcc ', pump_cmd='pump ', num_hosts=hosts, host_opts=",cpp,lzo", make_opts='-j%d' % jobs) else: raise ValueError, ("invalid compiler option: don't understand %s" % `where`) def prepare_shell_script_farm(compiler, farm_dir, masquerade): compiler.prepare_shell_script_farm(farm_dir, masquerade) distcc-3.1/source/bench/Summary.py0000750000175000017500000001023111115326635016226 0ustar wolffwolff# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. import buildutil import os import statistics class Summary: """Stores and prints results of building different things""" # Table is a sequence, because we prefer to have things printed # out in the order they were executed. def __init__(self): self._table = [] def store(self, project, compiler, time_info_accumulator): """ Args: project: a Project object compiler: a Compiler object time_info_accumulator: the string 'FAIL' or a list of Build.TimeInfo records The time information is a list because we can build projects repeatedly. """ self._table.append((project.name, compiler.name, time_info_accumulator)) def print_raw(self): from pprint import pprint pprint(self._table) @staticmethod def print_mean_and_sd(times, unit='s', no_sd=False): assert len(unit) == 1, unit mean = statistics.mean(times) sd = statistics.std(times) if mean is None: print "%s%s " % ("n/a", sd_space), else: print "%8.1f%s " % (mean, unit), if not no_sd: if sd is None: print "%9s " % "n/a", else: print "%8.1f%s " % (sd, unit), def print_table(self): import time, os, sys import statistics # if nothing was run, skip it if not len(self._table): return """Print out in a nice tabular form""" print """ ======================== distcc benchmark results ======================== """ print "Date: ", time.ctime() hosts = os.getenv('DISTCC_HOSTS') print "DISTCC_HOSTS: %s" % `hosts` print "Total hosts: %d" % buildutil.count_hosts(hosts) number_CPUs = os.sysconf('SC_NPROCESSORS_ONLN') print "Local number of CPUs: %s" % number_CPUs sys.stdout.flush() os.system("uname -a") print ("%-20s %-30s %9s %9s %9s %9s %9s" % ('project', 'compiler', 'time', 's.d.', 'CPU time', 'CPU util', 'incl serv')) for row in self._table: print "%-20s %-30s " % row[:2], time_info_accumulator = row[2] if isinstance(time_info_accumulator, str): print ' ' * 4, time_info_accumulator else: real_times = [time_info.real for time_info in time_info_accumulator] Summary.print_mean_and_sd(real_times) cpu_times = [time_info.user + time_info.system for time_info in time_info_accumulator] self.print_mean_and_sd(cpu_times, no_sd=True) cpu_util_ratios = ( [100 * cpu_times[i]/(number_CPUs * time_info_accumulator[i].real) for i in range(len(time_info_accumulator))]) self.print_mean_and_sd(cpu_util_ratios, unit='%', no_sd=True) include_server_times = [time_info.include_server for time_info in time_info_accumulator] if None not in include_server_times: self.print_mean_and_sd(include_server_times, no_sd=True) print distcc-3.1/source/bench/ProjectDefs.py0000750000175000017500000001364211115326635017012 0ustar wolffwolff# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003, 2004 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. __doc__ = """distcc benchmark project definitions""" from Project import Project # Consider the following when adding a new project: # 1) Should be fairly large. That's where distcc helps most. # 2) Should have minimal dependencies. That way, the build will # succeed without you needing to install lots of libraries # on your machine. # # See Project.py:Project.__init__.doc() for documentation of the # named arguments that are allowed for Project. Project(url='http://ftp.gnu.org/gnu/hello/hello-2.1.1.tar.gz', md5='70c9ccf9fac07f762c24f2df2290784d *hello-2.1.1.tar.gz', ).register() Project(url='http://ftp.gnu.org/gnu/make/make-3.80.tar.bz2', md5='0bbd1df101bc0294d440471e50feca71 *make-3.80.tar.bz2' ).register() Project(url='ftp://ftp.gtk.org/pub/gtk/v2.0/glib-2.0.7.tar.bz2', md5='5882b1e729f57cb18af653a2f504197b glib-2.0.7.tar.bz2' ).register() Project(url='http://us1.samba.org/samba/ftp/old-versions/samba-2.2.7.tar.gz', build_subdir='source', md5='824cd4e305f9b744f3eec702a7b96f7f samba-2.2.7.tar.gz', ).register() Project(url='http://us1.samba.org/samba/ftp/old-versions/samba-3.0.20.tar.gz', name='samba-3.0.20', build_subdir='source', # newer versions of popt can be incompatible configure_cmd='./configure --with-included-popt', pre_build_cmd = 'make proto', ).register() Project(url='http://archive.apache.org/dist/httpd/httpd-2.0.43.tar.gz', md5='8051de5d160c43d4ed2cc47dc9be6fd3 httpd-2.0.43.tar.gz' ).register() Project(url='http://yate.null.ro/tarballs/yate2/yate-2.0.0-alpha2.tar.gz', name='yate', configure_cmd='./configure --without-libpq --without-mysql --without-wphwec --without-libgsm --without-libspeex --without-spandsp --without-pwlib --without-openh323 --without-libgtk2 --without-gtkmozilla --without-libqt4 --without-coredumper --without-doxygen --without-kdoc', md5='b9fd116bc5c8142de6e130931cd3bdf2 yate-2.0.0-alpha2.tar.gz' ).register() Project(url='http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.25.tar.bz2', md5='db95a49a656a3247d4995a797d333153 *linux-2.6.25.tar.bz2', configure_cmd="make V=1 HOSTCC='$(CC)' defconfig", build_cmd="make V=1 HOSTCC='$(CC)' bzImage", include_server_args='--stat_reset_triggers=include/linux/compile.h:include/asm/asm-offsets.h' ).register() Project(url='http://www.python.org/ftp/python/2.5.2/Python-2.5.2.tgz', name='Python-2.5.2', ).register() Project(url='http://ftp.gnu.org/gnu/binutils/binutils-2.18.tar.bz2', configure_cmd = './configure --disable-werror', ).register() # disable-sanity-checks is needed to stop it wanting linuxthreads -- # the resulting library is useless, but this is only a test. Project(url = 'http://ftp.gnu.org/pub/gnu/glibc/glibc-2.6.tar.bz2', build_subdir = '_build', configure_cmd = '../configure --disable-sanity-checks', ).register() Project(url='http://mirror.trouble-free.net/mysql_mirror/Downloads/MySQL-5.0/mysql-5.0.51b.tar.gz', md5='e6715a878a7c102f7a4c323f9ef63e8f *mysql-5.0.51b.tar.gz', configure_cmd = './configure', ).register() Project(url='http://sources-redhat.oc1.mirrors.redwire.net/gdb/old-releases/gdb-5.3.tar.gz', ).register() #### Commented out: gimp 1.2.3 has makefile bugs that break -j ## Project(url='ftp://212.8.35.65/pub/FreeBSD/distfiles/gimp-1.2.3.tar.bz2', ## md5='b19235f19f524f772a4aef597a69b1da *gimp-1.2.3.tar.bz2', ## configure_cmd='./configure --disable-perl', ## ).register() Project(url='ftp://ftp.gimp.org/pub/gimp/v2.2/gimp-2.2.10.tar.bz2', md5='aa29506ed2272af02941a7a601a7a097 gimp-2.2.10.tar.bz2', configure_cmd='./configure --disable-perl --disable-print', ).register() Project(url='http://ibiblio.org/pub/linux/system/emulators/wine/wine-0.9.4.tar.bz2', md5='73205d83a5612a43441a8532683c0434 wine-0.9.4.tar.bz2', ).register() Project(url='ftp://ftp.slackware.com/pub/slackware/slackware-9.1/source/xap/mozilla/mozilla-source-1.4.tar.bz2', name='mozilla-1.4', configure_cmd="LIBIDL_CONFIG=libIDL-config-2 ./configure", unpacked_subdir='mozilla', ).register() Project(url='http://ftp.mozilla.org/pub/firebird/releases/0.6/MozillaFirebird-0.6-source.tar.bz2', name='MozillaFirebird', unpacked_subdir='mozilla', ).register() #### Commented out: configure script hasn't kept up with modern gcc's. #### For instance, they check whether setrlimit takes an enum as the #### first argument by grepping for 'setrlimit(enum' in the .h file, #### but crosstool gcc's use a typedef, so it's 'setrlimit(newtype'. ## Project(url='http://download.dre.vanderbilt.edu/previous_versions/ACE+TAO+CIAO-5.6.5.tar.bz2', ## name='ace-5.6.5', ## unpacked_subdir='ACE_wrappers', ## build_subdir = '_build', ## configure_cmd='../configure', ## md5='32157a0a4cc9bd8dc03d98b90b707759 ACE+TAO+CIAO-5.6.5.tar.bz2' ## ).register() distcc-3.1/source/bench/statistics.py0000750000175000017500000000236711115326635016776 0ustar wolffwolff#! /usr/bin/env python2.2 # benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. import math def var(m): """ Variance of m. """ if len(m) < 2: return None mu = mean(m) return sum((x - mu) * (x - mu) for x in m) / (len(m) - 1.0) def std(m): """ Standard deviation of m. """ v = var(m) return v and math.sqrt(v) def mean(m): if len(m) < 1: return None return sum(m)/len(m) distcc-3.1/source/bench/Project.py0000750000175000017500000001341511115326635016206 0ustar wolffwolff# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. import re, os, sys, time from buildutil import make_dir, run_cmd # Trees of software to be built. trees = { } class Project: """Defines a project to be built and tested. The Python process remains in the top-level directory for the whole process. Commands are kicked off in subdirectories if necessary. 'subdir' variables give just a single component of a name; 'dir' variables give a full path.""" def __init__(self, url, package_file=None, name=None, md5=None, unpacked_subdir=None, build_subdir=None, configure_cmd=None, pre_build_cmd = None, build_cmd=None, include_server_args=""): """Specification of a project to build. url: the url to download the file. package_file: the filename of the downloaded url. If not specified, taken to be basename(url). This should rarely need to be specified. specified on the commandline to just benchmark a single project. name: the name used to identify the project when listing projects on the benchmark commandline. If not specified, taken to be package_file, but with the .tar.* extension removed. md5: the output of 'md5sum package_file'; used to verify a download. unpacked_subdir: The top-level directory created when we untar the package_file. If not specified, taken to be self.name, which is typically right (at least for projects make using autotools). build_subdir: the subdirectory of unpacked_subdir where building should be done; we create it if needed. Defaults to '.'. You should only need to change this if your project does not have its configure script in the top-level directory. configure_cmd: the command to generate the project's Makefile. It is run in build_subdir. Defaults to './configure'. pre_build_cmd: a command to run before running the build command. It is run in build_subdir. Defaults to running nothing. build_cmd: The command to build the project from the Makefile. We add VAR=val arguments, so build_cmd must be a single command that is either a form of 'make', or takes the same style arguments. Defaults to 'make'. include_server_args: include server tweaks such as stat reset triggers for builds that modify source files. """ self.url = url if not package_file: package_file = url.split('/')[-1] self.package_file = package_file if not name: name = re.match(r"(.*)\.tar(\.gz|\.bz2|)$", package_file).group(1) self.name = name self.md5 = md5 self.configure_cmd = configure_cmd or "./configure" self.build_cmd = build_cmd or "make" self.pre_build_cmd = pre_build_cmd self.package_dir = "packages" self.download_dir = "download" # By default, we assume the package creates an unpacked # directory whose name is the same as the tarball. For # example, Wine's tarball is "Wine-xxxxxxx", but it unpacks to # "wine-xxxxxxxx". # TODO(csilvers): figure out automatically if only one TLD. self.unpacked_subdir = unpacked_subdir or self.name self.build_subdir = build_subdir self.include_server_args = include_server_args def register(self): trees[self.name] = self def __repr__(self): return "Project(name=%s)" % `self.name` def download(self): """Download package from vendor site.""" make_dir(self.package_dir) make_dir(self.download_dir) if not os.path.isfile(os.path.join(self.package_dir, self.package_file)): # XXX: snarf gets upset if the HTTP server returns "416 # Requested Range Not Satisfiable" because the file is already # totally downloaded. This is kind of a snarf bug. print "** Downloading" run_cmd("cd %s && wget --continue %s" % (self.download_dir, self.url)) run_cmd("mv %s %s" % (os.path.join(self.download_dir, self.package_file), self.package_dir)) def did_download(self): return os.path.exists(os.path.join(self.package_dir, self.package_file)) def md5check(self): if self.md5: print "** Checking source package integrity" run_cmd("cd %s && echo '%s' | md5sum -c /dev/stdin" % (self.package_dir, self.md5)) def pre_actions(self, actions): """Perform actions preparatory to building according to selection.""" if 'download' in actions: self.download() if 'md5check' in actions: self.md5check() distcc-3.1/source/bench/Build.py0000750000175000017500000002322211115326635015634 0ustar wolffwolff# benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. from Project import Project from compiler import CompilerSpec, prepare_shell_script_farm import buildutil from buildutil import make_dir, run_cmd, rm_files import re, os, sys, time # For parsing output of 'time -p'. RE_TIME = re.compile(r"""^real \s* (\d*\.\d*)\n user \s* (\d*\.\d*)\n sys \s* (\d*\.\d*)""", re.VERBOSE | re.MULTILINE) class TimeInfo: """A record of real, system, and user time.""" def __init__(self, real=None, system=None, user=None, include_server=None): self.real = real self.system = system self.user = user self.include_server = include_server class Build: """A Build is a combination of a Project and CompilerSpec. Note: when done with an object of this type, call its restore function; otherwise PATH will remain changed to an inappropriate value. """ def __init__(self, project, compiler, n_repeats): self.project = project self.compiler = compiler self.n_repeats = n_repeats self.base_dir = os.path.join(os.getcwd(), "build", self.project.name, self.compiler.name) self.unpacked_dir = os.path.join(self.base_dir, self.project.unpacked_subdir) # Some packages need to be started from a subdirectory of their # unpacked form. For example, Samba is compiled from the "source/" # subdirectory of the unpacked source. if self.project.build_subdir: self.build_dir = os.path.join(self.unpacked_dir, project.build_subdir) else: self.build_dir = self.unpacked_dir self.log_dir = self.build_dir self.configure_done = os.path.join(self.log_dir, "bench-configure.done") def __repr__(self): return "Build(%s, %s)" % (`self.project`, `self.compiler`) def _run_cmd_with_redirect_farm(self, cmd): """Initialize shell script farm for given compiler, augment PATH, and run cmd. A shell script farm is a set of scripts for dispatching a chosen compiler using distcc. For example, the 'cc' script may contain the one line: dist /usr/mine/gcc "$@" """ farm_dir = os.path.join(self.build_dir, 'build-cc-script-farm') make_dir(farm_dir) print ("** Creating masquerading shell scripts in '%s'" % farm_dir) masquerade = os.path.join(self.build_dir, 'masquerade') prepare_shell_script_farm(self.compiler, farm_dir, masquerade) old_path = os.environ['PATH'] try: os.environ['PATH'] = farm_dir + ":" + old_path return run_cmd(cmd) finally: os.environ['PATH'] = old_path def unpack(self): """Unpack from source tarball into build directory""" if re.search(r"\.tar\.bz2$", self.project.package_file): tar_fmt = "tar xf %s --bzip2" else: tar_fmt = "tar xfz %s" tar_cmd = tar_fmt % os.path.join(os.getcwd(), self.project.package_dir, self.project.package_file) make_dir(self.base_dir) print "** Unpacking..." run_cmd("cd %s && %s" % (self.base_dir, tar_cmd)) def configure(self): """Run configuration command for this tree, if any.""" make_dir(self.log_dir) configure_log = os.path.join(self.log_dir, "bench-configure.log") distcc_log = os.path.join(self.log_dir, "bench-configure-distcc.log") rm_files((configure_log, distcc_log, self.configure_done)) make_dir(self.build_dir) print "** Configuring..." cmd = ("cd %s && \\\nDISTCC_LOG='%s' \\\nCC='%s' \\\nCXX='%s' \\\n%s \\\n>%s 2>&1" % (self.build_dir, distcc_log, self.compiler.cc, self.compiler.cxx, self.project.configure_cmd, configure_log)) self._run_cmd_with_redirect_farm(cmd) # Touch a file if the configure was successfully done, so we know. open(self.configure_done, 'w').close() @staticmethod def _extract_time_info(log_file_name): """Open log file and look for output of 'time -p' and include server time.""" log_file = open(log_file_name, 'r') text = log_file.read() log_file.close() match = RE_TIME.search(text) if not match: sys.exit('Could not locate time information in log %s.' % log_file_name) time_info = TimeInfo(float(match.group(1)), float(match.group(2)), float(match.group(3))) # Now locate include server cpu time if present. lines = text.splitlines() for line in lines: if line.startswith('Include server timing. '): is_time = float( line[len('Include server timing. '):].split()[9][:-1]) time_info.include_server = is_time break return time_info def did_configure(self): """Returns true if configure was successfully run for this build in the past. """ return os.path.isfile(self.configure_done) def build(self): """Actually build the package.""" build_log = os.path.join(self.log_dir, "bench-build.log") prebuild_log = os.path.join(self.log_dir, "bench-prebuild.log") distcc_log = os.path.join(self.log_dir, "bench-build-distcc.log") rm_files((build_log, distcc_log)) make_dir(self.build_dir) print "** Building..." if self.project.pre_build_cmd: cmd = ("cd %s && %s > %s 2>&1" % (self.build_dir, self.project.pre_build_cmd, prebuild_log)) self._run_cmd_with_redirect_farm(cmd) distcc_hosts = buildutil.tweak_hosts(os.getenv("DISTCC_HOSTS"), self.compiler.num_hosts, self.compiler.host_opts) # We use built-in 'time' to measure real, system, and user time. To # allow its stderr to be grabbed, the time command is executed in a # subshell. cmd = ("cd %s && \\\n" "(time -p \\\n" "DISTCC_HOSTS='%s' \\\n" "INCLUDE_SERVER_ARGS='-t --unsafe_absolute_includes %s' \\\n" "%s%s \\\nDISTCC_LOG='%s' \\\nCC='%s' \\\nCXX='%s' " "\\\n%s)" "\\\n>%s 2>&1" % (self.build_dir, distcc_hosts, self.project.include_server_args, self.compiler.pump_cmd, self.project.build_cmd, distcc_log, self.compiler.cc, self.compiler.cxx, self.compiler.make_opts, build_log)) result, unused_elapsed = self._run_cmd_with_redirect_farm(cmd) return (result, Build._extract_time_info(build_log)) def clean(self): clean_log = os.path.join(self.log_dir, "bench-clean.log") make_dir(self.build_dir) print "** Cleaning build directory" cmd = "cd %s && make clean >%s 2>&1" % (self.build_dir, clean_log) self._run_cmd_with_redirect_farm(cmd) def scrub(self): print "** Removing build directory" rm_files((self.configure_done, )) run_cmd("rm -rf %s" % self.unpacked_dir) def build_actions(self, actions, summary): """Carry out selected actions. Catch exceptions and handle.""" try: # The time_info_accumulator is normally a list. But if something # goes wrong, it will contain a short string indicating the problem. time_info_accumulator = [] if 'sweep' in actions: self.scrub() if 'unpack' in actions: self.unpack() if 'configure' in actions: self.configure() # This is a safety measure, in case a previous benchmark # run left the build in an incomplete state. if 'clean' in actions: self.clean() for i in range(self.n_repeats): if 'build' in actions: (result, time_info) = self.build() if result: # that is, if result is bad! time_info_accumulator = 'NON-ZERO STATUS' elif isinstance(time_info_accumulator, list): time_info_accumulator.append(time_info) if 'clean' in actions: self.clean() if 'scrub' in actions: self.scrub() summary.store(self.project, self.compiler, time_info_accumulator) except KeyboardInterrupt: raise except: apply(sys.excepthook, sys.exc_info()) # print traceback summary.store(self.project, self.compiler, 'FAIL WITH EXCEPTION') distcc-3.1/source/bench/benchmark.py0000750000175000017500000002014511115326635016530 0ustar wolffwolff#! /usr/bin/python # benchmark -- automated system for testing distcc correctness # and performance on various source trees. # Copyright (C) 2002, 2003, 2004 by Martin Pool # Copyright 2008 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. # Unlike the main distcc test suite, this program *does* require you # to manually set up servers on your choice of machines on the # network, and make sure that they all have appropriate compilers # installed. The performance measurements obviously depend on the # network and hardware available. # It also depends on you having the necessary dependencies to build # the software. If you regularly build software on Linux you should # be OK. Some things (the GIMP) will be harder than others. # On some platforms, it may be impossible to build some targets -- for # example, Linux depends on having a real-mode x86 assembler, which # probably isn't installed on Solaris. # Note that running this program will potentially download many # megabytes of test data. # TODO: Support applying patches after unpacking, before building. # For example, they might be needed to fix -j bugs in the Makefile. # TODO: In stats, show ratio of build time to slowest build time. (Or # to first one run?) # TODO: Allow choice of which compiler and make options to use. # TODO: Perhaps add option to do "make clean" -- this might be faster # than unzipping and configuring every time. But perhaps also less # reproducible. # TODO: Add option to run tests on different sets or orderings of # machines. import os import re import sys import time from getopt import getopt from Summary import Summary from Project import Project, trees from compiler import CompilerSpec from Build import Build import actions, compiler import ProjectDefs # this adds a lot of definitions to 'trees' def error(msg): sys.stderr.write(msg + "\n") def list_projects(): names = trees.keys() names.sort() for n in names: print n def find_project(name): """ Return the nearest unique match for name. """ best_match = None for pn in trees.keys(): if pn.startswith(name): if best_match: raise ValueError, "ambiguous prefix %s" % name else: best_match = pn if not best_match: raise ValueError, "nothing matches %s" % name else: return trees[best_match] def show_help(): print """Usage: benchmark.py [OPTION]... [PROJECT]... Test distcc relative performance building different projects. By default, all known projects are built. Options: --help show brief help message --list-projects show defined projects --cc=PATH specify base value of CC to pass to configure --cxx=PATH specify base value of CXX to pass to configure --output=FILE print final summary to FILE in addition to stdout -c, --compiler=COMPILER specify one compiler to use; format is {local|dist|lzo|pump},h,j -n N repeat compilation N times -a, --actions=ACTIONS comma-separated list of action phases to perform -f N, --force=N If set to 0, skip download, unpack, and configure actions if they've already been successfully performed; if set to 1 (the default), only skip the download action; if set to 2, do not skip any action The C and C++ compiler versions used can be set with the --cc and --cxx options. Use of distcc features is set with the -c/--compiler option. The argument to -c/--compiler has three components, separated by commas. The first component specifies which distcc features to enabled: "local" means run cc locally, "distcc" means use plain distcc, "lzo" means enabled compression, and "pump" means to enable pump mode and compression. The second component specifies how many distcc hosts to use. The third component specifies how many jobs to run (the -j/--jobs option to "make"). Multiple -c/--compiler options specify different scenarios to measure. The default is to measure a few reasonable scenarios. """ actions.action_help() # -a is for developer use only and not documented; unless you're # careful the results will just be confusing. ###################################################################### def main(): """Run the benchmark per arguments""" # Ensure that stdout and stderr are line buffered, rather than # block buffered, as might be the default when running with # stdout/stderr redirected to a file; this ensures that the # output is prompt, even when the script takes a long time for # a single step, and it also avoids confusing intermingling of # stdout and stderr. sys.stdout = os.fdopen(1, "w", 1) sys.stderr = os.fdopen(2, "w", 1) sum = Summary() options, args = getopt(sys.argv[1:], 'a:c:n:f:', ['list-projects', 'actions=', 'help', 'compiler=', 'cc=', 'cxx=', 'output=', 'force=']) opt_actions = actions.default_actions opt_cc = 'cc' opt_cxx = 'c++' opt_output = None opt_compilers = [] opt_repeats = 1 opt_force = 1 for opt, optarg in options: if opt == '--help': show_help() return elif opt == '--list-projects': list_projects() return elif opt == '--actions' or opt == '-a': opt_actions = actions.parse_opt_actions(optarg) elif opt == '--cc': opt_cc = optarg elif opt == '--cxx': opt_cxx = optarg elif opt == '--output': opt_output = optarg elif opt == '--compiler' or opt == '-c': opt_compilers.append(optarg) elif opt == '-n': opt_repeats = int(optarg) elif opt == '-f' or opt == '--force': opt_force = int(optarg) if opt_compilers: set_compilers = [compiler.parse_compiler_opt(c, cc=opt_cc, cxx=opt_cxx) for c in opt_compilers] else: set_compilers = compiler.default_compilers(cc=opt_cc, cxx=opt_cxx) # Find named projects, or run all by default if args: chosen_projects = [find_project(name) for name in args] else: chosen_projects = trees.values() for proj in chosen_projects: # Ignore actions we did in a previous benchmark run, absent -f. # We only run the project's pre-actions if one of the builds # needs it because it hasn't successfully run 'configure' yet. project_actions, _ = actions.remove_unnecessary_actions( opt_actions, opt_force, proj.did_download(), 0) proj.pre_actions(project_actions) for comp in set_compilers: build = Build(proj, comp, opt_repeats) _, build_actions = actions.remove_unnecessary_actions( opt_actions, opt_force, proj.did_download(), build.did_configure()) build.build_actions(build_actions, sum) sum.print_table() # If --output was specified, print the table to the output-file too if opt_output: old_stdout = sys.stdout sys.stdout = open(opt_output, 'w') try: sum.print_table() finally: sys.stdout.close() sys.stdout = old_stdout if __name__ == '__main__': main() distcc-3.1/source/mkinstalldirs0000750000175000017500000000132111115326647015746 0ustar wolffwolff#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.1 2002/05/28 02:43:45 mbp Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here distcc-3.1/source/AUTHORS0000640000175000017500000000043311115326647014214 0ustar wolffwolffAuthor and maintainer emeritus of distcc: Martin Pool Authors of "pump" functionality, and maintainers of distcc: Nils Klarlund Fergus Henderson Craig Silverstein Manos Renieris See NEWS for credits of other contributors. distcc-3.1/source/contrib/0000750000175000017500000000000011115327755014604 5ustar wolffwolffdistcc-3.1/source/contrib/dmake0000640000175000017500000000074211115326641015605 0ustar wolffwolff#! /bin/sh # Example script contributed by Luke Gorrie # "Drop-in" front end to 'make' that uses the distributed compile farm # via `distcc' # Compile farm hosts are stored in ~bluetail/distcc-hosts. We exclude # the local machine to free up resources for preprocessing and # linking, since it seems to be the bottleneck (at least on # kookaburra). DISTCC_HOSTS=$(sed s/$(hostname -s)// < /home/share/bluetail/distcc-hosts) make CC='/home/share/luke/bin/distcc gcc' -j 7 "$@" distcc-3.1/source/contrib/stage-cc-wrapper.patch0000640000175000017500000000767411115326641021001 0ustar wolffwolffIndex: Makefile.in =================================================================== RCS file: /cvs/gcc/egcs/Makefile.in,v retrieving revision 1.110 diff -u -p -r1.110 Makefile.in --- Makefile.in 8 Jul 2002 21:40:41 -0000 1.110 +++ Makefile.in 14 Aug 2002 02:49:35 -0000 @@ -251,7 +251,7 @@ GCJ_FOR_TARGET = # variable is passed down to the gcc Makefile, where it is used to # build libgcc2.a. We define it here so that it can itself be # overridden on the command line. -GCC_FOR_TARGET = $$r/gcc/xgcc -B$$r/gcc/ $(FLAGS_FOR_TARGET) +GCC_FOR_TARGET = $(STAGE_CC_WRAPPER) $$r/gcc/xgcc -B$$r/gcc/ $(FLAGS_FOR_TARGET) AS_FOR_TARGET = ` \ if [ -f $$r/gas/as-new ] ; then \ Index: configure.in =================================================================== RCS file: /cvs/gcc/egcs/configure.in,v retrieving revision 1.176 diff -u -p -r1.176 configure.in --- configure.in 6 Aug 2002 09:26:29 -0000 1.176 +++ configure.in 14 Aug 2002 02:49:38 -0000 @@ -1554,10 +1554,10 @@ cat >$sedtemp < stage_last stage2_build: stage1_copy - $(MAKE) CC="stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" \ + $(MAKE) CC="$(STAGE_CC_WRAPPER) stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" \ STAGE_PREFIX=stage1/ \ $(STAGE2_FLAGS_TO_PASS) $(STAMP) stage2_build @@ -3342,7 +3342,7 @@ stage2_copy: stage2_build echo stage3_build > stage_last stage3_build: stage2_copy - $(MAKE) CC="stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" \ + $(MAKE) CC="$(STAGE_CC_WRAPPER) stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" \ STAGE_PREFIX=stage2/ \ $(STAGE2_FLAGS_TO_PASS) $(STAMP) stage3_build @@ -3355,7 +3355,7 @@ stage3_copy: stage3_build echo stage4_build > stage_last stage4_build: stage3_copy - $(MAKE) CC="stage3/xgcc$(exeext) -Bstage3/ -B$(build_tooldir)/bin/" \ + $(MAKE) CC="$(STAGE_CC_WRAPPER) stage3/xgcc$(exeext) -Bstage3/ -B$(build_tooldir)/bin/" \ STAGE_PREFIX=stage3/ \ $(STAGE2_FLAGS_TO_PASS) $(STAMP) stage4_build distcc-3.1/source/contrib/redhat/0000750000175000017500000000000011115327755016053 5ustar wolffwolffdistcc-3.1/source/contrib/redhat/init0000640000175000017500000000267111115326641016741 0ustar wolffwolff#!/bin/sh # # Init file for Distccd - A distributed compilation front-end. # WARNING: Don't enable on untrusted networks # # Written by Dag Wieers . # # chkconfig: - 80 20 # description: Distccd - distributed compilation front-end (daemon) \ # WARNING: Don't enable on untrusted networks # # processname: distccd # # config: /etc/sysconfig/distccd source /etc/init.d/functions source /etc/sysconfig/network ### Check that networking is up. [ "${NETWORKING}" == "no" ] && exit 0 [ -x "/usr/bin/distccd" ] || exit 1 ### Default variables SYSCONFIG="/etc/sysconfig/distccd" OPTIONS="" USER="distcc" DISTCCPATH="$PATH" ### Read configuration [ -r "$SYSCONFIG" ] && source "$SYSCONFIG" RETVAL=0 prog="distccd" desc="Distributed Compiler daemon" start() { echo -n $"Starting $desc ($prog): " PATH="$DISTCCPATH" daemon --user "$USER" $prog --daemon --log-file="/var/log/distccd.log" $OPTIONS RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog return $RETVAL } stop() { echo -n $"Shutting down $desc ($prog): " killproc $prog RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog return $RETVAL } restart() { stop start } case "$1" in start) start ;; stop) stop ;; restart|reload) restart ;; condrestart) [ -e /var/lock/subsys/$prog ] && restart RETVAL=$? ;; status) status $prog RETVAL=$? ;; *) echo $"Usage $0 {start|stop|restart|condrestart|status}" RETVAL=1 esac exit $RETVAL distcc-3.1/source/contrib/redhat/logrotate0000640000175000017500000000012311115326641017764 0ustar wolffwolff/var/log/distccd.log { missingok copytruncate notifempty } distcc-3.1/source/contrib/redhat/xinetd0000640000175000017500000000075611115326641017273 0ustar wolffwolff# default: off # description: Distccd - distributed compilation front-end (xinetd) \ # Please disable the daemon if you enable this. \ # WARNING: Don't enable on untrusted networks service distccd { disable = yes socket_type = stream protocol = tcp port = 3632 type = UNLISTED wait = no user = distcc server = /usr/bin/distccd server_args = --inetd --log-file="/var/log/distccd.log" only_from = 127.0.0.1 } distcc-3.1/source/contrib/redhat/sysconfig0000640000175000017500000000037311115326641017777 0ustar wolffwolff### See distcc(1) manual page for more information on these options. ### #OPTIONS="--nice 5 --jobs 5 --allow 10.0.0.0/24 --port 1234" #USER="distcc" ### Set this if don't want distccd to use gcc or g++ by accident. #DISTCCPATH="/usr/lib/distcc/bin" distcc-3.1/source/contrib/netpwd0000640000175000017500000000142611115326641016025 0ustar wolffwolff#! /bin/sh # Copyright 2002 Free Software Foundation # by Alexandre Oliva # This script is Free Software, and it can be copied, distributed and # modified as defined in the GNU General Public License. A copy of # its license can be downloaded from http://www.gnu.org/copyleft/gpl.html # Turn a local pathname into a network-neutral one. It assumes # /net/$HOSTNAME/pathname can access $HOSTNAME's /pathname from other # machines, and that /net/$HOSTNAME is actually mounted (by amd) # inside /.automount/$HOSTNAME/root, so it compensates for that. dir=`${REAL_PWD-pwd}` case $dir in /net/*) ;; /.automount/*/root/*) dir=/net/`echo "$dir" | sed -e '1s,^/\.automount/,,' -e 's,/root/,/,'` ;; *) dir=/net/${HOSTNAME-`uname -n`}$dir ;; esac echo $dir exit 0 distcc-3.1/source/contrib/distccd-init0000640000175000017500000000327111115326641017102 0ustar wolffwolff#! /bin/sh # # distccd Debian init.d script contributed by Jason Thomas. (Debian #161136) # # skeleton example file to build /etc/init.d/ scripts. # This file should be used to construct scripts for /etc/init.d. # # Written by Miquel van Smoorenburg . # Modified for Debian GNU/Linux # by Ian Murdock . # # Version: @(#)skeleton 1.9.1 08-Apr-2002 miquels@cistron.nl # PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/bin/distccd NAME=distccd DESC="Distributed Compiler Daemon" DAEMON_ARGS="--nice=10 --port=4200 --pid-file=/var/run/$NAME.pid \ --log-file=/var/log/$NAME.log --daemon" test -x $DAEMON || exit 0 set -e # we need permission to write to the pid file touch /var/run/$NAME.pid chown distccd /var/run/$NAME.pid case "$1" in start) echo -n "Starting $DESC: $NAME" start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ --chuid distccd \ --exec $DAEMON -- $DAEMON_ARGS echo "." ;; stop) echo -n "Stopping $DESC: $NAME " start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \ --oknodo \ --exec $DAEMON echo "." ;; restart|force-reload) # # If the "reload" option is implemented, move the "force-reload" # option to the "reload" entry above. If not, "force-reload" is # just the same as "restart". # echo -n "Restarting $DESC: $NAME" start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \ --oknodo \ --exec $DAEMON sleep 1 start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ --chuid distccd \ --exec $DAEMON -- $DAEMON_ARGS echo "." ;; *) N=/etc/init.d/$NAME echo "Usage: $N {start|stop|restart|force-reload}" >&2 exit 1 ;; esac exit 0 distcc-3.1/source/contrib/make-j0000640000175000017500000000101011115326641015655 0ustar wolffwolff#! /bin/sh # make-j script from Alexandre Oliva for use with distcc # Tests which machines are up, and runs Make with concurrency set # appropriately. hostlist=$DISTCC_HOSTS distcc_port=4200 DISTCC_HOSTS= count=0 for h in $hostlist; do echo trying $h... >&2 if test "x$h" = xlocalhost || nc -z $h $distcc_port; then echo added $h... >&2 DISTCC_HOSTS=`echo $DISTCC_HOSTS $h` # remove leading blank count=`expr $count + 1` fi done export DISTCC_HOSTS exec make -j $count ${1+"$@"} distcc-3.1/source/contrib/distcc.sh0000640000175000017500000000216111115326641016403 0ustar wolffwolff#! /bin/sh # This file, contributed by Dimitri PAPADOPOULOS-ORFANOS # may be installed as "cc" somewhere on your $PATH ahead of the real gcc. That # allows you to just use regular Makefiles without modifying them to change # hardcoded calls to cc. # This script will be a bit slow because of the overhead of running # things through a shell. In a future release, this function should # be supported directly by distcc, which should be a bit faster. DISTCC_HOME=/usr/local/distcc name=`basename $0` if [ "$name" = distcc ]; then echo "In normal use distcc is not called by its real name." 1>&2 echo "Instead create links to the actual compiler you wish to run, e.g." 1>&2 echo " ln -s distcc gcc" 1>&2 echo "and make sure the link is before the real compiler in your path." 1>&2 exit 1 fi unset found IFS=: for item in $PATH; do if [ -x "$item/$name" -a ! -d "$item/$name" ]; then if [ `cd $item; /bin/pwd` != `/bin/pwd` ]; then found=true break fi fi done if [ -n "$found" ]; then exec "distcc $item/$name $@" else echo "$name: not found" 1>&2 fi exit 1 distcc-3.1/source/contrib/distcc-absolutify0000640000175000017500000000240611115326641020153 0ustar wolffwolff#! /bin/sh # Copyright 2002 Free Software Foundation # by Alexandre Oliva # This script is Free Software, and it can be copied, distributed and # modified as defined in the GNU General Public License. A copy of # its license can be downloaded from http://www.gnu.org/copyleft/gpl.html # This is a wrapper for distcc that turns relative pathnames into # network-neutral ones. It modifies anything containing a slash and # not starting with dash or slash, as well as -B flags. We need not # be concerned about -I and -L, since distcc always does preprocessing # and linking locally. # If the first pathname is relative (.../xgcc, ./libtool, etc), case "$1" in [^/]*/*) nargs=$# basedir=`${NETPWD-netpwd}` # then process arguments for arg do case $arg in -B[^/]*) arg=-B$basedir/`echo "X$arg" | sed -e '1s/^X-B//'` ;; [^-/]*/*) arg=$basedir/$arg ;; esac set fnord ${1+"$@"} "$arg" done shift $nargs # take list of fnords out shift $nargs # take original args out ;; esac # Now run the real distcc thingie, or just run the program directly if # distcc is found to be missing. if test -x ${REAL_DISTCC-/usr/bin/distcc}; then x=${REAL_DISTCC-/usr/bin/distcc} else x=$1 shift fi exec $x ${1+"$@"} distcc-3.1/source/src/0000750000175000017500000000000011115327756013734 5ustar wolffwolffdistcc-3.1/source/src/srvrpc.c0000640000175000017500000001262311115326640015413 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Server-specific RPC code. **/ #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "rpc.h" #include "exitcode.h" #include "dopt.h" #include "hosts.h" #include "bulk.h" #include "snprintf.h" int dcc_r_request_header(int ifd, enum dcc_protover *ver_ret) { unsigned vers; int ret; if ((ret = dcc_r_token_int(ifd, "DIST", &vers)) != 0) { rs_log_error("client did not provide distcc magic fairy dust"); return ret; } if (vers > DCC_VER_3) { rs_log_error("can't handle requested protocol version is %d", vers); return EXIT_PROTOCOL_ERROR; } *ver_ret = (enum dcc_protover) vers; return 0; } /** * Receive the working directory from the client */ int dcc_r_cwd(int ifd, char **cwd) { return dcc_r_token_string(ifd, "CDIR", cwd); } /* @p path must be point to malloc'ed memory * Replaces **path with a pointer to a string containing * dirname + path. * path must be absolute. */ static int prepend_dir_to_name(const char *dirname, char **path) { char *buf; asprintf(&buf, "%s%s", dirname, *path); if (buf == NULL) { return EXIT_OUT_OF_MEMORY; } free(*path); *path = buf; return 0; } int dcc_r_many_files(int in_fd, const char *dirname, enum dcc_compress compr) { int ret = 0; unsigned int n_files; unsigned int i; char *name = 0; char *link_target = 0; char token[5]; if ((ret = dcc_r_token_int(in_fd, "NFIL", &n_files))) return ret; for (i = 0; i < n_files; ++i) { /* like dcc_r_argv */ unsigned int link_or_file_len; if ((ret = dcc_r_token_string(in_fd, "NAME", &name))) goto out_cleanup; /* FIXME: verify that name starts with '/' and doesn't contain '..'. */ if ((ret = prepend_dir_to_name(dirname, &name))) goto out_cleanup; if ((ret = dcc_r_sometoken_int(in_fd, token, &link_or_file_len))) goto out_cleanup; /* Must prepend the dirname for the file name, a link's target name. */ if (strncmp(token, "LINK", 4) == 0) { if ((ret = dcc_r_str_alloc(in_fd, link_or_file_len, &link_target))){ goto out_cleanup; } /* FIXME: verify that link_target doesn't contain '..'. * But the include server uses '..' to reference system * directories (see _MakeLinkFromMirrorToRealLocation * in include_server/compiler_defaults.py), so we'll need to * modify that first. */ if (link_target[0] == '/') { if ((ret = prepend_dir_to_name(dirname, &link_target))) { goto out_cleanup; } } if ((ret = dcc_mk_tmp_ancestor_dirs(name))) { goto out_cleanup; } if (symlink(link_target, name) != 0) { rs_log_error("failed to create path for %s: %s", name, strerror(errno)); ret = 1; goto out_cleanup; } if ((ret = dcc_add_cleanup(name))) { /* bailing out */ unlink(name); goto out_cleanup; } } else if (strncmp(token, "FILE", 4) == 0) { if ((ret = dcc_r_file(in_fd, name, link_or_file_len, compr))) { goto out_cleanup; } if ((ret = dcc_add_cleanup(name))) { /* bailing out */ unlink(name); goto out_cleanup; } } else { char buf[4 + sizeof(link_or_file_len)]; /* unexpected token */ rs_log_error("protocol derailment: expected token FILE or LINK"); /* We should explain what happened here, but we have already read * a few more bytes. */ 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; } distcc-3.1/source/src/dotd.h0000640000175000017500000000233211115326640015027 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ int dcc_cleanup_dotd(const char *dotd_fname, char **new_dotd_fname, const char *root_dir, const char *client_out_name, const char *server_out_name); int dcc_get_dotd_info(char **argv, char **dotd_fname, int *needs_dotd, int *sets_dotd_target, char **dotd_target); distcc-3.1/source/src/daemon.h0000640000175000017500000000304511115326641015343 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* daemon.c */ int dcc_refuse_root(void); int dcc_set_lifetime(void); int dcc_log_daemon_started(const char *role); /* dsignal.c */ void dcc_ignore_sighup(void); void dcc_daemon_catch_signals(void); /* dparent.c */ int dcc_standalone_server(void); void dcc_remove_pid(void); void dcc_reap_kids(int must_reap); /* prefork.c */ int dcc_preforking_parent(int listen_fd); /* serve.c */ struct sockaddr; int dcc_service_job(int in_fd, int out_fd, struct sockaddr *, int); /* setuid.c */ int dcc_discard_root(void); extern const char *opt_user; extern int dcc_max_kids; extern int dcc_nkids; extern volatile pid_t dcc_master_pid; distcc-3.1/source/src/where.h0000640000175000017500000000223311115326640015207 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* where.c */ int dcc_pick_host_from_list_and_lock_it(struct dcc_hostdef **, int *cpu_lock_fd); int dcc_lock_local(int *cpu_lock_fd); int dcc_lock_local_cpp(int *cpu_lock_fd); distcc-3.1/source/src/stringmap.h0000640000175000017500000000301711115326640016102 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef STRINGMAP_H #define STRINGMAP_H typedef struct { /* the strings, and what they map to */ struct { char *key; char *value; } *map; /* number of elements in map */ int n; /* if nonzero, ignore all but this many trailing words, * where words are separated by the '/' char * Example: * comparison num=1 num=2 num=3 * a/b/z =? 1/y/z match no no * a/b/z =? 1/b/z match match no */ int numFinalWordsToMatch; } stringmap_t; stringmap_t *stringmap_load(const char *filename, int numFinalWordsToMatch); const char *stringmap_lookup(const stringmap_t *map, const char *string); #endif distcc-3.1/source/src/dparent.c0000640000175000017500000002502411115326641015531 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Near is thy forgetfulness of all things; and near the * forgetfulness of thee by all. * -- Marcus Aurelius */ /** * @file * * Daemon parent. Accepts connections, forks, etc. * * @todo Quite soon we need load management. Basically when we think * we're "too busy" we should stop accepting connections. This could * be because of the load average, or because too many jobs are * running, or perhaps just because of a signal from the administrator * of this machine. In that case we want to do a blocking wait() to * find out when the current jobs are done, or perhaps a sleep() if * we're waiting for the load average to go back down. However, we * probably ought to always keep at least one job running so that we * can make progress through the queue. If you don't want any work * done, you should kill the daemon altogether. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "dopt.h" #include "exec.h" #include "srvnet.h" #include "types.h" #include "daemon.h" #include "netutil.h" #include "zeroconf.h" static void dcc_nofork_parent(int listen_fd) NORETURN; static void dcc_detach(void); static void dcc_save_pid(pid_t); int dcc_nkids = 0; /** * In forking or prefork mode, the maximum number of connections we want to * allow at any time. **/ int dcc_max_kids = 0; /** * Be a standalone server, with responsibility for sockets and forking * children. Puts the daemon in the background and detaches from the * controlling tty. **/ int dcc_standalone_server(void) { int listen_fd; int n_cpus; int ret; #ifdef HAVE_AVAHI void *avahi = NULL; #endif if ((ret = dcc_socket_listen(arg_port, &listen_fd, opt_listen_addr)) != 0) return ret; dcc_defer_accept(listen_fd); set_cloexec_flag(listen_fd, 1); if (dcc_ncpus(&n_cpus) == 0) rs_log_info("%d CPU%s online on this server", n_cpus, n_cpus == 1 ? "" : "s"); /* By default, allow one job per CPU, plus two for the pot. The extra * ones are started to allow for a bit of extra concurrency so that the * machine is not idle waiting for disk or network IO. */ if (arg_max_jobs) dcc_max_kids = arg_max_jobs; else dcc_max_kids = 2 + n_cpus; rs_log_info("allowing up to %d active jobs", dcc_max_kids); if (!opt_no_detach) { /* Don't go into the background until we're listening and * ready. This is useful for testing -- when the daemon * detaches, we know we can go ahead and try to connect. */ dcc_detach(); } else { /* Still create a new process group, even if not detached */ rs_trace("not detaching"); if ((ret = dcc_new_pgrp()) != 0) return ret; dcc_save_pid(getpid()); } /* Don't catch signals until we've detached or created a process group. */ dcc_daemon_catch_signals(); #ifdef HAVE_AVAHI /* Zeroconf registration */ if (opt_zeroconf) { if (!(avahi = dcc_zeroconf_register((uint16_t) arg_port, n_cpus))) return EXIT_CONNECT_FAILED; } #endif /* This is called in the master daemon, whether that is detached or * not. */ dcc_master_pid = getpid(); if (opt_no_fork) { dcc_log_daemon_started("non-forking daemon"); dcc_nofork_parent(listen_fd); ret = 0; } else { dcc_log_daemon_started("preforking daemon"); ret = dcc_preforking_parent(listen_fd); } #ifdef HAVE_AVAHI /* Remove zeroconf registration */ if (opt_zeroconf) { if (dcc_zeroconf_unregister(avahi) != 0) return EXIT_CONNECT_FAILED; } #endif return ret; } static void dcc_log_child_exited(pid_t kid, int status) { if (WIFSIGNALED(status)) { int sig = WTERMSIG(status); int severity = sig == SIGTERM ? RS_LOG_INFO : RS_LOG_ERR; rs_log(severity, "child %d: signal %d (%s)", (int) kid, sig, WCOREDUMP(status) ? "core dumped" : "no core"); } else if (WIFEXITED(status)) { rs_log_info("child %d exited: exit status %d", (int) kid, WEXITSTATUS(status)); } } /** * @sa dcc_wait_child(), which is used by a process that wants to do a blocking * wait for some task like cpp or gcc. * * @param must_reap If True, don't return until at least one child has been * collected. Used when e.g. all our process slots are full. In either case * we keep going until all outstanding zombies are collected. * * FIXME: Are blocking waits meant to collect all of them, or just one? At * the moment it waits until all children have exited. **/ void dcc_reap_kids(int must_reap) { while (1) { int status; pid_t kid; kid = waitpid(WAIT_ANY, &status, must_reap ? 0 : WNOHANG); if (kid == 0) { /* nobody has exited */ break; } else if (kid != -1) { /* child exited */ --dcc_nkids; rs_trace("down to %d children", dcc_nkids); dcc_log_child_exited(kid, status); } else if (errno == ECHILD) { /* No children left? That's ok, we'll go back to waiting * for new connections. */ break; } else if (errno == EINTR) { /* If we got a SIGTERM or something, then on the next pass * through the loop we'll find no children done, and we'll * return to the top loop at which point we'll exit. So * no special action is required here. */ continue; /* loop again */ } else { rs_log_error("wait failed: %s", strerror(errno)); /* e.g. too many open files; nothing we can do */ dcc_exit(EXIT_DISTCC_FAILED); } /* If there are more children keep looking, but don't block once we've * collected at least one. */ must_reap = FALSE; } } /** * Main loop for no-fork mode. * * Much slower and may leak. Should only be used when you want to run gdb on * distccd. **/ static void dcc_nofork_parent(int listen_fd) { while (1) { int acc_fd; struct dcc_sockaddr_storage cli_addr; socklen_t cli_len; rs_log_info("waiting to accept connection"); cli_len = sizeof cli_addr; acc_fd = accept(listen_fd, (struct sockaddr *) &cli_addr, &cli_len); if (acc_fd == -1 && errno == EINTR) { ; } else if (acc_fd == -1) { rs_log_error("accept failed: %s", strerror(errno)); 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(); } distcc-3.1/source/src/h_exten.c0000640000175000017500000000303511115326641015524 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_exten.c,v 1.7 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" const char *rs_program_name = __FILE__; /** * Test harness that makes sure the filename extension manipulation * stuff works OK. **/ int main(int argc, char *argv[]) { char *ex; if (argc != 2) { rs_log_error("usage: h_exten FILENAME"); return 1; } printf("%s", (ex = dcc_find_extension(argv[1])) ? ex : "(NULL)"); return 0; } distcc-3.1/source/src/rslave.c0000640000175000017500000001203511115326641015366 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* don't blame me, I was in a hurry */ #include #include #include #include #include #include #include #include #include #include #include "rslave.h" /*-------------------------------------------------------------------------- Class to provide asynchronous DNS lookup. To use, first call rslave_init() very early in your program to fork the dns slave processes. Then call rslave_write() any time you need a DNS name resolved and rslave_read() to retrieve the next result. Order of lookup requests is not preserved. Call rslave_getfd() and select on that fd for readability if you want to only call rslave_read() once it won't block. The slaves will shut down when their input file descriptor is closed, which normally happens when your program exits. --------------------------------------------------------------------------*/ int rslave_getfd_fromSlaves(struct rslave_s *rslave) { return rslave->pipeFromSlaves[0]; } int rslave_getfd_toSlaves(struct rslave_s *rslave) { return rslave->pipeToSlaves[1]; } void rslave_request_init(struct rslave_request_s *buf, const char *hostname, int id) { memset(buf, 0, sizeof(*buf)); strncpy(buf->hname, hostname, rslave_HOSTLEN); buf->id = id; } int rslave_writeRequest(struct rslave_s *rslave, const struct rslave_request_s *req) { if (write(rslave->pipeToSlaves[1], req, sizeof(*req)) != sizeof(*req)) return -1; return 0; } int rslave_gethostbyname(struct rslave_s *rslave, const char *hostname, int id) { struct rslave_request_s buf; rslave_request_init(&buf, hostname, id); return rslave_writeRequest(rslave, &buf); } int rslave_readRequest(struct rslave_s *rslave, struct rslave_request_s *req) { if (read(rslave->pipeToSlaves[0], req, sizeof(*req)) != sizeof(*req)) return -1; return 0; } int rslave_writeResult(struct rslave_s *rslave, struct rslave_result_s *result) { if (write(rslave->pipeFromSlaves[1], result, sizeof(*result)) != sizeof(*result)) return -1; return 0; } int rslave_readResult(struct rslave_s *rslave, struct rslave_result_s *result) { if (read(rslave->pipeFromSlaves[0], result, sizeof(*result)) != sizeof(*result)) return -1; return 0; } void be_a_dnsslave(struct rslave_s *rslave); void be_a_dnsslave(struct rslave_s *rslave) { struct rslave_request_s req; while (rslave_readRequest(rslave, &req) == 0) { struct rslave_result_s result; struct hostent *h; /* fprintf(stderr, "Calling gethostbyname on %s\n", req.hname); */ h = gethostbyname(req.hname); memset(&result, 0, sizeof(result)); result.id = req.id; result.err = h_errno; if (h && (h->h_length == sizeof(result.addr))) { memcpy(result.addr, h->h_addr_list[0], (unsigned) h->h_length); result.err = 0; } if (rslave_writeResult(rslave, &result)) break; } exit(0); } /*-------------------------------------------------------------------------- Initialize an rslave_s and fork slave processes. Returns 0 on success, -1 on error. --------------------------------------------------------------------------*/ int rslave_init(struct rslave_s *rslave) { int err; int i; int nslaves = rslave_NSLAVES; memset(rslave, 0, sizeof(*rslave)); err = pipe(rslave->pipeToSlaves); if (err == -1) return -1; err = pipe(rslave->pipeFromSlaves); if (err == -1) return -1; for (i=0; ipipeToSlaves[1]); close(rslave->pipeFromSlaves[0]); be_a_dnsslave(rslave); break; default: /* parent */ rslave->pids[i] = childpid; /* Save pid so we can kill it later */ break; } } close(rslave->pipeToSlaves[0]); close(rslave->pipeFromSlaves[1]); rslave->nslaves = nslaves; return 0; } /* TODO: add rslave_shutdown() that kills all the slaves by iterating through rslave->pids[] */ distcc-3.1/source/src/access.h0000640000175000017500000000237011115326640015340 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* 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; }; distcc-3.1/source/src/ssh.c0000640000175000017500000001460011115326640014666 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2001-2004 by Martin Pool * Copyright (C) 1996-2001 by Andrew Tridgell * Copyright (C) 1996 by Paul Mackerras * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * ssh.c -- Open a connection a server over ssh or something similar. * * The ssh connection always opens immediately from distcc's point of view, * because the local socket/pipe to the child is ready. If the remote * connection failed or is slow, distcc will only know when it tries to read * or write. (And in fact the first page or more written will go out * immediately too...) * * This file always uses nonblocking ssh, which has proven in rsync to be the * better solution for ssh. It may cause trouble with ancient proprietary rsh * implementations which can't handle their input being in nonblocking mode. * rsync has a configuration option for that, but I don't support it here, * because there's no point using rsh, you might as well use the native * protocol. */ #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "exec.h" #include "snprintf.h" #include "netutil.h" const char *dcc_default_ssh = "ssh"; /** * Create a file descriptor pair - like pipe() but use socketpair if * possible (because of blocking issues on pipes). * * Always set non-blocking. */ static int fd_pair(int fd[2]) { int ret; #if HAVE_SOCKETPAIR ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); #else ret = pipe(fd); #endif if (ret == 0) { dcc_set_nonblocking(fd[0]); dcc_set_nonblocking(fd[1]); } return ret; } /** * Create a child connected to use on stdin/stdout. * * This is derived from CVS code * * Note that in the child STDIN is set to blocking and STDOUT is set to * non-blocking. This is necessary as rsh relies on stdin being blocking and * ssh relies on stdout being non-blocking **/ static int dcc_run_piped_cmd(char **argv, int *f_in, int *f_out, pid_t * child_pid) { pid_t pid; int to_child_pipe[2]; int from_child_pipe[2]; dcc_trace_argv("execute", argv); if (fd_pair(to_child_pipe) < 0) { rs_log_error("fd_pair: %s", strerror(errno)); return EXIT_IO_ERROR; } if (fd_pair(from_child_pipe) < 0) { dcc_close(to_child_pipe[0]); dcc_close(to_child_pipe[1]); rs_log_error("fd_pair: %s", strerror(errno)); return EXIT_IO_ERROR; } *child_pid = pid = fork(); if (pid == -1) { rs_log_error("fork failed: %s", strerror(errno)); dcc_close(to_child_pipe[0]); dcc_close(to_child_pipe[1]); dcc_close(from_child_pipe[0]); dcc_close(from_child_pipe[1]); return EXIT_IO_ERROR; } if (pid == 0) { if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 || close(to_child_pipe[1]) < 0 || close(from_child_pipe[0]) < 0 || dup2(from_child_pipe[1], STDOUT_FILENO) < 0) { rs_log_error("dup/close: %s", strerror(errno)); return EXIT_IO_ERROR; } if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]); if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]); dcc_set_blocking(STDIN_FILENO); execvp(argv[0], (char **) argv); rs_log_error("failed to exec %s: %s", argv[0], strerror(errno)); return EXIT_IO_ERROR; } if (dcc_close(from_child_pipe[1]) || dcc_close(to_child_pipe[0])) { rs_log_error("failed to close pipes"); return EXIT_IO_ERROR; } *f_in = from_child_pipe[0]; *f_out = to_child_pipe[1]; return 0; } /** * Open a connection to a remote machine over ssh. * * Based on code in rsync, but rewritten. * * @note The tunnel command is always opened directly using execvp(), not * through a shell. So you cannot pass shell operators like redirections, and * at the moment you cannot specify additional options. Perhaps it would be * nice for us to parse it into an argv[] string by splitting on * wildcards/quotes, but at the moment this seems redundant. It can be done * adequately using .ssh/config I think. **/ 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; } distcc-3.1/source/src/h_argvtostr.c0000640000175000017500000000275511115326641016444 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_argvtostr.c,v 1.4 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" const char *rs_program_name = __FILE__; /** * @file * * Test argv-to-string converter. **/ int main(int argc, char *argv[]) { rs_trace_set_level(RS_LOG_WARNING); if (argc < 2) { rs_log_error("usage: h_scanargs COMMAND ARG...\n"); return 1; } printf("%s\n", dcc_argv_tostr(&argv[1])); return 0; } distcc-3.1/source/src/cleanup.c0000640000175000017500000001265711115326641015533 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "I have not come through fire and death to bandy crooked * words with a serving-man until the lightning falls!" * -- Gandalf (BBC LoTR radio play) */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "exitcode.h" #include "trace.h" #include "util.h" /** * A list of files that need to be cleaned up on exit. * * Volatile because it can be read from signal handlers. **/ char *volatile *volatile cleanups = 0; /* Dynamically allocated array. */ volatile int cleanups_size = 0; /* The length of the array. */ volatile int n_cleanups = 0; /* The number of entries used. */ static void dcc_cleanup_tempfiles_inner(int from_signal_handler); void dcc_cleanup_tempfiles(void) { dcc_cleanup_tempfiles_inner(0); } void dcc_cleanup_tempfiles_from_signal_handler(void) { dcc_cleanup_tempfiles_inner(1); } /* * You can call this at any time, or hook it into atexit(). It is * safe to call repeatedly. * * If from_signal_handler (a boolean) is non-zero, it means that * we're being called from a signal handler, so we need to be * careful not to call malloc() or free() or any other functions * that might not be async-signal-safe. * (We do call the tracing functions, which is perhaps unsafe * because they call sprintf() if DISCC_VERBOSE=1 is enabled. * But in that case it is probably worth the very small risk * of a crash to get the full tracing output.) * * If $DISTCC_SAVE_TEMPS is set to "1", then files are not actually * deleted, which can be good for debugging. However, we still need * to remove them from the list, otherwise it will eventually overflow * in prefork mode. */ static void dcc_cleanup_tempfiles_inner(int from_signal_handler) { int i; int done = 0; int save = dcc_getenv_bool("DISTCC_SAVE_TEMPS", 0); /* do the unlinks from the last to the first file. * This way, directories get deleted after their files. */ /* tempus fugit */ for (i = n_cleanups - 1; i >= 0; i--) { if (save) { rs_trace("skip cleanup of %s", cleanups[i]); } else { /* Try removing it as a directory first, and * if that fails, try removing is as a file. * Report the error from removing-as-a-file * if both fail. */ if ((rmdir(cleanups[i]) == -1) && (unlink(cleanups[i]) == -1) && (errno != ENOENT)) { rs_log_notice("cleanup %s failed: %s", cleanups[i], strerror(errno)); } done++; } n_cleanups = i; if (from_signal_handler) { /* It's not safe to call free() in this case. * Don't worry about the memory leak - we're about * to exit the process anyway. */ } else { free(cleanups[i]); } cleanups[i] = NULL; } rs_trace("deleted %d temporary files", done); } /** * Add to the list of files to delete on exit. * If it runs out of memory, it returns non-zero. */ int dcc_add_cleanup(const char *filename) { char *new_filename; int new_n_cleanups = n_cleanups + 1; /* Increase the size of the cleanups array, if needed. * We avoid using realloc() here, to ensure that 'cleanups' remains * valid at all times - we might get a signal in the middle here * that could call dcc_cleanup_tempfiles_from_signal_handler(). */ if (new_n_cleanups > cleanups_size) { char **old_cleanups; int new_cleanups_size = (cleanups_size == 0 ? 10 : cleanups_size * 3); char **new_cleanups = malloc(new_cleanups_size * sizeof(char *)); if (new_cleanups == NULL) { rs_log_crit("malloc failed - too many cleanups"); return EXIT_OUT_OF_MEMORY; } memcpy(new_cleanups, (char **)cleanups, cleanups_size * sizeof(char *)); old_cleanups = (char **)cleanups; cleanups = new_cleanups; /* Atomic assignment. */ cleanups_size = new_cleanups_size; /* Atomic assignment. */ free(old_cleanups); } new_filename = strdup(filename); if (new_filename == NULL) { rs_log_crit("strdup failed - too many cleanups"); return EXIT_OUT_OF_MEMORY; } cleanups[new_n_cleanups - 1] = new_filename; /* Atomic assignment. */ n_cleanups = new_n_cleanups; /* Atomic assignment. */ return 0; } distcc-3.1/source/src/loadfile.c0000640000175000017500000000620411115326641015652 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** * Load a whole file into a new string in a malloc'd memory buffer. * * Files larger than a certain reasonableness limit are not loaded, because * this is only used for reasonably short text files. * * Files that do not exist cause EXIT_NO_SUCH_FILE, but no error message. * (This suits our case of loading configuration files. It could be made * optional.) **/ int dcc_load_file_string(const char *filename, char **retbuf) { int fd; int ret; ssize_t read_bytes; struct stat sb; char *buf; /* Open the file */ if ((fd = open(filename, O_RDONLY)) == -1) { if (errno == 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; } distcc-3.1/source/src/ncpus.c0000640000175000017500000001044311115326641015223 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Thanks to Dimitri PAPADOPOULOS-ORFANOS for researching many of the methods * in this file. */ #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" /** * Determine number of processors online. * * We will in the future use this to gauge how many concurrent tasks * should run on this machine. Obviously this is only very rough: the * correct number needs to take into account disk buffers, IO * bandwidth, other tasks, etc. **/ #if defined(__hpux__) || defined(__hpux) #include #include int dcc_ncpus(int *ncpus) { struct pst_dynamic psd; if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) != -1) { *ncpus = psd.psd_proc_cnt; return 0; } else { rs_log_error("pstat_getdynamic failed: %s", strerror(errno)); *ncpus = 1; return EXIT_DISTCC_FAILED; } } #elif defined(__VOS__) #ifdef __GNUC__ #define $shortmap #endif #include extern void s$get_module_info (char_varying *module_name, void *mip, short int *code); int dcc_ncpus(int *ncpus) { short int code; module_info mi; char_varying(66) module_name; strcpy_vstr_nstr (&module_name, ""); mi.version = MODULE_INFO_VERSION_1; s$get_module_info ((char_varying *)&module_name, (void *)&mi, &code); if (code != 0) *ncpus = 1; /* safe guess... */ else *ncpus = mi.n_user_cpus; return 0; } #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(__bsdi__) /* http://www.FreeBSD.org/cgi/man.cgi?query=sysctl&sektion=3&manpath=FreeBSD+4.6-stable http://www.openbsd.org/cgi-bin/man.cgi?query=sysctl&sektion=3&manpath=OpenBSD+Current http://www.tac.eu.org/cgi-bin/man-cgi?sysctl+3+NetBSD-current */ #include #include #include int dcc_ncpus(int *ncpus) { int mib[2]; size_t len = sizeof(*ncpus); mib[0] = CTL_HW; mib[1] = HW_NCPU; if (sysctl(mib, 2, ncpus, &len, NULL, 0) == 0) return 0; else { rs_log_error("sysctl(CTL_HW:HW_NCPU) failed: %s", strerror(errno)); *ncpus = 1; return EXIT_DISTCC_FAILED; } } #else /* every other system */ /* http://www.opengroup.org/onlinepubs/007904975/functions/sysconf.html http://docs.sun.com/?p=/doc/816-0213/6m6ne38dd&a=view http://www.tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V40G_HTML/MAN/MAN3/0629____.HTM http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650&db=man&fname=/usr/share/catman/p_man/cat3c/sysconf.z */ int dcc_ncpus(int *ncpus) { #if defined(_SC_NPROCESSORS_ONLN) /* Linux, Solaris, Tru64, UnixWare 7, and Open UNIX 8 */ *ncpus = sysconf(_SC_NPROCESSORS_ONLN); #elif defined(_SC_NPROC_ONLN) /* IRIX */ *ncpus = sysconf(_SC_NPROC_ONLN); #else #warning "Please port this function" *ncpus = -1; /* unknown */ #endif if (*ncpus == -1) { rs_log_error("sysconf(_SC_NPROCESSORS_ONLN) failed: %s", strerror(errno)); *ncpus = 1; return EXIT_DISTCC_FAILED; } else if (*ncpus == 0) { /* if there are no cpus, what are we running on? But it has * apparently been observed to happen on ARM Linux */ *ncpus = 1; } return 0; } #endif distcc-3.1/source/src/timefile.c0000640000175000017500000000755411115326640015701 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * @brief Track timeouts by setting the mtime of a file. * * distcc needs to set timeouts to backoff from unreachable hosts. As a very * simple and robust way of keeping track of this, we simply touch a file in * our state directory, whenever we fail to connect. Future invocations can * look at how recently the host failed when deciding whether to use it again. **/ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "snprintf.h" #include "lock.h" #include "timefile.h" /** * Record the current time against the specified function and host. **/ int dcc_mark_timefile(const char *lockname, const struct dcc_hostdef *host) { char *filename; int fd; int ret; if ((ret = dcc_make_lock_filename(lockname, host, 0, &filename))) return ret; if ((ret = dcc_open_lockfile(filename, &fd))) { free(filename); return ret; } /* Merely opening it with O_WRONLY is not necessarily enough to set its * mtime to the current time. */ if (write(fd, "x", 1) != 1) { rs_log_error("write to %s failed: %s", lockname, strerror(errno)); dcc_close(fd); return EXIT_IO_ERROR; } dcc_close(fd); rs_trace("mark %s", filename); free(filename); return 0; } /** * Remove the specified timestamp. **/ int dcc_remove_timefile(const char *lockname, const struct dcc_hostdef *host) { char *filename; int ret = 0; if ((ret = dcc_make_lock_filename(lockname, host, 0, &filename))) return ret; if (unlink(filename) == 0) { rs_trace("remove %s", filename); } else { if (errno == ENOENT) { /* it's ok if somebody else already removed it */ } else { rs_log_error("unlink %s failed: %s", filename, strerror(errno)); ret = EXIT_IO_ERROR; } } free(filename); return 0; } /** * Return the mtime for a timestamp file. * * If the timestamp doesn't exist then we count it as time zero. **/ int dcc_check_timefile(const char *lockname, const struct dcc_hostdef *host, time_t *mtime) { char *filename; struct stat sb; int ret; if ((ret = dcc_make_lock_filename(lockname, host, 0, &filename))) return ret; if (stat(filename, &sb) == -1) { *mtime = (time_t) 0; if (errno == ENOENT) { /* just no record for this file; that's fine. */ free(filename); return 0; } else { rs_log_error("stat %s failed: %s", filename, strerror(errno)); free(filename); return EXIT_IO_ERROR; } } *mtime = sb.st_mtime; free(filename); return 0; } distcc-3.1/source/src/zeroconf.h0000640000175000017500000000247711115326640015734 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef foozeroconfhfoo #define foozeroconfhfoo #include int dcc_zeroconf_add_hosts(struct dcc_hostdef **re_list, int *ret_nhosts, int slots, struct dcc_hostdef **ret_prev); void *dcc_zeroconf_register(uint16_t port, int n_cpus); int dcc_zeroconf_unregister(void*); char* dcc_get_gcc_version(char *s, size_t nbytes); char* dcc_get_gcc_machine(char *s, size_t nbytes); char* dcc_make_dnssd_subtype(char *stype, size_t nbytes, const char *v, const char *m); #define DCC_DNS_SERVICE_TYPE "_distcc._tcp" #endif distcc-3.1/source/src/hosts.h0000640000175000017500000000517511115326640015245 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Declarations for distcc host selection stuff. **/ /** * A simple linked list of host definitions. All strings are mallocd. **/ struct dcc_hostdef { enum { DCC_MODE_TCP = 1, DCC_MODE_SSH, DCC_MODE_LOCAL } mode; char * user; char * hostname; int port; char * ssh_command; /** Mark the host as up == 1, by default, or down == 0, if !hostname */ int is_up; /** Number of tasks that can be dispatched concurrently to this machine. */ int n_slots; /** The full name of this host, taken verbatim from the host * definition. **/ char * hostdef_string; enum dcc_protover protover; /** The kind of compression to use for this host */ enum dcc_compress compr; /** Where are we doing preprocessing? */ enum dcc_cpp_where cpp_where; struct dcc_hostdef *next; }; /** Static definition of localhost **/ extern struct dcc_hostdef *dcc_hostdef_local; extern struct dcc_hostdef *dcc_hostdef_local_cpp; /* hosts.c */ int dcc_get_hostlist(struct dcc_hostdef **ret_list, int *ret_nhosts); int dcc_free_hostdef(struct dcc_hostdef *host); int dcc_get_features_from_protover(enum dcc_protover protover, enum dcc_compress *compr, enum dcc_cpp_where *cpp_where); int dcc_get_protover_from_features(enum dcc_compress compr, enum dcc_cpp_where cpp_where, enum dcc_protover *protover); /* hostfile.c */ int dcc_parse_hosts_file(const char *fname, struct dcc_hostdef **ret_list, int *ret_nhosts); distcc-3.1/source/src/exec.h0000640000175000017500000000352011115326640015021 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* exec.c */ extern const int timeout_null_fd; extern int dcc_job_lifetime; int dcc_redirect_fds(const char *stdin_file, const char *stdout_file, const char *stderr_file); int dcc_spawn_child(char **argv, pid_t *pidptr, const char *, const char *, const char *); /* if in_fd is timeout_null_fd, means this parameter is not used */ int dcc_collect_child(const char *what, pid_t pid, int *wait_status, int in_fd); int dcc_critique_status(int s, const char *, const char *, struct dcc_hostdef *host, int verbose); void dcc_note_execution(struct dcc_hostdef *host, char **argv); int dcc_new_pgrp(void); void dcc_reset_signal(int whichsig); #ifndef W_EXITCODE # define W_EXITCODE(exit, signal) ((exit)<<8 | (signal)) #endif distcc-3.1/source/src/h_parsemask.c0000640000175000017500000000352611115326641016374 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "access.h" const char * rs_program_name = "h_parsemask"; int main(int argc, char **argv) { int ret; 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); } distcc-3.1/source/src/renderer.h0000640000175000017500000000414411115326640015706 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Implementation of a GtkCellRenderer subclass that draws a little * chart of programs that have run in that slot. **/ #define DCC_TYPE_CELL_RENDERER_CHART (dcc_cell_renderer_chart_get_type ()) #define DCC_CELL_RENDERER_CHART(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DCC_TYPE_CELL_RENDERER_CHART, DccCellRendererChart)) #define DCC_CELL_RENDERER_CHART_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DCC_TYPE_CELL_RENDERER_CHART, DccCellRendererChartClass)) #define DCC_IS_CELL_RENDERER_CHART(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DCC_TYPE_CELL_RENDERER_CHART)) #define DCC_IS_CELL_RENDERER_CHART_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DCC_TYPE_CELL_RENDERER_CHART)) #define DCC_CELL_RENDERER_CHART_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DCC_TYPE_CELL_RENDERER_CHART, DccCellRendererChartClass)) typedef struct _DccCellRendererChart DccCellRendererChart; typedef struct _DccCellRendererChartClass DccCellRendererChartClass; GType dcc_cell_renderer_chart_get_type (void); GtkCellRenderer *dcc_cell_renderer_chart_new (void); extern GdkGC *dcc_phase_gc[DCC_PHASE_DONE]; extern const guint dcc_max_history_queue; distcc-3.1/source/src/va_copy.h0000640000175000017500000000310611115326640015535 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef VA_COPY_H #define VA_COPY_H #include #ifdef HAVE_VA_COPY /* C99: use va_copy(), and match it with calls to va_end(). */ #define VA_COPY(dest, src) va_copy(dest, src) #define VA_COPY_END(dest) va_end(dest) #elif defined(HAVE_UNDERSCORE_UNDERSCORE_VA_COPY) /* Earlier drafts of the C99 standard used __va_copy(). */ #define VA_COPY(dest, src) __va_copy(dest, src) #define VA_COPY_END(dest) va_end(dest) #else /* Pre-C99: the best we can do is to assume that va_list values can be freely copied. This works on most (but not all) pre-C99 C implementations. */ #define VA_COPY(dest, src) ((dest) = (src), (void) 0) #define VA_COPY_END(dest) ((void) 0) #endif #endif /* VA_COPY_H */ distcc-3.1/source/src/netutil.c0000640000175000017500000001273511115326640015564 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ARPA_NAMESER_H # include #endif #include #ifdef HAVE_RESOLV_H # include #endif #include #include "types.h" #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "srvnet.h" #include "access.h" #include "netutil.h" #include "snprintf.h" /* work out what fcntl flag to use for non-blocking */ #ifdef O_NONBLOCK # define NONBLOCK_FLAG O_NONBLOCK #elif defined(SYSV) # define NONBLOCK_FLAG O_NDELAY #else # define NONBLOCK_FLAG FNDELAY #endif #ifndef AF_UNIX # define AF_UNIX AF_LOCAL #endif #ifndef HAVE_HSTRERROR /* Missing on e.g. Solaris 2.6 */ const char *hstrerror(int err) { switch (err) { case HOST_NOT_FOUND: return "Host not found"; case TRY_AGAIN: return "Name server not contacted"; case NO_RECOVERY: return "Non-recoverable error"; case NO_ADDRESS: return "No IP address for host"; default: return "Unknown error"; } } #endif /** * Set a fd into blocking mode **/ void dcc_set_blocking(int fd) { int val; if ((val = fcntl(fd, F_GETFL, 0)) == -1) return; if (val & NONBLOCK_FLAG) { val &= ~NONBLOCK_FLAG; fcntl(fd, F_SETFL, val); } } /** * Set a fd into nonblocking mode **/ void dcc_set_nonblocking(int fd) { int val; if ((val = fcntl(fd, F_GETFL, 0)) == -1) return; if (!(val & NONBLOCK_FLAG)) { val |= NONBLOCK_FLAG; fcntl(fd, F_SETFL, val); } } /* Ask for the server not to be awakened until some data has arrived * on the socket. This works for our protocol because the client * sends a request immediately after connection without waiting for * anything from the server. */ void dcc_defer_accept(int POSSIBLY_UNUSED(listen_fd)) { #ifdef TCP_DEFER_ACCEPT int val = 1; if (!dcc_getenv_bool("DISTCC_TCP_DEFER_ACCEPT", 1)) { rs_trace("TCP_DEFER_ACCEPT disabled"); return; } if (setsockopt(listen_fd, SOL_TCP, TCP_DEFER_ACCEPT, &val, sizeof val) == -1) { rs_log_warning("failed to set TCP_DEFER_ACCEPT: %s", strerror(errno)); } else { rs_trace("TCP_DEFER_ACCEPT turned on"); } #endif } #ifdef ENABLE_RFC2553 /* TODO: Make the returned strings consistent with the other * implementation. */ int dcc_sockaddr_to_string(struct sockaddr *sa, size_t salen, char **p_buf) { int err; char host[1024]; char port[32]; if (!sa) { *p_buf = strdup("NOTSOCKET"); return 0; } else if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6) { err = getnameinfo(sa, salen, host, sizeof host, port, sizeof port, NI_NUMERICHOST | NI_NUMERICSERV); if (err) { rs_log_warning("getnameinfo failed: %s", gai_strerror(err)); *p_buf = strdup("(UNKNOWN)"); return 0; /* it's still a valid string */ } 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) { /* The double-cast here suppresses warnings from -Wcast-align. */ struct sockaddr_in *sain = (struct sockaddr_in *) (void *) 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 */ distcc-3.1/source/src/bulk.h0000640000175000017500000000355511115326640015042 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ int dcc_r_file(int ifd, const char *filename, unsigned, enum dcc_compress); int dcc_r_fifo(int ifd, const char *fifo_name, size_t len); int dcc_x_file(int ofd, const char *fname, const char *token, enum dcc_compress compression, off_t *); int dcc_r_file_timed(int ifd, const char *fname, unsigned size, enum dcc_compress); int dcc_r_token_file(int ifd, const char *token, const char *fname, enum dcc_compress compr); int dcc_open_read(const char *fname, int *ifd, off_t *fsize); int dcc_copy_file_to_fd(const char *in_fname, int out_fd); /* clirpc.c */ int dcc_x_many_files(int ofd, unsigned int n_files, char **fnames); /* srvrpc.c */ int dcc_r_many_files(int in_fd, const char *dirname, enum dcc_compress compr); distcc-3.1/source/src/filename.c0000640000175000017500000002032011115326641015646 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** * @file * * Everything we know about C filenames. * * We need to have some heuristics about input and output filenames to * understand command lines, because that's what cc does. * * @note As of 0.10, .s and .S files are never distributed, because * they might contain '.include' pseudo-operations, which are resolved * by the assembler. */ /** * Return a pointer to the extension, including the dot, or NULL. **/ char * dcc_find_extension(char *sfile) { char *dot; dot = strrchr(sfile, '.'); if (dot == NULL || dot[1] == '\0') { /* make sure there's space for one more character after the * dot */ return NULL; } return dot; } /** * Return a pointer to the extension, including the dot, or NULL. * Same as dcc_find_extension(), but the argument and return * value are both pointers to const. **/ const char * dcc_find_extension_const(const char *sfile) { #if 0 return dcc_find_extension((char *) sfile); #else /* The following intermediate variable works around a bug in gcc 4.2.3 where * for the code above gcc spuriously reports "warning: passing argument 1 * of 'dcc_find_extension' discards qualifiers from pointer target type", * despite the explicit cast. */ char *sfile_nonconst = (char *)sfile; return dcc_find_extension(sfile_nonconst); #endif } /** * Return a pointer to the basename of the file (everything after the * last slash.) If there is no slash, return the whole filename, * which is presumably in the current directory. **/ const char * dcc_find_basename(const char *sfile) { char *slash; if (!sfile) return sfile; slash = strrchr(sfile, '/'); if (slash == NULL || slash[1] == '\0') return sfile; return slash+1; } /** Truncate the filename to its dirname (everything before the last slash). * If the filename ends with a slash, just lop off the last slash. * Note: this is destructive. */ void dcc_truncate_to_dirname(char *file) { char *slash = 0; slash = strrchr(file, '/'); if (slash == NULL) { file[0] = '\0'; } else { *slash = '\0'; } } static int dcc_set_file_extension(const char *sfile, const char *new_ext, char **ofile) { char *dot, *o; o = strdup(sfile); if (!o) { rs_log_error("strdup failed (out of memory?)"); return EXIT_DISTCC_FAILED; } dot = dcc_find_extension(o); if (!dot) { rs_log_error("couldn't find extension in \"%s\"", o); return EXIT_DISTCC_FAILED; } if (strlen(dot) < strlen(new_ext)) { rs_log_error("not enough space for new extension"); return EXIT_DISTCC_FAILED; } strcpy(dot, new_ext); *ofile = o; return 0; } /* * Apple extensions: * file.mm, file.M * Objective-C++ source code which must be preprocessed. (APPLE ONLY) * * file.mii Objective-C++ source code which should not be * preprocessed. (APPLE ONLY) * * http://developer.apple.com/techpubs/macosx/DeveloperTools/gcc3/gcc/Overall-Options.html */ /** * If you preprocessed a file with extension @p e, what would you get? * * @param e original extension (e.g. ".c") * * @returns preprocessed extension, (e.g. ".i"), or NULL if * unrecognized. **/ const char * dcc_preproc_exten(const char *e) { if (e[0] != '.') return NULL; e++; if (!strcmp(e, "i") || !strcmp(e, "c")) { return ".i"; } else if (!strcmp(e, "c") || !strcmp(e, "cc") || !strcmp(e, "cpp") || !strcmp(e, "cxx") || !strcmp(e, "cp") || !strcmp(e, "c++") || !strcmp(e, "C") || !strcmp(e, "ii")) { return ".ii"; } else if(!strcmp(e,"mi") || !strcmp(e, "m")) { return ".mi"; } else if(!strcmp(e,"mii") || !strcmp(e,"mm") || !strcmp(e,"M")) { return ".mii"; } else if (!strcasecmp(e, "s")) { return ".s"; } else { return NULL; } } /** * Does the extension of this file indicate that it is already * preprocessed? **/ int dcc_is_preprocessed(const char *sfile) { const char *dot, *ext; dot = dcc_find_extension_const(sfile); if (!dot) return 0; ext = dot+1; switch (ext[0]) { #ifdef ENABLE_REMOTE_ASSEMBLE case 's': /* .S needs to be run through cpp; .s does not */ return !strcmp(ext, "s"); #endif case 'i': return !strcmp(ext, "i") || !strcmp(ext, "ii"); case 'm': return !strcmp(ext, "mi") || !strcmp(ext, "mii"); default: return 0; } } /** * Work out whether @p sfile is source based on extension **/ int dcc_is_source(const char *sfile) { const char *dot, *ext; dot = dcc_find_extension_const(sfile); if (!dot) return 0; ext = dot+1; /* you could expand this out further into a RE-like set of case * statements, but i'm not sure it's that important. */ switch (ext[0]) { case 'i': return !strcmp(ext, "i") || !strcmp(ext, "ii"); case 'c': return !strcmp(ext, "c") || !strcmp(ext, "cc") || !strcmp(ext, "cpp") || !strcmp(ext, "cxx") || !strcmp(ext, "cp") || !strcmp(ext, "c++"); case 'C': return !strcmp(ext, "C"); case 'm': return !strcmp(ext,"m") || !strcmp(ext,"mm") || !strcmp(ext,"mi") || !strcmp(ext,"mii"); case 'M': return !strcmp(ext, "M"); #ifdef ENABLE_REMOTE_ASSEMBLE case 's': return !strcmp(ext, "s"); case 'S': return !strcmp(ext, "S"); #endif default: return 0; } } /** * Decide whether @p filename is an object file, based on its * extension. **/ int dcc_is_object(const char *filename) { const char *dot; dot = dcc_find_extension_const(filename); if (!dot) return 0; return !strcmp(dot, ".o"); } /* Some files should always be built locally... */ int dcc_source_needs_local(const char *filename) { const char *p; p = dcc_find_basename(filename); if (str_startswith("conftest.", p) || str_startswith("tmp.conftest.", p)) { rs_trace("autoconf tests are run locally: %s", filename); return EXIT_DISTCC_FAILED; } return 0; } /** * Work out the default object file name the compiler would use if -o * was not specified. We don't need to worry about "a.out" because * we've already determined that -c or -S was specified. * * However, the compiler does put the output file in the current * directory even if the source file is elsewhere, so we need to strip * off all leading directories. * * @param sfile Source filename. Assumed to match one of the * recognized patterns, otherwise bad things might happen. **/ int dcc_output_from_source(const char *sfile, const char *out_extn, char **ofile) { char *slash; if ((slash = strrchr(sfile, '/'))) sfile = slash+1; if (strlen(sfile) < 3) { rs_log_error("source file %s is bogus", sfile); return EXIT_DISTCC_FAILED; } return dcc_set_file_extension(sfile, out_extn, ofile); } distcc-3.1/source/src/include_server_if.h0000640000175000017500000000206311115326640017565 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Manos Renieris */ int dcc_talk_to_include_server(char **argv, char ***files); int dcc_get_original_fname(const char *fname, char **original_fname); int dcc_approximate_includes(struct dcc_hostdef *host, char **argv); distcc-3.1/source/src/h_issource.c0000640000175000017500000000313511115326641016236 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_issource.c,v 1.7 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" const char *rs_program_name = __FILE__; /** * Test harness: determine whether a file is source, and is preprocessed. **/ int main(int argc, char *argv[]) { if (argc != 2) { rs_log_error("usage: %s FILENAME", argv[0]); return 1; } printf("%s %s\n", dcc_is_source(argv[1]) ? "source" : "not-source", dcc_is_preprocessed(argv[1]) ? "preprocessed" : "not-preprocessed"); return 0; } distcc-3.1/source/src/history.c0000640000175000017500000000363111115326640015574 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include "distcc.h" #include "mon.h" #include "trace.h" /* Number of previous states to retain for drawing history. */ const int dcc_max_history_queue = 200; void dcc_history_push(struct dcc_history *history, enum dcc_phase new_state) { history->now = (history->now + 1) % history->len; history->past_phases[history->now] = new_state; } struct dcc_history* dcc_history_new(void) { struct dcc_history *history; int i; history = malloc(sizeof *history); if (!history) { rs_log_crit("allocation failed!"); return NULL; } history->len = dcc_max_history_queue; history->now = 0; history->past_phases = malloc(history->len * (sizeof *history->past_phases)); if (!history->past_phases) { rs_log_crit("history allocation failed"); return NULL; } for (i = 0; i < history->len; i++) history->past_phases[i] = DCC_PHASE_DONE; return history; } distcc-3.1/source/src/compile.h0000640000175000017500000000362211115326641015531 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* remote.c */ int dcc_compile_remote(char **argv, char *input_fname, char *cpp_fname, char **file_names, char *output_fname, char *deps_fname, char *server_stderr_fname, pid_t cpp_pid, int local_cpu_lock_fd, struct dcc_hostdef *host, int *status); /* compile.c */ extern int dcc_scan_includes; int dcc_build_somewhere_timed(char *argv[], int sg_level, int *status); /* Declared here for testing purposes. */ int dcc_fresh_dependency_exists(const char *dotd_fname, const char *exlude_pat, time_t reference_time, char **fresh_dependency); int dcc_discrepancy_filename(char **filename); distcc-3.1/source/src/util.h0000640000175000017500000000376511115326640015065 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include /* util.c */ int dcc_getcurrentload(void); void dcc_getloadavg(double loadavg[3]); int argv_contains(char **argv, const char *s); int dcc_redirect_fd(int, const char *fname, int); int str_startswith(const char *head, const char *worm); char *dcc_gethostname(void); void dcc_exit(int exitcode) NORETURN; int dcc_getenv_bool(const char *name, int def_value); int set_cloexec_flag (int desc, int value); int dcc_ignore_sigpipe(int val); int dcc_remove_if_exists(const char *fname); int dcc_trim_path(const char *compiler_name); int dcc_set_path(const char *newpath); char *dcc_abspath(const char *path, int path_len); int dcc_get_dns_domain(const char **domain_name); #define str_equal(a, b) (!strcmp((a), (b))) void dcc_get_proc_stats(int *num_D, int *max_RSS, char **max_RSS_name); void dcc_get_disk_io_stats(int *n_reads, int *n_writes); int dcc_dup_part(const char **psrc, char **pdst, const char *sep); #ifndef HAVE_STRLCPY size_t strlcpy(char *d, const char *s, size_t bufsize); #endif int dcc_tokenize_string(const char *in, char ***argv_ptr); distcc-3.1/source/src/dopt.c0000640000175000017500000002250411115326640015041 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* dopt.c -- Parse and apply server options. */ #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "trace.h" #include "dopt.h" #include "exitcode.h" #include "daemon.h" #include "access.h" #include "exec.h" int opt_niceness = 5; /* default */ /** * Number of children running jobs on this machine. If zero (recommended), * then dynamically set from the number of CPUs. **/ int arg_max_jobs = 0; 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 }; #ifdef HAVE_AVAHI /* Flag for enabling/disabling Zeroconf using Avahi */ int opt_zeroconf = 0; #endif 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 }, #ifdef HAVE_AVAHI { "zeroconf", 0, POPT_ARG_NONE, &opt_zeroconf, 0, 0, 0 }, #endif { 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" #ifdef HAVE_AVAHI " --zeroconf register via mDNS/DNS-SD\n" #endif " Debug and trace:\n" " --log-level=LEVEL set detail level for log file\n" " levels: critical, error, warning, notice, info, debug\n" " --verbose set log level to \"debug\"\n" " --no-detach don't detach from parent (for daemontools, etc)\n" " --log-file=FILE send messages here instead of syslog\n" " --log-stderr send messages to stderr\n" " --wizard for running under gdb\n" " Mode of operation:\n" " --inetd serve client connected to stdin\n" " --daemon bind and listen on socket\n" "\n" "distccd runs either from inetd or as a standalone daemon to compile\n" "files submitted by the distcc client.\n" "\n" "distccd should only run on trusted networks.\n" ); } 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); opt_log_level_num = RS_LOG_DEBUG; break; default: /* bad? */ rs_log(RS_LOG_NONAME|RS_LOG_ERR|RS_LOG_NO_PID, "%s: %s", poptBadOption(po, POPT_BADOPTION_NOALIAS), poptStrerror(po_err)); exitcode = EXIT_BAD_ARGUMENTS; goto out_exit; } } poptFreeContext(po); return 0; out_exit: poptFreeContext(po); exit(exitcode); } distcc-3.1/source/src/mon-text.c0000640000175000017500000000547711115326640015660 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "rpc.h" #include "trace.h" #include "exitcode.h" #include "snprintf.h" #include "mon.h" /** * @file * * Plain text monitor program. Just prints out the state once, or * repeatedly, kind of like Linux vmstat. */ const char *rs_program_name = "distccmon-text"; static void usage(void) { fprintf(stderr, "usage: distccmon-text [DELAY]\n" "\n" "Displays current compilation jobs in text form.\n" "\n" "If delay is specified, repeatedly updates after that many (fractional)\n" "seconds. Otherwise, runs just once.\n"); } int main(int argc, char *argv[]) { struct dcc_task_state *list; int ret; float delay; char *end; dcc_set_trace_from_env(); if (argc == 1) delay = 0.0; else if (argc == 2) { delay = strtod(argv[1], &end); if (*end) { usage(); return 1; } } else { usage(); return 1; } /* We might be writing to e.g. a pipe that's being read by some * other program, so make sure we're always line buffered. */ setvbuf (stdout, NULL, _IOLBF, BUFSIZ); do { struct dcc_task_state *i; if ((ret = dcc_mon_poll(&list))) return ret; for (i = list; i; i = i->next) { #if 1 if (i->curr_phase == DCC_PHASE_DONE) continue; #endif /* Assume 80 cols = */ printf("%6ld %-10.10s %-30.30s %24.24s[%d]\n", (long) i->cpid, dcc_get_phase_name(i->curr_phase), i->file, i->host, i->slot); } printf("\n"); /* XXX: usleep() is probably not very portable */ usleep(delay * 1000000); dcc_task_state_free(list); } while (delay); return 0; } distcc-3.1/source/src/emaillog.c0000640000175000017500000001063311115326640015664 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "emaillog.h" #include "distcc.h" #include "util.h" #include "trace.h" #include "bulk.h" #include "snprintf.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); } distcc-3.1/source/src/distcc.c0000640000175000017500000002057211115326641015350 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* 4: The noise of a multitude in the * mountains, like as of a great people; a * tumultuous noise of the kingdoms of nations * gathered together: the LORD of hosts * mustereth the host of the battle. * -- Isaiah 13 */ #include #include #include #include #include #include #include #include #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" " --show-hosts show host list and exit\n" " -j calculate the concurrency level from\n" " the host list.\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); } static void dcc_free_hostlist(struct dcc_hostdef *list) { while (list) { struct dcc_hostdef *l = list; list = list->next; dcc_free_hostdef(l); } } static void dcc_show_hosts(void) { struct dcc_hostdef *list, *l; int nhosts; if (dcc_get_hostlist(&list, &nhosts) != 0) { rs_log_crit("Failed to get host list"); return; } for (l = list; l; l = l->next) printf("%s\n", l->hostdef_string); dcc_free_hostlist(list); } static void dcc_concurrency_level(void) { struct dcc_hostdef *list, *l; int nhosts; int nslots = 0; if (dcc_get_hostlist(&list, &nhosts) != 0) { rs_log_crit("Failed to get host list"); return; } for (l = list; l; l = l->next) nslots += l->n_slots; dcc_free_hostlist(list); printf("%i\n", nslots); } /** * distcc client entry point. * * This is typically called by make in place of the real compiler. * * Performs basic setup and checks for distcc arguments, and then kicks off * dcc_build_somewhere(). **/ int main(int argc, char **argv) { int status, sg_level, tweaked_path = 0; char **compiler_args = NULL; /* dynamically allocated */ char *compiler_name; /* points into argv[0] */ int ret; dcc_client_catch_signals(); atexit(dcc_cleanup_tempfiles); atexit(dcc_remove_state_file); dcc_set_trace_from_env(); dcc_setup_log_email(); dcc_trace_version(); 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; } if (!strcmp(argv[1], "--show-hosts")) { dcc_show_hosts(); ret = 0; goto out; } if (!strcmp(argv[1], "-j")) { dcc_concurrency_level(); ret = 0; goto out; } if (!strcmp(argv[1], "--scan-includes")) { dcc_scan_includes = 1; argv++; } if ((ret = dcc_find_compiler(argv, &compiler_args)) != 0) { goto out; } /* compiler_args is now respectively either "cc -c hello.c" or * "gcc -c hello.c" */ #if 0 /* I don't think we need to call this: if we reached this * line, our invocation name is something like 'distcc', and * that's never a problem for masquerading loops. */ if ((ret = dcc_trim_path(compiler_name)) != 0) goto out; #endif } else { /* Invoked as "cc -c hello.c", with masqueraded path */ if ((ret = dcc_support_masquerade(argv, compiler_name, &tweaked_path)) != 0) goto out; if ((ret = dcc_copy_argv(argv, &compiler_args, 0)) != 0) { goto out; } free(compiler_args[0]); compiler_args[0] = strdup(compiler_name); if (!compiler_args[0]) { rs_log_error("strdup failed - out of memory?"); ret = EXIT_OUT_OF_MEMORY; goto out; } } if (sg_level - tweaked_path > 0) { rs_log_crit("distcc seems to have invoked itself recursively!"); ret = EXIT_RECURSION; goto out; } ret = dcc_build_somewhere_timed(compiler_args, sg_level, &status); compiler_args = NULL; /* dcc_build_somewhere_timed already free'd it. */ out: if (compiler_args) { dcc_free_argv(compiler_args); } dcc_maybe_send_email(); dcc_exit(ret); } distcc-3.1/source/src/implicit.h0000640000175000017500000000207111115326641015710 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/implicit.h,v 1.3 2002/09/18 06:57:45 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ int dcc_find_compiler(char **argv, char ***); distcc-3.1/source/src/backoff.c0000640000175000017500000000515711115326641015474 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Keep track of hosts which are, or are not, usable. **/ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "snprintf.h" #include "lock.h" #include "timefile.h" #include "hosts.h" 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; } distcc-3.1/source/src/clinet.c0000640000175000017500000001363511115326641015357 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* I just wish I could get caller-IQ on my phones... -- The Purple People-Eater, NANAE */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "clinet.h" #include "util.h" #include "netutil.h" #ifndef h_errno extern int h_errno; #endif const int dcc_connect_timeout = 4; /* seconds */ /* * Client-side networking. * * These are called with an alarm set so we get a single timeout over the * whole resolution and connection process. * * TODO: In error messages, show the name of the relevant host. * Should do this even in readx(), etc. * * TODO: After connecting, perhaps try to read 0 bytes to see if there's an * error. */ /* * Connect to a host given its binary address, with a timeout. * * host and port are only here to aid printing debug messages. */ int dcc_connect_by_addr(struct sockaddr *sa, size_t salen, int *p_fd) { int fd; int ret; char *s; int failed; int connecterr; int tries = 3; dcc_sockaddr_to_string(sa, salen, &s); rs_trace("started connecting to %s", s); if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == -1) { rs_log_error("failed to create socket: %s", strerror(errno)); ret = EXIT_CONNECT_FAILED; goto out_failed; } dcc_set_nonblocking(fd); /* start the nonblocking connect... */ do failed = connect(fd, sa, salen); while (failed == -1 && (errno == EINTR || (errno == EAGAIN && tries-- && poll(NULL, 0, 500) == 0))); if (failed == -1 && errno != EINPROGRESS) { rs_log(RS_LOG_ERR|RS_LOG_NONAME, "failed to connect to %s: %s", s, strerror(errno)); ret = EXIT_CONNECT_FAILED; goto out_failed; } do { socklen_t len; if ((ret = dcc_select_for_write(fd, dcc_connect_timeout))) { rs_log(RS_LOG_ERR|RS_LOG_NONAME, "timeout while connecting to %s", s); goto out_failed; } connecterr = -1; len = sizeof(connecterr); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&connecterr, &len) < 0) { rs_log_error("getsockopt SO_ERROR failed?!"); ret = EXIT_CONNECT_FAILED; goto out_failed; } /* looping is unlikely, but I believe I needed this in dkftpbench */ /* fixme: should reduce timeout on each time around this loop */ } while (connecterr == EINPROGRESS); if (connecterr) { rs_log(RS_LOG_ERR|RS_LOG_NONAME, "nonblocking connect to %s failed: %s", s, strerror(connecterr)); ret = EXIT_CONNECT_FAILED; goto out_failed; } *p_fd = fd; free(s); return 0; out_failed: free(s); return ret; } #if defined(ENABLE_RFC2553) /** * Open a socket to a tcp remote host with the specified port. **/ int dcc_connect_by_name(const char *host, int port, int *p_fd) { struct addrinfo hints; struct addrinfo *res; int error; int ret; char portname[20]; rs_trace("connecting to %s port %d", host, port); /* Unfortunately for us, getaddrinfo wants the port (service) as a string */ snprintf(portname, sizeof portname, "%d", port); memset(&hints, 0, sizeof(hints)); /* set-up hints structure */ hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(host, portname, &hints, &res); if (error) { rs_log_error("failed to resolve host %s port %d: %s", host, port, gai_strerror(error)); return EXIT_CONNECT_FAILED; } /* Try each of the hosts possible addresses. */ do { ret = dcc_connect_by_addr(res->ai_addr, res->ai_addrlen, p_fd); } while (ret != 0 && (res = res->ai_next)); return ret; } #else /* not ENABLE_RFC2553 */ /** * Open a socket to a tcp remote host with the specified port. * * @todo Don't try for too long to connect. **/ int dcc_connect_by_name(const char *host, int port, int *p_fd) { struct sockaddr_in sock_out; struct hostent *hp; /* FIXME: "warning: gethostbyname() leaks memory. Use gethostbyname_r * instead!" (or indeed perhaps use getaddrinfo?) */ hp = gethostbyname(host); if (!hp) { rs_log_error("failed to look up host \"%s\": %s", host, hstrerror(h_errno)); return EXIT_CONNECT_FAILED; } memcpy(&sock_out.sin_addr, hp->h_addr, (size_t) hp->h_length); sock_out.sin_port = htons((in_port_t) port); sock_out.sin_family = PF_INET; return dcc_connect_by_addr((struct sockaddr *) &sock_out, sizeof sock_out, p_fd); } #endif /* not ENABLE_RFC2553 */ distcc-3.1/source/src/trace.h0000640000175000017500000001626311115326640015203 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * librsync -- generate and apply network deltas * * Copyright (C) 2000, 2001, 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** * @file * * Reusable trace library. * * @todo A function like perror that includes strerror output. Apache * does this by adding flags as well as the severity level which say * whether such information should be included. * * @todo Also check in configure for the C9X predefined identifier `_function', or * whatever it's called. **/ /* Provide simple macro statement wrappers (adapted from glib, and originally from Perl): * RS_STMT_START { statements; } RS_STMT_END; * can be used as a single statement, as in * if (x) RS_STMT_START { ... } RS_STMT_END; else ... * * For gcc we will wrap the statements within `({' and `})' braces. * For SunOS they will be wrapped within `if (1)' and `else (void) 0', * and otherwise within `do' and `while (0)'. */ #if !(defined (RS_STMT_START) && defined (RS_STMT_END)) # if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) # define RS_STMT_START (void)( # define RS_STMT_END ) # else # if (defined (sun) || defined (__sun__)) # define RS_STMT_START if (1) # define RS_STMT_END else (void)0 # else # define RS_STMT_START do # define RS_STMT_END while (0) # endif # endif #endif #include /* unconditionally on */ #define DO_RS_TRACE /** * Log severity levels. * * These have the same numeric values as the levels for syslog, at * least in glibc. * * Trace may be turned off. * * Error is always on, but you can return and continue in some way. */ typedef enum { RS_LOG_EMERG = 0, /**< System is unusable */ RS_LOG_ALERT = 1, /**< Action must be taken immediately */ RS_LOG_CRIT = 2, /**< Critical conditions */ RS_LOG_ERR = 3, /**< Error conditions */ RS_LOG_WARNING = 4, /**< Warning conditions */ RS_LOG_NOTICE = 5, /**< Normal but significant condition */ RS_LOG_INFO = 6, /**< Informational */ RS_LOG_DEBUG = 7 /**< Debug-level messages */ } rs_loglevel; int rs_loglevel_from_name(const char *name); enum { RS_LOG_PRIMASK = 7, /**< Mask to extract priority part. \internal */ RS_LOG_NONAME = 8, /**< \b Don't show function name in message. */ RS_LOG_NO_PROGRAM = 16, RS_LOG_NO_PID = 32 }; /** * \typedef rs_logger_fn * \brief Callback to write out log messages. * \param level a syslog level. * \param msg message to be logged. * * \param private Opaque data passed in when logger was added. For * example, pointer to file descriptor. */ typedef void rs_logger_fn(int flags, const char *fn, char const *msg, va_list, void *private_ptr, int private_int); void rs_format_msg(char *buf, size_t, int, const char *, const char *fmt, va_list); void rs_trace_set_level(rs_loglevel level); void rs_add_logger(rs_logger_fn *, int level, void *, int); void rs_remove_logger(rs_logger_fn *, int level, void *, int); void rs_remove_all_loggers(void); void rs_logger_file(int level, const char *fn, char const *fmt, va_list va, void *, int); void rs_logger_syslog(int level, const char *fn, char const *fmt, va_list va, void *, int); /** Check whether the library was compiled with debugging trace 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); distcc-3.1/source/src/lock.c0000640000175000017500000002242011115326641015021 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Power is nothing without control * -- Pirelli tyre 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 #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "hosts.h" #include "lock.h" #include "exitcode.h" #include "snprintf.h" /* Note that we use the _same_ lock file for * dcc_hostdef_local and dcc_hostdef_local_cpp, * so that they both use the same underlying lock. * This ensures that we respect the limits for * both "localslots" and "localslots_cpp". * * Extreme care with lock ordering is required in order to avoid * deadlocks. In particular, the following invariants apply: * * - Each distcc process should hold no more than two locks at a time; * one local lock, and one remote lock. * * - When acquring more than one lock, a strict lock ordering discipline * must be observed: the remote lock must be acquired first, before the * local lock; and conversely the local lock must be released first, * before the remote lock. */ struct dcc_hostdef _dcc_local = { DCC_MODE_LOCAL, NULL, (char *) "localhost", 0, NULL, 1, /* host is_up */ 4, /* number of tasks */ (char *)"localhost", /* verbatim string */ DCC_VER_1, /* protocol (ignored) */ DCC_COMPRESS_NONE, /* compression (ignored) */ DCC_CPP_ON_CLIENT, /* where to cpp (ignored) */ 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) { #if defined(F_SETLK) struct flock lockparam; lockparam.l_type = F_UNLCK; lockparam.l_whence = SEEK_SET; lockparam.l_start = 0; lockparam.l_len = 0; if (fcntl(lock_fd, F_SETLK, &lockparam) == -1) { rs_log_error("fcntl(fd%d, F_SETLK, F_UNLCK) failed: %s", lock_fd, strerror(errno)); close(lock_fd); return EXIT_IO_ERROR; } #elif defined (HAVE_FLOCK) /* flock() style locks are released when the fd is closed */ #elif defined (HAVE_LOCKF) if (lockf(lock_fd, F_ULOCK, 0) == -1) { rs_log_error("lockf(fd%d, F_ULOCK, 0) failed: %s", lock_fd, strerror(errno)); close(lock_fd); return EXIT_IO_ERROR; } #endif rs_trace("release lock fd%d", lock_fd); /* All our current locks can just be closed */ if (close(lock_fd)) { rs_log_error("close failed: %s", strerror(errno)); return EXIT_IO_ERROR; } return 0; } /** * Open a lockfile, creating if it does not exist. **/ int dcc_open_lockfile(const char *fname, int *plockfd) { /* Create if it doesn't exist. We don't actually do anything with * the file except lock it. * * The file is created with the loosest permissions allowed by the user's * umask, to give the best chance of avoiding problems if they should * happen to use a shared lock dir. */ /* FIXME: If we fail to open with EPERM or something similar, try deleting * the file and try again. That might fix problems with root-owned files * in user home directories. */ *plockfd = open(fname, O_WRONLY|O_CREAT, 0666); if (*plockfd == -1 && errno != EEXIST) { rs_log_error("failed to 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; } } distcc-3.1/source/src/lock.h0000640000175000017500000000250111115326641015024 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ int dcc_lock_host(const char *lockname, const struct dcc_hostdef *host, int slot, int block, int *lock_fd); int dcc_unlock(int lock_fd); int dcc_make_lock_filename(const char *lockname, const struct dcc_hostdef *host, int iter, char **); int dcc_open_lockfile(const char *fname, int *plockfd); distcc-3.1/source/src/fix_debug_info.h0000640000175000017500000000212411115326640017043 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Fergus Henderson */ #ifndef DISTCC_FIX_DEBUG_INFO_H__ #define DISTCC_FIX_DEBUG_INFO_H__ int dcc_fix_debug_info(const char *path, const char *client_cwd, const char *server_cwd); #endif /* DISTCC_FIX_DEBUG_INFO_H__ */ distcc-3.1/source/src/safeguard.c0000640000175000017500000000456111115326641016040 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** * @file * @brief Protect against unbounded recursion. * * It would be fairly easy for somebody to get confused in masquerade mode and * try to get distcc to invoke itself in a loop. We can't always work out the * right thing to do but we can at least flag an error. * * This environment variable is set to guard against distcc accidentally * recursively invoking itself, thinking it's the real compiler. **/ static const char dcc_safeguard_name[] = "_DISTCC_SAFEGUARD"; static char dcc_safeguard_set[] = "_DISTCC_SAFEGUARD=1"; static int dcc_safeguard_level; int dcc_recursion_safeguard(void) { char *env = getenv(dcc_safeguard_name); if (env) { rs_trace("safeguard: %s", env); if (!(dcc_safeguard_level = atoi(env))) dcc_safeguard_level = 1; } else dcc_safeguard_level = 0; rs_trace("safeguard level=%d", dcc_safeguard_level); return dcc_safeguard_level; } int dcc_increment_safeguard(void) { if (dcc_safeguard_level > 0) dcc_safeguard_set[sizeof dcc_safeguard_set-2] = dcc_safeguard_level+'1'; rs_trace("setting safeguard: %s", dcc_safeguard_set); if ((putenv(strdup(dcc_safeguard_set)) == -1)) { rs_log_error("putenv failed"); /* and continue */ } return 0; } distcc-3.1/source/src/state.h0000640000175000017500000000505211115326641015220 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef _DISTCC_STATE_H #define _DISTCC_STATE_H #ifdef __cplusplus extern "C" { #endif int dcc_get_state_dir (char **p); int dcc_open_state_file (int *p_fd); /* Note that these must be in the order in which they are encountered * for the state file to work properly. It's OK if some are skipped * though. */ enum dcc_phase { DCC_PHASE_STARTUP, DCC_PHASE_BLOCKED, DCC_PHASE_CONNECT, DCC_PHASE_CPP, DCC_PHASE_SEND, DCC_PHASE_COMPILE, /**< or unknown */ DCC_PHASE_RECEIVE, DCC_PHASE_DONE /**< MUST be last */ }; int dcc_note_state (enum dcc_phase state, const char *file, const char *host); void dcc_remove_state_file (void); extern const char *dcc_state_prefix; #define DCC_STATE_MAGIC 0x44494800 /* DIH\0 */ /** * State and history of a distcc process. Used in memory and also in native * format for binary state files. * * This should be <4kB, so that it will normally be written out * atomically. **/ struct dcc_task_state { size_t struct_size; unsigned long magic; unsigned long cpid; /**< Client pid */ char file[128]; /**< Input filename */ char host[128]; /**< Destination host description */ int slot; /**< Which CPU slot for this host */ enum dcc_phase curr_phase; /** In memory, point to the next in a list of all tasks. In the * file, undefined. */ struct dcc_task_state *next; }; const char *dcc_get_phase_name(enum dcc_phase); void dcc_note_state_slot(int slot); #ifdef __cplusplus } #endif #endif /* _DISTCC_STATE_H */ distcc-3.1/source/src/dsignal.c0000640000175000017500000000701011115326641015510 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * A servant will not be corrected by words: for * though he understand he will not answer. * -- Proverbs 29:19 */ /** * @file * @brief Daemon signal handling. * * Signals are handled differently in the daemon parent and its children. * * When the parent is killed, the entire process group is shut down, and the * pid file (if any) is removed. * * For both cases any temporary files created by the process are removed. **/ #include #include #include #include #include #include #include #include #include #include #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "dopt.h" #include "exec.h" #include "daemon.h" /* 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); } distcc-3.1/source/src/emaillog.h0000640000175000017500000000224711115326641015674 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef DCC_EMAILLOG_H #define DCC_EMAILLOG_H /* See also include_server/basics.py */ #define DCC_EMAILLOG_WHOM_TO_BLAME "distcc-pump-errors" void dcc_please_send_email(void); void dcc_setup_log_email(void); void dcc_maybe_send_email(void); int dcc_add_file_to_log_email(const char *description, const char *fname); #endif /* EMAILLOG_H */ distcc-3.1/source/src/srvnet.c0000640000175000017500000002032011115326640015406 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "Happy is the man who finds wisdom, and the man who * gets understanding; for the gain from it is better * than gain from silver and its profit better than * gold." -- Proverbs 3:13 */ /** * @file * * Server-side networking. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ARPA_NAMESER_H # include #endif #include #ifdef HAVE_RESOLV_H # include #endif #include "types.h" #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "srvnet.h" #include "access.h" #include "netutil.h" #include "dopt.h" /* * Listen on a predetermined address (often the passive address). The way in * which we get the address depends on the resolver API in use. **/ static int dcc_listen_by_addr(int fd, struct sockaddr *sa, size_t salen) { int one = 1; char *sa_buf = NULL; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)); dcc_sockaddr_to_string(sa, salen, &sa_buf); /* 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; /* The double-cast here avoids warnings from -Wcast-align. */ cli_inaddr = ((struct sockaddr_in *) (void *) 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; } distcc-3.1/source/src/traceenv.c0000640000175000017500000000573011115326640015704 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" /** * Setup client error/trace output. * * Trace goes to the file specified by DISTCC_LOG, if any. Otherwise, it goes * to stderr, except that UNCACHED_ERR_FD can redirect it elsewhere, for use * under ccache. * * The exact setting of log level is a little strange, but for a good * reason: if you ask for verbose, you get everything. Otherwise, if * you set a file, you get INFO and above. Otherwise, you only get * WARNING messages. In practice this seems to be a nice balance. **/ void dcc_set_trace_from_env(void) { const char *logfile, *logfd_name; int fd; int failed_to_open_logfile = 0; int save_errno = 0; int level = RS_LOG_WARNING; /* by default, warnings only */ /* let the decision on what to log rest on the loggers */ /* the email-an-error functionality in emaillog.c depends on this */ rs_trace_set_level(RS_LOG_DEBUG); if ((logfile = getenv("DISTCC_LOG")) && logfile[0]) { fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0666); if (fd != -1) { /* asked for a file, and we can open that file: include info messages */ level = RS_LOG_INFO; } else { /* asked for a file, can't use it; use stderr instead */ fd = STDERR_FILENO; save_errno = errno; failed_to_open_logfile = 1; } } else { /* not asked for file */ if ((logfd_name = getenv("UNCACHED_ERR_FD")) == NULL || (fd = atoi(logfd_name)) == 0) { fd = STDERR_FILENO; } } if (dcc_getenv_bool("DISTCC_VERBOSE", 0)) { level = RS_LOG_DEBUG; } rs_add_logger(rs_logger_file, level, NULL, fd); if (failed_to_open_logfile) { rs_log_error("failed to open logfile %s: %s", logfile, strerror(save_errno)); } } distcc-3.1/source/src/implicit.c0000640000175000017500000000646511115326641015716 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2008 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "I do not trouble myself to be understood. I see * that the elementary laws never apologize." * -- Whitman, "Song of Myself". */ #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "implicit.h" /** * @file * * Handle invocations where the compiler name is implied rather than * specified. That is, "distcc -c foo.c". * * This method of invocation is less transparent than the masquerade system, * and less explicit than giving the real compiler name. But it is pretty * simple, and is retained for that reason. * * This is used on the client only. The compiler name is always passed (as * argv[0]) to the server. * * The current implementation determines that no compiler name has been * specified by checking whether the first argument is either an option, or a * source or object file name. If not, it is assumed to be the name of the * compiler to use. * * At the moment the default compiler name is always "cc", but this could * change to come from an environment variable. That's not supported at the * moment, and may never be. If you need that level of control, using a * different invocation method is recommended. **/ /** * Find the compiler for non-masquerade use. * * If we're invoked with no compiler name, insert one. * * We can tell there's no compiler name because argv[1] will be either * a source filename or an object filename or an option. I don't * think anything else is possible. * * Returns a dynamically allocated argv array in *out_argv. * The caller is responsible for deallocating it. **/ int dcc_find_compiler(char **argv, char ***out_argv) { int ret; if (argv[1][0] == '-' || dcc_is_source(argv[1]) || dcc_is_object(argv[1])) { if ((ret = dcc_copy_argv(argv, out_argv, 0)) != 0) { return ret; } /* change "distcc -c foo.c" -> "cc -c foo.c" */ free((*out_argv)[0]); (*out_argv)[0] = strdup("cc"); if ((*out_argv)[0] == NULL) { return EXIT_OUT_OF_MEMORY; } return 0; } else { /* skip "distcc", point to "gcc -c foo.c" */ return dcc_copy_argv(argv + 1, out_argv, 0); } } distcc-3.1/source/src/timefile.h0000640000175000017500000000240611115326641015676 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* timefile.c */ int dcc_mark_timefile(const char *lockname, const struct dcc_hostdef *host); int dcc_remove_timefile(const char *lockname, const struct dcc_hostdef *host); int dcc_check_timefile(const char *lockname, const struct dcc_hostdef *host, time_t *mtime); distcc-3.1/source/src/include_server_if.c0000640000175000017500000002057511115326640017570 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Authors: Manos Renieris, Fergus Henderson */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "rpc.h" #include "clinet.h" #include "exitcode.h" #include "util.h" #include "hosts.h" #include "include_server_if.h" static int dcc_count_slashes(const char *path); static int dcc_count_leading_dotdots(const char *path); static int dcc_categorize_file(const char *include_server_filename); /* The include server puts all files in its own special directory, * which is n path components long, where n = INCLUDE_SERVER_DIR_DEPTH */ #define INCLUDE_SERVER_DIR_DEPTH 3 /** Talks to the include server, over the AF_UNIX socket specified * in env variable INCLUDE_SERVER_PORT. If all goes well, * it returns the array of files in @p files and returns 0; * if anything goes wrong, it returns a non-zero value. */ int dcc_talk_to_include_server(char **argv, char ***files) { char *include_server_port; int fd; struct sockaddr_un sa; int ret; char *stub; /* for testing purposes, if INCLUDE_SERVER_STUB is set, use its value rather than the include server */ stub = getenv("INCLUDE_SERVER_STUB"); if (stub != NULL) { ret = dcc_tokenize_string(stub, files); rs_log_warning("INCLUDE_SERVER_STUB is set to '%s'; " "ignoring include server", dcc_argv_tostr(*files)); return ret; } include_server_port = getenv("INCLUDE_SERVER_PORT"); if (include_server_port == NULL) { rs_log_warning("INCLUDE_SERVER_PORT not set - " "did you forget to run under 'pump'?"); return 1; } if (strlen(include_server_port) >= ((int)sizeof(sa.sun_path) - 1)) { rs_log_warning("$INCLUDE_SERVER_PORT is longer than %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; } /** * This implements the --scan_includes option. * Talks to the include server, and prints the results to stdout. */ int dcc_approximate_includes(struct dcc_hostdef *host, char **argv) { char **files; int i; int ret; if (host->cpp_where != DCC_CPP_ON_SERVER) { rs_log_error("'--scan_includes' specified, " "but distcc wouldn't have used include server " "(make sure hosts list includes ',cpp' option?)"); return EXIT_DISTCC_FAILED; //return 0; } if ((ret = dcc_talk_to_include_server(argv, &files))) { rs_log_error("failed to get includes from include server"); return ret; } for (i = 0; files[i]; i++) { if ((ret = dcc_categorize_file(files[i]))) return ret; } return 0; } /* * A subroutine of dcc_approximate_includes(). * Take a filename output from the include server, * convert the filename back so that it refers to the original source tree * (as opposed to the include server's mirror tree), * categorize it as SYSTEMDIR, DIRECTORY, SYMLINK, or FILE, * and print the category and original name to stdout. * For SYMLINKs, also print out what the symlink points to. */ static int dcc_categorize_file(const char *include_server_filename) { char *filename; int is_symlink = 0; int is_forced_directory = 0; int is_system_include_directory = 0; char link_target[MAXPATHLEN + 1]; int ret; if ((ret = dcc_is_link(include_server_filename, &is_symlink))) return ret; if (is_symlink) if ((ret = dcc_read_link(include_server_filename, link_target))) return ret; if ((ret = dcc_get_original_fname(include_server_filename, &filename))) { rs_log_error("dcc_get_original_fname failed"); return ret; } if (str_endswith("/forcing_technique_271828", filename)) { /* Replace "/forcing_technique_271818" with "". */ filename[strlen(filename) - strlen("/forcing_technique_271828")] = '\0'; is_forced_directory = 1; } if (is_symlink) { int leading_dotdots = dcc_count_leading_dotdots(link_target); is_system_include_directory = leading_dotdots > 0 && leading_dotdots > dcc_count_slashes(filename) && strcmp(link_target + 3 * leading_dotdots - 1, filename) == 0; } printf("%-9s %s\n", is_system_include_directory ? "SYSTEMDIR" : is_forced_directory ? "DIRECTORY" : is_symlink ? "SYMLINK" : "FILE", filename); return 0; } /* Count the number of slashes in a path. */ static int dcc_count_slashes(const char *path) { int i; int count = 0; for (i = 0; path[i]; i++) { if (path[i] == '/') count++; } return count; } /* Count the number of leading "../" references in a path. */ static int dcc_count_leading_dotdots(const char *path) { int count = 0; while (str_startswith("../", path)) { path += 3; count++; } return count; } distcc-3.1/source/src/mon.h0000640000175000017500000002302211115326640014665 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * Copyright (C) 2003 by Frerich Raabe * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef _DISTCC_MON_H #define _DISTCC_MON_H #ifdef __cplusplus extern "C" { #endif /* Writing Monitors for distcc --------------------------- It is possible for third party developers to write monitoring software for distcc clusters, and you are encouranged to do so. This appendix attempts to provide you with all the information you'll need to write a distcc monitor, but just like all other software, distcc is not perfect; in case you are stuck, can't seem to get your monitor working, or just think a particular quirk in the way a monitor was to be written is worth being pointed out, don't hesitate to subscribe to the list (http://lists.samba.org/) and present your problem. Limitations on monitoring ------------------------- As of distcc 2.11, monitoring information is only available for currently running jobs originating from your machine and account. There is no direct interface available for finding out about jobs scheduled onto your machine by other users. The state information is stored as files in the $DISTCC_DIR (typically ~/.distcc/state), which are updated by client processes as they run. The goal of the design is to be adequately secure and not to reduce the performance of compilation, which is after all the whole point. If you have permission to read the state files of some other users, you can run a monitor on them by setting DISTCC_DIR before running the monitor. distcc does not maintain a history of tasks that have completed. Your monitor program must do that if you want to present that information. mon-gnome.c has a simple implementation of this. Possible Approaches ------------------- Right now, there are two general approaches which developers can follow to develop distcc monitors: 1 - Writing a program which parses the output of the distccmon-text monitor. This is the most flexible solution, since it poses very little requirements for the monitor - you are free to use whatever programming language you prefer, and the only requirement your software has is that the distccmon-text monitor exists on the user systems, and that its output is compatible with the output of the distccmon-text monitor you developed your software with. Alas, the latter also embodies a problem, since parsing a programs text output is fragile, and it's not guaranteed that the output format of the distccmon-text monitor won't change in the future. 2 - Writing a program which links against distcc. This is the cleaner solution from a software engineer's point of view, since you retrieve the status information from distcc via, more or less typesafe, data structures, and don't have to bother parsing text output. The distcc functions and data types which your monitor will probably want to use are declared in the header files exitcode.h, mon.h and state.h. Unfortunately, this requires that you use a programming language which is able to link against the relevant distcc source files (i.e. C or C++), and that the system which builds your monitor has the distcc sources installed. Also, it's currently not guaranteed that the interface established by these three header files maintains source or binary compatibility between distcc releases. Since only the second approach requires detailed knowledge about the interface to distcc's monitoring facilities, only the second approach will be documented in this chapter. For the first approach, consult your programming manuals for how to parse the stdout output of external processes. The C Interface Provided by distcc ---------------------------------- In case you decide to let your monitor link directly against distcc, you will get exposed to the interface which distcc offers to provide your monitor with status information about the cluster. The general concept behind this interface is that you should poll distcc regularly for status information, and it will return a list of jobs which are currently being processed on the network. In practice, this interface is made up of the following function: int dcc_mon_poll(struct dcc_task_state **ppl) This function, declared in the mon.h header file, allows you to poll a list of jobs which are currently being processed on the distcc cluster. It returns 0 in case the poll was successful, otherwise one of the errors declared in the exitcode.h header file. The "ppl" list is a single-linked list of dcc_task_state structs, which represent the "jobs" being worked on. The dcc_task_state struct is declared in the state.h header file. int dcc_task_state_free(struct dcc_history *) Call this method and pass it the list of dcc_task_state structs you acquired by calling dcc_mon_poll in order to free the resources allocated by the list. So generally, the algorithm you will employ is: - Acquire a list of jobs by calling dcc_mon_poll. - Process the list of jobs, displaying results to the user. - Free the resources allocated by the list of jobs by calling dcc_task_state_free. For being able to do the second of the three steps listed above, you will need to know what information the dcc_task_state struct (which represents a job) provides. For a full list of properties, refer to the state.h header file, for convenience here is a list of noteworthy properties: unsigned long cpid The process ID of the compiler process for this job (on the remote host). char file[128] The name of the input file of this job. char host[128] The name of the remote host this job is being processed on. int slot The CPU slot which is occupied by this job on the remote hosts. enum dcc_phase curr_phase This variable holds the current state of the job (i.e. preprocess, compile, send, receive etc.). Refer to the state.h header file for the complete list of values declared in the dcc_phase enumeration. Note that there's a convenience function const char *dcc_get_state_name(enum dcc_phase state) declared in the state.h header file which lets you retrieve a descriptive string representation of the given enum, suitable for display to the user. struct dcc_task_state *next A pointer to the next dcc_task_state struct in the list, or NULL if this job is the last in the list. */ /** * Read the list of running processes for this user. * * @param ppl On return, 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 */ distcc-3.1/source/src/state.c0000640000175000017500000001401311115326641015210 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include "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; } distcc-3.1/source/src/where.c0000640000175000017500000001341111115326640015202 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* I put the shotgun in an Adidas bag and padded it * out with four pairs of tennis socks, not my style * at all, but that was what I was aiming for: If they * think you're crude, go technical; if they think * you're technical, go crude. I'm a very technical * boy. So I decided to get as crude as possible. * These days, though, you have to be pretty technical * before you can even aspire to crudeness. * -- William Gibson, "Johnny Mnemonic" */ /** * @file * * Routines to decide on which machine to run a distributable job. * * The current algorithm (new in 1.2 and subject to change) is as follows. * * CPU lock is held until the job is complete. * * Once the request has been transmitted, the lock is released and a second * job can be sent. * * Servers which wish to limit their load can defer accepting jobs, and the * client will block with that lock held. * * cpp is probably cheap enough that we can allow it to run unlocked. However * that is not true for local compilation or linking. * * @todo Write a test harness for the host selection algorithm. Perhaps a * really simple simulation of machines taking different amounts of time to * build stuff? */ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "hosts.h" #include "lock.h" #include "where.h" #include "exitcode.h" static int dcc_lock_one(struct dcc_hostdef *hostlist, struct dcc_hostdef **buildhost, int *cpu_lock_fd); int dcc_pick_host_from_list_and_lock_it(struct dcc_hostdef **buildhost, int *cpu_lock_fd) { struct dcc_hostdef *hostlist; int ret; int n_hosts; if ((ret = dcc_get_hostlist(&hostlist, &n_hosts)) != 0) { return EXIT_NO_HOSTS; } if ((ret = dcc_remove_disliked(&hostlist))) return ret; if (!hostlist) { return EXIT_NO_HOSTS; } return dcc_lock_one(hostlist, buildhost, cpu_lock_fd); /* FIXME: Host list is leaked? */ } static void dcc_lock_pause(void) { /* This could do with some tuning. * * My assumption basically is that polling a little too often is * relatively cheap; sleeping when we should be working is bad. However, * if we hit this code at all we're overloaded, so sleeping a while is * perhaps OK. * * We don't use exponential backoff, because that would tend to prefer * later arrivals and penalize jobs that have been waiting for a long * time. This would mean more compiler processes hanging around than is * really necessary, and also by making jobs complete very-out-of-order is * more likely to find Makefile bugs. */ unsigned pause_time = 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; } distcc-3.1/source/src/hosts.c0000640000175000017500000004564311115326640015244 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2004 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* dcc_randomize_host_list() and friends: * Author: Josh Hyman */ /* The lyf so short, the craft so long to lerne. * -- Chaucer */ /** * @file * * Routines to parse $DISTCC_HOSTS. Actual decisions about * where to run a job are in where.c. * * The grammar of this variable is, informally: * DISTCC_HOSTS = HOSTSPEC ... HOSTSPEC = LOCAL_HOST | SSH_HOST | TCP_HOST | OLDSTYLE_TCP_HOST | GLOBAL_OPTION LOCAL_HOST = localhost[/LIMIT] SSH_HOST = [USER]@HOSTID[/LIMIT][:COMMAND][OPTIONS] TCP_HOST = HOSTID[:PORT][/LIMIT][OPTIONS] OLDSTYLE_TCP_HOST = HOSTID[/LIMIT][:PORT][OPTIONS] HOSTID = HOSTNAME | IPV4 OPTIONS = ,OPTION[OPTIONS] OPTION = lzo | cpp GLOBAL_OPTION = --randomize * * Any amount of whitespace may be present between hosts. * * The command specified for SSH defines the location of the remote * server, e.g. "/usr/local/bin/distccd". This is provided as a * convenience who have trouble getting their PATH set correctly for * sshd to find distccd, and should not normally be needed. * * If you need to specify special options for ssh, they should be put * in ~/.ssh/config and referenced by the hostname. * * The TCP port defaults to 3632 and should not normally need to be * overridden. * * IPv6 literals are not supported yet. They will need to be * surrounded by square brackets because they may contain a colon, * which would otherwise be ambiguous. This is consistent with other * URL-like schemes. */ /* Alexandre Oliva writes I take this opportunity to plead people to consider such issues when proposing additional syntax for DISTCC_HOSTS: if it was possible to handle DISTCC_HOSTS as a single shell word (perhaps after turning blanks into say commas), without the risk of any shell active characters such as {, }, ~, $, quotes getting in the way, outputting distcc commands that override DISTCC_HOSTS would be far simpler. TODO: Perhaps entries in the host list that "look like files" (start with '/' or '~') should be read in as files? This could even be recursive. */ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "hosts.h" #include "exitcode.h" #include "snprintf.h" #ifdef HAVE_AVAHI #include "zeroconf.h" #define ZEROCONF_MAGIC "+zeroconf" #endif const int dcc_default_port = DISTCC_DEFAULT_PORT; /*** * A simple container which would hold a host -> rand int pair ***/ struct rand_container { struct dcc_hostdef *host; int rand; }; int dcc_randomize_host_list(struct dcc_hostdef **host_list, int length); int dcc_compare_container(const void *a, const void *b); #ifndef HAVE_STRNDUP /** * Copy at most @p size characters from @p src, plus a terminating nul. * * Really this needs to be in util.c, but it's only used here. **/ 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; *ret_list = NULL; *ret_nhosts = 0; if ((env = getenv("DISTCC_HOSTS")) != NULL) { rs_trace("read hosts from environment"); return dcc_parse_hosts(env, "$DISTCC_HOSTS", ret_list, ret_nhosts, NULL); } /* $DISTCC_DIR or ~/.distcc */ if ((ret = dcc_get_top_dir(&top)) == 0) { /* if we failed to get it, just warn */ 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_error("unrecognized option in host specification: %s", started); return EXIT_BAD_HOSTSPEC; } } if (dcc_get_protover_from_features(host->compr, host->cpp_where, &host->protover) == -1) { rs_log_error("invalid host options: %s", started); return EXIT_BAD_HOSTSPEC; } *psrc = p; return 0; } static int dcc_parse_ssh_host(struct dcc_hostdef *hostdef, const char *token_start) { int ret; const char *token = token_start; /* Everything up to '@' is the username */ if ((ret = dcc_dup_part(&token, &hostdef->user, "@")) != 0) return ret; if (token[0] != '@') { rs_log_error("expected '@' to start ssh token"); return EXIT_BAD_HOSTSPEC; } token++; if ((ret = dcc_dup_part(&token, &hostdef->hostname, "/: \t\n\r\f,")) != 0) return ret; if (!hostdef->hostname) { rs_log_error("hostname is required in SSH host specification \"%s\"", token_start); return EXIT_BAD_HOSTSPEC; } if ((ret = dcc_parse_multiplier(&token, hostdef)) != 0) return ret; if (token[0] == ':') { token++; if ((ret = dcc_dup_part(&token, &hostdef->ssh_command, " \t\n\r\f,"))) return ret; } if ((ret = dcc_parse_options(&token, hostdef))) return ret; hostdef->mode = DCC_MODE_SSH; return 0; } static int dcc_parse_tcp_host(struct dcc_hostdef *hostdef, const char * const token_start) { int ret; const char *token = token_start; if ((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; } if (compr == DCC_COMPRESS_NONE && cpp_where == DCC_CPP_ON_SERVER) { rs_log_error("pump mode (',cpp') requires compression (',lzo')"); } return *protover; } /** * @p where is the host list, taken either from the environment or file. * * @return 0 if parsed successfully; nonzero if there were any errors, * or if no hosts were defined. **/ int dcc_parse_hosts(const char *where, const char *source_name, struct dcc_hostdef **ret_list, int *ret_nhosts, struct dcc_hostdef **ret_prev) { int ret, flag_randomize = 0; struct dcc_hostdef *curr, *_prev; if (!ret_prev) { ret_prev = &_prev; _prev = NULL; } /* TODO: Check for '/' in places where it might cause trouble with * a lock file name. */ /* A simple, hardcoded scanner. Some of the GNU routines might be * useful here, but they won't work on less capable systems. * * We repeatedly attempt to extract a whitespace-delimited host * definition from the string until none remain. Allocate an * entry; hook to previous entry. We then determine if there is a * '@' in it, which tells us whether it is an SSH or TCP * definition. We then duplicate the relevant subcomponents into * the relevant fields. */ while (1) { int token_len; const char *token_start; int has_at; if (where[0] == '\0') break; /* end of string */ /* skip over comments */ if (where[0] == '#') { do where++; while (where[0] != '\n' && where[0] != '\r' && where[0] != '\0'); continue; } if (isspace(where[0])) { where++; /* skip space */ continue; } token_start = where; token_len = strcspn(where, " #\t\n\f\r"); /* intercept keywords which are not actually hosts */ if (!strncmp(token_start, "--randomize", 11)) { flag_randomize = 1; where = token_start + token_len; continue; } if(!strncmp(token_start, "--localslots_cpp", 16)) { const char *ptr; ptr = token_start + 16; if(dcc_parse_multiplier(&ptr, dcc_hostdef_local_cpp) == 0) { where = token_start + token_len; continue; } } if(!strncmp(token_start, "--localslots", 12)) { const char *ptr; ptr = token_start + 12; if(dcc_parse_multiplier(&ptr, dcc_hostdef_local) == 0) { where = token_start + token_len; continue; } } #ifdef HAVE_AVAHI if (token_len == sizeof(ZEROCONF_MAGIC)-1 && !strncmp(token_start, ZEROCONF_MAGIC, (unsigned) token_len)) { if ((ret = dcc_zeroconf_add_hosts(ret_list, ret_nhosts, 4, ret_prev) != 0)) return ret; goto skip; } #endif /* Allocate new list item */ curr = calloc(1, sizeof(struct dcc_hostdef)); if (!curr) { rs_log_crit("failed to allocate host definition"); return EXIT_OUT_OF_MEMORY; } /* by default, mark the host up */ curr->is_up = 1; /* Store verbatim hostname */ if (!(curr->hostdef_string = strndup(token_start, (size_t) token_len))) { rs_log_crit("failed to allocate hostdef_string"); return EXIT_OUT_OF_MEMORY; } /* Link into list */ if (*ret_prev) { (*ret_prev)->next = curr; } else { *ret_list = curr; /* first */ } /* Default task limit. A bit higher than the local limit to allow for * some files in transit. */ curr->n_slots = 4; curr->protover = DCC_VER_1; /* default */ curr->compr = DCC_COMPRESS_NONE; has_at = (memchr(token_start, '@', (size_t) token_len) != NULL); if (!strncmp(token_start, "localhost", 9) && (token_len == 9 || token_start[9] == '/')) { rs_trace("found localhost token \"%.*s\"", token_len, token_start); if ((ret = dcc_parse_localhost(curr, token_start)) != 0) return ret; } else if (has_at) { rs_trace("found ssh token \"%.*s\"", token_len, token_start); if ((ret = dcc_parse_ssh_host(curr, token_start)) != 0) return ret; } else { rs_trace("found tcp token \"%.*s\"", token_len, token_start); if ((ret = dcc_parse_tcp_host(curr, token_start)) != 0) return ret; } if (!curr->is_up) { rs_trace("host %s is down", curr->hostdef_string); } (*ret_nhosts)++; *ret_prev = curr; #ifdef HAVE_AVAHI skip: #endif /* continue to next token if any */ where = token_start + token_len; } if (*ret_nhosts) { if (flag_randomize) if ((ret = dcc_randomize_host_list(ret_list, *ret_nhosts)) != 0) return ret; return 0; } else { rs_log_warning("%s contained no hosts; can't distribute work", source_name); return EXIT_BAD_HOSTSPEC; } } int dcc_compare_container(const void *a, const void *b) { struct rand_container *i, *j; i = (struct rand_container *) a; j = (struct rand_container *) b; if (i->rand == j->rand) return 0; else if (i->rand > j->rand) return 1; else return -1; } int dcc_randomize_host_list(struct dcc_hostdef **host_list, int length) { int i; unsigned int rand_val; struct dcc_hostdef *curr; struct rand_container *c; c = malloc(length * sizeof(struct rand_container)); if (!c) { rs_log_crit("failed to allocate host definition"); return EXIT_OUT_OF_MEMORY; } /* { #ifdef HAVE_GETTIMEOFDAY int ret; struct timeval tv; if ((ret = gettimeofday(&tv, NULL)) == 0) rand_val = (unsigned int) tv.tv_usec; else #else rand_val = (unsigned int) time(NULL) ^ (unsigned int) getpid(); #endif } */ rand_val = (unsigned int) getpid(); /* create pairs of hosts -> random numbers */ srand(rand_val); curr = *host_list; for (i = 0; i < length; i++) { c[i].host = curr; c[i].rand = rand(); curr = curr->next; } /* sort */ qsort(c, length, sizeof(struct rand_container), &dcc_compare_container); /* reorder the list */ for (i = 0; i < length; i++) { if (i != length - 1) c[i].host->next = c[i+1].host; else c[i].host->next = NULL; } /* move the start of the list */ *host_list = c[0].host; free(c); return 0; } int dcc_free_hostdef(struct dcc_hostdef *host) { /* ANSI C requires free() to accept NULL */ free(host->user); free(host->hostname); free(host->ssh_command); free(host->hostdef_string); memset(host, 0xf1, sizeof *host); free(host); return 0; } distcc-3.1/source/src/setuid.c0000640000175000017500000000735311115326640015375 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "daemon.h" #include "exitcode.h" 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; } distcc-3.1/source/src/netutil.h0000640000175000017500000000237011115326640015563 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ struct sockaddr; int dcc_sockaddr_to_string(struct sockaddr *sa, size_t salen, char **p_buf); void dcc_set_nonblocking(int fd); void dcc_set_blocking(int fd); #ifndef HAVE_HSTRERROR /* Missing on e.g. Solaris 2.6 */ const char *hstrerror(int err); #endif void dcc_defer_accept(int); distcc-3.1/source/src/renderer.c0000640000175000017500000002015011115326640015674 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * GtkCellRenderer subclass for drawing strip charts. * * Based on the example of gtkcellrendererpixbuf and hacked up. * * Each table cell corresponds to one execution slot for the client. * Each host can have several slots. At most one task can run on each * slot at any time. Therefore we can draw the history of tasks in * this slot as a set of rectangles that do not overlap in time. * * The renderer looks directly at the list of running tasks to find * the ones in its slot. It accesses the list through a global * variable. This is pretty gross in terms of the Gtk object system, * but it avoids worrying about memory management and filtering the * tasks to put them on the right view of the model. **/ #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "rpc.h" #include "trace.h" #include "exitcode.h" #include "mon.h" #include "netutil.h" #include "renderer.h" struct _DccCellRendererChart { GtkCellRenderer parent; /** History of tasks for this slot. Exposed through the "history" * property. */ struct dcc_history *history; }; struct _DccCellRendererChartClass { GtkCellRendererClass parent_class; }; enum { PROP_ZERO, PROP_HISTORY }; /** * Create a new cell renderer to display a chart of compilation jobs. **/ GtkCellRenderer * dcc_cell_renderer_chart_new (void) { return g_object_new (DCC_TYPE_CELL_RENDERER_CHART, NULL); } static void dcc_cell_renderer_chart_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { DccCellRendererChart *renderer; renderer = DCC_CELL_RENDERER_CHART (object); switch (prop_id) { case PROP_HISTORY: renderer->history = g_value_get_pointer (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void dcc_cell_renderer_chart_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { DccCellRendererChart *renderer; renderer = DCC_CELL_RENDERER_CHART (object); switch (prop_id) { case PROP_HISTORY: g_value_set_pointer (value, renderer->history); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } /** * Actually draw one cell (one strip chart) into a widget. * * I tried checking against the expose area to see whether we needed * to repaint the whole thing, but it does not seem to help very much. * GTK+ always tells us the whole cell is exposed when it updates the * table, even if part of the cell is actually obscured by some other * window. The refresh events are the performance-critical ones for * us; the others don't matter nearly so much. **/ static void dcc_cell_renderer_chart_render (GtkCellRenderer *cell, 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; } distcc-3.1/source/src/h_hosts.c0000640000175000017500000000575511115326640015553 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_hosts.c,v 1.13 2004/01/30 12:39:14 mbp Exp $ * * Copyright (C) 2002, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Test harness for hosts.c. * * Precondition: DISTCC_HOSTS set in the environment. * * Action: calls the environment parser. * * Output: on the first line, the number of hosts. Then, one per * line, either * * "ssh" USER HOST COMMAND * "tcp" HOST PORT **/ #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "hosts.h" #include "exitcode.h" const char *rs_program_name = "h_hosts"; int main(int UNUSED(argc), char **argv) { struct dcc_hostdef *list, *e; int nhosts, i; int ret; rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO); if (argv[1] && !strcmp(argv[1], "-v")) { rs_trace_set_level(RS_LOG_DEBUG); } if ((ret = dcc_get_hostlist(&list, &nhosts)) != 0) { rs_log_error("failed to parse \"%s\"", getenv("DISTCC_HOSTS")); exit(ret); } printf("%d\n", nhosts); for (i = 0, e = list; i < nhosts; i++, e = e->next) { if (!e) { rs_log_error("entry %d is NULL", i); exit(1); } printf("%4d ", e->n_slots); if (e->mode == DCC_MODE_LOCAL) { printf("LOCAL\n"); } else if (e->mode == DCC_MODE_SSH) { printf("SSH %s %s %s\n", e->user ? e->user : "(no-user)", e->hostname ? e->hostname : "(no-hostname)", e->ssh_command ? e->ssh_command : "(no-command)"); } else if (e->mode == DCC_MODE_TCP) { printf("TCP %s %d\n", e->hostname ? e->hostname : "(no-hostname)", e->port); } else { printf("BOGUS %d\n", e->mode); } } if (e) { rs_log_error("extra entries in list!"); exit(EXIT_BAD_HOSTSPEC); } exit(0); } distcc-3.1/source/src/snprintf.c0000640000175000017500000007131011115326641015736 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright Patrick Powell 1995 * This code is based on code written by Patrick Powell (papowell@astart.com) * It may be used for any purpose as long as this notice remains intact * on all source code distributions */ /* * NOTE: If you change this file, please merge it into rsync, samba, etc. */ /************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * A bombproof version of doprnt (dopr) included. * Sigh. This sort of thing is always nasty do deal with. Note that * the version here does not include floating point... * * snprintf() is used instead of sprintf() as it does limit checks * for string length. This covers a nasty loophole. * * The other functions are there to prevent NULL pointers from * causing nast effects. * * More Recently: * Brandon Long 9/15/96 for mutt 0.43 * This was ugly. It is still ugly. I opted out of floating point * numbers, but the formatter understands just about everything * from the normal C string format, at least as far as I can tell from * the Solaris 2.5 printf(3S) man page. * * Brandon Long 10/22/97 for mutt 0.87.1 * Ok, added some minimal floating point support, which means this * probably requires libm on most operating systems. Don't yet * support the exponent (e,E) and sigfig (g,G). Also, fmtint() * was pretty badly broken, it just wasn't being exercised in ways * which showed it, so that's been fixed. Also, 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 01/27/98 for mutt 0.89i * The PGP code was using unsigned hexadecimal formats. * Unfortunately, unsigned formats simply didn't work. * * Michael Elkins 03/05/98 for mutt 0.90.8 * The original code assumed that both snprintf() and vsnprintf() were * missing. Some systems only have snprintf() but not vsnprintf(), so * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. * * Andrew Tridgell (tridge@samba.org) Oct 1998 * fixed handling of %.0f * added test for HAVE_LONG_DOUBLE * * tridge@samba.org, idra@samba.org, April 2001 * got rid of fcvt code (twas buggy and made testing harder) * added C99 semantics * * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0 * actually print args for %g and %e * * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0 * Since includes.h isn't included here, VA_COPY has to be defined here. I don't * see any include file that is guaranteed to be here, so I'm defining it * locally. Fixes AIX and Solaris builds. * * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13 * put the ifdef for HAVE_VA_COPY in one place rather than in lots of * functions * * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4 * Fix usage of va_list passed as an arg. Use __va_copy before using it * when it exists. * * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14 * Fix incorrect zpadlen handling in fmtfp. * Thanks to Ollie Oldham for spotting it. * few mods to make it easier to compile the tests. * 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 #else #define NULL 0 #endif #ifdef TEST_SNPRINTF /* need math library headers for testing */ /* In test mode, we pretend that this system doesn't have any snprintf * functions, regardless of what config.h says. */ # undef HAVE_SNPRINTF # undef HAVE_VSNPRINTF # undef HAVE_C99_VSNPRINTF # undef HAVE_ASPRINTF # undef HAVE_VASPRINTF # include #endif /* TEST_SNPRINTF */ /* Solaris x86, for instance, declares vsnprintf here. */ #include #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #ifdef HAVE_CTYPE_H #include #endif #include #include #ifdef HAVE_STDLIB_H #include #endif #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" #include "va_copy.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 /* yes this really must be a ||. Don't muck with this (tridge) */ #if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in); static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, const char *value, int flags, int min, int max); static void fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags); static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue, int min, int max, int flags); static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); /* * dopr(): poor man's version of doprintf */ /* format read states */ #define DP_S_DEFAULT 0 #define DP_S_FLAGS 1 #define DP_S_MIN 2 #define DP_S_DOT 3 #define DP_S_MAX 4 #define DP_S_MOD 5 #define DP_S_CONV 6 #define DP_S_DONE 7 /* format flags - Bits */ #define DP_F_MINUS (1 << 0) #define DP_F_PLUS (1 << 1) #define DP_F_SPACE (1 << 2) #define DP_F_NUM (1 << 3) #define DP_F_ZERO (1 << 4) #define DP_F_UP (1 << 5) #define DP_F_UNSIGNED (1 << 6) /* Conversion Flags */ #define DP_C_SHORT 1 #define DP_C_LONG 2 #define DP_C_LDOUBLE 3 #define DP_C_LLONG 4 #define char_to_int(p) ((p)- '0') #ifndef MAX #define MAX(p,q) (((p) >= (q)) ? (p) : (q)) #endif static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) { char ch; LLONG value; LDOUBLE fvalue; char *strvalue; const char *const_strvalue; int min; int max; int state; int flags; int cflags; size_t currlen; va_list args; VA_COPY(args, args_in); state = DP_S_DEFAULT; currlen = flags = cflags = min = 0; max = -1; ch = *format++; while (state != DP_S_DONE) { if (ch == '\0') state = DP_S_DONE; switch(state) { case DP_S_DEFAULT: if (ch == '%') state = DP_S_FLAGS; else dopr_outch (buffer, &currlen, maxlen, ch); ch = *format++; break; case DP_S_FLAGS: switch (ch) { case '-': flags |= DP_F_MINUS; ch = *format++; break; case '+': flags |= DP_F_PLUS; ch = *format++; break; case ' ': flags |= DP_F_SPACE; ch = *format++; break; case '#': flags |= DP_F_NUM; ch = *format++; break; case '0': flags |= DP_F_ZERO; ch = *format++; break; default: state = DP_S_MIN; break; } break; case DP_S_MIN: if (isdigit((unsigned char)ch)) { min = 10*min + char_to_int (ch); ch = *format++; } else if (ch == '*') { min = va_arg (args, int); ch = *format++; state = DP_S_DOT; } else { state = DP_S_DOT; } break; case DP_S_DOT: if (ch == '.') { state = DP_S_MAX; ch = *format++; } else { state = DP_S_MOD; } break; case DP_S_MAX: if (isdigit((unsigned char)ch)) { if (max < 0) max = 0; max = 10*max + char_to_int (ch); ch = *format++; } else if (ch == '*') { max = va_arg (args, int); ch = *format++; state = DP_S_MOD; } else { state = DP_S_MOD; } break; case DP_S_MOD: switch (ch) { case 'h': cflags = DP_C_SHORT; ch = *format++; break; case 'l': cflags = DP_C_LONG; ch = *format++; if (ch == 'l') { /* It's a long long */ cflags = DP_C_LLONG; ch = *format++; } break; case 'L': cflags = DP_C_LDOUBLE; ch = *format++; break; default: break; } state = DP_S_CONV; break; case DP_S_CONV: switch (ch) { case 'd': case 'i': if (cflags == DP_C_SHORT) value = va_arg (args, int); else if (cflags == DP_C_LONG) value = va_arg (args, long int); else if (cflags == DP_C_LLONG) value = va_arg (args, LLONG); else value = va_arg (args, int); fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'o': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (long)va_arg (args, unsigned LLONG); else value = (long)va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); break; case 'u': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (LLONG)va_arg (args, unsigned LLONG); else value = (long)va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'X': flags |= DP_F_UP; case 'x': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (LLONG)va_arg (args, unsigned LLONG); else value = (long)va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); break; case 'f': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); /* um, floating point? */ fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); break; case 'E': flags |= DP_F_UP; case 'e': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); break; case 'G': flags |= DP_F_UP; case 'g': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); break; case 'c': dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); break; case 's': strvalue = va_arg (args, char *); const_strvalue = strvalue; if (!const_strvalue) const_strvalue = "(NULL)"; if (max == -1) { max = strlen(const_strvalue); } if (min > 0 && max >= 0 && min > max) max = min; fmtstr (buffer, &currlen, maxlen, const_strvalue, flags, min, max); break; case 'p': strvalue = va_arg (args, void *); fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); break; case 'n': if (cflags == DP_C_SHORT) { short int *num; num = va_arg (args, short int *); *num = currlen; } else if (cflags == DP_C_LONG) { long int *num; num = va_arg (args, long int *); *num = (long int)currlen; } else if (cflags == DP_C_LLONG) { LLONG *num; num = va_arg (args, LLONG *); *num = (LLONG)currlen; } else { int *num; num = va_arg (args, int *); *num = currlen; } break; case '%': dopr_outch (buffer, &currlen, maxlen, ch); break; case 'w': /* not supported yet, treat as next char */ ch = *format++; break; default: /* Unknown, skip */ break; } ch = *format++; state = DP_S_DEFAULT; flags = cflags = min = 0; max = -1; break; case DP_S_DONE: break; default: /* hmm? */ break; /* some picky compilers need this */ } } if (maxlen != 0) { if (currlen < maxlen - 1) buffer[currlen] = '\0'; else if (maxlen > 0) buffer[maxlen - 1] = '\0'; } VA_COPY_END(args); return currlen; } static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, const char *value, int flags, int min, int max) { int padlen, strln; /* amount to pad */ int cnt = 0; #ifdef DEBUG_SNPRINTF printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); #endif if (value == 0) { value = ""; } for (strln = 0; value[strln]; ++strln); /* strlen */ padlen = min - strln; if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justify */ while ((padlen > 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; ++cnt; } while (*value && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, *value++); ++cnt; } while ((padlen < 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; ++cnt; } } /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ static void fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags) { int signvalue = 0; unsigned long uvalue; char convert[20]; int place = 0; int spadlen = 0; /* amount to space pad */ int zpadlen = 0; /* amount to zero pad */ int caps = 0; if (max < 0) max = 0; uvalue = value; if(!(flags & DP_F_UNSIGNED)) { if( value < 0 ) { signvalue = '-'; uvalue = -value; } else { if (flags & DP_F_PLUS) /* Do a sign (+/i) */ signvalue = '+'; else if (flags & DP_F_SPACE) signvalue = ' '; } } if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ do { convert[place++] = (caps? "0123456789ABCDEF":"0123456789abcdef") [uvalue % (unsigned)base ]; uvalue = (uvalue / (unsigned)base ); } while(uvalue && (place < 20)); if (place == 20) place--; convert[place] = 0; zpadlen = max - place; spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); if (zpadlen < 0) zpadlen = 0; if (spadlen < 0) spadlen = 0; if (flags & DP_F_ZERO) { zpadlen = MAX(zpadlen, spadlen); spadlen = 0; } if (flags & DP_F_MINUS) spadlen = -spadlen; /* Left Justifty */ #ifdef DEBUG_SNPRINTF printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", zpadlen, spadlen, min, max, place); #endif /* Spaces */ while (spadlen > 0) { dopr_outch (buffer, currlen, maxlen, ' '); --spadlen; } /* Sign */ if (signvalue) dopr_outch (buffer, currlen, maxlen, signvalue); /* Zeros */ if (zpadlen > 0) { while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } } /* Digits */ while (place > 0) dopr_outch (buffer, currlen, maxlen, convert[--place]); /* Left Justified spaces */ while (spadlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); ++spadlen; } } static LDOUBLE abs_val(LDOUBLE value) { LDOUBLE result = value; if (value < 0) result = -value; return result; } static LDOUBLE POW10(int exp) { LDOUBLE result = 1; while (exp) { result *= 10; exp--; } return result; } static LLONG ROUND(LDOUBLE value) { LLONG intpart; intpart = (LLONG)value; value = value - intpart; if (value >= 0.5) intpart++; return intpart; } /* a replacement for modf that doesn't need the math library. Should be portable, but slow */ static double my_modf(double x0, double *iptr) { int i; long l; double x = x0; double f = 1.0; for (i=0;i<100;i++) { l = (long)x; if (l <= (x+1) && l >= (x-1)) break; x *= 0.1; f *= 10.0; } if (i == 100) { /* yikes! the number is beyond what we can handle. What do we do? */ (*iptr) = 0; return 0; } if (i != 0) { double i2; double ret; ret = my_modf(x0-l*f, &i2); (*iptr) = l*f + i2; return ret; } (*iptr) = l; return x - (*iptr); } static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue, int min, int max, int flags) { int signvalue = 0; double ufvalue; char iconvert[311]; char fconvert[311]; int iplace = 0; int fplace = 0; int padlen = 0; /* amount to pad */ int zpadlen = 0; int caps = 0; int idx; double intpart; double fracpart; double temp; /* * AIX manpage says the default is 0, but Solaris says the default * is 6, and sprintf on AIX defaults to 6 */ if (max < 0) max = 6; ufvalue = abs_val (fvalue); if (fvalue < 0) { signvalue = '-'; } else { if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ signvalue = '+'; } else { if (flags & DP_F_SPACE) signvalue = ' '; } } #if 0 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ #endif #if 0 if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ #endif /* * Sorry, we only support 16 digits past the decimal because of our * conversion method */ if (max > 16) max = 16; /* We "cheat" by converting the fractional part to integer by * multiplying by a factor of 10 */ temp = ufvalue; my_modf(temp, &intpart); fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); if (fracpart >= POW10(max)) { intpart++; fracpart -= POW10(max); } /* Convert integer part */ do { temp = intpart*0.1; my_modf(temp, &intpart); idx = (int) ((temp -intpart +0.05)* 10.0); /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ /* printf ("%llf, %f, %x\n", temp, intpart, idx); */ iconvert[iplace++] = (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; } while (intpart && (iplace < 311)); if (iplace == 311) iplace--; iconvert[iplace] = 0; /* Convert fractional part */ if (fracpart) { do { temp = fracpart*0.1; my_modf(temp, &fracpart); idx = (int) ((temp -fracpart +0.05)* 10.0); /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */ /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx); */ fconvert[fplace++] = (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; } while(fracpart && (fplace < 311)); if (fplace == 311) fplace--; } fconvert[fplace] = 0; /* -1 for decimal point, another -1 if we are printing a sign */ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); zpadlen = max - fplace; if (zpadlen < 0) zpadlen = 0; if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justifty */ if ((flags & DP_F_ZERO) && (padlen > 0)) { if (signvalue) { dopr_outch (buffer, currlen, maxlen, signvalue); --padlen; signvalue = 0; } while (padlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --padlen; } } while (padlen > 0) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; } if (signvalue) dopr_outch (buffer, currlen, maxlen, signvalue); while (iplace > 0) dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); #ifdef DEBUG_SNPRINTF printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); #endif /* * Decimal point. This should probably use locale to find the correct * char to print out. */ if (max > 0) { dopr_outch (buffer, currlen, maxlen, '.'); while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } while (fplace > 0) dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); } while (padlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; } } static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) { if (*currlen < maxlen) { buffer[(*currlen)] = c; } (*currlen)++; } int vsnprintf (char *str, size_t count, const char *fmt, va_list args) { return dopr(str, count, fmt, args); } #endif /* yes this really must be a ||. Don't muck wiith this (tridge) * * The logic for these two is that we need our own definition if the * OS *either* has no definition of *sprintf, or if it does have one * that doesn't work properly according to the autoconf test. Perhaps * these should really be smb_snprintf to avoid conflicts with buggy * linkers? -- mbp */ #if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) int snprintf(char *str,size_t count,const char *fmt,...) { size_t ret; va_list ap; va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); return ret; } #endif #endif /* HAVE_SNPRINTF, and everything */ #ifndef HAVE_VASPRINTF int vasprintf(char **ptr, const char *format, va_list ap) { int ret; va_list ap2; VA_COPY(ap2, ap); ret = vsnprintf(NULL, 0, format, ap2); VA_COPY_END(ap2); if (ret <= 0) return ret; (*ptr) = (char *)malloc(ret+1); if (!*ptr) return -1; VA_COPY(ap2, ap); ret = vsnprintf(*ptr, ret+1, format, ap2); VA_COPY_END(ap2); return ret; } #endif /* HAVE_VASPRINTF */ #ifndef HAVE_ASPRINTF int asprintf(char **ptr, const char *format, ...) { va_list ap; int ret; *ptr = NULL; va_start(ap, format); ret = vasprintf(ptr, format, ap); va_end(ap); return ret; } #endif /* HAVE_ASPRINTF */ #ifdef TEST_SNPRINTF int sprintf(char *str,const char *fmt,...); int main (void) { char buf1[1024]; char buf2[1024]; char *fp_fmt[] = { "%1.1f", "%-1.5f", "%1.5f", "%123.9f", "%10.5f", "% 10.5f", "%+22.9f", "%+4.9f", "%01.3f", "%4f", "%3.1f", "%3.2f", "%.0f", "%f", "-16.16f", NULL }; double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996, 0.9996, 1.996, 4.136, 5.030201, 0.00205, /* END LIST */ 0}; char *int_fmt[] = { "%-1.5d", "%1.5d", "%123.9d", "%5.5d", "%10.5d", "% 10.5d", "%+22.33d", "%01.3d", "%4d", "%d", NULL }; long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; char *str_fmt[] = { "10.5s", "5.10s", "10.1s", "0.10s", "10.0s", "1.10s", "%s", "%.1s", "%.10s", "%10s", NULL }; char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; int x, y; int fail = 0; int num = 0; printf ("Testing snprintf format codes against system sprintf...\n"); for (x = 0; fp_fmt[x] ; x++) { for (y = 0; fp_nums[y] != 0 ; y++) { int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]); int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); sprintf (buf2, fp_fmt[x], fp_nums[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", fp_fmt[x], buf1, buf2); fail++; } if (l1 != l2) { printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]); fail++; } num++; } } for (x = 0; int_fmt[x] ; x++) { for (y = 0; int_nums[y] != 0 ; y++) { int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]); int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); sprintf (buf2, int_fmt[x], int_nums[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", int_fmt[x], buf1, buf2); fail++; } if (l1 != l2) { printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]); fail++; } num++; } } for (x = 0; str_fmt[x] ; x++) { for (y = 0; str_vals[y] != 0 ; y++) { int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]); int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); sprintf (buf2, str_fmt[x], str_vals[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", str_fmt[x], buf1, buf2); fail++; } if (l1 != l2) { printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]); fail++; } num++; } } printf ("%d tests failed out of %d.\n", fail, num); printf("seeing how many digits we support\n"); { double v0 = 0.12345678901234567890123456789012345678901; for (x=0; x<100; x++) { double p = pow(10, x); double r = v0*p; snprintf(buf1, sizeof(buf1), "%1.1f", r); sprintf(buf2, "%1.1f", r); if (strcmp(buf1, buf2)) { printf("we seem to support %d digits\n", x-1); break; } } } return 0; } #endif /* TEST_SNPRINTF */ distcc-3.1/source/src/pump.c0000640000175000017500000001064611115326641015061 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* pump.c - Transfer of bulk data (source, object code) */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SELECT_H # include #endif #include #ifdef HAVE_SYS_MMAN_H # include #endif #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /* * Receive either compressed or uncompressed bulk data. */ int dcc_r_bulk(int ofd, int ifd, unsigned f_size, enum dcc_compress compression) { if (f_size == 0) return 0; /* don't decompress nothing */ if (compression == DCC_COMPRESS_NONE) { return dcc_pump_readwrite(ofd, ifd, f_size); } else if (compression == DCC_COMPRESS_LZO1X) { return dcc_r_bulk_lzo1x(ofd, ifd, f_size); } else { rs_log_error("impossible compression %d", compression); return EXIT_PROTOCOL_ERROR; } } /** * Copy @p n bytes from @p ifd to @p ofd. * * Does not use sendfile(), so either one may be a socket. * * In the current code at least one of the files will always be a regular * (disk) file, even though it may not be mmapable. That should mean that * writes to it will always complete immediately. That in turn means that on * each pass through the main loop we ought to either completely fill our * buffer, or completely drain it, depending on which one is the disk. * * In future we may put back the ability to feed the compiler from a fifo, in * which case it may be that the writes don't complete. * * We might try selecting on both buffers and handling whichever is ready. * This would require some approximation to a circular buffer though, which * might be more complex. **/ int dcc_pump_readwrite(int ofd, int ifd, size_t n) { static char buf[262144]; /* we're not recursive */ char *p; ssize_t r_in, r_out, wanted; int ret; while (n > 0) { wanted = (n > sizeof buf) ? (sizeof buf) : n; r_in = read(ifd, buf, (size_t) wanted); if (r_in == -1 && errno == EAGAIN) { if ((ret = dcc_select_for_read(ifd, dcc_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; } distcc-3.1/source/src/stats.c0000640000175000017500000002662111115326640015235 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Thomas Kho */ #include #include #include #include #include #include #include #include #include #include #include #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "dopt.h" #include "stats.h" #include "srvnet.h" #include "util.h" #include "netutil.h" #include "fcntl.h" #include "daemon.h" int dcc_statspipe[2]; #define MAX_FILENAME_LEN 1024 /* in prefork.c */ void dcc_manage_kids(int listen_fd); struct stats_s { int counters[STATS_ENUM_MAX]; int 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\ \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\ \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 */ #if 0 shutdown(acc_fd, SHUT_WR); /* prevent connection reset */ #endif dcc_close(acc_fd); } /** * Process a packet of stats data **/ static void dcc_stats_process(struct statsdata *sd) { if (sd->type > STATS_ENUM_MAX) { /* Got a bad message */ return; } switch (sd->type) { case STATS_TCP_ACCEPT: case STATS_REJ_BAD_REQ: case STATS_REJ_OVERLOAD: break; case STATS_COMPILE_OK: /* 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); } } distcc-3.1/source/src/gcc-id.c0000640000175000017500000000513111115326640015216 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright (C) 2007 Lennart Poettering * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include "distcc.h" #include "hosts.h" #include "zeroconf.h" #include "trace.h" static char *strip_bad_chars(char *s) { char *k; for (k = s; *k; k++) { if (*k >= 'a' && *k <= 'z') continue; if (*k >= '0' && *k <= '9') continue; if (*k >= 'A' && *k <= 'Z') *k = tolower(*k); else *k = '-'; } return s; } static char* read_string_from_popen(const char *cmdline, char *s, size_t nbytes) { FILE *p = NULL; char *ret = NULL; errno = 0; if (!(p = popen(cmdline, "r"))) { rs_log_crit("Failed to read string from C compiler: %s\n", errno ? strerror(errno) : "failure"); goto fail; } if (!fgets(s, (int) nbytes, p)) { rs_log_crit("Failed to read string from C compiler.\n"); goto fail; } s[nbytes-1] = 0; s[strcspn(s, " \t\n\r")] = 0; ret = s; fail: if (p) pclose(p); return ret; } char* dcc_get_gcc_version(char *s, size_t nbytes) { return read_string_from_popen("cc -dumpversion", s, nbytes); } char* dcc_get_gcc_machine(char *s, size_t nbytes) { return read_string_from_popen("cc -dumpmachine", s, nbytes); } char* dcc_make_dnssd_subtype(char *stype, size_t nbytes, const char *v, const char *m) { char version[64], machine[64]; strncpy(version, v, sizeof(version)-1); version[sizeof(version)-1] = 0; strncpy(machine, m, sizeof(machine)-1); machine[sizeof(machine)-1] = 0; strip_bad_chars(version); strip_bad_chars(machine); snprintf(stype, nbytes, "_%s--%s._sub." DCC_DNS_SERVICE_TYPE, machine, version); stype[nbytes-1] = 0; return stype; } distcc-3.1/source/src/argutil.c0000640000175000017500000000753511115326641015552 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * Utilities for dealing with argv[]-style strings. * * These rules might not yet be consistently applied in distcc, but they * should be in the future: * * For simplicity in managing memory we try to keep all argv structures * malloc'd, without any shared structure. It is then possible to just free * the whole thing whenever we're finished with it. * * One exception is of course the argv used to invoke the program, which is * treated as read-only. */ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** * Return true if argv contains needle as an argument. **/ int dcc_argv_search(char **a, const char *needle) { for (; *a; a++) if (!strcmp(*a, needle)) return 1; return 0; } unsigned int dcc_argv_len(char **a) { unsigned int i; for (i = 0; a[i]; i++) ; return i; } /* Free a malloc'd argv structure. Only safe when the array and all its * components were malloc'd. */ void dcc_free_argv(char **argv) { char **a; for (a = argv; *a != NULL; a++) free(*a); free(argv); } /* Copy an argv array, adding extra NULL elements to the end to allow for * adding more arguments later. */ int dcc_copy_argv(char **from, char ***out, int delta) { char **b; int l, i; l = dcc_argv_len(from); b = malloc((l+1+delta) * (sizeof from[0])); if (b == NULL) { rs_log_error("failed to allocate copy of argv"); return EXIT_OUT_OF_MEMORY; } for (i = 0; i < l; i++) { if ((b[i] = strdup(from[i])) == NULL) { rs_log_error("failed to duplicate element %d", i); 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; } distcc-3.1/source/src/clinet.h0000640000175000017500000000227311115326641015360 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ struct sockaddr; int dcc_connect_by_name(const char *host, int port, int *p_fd); int dcc_connect_by_addr(struct sockaddr *sa, size_t salen, int *p_fd); distcc-3.1/source/src/util.c0000640000175000017500000005061411115326640015053 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_RESOURCE_H #include #endif #ifdef HAVE_SYS_LOADAVG_H #include #endif #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "snprintf.h" /* I will make a man more precious than fine * gold; even a man than the golden wedge of * Ophir. * -- Isaiah 13:12 */ void dcc_exit(int exitcode) { struct rusage self_ru, children_ru; if (getrusage(RUSAGE_SELF, &self_ru)) { rs_log_warning("getrusage(RUSAGE_SELF) failed: %s", strerror(errno)); memset(&self_ru, 0, sizeof self_ru); } if (getrusage(RUSAGE_CHILDREN, &children_ru)) { rs_log_warning("getrusage(RUSAGE_CHILDREN) failed: %s", strerror(errno)); memset(&children_ru, 0, sizeof children_ru); } /* NB fields must match up for microseconds */ rs_log(RS_LOG_INFO, "exit: code %d; self: %d.%06d user %d.%06d sys; children: %d.%06d user %d.%06d sys", exitcode, (int) self_ru.ru_utime.tv_sec, (int) self_ru.ru_utime.tv_usec, (int) self_ru.ru_stime.tv_sec, (int) self_ru.ru_stime.tv_usec, (int) children_ru.ru_utime.tv_sec, (int) children_ru.ru_utime.tv_usec, (int) children_ru.ru_stime.tv_sec, (int) children_ru.ru_stime.tv_usec); exit(exitcode); } int str_endswith(const char *tail, const char *tiger) { size_t len_tail = strlen(tail); size_t len_tiger = strlen(tiger); if (len_tail > len_tiger) return 0; return !strcmp(tiger + len_tiger - len_tail, tail); } int str_startswith(const char *head, const char *worm) { return !strncmp(head, worm, strlen(head)); } /** * Skim through NULL-terminated @p argv, looking for @p s. **/ int argv_contains(char **argv, const char *s) { while (*argv) { if (!strcmp(*argv, s)) return 1; argv++; } return 0; } /** * Redirect a file descriptor into (or out of) a file. * * Used, for example, to catch compiler error messages into a * temporary file. **/ int dcc_redirect_fd(int fd, const char *fname, int mode) { int newfd; /* ignore errors */ close(fd); newfd = open(fname, mode, 0666); if (newfd == -1) { rs_log_crit("failed to reopen fd%d onto %s: %s", fd, fname, strerror(errno)); return EXIT_IO_ERROR; } else if (newfd != fd) { rs_log_crit("oops, reopened fd%d onto fd%d?", fd, newfd); return EXIT_IO_ERROR; } return 0; } char *dcc_gethostname(void) { static char myname[100] = "\0"; if (!myname[0]) { if (gethostname(myname, sizeof myname - 1) == -1) strcpy(myname, "UNKNOWN"); } return myname; } /** * Look up a boolean environment option, which must be either "0" or * "1". The default, if it's not set or is empty, is @p default. **/ int dcc_getenv_bool(const char *name, int default_value) { const char *e; e = getenv(name); if (!e || !*e) return default_value; if (!strcmp(e, "1")) return 1; else if (!strcmp(e, "0")) return 0; else return default_value; } #define IS_LEGAL_DOMAIN_CHAR(c) (isalnum(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 static char RSS_name[] = "none"; *num_D = -1; *max_RSS = -1; *max_RSS_name = RSS_name; #endif } /* Returns the number of sector read/writes since boot */ void dcc_get_disk_io_stats(int *n_reads, int *n_writes) { #if defined(linux) int retval; int kernel26 = 1; FILE *f; int reads, writes, minor; char dev[100]; char tmp[1024]; *n_reads = 0; *n_writes = 0; f = fopen("/proc/diskstats", "r"); if (f == NULL) { if (errno != ENOENT) return; /* /proc/diskstats does not exist. probably a 2.4 kernel, so try reading * /proc/partitions */ f = fopen("/proc/partitions", "r"); if (f == NULL) return; kernel26 = 0; } if (!kernel26) /* blast away 2 header lines in /proc/partitions */ 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 { #if 0 /* individual parition stats */ retval = fscanf(f, " %*d %d %*d %d", &reads, &writes); if (retval == EOF || retval != 2) break; #endif /* assume the lines aren't longer that 1024 characters */ 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 #ifndef HAVE_STRSEP static char* strsep(char** str, const char* delims) { char* token; if (*str == NULL) { return NULL; } token = *str; while (**str != '\0') { if (strchr(delims, **str) != NULL) { **str = '\0'; (*str)++; return token; } (*str)++; } *str = NULL; return token; } #endif /* Given a string @p input, this function fills a a newly-allocated array of strings with copies of the input's whitespace-separated parts. Returns 0 on success, 1 on error. */ int dcc_tokenize_string(const char *input, char ***argv_ptr) { size_t n_spaces = 0; char *for_count; char **ap; char *input_copy; /* First of all, make a copy of the input string; * this way, we can destroy the copy. */ input_copy = strdup(input); if (input_copy == NULL) return 1; /* Count the spaces in the string. */ for (for_count = input_copy; *for_count; for_count++) if (isspace(*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; } distcc-3.1/source/src/compile.c0000640000175000017500000007102011115326641015521 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #ifdef HAVE_FNMATCH_H #include #endif #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "hosts.h" #include "bulk.h" #include "implicit.h" #include "exec.h" #include "where.h" #include "lock.h" #include "timeval.h" #include "compile.h" #include "include_server_if.h" #include "emaillog.h" #include "dotd.h" /** * This boolean is true iff --scan-includes option is enabled. * If so, distcc will just run the source file through the include server, * and print out the list of header files that might be #included, * rather than actually compiling the sources. */ int dcc_scan_includes = 0; /* TODO(klarlund)Warning: this constant should have the same value as in the * pump.in script! Make it configurable and user changeable.*/ 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 dcc_discrepancy_filename(char **filename) { const char *include_server_port = getenv("INCLUDE_SERVER_PORT"); *filename = NULL; if (include_server_port == NULL) { return 0; } else if (str_endswith(include_server_port_suffix, include_server_port)) { /* We're going to make a longer string from include_server_port: one * that replaces include_server_port_suffix with discrepancy_suffix. */ int delta = strlen(discrepancy_suffix) - strlen(include_server_port_suffix); assert (delta > 0); *filename = malloc(strlen(include_server_port) + 1 + delta); if (!*filename) { rs_log_error("failed to allocate space for filename"); return EXIT_OUT_OF_MEMORY; } strcpy(*filename, include_server_port); int slash_pos = strlen(include_server_port) - strlen(include_server_port_suffix); /* Because include_server_port_suffix is a suffix of include_server_port * we expect to find a '/' at slash_pos in filename. */ assert((*filename)[slash_pos] == '/'); (void) strcpy(*filename + slash_pos, discrepancy_suffix); return 0; } else return 0; } /** * Return the length of the @param discrepancy_filename in newly allocated * memory; return 0 if it's not possible to determine the length (if * e.g. @param discrepancy_filename is NULL). **/ static int dcc_read_number_discrepancies(const char *discrepancy_filename) { if (!discrepancy_filename) return 0; struct stat stat_record; if (stat(discrepancy_filename, &stat_record) == 0) { size_t size = stat_record.st_size; /* Does size fit in an 'int'? */ if ((((size_t) (int) size) == size) && ((int) size) > 0) return ((int) size); else return INT_MAX; } else return 0; } /** * Lengthen the file whose name is @param discrepancy_filename by one byte. Or, * do nothing, if @param discrepancy_filename is NULL. **/ static int dcc_note_discrepancy(const char *discrepancy_filename) { FILE *discrepancy_file; if (!discrepancy_filename) return 0; if (!(discrepancy_file = fopen(discrepancy_filename, "a"))) { rs_log_error("failed to open discrepancy_filename file: %s: %s", discrepancy_filename, strerror(errno)); return EXIT_IO_ERROR; } if (fputc('@', discrepancy_file) == EOF) { rs_log_error("failed to write to discrepancy_filename file: %s", discrepancy_filename); fclose(discrepancy_file); return EXIT_IO_ERROR; } /* The file position is a property of the stream, so we are assured that exactly one process will take the 'if' branch when max_discrepancies_before_demotion failures is reached. */ if (ftell(discrepancy_file) == (long int)max_discrepancies_before_demotion) { rs_log_warning("now using plain distcc, possibly due to " "inconsistent file system changes during build"); } fclose(discrepancy_file); return 0; } /** * In some cases, it is ill-advised to preprocess on the server. Check for such * situations. If they occur, then change protocol version. **/ static void dcc_perhaps_adjust_cpp_where_and_protover( char *input_fname, struct dcc_hostdef *host, char *discrepancy_filename) { /* It's unfortunate that the variable that controls preprocessing is in the "host" datastructure. See elaborate complaint in dcc_build_somewhere. */ /* Check whether there has been too much trouble running distcc-pump during this build. */ if (dcc_read_number_discrepancies(discrepancy_filename) >= max_discrepancies_before_demotion) { /* Give up on using distcc-pump */ host->cpp_where = DCC_CPP_ON_CLIENT; dcc_get_protover_from_features(host->compr, host->cpp_where, &host->protover); } /* Don't do anything silly for already preprocessed files. */ if (dcc_is_preprocessed(input_fname)) { /* Don't subject input file to include analysis. */ rs_log_warning("cannot use distcc_pump on already preprocessed file" " (such as emitted by ccache)"); host->cpp_where = DCC_CPP_ON_CLIENT; dcc_get_protover_from_features(host->compr, host->cpp_where, &host->protover); } /* Environment variables CPATH and two friends are hidden ways of passing * -I's. Beware! */ if (getenv("CPATH") || getenv("C_INCLUDE_PATH") || getenv("CPLUS_INCLUDE_PATH")) { rs_log_warning("cannot use distcc_pump with any of environment" " variables CPATH, C_INCLUDE_PATH or CPLUS_INCLUDE_PATH" " set, preprocessing locally"); host->cpp_where = DCC_CPP_ON_CLIENT; dcc_get_protover_from_features(host->compr, host->cpp_where, &host->protover); } } /** * Do a time analysis of dependencies in dotd file. First, if @param dotd_fname * is created before @param reference_time, then return NULL in result. Second, * if one of the files mentioned in the @param dotd_fname is modified after time * @param reference_time, then return non-NULL in result. Otherwise return NULL * in result. A non-NULL value in result is a pointer to a newly allocated * string describing the offending dependency. * If @param exclude_pattern is not NULL, then files matching the glob @param * exclude_pattern are not considered in the above comparison. * * This function is not declared static --- for purposes of testing. **/ int dcc_fresh_dependency_exists(const char *dotd_fname, const char *exclude_pattern, time_t reference_time, char **result) { struct stat stat_dotd; off_t dotd_fname_size = 0; FILE *fp; int c; int res; char *dep_name; *result = NULL; /* Allocate buffer for dotd contents and open it. */ res = stat(dotd_fname, &stat_dotd); if (res) { rs_trace("could not stat \"%s\": %s", dotd_fname, strerror(errno)); return 0; } if (stat_dotd.st_mtime < reference_time) { /* That .d file appears to be too old; don't trust it for this * analysis. */ rs_trace("old dotd file \"%s\"", dotd_fname); return 0; } dotd_fname_size = stat_dotd.st_size; /* Is dotd_fname_size representable as a size_t value ? */ if ((off_t) (size_t) dotd_fname_size == dotd_fname_size) { dep_name = malloc((size_t) dotd_fname_size); if (!dep_name) { rs_log_error("failed to allocate space for dotd file"); return EXIT_OUT_OF_MEMORY; } } else { /* This is exceedingly unlikely. */ rs_trace("file \"%s\" is too big", dotd_fname); return 0; } if ((fp = fopen(dotd_fname, "r")) == NULL) { rs_trace("could not open \"%s\": %s", dotd_fname, strerror(errno)); free(dep_name); return 0; } /* Find ':'. */ while ((c = getc(fp)) != EOF && c != ':'); if (c != ':') goto return_0; /* Process dependencies. */ while (c != EOF) { struct stat stat_dep; int i = 0; /* Skip whitespaces and backslashes. */ while ((c = getc(fp)) != EOF && (isspace(c) || c == '\\')); /* Now, we're at start of file name. */ ungetc(c, fp); while ((c = getc(fp)) != EOF && (!isspace(c) || c == '\\')) { if (i >= dotd_fname_size) { /* Impossible */ rs_log_error("not enough room for dependency name"); goto return_0; } if (c == '\\') { /* Skip the newline. */ if ((c = getc(fp)) != EOF) if (c != '\n') ungetc(c, fp); } else dep_name[i++] = c; } if (i != 0) { dep_name[i] = '\0'; #ifdef HAVE_FNMATCH_H if (exclude_pattern == NULL || fnmatch(exclude_pattern, dep_name, 0) == FNM_NOMATCH) { #else /* Tautology avoids compiler warning about unused variable. */ if (exclude_pattern == exclude_pattern) { #endif /* The dep_name is not excluded; now verify that it is not too * young. */ rs_log_info("Checking dependency: %s", dep_name); res = stat(dep_name, &stat_dep); if (res) goto return_0; if (stat_dep.st_ctime >= reference_time) { fclose(fp); *result = realloc(dep_name, strlen(dep_name) + 1); if (*result == NULL) { rs_log_error("realloc failed"); return EXIT_OUT_OF_MEMORY; } return 0; } } } } return_0: fclose(fp); free(dep_name); return 0; } /** * Invoke a compiler locally. This is, obviously, the alternative to * dcc_compile_remote(). * * The server does basically the same thing, but it doesn't call this * routine because it wants to overlap execution of the compiler with * copying the input from the network. * * This routine used to exec() the compiler in place of distcc. That * is slightly more efficient, because it avoids the need to create, * schedule, etc another process. The problem is that in that case we * can't clean up our temporary files, and (not so important) we can't * log our resource usage. * * This is called with a lock on localhost already held. **/ static int dcc_compile_local(char *argv[], char *input_name) { pid_t pid; int ret; int status; dcc_note_execution(dcc_hostdef_local, argv); dcc_note_state(DCC_PHASE_COMPILE, input_name, "localhost"); /* 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'. * Must be dynamically allocated. This routine deallocates it. * * @param status On return, contains the waitstatus of the compiler or * preprocessor. This function can succeed (in running the compiler) even if * the compiler itself fails. If either the compiler or preprocessor fails, * @p status is guaranteed to hold a failure value. * * Implementation notes: * * This code might be simpler if we would only acquire one lock * at a time. But we need to choose the server host in order * to determine whether it supports pump mode or not, * and choosing the server host requires acquiring its lock * (otherwise it might be busy when we we try to acquire it). * So if the server chosen is not localhost, we need to hold the * remote host lock while we're doing local preprocessing or include * scanning. Since local preprocessing/include scanning requires * us to acquire the local cpu lock, that means we need to hold two * locks at one time. * * TODO: make pump mode a global flag, and drop support for * building with cpp mode on some hosts and not on others. * Then change the code so that we only choose the remote * host after local preprocessing/include scanning is finished * and the local cpu lock is released. */ static int dcc_build_somewhere(char *argv[], int sg_level, int *status) { char *input_fname = NULL, *output_fname, *cpp_fname, *deps_fname = NULL; char **files; char **server_side_argv = NULL; int server_side_argv_deep_copied = 0; char *server_stderr_fname = NULL; int needs_dotd = 0; int sets_dotd_target = 0; pid_t cpp_pid = 0; int cpu_lock_fd = -1, local_cpu_lock_fd = -1; int ret; int remote_ret = 0; struct dcc_hostdef *host = NULL; char *discrepancy_filename = NULL; char **new_argv; if ((ret = dcc_expand_preprocessor_options(&argv)) != 0) goto clean_up; if ((ret = dcc_discrepancy_filename(&discrepancy_filename))) goto clean_up; if (sg_level) /* Recursive distcc - run locally, and skip all locking. */ goto run_local; /* TODO: Perhaps tidy up these gotos. */ /* FIXME: this may leak memory for argv. */ ret = dcc_scan_args(argv, &input_fname, &output_fname, &new_argv); dcc_free_argv(argv); argv = new_argv; if (ret != 0) { /* we need to scan the arguments even if we already know it's * local, so that we can pick up distcc client options. */ goto lock_local; } #if 0 /* turned off because we never spend long in this state. */ dcc_note_state(DCC_PHASE_STARTUP, input_fname, NULL); #endif if ((ret = dcc_make_tmpnam("distcc_server_stderr", ".txt", &server_stderr_fname))) { /* So we are failing locally to make a temp file to store the * server-side errors in; it's unlikely anything else will * work, but let's try the compilation locally. * FIXME: this will blame the server for a failure that is * local. However, we don't make any distrinction between * all the reasons dcc_compile_remote can fail either; * and some of those reasons are local. */ goto fallback; } /* Lock ordering invariant: always acquire the lock for the * remote host (if any) first. */ /* Choose the distcc server host (which could be either a remote * host or localhost) and acquire the lock for it. */ if ((ret = dcc_pick_host_from_list_and_lock_it(&host, &cpu_lock_fd)) != 0) { /* Doesn't happen at the moment: all failures are masked by returning localhost. */ goto fallback; } if (host->mode == DCC_MODE_LOCAL) { /* We picked localhost and already have a lock on it so no * need to lock it now. */ goto run_local; } /* Lock the local CPU, since we're going to be doing preprocessing * or include scanning. */ if ((ret = dcc_lock_local_cpp(&local_cpu_lock_fd)) != 0) { goto fallback; } if (host->cpp_where == DCC_CPP_ON_SERVER) { /* Perhaps it is not a good idea to preprocess on the server. */ dcc_perhaps_adjust_cpp_where_and_protover(input_fname, host, discrepancy_filename); } if (dcc_scan_includes) { ret = dcc_approximate_includes(host, argv); goto unlock_and_clean_up; } if (host->cpp_where == DCC_CPP_ON_SERVER) { if ((ret = dcc_talk_to_include_server(argv, &files))) { /* Fallback to doing cpp locally */ /* It's unfortunate that the variable that controls that is in the * "host" datastructure, even though in this case it's the client * that fails to support it, but "host" is what gets passed * around in the client code. We are, in 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 { /* Include server succeeded. */ /* We're done with local "preprocessing" (include scanning). */ dcc_unlock(local_cpu_lock_fd); /* Don't try to unlock again in dcc_compile_remote. */ local_cpu_lock_fd = -1; } } if (host->cpp_where == DCC_CPP_ON_CLIENT) { files = NULL; if ((ret = dcc_cpp_maybe(argv, input_fname, &cpp_fname, &cpp_pid) != 0)) goto fallback; if ((ret = dcc_strip_local_args(argv, &server_side_argv))) goto fallback; } else { char *dotd_target = NULL; cpp_fname = NULL; cpp_pid = 0; dcc_get_dotd_info(argv, &deps_fname, &needs_dotd, &sets_dotd_target, &dotd_target); server_side_argv_deep_copied = 1; if ((ret = dcc_copy_argv(argv, &server_side_argv, 2))) goto fallback; if (needs_dotd && !sets_dotd_target) { dcc_argv_append(server_side_argv, strdup("-MT")); if (dotd_target == NULL) dcc_argv_append(server_side_argv, strdup(output_fname)); else dcc_argv_append(server_side_argv, strdup(dotd_target)); } } if ((ret = dcc_compile_remote(server_side_argv, input_fname, cpp_fname, files, output_fname, needs_dotd ? deps_fname : NULL, server_stderr_fname, cpp_pid, local_cpu_lock_fd, host, status)) != 0) { /* Returns zero if we successfully ran the compiler, even if * the compiler itself bombed out. */ /* dcc_compile_remote() already unlocked local_cpu_lock_fd. */ local_cpu_lock_fd = -1; goto fallback; } /* dcc_compile_remote() already unlocked local_cpu_lock_fd. */ local_cpu_lock_fd = -1; dcc_enjoyed_host(host); dcc_unlock(cpu_lock_fd); cpu_lock_fd = -1; ret = dcc_critique_status(*status, "compile", input_fname, host, 1); if (ret == 0) { /* Try to copy the server-side errors on stderr. * If that fails, even though the compilation succeeded, * we haven't managed to give these errors to the user, * so we have to try again. * FIXME: Just like in the attempt to make a temporary file, this * is unlikely to fail, if it does it's unlikely any other * operation will work, and this makes the mistake of * blaming the server for what is (clearly?) a local failure. */ if ((dcc_copy_file_to_fd(server_stderr_fname, STDERR_FILENO))) { rs_log_warning("Could not show server-side errors"); goto fallback; } /* SUCCESS! */ goto clean_up; } if (ret < 128) { /* Remote compile just failed, e.g. with syntax error. It may be that the remote compilation failed because the file has an error, or because we did something wrong (e.g. we did not send all the necessary files.) Retry locally. If the local compilation also fails, then we know it's the program that has the error, and it doesn't really matter that we recompile, because this is rare. If the local compilation succeeds, then we know it's our fault, and we should do something about it later. (Currently, we send email to an appropriate email address). */ 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 (cpu_lock_fd != -1) { dcc_unlock(cpu_lock_fd); cpu_lock_fd = -1; } if (local_cpu_lock_fd != -1) { dcc_unlock(local_cpu_lock_fd); local_cpu_lock_fd = -1; } 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); } unlock_and_clean_up: if (cpu_lock_fd != -1) { dcc_unlock(cpu_lock_fd); cpu_lock_fd = -1; /* Not really needed, just for consistency. */ } /* For the --scan_includes case. */ if (local_cpu_lock_fd != -1) { dcc_unlock(local_cpu_lock_fd); local_cpu_lock_fd = -1; /* Not really needed, just for consistency. */ } clean_up: dcc_free_argv(argv); if (server_side_argv_deep_copied) { if (server_side_argv != NULL) { dcc_free_argv(server_side_argv); } } else { free(server_side_argv); } free(discrepancy_filename); return ret; } /* * argv must be dynamically allocated. * This routine will deallocate it. */ int dcc_build_somewhere_timed(char *argv[], int sg_level, int *status) { struct timeval before, after, delta; int ret; if (gettimeofday(&before, NULL)) rs_log_warning("gettimeofday failed"); ret = dcc_build_somewhere(argv, sg_level, status); if (gettimeofday(&after, NULL)) { rs_log_warning("gettimeofday failed"); } else { /* TODO: Show rate based on cpp size? Is that meaningful? */ timeval_subtract(&delta, &after, &before); rs_log(RS_LOG_INFO|RS_LOG_NONAME, "elapsed compilation time %ld.%06lds", delta.tv_sec, (long) delta.tv_usec); } return ret; } distcc-3.1/source/src/fix_debug_info.c0000640000175000017500000003745611115326640017056 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Author: Fergus Henderson */ /* * fix_debug_info.cc: * Performs search-and-replace in the debug info section of an ELF file. */ #include #include #include #include #include #include #include #include #ifdef HAVE_ELF_H #include #endif #include #ifdef HAVE_SYS_MMAN_H #include #endif #include "trace.h" #include "fix_debug_info.h" /* XINDEX isn't defined everywhere, but where it is, it's always the * same as HIRESERVE, so I think this should be safe. */ #ifndef SHN_XINDEX #define SHN_XINDEX SHN_HIRESERVE #endif #ifdef HAVE_ELF_H /* * Search for an ELF section of the specified name and type. * Given an ELF file that has been mmapped (or read) into memory starting * at @p elf_mapped_base, find the section with the desired name and type, * and return (via the parameters) its start point and size. * Returns 1 if found, 0 otherwise. */ static int FindElfSection(const void *elf_mapped_base, off_t elf_size, const char *desired_section_name, const void **section_start, int *section_size) { const unsigned char *elf_base = (const unsigned char *) elf_mapped_base; /* The double cast below avoids warnings with -Wcast-align. */ const Elf32_Ehdr *elf32_header = (const Elf32_Ehdr *) (const void *) elf_base; unsigned int i; unsigned int num_sections; assert(elf_mapped_base); assert(section_start); assert(section_size); *section_start = NULL; *section_size = 0; /* * There are two kinds of ELF files, 32-bit and 64-bit. They have similar * but slightly different file structures. It's OK to use the elf32_header * structure at this point, prior to checking whether this file is a 32 or * 64 bit ELF file, so long as we only access the e_ident field, because * the layout of the e_ident field is the same for both kinds: it's the * first field in the struct, so its offset is zero, and its size is the * same for both 32 and 64 bit ELF files. * * The magic number which identifies an ELF file is stored in the * first few bytes of the e_ident field, which is also the first few * bytes of the file. */ if (elf_size < SELFMAG || memcmp(elf32_header, ELFMAG, SELFMAG) != 0) { rs_trace("object file is not an ELF file"); return 0; } /* * The ELF file layouts are defined using fixed-size data structures * in , so we don't need to worry about the host computer's * word size. But we do need to worry about the host computer's * enddianness, because ELF header fields use the same endianness * as the target computer. When cross-compiling to a target with * a different endianness, we would need to byte-swap all the fields * that we use. Right now we don't handle that case. * * TODO(fergus): * handle object files with different endianness than the host. */ #if WORDS_BIGENDIAN if (elf32_header->e_ident[EI_DATA] != ELFDATA2MSB) { rs_trace("sorry, not fixing debug info: " "distcc server host is big-endian, object file is not"); return 0; } #else if (elf32_header->e_ident[EI_DATA] != ELFDATA2LSB) { rs_trace("sorry, not fixing debug info: " "distcc server host is little-endian, object file is not"); return 0; } #endif /* * Warning: the following code section is duplicated: * once for 32-bit ELF files, and again for 64-bit ELF files. * Please be careful to keep them consistent! */ if (elf32_header->e_ident[EI_CLASS] == ELFCLASS32) { const Elf32_Ehdr *elf_header = elf32_header; const Elf32_Shdr *sections = /* The double cast below avoids warnings with -Wcast-align. */ (const Elf32_Shdr *) (const void *) (elf_base + elf_header->e_shoff); const Elf32_Shdr *string_section = sections + elf_header->e_shstrndx; const Elf32_Shdr *desired_section = NULL; if (elf_size < (off_t) sizeof(*elf_header)) { rs_trace("object file is too small for ELF header; maybe got truncated?"); return 0; } if (elf_header->e_shoff <= 0 || elf_header->e_shoff > elf_size - sizeof(Elf32_Shdr)) { rs_trace("invalid e_shoff value in ELF header"); return 0; } if (elf_header->e_shstrndx == SHN_UNDEF) { rs_trace("object file has no section name string table" " (e_shstrndx == SHN_UNDEF)"); return 0; } /* Special case for more sections than will fit in e_shstrndx. */ if (elf_header->e_shstrndx == SHN_XINDEX) { string_section = sections + sections[0].sh_link; } num_sections = elf_header->e_shnum; /* Special case for more sections than will fit in e_shnum. */ if (num_sections == 0) { num_sections = sections[0].sh_size; } for (i = 0; i < num_sections; ++i) { const char *section_name = (char *)(elf_base + string_section->sh_offset + sections[i].sh_name); if (!strcmp(section_name, desired_section_name)) { desired_section = §ions[i]; break; } } if (desired_section != NULL && desired_section->sh_size > 0) { int desired_section_size = desired_section->sh_size; *section_start = elf_base + desired_section->sh_offset; *section_size = desired_section_size; return 1; } else { return 0; } } else if (elf32_header->e_ident[EI_CLASS] == ELFCLASS64) { /* The double cast below avoids warnings with -Wcast-align. */ const Elf64_Ehdr *elf_header = (const Elf64_Ehdr *) (const void *) elf_base; const Elf64_Shdr *sections = (const Elf64_Shdr *) (const void *) (elf_base + elf_header->e_shoff); const Elf64_Shdr *string_section = sections + elf_header->e_shstrndx; const Elf64_Shdr *desired_section = NULL; if (elf_size < (off_t) sizeof(*elf_header)) { rs_trace("object file is too small for ELF header; maybe got truncated?"); return 0; } if (elf_header->e_shoff <= 0 || elf_header->e_shoff > (size_t) elf_size - sizeof(Elf64_Shdr)) { rs_trace("invalid e_shoff value in ELF header"); return 0; } if (elf_header->e_shstrndx == SHN_UNDEF) { rs_trace("object file has no section name string table" " (e_shstrndx == SHN_UNDEF)"); return 0; } /* Special case for more sections than will fit in e_shstrndx. */ if (elf_header->e_shstrndx == SHN_XINDEX) { string_section = sections + sections[0].sh_link; } num_sections = elf_header->e_shnum; if (num_sections == 0) { /* Special case for more sections than will fit in e_shnum. */ num_sections = sections[0].sh_size; } for (i = 0; i < num_sections; ++i) { const char *section_name = (char*)(elf_base + string_section->sh_offset + sections[i].sh_name); if (!strcmp(section_name, desired_section_name)) { desired_section = §ions[i]; break; } } if (desired_section != NULL && desired_section->sh_size > 0) { int desired_section_size = desired_section->sh_size; *section_start = elf_base + desired_section->sh_offset; *section_size = desired_section_size; return 1; } else { return 0; } } else { rs_trace("unknown ELF class - neither ELFCLASS32 nor ELFCLASS64"); return 0; } } /* * Search in a memory buffer (starting at @p base and of size @p size) * for a string (@p search), and replace @p search with @p replace * in all null-terminated strings that contain @p search. */ static int replace_string(void *base, size_t size, const char *search, const char *replace) { char *start = (char *) base; char *end = (char *) base + size; int count = 0; char *p; size_t search_len = strlen(search); size_t replace_len = strlen(replace); assert(replace_len == search_len); if (size < search_len + 1) return 0; for (p = start; p < end - search_len - 1; p++) { if (memcmp(p, search, search_len) == 0) { memcpy(p, replace, replace_len); count++; } } return count; } /* * Map the specified file into memory with MAP_SHARED. * Returns the mapped address, and stores the file descriptor in @p p_fd. * It also fstats the file and stores the results in @p st. * Logs an error message and returns NULL on failure. */ static void *mmap_file(const char *path, int *p_fd, struct stat *st) { int fd; void *base; fd = open(path, O_RDWR); if (fd < 0) { rs_log_error("error opening file '%s': %s", path, strerror(errno)); return NULL; } if (fstat(fd, st) != 0) { rs_log_error("fstat of file '%s' failed: %s", path, strerror(errno)); close(fd); return NULL; } if (st->st_size <= 0) { rs_log_error("file '%s' has invalid file type or size", path); close(fd); return NULL; } #ifdef HAVE_SYS_MMAP_H base = mmap(NULL, st->st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (base == MAP_FAILED) { rs_log_error("mmap of file '%s' failed: %s", path, strerror(errno)); close(fd); return NULL; } #else base = malloc(st->st_size); if (base == NULL) { rs_log_error("can't allocate buffer for %s: malloc failed", path); close(fd); return NULL; } errno = 0; if (read(fd, base, st->st_size) != st->st_size) { rs_log_error("can't read %ld bytes from %s: %s", (long) st->st_size, path, strerror(errno)); close(fd); return NULL; } #endif *p_fd = fd; return base; } static int munmap_file(void *base, const char *path, int fd, const struct stat *st) { int status = 0; #ifdef HAVE_SYS_MMAP_H if (munmap(base, st->st_size) != 0) { rs_log_error("munmap of file '%s' failed: %s", path, strerror(errno)); status = 1; } #else errno = 0; if (lseek(fd, 0, SEEK_SET) == -1) { rs_log_error("can't seek to start of %s: %s", path, strerror(errno)); status = 1; } else if (write(fd, base, st->st_size) != st->st_size) { rs_log_error("can't write %ld bytes to %s: %s", (long) st->st_size, path, strerror(errno)); status = 1; } #endif if (close(fd) != 0) { rs_log_error("close of file '%s' failed: %s", path, strerror(errno)); status = 1; } return status; } /* * Update the ELF file residing at @p path, replacing all occurrences * of @p search with @p replace in the section named @p desired_section_name. * The replacement string must be the same length or shorter than * the search string. */ static void update_section(const char *path, const void *base, off_t size, const char *desired_section_name, const char *search, const char *replace) { const void *desired_section = NULL; int desired_section_size = 0; if (FindElfSection(base, size, desired_section_name, &desired_section, &desired_section_size) && desired_section_size > 0) { /* The local variable below works around a bug in some versions * of gcc (4.2.1?), which issues an erroneous warning if * 'desired_section_rw' is replaced with '(void *) desired_section' * in the call below, causing compile errors with -Werror. */ void *desired_section_rw = (void *) desired_section; int count = replace_string(desired_section_rw, desired_section_size, search, replace); if (count == 0) { rs_trace("\"%s\" section of file %s has no occurrences of \"%s\"", desired_section_name, path, search); } else { rs_log_info("updated \"%s\" section of file \"%s\": " "replaced %d occurrences of \"%s\" with \"%s\"", desired_section_name, path, count, search, replace); if (count > 1) { rs_log_warning("only expected to replace one occurrence!"); } } } else { rs_trace("file %s has no \"%s\" section", 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 , so can't change %s to %s in debug info for %s", server_path, client_path, path); return 0; #else /* * We can only safely replace a string with another of exactly * the same length. (Replacing a string with a shorter string * results in errors from gdb.) * So we append trailing slashes on the client side path. */ size_t client_path_len = strlen(client_path); size_t server_path_len = strlen(server_path); assert(client_path_len <= server_path_len); char *client_path_plus_slashes = malloc(server_path_len + 1); if (!client_path_plus_slashes) { rs_log_crit("failed to allocate memory"); return 1; } strcpy(client_path_plus_slashes, client_path); while (client_path_len < server_path_len) { client_path_plus_slashes[client_path_len++] = '/'; } client_path_plus_slashes[client_path_len] = '\0'; rs_log_info("client_path_plus_slashes = %s", client_path_plus_slashes); return update_debug_info(path, server_path, client_path_plus_slashes); #endif } #ifdef TEST const char *rs_program_name; int main(int argc, char **argv) { rs_program_name = argv[0]; rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO); rs_trace_set_level(RS_LOG_DEBUG); if (argc != 4) { rs_log_error("Usage: %s ", rs_program_name); exit(1); } return dcc_fix_debug_info(argv[1], argv[2], argv[3]); } #endif distcc-3.1/source/src/strip.c0000640000175000017500000001356011115326640015236 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2008 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** * Strip arguments like -D and -I from a command line, because they do * not need to be passed across the wire. This covers options for * both the preprocess and link phases, since they should never happen * remotely. * * In the case where we inadvertently do cause preprocessing to happen * remotely, it is possible that omitting these options will make * failure more obvious and avoid false success. * * Giving -L on a compile-only command line is a bit 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. * * The value stored in '*out_argv' is malloc'd, but the arguments that * are pointed to by that array are aliased with the values pointed * to by 'from'. The caller is responsible for calling free() on * '*out_argv'. **/ int dcc_strip_local_args(char **from, char ***out_argv) { char **to; int from_i, to_i; int from_len; from_len = dcc_argv_len(from); *out_argv = to = malloc((from_len + 1) * sizeof (char *)); if (!to) { rs_log_error("failed to allocate space for arguments"); return EXIT_OUT_OF_MEMORY; } /* skip through argv, copying all arguments but skipping ones that * ought to be omitted */ for (from_i = to_i = 0; from[from_i]; from_i++) { if (str_equal("-D", from[from_i]) || str_equal("-I", from[from_i]) || str_equal("-U", from[from_i]) || str_equal("-L", from[from_i]) || str_equal("-l", from[from_i]) || str_equal("-MF", from[from_i]) || str_equal("-MT", from[from_i]) || str_equal("-MQ", from[from_i]) || str_equal("-include", from[from_i]) || str_equal("-imacros", from[from_i]) || str_equal("-iprefix", from[from_i]) || str_equal("-iwithprefix", from[from_i]) || str_equal("-isystem", from[from_i]) || str_equal("-iwithprefixbefore", from[from_i]) || str_equal("-idirafter", from[from_i])) { /* skip next word, being option argument */ if (from[from_i+1]) from_i++; } else if (str_startswith("-Wp,", from[from_i]) || str_startswith("-Wl,", from[from_i]) || str_startswith("-D", from[from_i]) || str_startswith("-U", from[from_i]) || str_startswith("-I", from[from_i]) || str_startswith("-l", from[from_i]) || str_startswith("-L", from[from_i]) || str_startswith("-MF", from[from_i]) || str_startswith("-MT", from[from_i]) || str_startswith("-MQ", from[from_i])) { /* Something like "-DNDEBUG" or * "-Wp,-MD,.deps/nsinstall.pp". Just skip this word */ ; } else if (str_equal("-undef", from[from_i]) || str_equal("-nostdinc", from[from_i]) || str_equal("-nostdinc++", from[from_i]) || str_equal("-MD", from[from_i]) || str_equal("-MMD", from[from_i]) || str_equal("-MG", from[from_i]) || str_equal("-MP", from[from_i])) { /* Options that only affect cpp; skip */ ; } else { to[to_i++] = from[from_i]; } } /* NULL-terminate */ to[to_i] = NULL; dcc_trace_argv("result", to); return 0; } /** * Remove "-o" options from argument list. * * This is used when running the preprocessor, when we just want it to write * to stdout, which is the default when no -o option is specified. * * Structurally similar to dcc_strip_local_args() **/ int dcc_strip_dasho(char **from, char ***out_argv) { char **to; int from_i, to_i; int from_len; from_len = dcc_argv_len(from); *out_argv = to = malloc((from_len + 1) * sizeof (char *)); if (!to) { rs_log_error("failed to allocate space for arguments"); return EXIT_OUT_OF_MEMORY; } /* skip through argv, copying all arguments but skipping ones that * ought to be omitted */ for (from_i = to_i = 0; from[from_i]; ) { if (!strcmp(from[from_i], "-o")) { /* skip "-o FILE" */ from_i += 2; } else if (str_startswith("-o", from[from_i])) { /* skip "-oFILE" */ from_i++; } else { to[to_i++] = from[from_i++]; } } /* NULL-terminate */ to[to_i] = NULL; dcc_trace_argv("result", to); return 0; } distcc-3.1/source/src/h_dotd.c0000640000175000017500000000407111115326640015333 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Test harness for dotd.c. **/ #include #include #include #include #include #include #include #include "dotd.h" #include "trace.h" #define USAGE \ "usage: h_dotd COMMAND ARGS...\n" \ "where\n" \ " COMMAND is dcc_get_dotd_info, ARGS is NAME\n" const char *rs_program_name = __FILE__; int main(int argc, char *argv[]) { rs_trace_set_level(RS_LOG_WARNING); if (argc < 2) { rs_log_error(USAGE); return 1; } if (strcmp(argv[1], "dcc_get_dotd_info") == 0) { char *dotd_fname; int needs_dotd, sets_dotd_target; char *dotd_target; dcc_get_dotd_info(argv + 2, &dotd_fname, &needs_dotd, &sets_dotd_target, &dotd_target); /* Print out in a format easily digested in Python. */ printf("{'dotd_fname':'%s', 'needs_dotd':%d, 'sets_dotd_target':%d," " 'dotd_target':'%s'}", dotd_fname, needs_dotd, sets_dotd_target, dotd_target ? dotd_target : "None"); } else { rs_log_error(USAGE); return 1; } return 0; } distcc-3.1/source/src/snprintf.h0000640000175000017500000000223111115326641015737 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- */ /* * Copyright Patrick Powell 1995 * This code is based on code written by Patrick Powell (papowell@astart.com) * It may be used for any purpose as long as this notice remains intact * on all source code distributions */ #include #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 distcc-3.1/source/src/mon-gnome.c0000640000175000017500000004663411115326641016002 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * @file * * Gnome 2.x monitor for distcc. * * For each slot we have a record in a tree model, including an array * indicating the past states. This is stored in the "history" column * of the TreeMode for that slot. * * The renderer knows how to walk over the queue and draw state * rectangles for the values it finds. The queue is implemented as a * circular array, whose values are initialized to idle. * * Starved jobs are currently not shown in the chart view. * * Colors should perhaps be customizable with reasonable defaults. */ /* FIXME: When the dialogs are dismissed, they seem to get destroyed. We need to make sure that they just get hidden and can be summoned again. */ /* last one using chart drawingarea is 1.43.2.37 */ #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_LOADAVG_H # include #endif #ifdef WITH_GNOME # include #endif #include #include "types.h" #include "distcc.h" #include "rpc.h" #include "trace.h" #include "exitcode.h" #include "mon.h" #include "renderer.h" const char *rs_program_name = "distccmon-gnome"; static GtkWidget *chart_treeview; static GtkListStore *chart_model; /* Note: these must match the types given in order in the call to gtk_list_store_new() */ enum { COLUMN_HOST, COLUMN_SLOT, COLUMN_FILE, COLUMN_STATE, COLUMN_HISTORY, }; /** * 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; } distcc-3.1/source/src/cpp.c0000640000175000017500000000643111115326640014656 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Run the preprocessor. Client-side only. **/ #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "implicit.h" #include "exec.h" /** * If the input filename is a plain source file rather than a * preprocessed source file, then preprocess it to a temporary file * and return the name in @p cpp_fname. * * The preprocessor may still be running when we return; you have to * wait for @p cpp_fid to exit before the output is complete. This * allows us to overlap opening the TCP socket, which probably doesn't * use many cycles, with running the preprocessor. **/ int dcc_cpp_maybe(char **argv, char *input_fname, char **cpp_fname, pid_t *cpp_pid) { char **cpp_argv; int ret; char *input_exten; const char *output_exten; *cpp_pid = 0; if (dcc_is_preprocessed(input_fname)) { /* TODO: Perhaps also consider the option that says not to use cpp. * Would anyone do that? */ rs_trace("input is already preprocessed"); /* already preprocessed, great. */ if (!(*cpp_fname = strdup(input_fname))) { rs_log_error("couldn't duplicate string"); return EXIT_OUT_OF_MEMORY; } return 0; } input_exten = dcc_find_extension(input_fname); output_exten = dcc_preproc_exten(input_exten); if ((ret = dcc_make_tmpnam("distcc", output_exten, cpp_fname))) return ret; /* We strip the -o option and allow cpp to write to stdout, which is * caught in a file. Sun cc doesn't understand -E -o, and gcc screws up * -MD -E -o. * * There is still a problem here with -MD -E -o, gcc writes dependencies * to a file determined by the source filename. We could fix it by * generating a -MF option, but that would break compilation with older * versions of gcc. This is only a problem for people who have the source * and objects in different directories, and who don't specify -MF. They * can fix it by specifying -MF. */ if ((ret = dcc_strip_dasho(argv, &cpp_argv)) || (ret = dcc_set_action_opt(cpp_argv, "-E"))) return ret; /* FIXME: cpp_argv is leaked */ return dcc_spawn_child(cpp_argv, cpp_pid, "/dev/null", *cpp_fname, NULL); } distcc-3.1/source/src/tempfile.c0000640000175000017500000002641711115326640015707 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "More computing sins are committed in the name of * efficiency (without necessarily achieving it) than * for any other single reason - including blind * stupidity." -- W.A. Wulf */ #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "snprintf.h" #include "exitcode.h" #ifdef __CYGWIN32__ #define NOGDI #include #endif /** * @file * * Routines for naming, generating and removing temporary files. * * Temporary files are stored under $TMPDIR or /tmp. * * From 2.10 on, our lock and state files are not stored in there. * * It would be nice if we could use a standard function, but I don't * think any of them are adequate: we need to control the extension * and know the filename. tmpfile() does not give back the filename. * tmpnam() is insecure. mkstemp() does not allow us to set the * extension. * * It sucks that there is no standard function. The implementation * below is inspired by the __gen_tempname() code in glibc; hopefully * it will be secure on all platforms. * * We need to touch the filename before running commands on it, * because we cannot be sure that the compiler will create it * securely. * * Even with all this, we are not necessarily secure in the presence * of a tmpreaper if the attacker can play timing tricks. However, * since we are not setuid and since there is no completely safe way * to write tmpreapers, this is left alone for now. * * If you're really paranoid, you should just use per-user TMPDIRs. * * @sa http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/avoid-race.html#TEMPORARY-FILES **/ /** * Create the directory @p path, and register it for deletion when this * compilation finished. If it already exists as a directory * we succeed, but we don't register the directory for deletion. **/ int dcc_mk_tmpdir(const char *path) { struct stat buf; int ret; if (stat(path, &buf) == -1) { if (mkdir(path, 0777) == -1) { return EXIT_IO_ERROR; } if ((ret = dcc_add_cleanup(path))) { /* bailing out */ rmdir(path); return ret; } } else { /* we could stat the file successfully; if it's a directory, * all is well, but we should not it delete later, since we did * not make it. */ if (S_ISDIR(buf.st_mode)) { return 0; } else { rs_log_error("mkdir '%s' failed: %s", path, strerror(errno)); return EXIT_IO_ERROR; } } return 0; } /** * Create the directory @p path. If it already exists as a directory * we succeed. **/ int dcc_mkdir(const char *path) { if ((mkdir(path, 0777) == -1) && (errno != EEXIST)) { rs_log_error("mkdir '%s' failed: %s", path, strerror(errno)); return EXIT_IO_ERROR; } return 0; } #ifndef HAVE_MKDTEMP static char* mkdtemp(char *pattern) { /* We could try this a few times if we wanted */ char* path = mktemp(pattern); if (path == NULL) return NULL; if (mkdir(path, 0700) == 0) return path; return NULL; } #endif /* This function creates a temporary directory, to be used for * all (input) files during one compilation. * The name of the directory is stored in @p tempdir, which is * malloc'ed here. The caller is responsible for freeing it. * The format of the directory name is /distccd_ * Returns the new temp dir in tempdir. */ int dcc_get_new_tmpdir(char **tempdir) { int ret; const char *tmp_top; char *s; if ((ret = dcc_get_tmp_top(&tmp_top))) { return ret; } if (asprintf(&s, "%s/distccd_XXXXXX", tmp_top) == -1) return EXIT_OUT_OF_MEMORY; if ((*tempdir = mkdtemp(s)) == 0) { return EXIT_IO_ERROR; } if ((ret = dcc_add_cleanup(s))) { /* bailing out */ rmdir(s); return ret; } return 0; } /* This function returns a directory-name, it does not end in a slash. */ int dcc_get_tmp_top(const char **p_ret) { #ifdef __CYGWIN32__ int ret; char *s = malloc(MAXPATHLEN+1); int f,ln; GetTempPath(MAXPATHLEN+1,s); /* Convert slashes */ for (f = 0, ln = strlen(s); f != ln; f++) if (s[f]=='\\') s[f]='/'; /* Delete trailing slashes -- but leave one slash if s is all slashes */ for (f = strlen(s)-1; f > 0 && s[f] == '/'; f--) s[f]='\0'; if ((ret = dcc_add_cleanup(s))) { free(s); return ret; } *p_ret = s; return 0; #else const char *d; d = getenv("TMPDIR"); if (!d || d[0] == '\0') { *p_ret = "/tmp"; return 0; } else { *p_ret = d; return 0; } #endif } /** * Create the full @path. If it already exists as a directory * we succeed. */ int dcc_mk_tmp_ancestor_dirs(const char *path) { char *copy = 0; char *p; int ret; copy = strdup(path); if (copy == NULL) { return EXIT_OUT_OF_MEMORY; } dcc_truncate_to_dirname(copy); if (copy[0] == '\0') { free(copy); return 0; } /* First, let's try and see if all parent directories * exist already */ if ((ret = dcc_mk_tmpdir(copy)) == 0) { free(copy); return 0; } /* This is the "pessimistic" algorithm for making directories, * which assumes that most directories that it's asked to create * do not exist. It's expensive for very deep directories; * it tries to make all the directories from the root to that * dir. However, it only gets called if we tried to make a dir * in a directory and failed; which means we only get called * once per directory. */ /* Body of this loop does not execute when *p=='\0'; * therefore the very last component of the directory does not * get created here. */ for (p = copy; *p != '\0'; ++p) { if (*p == '/' && p != copy) { *p = '\0'; if ((ret = dcc_mk_tmpdir(copy))) { free(copy); return ret; } *p = '/'; } } ret = dcc_mk_tmpdir(copy); free(copy); return ret; } /** * Return a static string holding DISTCC_DIR, or ~/.distcc. * The directory is created if it does not exist. **/ int dcc_get_top_dir(char **path_ret) { char *env; static char *cached; int ret; if (cached) { *path_ret = cached; return 0; } if ((env = getenv("DISTCC_DIR"))) { if ((cached = strdup(env)) == NULL) { return EXIT_OUT_OF_MEMORY; } else { *path_ret = cached; return 0; } } if ((env = getenv("HOME")) == NULL) { rs_log_warning("HOME is not set; can't find distcc directory"); return EXIT_BAD_ARGUMENTS; } if (asprintf(path_ret, "%s/.distcc", env) == -1) { rs_log_error("asprintf failed"); return EXIT_OUT_OF_MEMORY; } ret = dcc_mkdir(*path_ret); if (ret == 0) cached = *path_ret; return ret; } /** * Return a subdirectory of the DISTCC_DIR of the given name, making * sure that the directory exists. **/ int dcc_get_subdir(const char *name, char **dir_ret) { int ret; char *topdir; if ((ret = dcc_get_top_dir(&topdir))) return ret; if (asprintf(dir_ret, "%s/%s", topdir, name) == -1) { rs_log_error("asprintf failed"); return EXIT_OUT_OF_MEMORY; } return dcc_mkdir(*dir_ret); } int dcc_get_lock_dir(char **dir_ret) { static char *cached; int ret; if (cached) { *dir_ret = cached; return 0; } else { ret = dcc_get_subdir("lock", dir_ret); if (ret == 0) cached = *dir_ret; return ret; } } int dcc_get_state_dir(char **dir_ret) { static char *cached; int ret; if (cached) { *dir_ret = cached; return 0; } else { ret = dcc_get_subdir("state", dir_ret); if (ret == 0) cached = *dir_ret; return ret; } } /** * Create a file inside the temporary directory and register it for * later cleanup, and return its name. * * The file will be reopened later, possibly in a child. But we know * that it exists with appropriately tight permissions. **/ int dcc_make_tmpnam(const char *prefix, const char *suffix, char **name_ret) { char *s = NULL; const char *tempdir; int ret; unsigned long random_bits; int fd; if ((ret = dcc_get_tmp_top(&tempdir))) return ret; if (access(tempdir, W_OK|X_OK) == -1) { rs_log_error("can't use TMPDIR \"%s\": %s", tempdir, strerror(errno)); return EXIT_IO_ERROR; } random_bits = (unsigned long) getpid() << 16; # if HAVE_GETTIMEOFDAY { struct timeval tv; gettimeofday(&tv, NULL); random_bits ^= tv.tv_usec << 16; random_bits ^= tv.tv_sec; } # else random_bits ^= time(NULL); # endif #if 0 random_bits = 0; /* FOR TESTING */ #endif do { free(s); if (asprintf(&s, "%s/%s_%08lx%s", tempdir, prefix, random_bits & 0xffffffffUL, suffix) == -1) return EXIT_OUT_OF_MEMORY; /* Note that if the name already exists as a symlink, this * open call will fail. * * The permissions are tight because nobody but this process * and our children should do anything with it. */ fd = open(s, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd == -1) { /* try again */ rs_trace("failed to create %s: %s", s, strerror(errno)); random_bits += 7777; /* fairly prime */ continue; } if (close(fd) == -1) { /* huh? */ rs_log_warning("failed to close %s: %s", s, strerror(errno)); return EXIT_IO_ERROR; } break; } while (1); if ((ret = dcc_add_cleanup(s))) { /* bailing out */ unlink(s); free(s); return ret; } *name_ret = s; return 0; } distcc-3.1/source/src/zeroconf.c0000640000175000017500000004160211115326640015720 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright (C) 2007 Lennart Poettering * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "hosts.h" #include "zeroconf.h" #include "trace.h" #include "exitcode.h" /* How long shall the background daemon be idle before i terminates itself? */ #define MAX_IDLE_TIME 20 /* Maxium size of host file to load */ #define MAX_FILE_SIZE (1024*100) /* General daemon data */ struct daemon_data { struct host *hosts; int fd; int n_slots; AvahiClient *client; AvahiServiceBrowser *browser; AvahiSimplePoll *simple_poll; }; /* Zeroconf service wrapper */ struct host { struct daemon_data *daemon_data; struct host *next; AvahiIfIndex interface; AvahiProtocol protocol; char *service; char *domain; AvahiAddress address; uint16_t port; int n_cpus; AvahiServiceResolver *resolver; }; /* A generic, system independant lock routine, similar to sys_lock, * but more powerful: * rw: if non-zero: r/w lock instead of r/o lock * enable: lock or unlock * block: block when locking */ static int generic_lock(int fd, int rw, int enable, int block) { #if defined(F_SETLK) struct flock lockparam; lockparam.l_type = enable ? (rw ? F_WRLCK : F_RDLCK) : F_UNLCK; lockparam.l_whence = SEEK_SET; lockparam.l_start = 0; lockparam.l_len = 0; /* whole file */ return fcntl(fd, block ? F_SETLKW : F_SETLK, &lockparam); #elif defined(HAVE_FLOCK) return flock(fd, (enable ? (rw ? LOCK_EX : LOCK_SH) : LOCK_UN) | (block ? LOCK_NB : 0)); #elif defined(HAVE_LOCKF) return lockf(fd, (enable ? (block ? F_LOCK : F_TLOCK) : F_ULOCK)); #else # error "No supported lock method. Please port this code." #endif } /* Return the number of seconds, when the specified file was last * read. If the atime of that file is < clip_time, use clip_time * instead */ static time_t fd_last_used(int fd, time_t clip_time) { struct stat st; time_t now, ft; assert(fd >= 0); if (fstat(fd, &st) < 0) { rs_log_crit("fstat() failed: %s\n", strerror(errno)); return -1; } if ((now = time(NULL)) == (time_t) -1) { rs_log_crit("time() failed: %s\n", strerror(errno)); return -1; } ft = clip_time ? (st.st_atime < clip_time ? clip_time : st.st_atime) : st.st_atime; assert(ft <= now); return now - ft; } /* Write host data to host file */ static int write_hosts(struct daemon_data *d) { struct host *h; int r = 0; assert(d); rs_log_info("writing zeroconf data.\n"); if (generic_lock(d->fd, 1, 1, 1) < 0) { rs_log_crit("lock failed: %s\n", strerror(errno)); return -1; } if (lseek(d->fd, 0, SEEK_SET) < 0) { rs_log_crit("lseek() failed: %s\n", strerror(errno)); return -1; } if (ftruncate(d->fd, 0) < 0) { rs_log_crit("ftruncate() failed: %s\n", strerror(errno)); return -1; } for (h = d->hosts; h; h = h->next) { char t[256], a[AVAHI_ADDRESS_STR_MAX]; if (h->resolver) /* Not yet fully resolved */ continue; snprintf(t, sizeof(t), "%s:%u/%i\n", avahi_address_snprint(a, sizeof(a), &h->address), h->port, d->n_slots * h->n_cpus); if (dcc_writex(d->fd, t, strlen(t)) != 0) { rs_log_crit("write() failed: %s\n", strerror(errno)); goto finish; } } r = 0; finish: generic_lock(d->fd, 1, 0, 1); return r; }; /* Free host data */ static void free_host(struct host *h) { assert(h); if (h->resolver) avahi_service_resolver_free(h->resolver); free(h->service); free(h->domain); free(h); } /* Remove a service from the host list */ static void remove_service(struct daemon_data *d, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *domain) { struct host *h, *p = NULL; assert(d); for (h = d->hosts; h; h = h->next) { if (h->interface == interface && h->protocol == protocol && !strcmp(h->service, name) && avahi_domain_equal(h->domain, domain)) { if (p) p->next = h->next; else d->hosts = h->next; free_host(h); break; } else p = h; } } /* Called when a resolve call completes */ static void resolve_reply( AvahiServiceResolver *UNUSED(r), AvahiIfIndex UNUSED(interface), AvahiProtocol UNUSED(protocol), AvahiResolverEvent event, const char *name, const char *UNUSED(type), const char *UNUSED(domain), const char *UNUSED(host_name), const AvahiAddress *a, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags UNUSED(flags), void *userdata) { struct host *h = userdata; switch (event) { case AVAHI_RESOLVER_FOUND: { AvahiStringList *i; /* Look for the number of CPUs in TXT RRs */ for (i = txt; i; i = i->next) { char *key, *value; if (avahi_string_list_get_pair(i, &key, &value, NULL) < 0) continue; if (!strcmp(key, "cpus")) if ((h->n_cpus = atoi(value)) <= 0) h->n_cpus = 1; avahi_free(key); avahi_free(value); } h->address = *a; h->port = port; avahi_service_resolver_free(h->resolver); h->resolver = NULL; /* Write modified hosts file */ write_hosts(h->daemon_data); break; } case AVAHI_RESOLVER_FAILURE: rs_log_warning("Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(h->daemon_data->client))); free_host(h); break; } } /* Called whenever a new service is found or removed */ static void browse_reply( AvahiServiceBrowser *UNUSED(b), AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags UNUSED(flags), void *userdata) { struct daemon_data *d = userdata; assert(d); switch (event) { case AVAHI_BROWSER_NEW: { struct host *h; h = malloc(sizeof(struct host)); assert(h); rs_log_info("new service: %s\n", name); if (!(h->resolver = avahi_service_resolver_new(d->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_reply, h))) { rs_log_warning("Failed to create service resolver for '%s': %s\n", name, avahi_strerror(avahi_client_errno(d->client))); free(h); } else { /* Fill in missing data */ h->service = strdup(name); assert(h->service); h->domain = strdup(domain); assert(h->domain); h->daemon_data = d; h->interface = interface; h->protocol = protocol; h->next = d->hosts; h->n_cpus = 1; d->hosts = h; } break; } case AVAHI_BROWSER_REMOVE: rs_log_info("Removed service: %s\n", name); remove_service(d, interface, protocol, name, domain); write_hosts(d); break; case AVAHI_BROWSER_FAILURE: rs_log_crit("Service Browser failure '%s': %s\n", name, avahi_strerror(avahi_client_errno(d->client))); avahi_simple_poll_quit(d->simple_poll); break; case AVAHI_BROWSER_CACHE_EXHAUSTED: case AVAHI_BROWSER_ALL_FOR_NOW: ; } } static void client_callback(AvahiClient *client, AvahiClientState state, void *userdata) { struct daemon_data *d = userdata; switch (state) { case AVAHI_CLIENT_FAILURE: rs_log_crit("Client failure: %s\n", avahi_strerror(avahi_client_errno(client))); avahi_simple_poll_quit(d->simple_poll); break; case AVAHI_CLIENT_S_COLLISION: case AVAHI_CLIENT_S_REGISTERING: case AVAHI_CLIENT_S_RUNNING: case AVAHI_CLIENT_CONNECTING: ; } } /* The main function of the background daemon */ static int daemon_proc(const char *host_file, const char *lock_file, int n_slots) { int ret = 1; int lock_fd = -1; struct daemon_data d; time_t clip_time; int error; char machine[64], version[64], stype[128]; rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0); /* Prepare daemon data structure */ d.fd = -1; d.hosts = NULL; d.n_slots = n_slots; d.simple_poll = NULL; d.browser = NULL; d.client = NULL; clip_time = time(NULL); rs_log_info("Zeroconf daemon running.\n"); /* Open daemon lock file and lock it */ if ((lock_fd = open(lock_file, O_RDWR|O_CREAT, 0666)) < 0) { rs_log_crit("open('%s') failed: %s\n", lock_file, strerror(errno)); goto finish; } if (generic_lock(lock_fd, 1, 1, 0) < 0) { /* lock failed, there's probably already another daemon running */ goto finish; } /* Open host file */ if ((d.fd = open(host_file, O_RDWR|O_CREAT, 0666)) < 0) { rs_log_crit("open('%s') failed: %s\n", host_file, strerror(errno)); goto finish; } /* Clear host file */ write_hosts(&d); if (!(d.simple_poll = avahi_simple_poll_new())) { rs_log_crit("Failed to create simple poll object.\n"); goto finish; } if (!(d.client = avahi_client_new( avahi_simple_poll_get(d.simple_poll), 0, client_callback, &d, &error))) { rs_log_crit("Failed to create Avahi client object: %s\n", avahi_strerror(error)); goto finish; } if (dcc_get_gcc_version(version, sizeof(version)) && dcc_get_gcc_machine(machine, sizeof(machine))) { dcc_make_dnssd_subtype(stype, sizeof(stype), version, machine); } else { rs_log_warning("Warning, failed to get CC version and machine type.\n"); strncpy(stype, DCC_DNS_SERVICE_TYPE, sizeof(stype)); stype[sizeof(stype)-1] = 0; } rs_log_info("Browsing for '%s'.\n", stype); if (!(d.browser = avahi_service_browser_new( d.client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, stype, NULL, 0, browse_reply, &d))) { rs_log_crit("Failed to create service browser object: %s\n", avahi_strerror(avahi_client_errno(d.client))); goto finish; } /* Check whether the host file has been used recently */ while (fd_last_used(d.fd, clip_time) <= MAX_IDLE_TIME) { /* Iterate the main loop for 5s */ if (avahi_simple_poll_iterate(d.simple_poll, 5000) != 0) { rs_log_crit("Event loop exited abnormaly.\n"); goto finish; } } /* Wer are idle */ rs_log_info("Zeroconf daemon unused.\n"); ret = 0; finish: /* Cleanup */ if (lock_fd >= 0) { generic_lock(lock_fd, 1, 0, 0); close(lock_fd); } if (d.fd >= 0) close(d.fd); while (d.hosts) { struct host *h = d.hosts; d.hosts = d.hosts->next; free_host(h); } if (d.client) avahi_client_free(d.client); if (d.simple_poll) avahi_simple_poll_free(d.simple_poll); rs_log_info("zeroconf daemon ended.\n"); return ret; } /* Return path to the zeroconf directory in ~/.distcc */ static int get_zeroconf_dir(char **dir_ret) { static char *cached; int ret; if (cached) { *dir_ret = cached; return 0; } else { ret = dcc_get_subdir("zeroconf", dir_ret); if (ret == 0) cached = *dir_ret; return ret; } } /* Get the host list from zeroconf */ int dcc_zeroconf_add_hosts(struct dcc_hostdef **ret_list, int *ret_nhosts, int n_slots, struct dcc_hostdef **ret_prev) { char host_file[PATH_MAX], lock_file[PATH_MAX], *s = NULL; int lock_fd = -1, host_fd = -1; int fork_daemon = 0; int r = -1; char *dir; struct stat st; if (get_zeroconf_dir(&dir) != 0) { rs_log_crit("failed to get zeroconf dir.\n"); goto finish; } snprintf(lock_file, sizeof(lock_file), "%s/lock", dir); snprintf(host_file, sizeof(host_file), "%s/hosts", dir); /* Open lock file */ if ((lock_fd = open(lock_file, O_RDWR|O_CREAT, 0666)) < 0) { rs_log_crit("open('%s') failed: %s\n", lock_file, strerror(errno)); goto finish; } /* Try to lock the lock file */ if (generic_lock(lock_fd, 1, 1, 0) >= 0) { /* The lock succeeded => there's no daemon running yet! */ fork_daemon = 1; generic_lock(lock_fd, 1, 0, 0); } close(lock_fd); /* Shall we fork a new daemon? */ if (fork_daemon) { pid_t pid; rs_log_info("Spawning zeroconf daemon.\n"); if ((pid = fork()) == -1) { rs_log_crit("fork() failed: %s\n", strerror(errno)); goto finish; } else if (pid == 0) { int fd; /* Child */ /* Close file descriptors and replace them by /dev/null */ close(0); close(1); close(2); fd = open("/dev/null", O_RDWR); assert(fd == 0); fd = dup(0); assert(fd == 1); fd = dup(0); assert(fd == 2); #ifdef HAVE_SETSID setsid(); #endif chdir("/"); rs_add_logger(rs_logger_syslog, RS_LOG_DEBUG, NULL, 0); _exit(daemon_proc(host_file, lock_file, n_slots)); } /* Parent */ /* Wait some time for initial host gathering */ usleep(1000000); /* 1000 ms */ } /* Open host list read-only */ if ((host_fd = open(host_file, O_RDONLY)) < 0) { rs_log_crit("open('%s') failed: %s\n", host_file, strerror(errno)); goto finish; } /* A read lock */ if (generic_lock(host_fd, 0, 1, 1) < 0) { rs_log_crit("lock failed: %s\n", strerror(errno)); goto finish; } /* Get file size */ if (fstat(host_fd, &st) < 0) { rs_log_crit("stat() failed: %s\n", strerror(errno)); goto finish; } if (st.st_size >= MAX_FILE_SIZE) { rs_log_crit("file too large.\n"); goto finish; } /* read file data */ s = malloc((size_t) st.st_size+1); assert(s); if (dcc_readx(host_fd, s, (size_t) st.st_size) != 0) { rs_log_crit("failed to read from file.\n"); goto finish; } s[st.st_size] = 0; /* Parse host data */ if (dcc_parse_hosts(s, host_file, ret_list, ret_nhosts, ret_prev) != 0) { rs_log_crit("failed to parse host file.\n"); goto finish; } r = 0; finish: if (host_fd >= 0) { generic_lock(host_fd, 0, 0, 1); close(host_fd); } free(s); return r; } distcc-3.1/source/src/stringmap.c0000640000175000017500000001161611115326640016101 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include "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) { pos++; break; } } } result->map[n].value = strdup(buf); result->map[n].key = strdup(buf+pos); n++; } fclose(fp); return result; } const char *stringmap_lookup(const stringmap_t *map, const char *string) { int i, w; int len = strlen(string); int pos; for (pos=len-1, w=0; pos>0; pos--) { if (string[pos] == '/') { w++; if (w >= map->numFinalWordsToMatch) { pos++; break; } } } for (i=0; in; i++) { /*printf("Comparing %s and %s\n", map->map[i].key, string+pos);*/ if (!strcmp(map->map[i].key, string+pos)) return map->map[i].value; } return NULL; } #if 0 void dumpMap(stringmap_t *sm) { int i; printf("map has %d elements, and numFinalWordsToMatch is %d\n", sm->n, sm->numFinalWordsToMatch); for (i=0; i < sm->n; i++) { printf("row %d: key %s, value %s\n", i, sm->map[i].key, sm->map[i].value); } } #define verifyMap(sm, a, b) { \ const char *c = stringmap_lookup(sm, a); \ if (!b) \ assert(!c); \ else { \ assert(c); \ assert(!strcmp(b, c)); } } int main(int argc, char **argv) { FILE *fp; stringmap_t *sm; fp = fopen("stringmap_test.dat", "w"); fprintf(fp, "/foo/bar/bletch\n"); fclose(fp); sm = stringmap_load("stringmap_test.dat", 1); dumpMap(sm); verifyMap(sm, "/bar/bletch", "/foo/bar/bletch"); verifyMap(sm, "bletch", "/foo/bar/bletch"); verifyMap(sm, "/whatever/bletch", "/foo/bar/bletch"); verifyMap(sm, "baz", NULL); verifyMap(sm, "/foo/bar/bletch", "/foo/bar/bletch"); fp = fopen("stringmap_test.dat", "w"); fprintf(fp, "/usr/bin/gcc\n"); fprintf(fp, "/usr/bin/cc\n"); fclose(fp); sm = stringmap_load("stringmap_test.dat", 1); dumpMap(sm); verifyMap(sm, "/usr/bin/gcc", "/usr/bin/gcc"); verifyMap(sm, "/usr/bin/cc", "/usr/bin/cc"); verifyMap(sm, "gcc", "/usr/bin/gcc"); verifyMap(sm, "cc", "/usr/bin/cc"); verifyMap(sm, "g77", NULL); fp = fopen("stringmap_test.dat", "w"); fprintf(fp, "/usr/bin/i686-blah-blah/gcc\n"); fprintf(fp, "/usr/bin/i386-blah-blah/gcc\n"); fclose(fp); sm = stringmap_load("stringmap_test.dat", 2); dumpMap(sm); verifyMap(sm, "/usr/bin/i686-blah-blah/gcc", "/usr/bin/i686-blah-blah/gcc"); verifyMap(sm, "/usr/bin/i386-blah-blah/gcc", "/usr/bin/i386-blah-blah/gcc"); verifyMap(sm, "i686-blah-blah/gcc", "/usr/bin/i686-blah-blah/gcc"); verifyMap(sm, "i386-blah-blah/gcc", "/usr/bin/i386-blah-blah/gcc"); verifyMap(sm, "gcc", NULL); verifyMap(sm, "g77", NULL); return 0; } #endif distcc-3.1/source/src/trace.c0000640000175000017500000002445211115326640015175 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * ecolog - Reusable application logging library. * * Copyright (C) 2000 - 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* | Finality is death. | Perfection is finality. | Nothing is perfect. | There are lumps in it. */ #include #include #include #include #include #include #include #include #include #include "trace.h" #include "snprintf.h" #include "va_copy.h" struct rs_logger_list { rs_logger_fn *fn; void *private_ptr; int private_int; int max_level; struct rs_logger_list *next; }; static struct rs_logger_list *logger_list = NULL; int rs_trace_level = RS_LOG_NOTICE; #ifdef UNUSED /* nothing */ #elif defined(__GNUC__) # define UNUSED(x) x __attribute__((unused)) #elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define UNUSED(x) x #endif /* !__GNUC__ && !__LCLINT__ */ static void rs_log_va(int level, char const *fn, char const *fmt, va_list va); #if SIZEOF_SIZE_T > SIZEOF_LONG # warning size_t is larger than a long integer, values in trace messages may be wrong #endif /** * Log severity strings, if any. Must match ordering in * ::rs_loglevel. */ static const char *rs_severities[] = { "EMERGENCY! ", "ALERT! ", "CRITICAL! ", "ERROR: ", "Warning: ", "", "", "" }; /********************************************************************** * Functions for manipulating the list of loggers **********************************************************************/ void rs_remove_all_loggers(void) { struct rs_logger_list *l, *next; for (l = logger_list; l; l = next) { next = l -> next; /* save before destruction */ free(l); } logger_list = NULL; } void rs_add_logger(rs_logger_fn fn, int max_level, void *private_ptr, int private_int) { struct rs_logger_list *l; if ((l = malloc(sizeof *l)) == NULL) return; l->fn = fn; l->max_level = max_level; l->private_ptr = private_ptr; l->private_int = private_int; l->next = logger_list; logger_list = l; } /** * Remove only the logger that exactly matches the specified parameters **/ void rs_remove_logger(rs_logger_fn fn, int max_level, void *private_ptr, int private_int) { struct rs_logger_list *l, **pl; for (pl = &logger_list; *pl; pl = &((*pl)->next)) { l = *pl; if (l->fn == fn && l->max_level == max_level && l->private_ptr == private_ptr && l->private_int == private_int) { /* unhook from list by adjusting whoever points to this. */ *pl = l->next; free(l); return; } } } /** * Set the least important (i.e. largest) message severity that * will be output. */ void rs_trace_set_level(rs_loglevel level) { rs_trace_level = level; } /** * Work out a log level from a string name. * * Returns -1 for invalid names. */ int rs_loglevel_from_name(const char *name) { if (!strcmp(name, "emerg") || !strcmp(name, "emergency")) return RS_LOG_EMERG; else if (!strcmp(name, "alert")) return RS_LOG_ALERT; else if (!strcmp(name, "critical") || !strcmp(name, "crit")) return RS_LOG_CRIT; else if (!strcmp(name, "error") || !strcmp(name, "err")) return RS_LOG_ERR; else if (!strcmp(name, "warning") || !strcmp(name, "warn")) return RS_LOG_WARNING; else if (!strcmp(name, "notice") || !strcmp(name, "note")) return RS_LOG_NOTICE; else if (!strcmp(name, "info")) return RS_LOG_INFO; else if (!strcmp(name, "debug")) return RS_LOG_DEBUG; return -1; } /** * If you don't initialize a logger before first logging, then we * write to stderr by default. **/ static void rs_lazy_default(void) { static int called; if (called) return; called = 1; if (logger_list == NULL) rs_add_logger(rs_logger_file, RS_LOG_WARNING, NULL, STDERR_FILENO); } /* Heart of the matter */ static void rs_log_va(int flags, char const *caller_fn_name, char const *fmt, va_list va) { int level = flags & RS_LOG_PRIMASK; struct rs_logger_list *l; rs_lazy_default(); if (level <= rs_trace_level) for (l = logger_list; l; l = l->next) if (level <= l->max_level) { /* We need to use va_copy() here, because functions like vsprintf * may destructively modify their va_list argument, but we need * to ensure that it's still valid next time around the loop. */ va_list copied_va; VA_COPY(copied_va, va); l->fn(flags, caller_fn_name, fmt, copied_va, l->private_ptr, l->private_int); VA_COPY_END(copied_va); } } void rs_format_msg(char *buf, size_t buf_len, int flags, const char *fn, const char *fmt, va_list va) { unsigned level = flags & RS_LOG_PRIMASK; int len; const char *sv; *buf = '\0'; len = 0; if (!(flags & RS_LOG_NO_PROGRAM)) { strcpy(buf, rs_program_name); len = strlen(buf); } if (!(flags & RS_LOG_NO_PID)) { /* You might like to cache the pid, but that would cause trouble when we fork. */ sprintf(buf+len, "[%d] ", (int) getpid()); } else if (~flags & RS_LOG_NO_PROGRAM) { strcat(buf+len, ": "); } len = strlen(buf); if (!(flags & RS_LOG_NONAME) && fn) { sprintf(buf+len, "(%s) ", fn); len = strlen(buf); } sv = rs_severities[level]; if (*sv) { strcpy(buf + len, sv); len = strlen(buf); } vsnprintf(buf + len, buf_len - len, fmt, va); } /** * Called by a macro, used on platforms where we can't determine the * calling function name. */ void rs_log0_nofn(int level, char const *fmt, ...) { va_list va; va_start(va, fmt); rs_log_va(level, NULL, fmt, va); va_end(va); } void rs_log0(int level, char const *fn, char const *fmt, ...) { va_list va; va_start(va, fmt); rs_log_va(level, fn, fmt, va); va_end(va); } void rs_logger_syslog(int flags, const char *fn, char const *fmt, va_list va, void * UNUSED(private_ptr), int UNUSED(private_int)) { /* NOTE NO TRAILING NUL */ char buf[4090]; /* you're never going to want program or pid in a syslog message, * because it's redundant. */ rs_format_msg(buf, sizeof buf, flags | RS_LOG_NO_PROGRAM | RS_LOG_NO_PID, fn, fmt, va); syslog(flags & RS_LOG_PRIMASK, "%s", buf); } void rs_logger_file(int flags, const char *fn, char const *fmt, va_list va, void * UNUSED(private_ptr), int log_fd) { /* NOTE NO TRAILING NUL */ char buf[4090]; size_t len; 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)); } distcc-3.1/source/src/zeroconf-reg.c0000640000175000017500000002003111115326641016465 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright (C) 2007 Lennart Poettering * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "zeroconf.h" #include "trace.h" #include "exitcode.h" struct context { char *name; AvahiThreadedPoll *threaded_poll; AvahiClient *client; AvahiEntryGroup *group; uint16_t port; int n_cpus; }; static void publish_reply(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata); static void register_stuff(struct context *ctx) { if (!ctx->group) { if (!(ctx->group = avahi_entry_group_new(ctx->client, publish_reply, ctx))) { rs_log_crit("Failed to create entry group: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } } if (avahi_entry_group_is_empty(ctx->group)) { char cpus[32], machine[64] = "cc_machine=", version[64] = "cc_version=", *m, *v; snprintf(cpus, sizeof(cpus), "cpus=%i", ctx->n_cpus); v = dcc_get_gcc_version(version+11, sizeof(version)-11); m = dcc_get_gcc_machine(machine+11, sizeof(machine)-11); /* Register our service */ if (avahi_entry_group_add_service( ctx->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, ctx->name, DCC_DNS_SERVICE_TYPE, NULL, NULL, ctx->port, "txtvers=1", cpus, "distcc="PACKAGE_VERSION, "gnuhost="GNU_HOST, v ? version : NULL, m ? machine : NULL, NULL) < 0) { rs_log_crit("Failed to add service: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } if (v && m) { char stype[128]; dcc_make_dnssd_subtype(stype, sizeof(stype), v, m); if (avahi_entry_group_add_service_subtype( ctx->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, ctx->name, DCC_DNS_SERVICE_TYPE, NULL, stype) < 0) { rs_log_crit("Failed to add service: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } } else rs_log_warning("Failed to determine CC version, not registering DNS-SD service subtype!"); if (avahi_entry_group_commit(ctx->group) < 0) { rs_log_crit("Failed to commit entry group: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } } return; fail: avahi_threaded_poll_quit(ctx->threaded_poll); } /* Called when publishing of service data completes */ static void publish_reply(AvahiEntryGroup *UNUSED(g), AvahiEntryGroupState state, void *userdata) { struct context *ctx = userdata; switch (state) { case AVAHI_ENTRY_GROUP_COLLISION: { char *n; /* Pick a new name for our service */ n = avahi_alternative_service_name(ctx->name); assert(n); avahi_free(ctx->name); ctx->name = n; register_stuff(ctx); break; } case AVAHI_ENTRY_GROUP_FAILURE: rs_log_crit("Failed to register service: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); avahi_threaded_poll_quit(ctx->threaded_poll); break; case AVAHI_ENTRY_GROUP_UNCOMMITED: case AVAHI_ENTRY_GROUP_REGISTERING: case AVAHI_ENTRY_GROUP_ESTABLISHED: ; } } static void client_callback(AvahiClient *client, AvahiClientState state, void *userdata) { struct context *ctx = userdata; ctx->client = client; switch (state) { case AVAHI_CLIENT_S_RUNNING: register_stuff(ctx); break; case AVAHI_CLIENT_S_COLLISION: case AVAHI_CLIENT_S_REGISTERING: if (ctx->group) avahi_entry_group_reset(ctx->group); break; case AVAHI_CLIENT_FAILURE: if (avahi_client_errno(client) == AVAHI_ERR_DISCONNECTED) { int error; avahi_client_free(ctx->client); ctx->client = NULL; ctx->group = NULL; /* Reconnect to the server */ if (!(ctx->client = avahi_client_new( avahi_threaded_poll_get(ctx->threaded_poll), AVAHI_CLIENT_NO_FAIL, client_callback, ctx, &error))) { rs_log_crit("Failed to contact server: %s\n", avahi_strerror(error)); avahi_threaded_poll_quit(ctx->threaded_poll); } } else { rs_log_crit("Client failure: %s\n", avahi_strerror(avahi_client_errno(client))); avahi_threaded_poll_quit(ctx->threaded_poll); } break; case AVAHI_CLIENT_CONNECTING: ; } } /* register a distcc service in DNS-SD/mDNS with the given port and number of CPUs */ void* dcc_zeroconf_register(uint16_t port, int n_cpus) { struct context *ctx = NULL; char service[256] = "distcc@"; int error; ctx = malloc(sizeof(struct context)); assert(ctx); ctx->client = NULL; ctx->group = NULL; ctx->threaded_poll = NULL; ctx->port = port; ctx->n_cpus = n_cpus; /* Prepare service name */ gethostname(service+7, sizeof(service)-8); service[sizeof(service)-1] = 0; ctx->name = strdup(service); assert(ctx->name); if (!(ctx->threaded_poll = avahi_threaded_poll_new())) { rs_log_crit("Failed to create event loop object.\n"); goto fail; } if (!(ctx->client = avahi_client_new(avahi_threaded_poll_get(ctx->threaded_poll), AVAHI_CLIENT_NO_FAIL, client_callback, ctx, &error))) { rs_log_crit("Failed to create client object: %s\n", avahi_strerror(avahi_client_errno(ctx->client))); goto fail; } /* Create the mDNS event handler */ if (avahi_threaded_poll_start(ctx->threaded_poll) < 0) { rs_log_crit("Failed to create thread.\n"); goto fail; } return ctx; fail: if (ctx) dcc_zeroconf_unregister(ctx); return NULL; } /* Unregister this server from DNS-SD/mDNS */ int dcc_zeroconf_unregister(void *u) { struct context *ctx = u; if (ctx->threaded_poll) avahi_threaded_poll_stop(ctx->threaded_poll); if (ctx->client) avahi_client_free(ctx->client); if (ctx->threaded_poll) avahi_threaded_poll_free(ctx->threaded_poll); avahi_free(ctx->name); free(ctx); return 0; } distcc-3.1/source/src/exitcode.h0000640000175000017500000000460711115326641015711 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef _DISTCC_EXITCODE_H #define _DISTCC_EXITCODE_H /** * @file * * Common exit codes. **/ /** * Common exit codes for both client and server. * * These need to be in [1,255] so that they can be used as exit() codes. They * are fairly high so that they're not confused with the real error code from * gcc. * * WARNING: ANY CHANGES HERE NEED TO BE DUPLICATED IN THE MAN PAGE * (../man/distcc.1). **/ enum dcc_exitcode { EXIT_DISTCC_FAILED = 100, /**< General failure */ EXIT_BAD_ARGUMENTS = 101, EXIT_BIND_FAILED = 102, EXIT_CONNECT_FAILED = 103, EXIT_COMPILER_CRASHED = 104, EXIT_OUT_OF_MEMORY = 105, EXIT_BAD_HOSTSPEC = 106, EXIT_IO_ERROR = 107, EXIT_TRUNCATED = 108, EXIT_PROTOCOL_ERROR = 109, EXIT_COMPILER_MISSING = 110, /**< Compiler executable not found */ EXIT_RECURSION = 111, /**< distcc called itself */ EXIT_SETUID_FAILED = 112, /**< Failed to discard privileges */ EXIT_ACCESS_DENIED = 113, /**< Network access denied */ EXIT_BUSY = 114, /**< In use by another process. */ EXIT_NO_SUCH_FILE = 115, EXIT_NO_HOSTS = 116, EXIT_GONE = 117, /**< No longer relevant */ EXIT_TIMEOUT = 118 }; #endif /* _DISTCC_EXITCODE_H */ distcc-3.1/source/src/serve.c0000640000175000017500000006223511115326641015225 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* He who waits until circumstances completely favour * * his undertaking will never accomplish anything. * * -- Martin Luther */ /** * @file * * Actually serve remote requests. Called from daemon.c. * * @todo Make sure wait statuses are packed in a consistent format * (exit<<8 | signal). Is there any platform that doesn't do this? * * @todo The server should catch signals, and terminate the compiler process * group before handling them. * * @todo It might be nice to detect that the client has dropped the * connection, and then kill the compiler immediately. However, we probably * won't notice that until we try to do IO. SIGPIPE won't help because it's * not triggered until we try to do IO. I don't think it matters a lot, * though, because the client's not very likely to do that. The main case is * probably somebody getting bored and interrupting compilation. * * What might help is to select() on the network socket while we're waiting * for the child to complete, allowing SIGCHLD to interrupt the select() when * the child completes. However I'm not sure if it's really worth the trouble * of doing that just to handle a fairly marginal case. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SIGNAL_H # include #endif /* HAVE_SYS_SIGNAL_H */ #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "stats.h" #include "rpc.h" #include "exitcode.h" #include "snprintf.h" #include "dopt.h" #include "bulk.h" #include "exec.h" #include "srvnet.h" #include "hosts.h" #include "daemon.h" #include "stringmap.h" #include "dotd.h" #include "fix_debug_info.h" /** * 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 -MT at the end of the command line"); return 1; } /* the dotd_target is the argument of -MT */ *dotd_target = argv[i+1]; /* copy the next-next argument on top of this. */ for (; argv[i+2]; ++i) { argv[i] = argv[i+2]; } /* and then put the terminal null in. */ argv[i] = argv[i+2]; return 0; } /** * Add -MMD and -MF to get a .d file. * Find what the dotd target should be (if any). * Prepend @p root_dir to every command * line argument that refers to a file/dir by an absolute name. **/ static int tweak_arguments_for_server(char **argv, const char *root_dir, const char *deps_fname, char **dotd_target, char ***tweaked_argv) { int ret; *dotd_target = 0; if ((ret = dcc_copy_argv(argv, tweaked_argv, 3))) return 1; if ((ret = dcc_convert_mt_to_dotd_target(*tweaked_argv, dotd_target))) return 1; 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; } distcc-3.1/source/src/h_strip.c0000640000175000017500000000314511115326640015543 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_strip.c,v 1.4 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" const char *rs_program_name = __FILE__; /** * Test harness: determine whether a file is source, and is preprocessed. **/ int main(int argc, char *argv[]) { char **new_args; int ret; if (argc < 2) { rs_log_error("usage: %s ARGS...", argv[0]); return 1; } if ((ret = dcc_strip_local_args(argv + 1, &new_args))) { return ret; } printf("%s\n", dcc_argv_tostr(new_args)); return 0; } distcc-3.1/source/src/distcc.h0000640000175000017500000002372211115326641015355 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* distcc.h -- common internal-use header file */ #include #include /* for struct timeval */ #ifdef NORETURN /* nothing */ #elif defined(__GNUC__) # define NORETURN __attribute__((noreturn)) #elif defined(__LCLINT__) # define NORETURN /*@noreturn@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define NORETURN #endif /* !__GNUC__ && !__LCLINT__ */ #ifdef UNUSED /* nothing */ #elif defined(__GNUC__) # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) #elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define UNUSED(x) x #endif /* !__GNUC__ && !__LCLINT__ */ /* According to the gcc info page, __attribute__((unused)) means "this * variable is *possibly* unused" (emphasis added). So we can use it for * POSSIBLY_UNUSED. This macro is used when a variable is used in one #ifdef * case but not another, say. */ #ifdef POSSIBLY_UNUSED /* nothing */ #elif defined(__GNUC__) # define POSSIBLY_UNUSED(x) x __attribute__((unused)) #elif defined(__LCLINT__) # define POSSIBLY_UNUSED(x) /*@unused@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define POSSIBLY_UNUSED(x) x #endif /* !__GNUC__ && !__LCLINT__ */ #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) /* This works on Gentoo's (patched?) gcc 3.3.3 but not 3.2.3, and not Debian's * 3.3.4. It should be standard on 3.4. */ # define WARN_UNUSED __attribute__((warn_unused_result)) #else # define WARN_UNUSED #endif #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif struct dcc_hostdef; #include "state.h" enum dcc_compress { /* 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, struct dcc_hostdef **ret_prev); /* ncpu.c */ int dcc_ncpus(int *); /* ssh.c */ int dcc_ssh_connect(char *ssh_cmd, char *user, char *machine, char *path, int *f_in, int *f_out, pid_t *ssh_pid); /* safeguard.c */ int dcc_increment_safeguard(void); int dcc_recursion_safeguard(void); /* clirpc.c */ int dcc_x_req_header(int fd, enum dcc_protover protover); int dcc_x_argv(int fd, char **argv); int dcc_x_cwd(int fd); int dcc_is_link(const char *fname, int *is_link); int dcc_read_link(const char* fname, char *points_to); /* srvrpc.c */ int dcc_r_cwd(int ifd, char **cwd); /* remote.c */ int dcc_send_job_corked(int net_fd, char **argv, pid_t cpp_pid, int *status, const char *, const char *cpp_fname, struct dcc_hostdef *); int dcc_retrieve_results(int net_fd, int *status, const char *output_fname, const char *deps_fname, const char *server_stderr_fname, struct dcc_hostdef *); /* climasq.c */ int dcc_support_masquerade(char *argv[], char *progname, int *); /* backoff.c */ int dcc_enjoyed_host(const struct dcc_hostdef *host); int dcc_disliked_host(const struct dcc_hostdef *host); int dcc_remove_disliked(struct dcc_hostdef **hostlist); #define DISTCC_DEFAULT_PORT 3632 #define DISTCC_DEFAULT_STATS_ENABLED 0 #define DISTCC_DEFAULT_STATS_PORT 3633 #ifndef WAIT_ANY # define WAIT_ANY (-1) #endif /* If --enable-rfc2553 was given, then we will try to enable compile-time IPv6 * support. This means we must have a sockaddr_storage large enough to hold * IPv6 addresses. If not, we'll just use a plain sockaddr, which is more * likely to compile correctly. */ #ifdef ENABLE_RFC2553 # ifndef HAVE_SOCKADDR_STORAGE # error You can't use RFC2553 because you don't have a sockaddr_storage type # endif /* HAVE_SOCKADDR_STORAGE */ # define dcc_sockaddr_storage sockaddr_storage #else /* !ENABLE_RFC2553 */ # define dcc_sockaddr_storage sockaddr #endif /* !ENABLE_RFC2553 */ #ifndef O_BINARY # define O_BINARY 0 #endif void dcc_set_trace_from_env(void); /* compress.c */ int dcc_r_bulk_lzo1x(int outf_fd, int in_fd, unsigned in_len); int dcc_compress_file_lzo1x(int in_fd, size_t in_len, char **out_buf, size_t *out_len); int dcc_compress_lzo1x_alloc(const char *in_buf, size_t in_len, char **out_buf_ret, size_t *out_len_ret); /* bulk.c */ void dcc_calc_rate(off_t size_out, struct timeval *before, struct timeval *after, double *secs, double *rate); /* arg.c */ int dcc_set_action_opt(char **, const char *); int dcc_set_output(char **, char *); int dcc_set_input(char **, char *); int dcc_scan_args(char *argv[], /*@out@*/ /*@relnull@*/ char **orig_o, char **orig_i, char ***ret_newargv); int dcc_expand_preprocessor_options(char ***argv_ptr); /* argutil.c */ unsigned int dcc_argv_len(char **a); int dcc_argv_search(char **a, const char *); int dcc_copy_argv(char **argv, char ***out_argv, int extra_args); int dcc_argv_append(char **argv, char *toadd); char *dcc_argv_tostr(char **a); void dcc_free_argv(char **argv); /* tempfile.c */ int dcc_get_tempdir(const char **); int dcc_make_tmpnam(const char *, const char *suffix, char **); int dcc_get_new_tmpdir(char **tmpdir); int dcc_mk_tmpdir(const char *path); int dcc_mkdir(const char *path); int dcc_get_subdir(const char *name, char **path_ret) WARN_UNUSED; int dcc_get_lock_dir(char **path_ret) WARN_UNUSED; int dcc_get_state_dir(char **path_ret) WARN_UNUSED; int dcc_get_top_dir(char **path_ret) WARN_UNUSED; int dcc_get_tmp_top(const char **p_ret) WARN_UNUSED; int dcc_mk_tmp_ancestor_dirs(const char* file); /* cleanup.c */ void dcc_cleanup_tempfiles(void); void dcc_cleanup_tempfiles_from_signal_handler(void); int dcc_add_cleanup(const char *filename) WARN_UNUSED; /* strip.c */ int dcc_strip_local_args(char **from, char ***out_argv); int dcc_strip_dasho(char **from, char ***out_argv); /* cpp.c */ int dcc_cpp_maybe(char **argv, char *input_fname, char **cpp_fname, pid_t *cpp_pid); /* filename.c */ int dcc_is_source(const char *sfile); int dcc_is_preprocessed(const char *sfile); int dcc_is_object(const char *filename); int dcc_source_needs_local(const char *); char * dcc_find_extension(char *sfile); const char * dcc_find_extension_const(const char *sfile); int dcc_output_from_source(const char *sfile, const char *out_extn, char **ofile); const char * dcc_preproc_exten(const char *e); const char * dcc_find_basename(const char *sfile); void dcc_truncate_to_dirname(char *file); /* io.c */ int dcc_writex(int fd, const void *buf, size_t len); int dcc_r_token(int ifd, char *token); int dcc_readx(int fd, void *buf, size_t len); int dcc_pump_sendfile(int ofd, int ifd, size_t n); int dcc_r_str_alloc(int fd, unsigned len, char **buf); int tcp_cork_sock(int fd, int corked); int dcc_close(int fd); int dcc_want_mmap(void); int dcc_select_for_write(int fd, int timeout); int dcc_select_for_read(int fd, int timeout); /* loadfile.c */ int dcc_load_file_string(const char *filename, char **retbuf); extern const int dcc_connect_timeout, dcc_io_timeout; /* pump.c */ int dcc_r_bulk(int ofd, int ifd, unsigned f_size, enum dcc_compress compression); int dcc_pump_readwrite(int ofd, int ifd, size_t n); /* mapfile.c */ int dcc_map_input_file(int in_fd, off_t in_size, char **buf_ret); /* XXX: Kind of kludgy, we should do dynamic allocation. But this will do for * now. */ #ifndef MAXPATHLEN #define MAXPATHLEN 4096 #endif #ifndef WCOREDUMP # define WCOREDUMP(status) 0 #endif distcc-3.1/source/src/mon-notify.c0000640000175000017500000000662211115326641016176 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "rpc.h" #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "snprintf.h" #include "mon.h" #include "util.h" #include "netutil.h" static volatile int pipe_fd[2]; static void dcc_mon_siginfo_handler (int UNUSED (whatsig)) { /* Just ignore any errors. If people aren't listening or the pipe * is full, too bad. */ write (pipe_fd[1], "*", 1); } /* * Try to setup dnotify on the state directory. This returns the * descriptor of a pipe in @p dummy_fd. Every time the state changes, * a single byte is written to this pipe. A caller who select()s on * the pipe will therefore be woken every time there is a change. * * If we can do dnotify, create the dummy pipe and turn it on. * * @fixme One problem here is that if the state directory is deleted * and recreated, then we'll never notice and find the new one. I * don't know of any good fix, other than perhaps polling every so * often. So just don't do that. * * @fixme If this function is called repeatedly it will leak FDs. * * @todo Reimplement this on top of kevent for BSD. */ int dcc_mon_setup_notify (int *dummy_fd) { #ifdef F_NOTIFY char *state_dir; int ret; int fd; if (signal (SIGIO, dcc_mon_siginfo_handler) == SIG_ERR) { rs_log_error ("signal(SIGINFO) failed: %s", strerror(errno)); return EXIT_IO_ERROR; } if (pipe ((int *) pipe_fd) == -1) { rs_log_error ("pipe failed: %s", strerror (errno)); return EXIT_IO_ERROR; } *dummy_fd = pipe_fd[0]; /* read end */ dcc_set_nonblocking (pipe_fd[0]); dcc_set_nonblocking (pipe_fd[1]); if ((ret = dcc_get_state_dir (&state_dir))) return ret; if ((fd = open (state_dir, O_RDONLY)) == -1) { rs_log_error ("failed to open %s: %s", state_dir, strerror (errno)); free (state_dir); return EXIT_IO_ERROR; } /* CAUTION! Signals can start arriving immediately. Be ready. */ if (fcntl (fd, F_NOTIFY, DN_RENAME|DN_DELETE|DN_MULTISHOT) == -1) { rs_log_warning ("setting F_NOTIFY failed: %s", strerror (errno)); free (state_dir); return EXIT_IO_ERROR; } return 0; #else /* F_NOTIFY */ return EXIT_IO_ERROR; #endif /* F_NOTIFY */ } distcc-3.1/source/src/sendfile.c0000640000175000017500000001775511115326640015700 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2008 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "I've always wanted to use sendfile(), but * never had a reason until now" * -- mbp */ #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SENDFILE_H # include #endif /* !HAVE_SYS_SENDFILE_H */ #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /* * Could also use sendfilev() on Solaris >= 8: * * http://docs.sun.com/db/doc/816-0217/6m6nhtaps?a=view */ #ifdef HAVE_SENDFILE /* If you don't have it, just use dcc_pump_readwrite */ /** * sys_sendfile maps all the different implementations of sendfile() into * something like the Linux interface. * * Our sockets are never non-blocking, so that seems to me to say that * the kernel will never return EAGAIN -- we will always either send * the whole thing or get an error. Is that really true? * * How nice to have the function parameters reversed between platforms * in a way that will not give a compiler warning. * * @param offset offset in input to start writing; updated on return * to reflect the number of bytes sent. * * sys_sendfile returns the number of bytes sent, if transmission succeeded. * If there was an error, it returns -1 with errno set. It should never * return 0. **/ #if defined(__FreeBSD__) static ssize_t sys_sendfile(int ofd, int ifd, off_t *offset, size_t size) { off_t sent_bytes; int ret; /* According to the manual, this can never partially complete on a * socket open for blocking IO. */ ret = sendfile(ifd, ofd, *offset, size, 0, &sent_bytes, 0); if (ret == -1) { /* http://cvs.apache.org/viewcvs.cgi/apr/network_io/unix/sendrecv.c?rev=1.95&content-type=text/vnd.viewcvs-markup */ if (errno == EAGAIN) { if (sent_bytes == 0) { /* Didn't send anything. Return error with errno == EAGAIN. */ return -1; } else { /* We sent some bytes, but they we would block. Treat this as * success for now. */ *offset += sent_bytes; return sent_bytes; } } else { /* some other error */ return -1; } } else if (ret == 0) { *offset += size; return size; } else { rs_log_error("don't know how to handle return %d from BSD sendfile", ret); return -1; } } #elif defined(linux) static ssize_t sys_sendfile(int ofd, int ifd, off_t *offset, size_t size) { return sendfile(ofd, ifd, offset, size); } #elif defined(__hpux) || defined(__hpux__) /* HP cc in ANSI mode defines __hpux; gcc defines __hpux__ */ static ssize_t sys_sendfile(int ofd, int ifd, off_t *offset, size_t size) { ssize_t ret; ret = sendfile(ofd, ifd, *offset, size, NULL, 0); if (ret == -1) { return -1; } else if (ret > 0) { *offset += ret; return ret; } else { rs_log_error("don't know how to handle return %ld from HP-UX sendfile", (long) ret); return -1; } } #elif defined(__MACH__) && defined(__APPLE__) static ssize_t sys_sendfile(int ofd, int ifd, off_t *offset, size_t size) { off_t sent_bytes = size; int ret; ret = sendfile(ofd, ifd, *offset, &sent_bytes, NULL, 0); if (ret == -1) { if (errno == EAGAIN) { if (sent_bytes == 0) { /* Didn't send anything. Return error with errno == EAGAIN. */ return -1; } else { /* We sent some bytes, but they we would block. Treat this as * success for now. */ *offset += sent_bytes; return sent_bytes; } } else { /* some other error */ return -1; } } else if (ret == 0) { *offset += size; return size; } else { rs_log_error("don't know how to handle return %d from OS X sendfile", ret); return -1; } } #else /* Please write a sendfile implementation for your system! */ static ssize_t sys_sendfile(int UNUSED(ofd), int UNUSED(ifd), off_t *UNUSED(offset), size_t UNUSED(size)) { rs_log_warning("no sendfile implementation on this platform"); errno = ENOSYS; return -1; } #endif /* !(__FreeBSD__) && !def(linux) && ... */ /* * Transmit the body of a file using sendfile(). * * Linux at the moment requires the input be page-based -- ie a disk file, and * only on particular filesystems. If the sendfile() call fails in a way that * makes us think that regular IO might work, then we try that instead. For * example, the /tmp filesystem may not support sendfile(). */ int dcc_pump_sendfile(int ofd, int ifd, size_t size) { ssize_t sent; off_t offset = 0; int ret; while (size) { /* Handle possibility of partial transmission, e.g. if * sendfile() is interrupted by a signal. size is decremented * as we go. */ sent = sys_sendfile(ofd, ifd, &offset, size); if (sent == -1) { if (errno == EAGAIN) { /* Sleep until we're able to write out more data. */ if ((ret = dcc_select_for_write(ofd, dcc_io_timeout)) != 0) return ret; rs_trace("select() returned, continuing to write"); } else if (errno == EINTR) { rs_trace("sendfile() interrupted, continuing"); } else if (offset == 0) { /* The offset==0 tests is because we may be part way through * the file. We can't just naively go back to read/write * because sendfile() does not update the file pointer: we * would need to lseek() first. That case is not handled at * the moment because it's unlikely that sendfile() would * suddenly be unsupported while we're using it. A failure * halfway through probably indicates a genuine error. */ rs_log_info("decided to use read/write rather than sendfile"); return dcc_pump_readwrite(ofd, ifd, size); } else { rs_log_error("sendfile failed: %s", strerror(errno)); return EXIT_IO_ERROR; } } else if (sent == 0) { rs_log_error("sendfile returned 0? can't cope"); return EXIT_IO_ERROR; } else if (sent != (ssize_t) size) { /* offset is automatically updated by sendfile. */ size -= sent; rs_log_notice("sendfile: partial transmission of %ld bytes; retrying %ld @%ld", (long) sent, (long) size, (long) offset); } else { /* normal case, everything was sent. */ break; } } return 0; } #endif /* def HAVE_SENDFILE */ distcc-3.1/source/src/rslave.h0000640000175000017500000000451311115326641015375 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef rslave_H #define rslave_H /* don't blame me, I was in a hurry */ #include /* for pid_t */ /* maximum length of hostname */ #define rslave_HOSTLEN 200 /* Number of DNS slave processes. Emperically I've found that I need * for up to about 50 servers, you need 1 for main lookup plus two spares for retries; * for up to about 150 servers, you need 2 for main lookup plus a few spares for retries. * Six seems like it should be enough for most sites. */ #define rslave_NSLAVES 6 struct rslave_s { int nslaves; int pipeToSlaves[2]; int pipeFromSlaves[2]; pid_t pids[rslave_NSLAVES]; }; struct rslave_request_s { int id; char hname[rslave_HOSTLEN+1]; }; typedef struct rslave_request_s rslave_request_t; struct rslave_result_s { int id; int err; unsigned char addr[4]; }; typedef struct rslave_result_s rslave_result_t; int rslave_init(struct rslave_s *rslave); int rslave_gethostbyname(struct rslave_s *rslave, const char *hostname, int id); void rslave_request_init(struct rslave_request_s *buf, const char *hostname, int id); int rslave_readRequest(struct rslave_s *rslave, struct rslave_request_s *req); int rslave_writeRequest(struct rslave_s *rslave, const struct rslave_request_s *req); int rslave_writeResult(struct rslave_s *rslave, struct rslave_result_s *result); int rslave_readResult(struct rslave_s *rslave, struct rslave_result_s *result); int rslave_getfd_fromSlaves(struct rslave_s *rslave); int rslave_getfd_toSlaves(struct rslave_s *rslave); #endif distcc-3.1/source/src/prefork.c0000640000175000017500000001240411115326640015541 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* The dead cry out with joy when their books are reprinted */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "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; } distcc-3.1/source/src/arg.c0000640000175000017500000004473711115326640014660 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "I have a bone to pick, and a few to break." */ /** * @file * * Functions for understanding and manipulating argument vectors. * * The few options explicitly handled by the client are processed in its * main(). At the moment, this is just --help and --version, so this function * never has to worry about them. * * We recognize two basic forms "distcc gcc ..." and "distcc ...", with no * explicit compiler name. This second one is used if you have a Makefile * that can't manage two-word values for $CC; eventually it might support * putting a link to distcc on your path as 'gcc'. We call this second one an * implicit compiler. * * We need to distinguish the two by working out whether the first argument * "looks like" a compiler name or not. I think the two cases in which we * should assume it's implicit are "distcc -c hello.c" (starts with a 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 #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "snprintf.h" int dcc_argv_append(char **argv, char *toadd) { int l = dcc_argv_len(argv); argv[l] = toadd; argv[l+1] = NULL; /* just make sure */ return 0; } static void dcc_note_compiled(const char *input_file, const char *output_file) { const char *input_base, *output_base; input_base = dcc_find_basename(input_file); output_base = dcc_find_basename(output_file); rs_log(RS_LOG_INFO|RS_LOG_NONAME, "compile from %s to %s", input_base, output_base); } /** * Parse arguments, extract ones we care about, and also work out * whether it will be possible to distribute this invocation remotely. * * This is a little hard because the cc argument rules are pretty complex, but * the function still ought to be simpler than it already is. * * This code is called on both the client and the server, though they use the * results differently. * * This function makes a copy of the arguments, modified to ensure that * the arguments include '-o '. This is returned in *ret_newargv. * The copy is dynamically allocated and the caller is responsible for * deallocating it. * * @returns 0 if it's ok to distribute this compilation, or an error code. **/ int dcc_scan_args(char *argv[], char **input_file, char **output_file, char ***ret_newargv) { int seen_opt_c = 0, seen_opt_s = 0; int i; char *a; int ret; /* allow for -o foo.o */ if ((ret = dcc_copy_argv(argv, ret_newargv, 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 (!strncmp(a, "-MF", 3) || !strncmp(a, "-MT", 3) || !strncmp(a, "-MQ", 3)) { /* As above, without extra argument. */ } else if (a[1] == 'M') { /* -M(anything else) causes the preprocessor to produce a list of make-style dependencies on header files, either to stdout or to a local file. It implies -E, so only the preprocessor is run, not the compiler. There would be no point trying to distribute it even if we could. */ rs_trace("%s implies -E (maybe) and must be local", a); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-march=native")) { rs_trace("-march=native generates code for local machine; " "must be local"); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-mtune=native")) { rs_trace("-mtune=native optimizes for local machine; " "must be local"); return EXIT_DISTCC_FAILED; } else if (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 (str_startswith("-dr", a)) { rs_log_info("gcc's debug option %s may write extra files; " "running locally", a); return EXIT_DISTCC_FAILED; } else if (!strcmp(a, "-c")) { seen_opt_c = 1; } else if (!strcmp(a, "-o")) { /* Whatever follows must be the output */ a = argv[++i]; goto GOT_OUTPUT; } else if (str_startswith("-o", a)) { a += 2; /* skip "-o" */ goto GOT_OUTPUT; } } else { if (dcc_is_source(a)) { rs_trace("found input file \"%s\"", a); if (*input_file) { rs_log_info("do we have two inputs? i give up"); return EXIT_DISTCC_FAILED; } *input_file = a; } else if (str_endswith(".o", a)) { GOT_OUTPUT: rs_trace("found object/output file \"%s\"", a); if (*output_file) { rs_log_info("called for link? i give up"); return EXIT_DISTCC_FAILED; } *output_file = a; } } } /* TODO: ccache has the heuristic of ignoring arguments that are not * extant files when looking for the input file; that's possibly * 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; } /* Subroutine of dcc_expand_preprocessor_options(). * Calculate how many extra arguments we'll need to convert * a "-Wp,..." option into regular gcc options. * Returns the number of extra arguments needed. */ static int count_extra_args(char *dash_Wp_option) { int extra_args = 0; char *comma = dash_Wp_option + strlen("-Wp"); while (comma != NULL) { char *opt = comma + 1; comma = strchr(opt, ','); if (str_startswith("-MD,", opt) || str_startswith("-MMD,", opt)) { char *filename = comma + 1; comma = strchr(filename, ','); extra_args += 3; /* "-MD", "-MF", filename. */ } else { extra_args++; } } return extra_args; } /* Subroutine of dcc_expand_preprocessor_options(). * Convert a "-Wp,..." option into one or more regular gcc options. * Copy the resulting gcc options to dest_argv, which should be * pre-allocated by the caller. * Destructively modifies dash_Wp_option as it goes. * Returns 0 on success, nonzero for error (out of memory). */ static int copy_extra_args(char **dest_argv, char *dash_Wp_option, int extra_args) { int i = 0; char *comma = dash_Wp_option + strlen("-Wp"); while (comma != NULL) { char *opt = comma + 1; comma = strchr(opt, ','); if (comma) *comma = '\0'; dest_argv[i] = strdup(opt); if (!dest_argv[i]) return EXIT_OUT_OF_MEMORY; i++; if (strcmp(opt, "-MD") == 0 || strcmp(opt, "-MMD") == 0) { char *filename; if (!comma) { rs_log_warning("'-Wp,-MD' or '-Wp,-MMD' option is missing " "filename argument"); break; } filename = comma + 1; comma = strchr(filename, ','); if (comma) *comma = '\0'; dest_argv[i] = strdup("-MF"); if (!dest_argv[i]) return EXIT_OUT_OF_MEMORY; i++; dest_argv[i] = strdup(filename); if (!dest_argv[i]) return EXIT_OUT_OF_MEMORY; i++; } } assert(i == extra_args); return 0; } /* * Convert any "-Wp," options into regular gcc options. * We do this because it simplifies the command-line * option handling elsewhere; this is the only place * that needs to parse "-Wp," options. * Returns 0 on success, nonzero for error (out of memory). * * The argv array pointed to by argv_ptr when this function * is called must have been dynamically allocated. It remains * the caller's responsibility to deallocate it. */ int dcc_expand_preprocessor_options(char ***argv_ptr) { int i, j, ret; char **argv = *argv_ptr; char **new_argv; int argc = dcc_argv_len(argv); for (i = 0; argv[i]; i++) { if (str_startswith("-Wp,", argv[i])) { /* First, calculate how many extra arguments we'll need. */ int extra_args = count_extra_args(argv[i]); assert(extra_args >= 1); new_argv = calloc(argc + extra_args, sizeof(char *)); if (!new_argv) { return EXIT_OUT_OF_MEMORY; } for (j = 0; j < i; j++) { new_argv[j] = argv[j]; } if ((ret = copy_extra_args(new_argv + i, argv[i], extra_args)) != 0) { free(new_argv); return ret; } for (j = i + 1; j <= argc; j++) { new_argv[j + extra_args - 1] = argv[j]; } free(argv); *argv_ptr = argv = new_argv; } } return 0; } distcc-3.1/source/src/access.c0000640000175000017500000000660611115326640015341 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * They that forsake the law praise the wicked: but such * as keep the law contend with them. * -- Proverbs 28:4 */ #include #include #include #include #include #include #include #include #include "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; } } distcc-3.1/source/src/mon.c0000640000175000017500000002244511115326640014670 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "distcc.h" #include "rpc.h" #include "trace.h" #include "exitcode.h" #include "snprintf.h" #include "mon.h" #include "util.h" /** * @file * * Common routines for monitoring compiler state. * * Every time the client wants an update, it can call dcc_mon_poll(), * which returns a newly allocated list of all running processes. * * The list is returned sorted by hostname and then by slot, so tasks * will be more stable from one call to the next. **/ /* TODO: Shouldn't fail if the directory doesn't exist at the moment * it's called. */ /* * State files older than this are assumed to be leftovers from * compilers that died off. It's possible for a remote compilation to * take a very long time, and combined with the check that the process * exists we can allow this to be reasonably large. */ const int dcc_phase_max_age = 60; /** * Check if the state file @p fd is too old to be believed -- probably * because it was left over from a client that was killed. * * If so, close @p fd, unlink the file, and return EXIT_GONE. * * fd is closed on failure. **/ static int dcc_mon_kill_old(int fd, char *fullpath) { struct stat st; time_t now; /* Check if the file is old. */ if (fstat(fd, &st) == -1) { dcc_close(fd); rs_log_warning("error statting %s: %s", fullpath, strerror(errno)); return EXIT_IO_ERROR; } time(&now); /* Time you hear the siren / it's already too late */ if (now - st.st_mtime > dcc_phase_max_age) { dcc_close(fd); /* close first for windoze */ rs_trace("unlink %s", fullpath); if (unlink(fullpath) == -1) { rs_log_warning("unlink %s failed: %s", fullpath, strerror(errno)); return EXIT_IO_ERROR; } return EXIT_GONE; } return 0; } static int dcc_mon_read_state(int fd, char *fullpath, struct dcc_task_state *lp) { int nread; /* Don't use dcc_readx(), because not being able to read it is not * a big deal. */ nread = read(fd, lp, sizeof *lp); if (nread == -1) { rs_trace("failed to read state from %s: %s", fullpath, strerror(errno)); return EXIT_IO_ERROR; } else if (nread == 0) { /* empty file; just bad timing. */ return EXIT_IO_ERROR; } else if (nread != sizeof *lp) { rs_trace("short read getting state from %s", fullpath); return EXIT_IO_ERROR; } /* sanity-check some fields */ if (lp->magic != DCC_STATE_MAGIC) { rs_log_warning("wrong magic number: %s", fullpath); return EXIT_IO_ERROR; } if (lp->struct_size != sizeof (struct dcc_task_state)) { rs_log_warning("wrong structure size: %s: version mismatch?", fullpath); return EXIT_IO_ERROR; } lp->file[sizeof lp->file - 1] = '\0'; lp->host[sizeof lp->host - 1] = '\0'; if (lp->curr_phase > DCC_PHASE_DONE) { lp->curr_phase = DCC_PHASE_COMPILE; } lp->next = 0; return 0; } /** * Check that the process named by the file still exists; if not, * return EXIT_GONE. **/ static int dcc_mon_check_orphans(struct dcc_task_state *monl) { /* signal 0 just checks if it exists */ if (!kill(monl->cpid, 0)) { return 0; /* it's here */ } else if (errno == EPERM) { /* It's here, but it's not ours. Assume it's still a real * distcc process. */ return 0; } else if (errno == ESRCH) { return EXIT_GONE; /* no such pid */ } else { rs_log_warning("kill %ld, 0 failed: %s", (long) monl->cpid, strerror(errno)); return EXIT_GONE; } } /** * Read state. If loaded successfully, store a pointer to the newly * allocated structure into *ppl. */ static int dcc_mon_load_state(int fd, char *fullpath, struct dcc_task_state **ppl) { int ret; struct dcc_task_state *tl; tl = calloc(1, sizeof *tl); if (!tl) { rs_log_crit("failed to allocate dcc_task_state"); return EXIT_OUT_OF_MEMORY; } ret = dcc_mon_read_state(fd, fullpath, tl); if (ret) { dcc_task_state_free(tl); *ppl = NULL; return ret; } if (tl->curr_phase != DCC_PHASE_DONE) { ret = dcc_mon_check_orphans(tl); if (ret) { dcc_task_state_free(tl); *ppl = NULL; return ret; } } *ppl = tl; return ret; } /* Free the whole list */ int dcc_task_state_free(struct dcc_task_state *lp) { struct dcc_task_state *next; while (lp) { next = lp->next; /* save from clobbering */ free(lp); /* nothing dynamically allocated in them anymore */ lp = next; } return 0; } /** * Read in @p filename from inside @p dirname, and try to parse it as * a status file. * * If a new entry is read, a pointer to it is returned in @p lp. **/ static int dcc_mon_do_file(char *dirname, char *filename, struct dcc_task_state **lp) { int fd; char *fullpath; int ret; *lp = NULL; /* Is this a file we want to see */ if (!str_startswith(dcc_state_prefix, filename)) { /* rs_trace("skipped"); */ return 0; } 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; } distcc-3.1/source/src/lsdistcc.c0000640000175000017500000011310211115326640015676 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * lsdistcc -- A simple distcc server discovery program * Assumes all distcc servers are in DNS and are named distcc1...distccN. * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* Program to autodetect listening distcc servers by looking in DNS * for hosts named according to a given format. * hosts are considered good servers based solely on whether their * name fits the format and whether they are listening on the right port * (and optionally whether they respond when you send them a compile job). * Stops looking for servers after the first one it doesn't find in DNS. * Prints results to stdout. * Terminates with error status if no servers found. * * Examples: * * In your build script, add the lines * DISTCC_HOSTS=`lsdistcc` * export DISTCC_HOSTS * before the line that invokes make. * * Or, in your Makefile, add the lines * export DISTCC_HOSTS = $(shell lsdistcc) * * Changelog: * * Wed Jun 20 2007 - Manos Renieris, Google * Added -P option. * * Mon Jun 4 2007 - Manos Renieris, Google * Reformatted in 80 columns. * * Tue Jan 31 2006 - Dan Kegel, Google * Added -x option to list down hosts with ,down suffix (since * in sharded server cache mode, the hash space is partitioned * over all servers regardless of whether they're up or down at the moment) * * Thu Jan 5 2006 - Dan Kegel, Google * Actually read the output from the server and partially parse it. * * Sat Nov 26 2005 - Dan Kegel, Google * Added -l option, improved -v output * * Tue Nov 22 2005 - Dan Kegel & Dongmin Zhang, Google * added -pcc option to check that server actually responds when you send * it a job * added -c0 option to disable connect check * * Thu Oct 13 2005 - Dan Kegel, Google * use rslave to do asynchronous-ish hostname lookup, do all connects * in parallel * * Wed Oct 5 2005 - Dan Kegel, Google * Added -d, -m options * * Fri Sep 16 2005 - Dan Kegel, Google * Created * Added -v option --------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "clinet.h" #include "netutil.h" #include "util.h" #include "trace.h" #include "rslave.h" #include "../lzo/minilzo.h" /* Linux calls this setrlimit() argument NOFILE; bsd calls it OFILE */ #ifndef RLIMIT_NOFILE #define RLIMIT_NOFILE RLIMIT_OFILE #endif enum status_e { STATE_LOOKUP = 0, STATE_CONNECT, STATE_CONNECTING, STATE_READ_DONEPKT, STATE_READ_STATPKT, STATE_READ_REST, STATE_CLOSE, STATE_DONE}; struct state_s { rslave_request_t req; rslave_result_t res; struct timeval start; struct timeval deadline; char curhdrbuf[12]; int curhdrlen; enum status_e status; int ntries; int fd; int up; /* default is 0, set to 1 on success */ }; typedef struct state_s state_t; /* Default parameters */ #define DEFAULT_FORMAT "distcc%d" /* hostname format */ #define DEFAULT_PORT 3632 /* TCP port to connect to */ #define DEFAULT_PROTOCOL 1 /* protocol we'll try to speak */ #define DEFAULT_BIGTIMEOUT 7 /* max total runtime, seconds */ #define DEFAULT_DNSTIMEOUT_MS 500 /* individual DNS timeout, msec */ #define DEFAULT_CONNTIMEOUT_MS 900 /* individual connect timeout, msec */ #define DEFAULT_COMPTIMEOUT_MS 1500 /* individual compile timeout, msec (FIXME: should be lower) */ #define DEFAULT_OVERLAP 1 /* number of simultaneous DNS queries -1 */ #define DEFAULT_DNSGAP 0 /* number of missing hosts in DNS before we stop looking */ #define DEFAULT_COMPILER "none" char canned_query[1000]; size_t canned_query_len = 0; int opt_latency = 0; int opt_numeric = 0; int opt_overlap = DEFAULT_OVERLAP; int opt_dnsgap = DEFAULT_DNSGAP; int opt_port = DEFAULT_PORT; int opt_protocol = DEFAULT_PROTOCOL; int opt_bigtimeout_sec = DEFAULT_BIGTIMEOUT; int opt_conntimeout_ms = DEFAULT_CONNTIMEOUT_MS; int opt_comptimeout_ms = DEFAULT_COMPTIMEOUT_MS; int opt_dnstimeout_ms = DEFAULT_DNSTIMEOUT_MS; int opt_verbose = 0; int opt_domain = 0; int opt_match = 0; int opt_bang_down = 0; const char *opt_compiler = NULL; const char *protocol_suffix[] = { NULL, /* to make the rest 1-based */ "", ",lzo", ",lzo,cpp" }; #define MAXHOSTS 500 #define MAXTRIES 5 /* this constant can't be changed without changing some code */ #define MAXFDS (MAXHOSTS+2) /* just plain globals */ int fd2state[MAXHOSTS+1000]; /* kludge - fragile */ int nok; int ndone; /* globals used by other compilation units */ const char *rs_program_name = "lsdistcc"; /* Forward declarations (solely to prevent compiler warnings) */ void usage(void); int bitcompare(const unsigned char *a, const unsigned char *b, int nbits); void timeout_handler(int x); void get_thename(const char**sformat, const char *domain_name, int i, char *thename); int detect_distcc_servers(const char **argv, int argc, int opti, int bigtimeout, int dnstimeout, int matchbits, int overlap, int dnsgap); void server_read_packet_header(state_t *sp); void server_handle_event(state_t *sp); void usage(void) { printf("Usage: lsdistcc [-tTIMEOUT] [-mBITS] [-nvd] [format]\n\ Uses 'for i=1... sprintf(format, i)' to construct names of servers,\n\ stops after %d seconds or at second server that doesn't resolve,\n\ prints the names of all such servers listening on distcc's port.\n\ Default format is %s. \n\ If a list of host names are given in the command line,\n\ lsdistcc will only check those hosts. \n\ Options:\n\ -l Output latency in milliseconds after each hostname\n\ (not including DNS latency)\n\ -n Print IP address rather than name\n\ -x Append ,down to down hosts in host list\n\ -tTIMEOUT Set number of seconds to stop searching after [%d]\n\ -hHTIMEOUT Set number of milliseconds before retrying gethostbyname [%d]\n\ -cCTIMEOUT Set number of milliseconds before giving up on connect [%d]\n\ (0 to inhibit connect)\n\ -kKTIMEOUT Set number of milliseconds before giving up on compile [%d]\n\ (0 to inhibit compile)\n\ -mBITS Set number of bits of address that must match first host found [0]\n\ -oOVERLAP Set number of extra DNS requests to send [%d]\n\ -gDNSGAP Set number of missing DNS entries to tolerate [%d]\n\ -rPORT Port to connect to [%d]\n\ -PPROTOCOL Protocol version to use (1-3) [%d]\n\ -pCOMPILER Name of compiler to use [%s]\n\ -d Append DNS domain name to format\n\ -v Verbose\n\ \n\ Example:\n\ lsdistcc -l -p$COMPILER\n\ lsdistcc -p$COMPILER hosta somehost hostx hosty\n\ ", DEFAULT_BIGTIMEOUT, DEFAULT_FORMAT, DEFAULT_BIGTIMEOUT, DEFAULT_DNSTIMEOUT_MS, DEFAULT_CONNTIMEOUT_MS, DEFAULT_COMPTIMEOUT_MS, DEFAULT_OVERLAP, DEFAULT_DNSGAP, DEFAULT_PORT, DEFAULT_PROTOCOL, DEFAULT_COMPILER); exit(1); } /* Compare first nbits of a[] and b[] * If nbits is 1, only compares the MSB of a[0] and b[0] * Return 0 on equal, nonzero on nonequal */ int bitcompare(const unsigned char *a, const unsigned char *b, int nbits) { int fullbytes = nbits/8; int leftoverbits = nbits & 7; if (fullbytes) { int d = memcmp((char *)a, (char *)b, (size_t) fullbytes); if (d) return d; } if (leftoverbits) { int mask = 0; int i; for (i=0; i main() { assert(bitcompare("0", "0", 8) == 0); assert(bitcompare("0", "1", 8) != 0); assert(bitcompare("0", "1", 7) == 0); } #endif /* On timeout, silently terminate program */ void timeout_handler(int x) { (void) x; if (opt_verbose > 0) fprintf(stderr, "Timeout!\n"); /* FIXME: is it legal to call exit here? */ exit(0); } static void generate_query(void) { const char* program = "int foo(){return 0;}"; unsigned char lzod_program[1000]; unsigned char lzo_work_mem[LZO1X_1_MEM_COMPRESS]; lzo_uint lzod_program_len; lzo1x_1_compress((const unsigned char *)program, strlen(program), lzod_program, &lzod_program_len, lzo_work_mem); switch (opt_protocol) { case 1: { static const char canned_query_fmt_protocol_1[]= "DIST00000001" "ARGC00000005" "ARGV%08x%s" "ARGV00000002-c" "ARGV00000007hello.c" "ARGV00000002-o" "ARGV00000007hello.o" "DOTI%08x%s"; sprintf(canned_query, canned_query_fmt_protocol_1, (unsigned)strlen(opt_compiler), opt_compiler, (unsigned)strlen(program), program); canned_query_len = strlen(canned_query); break; } case 2: { static const char canned_query_fmt_protocol_2[]= "DIST00000002" "ARGC00000005" "ARGV%08x%s" "ARGV00000002-c" "ARGV00000007hello.c" "ARGV00000002-o" "ARGV00000007hello.o" "DOTI%08x"; sprintf(canned_query, canned_query_fmt_protocol_2, (unsigned)strlen(opt_compiler), opt_compiler, (unsigned)lzod_program_len); canned_query_len = strlen(canned_query) + lzod_program_len; memcpy(canned_query + strlen(canned_query), lzod_program, lzod_program_len); break; } case 3: { static const char canned_query_fmt_protocol_3[]= "DIST00000003" "CDIR00000001/" "ARGC00000005" "ARGV%08x%s" "ARGV00000002-c" "ARGV00000007hello.c" "ARGV00000002-o" "ARGV00000007hello.o" "NFIL00000001" "NAME00000008/hello.c" "FILE%08x"; sprintf(canned_query, canned_query_fmt_protocol_3, (unsigned)strlen(opt_compiler), opt_compiler, (unsigned)lzod_program_len); canned_query_len = strlen(canned_query) + lzod_program_len; memcpy(canned_query + strlen(canned_query), lzod_program, lzod_program_len); break; } } } /* Try reading a protocol packet header */ void server_read_packet_header(state_t *sp) { int arg; int nread; nread = read(sp->fd, sp->curhdrbuf + sp->curhdrlen, (size_t)(12 - sp->curhdrlen)); if (nread == 0) { /* A nonblocking read returning zero bytes means EOF. * FIXME: it may mean this only on the first read after poll said * bytes were ready, so beware of false EOFs here? */ if (opt_verbose > 0) fprintf(stderr, "lsdistcc: premature EOF while waiting for " "result from server %s\n", sp->req.hname); sp->status = STATE_CLOSE; return; } if (nread > 0) sp->curhdrlen += nread; if (sp->curhdrlen < 12) return; arg = (int)strtol(sp->curhdrbuf+4, NULL, 16); if (opt_verbose > 2) { int i; printf("Got hdr '%12.12s' = ", sp->curhdrbuf); for (i=0; i < sp->curhdrlen; i++) printf("%2x", sp->curhdrbuf[i]); printf("\n"); } /* Parse and validate the packet header, move on to next state */ switch (sp->status) { case STATE_READ_DONEPKT: if (memcmp(sp->curhdrbuf, "DONE", 4) != 0) { if (opt_verbose > 1) fprintf(stderr, "%s wrong protocol; expected DONE, got %4.4s!\n", sp->req.hname, sp->curhdrbuf); sp->status = STATE_CLOSE; break; } if (arg != opt_protocol) { if (opt_verbose > 1) fprintf(stderr, "%s wrong protocol, expected %d got %d!\n", sp->req.hname, opt_protocol, arg); sp->status = STATE_CLOSE; break; } /* No body to this type. Read next packet. */ sp->curhdrlen = 0; sp->status = STATE_READ_STATPKT; break; case STATE_READ_STATPKT: if (memcmp(sp->curhdrbuf, "STAT", 4) != 0) { if (opt_verbose > 1) fprintf(stderr, "%s wrong protocol! Expected STAT, got %4.4s\n", sp->req.hname, sp->curhdrbuf); sp->status = STATE_CLOSE; break; } if (arg != 0) { if (opt_verbose > 1) { /* FIXME: only conditional because my server uses load shedding */ fprintf(stderr, "lsdistcc: warning: test compile on %s failed! " "status 0x%x\n", sp->req.hname, arg); } sp->status = STATE_CLOSE; break; } /* No body to this type. Read next packet. */ sp->curhdrlen = 0; sp->status = STATE_READ_REST; break; default: fprintf(stderr, "bug\n"); exit(1); } } /* Grind state machine for a single server */ /* Take one transition through the state machine, unless that takes you to STATE_CLOSE, in which case go through that state too, into STATE_DONE */ void server_handle_event(state_t *sp) { struct timeval now; gettimeofday(&now, 0); do { struct sockaddr_in sa; if (opt_verbose > 2) fprintf(stderr, "now %ld %ld: server_handle_event: %s: state %d\n", now.tv_sec, (long) now.tv_usec/1000, sp->req.hname, sp->status); switch (sp->status) { case STATE_CONNECT: if (opt_conntimeout_ms == 0) { sp->fd = -1; sp->up = 1; sp->status = STATE_CLOSE; break; } /* Now do a nonblocking connect to that address */ memset(&sa, 0, sizeof sa); sa.sin_family = AF_INET; sa.sin_port = htons(opt_port); memcpy(&sa.sin_addr, sp->res.addr, 4); if ((sp->fd = socket(sa.sin_family, SOCK_STREAM, 0)) == -1) { fprintf(stderr, "failed to create socket: %s", strerror(errno)); sp->status = STATE_DONE; } else { dcc_set_nonblocking(sp->fd); /* start the nonblocking connect... */ if (opt_verbose > 0) fprintf(stderr, "now %ld %ld: Connecting to %s\n", now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); if (connect(sp->fd, (struct sockaddr *)&sa, sizeof(sa)) && errno != EINPROGRESS) { if (opt_verbose > 0) fprintf(stderr, "failed to connect socket: %s", strerror(errno)); sp->status = STATE_CLOSE; } else { sp->status = STATE_CONNECTING; fd2state[sp->fd] = sp->res.id; gettimeofday(&now, 0); sp->start = now; sp->deadline = now; sp->deadline.tv_usec += 1000 * opt_conntimeout_ms; sp->deadline.tv_sec += sp->deadline.tv_usec / 1000000; sp->deadline.tv_usec = sp->deadline.tv_usec % 1000000; } } break; case STATE_CONNECTING: { int connecterr; socklen_t len = sizeof(connecterr); int nsend; int nsent; if (getsockopt(sp->fd, SOL_SOCKET, SO_ERROR, (char *)&connecterr, &len) < 0) { fprintf(stderr, "getsockopt SO_ERROR failed?!"); sp->status = STATE_CLOSE; break; } if (connecterr) { if (opt_verbose > 0) fprintf(stderr, "now %ld %ld: Connecting to %s failed " "with errno %d = %s\n", now.tv_sec, (long) now.tv_usec/1000, sp->req.hname, connecterr, strerror(connecterr)); sp->status = STATE_CLOSE; /* not listening */ break; } if (opt_comptimeout_ms == 0 || !opt_compiler) { /* connect succeeded, don't need to compile */ sp->up = 1; sp->status = STATE_CLOSE; break; } if (opt_verbose > 0) fprintf(stderr, "now %ld %ld: %s: sending compile request\n", now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); nsend = canned_query_len; nsent = write(sp->fd, canned_query, nsend); if (nsent != nsend) { if (opt_verbose > 1) { if (nsent == -1) fprintf(stderr, "now %ld %ld: Sending to %s failed, " "errno %d\n", now.tv_sec, (long) 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, (long) now.tv_usec/1000, sp->req.hname, nsent, nsend); } /* ??? remote disconnect? Buffer too small? */ sp->status = STATE_CLOSE; break; } sp->status=STATE_READ_DONEPKT; sp->curhdrlen = 0; sp->deadline = now; sp->deadline.tv_usec += 1000 * opt_comptimeout_ms; sp->deadline.tv_sec += sp->deadline.tv_usec / 1000000; sp->deadline.tv_usec = sp->deadline.tv_usec % 1000000; } break; case STATE_READ_DONEPKT: case STATE_READ_STATPKT: server_read_packet_header(sp); break; case STATE_READ_REST: { char buf[1000]; int nread; nread = read(sp->fd, buf, sizeof(buf)); if (nread == 0) { /* A nonblocking read returning zero bytes means EOF. * FIXME: it may mean this only on the first read after * poll said bytes were ready, so beware of false EOFs here? */ sp->up = 1; sp->status = STATE_CLOSE; } } break; case STATE_CLOSE: if (sp->fd != -1) { close(sp->fd); sp->fd = -1; } if (opt_bang_down || sp->up) { if (opt_numeric) printf("%d.%d.%d.%d", sp->res.addr[0], sp->res.addr[1], sp->res.addr[2], sp->res.addr[3]); else printf("%s", sp->req.hname); if (opt_port != DEFAULT_PORT) printf(":%d", opt_port); printf("%s", protocol_suffix[opt_protocol]); if (opt_bang_down && !sp->up) printf(",down"); if (opt_latency) { int latency_ms; gettimeofday(&now, 0); latency_ms = (now.tv_usec - sp->start.tv_usec) / 1000 + 1000 * (now.tv_sec - sp->start.tv_sec); printf(" %d", latency_ms); } putchar('\n'); if (opt_verbose) fflush(stdout); } nok++; sp->status = STATE_DONE; ndone++; break; case STATE_DONE: ; default: ; } } while (sp->status == STATE_CLOSE); } /* A helper function for detecting all listening distcc servers: this * routine makes one pass through the poll() loop and analyzes what it * sees. */ static int one_poll_loop(struct rslave_s* rs, struct state_s states[], int start_state, int end_state, int nwithtries[], int* ngotaddr, int* nbaddns, unsigned char firstipaddr[4], int dnstimeout_usec, int matchbits, int overlap, int dnsgap) { int i; int nfds; struct state_s *sp; int nready; int found; struct timeval now; struct pollfd pollfds[MAXFDS]; /* See which sockets have any events */ nfds = 0; memset(pollfds, 0, sizeof(pollfds)); pollfds[nfds].fd = rslave_getfd_fromSlaves(rs); pollfds[nfds++].events = POLLIN; pollfds[nfds].fd = rslave_getfd_toSlaves(rs); /* Decide if we want to be notified if slaves are ready to handle * a DNS request. * To avoid sending too many DNS requests, we avoid sending more if * the number of first tries is greater than 'overlap' * or the number of outstanding DNS requests plus the number of * already satisfied ones would be greater than or equal to the max * number of hosts we're looking for. */ pollfds[nfds++].events = ((nwithtries[1] <= overlap) && (nwithtries[1]+ nwithtries[2]+ nwithtries[3]+ nwithtries[4]+ *ngotaddr < end_state)) ? POLLOUT : 0; /* Set interest bits. * When connecting, we want to know if we can write (aka if the * connect has finished); when waiting for a compile to finish, * we want to know if we can read. */ for (i=start_state; i<=end_state; i++) { switch (states[i].status) { case STATE_CONNECTING: pollfds[nfds].fd = states[i].fd; pollfds[nfds++].events = POLLOUT; break; case STATE_READ_DONEPKT: case STATE_READ_STATPKT: case STATE_READ_REST: pollfds[nfds].fd = states[i].fd; pollfds[nfds++].events = POLLIN; break; default: ; } } /* When polling, wait for no more than 50 milliseconds. * Anything lower doesn't help performance much. * Anything higher would inflate all our timeouts, * cause retries not to be sent as soon as they should, * and make the program take longer than it should. */ nready = poll(pollfds, (unsigned)nfds, 50); gettimeofday(&now, 0); /***** Check for timeout events *****/ sp = NULL; found = FALSE; for (i=start_state; i<=end_state; i++) { sp = &states[i]; if (sp->status == STATE_LOOKUP && sp->ntries > 0 && sp->ntries < MAXTRIES && (sp->deadline.tv_sec < now.tv_sec || (sp->deadline.tv_sec == now.tv_sec && sp->deadline.tv_usec < now.tv_usec))) { found = TRUE; nwithtries[sp->ntries]--; sp->ntries++; nwithtries[sp->ntries]++; if (opt_verbose > 0) fprintf(stderr, "now %ld %ld: Resending %s because " "deadline was %ld %ld\n", now.tv_sec, (long) now.tv_usec/1000, sp->req.hname, sp->deadline.tv_sec, (long) sp->deadline.tv_usec/1000); break; } if (sp->status == STATE_CONNECTING && (sp->deadline.tv_sec < now.tv_sec || (sp->deadline.tv_sec == now.tv_sec && sp->deadline.tv_usec < now.tv_usec))) { sp->status = STATE_CLOSE; server_handle_event(sp); if (opt_verbose > 0) fprintf(stderr, "now %ld %ld: %s timed out while connecting\n", now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); } if ((sp->status == STATE_READ_DONEPKT || sp->status == STATE_READ_STATPKT || sp->status == STATE_READ_REST) && (sp->deadline.tv_sec < now.tv_sec || (sp->deadline.tv_sec == now.tv_sec && sp->deadline.tv_usec < now.tv_usec))) { sp->status = STATE_CLOSE; server_handle_event(sp); if (opt_verbose > 0) fprintf(stderr, "now %ld %ld: %s timed out while compiling\n", now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); } } if (!found && (nwithtries[1] <= overlap) && (pollfds[1].revents & POLLOUT)) { /* Look for a fresh record to send */ for (i=start_state; i<=end_state; i++) { sp = &states[i]; if (sp->status == STATE_LOOKUP && sp->ntries == 0) { found = TRUE; nwithtries[sp->ntries]--; sp->ntries++; nwithtries[sp->ntries]++; break; } } } /* If we found a record to send or resend, send it, and mark its timeout. */ if (found) { if (opt_verbose) fprintf(stderr, "now %ld %ld: Looking up %s\n", now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); rslave_writeRequest(rs, &sp->req); sp->deadline = now; sp->deadline.tv_usec += dnstimeout_usec; sp->deadline.tv_sec += sp->deadline.tv_usec / 1000000; sp->deadline.tv_usec = sp->deadline.tv_usec % 1000000; } /***** Check poll results for DNS results *****/ if (pollfds[0].revents & POLLIN) { /* A reply is ready, huzzah! */ rslave_result_t result; if (rslave_readResult(rs, &result)) { printf("bug: can't read from pipe\n"); } else { /* Find the matching state_t, save the result, and mark it as done */ /* printf("result.id %d\n", result.id); fflush(stdout); */ assert(result.id >= start_state && result.id <= end_state); sp = &states[result.id]; if (sp->status == STATE_LOOKUP) { nwithtries[sp->ntries]--; sp->res = result; (*ngotaddr)++; if (matchbits > 0) { if (*ngotaddr == 1) { memcpy(firstipaddr, result.addr, 4); } else { /* break if new server on a 'different network' than first server */ if (bitcompare(firstipaddr, result.addr, matchbits)) result.err = -1; } } if (result.err) { if (opt_verbose) fprintf(stderr, "now %ld %ld: %s not found\n", now.tv_sec, (long) now.tv_usec/1000, sp->req.hname); sp->status = STATE_DONE; ndone++; (*nbaddns)++; if (*nbaddns > dnsgap) { int highest = 0; /* start no more lookups */ for (i=start_state; i <= end_state; i++) if (states[i].ntries > 0) highest = i; assert(highest <= end_state); if (opt_verbose && end_state != highest) fprintf(stderr, "Already searching up to host %d, " "won't search any higher\n", highest); end_state = highest; assert(end_state <= MAXHOSTS); } } else { sp->status = STATE_CONNECT; server_handle_event(sp); } } } } /***** Grind state machine for each remote server *****/ for (i=2; i rlim.rlim_max) rlim.rlim_cur = rlim.rlim_max; setrlimit(RLIMIT_NOFILE, &rlim); getrlimit(RLIMIT_NOFILE, &rlim); if (rlim.rlim_cur > 14) maxfds = (int)(rlim.rlim_cur - 10); } /* Don't run longer than bigtimeout seconds */ signal(SIGALRM, timeout_handler); alarm((unsigned) bigtimeout); if (rslave_init(&rs)) return 0; ngotaddr = 0; memset(nwithtries, 0, sizeof(nwithtries)); memset(states, 0, sizeof(states)); /* all hosts start off in state 'sent 0' */ for (i=1; i<=n; i++) { rslave_request_t *req = &states[i].req; get_thename(sformat, domain_name, i, thename); rslave_request_init(req, thename, i); states[i].status = STATE_LOOKUP; states[i].ntries = 0; nwithtries[0]++; } ndone = 0; nok = 0; nbaddns = 0; /* Loop until we're done finding distcc servers. We have to do * this loop in groups, with each group using no more than maxfds * fd's. One call to one_poll_loop uses n + 2 fds. */ for (start_state = 1; start_state <= n; start_state = end_state + 1) { int orig_end_state; end_state = start_state + maxfds-2; if (end_state > n) end_state = n; orig_end_state = end_state; while (ndone < end_state) { end_state = one_poll_loop(&rs, states, start_state, end_state, nwithtries, &ngotaddr, &nbaddns, firstipaddr, dnstimeout_usec, matchbits, overlap, dnsgap); } if (end_state < orig_end_state) { /* If we lowered end_state, it means we decided to stop * searching early. */ break; } } return nok; } int main(int argc, char **argv) { int opti; int nfound; for (opti = 1; opti < argc && argv[opti][0] == '-'; opti++) { switch (argv[opti][1]) { case 'm': opt_match = atoi(argv[opti]+2); if (opt_match > 31 || opt_match < 0) usage(); break; case 't': opt_bigtimeout_sec = atoi(argv[opti]+2); if (opt_bigtimeout_sec < 0) usage(); break; case 'h': opt_dnstimeout_ms = atoi(argv[opti]+2); if (opt_dnstimeout_ms < 0) usage(); break; case 'c': opt_conntimeout_ms = atoi(argv[opti]+2); if (opt_conntimeout_ms < 0) usage(); break; case 'k': opt_comptimeout_ms = atoi(argv[opti]+2); if (opt_comptimeout_ms < 0) usage(); break; case 'o': opt_overlap = atoi(argv[opti]+2); if (opt_overlap < 0) usage(); break; case 'g': opt_dnsgap = atoi(argv[opti]+2); if (opt_dnsgap < 0) usage(); break; case 'P': opt_protocol = atoi(argv[opti]+2); if (opt_protocol <= 0 || opt_protocol > 3) { usage(); } break; case 'p': opt_compiler = argv[opti]+2; if (! *opt_compiler) usage(); break; case 'r': opt_port = atoi(argv[opti]+2); if (opt_port <= 0) usage(); break; case 'l': opt_latency = 1; break; case 'n': opt_numeric = 1; break; case 'x': opt_bang_down = 1; break; case 'v': opt_verbose++; break; case 'd': opt_domain++; break; default: usage(); } } if (opt_compiler) generate_query(); nfound = detect_distcc_servers((const char **)argv, argc, opti, opt_bigtimeout_sec, opt_dnstimeout_ms, opt_match, opt_overlap, opt_dnsgap); /* return failure if no servers found */ return (nfound > 0) ? 0 : 1; } distcc-3.1/source/src/clirpc.c0000640000175000017500000001737511115326641015362 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exec.h" #include "rpc.h" #include "exitcode.h" #include "util.h" #include "clinet.h" #include "bulk.h" #include "hosts.h" #include "state.h" #include "include_server_if.h" #include "emaillog.h" /** * @file * * @brief Client-side RPC functions. **/ /* * Transmit header for whole request. */ int dcc_x_req_header(int fd, enum dcc_protover protover) { return dcc_x_token_int(fd, "DIST", protover); } /** * Transmit an argv 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))) rs_log_error("server provided no answer. " "Is the server configured to allow access from your IP" " address? Does the server have the compiler installed?" " Is the server configured to access the compiler?"); return ret; if (vers != expect_ver) { rs_log_error("got version %d not %d in response from server", vers, expect_ver); return EXIT_PROTOCOL_ERROR; } rs_trace("got response header"); return 0; } int dcc_r_cc_status(int ifd, int *status) { unsigned u_status; int ret; ret = dcc_r_token_int(ifd, "STAT", &u_status); *status = u_status; return ret; } /** * The second half of the client protocol: retrieve all results from the server. **/ int dcc_retrieve_results(int net_fd, int *status, const char *output_fname, const char *deps_fname, const char *server_stderr_fname, struct dcc_hostdef *host) { unsigned len; int ret; unsigned o_len; if ((ret = dcc_r_result_header(net_fd, host->protover))) return ret; /* We've started to see the response, so the server is done * compiling. */ dcc_note_state(DCC_PHASE_RECEIVE, NULL, NULL); if ((ret = dcc_r_cc_status(net_fd, status))) return ret; if ((ret = dcc_r_token_int(net_fd, "SERR", &len))) return ret; /* Save the server-side errors into a file. This way, we can decide later whether we want to report them to the user or not. We don't want to report them to the user if we are going to redo the compilation locally, because then the local errors are going to appear. Always put the server-side errors in the email we will send to the maintainers, though. */ if ((ret = dcc_r_file(net_fd, server_stderr_fname, len, host->compr))) return ret; if (dcc_add_file_to_log_email("server-side stderr", server_stderr_fname)) return ret; if ((ret = dcc_r_token_int(net_fd, "SOUT", &len)) || (ret = dcc_r_bulk(STDOUT_FILENO, net_fd, len, host->compr)) || (ret = dcc_r_token_int(net_fd, "DOTO", &o_len))) return ret; /* If the compiler succeeded, then we always retrieve the result, * even if it's 0 bytes. */ if (*status == 0) { if ((ret = dcc_r_file_timed(net_fd, output_fname, o_len, host->compr))) return ret; if (host->cpp_where == DCC_CPP_ON_SERVER) { if ((ret = dcc_r_token_int(net_fd, "DOTD", &len) == 0) && deps_fname != NULL) { ret = dcc_r_file_timed(net_fd, deps_fname, len, host->compr); return ret; } } } else if (o_len != 0) { rs_log_error("remote compiler failed but also returned output: " "I don't know what to do"); } return 0; } /* points_to must be at least MAXPATHLEN + 1 long */ int dcc_read_link(const char* fname, char *points_to) { int len; if ((len = readlink(fname, points_to, MAXPATHLEN)) == -1) { rs_log_error("readlink '%s' failed: %s", fname, strerror(errno)); return EXIT_IO_ERROR; } points_to[len] = '\0'; return 0; } int dcc_is_link(const char *fname, int *is_link) { struct stat buf; if (lstat(fname, &buf) == -1) { rs_log_error("stat '%s' failed: %s", fname, strerror(errno)); return EXIT_IO_ERROR; } *is_link = S_ISLNK(buf.st_mode); return 0; } /* Send to @p ofd @p n_files whose names are in @p fnames. * @fnames must be null-terminated. * The names can be coming from the include server, so * we consult dcc_get_original_fname to get the real names. * Always uses lzo compression. */ /* TODO: This code is highly specific to DCC_VER_3; it assumes lzo compression is on, and that the include server has actually compressed the files. */ int dcc_x_many_files(int ofd, unsigned int n_files, char **fnames) { int ret; char link_points_to[MAXPATHLEN + 1]; int is_link; const char *fname; char *original_fname; dcc_x_token_int(ofd, "NFIL", n_files); for (; *fnames != NULL; ++fnames) { fname = *fnames; ret = dcc_get_original_fname(fname, &original_fname); if (ret) return ret; if ((ret = dcc_is_link(fname, &is_link))) { return ret; } if (is_link) { if ((ret = dcc_read_link(fname, link_points_to)) || (ret = dcc_x_token_string(ofd, "NAME", original_fname)) || (ret = dcc_x_token_string(ofd, "LINK", link_points_to))) { return ret; } } else { ret = dcc_x_token_string(ofd, "NAME", original_fname); if (ret) return ret; /* File should be compressed already. If we ever support non-compressed server-side-cpp, we should have some checks here and then uncompress the file if it is compressed. */ ret = dcc_x_file(ofd, fname, "FILE", DCC_COMPRESS_NONE, NULL); if (ret) return ret; } } return 0; } distcc-3.1/source/src/types.h0000640000175000017500000000244111115326641015243 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #ifndef HAVE_IN_PORT_T #define HAVE_IN_PORT_T typedef int in_port_t; #endif #ifndef HAVE_IN_ADDR_T /* Seems to be equivalent to ulong on FreeBSD 3.3, where it is missing. * http://www.freebsd.org/cgi/man.cgi?query=inet_aton&apropos=0&sektion=0&manpath=FreeBSD+3.3-RELEASE&format=html * * On Linux it is uint32. */ #define HAVE_IN_ADDR_T typedef unsigned long in_addr_t; #endif distcc-3.1/source/src/remote.c0000640000175000017500000002403711115326640015371 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * Send a compilation request to a remote server. */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "rpc.h" #include "exitcode.h" #include "util.h" #include "clinet.h" #include "hosts.h" #include "exec.h" #include "lock.h" #include "compile.h" #include "bulk.h" /* * 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 local_cpu_lock_fd If != -1, file descriptor for the lock file. * Should be != -1 iff (host->cpp_where != DCC_CPP_ON_SERVER). * If != -1, the lock must be held on entry to this function, * and THIS FUNCTION WILL RELEASE THE LOCK. * * @param host Definition of host to send this job to. * * @param status on return contains the wait-status of the remote * compiler. * * Returns 0 on success, otherwise error. Returning nonzero does not * necessarily imply the remote compiler itself succeeded, only that * there were no communications problems. * * TODO: consider refactoring this (perhaps as two separate subroutines?) * to avoid the need for releasing the lock as a side effect of this call. */ int dcc_compile_remote(char **argv, char *input_fname, char *cpp_fname, char **files, char *output_fname, char *deps_fname, char *server_stderr_fname, pid_t cpp_pid, int local_cpu_lock_fd, struct dcc_hostdef *host, int *status) { int to_net_fd = -1, from_net_fd = -1; int ret; pid_t ssh_pid = 0; int ssh_status; off_t doti_size; struct timeval before, after; unsigned int n_files; if (gettimeofday(&before, NULL)) rs_log_warning("gettimeofday failed"); dcc_note_execution(host, argv); dcc_note_state(DCC_PHASE_CONNECT, input_fname, host->hostname); /* 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 with local preprocessing. Unlock to allow someone * else to start preprocessing. */ if (local_cpu_lock_fd != -1) { dcc_unlock(local_cpu_lock_fd); local_cpu_lock_fd = -1; } if (*status != 0) goto out; if ((ret = dcc_x_file(to_net_fd, cpp_fname, "DOTI", host->compr, &doti_size))) goto out; } rs_trace("client finished sending request to server"); tcp_cork_sock(to_net_fd, 0); /* but it might not have been read in by the server yet; there's * 100kB or more of buffers in the two kernels. */ /* OK, now all of the source has at least made it into the * client's TCP transmission queue, sometime soon the server will * start compiling it. */ dcc_note_state(DCC_PHASE_COMPILE, NULL, host->hostname); /* If cpp failed, just abandon the connection, without trying to * receive results. */ if (ret == 0 && *status == 0) { ret = dcc_retrieve_results(from_net_fd, status, output_fname, deps_fname, server_stderr_fname, host); } if (gettimeofday(&after, NULL)) { rs_log_warning("gettimeofday failed"); } else if (host->cpp_where == DCC_CPP_ON_CLIENT) { double secs, rate; dcc_calc_rate(doti_size, &before, &after, &secs, &rate); rs_log(RS_LOG_INFO|RS_LOG_NONAME, "%lu bytes from %s compiled on %s in %.4fs, rate %.0fkB/s", (unsigned long) doti_size, input_fname, host->hostname, secs, rate); } out: if (local_cpu_lock_fd != -1) { dcc_unlock(local_cpu_lock_fd); local_cpu_lock_fd = -1; /* Not really needed; just for consistency. */ } /* Close socket so that the server can terminate, rather than * making it wait until we've finished our work. */ if (to_net_fd != from_net_fd) { if (to_net_fd != -1) dcc_close(to_net_fd); } if (from_net_fd != -1) dcc_close(from_net_fd); /* Collect the SSH child. Strictly this is unnecessary; it might slow the * client down a little when things could otherwise be proceeding in the * background. But it helps make sure that we don't assume we succeeded * when something possibly went wrong, and it allows us to account for the * cost of the ssh child. */ if (ssh_pid) { dcc_collect_child("ssh", ssh_pid, &ssh_status, timeout_null_fd); /* ignore failure */ } return ret; } distcc-3.1/source/src/srvnet.h0000640000175000017500000000215411115326640015420 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* srvnet.c */ int dcc_socket_listen(int port, int *fd, const char *listen_addr); int is_a_socket(int fd); struct dcc_allow_list; int dcc_check_client(struct sockaddr *, int, struct dcc_allow_list *); distcc-3.1/source/src/help.c0000640000175000017500000000470111115326641015023 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * Tell me what you need, and I'll tell you how to * get along without it. -- Dilbert */ #include #include #include #include #include #include #include "distcc.h" #include "trace.h" int dcc_trace_version(void) { rs_trace("%s %s %s; built %s %s", rs_program_name, PACKAGE_VERSION, GNU_HOST, __DATE__, __TIME__); return 0; } int dcc_show_version(const char *prog) { /* The "built" message is the time this file was built, which may not be * completely accurate for the program as a whole unless you do "make * clean". * * Message looks like the one from "gcc --version". */ printf("%s %s %s\n" " (protocols 1, 2 and 3) (default port %d)\n" " built %s %s\n" "Copyright (C) 2002, 2003, 2004 by Martin Pool.\n" "Includes miniLZO (C) 1996-2002 by Markus Franz Xaver Johannes Oberhumer.\n" "Portions Copyright (C) 2007-2008 Google.\n" "\n" "distcc comes with ABSOLUTELY NO WARRANTY. distcc is free software, and\n" "you may use, modify and redistribute it under the terms of the GNU \n" "General Public License version 2 or later.\n" #ifdef HAVE_AVAHI "\nBuilt with Zeroconf support.\n" #endif "\n" "Please report bugs to %s\n" "\n" , prog, PACKAGE_VERSION, GNU_HOST, DISTCC_DEFAULT_PORT, __DATE__, __TIME__, PACKAGE_BUGREPORT); return 0; } distcc-3.1/source/src/h_compile.c0000640000175000017500000000631611115326640016035 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_exten.c,v 1.7 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * Test harness for functions in compile.c. (Only one so far.) **/ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "compile.h" #define USAGE \ "usage: h_compile COMMAND ARGS...\n" \ "where\n" \ " COMMAND is dcc_fresh_dependency_exists,\n" \ " with ARGS being DOTD_FNAME EXCL_PAT REF_TIME\n" \ "or\n" \ " COMMAND is dcc_discrepancy_filename\n" const char *rs_program_name = __FILE__; int main(int argc, char *argv[]) { rs_trace_set_level(RS_LOG_DEBUG); rs_add_logger(rs_logger_file, RS_LOG_DEBUG, NULL, STDERR_FILENO); if (argc < 2) { rs_log_error(USAGE); return 1; } if (strcmp(argv[1], "dcc_fresh_dependency_exists") == 0) { if (argc != 5) { rs_log_error("dcc_fresh_dependency_exists expects DOTD_FNAME " "EXCL_PAT REF_TIME"); return 1; } errno = 0; char *ptr; time_t ref_time = (time_t)strtol(argv[4], &ptr, 0); if (errno || (*ptr != '\0')) { rs_log_error("strtol failed"); return 1; } else { char *result; int ret; ret = dcc_fresh_dependency_exists((const char *)argv[2], (const char *)argv[3], ref_time, &result); if (ret) printf("h_compile.c: UNEXPECTED RETURN VALUE\n"); else printf("result %s\n", result ? result : "(NULL)"); if (result) free(result); } } else if (strcmp(argv[1], "dcc_discrepancy_filename") == 0) { if (argc != 2) { rs_log_error("dcc_discrepancy_filename expects no arguments"); return 1; } char *result; int ret = dcc_discrepancy_filename(&result); if (ret) printf("h_compile.c: UNEXPECTED RETURN VALUE\n"); else printf("%s", result ? result : "(NULL)"); } else { rs_log_error(USAGE); return 1; } return 0; } distcc-3.1/source/src/compress.c0000640000175000017500000001735111115326640015732 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* I think that I can safely speak for the * whole troll community when I say "I like * watching train wrecks". -- AC */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_MMAN_H # include #endif #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "minilzo.h" static char work_mem[LZO1X_1_MEM_COMPRESS]; /** * @file * * Compressed bulk data transfer for distcc. * * lzo doesn't have any detectable magic at the start in the raw form. (lzop * the command-line tool adds some.) Therefore we indicate in the request * header (the protocol version) whether compression is on or off. If it is * on, all bulk data in both directions is compressed. metadata whether the * transfer is compressed or not. * * It might be nice to unify this code with that in pump.c, which deals with * uncompressed files. There are some parallels between the routines. * However the details are rather different, because with compressed files we * do not know ahead of time how big the expanded form will be. This affects * sending, where we need to make a large-enough temporary buffer to compress * into. It also affects receipt, where we need to allow extra space for data * coming in. So for the moment they remain separate. * * We used to use mmap here, but it complicated the code (and caused a bug in * 2.14) without being clearly any faster. So it's out again. * * The chunk header gives the number of compressed bytes. The number of * plaintext bytes isn't transmitted, and so for decompression we might need * to scale up the buffer. */ /* * Compress from a file to a newly malloc'd block. */ int dcc_compress_file_lzo1x(int in_fd, size_t in_len, char **out_buf, size_t *out_len) { char *in_buf = NULL; int ret; if ((in_buf = malloc(in_len)) == NULL) { rs_log_error("allocation of %ld byte buffer failed", (long) in_len); ret = EXIT_OUT_OF_MEMORY; goto out; } if ((ret = dcc_readx(in_fd, in_buf, in_len))) goto out; if ((ret = dcc_compress_lzo1x_alloc(in_buf, in_len, out_buf, out_len))) goto out; out: if (in_buf != NULL) { free(in_buf); } return ret; } /** * Send LZO-compressed bulk data. * * The most 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; } distcc-3.1/source/src/dopt.h0000640000175000017500000000307711115326640015052 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* dopt.c */ extern struct dcc_allow_list *opt_allowed; 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; #ifdef HAVE_AVAHI extern int opt_zeroconf; #endif distcc-3.1/source/src/stats.h0000640000175000017500000000277111115326640015242 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright 2005 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * * Author: Thomas Kho */ #ifndef _DISTCC_STATS_H #define _DISTCC_STATS_H #ifdef __cplusplus extern "C" { #endif enum stats_e { STATS_TCP_ACCEPT, STATS_REJ_BAD_REQ, STATS_REJ_OVERLOAD, STATS_COMPILE_OK, STATS_COMPILE_ERROR, STATS_COMPILE_TIMEOUT, STATS_CLI_DISCONN, STATS_OTHER, STATS_ENUM_MAX }; 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 */ distcc-3.1/source/src/hostfile.c0000640000175000017500000000346211115326641015713 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * Copyright 2008 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "hosts.h" /* TODO: Perhaps in the future allow filenames to be given in environment * variables to cause other files to be "included". */ /** * Return a hostlist read from fname (possibly recursively.) **/ int dcc_parse_hosts_file(const char *fname, struct dcc_hostdef **ret_list, int *ret_nhosts) { char *body; int ret; rs_trace("load hosts from %s", fname); if ((ret = dcc_load_file_string(fname, &body)) != 0) return ret; ret = dcc_parse_hosts(body, fname, ret_list, ret_nhosts, NULL); free(body); return ret; } distcc-3.1/source/src/h_scanargs.c0000640000175000017500000000362711115326641016211 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_scanargs.c,v 1.9 2003/07/13 08:08:02 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "implicit.h" const char *rs_program_name = __FILE__; /** * Test harness: make argument-parsing code accessible from the * command line so that it can be tested. **/ int main(int argc, char *argv[]) { int result; char *infname, *outfname; char **newargv, **outargv; rs_trace_set_level(RS_LOG_DEBUG); if (argc < 2) { rs_log_error("usage: h_scanargs COMMAND ARG...\n"); return 1; } result = dcc_find_compiler(argv, &newargv); if (result) return result; result = dcc_scan_args(newargv, &infname, &outfname, &outargv); printf("%s %s %s\n", result == 0 ? "distribute" : "local", infname ? infname : "(NULL)", outfname ? outfname : "(NULL)"); return 0; } distcc-3.1/source/src/daemon.c0000640000175000017500000001776711115326641015356 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "Just like distributed.net, only useful!" */ /** * @file * * distcc volunteer server. Accepts and serves requests to compile * files. * * May be run from inetd (default if stdin is a socket), or as a * daemon by itself. * * distcc has an adequate but perhaps not optimal system for deciding * where to send files. The general principle is that the server * should say how many jobs it is willing to accept, rather than the * client having to know. This is probably good in two ways: it * allows for people in the future to impose limits on how much work * their contributed machine will do, and secondly it seems better to * put this information in one place rather than on every client. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ARPA_NAMESER_H # include #endif #include #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "dopt.h" #include "srvnet.h" #include "daemon.h" #include "types.h" /* 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; } distcc-3.1/source/src/io.c0000640000175000017500000001615411115326641014507 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /** * @file * * Common low-level IO utilities. * * This code is not meant to know about our protocol, only to provide * a more comfortable layer on top of Unix IO. * * @todo Perhaps write things out using writev() to reduce the number * of system calls, and the risk of small packets when not using * TCP_CORK. */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SELECT_H # include #endif #include #include #include #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" /** 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 (rs == 0) { rs_log_error("IO timeout"); return EXIT_IO_ERROR; } else { if (FD_ISSET(fd, &except_fds)) { rs_trace("error condition on fd%d", fd); /* * Don't fail here; we couldn't give a good error * message, because we don't know what the error * condition is. Instead just return 0 (success), * indicating that the select has successfully finished. * The next call to write() for that fd will fail but * will also set errno properly so that we can give a * good error message at that point. */ } return 0; } } } /** * Read exactly @p len bytes from a file. **/ int dcc_readx(int fd, void *buf, size_t len) { ssize_t r; int ret; while (len > 0) { r = read(fd, buf, len); if (r == -1 && errno == EAGAIN) { if ((ret = dcc_select_for_read(fd, dcc_io_timeout))) return ret; else continue; } else if (r == -1 && errno == EINTR) { continue; } else if (r == -1) { rs_log_error("failed to read: %s", strerror(errno)); return EXIT_IO_ERROR; } else if (r == 0) { rs_log_error("unexpected eof on fd%d", fd); return EXIT_TRUNCATED; } else { buf = &((char *) buf)[r]; len -= r; } } return 0; } /** * Write bytes to an fd. Keep writing until we're all done or something goes * wrong. * * @returns 0 or exit code. **/ int dcc_writex(int fd, const void *buf, size_t len) { ssize_t r; int ret; while (len > 0) { r = write(fd, buf, len); if (r == -1 && errno == EAGAIN) { if ((ret = dcc_select_for_write(fd, dcc_io_timeout))) return ret; else continue; } else if (r == -1 && errno == EINTR) { continue; } else if (r == -1) { rs_log_error("failed to write: %s", strerror(errno)); return EXIT_IO_ERROR; } else { buf = &((char *) buf)[r]; len -= r; } } return 0; } /** * Stick a TCP cork in the socket. It's not clear that this will help * performance, but it might. * * This is a no-op if we don't think this platform has corks. **/ int tcp_cork_sock(int POSSIBLY_UNUSED(fd), int POSSIBLY_UNUSED(corked)) { #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; } distcc-3.1/source/src/h_sa2str.c0000640000175000017500000000356711115326640015630 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/h_sa2str.c,v 1.1 2004/01/10 23:15:32 mbp Exp $ * * Copyright (C) 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "exitcode.h" #include "distcc.h" #include "trace.h" #include "util.h" #include "srvnet.h" #include "access.h" #include "netutil.h" #include "snprintf.h" const char *rs_program_name = "h_sa2str"; /* Try to print out a sockaddr */ int main(void) { struct sockaddr_in sa; char *buf; int ret; sa.sin_family = AF_INET; sa.sin_addr.s_addr = (in_addr_t) htonl(0x01020304); sa.sin_port = 4200; if ((ret = dcc_sockaddr_to_string((struct sockaddr *) &sa, sizeof sa, &buf))) return ret; puts(buf); free(buf); return 0; } distcc-3.1/source/src/exec.c0000640000175000017500000004767711115326640015041 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* 18 Their bows also shall dash the young men * to pieces; and they shall have no pity on * the fruit of the womb; their eyes shall not * spare children. * -- Isaiah 13 */ /** * @file * * Run compilers or preprocessors. * * The whole server is run in a separate process group and normally in a * separate session. (It is not a separate session in --no-detach debug * mode.) This allows us to cleanly kill off all children and all compilers * when the parent is terminated. * * @todo On Cygwin, fork() must be emulated and therefore will be * slow. It would be faster to just use their spawn() call, rather * than fork/exec. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __CYGWIN__ #define NOGDI #include #endif #include "distcc.h" #include "trace.h" #include "util.h" #include "exitcode.h" #include "exec.h" #include "lock.h" #include "hosts.h" #include "dopt.h" const int timeout_null_fd = -1; int dcc_job_lifetime = 0; static void dcc_inside_child(char **argv, const char *stdin_file, const char *stdout_file, const char *stderr_file) NORETURN; static void dcc_execvp(char **argv) NORETURN; void dcc_note_execution(struct dcc_hostdef *host, char **argv) { char *astr; astr = dcc_argv_tostr(argv); rs_log(RS_LOG_INFO|RS_LOG_NONAME, "exec on %s: %s", host->hostdef_string, astr); free(astr); } /** * Redirect stdin/out/err. Filenames may be NULL to leave them untouched. * * This is called when running a job remotely, but *not* when running * it locally, because people might e.g. want cpp to read from stdin. **/ int dcc_redirect_fds(const char *stdin_file, const char *stdout_file, const char *stderr_file) { int ret; if (stdin_file) if ((ret = dcc_redirect_fd(STDIN_FILENO, stdin_file, O_RDONLY))) return ret; if (stdout_file) { if ((ret = dcc_redirect_fd(STDOUT_FILENO, stdout_file, O_WRONLY | O_CREAT | O_TRUNC))) return ret; } if (stderr_file) { /* Open in append mode, because the server will dump its own error * messages into the compiler's error file. */ if ((ret = dcc_redirect_fd(STDERR_FILENO, stderr_file, O_WRONLY | O_CREAT | O_APPEND))) return ret; } return 0; } #ifdef __CYGWIN__ /* Execute a process WITHOUT console window and correctly redirect output. */ static DWORD dcc_execvp_cyg(char **argv, const char *input_file, const char *output_file, const char *error_file) { STARTUPINFO m_siStartInfo; PROCESS_INFORMATION m_piProcInfo; char cmdline[MAX_PATH+1]={0}; HANDLE stdin_hndl=INVALID_HANDLE_VALUE; HANDLE stdout_hndl=INVALID_HANDLE_VALUE; HANDLE stderr_hndl=INVALID_HANDLE_VALUE; char **ptr; DWORD exit_code; BOOL bRet=0; ZeroMemory(&m_siStartInfo, sizeof(STARTUPINFO)); ZeroMemory( &m_piProcInfo, sizeof(PROCESS_INFORMATION) ); /* Open files for IO redirection */ if (input_file && strcmp(input_file,"/dev/null")!=0) { if ((stdin_hndl = CreateFile(input_file,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_TEMPORARY,NULL)) == INVALID_HANDLE_VALUE) { exit_code = GetLastError(); goto cleanup; } } else stdin_hndl = GetStdHandle(STD_INPUT_HANDLE); if (output_file && strcmp(output_file,"/dev/null")!=0) { if ((stdout_hndl = CreateFile(output_file,GENERIC_WRITE,FILE_SHARE_READ,NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY,NULL)) == INVALID_HANDLE_VALUE) { exit_code = GetLastError(); goto cleanup; } } else stdout_hndl = GetStdHandle(STD_OUTPUT_HANDLE); if (error_file && strcmp(error_file,"/dev/null")!=0) { if ((stderr_hndl = CreateFile(error_file, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_TEMPORARY,NULL)) == INVALID_HANDLE_VALUE) { exit_code = GetLastError(); goto cleanup; } /* Seek to the end of file (ignore return code) */ SetFilePointer(stderr_hndl,0,NULL,FILE_END); } else stderr_hndl = GetStdHandle(STD_ERROR_HANDLE); /* Ensure handles can be inherited */ SetHandleInformation(stdin_hndl,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT); SetHandleInformation(stdout_hndl,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT); SetHandleInformation(stderr_hndl,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT); /*Set up members of STARTUPINFO structure.*/ m_siStartInfo.cb = sizeof(STARTUPINFO); m_siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; m_siStartInfo.wShowWindow = SW_HIDE; m_siStartInfo.hStdInput = stdin_hndl; m_siStartInfo.hStdOutput = stdout_hndl; m_siStartInfo.hStdError = stderr_hndl; /* Create command line */ for (ptr=argv;*ptr!=NULL;ptr++) { strcat(cmdline, *ptr); strcat(cmdline, " "); } /* Create the child process. */ bRet = CreateProcess(NULL, cmdline, /* application name */ NULL, /* process security attributes */ NULL, /* primary thread security attributes */ TRUE, /* handles are inherited */ CREATE_NEW_CONSOLE, /* creation flags */ NULL, /* use parent's environment */ NULL, /* use parent's current directory */ &m_siStartInfo, /* STARTUPINFO pointer */ &m_piProcInfo); /* receives PROCESS_INFORMATION */ if (!bRet) { exit_code = GetLastError(); goto cleanup; } WaitForSingleObject(m_piProcInfo.hProcess, (DWORD)(-1L)); /* return termination code and exit code*/ GetExitCodeProcess(m_piProcInfo.hProcess, &exit_code); CloseHandle(m_piProcInfo.hProcess); /* We can get here only if process creation failed */ cleanup: if (stdin_hndl != INVALID_HANDLE_VALUE) CloseHandle(stdin_hndl); if (stdout_hndl != INVALID_HANDLE_VALUE) CloseHandle(stdout_hndl); if (stderr_hndl != INVALID_HANDLE_VALUE) CloseHandle(stderr_hndl); if (bRet) ExitProcess(exit_code); /* Return cmdline's exit-code to parent process */ else return exit_code; /* Return failure reason to calling fn */ } #endif /** * Replace this program with another in the same process. * * Does not return, either execs the compiler in place, or exits with * a message. **/ static void dcc_execvp(char **argv) { char *slash; execvp(argv[0], argv); /* If we're still running, the program was not found on the path. One * thing that might have happened here is that the client sent an absolute * compiler path, but the compiler's located somewhere else on the server. * In the absence of anything better to do, we search the path for its * basename. * * Actually this code is called on both the client and server, which might * cause unintnded behaviour in contrived cases, like giving a full path * to a file that doesn't exist. I don't think that's a problem. */ slash = strrchr(argv[0], '/'); if (slash) execvp(slash + 1, argv); /* shouldn't be reached */ rs_log_error("failed to exec %s: %s", argv[0], strerror(errno)); dcc_exit(EXIT_COMPILER_MISSING); /* a generalization, i know */ } /** * Called inside the newly-spawned child process to execute a command. * Either executes it, or returns an appropriate error. * * This routine also takes a lock on localhost so that it's counted * against the process load. That lock will go away when the process * exits. * * In this current version locks are taken without regard to load limitation * on the current machine. The main impact of this is that cpp running on * localhost will cause jobs to be preferentially distributed away from * localhost, but it should never cause the machine to deadlock waiting for * localhost slots. * * @param what Type of process to be run here (cpp, cc, ...) **/ static void dcc_inside_child(char **argv, const char *stdin_file, const char *stdout_file, const char *stderr_file) { int ret; if ((ret = dcc_ignore_sigpipe(0))) goto fail; /* set handler back to default */ /* Ignore failure */ dcc_increment_safeguard(); #ifdef __CYGWIN__ /* This will execute compiler and CORRECTLY redirect output if compiler is * a native Windows application. If this never returns, it means the * compiler-execute succeeded. We use a hack to decide if it's a windows * application: if argv[0] starts with ":" or with "\\", then it's * a windows path and we try dcc_execvp_cyg. If not, we assume it's a * cygwin app and fall through to the unix-style forking, below. If we * guess wrong, dcc_execvp_cyg will probably fail with error 3 * (windows-exe for "path not found"), so again we'll fall through to the * unix-fork case. Otherwise we just fail in a generic way. * TODO(csilvers): Figure out the right way to deal with this. Running * cygwin apps via dcc_execvp_cyg segfaults (and takes a * long time to do it too), so I want to avoid that if * possible. I don't know enough about cygwin or * cygwin/windows interactions to know the right thing to * do here. Until distcc has cl.exe support, this may * all be a moot point anyway. */ if (argv[0] && ((argv[0][0] != '\0' && argv[0][1] == ':') || (argv[0][0] == '\\' && argv[0][1] == '\\'))) { DWORD status; status = dcc_execvp_cyg(argv, stdin_file, stdout_file, stderr_file); if (status != 3) { ret = EXIT_DISTCC_FAILED; goto fail; } } #endif /* do this last, so that any errors from previous operations are * visible */ if ((ret = dcc_redirect_fds(stdin_file, stdout_file, stderr_file))) goto fail; dcc_execvp(argv); ret = EXIT_DISTCC_FAILED; fail: dcc_exit(ret); } int dcc_new_pgrp(void) { /* If we're a session group leader, then we are not able to call * setpgid(). However, setsid will implicitly have put us into a new * process group, so we don't have to do anything. */ /* Does everyone have getpgrp()? It's in POSIX.1. We used to call * getpgid(0), but that is not available on BSD/OS. */ if (getpgrp() == getpid()) { rs_trace("already a process group leader"); return 0; } if (setpgid(0, 0) == 0) { rs_trace("entered process group"); return 0; } else { rs_trace("setpgid(0, 0) failed: %s", strerror(errno)); return EXIT_DISTCC_FAILED; } } /** * Run @p argv in a child asynchronously. * * stdin, stdout and stderr are redirected as shown, unless those * filenames are NULL. In that case they are left alone. * * @warning When called on the daemon, where stdin/stdout may refer to random * network sockets, all of the standard file descriptors must be redirected! **/ int dcc_spawn_child(char **argv, pid_t *pidptr, const char *stdin_file, const char *stdout_file, const char *stderr_file) { pid_t pid; dcc_trace_argv("forking to execute", argv); pid = fork(); if (pid == -1) { rs_log_error("failed to fork: %s", strerror(errno)); return EXIT_OUT_OF_MEMORY; /* probably */ } else if (pid == 0) { /* If this is a remote compile, * put the child in a new group, so we can * kill it and all its descendents without killing distccd * FIXME: if you kill distccd while it's compiling, and * the compiler has an infinite loop bug, the new group * will run forever until you kill it. */ if (stdout_file != NULL) { if (dcc_new_pgrp() != 0) rs_trace("Unable to start a new group\n"); } dcc_inside_child(argv, stdin_file, stdout_file, stderr_file); /* !! NEVER RETURN FROM HERE !! */ } else { *pidptr = pid; rs_trace("child started as pid%d", (int) pid); return 0; } } void dcc_reset_signal(int whichsig) { struct sigaction act_dfl; memset(&act_dfl, 0, sizeof act_dfl); act_dfl.sa_handler = SIG_DFL; sigaction(whichsig, &act_dfl, NULL); /* might be called from signal handler, therefore no IO to log a * message */ } static int sys_wait4(pid_t pid, int *status, int options, struct rusage *rusage) { /* Prefer use waitpid to wait4 for non-blocking wait with WNOHANG option */ #ifdef HAVE_WAITPID /* Just doing getrusage(children) is not sufficient, because other * children may have exited previously. */ memset(rusage, 0, sizeof *rusage); return waitpid(pid, status, options); #elif HAVE_WAIT4 return wait4(pid, status, options, rusage); #else #error Please port this #endif } /** * Blocking wait for a child to exit. This is used when waiting for * cpp, gcc, etc. * * This is not used by the daemon-parent; it has its own * implementation in dcc_reap_kids(). They could be unified, but the * parent only waits when it thinks a child has exited; the child * waits all the time. **/ int dcc_collect_child(const char *what, pid_t pid, int *wait_status, int in_fd) { struct rusage ru; pid_t ret_pid; int ret; int wait_timeout_sec; fd_set fds,readfds; wait_timeout_sec = dcc_job_lifetime; FD_ZERO(&readfds); if (in_fd != timeout_null_fd){ FD_SET(in_fd,&readfds); } while (!dcc_job_lifetime || wait_timeout_sec-- >= 0) { /* If we're called with a socket, break out of the loop if the socket disconnects. * To do that, we need to block in select, not in sys_wait4. * (Only waitpid uses WNOHANG to mean don't block ever, so I've modified * sys_wait4 above to preferentially call waitpid.) */ int flags = (in_fd == timeout_null_fd) ? 0 : WNOHANG; ret_pid = sys_wait4(pid, wait_status, flags, &ru); if (ret_pid == -1) { if (errno == EINTR) { rs_trace("wait4 was interrupted; retrying"); } else { rs_log_error("sys_wait4(pid=%d) borked: %s", (int) pid, strerror(errno)); return EXIT_DISTCC_FAILED; } } else if (ret_pid != 0) { /* This is not the main user-visible message; that comes from * critique_status(). */ rs_trace("%s child %ld terminated with status %#x", what, (long) ret_pid, *wait_status); rs_log_info("%s times: user %ld.%06lds, system %ld.%06lds, " "%ld minflt, %ld majflt", what, ru.ru_utime.tv_sec, (long) ru.ru_utime.tv_usec, ru.ru_stime.tv_sec, (long) ru.ru_stime.tv_usec, ru.ru_minflt, ru.ru_majflt); return 0; } /* check timeout */ if (in_fd != timeout_null_fd){ struct timeval timeout; /* If client disconnects, the socket will become readable, * and a read should return -1 and set errno to EPIPE. */ fds = readfds; timeout.tv_sec = 1; timeout.tv_usec = 0; ret = select(in_fd+1,&fds,NULL,NULL,&timeout); if (ret == 1) { char buf; int nread = read(in_fd, &buf, 1); if ((nread == -1) && (errno == EWOULDBLOCK)) { /* spurious wakeup, ignore */ ; } else if (nread == 0) { rs_log_error("Client fd disconnected, killing job"); /* If killpg fails, it might means the child process is not * in a new group, so, just kill the child process */ if (killpg(pid,SIGTERM)!=0) kill(pid, SIGTERM); return EXIT_IO_ERROR; } else if (nread == 1) { rs_log_error("Bug! Read from fd succeeded when checking whether client disconnected!"); } else rs_log_error("Bug! nread %d, errno %d checking whether client disconnected!", nread, errno); } } else poll(NULL, 0, 1000); } /* If timeout, also kill the child process */ if (killpg(pid,SIGTERM) !=0 ) kill(pid, SIGTERM); rs_log_error("Compilation takes too long, timeout."); return EXIT_TIMEOUT; } /** * Analyze and report to the user on a command's exit code. * * @param command short human-readable description of the command (perhaps * argv[0]) * * @returns 0 if the command succeeded; 128+SIGNAL if it stopped on a * signal; otherwise the command's exit code. **/ int dcc_critique_status(int status, const char *command, const char *input_fname, struct dcc_hostdef *host, int verbose) { int logmode; /* verbose mode is only used for executions that the user is likely to * particularly need to know about */ if (verbose) logmode = RS_LOG_ERR | RS_LOG_NONAME; else logmode = RS_LOG_INFO | RS_LOG_NONAME; if (input_fname == NULL) input_fname = "(null)"; if (WIFSIGNALED(status)) { #ifdef HAVE_STRSIGNAL rs_log(logmode, "%s %s on %s:%s %s", command, input_fname, host->hostdef_string, strsignal(WTERMSIG(status)), WCOREDUMP(status) ? " (core dumped)" : ""); #else rs_log(logmode, "%s %s on %s terminated by signal %d%s", command, input_fname, host->hostdef_string, WTERMSIG(status), WCOREDUMP(status) ? " (core dumped)" : ""); #endif /* Unix convention is to return 128+signal when a subprocess crashes. */ return 128 + WTERMSIG(status); } else if (WEXITSTATUS(status) == 1) { /* Normal failure gives exit code 1, so handle that specially */ rs_log(logmode, "%s %s on %s failed", command, input_fname, host->hostdef_string); return WEXITSTATUS(status); } else if (WEXITSTATUS(status)) { /* This is a tough call; we don't really want to clutter the client's * error stream, but if we don't say where the compilation failed then * people may find it hard to work things out. */ rs_log(logmode, "%s %s on %s failed with exit code %d", command, input_fname, host->hostdef_string, WEXITSTATUS(status)); return WEXITSTATUS(status); } else { rs_log(RS_LOG_INFO|RS_LOG_NONAME, "%s %s on %s completed ok", command, input_fname, host->hostdef_string); return 0; } } distcc-3.1/source/src/timeval.c0000640000175000017500000000335611115326641015541 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * from the GNU libc manual */ /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include "timeval.h" /* Subtract the `struct timeval' values X and Y, storing the result in RESULT. Return 1 if the difference is negative, otherwise 0. */ int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) { /* Perform the carry for the later subtraction by updating Y. */ if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (x->tv_usec - y->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; } /* Compute the time remaining to wait. `tv_usec' is certainly positive. */ result->tv_sec = x->tv_sec - y->tv_sec; result->tv_usec = x->tv_usec - y->tv_usec; /* Return 1 if result is negative. */ return x->tv_sec < y->tv_sec; } distcc-3.1/source/src/timeval.h0000640000175000017500000000166511115326641015547 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * from the GNU libc manual */ /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); distcc-3.1/source/src/rpc.h0000640000175000017500000000346511115326641014672 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* His hand is stretched out, and who shall turn it back? * -- Isaiah 14:27 */ 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); distcc-3.1/source/src/climasq.c0000640000175000017500000000775611115326641015541 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* * And the magicians did so with their enchantments, * and brought up frogs upon the land of Egypt. * -- Exodus 8:7 */ #include #include #include #include #include #include #include "distcc.h" #include "util.h" #include "trace.h" #include "exitcode.h" /** * For masquerade mode, change the path to remove the directory containing the * distcc mask, so that invoking the same name will find the underlying * compiler instead. * * @param progname basename under which distcc was introduced. If we reached * this point, then it's the same as the name of the real compiler, e.g. "cc". * * @param did_masquerade specifies an integer that will be set to 1 if the * path was changed. * * @return 0 or standard error. **/ int dcc_support_masquerade(char *argv[], char *progname, int *did_masquerade) { const char *envpath, *findpath, *p, *n; char *buf; size_t len; size_t findlen; if (!(envpath = getenv("PATH"))) /* strange but true*/ return 0; if (!(buf = malloc(strlen(envpath)+1+strlen(progname)+1))) { rs_log_error("failed to allocate buffer for new PATH"); return EXIT_OUT_OF_MEMORY; } /* Filter PATH to contain only the part that is past our dir. * If we were called explicitly, find the named dir on the PATH. */ if (progname != argv[0]) { findpath = dcc_abspath(argv[0], progname - argv[0] - 1); findlen = strlen(findpath); } else { findpath = NULL; findlen = 0; } for (n = p = envpath; *n; p = n) { /* Find the length of this component of the path */ n = strchr(p, ':'); if (n) len = n++ - p; else { len = strlen(p); n = p + len; } if (findpath) { /* Looking for a component in the path equal to findpath */ /* FIXME: This won't catch paths that are in fact the same, but * that are not the same string. This might happen if you have * multiple slashes, or dots, or symlinks... */ if (len != findlen || strncmp(p, findpath, findlen) != 0) continue; } else { /* Looking for a component in the path containing a file * progname. */ /* FIXME: This gets a false match if you have a subdirectory that * happens to be of the right name, e.g. /usr/bin/distcc... */ strncpy(buf, p, (size_t) len); sprintf(buf + len, "/%s", progname); if (access(buf, X_OK) != 0) continue; } /* Set p to the part of the path past our match. */ p = n; break; } if (*p != '\0') { int ret = dcc_set_path(p); if (ret) return ret; *did_masquerade = 1; } else { rs_trace("not modifying PATH"); *did_masquerade = 0; } free(buf); return 0; } distcc-3.1/source/src/dotd.c0000640000175000017500000002136511115326641015032 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include "distcc.h" #include "exitcode.h" #include "dotd.h" #include "snprintf.h" /* The dotd file is compiler generated, * so it should not have lines with more than * twice the length of the maximum path length. */ #define MAX_DOTD_LINE_LEN (MAXPATHLEN * 2) /* Replaces the first occurrence of needle in haystack with new_needle. haystack must be of at least hay_size, and hay_size must be large enough to hold the string after the replacement. new_needle should not overlap with the haystack. Returns 0 if all goes well, 1 otherwise. */ static int dcc_strgraft(char *haystack, size_t hay_size, const char *needle, const char *new_needle) { char *found; size_t needle_len = 0; size_t new_needle_len = 0; found = strstr(haystack, needle); if (found == NULL) return 0; needle_len = strlen(needle); new_needle_len = strlen(new_needle); if (strlen(haystack) - needle_len + new_needle_len + 1 > hay_size) return 1; /* make some room in the haystack for the new needle */ memmove(found + new_needle_len, found + needle_len, strlen(found + needle_len) + 1); memcpy(found, new_needle, new_needle_len); return 0; } /* Given the name of a dotd file, and the name of the directory * masquerading as root, write a @p new_dotd file that * contains everything in dotd, but with the "root" directory removed. * It will also substitute client_out_name for server_out_name, * rewriting the dependency target. */ int dcc_cleanup_dotd(const char *dotd_fname, char **new_dotd_fname, const char *root_dir, const char *client_out_name, const char *server_out_name) { /* When we do the substitution of server-side output name to * client-side output name, we may end up with a line that * longer than the longest line we expect from the compiler. */ char buf[2 * MAX_DOTD_LINE_LEN]; FILE *dotd, *tmp_dotd; char *found; int ret; dotd = fopen(dotd_fname, "r"); if (dotd == NULL) { return 1; } ret = dcc_make_tmpnam(dcc_find_basename(dotd_fname), ".d", new_dotd_fname); if (ret) { fclose(dotd); return ret; } tmp_dotd = fopen(*new_dotd_fname, "w"); if ((tmp_dotd == NULL)) { fclose(dotd); return 1; } while (fgets(buf, MAX_DOTD_LINE_LEN, dotd)) { if ((strchr(buf, '\n') == NULL) && !feof(dotd)) { /* Line length must have exceeded MAX_DOTD_LINE_LEN: bail out. */ fclose(dotd); fclose(tmp_dotd); return 1; } /* First, the dependency target substitution */ if (dcc_strgraft(buf, sizeof(buf), server_out_name, client_out_name)) { fclose(dotd); fclose(tmp_dotd); return 1; } /* Second, the trimming of the "root" directory" */ found = strstr(buf, root_dir); while (found) { char *rest_of_buf = found + strlen(root_dir); memmove(found, rest_of_buf, strlen(rest_of_buf) + 1); found = strstr(found, root_dir); } if (fprintf(tmp_dotd, "%s", buf) < 0) { fclose(dotd); fclose(tmp_dotd); return 1; } } if (ferror(dotd) || ferror(tmp_dotd)) { return 1; } fclose(dotd); if (fclose(tmp_dotd) < 0) { return 1; } return 0; } /* Go through arguments (in @p argv), and relevant environment variables, and * find out where the dependencies output should go. Return that location in a * newly allocated string in @p dotd_fname. @p needs_dotd is set to true if the * compilation command line and 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 (strncmp(a, "-MF", 3) == 0) { deps_output = argv[i] + 3; } else if (strcmp(a, "-o") == 0) { has_dash_o = 1; } } /* TODO(csilvers): we also need to parse -Wp,-x,-y,-z, in the same * way we do gcc flags in the for loop above. Note that the -Wp * flags are passed to cpp, with slightly different semantics than * gcc flags (eg -Wp,-MD takes a filename argument, while -MD does * not). */ if (deps_output) { *dotd_fname = strdup(deps_output); if (*dotd_fname == NULL) { return EXIT_OUT_OF_MEMORY; } else { return 0; } } /* ok, so there is no explicit setting of the deps filename. */ deps_output = env_var; if (deps_output) { char *space; *dotd_fname = strdup(deps_output); if (*dotd_fname == NULL) { return EXIT_OUT_OF_MEMORY; } space = strchr(*dotd_fname, ' '); if (space != NULL) { *space = '\0'; *dotd_target = space + 1; } return 0; } /* and it's not set explicitly in the variable */ { /* Call dcc_scan_args to find the input/output files in order to calculate a name for the .d file.*/ char *extension; char *tmp_dotd_fname; 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; } } distcc-3.1/source/src/bulk.c0000640000175000017500000002361211115326641015032 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* "A new contraption to capture a dandelion in one * piece has been put together by the crew." * -- Boards of Canada, "Geogaddi" */ /** * @file * * Bulk file transfer, used for sending .i, .o files etc. * * Files are always sent in the standard IO format: stream name, * length, bytes. This implies that we can deliver to a fifo (just * keep writing), but we can't send from a fifo, because we wouldn't * know how many bytes were coming. * * @note We don't time transmission of files: because the write returns when * they've just been written into the OS buffer, we don't really get * meaningful numbers except for files that are very large. **/ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "rpc.h" #include "bulk.h" #include "time.h" #include "exitcode.h" #include "timeval.h" /** * Open a file for read, and also put its size into @p fsize. * * If the file does not exist, then returns 0, but @p ifd is -1 and @p * fsize is zero. If @p fsize is zero, the caller should not try to * read from the file. * * This strange behaviour for ENOENT is useful because if there is * e.g. no output file from the compiler, we don't want to abort, but * rather just send nothing. The receiver has the corresponding * behaviour of not creating zero-length files. * * Using fstat() helps avoid a race condition -- not a security issue, * but possibly a failure. Shouldn't be very likely though. * * The caller is responsible for closing @p ifd. **/ int dcc_open_read(const char *fname, int *ifd, off_t *fsize) { struct stat buf; *ifd = open(fname, O_RDONLY|O_BINARY); if (*ifd == -1) { int save_errno = errno; if (save_errno == ENOENT) { /* that's OK, just assume it's empty */ *fsize = 0; return 0; } else { rs_log_error("failed to open %s: %s", fname, strerror(save_errno)); return EXIT_IO_ERROR; } } if (fstat(*ifd, &buf) == -1) { rs_log_error("fstat %s failed: %s", fname, strerror(errno)); dcc_close(*ifd); return EXIT_IO_ERROR; } *fsize = buf.st_size; return 0; } void dcc_calc_rate(off_t size_out, struct timeval *before, struct timeval *after, double *secs, double *rate) { struct timeval delta; /* FIXME: Protect against division by zero and other floating-point * exceptions. */ timeval_subtract(&delta, after, before); *secs = (double) delta.tv_sec + (double) delta.tv_usec / 1e6; if (*secs == 0.0) *rate = 0.0; else *rate = ((double) size_out / *secs) / 1024.0; } static int dcc_x_file_lzo1x(int out_fd, int in_fd, const char *token, unsigned in_len) { int ret; char *out_buf = NULL; size_t out_len; /* As a special case, send 0 as 0 */ if (in_len == 0) { if ((ret = dcc_x_token_int(out_fd, token, 0))) goto out; } else { if ((ret = dcc_compress_file_lzo1x(in_fd, in_len, &out_buf, &out_len))) goto out; if ((ret = dcc_x_token_int(out_fd, token, out_len))) goto out; if ((ret = dcc_writex(out_fd, out_buf, out_len))) goto out; } ret = 0; out: free(out_buf); return ret; } /** * Transmit from a local file to the network. Sends TOKEN, LENGTH, BODY, * where the length is the appropriate compressed length. * * Does compression if needed. * * @param ofd File descriptor for the network connection. * @param fname Name of the file to send. * @param token Token for this file, e.g. "DOTO". **/ int dcc_x_file(int ofd, const char *fname, const char *token, enum dcc_compress compression, off_t *f_size_out) { int ifd; int ret; off_t f_size; if (dcc_open_read(fname, &ifd, &f_size)) return EXIT_IO_ERROR; if (ifd == -1) return EXIT_IO_ERROR; if (f_size_out) *f_size_out = f_size; rs_trace("send %lu byte file %s with token %s and compression %d", (unsigned long) f_size, fname, token, compression); if (compression == DCC_COMPRESS_NONE) { if ((ret = dcc_x_token_int(ofd, token, f_size))) goto failed; /* FIXME: These could get truncated if the file was very large (>4G). * That seems pretty unlikely. */ #ifdef HAVE_SENDFILE ret = dcc_pump_sendfile(ofd, ifd, (size_t) f_size); #else ret = dcc_pump_readwrite(ofd, ifd, (size_t) f_size); #endif } else if (compression == DCC_COMPRESS_LZO1X) { ret = dcc_x_file_lzo1x(ofd, ifd, token, f_size); } else { rs_log_error("invalid compression"); return EXIT_PROTOCOL_ERROR; } if (ifd != -1) dcc_close(ifd); return 0; failed: if (ifd != -1) dcc_close(ifd); return ret; } /** * Receive a file stream from the network into a local file. * Make all necessary directories if they don't exist. * * Can handle compression. * * @param len Compressed length of the incoming file. * @param filename local filename to create. **/ int dcc_r_file(int ifd, const char *filename, unsigned len, enum dcc_compress compr) { int ofd; int ret, close_ret; struct stat s; /* This is meant to behave similarly to the output routines in bfd/cache.c * in gnu binutils, because makefiles or configure scripts may depend on * it for edge cases. * * We try to remove the output file first, if its size is not 0. That * should make the newly created file be owned by the current user; it * might also help in the dangerous case of some other process still * reading from the file. * * Checking for size 0 means that we won't unlink special files like * /dev/null or fifos. * * However, failure to remove the file does not cause a warning; we may * not have write permission on the directory, but +w for the file. */ if (dcc_mk_tmp_ancestor_dirs(filename)) { rs_log_error("failed to create path for '%s'", filename); return EXIT_IO_ERROR; } if (stat(filename, &s) == 0) { if (s.st_size != 0) { if (unlink(filename) && errno != ENOENT) { rs_trace("failed to remove %s: %s", filename, strerror(errno)); /* continue */ } } } else { if (errno != ENOENT) { rs_trace("stat %s failed: %s", filename, strerror(errno)); } /* continue */ } ofd = open(filename, O_TRUNC|O_WRONLY|O_CREAT|O_BINARY, 0666); if (ofd == -1) { rs_log_error("failed to create %s: %s", filename, strerror(errno)); return EXIT_IO_ERROR; } ret = 0; if (len > 0) { ret = dcc_r_bulk(ofd, ifd, len, compr); } close_ret = dcc_close(ofd); if (!ret && !close_ret) { rs_trace("received %d bytes to file %s", len, filename); return 0; } rs_trace("failed to receive %s, removing it", filename); if (unlink(filename)) { rs_log_error("failed to unlink %s after failed transfer: %s", filename, strerror(errno)); } return EXIT_IO_ERROR; } /** * Receive a file and print timing statistics. Only used for big files. * * Wrapper around dcc_r_file(). **/ int dcc_r_file_timed(int ifd, const char *fname, unsigned size, enum dcc_compress compr) { struct timeval before, after; int ret; if (gettimeofday(&before, NULL)) rs_log_warning("gettimeofday failed"); ret = dcc_r_file(ifd, fname, size, compr); if (gettimeofday(&after, NULL)) { rs_log_warning("gettimeofday failed"); } else { double secs, rate; dcc_calc_rate(size, &before, &after, &secs, &rate); rs_log_info("%ld bytes received in %.6fs, rate %.0fkB/s", (long) size, secs, rate); } return ret; } int dcc_r_token_file(int in_fd, const char *token, const char *fname, enum dcc_compress compr) { int ret; unsigned i_size; if ((ret = dcc_r_token_int(in_fd, token, &i_size))) return ret; if ((ret = dcc_r_file_timed(in_fd, fname, (size_t) i_size, compr))) return ret; return 0; } int dcc_copy_file_to_fd(const char *in_fname, int out_fd) { off_t len; int ifd; int ret; if ((ret = dcc_open_read(in_fname, &ifd, &len))) return ret; #ifdef HAVE_SENDFILE ret = dcc_pump_sendfile(out_fd, ifd, (size_t) len); #else ret = dcc_pump_readwrite(out_fd, ifd, (size_t) len); #endif if (ret) { close(ifd); return ret; } return 0; } distcc-3.1/source/src/rpc.c0000640000175000017500000002047011115326641014660 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ /* 15 Every one that is found shall be thrust * through; and every one that is joined unto * them shall fall by the sword. * -- Isaiah 13 */ #include #include #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "rpc.h" #include "snprintf.h" /** * @file * * Very simple RPC-like layer. Requests and responses are build of * little packets each containing a 4-byte ascii token, an 8-byte hex * value or length, and optionally data corresponding to the length. * * 'x' means transmit, and 'r' means receive. * * This builds on top of io.c and is called by the various routines * that handle communication. **/ /** * Transmit token name (4 characters) and value (32-bit int, as 8 hex * characters). **/ int dcc_x_token_int(int ofd, const char *token, unsigned param) { char buf[13]; int shift; char *p; const char *hex = "0123456789abcdef"; if (strlen(token) != 4) { rs_log_crit("token \"%s\" seems wrong", token); return EXIT_PROTOCOL_ERROR; } memcpy(buf, token, 4); /* Quick and dirty int->hex. The only standard way is to call snprintf * (?), which is undesirably slow for such a frequently-called * function. */ for (shift=28, p = &buf[4]; shift >= 0; shift -= 4, p++) { *p = hex[(param >> shift) & 0xf]; } buf[12] = '\0'; rs_trace("send %s", buf); return dcc_writex(ofd, buf, 12); } /** * Send start of a result: DONE **/ int dcc_x_result_header(int ofd, enum dcc_protover protover) { return dcc_x_token_int(ofd, "DONE", protover); } int dcc_x_cc_status(int ofd, int status) { return dcc_x_token_int(ofd, "STAT", (unsigned) status); } int dcc_r_token(int ifd, char *buf) { return dcc_readx(ifd, buf, 4); } /** * We got a mismatch on a token, which indicates either a bug in distcc, or * that somebody (inetd?) is interfering with our network stream, or perhaps * some other network problem. Whatever's happened, a bit more debugging * information would be handy. **/ int dcc_explain_mismatch(const char *buf, size_t buflen, int ifd) { ssize_t ret; char extrabuf[200]; char *p; size_t l; memcpy(extrabuf, buf, buflen); /* Read a bit more context, and find the printable prefix. */ ret = read(ifd, extrabuf + buflen, sizeof extrabuf - 1 - buflen); if (ret == -1) { ret = 0; /* pah, use what we've got */ } l = buflen + ret; extrabuf[l] = '\0'; for (p = extrabuf; *p; p++) if (!(isprint(*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; } distcc-3.1/source/src/config.h.in0000640000175000017500000001652511115326652015763 0ustar wolffwolff/* src/config.h.in. Generated from ./configure.ac by autoheader. */ /* Use getaddrinfo(), getnameinfo(), etc */ #undef ENABLE_RFC2553 /* Your gnu-style host triple */ #undef GNU_HOST /* Define to 1 if you have the header file. */ #undef HAVE_ALLOCA_H /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_NAMESER_H /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF /* defined if Avahi is available */ #undef HAVE_AVAHI /* define if vsnprintf is C99 compliant */ #undef HAVE_C99_VSNPRINTF /* Define to 1 if you have the header file. */ #undef HAVE_CTYPE_H /* Define to 1 if you have the declaration of `asprintf', and to 0 if you don't. */ #undef HAVE_DECL_ASPRINTF /* Define to 1 if you have the declaration of `snprintf', and to 0 if you don't. */ #undef HAVE_DECL_SNPRINTF /* Define to 1 if you have the declaration of `strndup', and to 0 if you don't. */ #undef HAVE_DECL_STRNDUP /* Define to 1 if you have the declaration of `vasprintf', and to 0 if you don't. */ #undef HAVE_DECL_VASPRINTF /* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you don't. */ #undef HAVE_DECL_VSNPRINTF /* Define to 1 if you have the header file. */ #undef HAVE_ELF_H /* Define to 1 if you have the header file. */ #undef HAVE_FLOAT_H /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK /* Define to 1 if you have the header file. */ #undef HAVE_FNMATCH_H /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD /* Define to 1 if you have the `geteuid' function. */ #undef HAVE_GETEUID /* Define to 1 if you have the `getloadavg' function. */ #undef HAVE_GETLOADAVG /* Define to 1 if you have the `getnameinfo' function. */ #undef HAVE_GETNAMEINFO /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the `getrusage' function. */ #undef HAVE_GETRUSAGE /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the `getuid' function. */ #undef HAVE_GETUID /* Define to 1 if you have the `getwd' function. */ #undef HAVE_GETWD /* Define to 1 if you have the `hstrerror' function. */ #undef HAVE_HSTRERROR /* Define to 1 if you have the `inet_ntoa' function. */ #undef HAVE_INET_NTOA /* Define to 1 if you have the `inet_ntop' function. */ #undef HAVE_INET_NTOP /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if the system has the type `in_addr_t'. */ #undef HAVE_IN_ADDR_T /* Define to 1 if the system has the type `in_port_t'. */ #undef HAVE_IN_PORT_T /* Define to 1 if you have the `lockf' function. */ #undef HAVE_LOCKF /* Define to 1 if you have the `mcheck' function. */ #undef HAVE_MCHECK /* Define to 1 if you have the header file. */ #undef HAVE_MCHECK_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mkdtemp' function. */ #undef HAVE_MKDTEMP /* Define to 1 if you have the `mmap' function. */ #undef HAVE_MMAP /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define if you have POSIX threads libraries and header files. */ #undef HAVE_PTHREAD /* Define to 1 if you have the header file. */ #undef HAVE_RESOLV_H /* Define to 1 if you have the `sendfile' function. */ #undef HAVE_SENDFILE /* Define to 1 if you have the `setgroups' function. */ #undef HAVE_SETGROUPS /* Define to 1 if you have the `setreuid' function. */ #undef HAVE_SETREUID /* Define to 1 if you have the `setsid' function. */ #undef HAVE_SETSID /* Define to 1 if you have the `setuid' function. */ #undef HAVE_SETUID /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF /* define if you have struct sockaddr_storage */ #undef HAVE_SOCKADDR_STORAGE /* define if you have a working socketpair */ #undef HAVE_SOCKETPAIR /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strlcpy' function. */ #undef HAVE_STRLCPY /* Define to 1 if you have the `strndup' function. */ #undef HAVE_STRNDUP /* Define to 1 if you have the `strsep' function. */ #undef HAVE_STRSEP /* Define to 1 if you have the `strsignal' function. */ #undef HAVE_STRSIGNAL /* Define to 1 if you have the header file. */ #undef HAVE_SYS_LOADAVG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MMAN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_RESOURCE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SENDFILE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SIGNAL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Whether __va_copy() is available */ #undef HAVE_UNDERSCORE_UNDERSCORE_VA_COPY /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define if your cpp has vararg macros */ #undef HAVE_VARARG_MACROS /* Define to 1 if you have the `vasprintf' function. */ #undef HAVE_VASPRINTF /* Whether va_copy() is available */ #undef HAVE_VA_COPY /* Define to 1 if you have the `vsnprintf' function. */ #undef HAVE_VSNPRINTF /* Define to 1 if you have the `wait3' function. */ #undef HAVE_WAIT3 /* Define to 1 if you have the `wait4' function. */ #undef HAVE_WAIT4 /* Define to 1 if you have the `waitpid' function. */ #undef HAVE_WAITPID /* Define if MAP_FAILED constant not available */ #undef MAP_FAILED /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Use GNOME */ #undef WITH_GNOME /* Use GTK+ */ #undef WITH_GTK /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ #undef WORDS_BIGENDIAN /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* type to use in place of socklen_t if not defined */ #undef socklen_t distcc-3.1/source/autogen.sh0000750000175000017500000000151411115326647015145 0ustar wolffwolff#! /bin/sh -e # Usage: autogen.sh [srcdir] # Run this script to build distcc from CVS. ## first try the default names ACLOCAL="aclocal" AUTOHEADER="autoheader" AUTOCONF="autoconf" if which $AUTOCONF > /dev/null then : else echo "$0: need autoconf 2.53 or later to regenerate configure scripts" >&2 exit 1 fi srcdir=`dirname "$0"` builddir=`pwd` echo "$0: running $ACLOCAL" (cd $srcdir && $ACLOCAL -I m4 --output=$builddir/aclocal.m4) echo "$0: running $AUTOHEADER" [ -d src ] || mkdir src # Needed for autoheader to generate src/config.h.in. $AUTOHEADER $srcdir/configure.ac echo "$0: running $AUTOCONF" $AUTOCONF $srcdir/configure.ac > configure chmod +x configure if [ "$srcdir" = "." ]; then echo "Now run './configure' and then 'make'." else echo "Now run './configure --srcdir=$srcdir' and then 'make'." fi exit 0 distcc-3.1/source/test/0000750000175000017500000000000011115327757014125 5ustar wolffwolffdistcc-3.1/source/test/onetest.py0000750000175000017500000000330611115326636016160 0ustar wolffwolff#!/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. """Usage: onetest.py [--valgrind[=command]] [--lzo] [--pump] TESTNAME This command runs a single test case. TESTNAME should be the name of one of the test cases from testdistcc.py. """ __author__ = 'Fergus Henderson' import testdistcc import comfychair import sys if __name__ == '__main__': while len(sys.argv) > 1 and sys.argv[1].startswith("--"): if sys.argv[1] == "--valgrind": testdistcc._valgrind_command = "valgrind --quiet " del sys.argv[1] elif sys.argv[1].startswith("--valgrind="): testdistcc._valgrind_command = sys.argv[1][len("--valgrind="):] + " " del sys.argv[1] elif sys.argv[1] == "--lzo": testdistcc._server_options = ",lzo" del sys.argv[1] elif sys.argv[1] == "--pump": testdistcc._server_options = ",lzo,cpp" del sys.argv[1] if len(sys.argv) > 1: testname = sys.argv[1] del sys.argv[1] comfychair.main([eval('testdistcc.' + testname)]) else: sys.exit(__doc__) distcc-3.1/source/test/testdistcc.py0000750000175000017500000022327311115326636016657 0ustar wolffwolff#! /usr/bin/env python2.2 # Copyright (C) 2002, 2003, 2004 by Martin Pool # Copyright 2007 Google Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """distcc test suite, using comfychair This script is called with $PATH pointing to the appropriate location for the built (or installed) programs to be tested. Options: --valgrind[=command] Run the tests under valgrind. Every program invocation will be prefixed with the valgrind command, which defaults to "valgrind --quiet". --lzo Run the server tests with lzo compression enabled. --pump Run the server tests with remote preprocessing enabled. Example: PATH="`pwd`:$PATH" python test/testdistcc.py --valgrind="valgrind --quiet --num-callers=20" """ # There are pretty strong hierarchies of test cases: ones to do with # running a daemon, compiling a file and so on. This nicely maps onto # a hierarchy of object classes. # It seems to work best if an instance of the class corresponds to an # invocation of a test: this means each method runs just once and so # object state is not very useful, but nevermind. # Having a complicated 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, glob, re, socket import signal, os.path import comfychair from stat import * # this is safe EXIT_DISTCC_FAILED = 100 EXIT_BAD_ARGUMENTS = 101 EXIT_BIND_FAILED = 102 EXIT_CONNECT_FAILED = 103 EXIT_COMPILER_CRASHED = 104 EXIT_OUT_OF_MEMORY = 105 EXIT_BAD_HOSTSPEC = 106 EXIT_COMPILER_MISSING = 110 EXIT_ACCESS_DENIED = 113 DISTCC_TEST_PORT = 42000 _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". def _ShellSafe(s): '''Returns a version of s that will be interpreted literally by the shell.''' return "'" + s.replace("'", "'\"'\"'") + "'" # Some tests only make sense for certain object formats def _FirstBytes(filename, count): '''Returns the first count bytes from the given file.''' f = open(filename) try: return f.read(count) finally: f.close() def _IsElf(filename): '''Given a filename, determine if it's an ELF object file or executable. The magic number used ('\177ELF' at file-start) is taken from /usr/share/file/magic on an ubuntu machine. ''' contents = _FirstBytes(filename, 5) return contents.startswith('\177ELF') def _IsMachO(filename): '''Given a filename, determine if it's an Mach-O object file or executable. The magic number used ('0xcafebabe' or '0xfeedface') is taken from /usr/share/file/magic on an ubuntu machine. ''' contents = _FirstBytes(filename, 10) return (contents.startswith('\xCA\xFE\xBA\xBE') or contents.startswith('\xFE\xED\xFA\xCE') or contents.startswith('\xCE\xFA\xED\xFE') or # The magic file says '4-bytes (BE) & 0xfeffffff == # 0xfeedface' and '4-bytes (LE) & 0xfffffffe == # 0xfeedface' are also mach-o. contents.startswith('\xFF\xED\xFA\xCE') or contents.startswith('\xCE\xFA\xED\xFF')) def _IsPE(filename): '''Given a filename, determine if it's a Microsoft PE object file or executable. The magic number used ('MZ') is taken from /usr/share/file/magic on an ubuntu machine. ''' contents = _FirstBytes(filename, 5) return contents.startswith('MZ') 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): SimpleDistCC_Case.setup(self) self.daemon_pidfile = os.path.join(os.getcwd(), "daemonpid.tmp") self.daemon_logfile = os.path.join(os.getcwd(), "distccd.log") self.server_port = DISTCC_TEST_PORT # random.randint(42000, 43000) self.startDaemon() self.setupEnv() def setupEnv(self): os.environ['DISTCC_HOSTS'] = ('127.0.0.1:%d%s' % (self.server_port, _server_options)) os.environ['DISTCC_LOG'] = os.path.join(os.getcwd(), 'distcc.log') os.environ['DISTCC_VERBOSE'] = '1' def teardown(self): SimpleDistCC_Case.teardown(self) def killDaemon(self): try: pid = int(open(self.daemon_pidfile, 'rt').read()) except IOError: # the daemon probably already exited, perhaps because of a timeout return os.kill(pid, signal.SIGTERM) # We can't wait on it, because it detached. So just keep # pinging until it goes away. while 1: try: os.kill(pid, 0) except OSError: break time.sleep(0.2) def daemon_command(self): """Return command to start the daemon""" return (self.distccd() + "--verbose --lifetime=%d --daemon --log-file %s " "--pid-file %s --port %d --allow 127.0.0.1" % (self.daemon_lifetime(), _ShellSafe(self.daemon_logfile), _ShellSafe(self.daemon_pidfile), self.server_port)) def daemon_lifetime(self): # Enough for most tests, even on a fairly loaded machine. # Might need more for long-running tests. return 60 def startDaemon(self): """Start a daemon in the background, return its pid""" # The daemon detaches once it has successfully bound the # socket, so if something goes wrong at startup we ought to # find out straight away. If it starts successfully, then we # can go ahead and try to connect. # We run the daemon in a 'daemon' subdirectory to make # sure that it has a different directory than the client. old_tmpdir = os.environ['TMPDIR'] daemon_tmpdir = old_tmpdir + "/daemon_tmp" os.mkdir(daemon_tmpdir) os.environ['TMPDIR'] = daemon_tmpdir os.mkdir("daemon") os.chdir("daemon") try: while 1: cmd = self.daemon_command() result, out, err = self.runcmd_unchecked(cmd) if result == 0: break elif result == EXIT_BIND_FAILED: self.server_port += 1 continue else: self.fail("failed to start daemon: %d" % result) self.add_cleanup(self.killDaemon) finally: os.environ['TMPDIR'] = old_tmpdir os.chdir("..") class StartStopDaemon_Case(WithDaemon_Case): def runtest(self): pass class VersionOption_Case(SimpleDistCC_Case): """Test that --version returns some kind of version string. This is also a good test that the programs were built properly and are executable.""" def runtest(self): for prog in 'distcc', 'distccd': out, err = self.runcmd("%s --version" % prog) assert out[-1] == '\n' out = out[:-1] line1,line2,trash = 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"), # Fixed in 2.18.4 -- -dr writes rtl to a local file ("gcc -dr -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.c -o hello.bar.foo -MD", "*.d", 1, None), ("foo.c -MD", "*.d", 1, None), ("foo.c -o hello. -MD", "*.d", 1, None), # The following test case fails under Darwin Kernel Version 8.11.0. For some # reason, gcc refuses to produce 'hello.d' when the object file is named # 'hello.D'. # ("foo.c -o hello.D -MD -MT tootoo", "hello.*d", 1, "tootoo"), ("foo.c -o hello. -MD -MT tootoo", "hello.*d", 1, "tootoo"), ("foo.c -o hello.o -MD -MT tootoo", "hello.*d", 1, "tootoo"), ("foo.c -o hello.o -MD -MF foobar", "foobar", 1, None), ] # These C++ cases fail if your gcc installation doesn't support C++. error_rc, _, _ = self.runcmd_unchecked("touch testtmp.cpp; " + _gcc + " -c testtmp.cpp -o /dev/null") if error_rc == 0: cases.extend([("foo.cpp -o hello.o", "*.d", 0, None), ("foo.cpp -o hello", "*.d", 0, None)]) def _eval(out): map_out = eval(out) return (map_out['dotd_fname'], map_out['needs_dotd'], map_out['sets_dotd_target'], map_out['dotd_target']) for (args, dep_glob, how_many, target) in cases: # Determine what gcc says. dotd_result = [] # prepare for some imperative style value passing class TempCompile_Case(Compilation_Case): def source(self): return """ int main(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) ret = comfychair.runtest(TempCompile_Case, 0, subtest=1) if ret: raise AssertionError( "Case (args:%s, dep_glob:%s, how_many:%s, target:%s)" % (args, dep_glob, how_many, target)) self.assert_equal(len(dotd_result), how_many) if how_many == 1: expected_dep_file = dotd_result[0] # Determine what dcc_get_dotd_info says. out, _err = self.runcmd("h_dotd dcc_get_dotd_info gcc -c %s" % args) dotd_fname, needs_dotd, sets_dotd_target, dotd_target = _eval(out) assert dotd_fname assert needs_dotd in [0,1] # Assert that "needs_dotd == 1" if and only if "how_many == 1". assert needs_dotd == how_many # Assert that "needs_dotd == 1" implies names by gcc and our routine # are the same. if needs_dotd: self.assert_equal(expected_dep_file, dotd_fname) self.assert_equal(sets_dotd_target == 1, target != None) if target: # A little convoluted: because target is set in command line, # and the command line is passed already, the dotd_target is not # set. self.assert_equal(dotd_target, "None") # Now some fun with DEPENDENCIES_OUTPUT variable. try: os.environ["DEPENDENCIES_OUTPUT"] = "xxx.d yyy" out, _err = self.runcmd("h_dotd dcc_get_dotd_info gcc -c foo.c") dotd_fname, needs_dotd, sets_dotd_target, dotd_target = _eval(out) assert dotd_fname == "xxx.d" assert needs_dotd assert not sets_dotd_target assert dotd_target == "yyy" os.environ["DEPENDENCIES_OUTPUT"] = "zzz.d" out, _err = self.runcmd("h_dotd dcc_get_dotd_info gcc -c foo.c") dotd_fname, needs_dotd, sets_dotd_target, dotd_target = _eval(out) assert dotd_fname == "zzz.d" assert needs_dotd assert not sets_dotd_target assert dotd_target == "None" finally: del os.environ["DEPENDENCIES_OUTPUT"] class Compile_c_Case(SimpleDistCC_Case): """Unit tests for source file 'compile.c.' Currently, only the functions dcc_fresh_dependency_exists() and dcc_discrepancy_filename() are tested. """ def getDep(self, line): """Parse line to yield dependency name. From say: "src/h_compile.c[21010] (dcc_fresh_dependency_exists) Checking dependency: bar_bar" return "bar_bar". """ m_obj = re.search(r"Checking dependency: ((\w|[.])*)", line) assert m_obj, line return m_obj.group(1) def 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 dcc_discrepancy_filename") self.assert_equal(out, "abc/discrepancy_counter") os.environ['INCLUDE_SERVER_PORT'] = "socket" out, err = self.runcmd( "h_compile dcc_discrepancy_filename") self.assert_equal(out, "(NULL)") # os.environ will be cleaned out at start of next test. # Test dcc_fresh_dependency_exists # ******************************** dotd_cases = [(""" foo.o: foo\ bar.h bar.h notthisone.h bar.h\ """, ["foobar.h", "bar.h"]), ( """foo_foo :\ bar_bar \ foo_bar""", ["bar_bar", "foo_bar"]), (":", []), ("\n", []), ("", []), ("foo.o:", []), ] for dotd_contents, deps in dotd_cases: 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 = {} for line in err.split("\n"): if re.search("[^ ]", line): # Line is non-blank checked_deps[self.getDep(line)] = 1 deps_list = deps[:] checked_deps_list = checked_deps.keys() deps_list.sort() checked_deps_list.sort() self.assert_equal(checked_deps_list, deps_list) # Let's try to touch, say the last dep file. Then, we should expect # the name of that very file as the output because there's a fresh # file. 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 " "--allow 127.0.0.1", 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""" return self.distcc_without_fallback() + \ _gcc + " -o testtmp.o " + self.compileOpts() + \ " -c %s" % (self.sourceFilename()) def compileOpts(self): """Returns any extra options to pass when compiling""" return "" def linkCmd(self): """Return command to link object files""" return self.distcc() + \ _gcc + " -o testtmp testtmp.o " + self.libraries() def libraries(self): """Returns any '-l' options needed to link the program.""" return "" def checkCompileMsgs(self, msgs): if msgs <> '': self.fail("expected no compiler messages, got \"%s\"" % msgs) def checkBuiltProgram(self): '''Check compile/link results. By default, just try to execute.''' msgs, errs = self.runcmd("./testtmp") self.checkBuiltProgramMsgs(msgs) self.assert_equal(errs, '') def checkBuiltProgramMsgs(self, msgs): pass class CompileHello_Case(Compilation_Case): """Test the simple case of building a program that works properly""" def headerSource(self): return """ #define HELLO_WORLD "hello world" """ def source(self): return """ #include #include "testhdr.h" int main(void) { puts(HELLO_WORLD); return 0; } """ def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello world\n") class LanguageSpecific_Case(Compilation_Case): """Abstract base class to test building non-C programs.""" def runtest(self): # Don't try to run the test if the language's compiler is not installed source = self.sourceFilename() lang = self.languageGccName() error_rc, _, _ = self.runcmd_unchecked( "touch " + source + "; " + "rm -f testtmp.o; " + _gcc + " -x " + lang + " " + self.compileOpts() + " -c " + source + " " + self.libraries() + " && " + "test -f testtmp.o" ) if error_rc != 0: raise comfychair.NotRunError ('GNU ' + self.languageName() + ' not installed') else: Compilation_Case.runtest (self) def sourceFilename(self): return "testtmp" + self.extension() def languageGccName(self): """Language name suitable for use with 'gcc -x'""" raise NotImplementedError def languageName(self): """Human-readable language name.""" raise NotImplementedError def extension(self): """Filename extension, with leading '.'.""" raise NotImplementedError class CPlusPlus_Case(LanguageSpecific_Case): """Test building a C++ program.""" def languageName(self): return "C++" def languageGccName(self): return "c++" def extension(self): return ".cpp" # Could also use ".cc", ".cxx", etc. def libraries(self): return "-lstdc++" def headerSource(self): return """ #define MESSAGE "hello c++" """ def source(self): return """ #import #import "testhdr.h" int main(void) { std::cout << MESSAGE << std::endl; return 0; } """ def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello c++\n") class ObjectiveC_Case(LanguageSpecific_Case): """Test building an Objective-C program.""" def languageName(self): return "Objective-C" def languageGccName(self): return "objective-c" def extension(self): return ".m" def headerSource(self): return """ #define MESSAGE "hello objective-c" """ def source(self): return """ #import #import "testhdr.h" /* TODO: use objective-c features. */ int main(void) { puts(MESSAGE); return 0; } """ class ObjectiveCPlusPlus_Case(LanguageSpecific_Case): """Test building an Objective-C++ program.""" def languageName(self): return "Objective-C++" def languageGccName(self): return "objective-c++" def extension(self): return ".mm" def libraries(self): return "-lstdc++" def headerSource(self): return """ #define MESSAGE "hello objective-c++" """ def source(self): return """ #import #import "testhdr.h" /* TODO: use Objective-C features. */ int main(void) { std::cout << MESSAGE << std::endl; return 0; } """ def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello objective-c++\n") class SystemIncludeDirectories_Case(Compilation_Case): """Test -I/usr/include/sys""" def compileOpts(self): return "-I/usr/include/sys" def headerSource(self): return """ #define HELLO_WORLD "hello world" """ def source(self): return """ #include "types.h" /* Should resolve to /usr/incude/sys/types.h. */ #include #include "testhdr.h" int main(void) { puts(HELLO_WORLD); return 0; } """ def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello world\n") class CPlusPlus_SystemIncludeDirectories_Case(CPlusPlus_Case): """Test -I/usr/include/sys for a C++ program""" def compileOpts(self): return "-I/usr/include/sys" def headerSource(self): return """ #define MESSAGE "hello world" """ def source(self): return """ #include "types.h" /* Should resolve to /usr/incude/sys/types.h. */ #include "testhdr.h" #include int main(void) { puts(MESSAGE); return 0; } """ def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello world\n") class Gdb_Case(CompileHello_Case): """Test that distcc generates correct debugging information.""" def sourceFilename(self): try: os.mkdir("src") except: pass return "src/testtmp.c" def compiler(self): """Command for compiling and linking.""" return _gcc + " -g "; def compileCmd(self): """Return command to compile source""" os.mkdir("obj") return self.distcc_without_fallback() + self.compiler() + \ " -o obj/testtmp.o -I. -c %s" % (self.sourceFilename()) def link(self): """ We do the linking in a subdirectory, so that the 'compilation directory' field of the debug info set by the link step (which will be done locally, not remotely) does NOT influence the behaviour of gdb. We want gdb to use the 'compilation directory' value set by the compilation. """ os.mkdir('link') cmd = self.distcc() + self.compiler() + " -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 runtest(self): # Don't try to run the test if gdb is not installed error_rc, _, _ = self.runcmd_unchecked("gdb --help") if error_rc != 0: raise comfychair.NotRunError ('gdb could not be found on path') else: CompileHello_Case.runtest (self) def checkBuiltProgram(self): # On windows, the binary may be called testtmp.exe. Check both if os.path.exists('link/testtmp.exe'): testtmp_exe = 'testtmp.exe' else: testtmp_exe = 'testtmp' # Run gdb and verify that it is able to correctly locate the # testtmp.c source file. We write the gdb commands to a file # and run them via gdb --command. (The alternative, to specify # the gdb commands directly on the commandline using gdb --ex, # is not as portable since only newer gdb's support it.) f = open('gdb_commands', 'w') f.write('break main\nrun\nstep\n') f.close() out, errs = self.runcmd("gdb --batch --command=gdb_commands " "link/%s /dev/null" % self.sourceFilename()) gcc_preprocessing_preserves_pwd = (error_rc == 0); if ((pump_mode and _IsElf('./%s' % testtmp_exe)) or ((not pump_mode) and gcc_preprocessing_preserves_pwd)): out, errs = self.runcmd("gdb --batch --command=../gdb_commands " "./%s acceptable_diffbytes)): # Just do the cmp again to give a good error message self.runcmd("cmp link/%s run/%s" % (testtmp_exe, testtmp_exe)) class GdbOpt1_Case(Gdb_Case): def compiler(self): """Command for compiling and linking.""" return _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 #include #include #include "testhdr.h" int main(void) { printf("%s\\n", HELLO_WORLD); return 0; } """ def setupEnv(self): Compilation_Case.setupEnv(self) os.environ['DISTCC_HOSTS'] = '127.0.0.1:%d,lzo' % self.server_port class DashONoSpace_Case(CompileHello_Case): def compileCmd(self): return self.distcc_without_fallback() + \ _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 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 """ def runtest(self): if _server_options.find('cpp') != -1: # Annoyingly, different versions of gcc are inconsistent # in how they treat a non-existent #include file when # invoked with "-MMD": some versions treat it as an error # (rc 1), some as a warning (rc 0). When distcc is # responsible for preprocessing (_server_options includes # 'cpp'), we need to figure out which our gcc does, in # order to verify distcc is doing the same thing. # FIXME(klarlund): this is arguably a bug in gcc, and it # is exacerbated by distcc's pump mode because we always # pass -MMD, even when the user didn't. TODO(klarlund): # change error_rc back to 1 once that FIXME is fixed. error_rc, _, _ = self.runcmd_unchecked(_gcc + " -MMD -E testtmp.c") else: error_rc = 1 self.runcmd(self.distcc() + _gcc + " -o testtmp.o -c testtmp.c", error_rc) class PreprocessPlainText_Case(Compilation_Case): """Try using cpp on something that's not C at all""" def setup(self): self.stripEnvironment() self.createSource() 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" % (_ShellSafe(self.daemon_logfile), _ShellSafe(self.daemon_pidfile), self.server_port)) self.pid = self.runcmd_background(cmd) self.add_cleanup(self.killDaemon) # Wait until the server is ready for connections. time.sleep(0.2) # Give distccd chance to start listening on the port sock = socket.socket() while sock.connect_ex(('127.0.0.1', self.server_port)) != 0: time.sleep(0.2) def killDaemon(self): os.kill(self.pid, signal.SIGTERM) pid, ret = os.wait() self.assert_equal(self.pid, pid) class ImplicitCompiler_Case(CompileHello_Case): """Test giving no compiler works""" def compileCmd(self): return self.distcc() + "-c testtmp.c" def linkCmd(self): # FIXME: Mozilla uses something like "distcc testtmp.o -o testtmp", # but that's broken at the moment. return self.distcc() + "-o testtmp testtmp.o " def runtest(self): if sys.platform == 'hp-ux10': raise comfychair.NotRunError ('HP-UX bundled C compiler non-ANSI') # We can't run if cc is not installed on the system (maybe only gcc is) error_rc, _, _ = self.runcmd_unchecked("cc -c testtmp.c") self.runcmd_unchecked("rm -f testtmp.o") # clean up the 'cc' output if error_rc != 0: raise comfychair.NotRunError ('Cannot find working "cc"') else: CompileHello_Case.runtest (self) class DashD_Case(Compilation_Case): """Test preprocessor arguments""" def source(self): return """ #include int main(void) { printf("%s\\n", MESSAGE); return 0; } """ def compileOpts(self): # quoting is hairy because this goes through the shell return "'-DMESSAGE=\"hello DashD\"'" def checkBuiltProgramMsgs(self, msgs): self.assert_equal(msgs, "hello DashD\n") class DashMD_DashMF_DashMT_Case(CompileHello_Case): """Test -MD -MFfoo -MTbar""" def compileOpts(self): return "-MD -MFdotd_filename -MTtarget_name_42" def runtest(self): try: os.remove('dotd_filename') except OSError: pass self.compile(); dotd_contents = open("dotd_filename").read() self.assert_re_search("target_name_42", dotd_contents) class DashWpMD_Case(CompileHello_Case): """Test -Wp,-MD,depfile""" def compileOpts(self): return "-Wp,-MD,depsfile" def runtest(self): try: os.remove('depsfile') except OSError: pass self.compile() deps = open('depsfile').read() self.assert_re_search(r"testhdr.h", deps); # The following assertion is commented out for now # because it does not pass in pump mode. # FIXME This is a real bug that we need to fix! # Pump mode is treating -MD as if it was -MMD. # self.assert_re_search(r"stdio.h", deps); class ScanIncludes_Case(CompileHello_Case): """Test --scan-includes""" def createSource(self): CompileHello_Case.createSource(self) self.runcmd("mv testhdr.h test_header.h") self.runcmd("ln -s test_header.h testhdr.h") self.runcmd("mkdir test_subdir") self.runcmd("touch test_another_header.h") def headerSource(self): return """ #define HELLO_WORLD "hello world" #include "test_subdir/../test_another_header.h" """ def compileCmd(self): return self.distcc_without_fallback() + "--scan-includes " + \ _gcc + " -o testtmp.o " + self.compileOpts() + \ " -c %s" % (self.sourceFilename()) def runtest(self): cmd = self.compileCmd() rc, out, err = self.runcmd_unchecked(cmd) log = open('distcc.log').read() pump_mode = _server_options.find('cpp') != -1 if pump_mode: if err != '': self.fail("distcc command %s produced stderr:\n%s" % (`cmd`, err)) if rc != 0: self.fail("distcc command %s failed:\n%s" % (`cmd`, rc)) self.assert_re_search( r"FILE /.*/ScanIncludes_Case/testtmp.c", out); self.assert_re_search( r"FILE /.*/ScanIncludes_Case/test_header\.h", out); self.assert_re_search( r"FILE /.*/ScanIncludes_Case/test_another_header\.h", out); self.assert_re_search( r"SYMLINK /.*/ScanIncludes_Case/testhdr\.h", out); self.assert_re_search( r"DIRECTORY /.*/ScanIncludes_Case/test_subdir", out); self.assert_re_search( r"SYSTEMDIR /.*", out); else: self.assert_re_search(r"ERROR: '--scan_includes' specified, but " "distcc wouldn't have used include server " ".make sure hosts list includes ',cpp' option", log) self.assert_equal(rc, 100) self.assert_equal(out, '') self.assert_equal(err, '') class AbsSourceFilename_Case(CompileHello_Case): """Test remote compilation of files with absolute names.""" def compileCmd(self): return (self.distcc() + _gcc + " -c -o testtmp.o %s/testtmp.c" % _ShellSafe(os.getcwd())) class HundredFold_Case(CompileHello_Case): """Try repeated simple compilations. This used to be a ThousandFold_Case -- but that slowed down testing significantly. It's unclear that testing a 1000 times is much better than doing it a 100 times. """ def daemon_lifetime(self): return 120 def runtest(self): for unused_i in xrange(100): 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 unused_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): # WithDaemon_Case sets this to point to the local host, but we # don't want that. Note that you cannot delete environment # keys in Python1.5, so we need to just set them to the empty # string. os.environ['DISTCC_HOSTS'] = '' os.environ['DISTCC_LOG'] = '' self.runcmd('env') msgs, errs = self.runcmd(self.compileCmd()) # We expect only one message, a warning from distcc self.assert_re_search(r"Warning.*\$DISTCC_HOSTS.*can't distribute work", errs) def compileCmd(self): """Return command to compile source and run tests""" return self.distcc_with_fallback() + \ _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. This test fails with an internal compiler error in GCC 3.4.x for x < 5 (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20239 [3.4 Regression] ICE on empty preprocessed input). But that's gcc's problem, not ours, so we make this test pass if gcc gets an ICE.""" def source(self): return '' def runtest(self): self.compile() def compile(self): rc, out, errs = self.runcmd_unchecked(self.distcc() + _gcc + " -c %s" % self.sourceFilename()) if not re.search("internal compiler error", errs): self.assert_equal(rc, 0) def sourceFilename(self): return "testtmp.i" class BadLogFile_Case(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(), _ShellSafe(self.daemon_logfile), _ShellSafe(self.daemon_pidfile), self.server_port)) def compileCmd(self): """Return command to compile source and run tests""" return self.distcc_with_fallback() + \ _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) # On some systems, 127.0.0.* are all loopback addresses. # On other systems, only 127.0.0.1 is a loopback address. # The lsdistcc test is more effective if we can use 127.0.0.2 etc. # but that only works on some systems, so we need to check whether # if will work. The ping command is not very portable, but that # doesn't matter; if it fails, we just won't test quite as much as # we would if it succeeds. So long as it succeeds on Linux, we'll # get good enough test coverage. rc, out, err = self.runcmd_unchecked("ping -c 3 -i 0.2 -w 1 127.0.0.2") multiple_loopback_addrs = (rc == 0) # Test "lsdistcc host1 host2 host3". out, err = self.runcmd(lsdistcc + " localhost 127.0.0.1 127.0.0.2 " + " anInvalidHostname") out_list = out.split() out_list.sort() expected = ["%s:%d" % (host, self.server_port) for host in ["127.0.0.1", "127.0.0.2", "localhost"]] if multiple_loopback_addrs: self.assert_equal(out_list, expected) else: # It may be that 127.0.0.2 isn't a loopback address, or it # may be that it is, but ping doesn't support -c or -i or # -w. So be happy if 127.0.0.2 is there, or if it's not. if out_list != expected: del expected[1] # remove 127.0.0.2 self.assert_equal(out_list, expected) self.assert_equal(err, "") # Test "lsdistcc host%d". out, err = self.runcmd(lsdistcc + " 127.0.0.%d") self.assert_equal(err, "") self.assert_re_search("127.0.0.1:%d\n" % self.server_port, out) if multiple_loopback_addrs: self.assert_re_search("127.0.0.2:%d\n" % self.server_port, out) self.assert_re_search("127.0.0.3:%d\n" % self.server_port, out) self.assert_re_search("127.0.0.4:%d\n" % self.server_port, out) self.assert_re_search("127.0.0.5:%d\n" % self.server_port, out) # 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, CPlusPlus_Case, ObjectiveC_Case, ObjectiveCPlusPlus_Case, SystemIncludeDirectories_Case, CPlusPlus_SystemIncludeDirectories_Case, Gdb_Case, GdbOpt1_Case, GdbOpt2_Case, GdbOpt3_Case, Lsdistcc_Case, BadLogFile_Case, ScanArgs_Case, ParseMask_Case, DotD_Case, DashMD_DashMF_DashMT_Case, Compile_c_Case, ImplicitCompilerScan_Case, StripArgs_Case, StartStopDaemon_Case, CompressedCompile_Case, DashONoSpace_Case, WriteDevNull_Case, CppError_Case, BadInclude_Case, PreprocessPlainText_Case, NoDetachDaemon_Case, SBeatsC_Case, DashD_Case, DashWpMD_Case, BinFalse_Case, BinTrue_Case, VersionOption_Case, HelpOption_Case, BogusOption_Case, MultipleCompile_Case, 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, HundredFold_Case, BigAssFile_Case] if __name__ == '__main__': while len(sys.argv) > 1 and sys.argv[1].startswith("--"): if sys.argv[1] == "--valgrind": _valgrind_command = "valgrind --quiet " del sys.argv[1] elif sys.argv[1].startswith("--valgrind="): _valgrind_command = sys.argv[1][len("--valgrind="):] + " " del sys.argv[1] elif sys.argv[1] == "--lzo": _server_options = ",lzo" del sys.argv[1] elif sys.argv[1] == "--pump": _server_options = ",lzo,cpp" del sys.argv[1] # Some of these tests need lots of file descriptors (especially to fork), # but sometimes the os only supplies a few. Try to raise that if we can. try: import resource (_, hard_limit) = resource.getrlimit(resource.RLIMIT_NOFILE) resource.setrlimit(resource.RLIMIT_NOFILE, (hard_limit, hard_limit)) except (ImportError, ValueError): pass comfychair.main(tests) distcc-3.1/source/test/comfychair.py0000750000175000017500000003503111115326636016623 0ustar wolffwolff#! /usr/bin/env python # Copyright (C) 2002, 2003 by Martin Pool # Copyright (C) 2003 by Tim Potter # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """comfychair: a Python-based instrument of software torture. Copyright (C) 2002, 2003 by Martin Pool Copyright (C) 2003 by Tim Potter This is a test framework designed for testing programs written in Python, or (through a fork/exec interface) any other language. For more information, see the file README.comfychair. To run a test suite based on ComfyChair, just run it as a program. """ import sys, re, shutil class TestCase: """A base class for tests. This class defines required functions which can optionally be overridden by subclasses. It also provides some utility functions for""" def __init__(self): self.test_log = "" self.background_pids = [] self._cleanups = [] self._enter_rundir() self._save_environment() self.add_cleanup(self.teardown) # -------------------------------------------------- # 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') shutil.rmtree(self.rundir, ignore_errors=1) os.makedirs(self.tmpdir) os.chdir(self.rundir) os.environ['LANG'] = 'C' 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 apply_cleanups(self, debugger): """Apply cleanup functions and return error code. Returns: 0 on success; 2 if a KeyboardInterrupt occurs; 1 if any other exception occurs. """ while self._cleanups: try: apply(self._cleanups.pop()) except KeyboardInterrupt: print "interrupted during cleanups" _report_error(self, debugger) return 2 except: print "error during cleanups" _report_error(self, debugger) return 1 return 0 def fail(self, reason = ""): """Say the test failed.""" raise AssertionError(reason) ############################################################# # Requisition methods def require(self, predicate, message): """Check a predicate for running this test. If the predicate value is not true, the test is skipped with a message explaining why.""" if not predicate: raise NotRunError, message def require_root(self): """Skip this test unless run by root.""" 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 runtest(testcase_class, ret, verbose=0, debugger=None, subtest=0): """Instantiate test class, run it, and catch and report exceptions. Inputs: testcase_class a class derived from TestCase ret return status, an integer verbose an integer (used as boolean) debugger debugger object to be applied to errors subtest an integer (used as boolean) Returns: a new return status Raises: KeyboardInterrupt If subtest is true, then the ordinary information about the test progress is not printed. """ if not subtest: print "%-30s" % _test_name(testcase_class), def failure_print(message): print message else: def failure_print(message): print '[%s %s]' % (_test_name(testcase_class), message) # flush now so that long running tests are easier to follow sys.stdout.flush() obj = None try: try: # run test and sometimes show result obj = testcase_class() obj.setup() obj.runtest() if not subtest: print "OK" except KeyboardInterrupt: failure_print("INTERRUPT") if obj: _report_error(obj, debugger) raise except NotRunError, msg: failure_print("NOTRUN, %s" % msg.value) except: failure_print("FAIL") if obj: _report_error(obj, debugger) return 1 finally: if obj: ret = obj.apply_cleanups(debugger) or ret # Display log file if we're verbose if ret == 0 and verbose: obj.explain_failure() return ret def runtests(test_list, verbose = 0, debugger = None): """Run a series of tests. Inputs: test_list sequence of TestCase classes verbose print more information as testing proceeds debugger debugger object to be applied to errors Returns: unix return code: 0 for success, 1 for failures, 2 for test failure """ import traceback ret = 0 for testcase_class in test_list: try: ret = runtest(testcase_class, ret, verbose=verbose, debugger=debugger) except KeyboardInterrupt: ret = 2 break return ret def _test_name(test_class): """Return a human-readable name for a test class. """ try: return test_class.__name__ except: return `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__ distcc-3.1/source/survey.txt0000640000175000017500000000203211115326647015237 0ustar wolffwolffIf you find distcc useful, please take a little time to fill out this survey and mail it to {distcc-survey at google.com}. Don't stress too much about getting scientifically rigorous numbers: rough numbers are more useful than none at all. Ideally, complete the survey for one large application that you work on, where compile speed is important. If after installing distcc you find that it makes your compile slower, or not as much faster as you would be expect, then please write to {distcc at lists.samba.org} instead of filling in the survey, and we'll try to resolve the problem. 0. What version of distcc are you using? 1. Your name and email address: 2. OK to publish this? - yes - yes, but without my identifying details - yes, but without my email address - no, for your eyes only 3. Your codebase: lines of code (by wc -l), and language: 4. Your machines: number, OS, processor, memory, network connectivity: 5. Time to compile, with and without distcc: 6. Any other observations: Thanks! The distcc maintainers. distcc-3.1/source/include_server/0000750000175000017500000000000011115327757016157 5ustar wolffwolffdistcc-3.1/source/include_server/compress_files.py0000750000175000017500000001135711115326647021555 0ustar wolffwolff#! /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_keeper): """Copy files in include_closure to the client_root directory, compressing them as we go, and also inserting #line directives. Arguments: include_closure: a dictionary, see IncludeAnalyzer.RunAlgorithm client_root_keeper: an object as defined in basics.py Returns: a list of filepaths under client_root Walk through the files in the include closure. Make sure their compressed images (with either .lzo or lzo.abs extension) exist under client_root as handled by client_root_keeper. Also collect all the .lzo or .lzo.abs filepaths in a list, which is the return value. """ realpath_string = self.realpath_map.string files = [] # where we accumulate files for realpath_idx in include_closure: # Thanks to symbolic links, many absolute filepaths may designate # the very same canonical path (as calculated by realpath). The # first such one to be discovered is the one used. realpath = realpath_string[realpath_idx] if len(include_closure[realpath_idx]) > 0: # Designate by suffix '.abs' that this file is to become known by an # absolute filepath through a #line directive. new_filepath = "%s%s.lzo.abs" % (client_root_keeper.client_root, realpath) else: new_filepath = "%s%s.lzo" % (client_root_keeper.client_root, realpath) files.append(new_filepath) if not new_filepath in self.files_compressed: self.files_compressed.add(new_filepath) dirname = os.path.dirname(new_filepath) try: if not os.path.isdir(dirname): 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 distcc-3.1/source/include_server/include_analyzer_memoizing_node.py0000750000175000017500000006423611115326647025157 0ustar wolffwolff#! /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, client_root_keeper, stat_reset_triggers={}): """Constructor.""" include_analyzer.IncludeAnalyzer.__init__(self, client_root_keeper, stat_reset_triggers) self._InitializeAllCachesMemoizing() def ClearStatCaches(self): """Reset stat caches and the node cache, which depends on stat caches.""" # First, clear caches as the IncludeAnalyzer class prescribes it. include_analyzer.IncludeAnalyzer.ClearStatCaches(self) # Then, clear own caches. self._InitializeAllCachesMemoizing() def _PrintableFilePath(self, fp): return (isinstance(fp, int) and self.includepath_map.String(fp) or isinstance(fp, tuple) and (self.directory_map.string[fp[0]], self.includepath_map.string[fp[1]])) def RunAlgorithm(self, filepath_resolved_pair, filepath_real_idx): """See RunAlgorithm of class IncludeAnalyzer in include_analyzer.""" incl_config = (self.currdir_idx, self.quote_dirs, self.angle_dirs) try: nodes_for_incl_config = self.master_cache[incl_config] except KeyError: nodes_for_incl_config = self.master_cache[incl_config] = {} # Process symbols defined on command line. for d_opt in self.d_opts: if len(d_opt) == 1: lhs, rhs = d_opt[0], "1" elif len(d_opt) == 2: [lhs, rhs] = d_opt parse_file.InsertMacroDefInTable(lhs, rhs, self.symbol_table, self.support_master.InvalidateRecords) else: # Assume this is a syntax error of some sort. pass # Construct or find the node for filepath_resolved. node = self.FindNode(nodes_for_incl_config, filepath_resolved_pair, RESOLVED, None, filepath_real_idx) # Find the nodes reachable from node and represent as an include closure. include_closure = {} self._CalculateIncludeClosureExceptSystem(node, include_closure) return include_closure def FindNode(self, nodes_for_incl_config, fp, resolution_mode, file_dir_idx=None, fp_real_idx=None): """Find a previously constructed node or create a new node. Arguments: nodes_for_incl_config: a dictionary (see class documentation). fp: a filepath index or, if resolution_mode == RESOLVED, a filepath pair resolution_mode: an integer in RESOLUTION_MODES file_dir_idx: consider the file F that has the line '#include "fp"' which is causing us to call FindNode on fp. file_dir_idx is the index of dirname(F). (This argument affects the semantics of resolution for resolution_mode == QUOTE.) fp_real_idx: the realpath index of resolved filepath (Useful for resolution_mode == RESOLVED only.) Returns: a node or None Raises: NotCoveredError This is function is long, too long. But function calls are expensive in Python. TODO(klarlund): refactor. """ # Convenient abbreviations for cache access. dir_map = self.directory_map includepath_map = self.includepath_map resolve = self.build_stat_cache.Resolve # Now a little dynamic type verification. Remember that "A implies B" is # exactly the same as "not A or B", at least in some primitive formal # systems. assert isinstance(nodes_for_incl_config, dict) assert (not self.IsFilepathPair(fp) or resolution_mode == RESOLVED) assert (not fp or (self.IsFilepathPair(fp) or (resolution_mode != RESOLVED and self.IsIncludepathIndex(fp)))) assert resolution_mode in RESOLUTION_MODES assert not resolution_mode == QUOTE or file_dir_idx assert not file_dir_idx or resolution_mode == QUOTE assert not fp_real_idx or resolution_mode == RESOLVED if __debug__: Debug(DEBUG_TRACE, "FindNode: fp: %s, mode: %s\n file_dir: %s,\n fp_real: %s" % (self._PrintableFilePath(fp), RESOLUTION_MODES_STR[resolution_mode], not file_dir_idx and " " or dir_map.string[file_dir_idx], not fp_real_idx and " " or self.realpath_map.string[fp_real_idx])) statistics.find_node_counter += 1 if fp == None: return # We must remember the resolution_mode when we key our function call. And # for resolution_mode == QUOTE it is important to also remember the # file_dir_idx, because the filepath is resolved against file_dir. key = (fp, resolution_mode, file_dir_idx) if key in nodes_for_incl_config: # Is the support record valid? if nodes_for_incl_config[key][self.SUPPORT_RECORD].valid: statistics.master_hit_counter += 1 return nodes_for_incl_config[key] else: # Invalid support record. The meaning of some computed includes may have # changed. node = nodes_for_incl_config[key] currdir_idx = self.currdir_idx quote_dirs = self.quote_dirs angle_dirs = self.angle_dirs # Retrieve filepath information. That is still OK. Disregard children, # because they will be rebuilt. Reuse support_record. Don't switch # support_record.valid to True before running through all the caching # code below -- we don't want to reuse an earlier result. [fp_real_idx, fp_resolved_pair, _, support_record] = node Debug(DEBUG_TRACE, "Invalid record for translation unit: %s, file: %s", self.translation_unit, self._PrintableFilePath(fp)) else: # This is a new file -- for this include configuration at least. support_record = SupportRecord(self.support_master) currdir_idx = self.currdir_idx quote_dirs = self.quote_dirs angle_dirs = self.angle_dirs if resolution_mode == QUOTE: (fp_resolved_pair, fp_real_idx) = ( resolve(fp, currdir_idx, file_dir_idx, quote_dirs)) elif resolution_mode == ANGLE: (fp_resolved_pair, fp_real_idx) = ( resolve(fp, currdir_idx, None, angle_dirs)) elif resolution_mode == NEXT: # The node we return is just a dummy whose children are all the # possible resolvants. fp_resolved_pair = None fp_real_idx = None else: assert resolution_mode == RESOLVED assert fp_real_idx # this is the realpath corresponding to fp assert self.IsFilepathPair(fp) fp_resolved_pair = fp # we are given the resolvant if fp_resolved_pair: # The resolution succeeded. Before recursing, make sure to # mirror the path. Guard the call of MirrorPath with a cache # check; many files will have been visited before (for other # include directories). (d_, fp_) = fp_resolved_pair if (fp_resolved_pair, currdir_idx) not in self.mirrored: self.mirrored.add((fp_resolved_pair, currdir_idx)) self.mirror_path.DoPath( os.path.join(dir_map.string[currdir_idx], dir_map.string[d_], includepath_map.string[fp_]), currdir_idx, self.client_root_keeper.client_root) # We have fp_resolved_pair if and only if we have fp_real_idx assert not fp_resolved_pair or fp_real_idx assert not fp_real_idx or fp_resolved_pair # Now construct the node, even before we know the children; this # early construction/late filling-in of children allows us to stop # a recursion early, when key is in nodes_for_incl_config. A cyclic # structure may arise in this way. children = [] node = (fp_real_idx, fp_resolved_pair, children, support_record) nodes_for_incl_config[key] = node if not fp_resolved_pair: if resolution_mode == NEXT: # Create children of this dummy node. Try against all # directories in quote_dirs; that list includes the # angle_dirs. Recurse for each success. for d in quote_dirs: (fp_resolved_pair_, fp_real_idx_) = ( resolve(fp, currdir_idx, None, (d,))) if fp_resolved_pair_ != None: node_ = self.FindNode(nodes_for_incl_config, fp_resolved_pair_, RESOLVED, None, # file_dir_idx fp_real_idx_) children.append(node_) return node else: # For non-NEXT resolution modes return node # Now, we've got the resolution: (search directory, include path). assert (fp and fp_real_idx and fp_resolved_pair) (searchdir_idx, includepath_idx) = fp_resolved_pair # We need the realpath index of the current file directory. That's because # we are going to ask whether we have really visited this file, despite the # failure above to recognize it using a possibly relative name. Here, # 'really' means 'with respect to realpath'. Please see the class # documentation for why we need to calculate the realpath index of file # directory as part of the investigation of whether we have 'really' # encountered the file before. try: (fp_dirname_idx, fp_dirname_real_idx) = ( self.dirname_cache.cache[(currdir_idx, searchdir_idx, includepath_idx)]) except KeyError: (fp_dirname_idx, fp_dirname_real_idx) = ( self.dirname_cache.Lookup(currdir_idx, searchdir_idx, includepath_idx)) if resolution_mode != RESOLVED: # See whether we know about filepath post-resolution. if ((fp_real_idx, fp_dirname_real_idx) in nodes_for_incl_config and support_record.valid): statistics.master_hit_counter += 1 # Redo former decision about node: we use the one that is # already there. node = nodes_for_incl_config[(fp_real_idx, fp_dirname_real_idx)] nodes_for_incl_config[key] = node return node # Couldn't find node under real name. We'll remember the node, but have to # continue processing it. nodes_for_incl_config[(fp_real_idx, fp_dirname_real_idx)] = node # All chances of hitting the node cache are now exhausted! statistics.master_miss_counter += 1 # If we're revisiting because the support record was invalid, then it is # time to set it. support_record.valid = True # Try to get the cached result of parsing file. try: (quote_includes, angle_includes, expr_includes, next_includes) = ( self.file_cache[fp_real_idx]) except KeyError: # Parse the file. self.file_cache[fp_real_idx] = self.parse_file.Parse( self.realpath_map.string[fp_real_idx], self.symbol_table) (quote_includes, angle_includes, expr_includes, next_includes) = ( self.file_cache[fp_real_idx]) # Do the includes of the form #include "foo.h". for quote_filepath in quote_includes: node_ = self.FindNode(nodes_for_incl_config, quote_filepath, QUOTE, fp_dirname_idx) if node_: children.append(node_) support_record.Update(node_[self.SUPPORT_RECORD].support_id) # Do the includes of the form #include . for angle_filepath in angle_includes: node_ = self.FindNode(nodes_for_incl_config, angle_filepath, ANGLE) if node_: children.append(node_) support_record.Update(node_[self.SUPPORT_RECORD].support_id) if __debug__: if expr_includes: # Computed includes are interesting Debug(DEBUG_DATA, "FindNode, expr_includes: file: %s: '%s'", (isinstance(fp, int) and includepath_map.String(fp) or (isinstance(fp, tuple) and (dir_map.string[fp[0]], includepath_map.string[fp[1]]))), expr_includes) # Do the includes of the form #include expr, the computed includes. for expr in expr_includes: # Use multi-valued semantics to gather set of possible filepaths that the # C/C++ string expr may evaluate to under preprocessing semantics, given # the current symbol table. The symbols are all those of possible # expansions. (files, symbols) = ( macro_eval.ResolveExpr(includepath_map.Index, resolve, expr, self.currdir_idx, fp_dirname_idx, self.quote_dirs, self.angle_dirs, self.symbol_table)) for (fp_resolved_pair_, fp_real_idx_) in files: node_ = self.FindNode(nodes_for_incl_config, fp_resolved_pair_, RESOLVED, None, fp_real_idx_) if node_: children.append(node_) support_record.Update(node_[self.SUPPORT_RECORD].support_id) # Now the resolution of includes of the file of the present node depends # on symbols. support_record.UpdateSet(symbols) # Do includes of the form #include_next "foo.h" or # #include_next . for include_next_filepath in next_includes: node_ = self.FindNode(nodes_for_incl_config, include_next_filepath, NEXT) if node_: children.append(node_) support_record.Update(node_[self.SUPPORT_RECORD].support_id) return node def _CalculateIncludeClosureExceptSystem(self, node, include_closure): """Explore the subgraph reachable from node and gather real paths. Arguments: node: the node of the translation unit, the initial source file (see class documentation for a description of this tuple). include_closure: a map (see IncludeAnalyzer.RunAlgorithm documentation for a description of this map). Modifies: include_closure. We modify in place to avoid copying this big struct. """ assert not include_closure # should start out empty # We access prefix_cache's vars directly, so we need to ensure it's filled. self.systemdir_prefix_cache.FillCache(self.realpath_map) visited = set([]) starts_with_systemdir = self.systemdir_prefix_cache.cache dir_map_string = self.directory_map.string if not node: return stack = ([node]) # TODO(csilvers): consider using a deque if __debug__: statistics.len_calculated_closure_nonsys = 0 while stack: node = stack.pop(-1) id_ = id(node) if id_ in visited: continue visited.add(id_) # We optimized away: # # (fp_real_idx, fp_resolved_pair, children) = node # # so that the common case (that fp_real_idx is known to compiler) # is dispatched away with quickly: if node[0]: # fp_real_idx if __debug__: statistics.len_calculated_closure_nonsys += 1 # We ignore "system" includes like /usr/include/stdio.h. # These files are not likely to change, so it's safe to skip them. if not starts_with_systemdir[node[0]]: # Add the resolved filepath to those found for realpath. if node[0] not in include_closure: include_closure[node[0]] = [] searchdir_idx = node[1][0] # the searchdir part of fp_pair if (searchdir_idx and dir_map_string[searchdir_idx] and dir_map_string[searchdir_idx][0] == '/'): include_closure[node[0]].append(node[1]) # Even when a node does not describe a filepath, it may still # have children that do if it is a dummy node. # TODO(csilvers): see if it speeds things up to append node[2], # so stack is a list of lists. stack.extend(node[2]) statistics.len_calculated_closure = len(include_closure) distcc-3.1/source/include_server/parse_command.py0000750000175000017500000004407311115326647021351 0ustar wolffwolff#! /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 -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: None, '-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'(? 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%s)$" % '|'.join([re.escape(ext) for ext in basics.TRANSLATION_UNIT_MAP.keys()]))) def ParseCommandArgs(args, current_dir, includepath_map, dir_map, compiler_defaults, timer=None): """Parse arguments like -I to make include directory lists. Arguments: args: list of arguments (strings) current_dir: string includepath_map: a MapToIndex object dir_map: a DirectoryMapToIndex object compiler_defaults: a CompilerDefaults object timer: a basics.IncludeAnalyzerTimer object Returns: (quote_dirs, angle_dirs, files, source_file, source_file_prefix, dopts) where: quote_dirs: a list of dir_map-indexed directories angle_dirs: a list of dir_map-indexed directories files: a list of includepath_map-indexed files source_file_prefix: the source file name with extension stripped dopts: a list of items as returned by _SplitMacroArg Modifies: compiler_defaults """ if __debug__: Debug(DEBUG_TRACE, "ParseCommand %s" % args) assert isinstance(dir_map, cache_basics.DirectoryMapToIndex) assert isinstance(includepath_map, cache_basics.MapToIndex) parse_state = ParseState() if len(args) < 2: raise NotCoveredError("Command line: too few arguments.") compiler = args[0] i = 1 while i < len(args): # First, deal with everything that's not a flag-option if args[i][0] != '-' or args[i] == '-': # - is the stdin file if args[i].startswith('"-'): pass # TODO(csilvers): parse arg inside quotes? else: parse_state.file_names.append(args[i]) # if not a flag, it's a file i += 1 continue # Deal with the one-letter options -- the kind most commonly seen. # We need to figure out whether the option-argument is glommed on to # the end of the option ("-Dfoo"), or is a separate word ("-D foo"). action = CPP_OPTIONS_ONE_LETTER.get(args[i][1]) # letter after the - if action: arg = args[i][2:] if arg: # the glommed-onto-end case action(parse_state, arg) i += 1 else: # the separate-word case try: action(parse_state, args[i+1]) i += 2 except IndexError: raise NotCoveredError("No argument found for option '%s'" % args[i]) continue # Deal with the have-arg options with the arg as the 2nd word ("-MF foo"). action = CPP_OPTIONS_TWO_WORDS.get(args[i]) if action: try: action(parse_state, args[i+1]) i += 2 except IndexError: raise NotCoveredError("No argument found for option '%s'" % args[i]) continue # Deal with the 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) suffix = language_match.group('suffix') parse_state.language = basics.TRANSLATION_UNIT_MAP[suffix] assert parse_state.language in basics.LANGUAGES compiler_defaults.SetSystemDirsDefaults(compiler, parse_state.language, timer) def IndexDirs(dir_list): """Normalize directory names and index. Remove leading "./" and trailing "/"'s from directory paths in dir_list before indexing them according to dir_map. """ S = basics.SafeNormPath I = dir_map.Index return [I(S(d)) for d in dir_list] # Now string the directory lists together according to CPP semantics. angle_dirs = IndexDirs(parse_state.i_dirs) angle_dirs.extend(IndexDirs(parse_state.before_system_dirs)) if not parse_state.nostdinc: angle_dirs.extend( IndexDirs(compiler_defaults.system_dirs_default [compiler][parse_state.language])) angle_dirs.extend(IndexDirs(parse_state.after_system_dirs)) quote_dirs = IndexDirs(parse_state.quote_dirs) quote_dirs.extend(angle_dirs) angle_dirs = tuple(angle_dirs) quote_dirs = tuple(quote_dirs) # Include files are meant to be sent to the server. They do not pose the # danger of absolute includes, which includepath_map is designed to avoid. include_files = tuple( [includepath_map.Index(basics.SafeNormPath(f), ignore_absolute_path_warning=True) for f in parse_state.include_files]) if __debug__: Debug(DEBUG_TRACE, ("ParseCommand result: %s %s %s %s %s %s" % (quote_dirs, angle_dirs, include_files, source_file, source_file_prefix, parse_state.Dopts))) return (quote_dirs, angle_dirs, include_files, source_file, source_file_prefix, parse_state.Dopts) distcc-3.1/source/include_server/include_server_test.py0000750000175000017500000001357611115326647022615 0ustar wolffwolff#!/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 sys import traceback import unittest import basics import cache_basics import parse_command import statistics import include_analyzer_memoizing_node import include_server import distcc_pump_c_extensions NotCoveredError = basics.NotCoveredError class IncludeServerTest(unittest.TestCase): def setUp(self): statistics.StartTiming() basics.opt_print_statistics = False basics.opt_debug_pattern = 1 def tearDown(self): if basics.opt_print_statistics: statistics.EndTiming() statistics.PrintStatistics(self.include_analyzer) def CanonicalPaths(self, dirs): return set([ self.canonical_path.Canonicalize(f) for f in dirs ]) def RetrieveCanonicalPaths(self, files): return set([ self.include_analyzer.realpath_map.string[f] for f in files ]) def test_IncludeHandler_handle(self): self_test = self client_root_keeper = basics.ClientRootKeeper() old_RWcd = distcc_pump_c_extensions.RCwd distcc_pump_c_extensions.RCwd = None # to be set below old_RArgv = distcc_pump_c_extensions.RArgv distcc_pump_c_extensions.RArgv = None # to be set below old_XArgv = distcc_pump_c_extensions.XArgv distcc_pump_c_extensions.XArgv = lambda _, __: None old_StreamRequestHandler = ( include_server.SocketServer.StreamRequestHandler) class Mock_StreamRequestHandler(object): def __init__(self): self.rfile = lambda: None self.rfile.fileno = lambda: 27 self.wfile = lambda: None self.wfile.fileno = lambda: 27 include_server.SocketServer.StreamRequestHandler = ( Mock_StreamRequestHandler) include_analyzer = ( include_analyzer_memoizing_node. IncludeAnalyzerMemoizingNode(client_root_keeper)) class Mock_EmailSender(object): def __init(self): self.expect = lambda: None def MaybeSendEmail(self, fd, force=False, never=False): fd.seek(0) text = fd.read() self.expect(text, force, never) fd.close() raise mock_email_sender = include_analyzer.email_sender = Mock_EmailSender() include_handler = ( include_server.DistccIncludeHandlerGenerator(include_analyzer)()) # Wow, that was a lot of set-up. Now exercise the include server and # analyzer with an emphasis on triggering exceptions. # Exercise 1: non-existent translation unit. distcc_pump_c_extensions.RArgv = lambda self: [ "gcc", "parse.c" ] distcc_pump_c_extensions.RCwd = lambda self: os.getcwd() def Expect1(txt, force, never): self_test.assert_( "Include server not covering: " + "Could not find translation unit 'parse.c'" in txt, txt) self_test.assertEqual(never, True) mock_email_sender.expect = Expect1 try: include_handler.handle() except NotCoveredError: pass else: raise AssertionError # Exercise 2: provoke assertion error in cache_basics by providing an # entirely false value of current directory as provided in RCwd. distcc_pump_c_extensions.RArgv = lambda self: [ "gcc", "parse.c" ] distcc_pump_c_extensions.RCwd = lambda self: "/" # The cwd will be changed because of false value. oldcwd = os.getcwd() # We must distinguish between provoked and erroneous exceptions. So, we # mock out, in a sense, the provoked assertion exception that we # expect. The variable got_here allows us to filter the provoked exception # away from unexpected ones. got_here = [] def Expect2(txt, force, never): self_test.assert_("Include server internal error" in txt, txt) self_test.assert_("exceptions.AssertionError" in txt, txt) self_test.assert_("for translation unit 'parse.c'" in txt, 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, txt) # Now check that this email is scheduled to not be sent. self_test.assertEqual(never, True) mock_email_sender.expect = Expect3 try: include_handler.handle() except NotCoveredError: pass distcc_pump_c_extensions.RWcd = old_RWcd distcc_pump_c_extensions.RArgv = old_RArgv distcc_pump_c_extensions.XArgv = old_XArgv include_server.SocketServer.StreamRequestHandler = ( old_StreamRequestHandler) unittest.main() distcc-3.1/source/include_server/parse_file.py0000750000175000017500000003034711115326647020651 0ustar wolffwolff#! /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 # group('directive') -- what we're after [#] # the pound sign [ \t]* # space(s) (define|include_next|include|import)\b # the directive ((?!\\\n).)* # the rest on this line: zero or more # characters, each not a backslash that # is followed by \n (\\\n((?!\\\n).)*)* # (backslash + \n + rest of line)* ) """, re.VERBOSE + re.MULTILINE) NOT_COMMA_OR_PARENS = "([^(),])" # For parsing macro expressions of the form: # symbol # symbol (something, ..., something), where something is not ',', '(', or ')' MACRO_EXPR = r""" (?P\w+) # the symbol, named 'symbol' ( \s* [(] \s* # beginning parenthesis (?P # a parenthesized expression (with no # containing expressions -- a limitation) # named 'args' %(NOT_COMMA_OR_PARENS)s* # the first argument (if it exists) ([,]%(NOT_COMMA_OR_PARENS)s*)* # subsequent arguments ) [)] # ending parenthesis )?""" % {'NOT_COMMA_OR_PARENS': NOT_COMMA_OR_PARENS} MACRO_EXPR_RE = re.compile(MACRO_EXPR, re.VERBOSE) # Nice little parser of certain directive lines (after backslash-ended # line continuations and comments are removed) DIRECTIVE_RE = re.compile(r""" ^[ \t]* [#] [ \t]* ( ((?P include_next | include | import) \s* ( "(?P (\w|[_/.+-])*)" | # "bar/foo.h" <(?P (\w|[_/.+-])*)> | # (?P .*?)) # expr, match . minimally ) | (?P define \s+ (?P %s) # insert MACRO_EXPR here \s* (?P .*?)) # match . minimally before # trailing white space ) \s* # trailing whitespace ((/[*]|//).*)? # optional trailing comment start $ """ % MACRO_EXPR, re.VERBOSE) # INCLUDE_STRING_RE = re.compile(r""" ^ \s* ( "\s*(?P (\w|[_/.+-])*)\s*" | <\s*(?P (\w|[_/.+-])*)\s*> ) \s* $ """, re.VERBOSE) # For ridding lines of backslash BACKSLASH_RE = re.compile(r"\\\n", re.MULTILINE) # For matching non-comment prefix of line. COMMENT_RE = re.compile(r"((?!/[*]|//).)*") # FOR SEARCHING AFTER /* .. */. PAIRED_COMMENT_RE = re.compile(r"(/[*].*?[*]/)") def InsertMacroDefInTable(lhs, rhs, symbol_table, callback_function): """Insert the definition of a pair (lhs, rhs) into symbol table. Arguments: lhs: a string, of the form "symbol" or "symbol(param1, ..., paramN)" rhs: a string symbol_table: where the definition will be inserted callback_function: a function called with value "symbol" """ m_expr = MACRO_EXPR_RE.match(lhs) if m_expr.end(0) != len(lhs): raise NotCoveredError( "Unexpected macro definition with LHS: '%s'." % lhs) # Calculate the definition df, either # - a pair ([arg_1, .., arg_n], rhs) where arg_i is the # i'th formal parameter (function-like macro definition), or # - just a symbol (object-like macro definition) if m_expr.group('args') != None: # perhaps '' # A function-like macro definition. # Construct pair (list of formal parameters, rhs). args = m_expr.group('args').split(',') df = args, rhs # lhs is adjusted to be just the 'function' name lhs = m_expr.group('symbol') else: # m_expr.group('args') # An object-like macro definition assert m_expr.group('symbol') == lhs df = rhs if lhs not in symbol_table: symbol_table[lhs] = [df] else: symbol_table[lhs].append(df) callback_function(lhs) class ParseFile(object): """Parser class for syntax understood by CPP, the C and C++ preprocessor. An instance of this class defines the Parse method.""" def __init__(self, includepath_map): """Constructor. Make a parser. Arguments: includepath_map: string-to-index map for includepaths """ assert isinstance(includepath_map, cache_basics.MapToIndex) self.includepath_map = includepath_map self.define_callback = lambda x: None def SetDefineCallback(self, callback_function): """Set a callback function, which is invoked for '#define's. The function is called as callback_function(symbol), whenever a '#define' of symbol is parsed. The callback allows an include processor to adjust its notion of which expressions are still current. If we (the include processor) already met #define A B and later meet #define B whether this is the first definition of B or not, then the possible meanings of A have changed. We set up a callback to identify such situations.""" self.define_callback = callback_function def _ParseFine(self, poundsign_match, includepath_map_index, file_contents, symbol_table, quote_includes, angle_includes, expr_includes, next_includes): """Helper function for ParseFile.""" Debug(DEBUG_TRACE2, "_ParseFine %s", file_contents[poundsign_match.start('directive'): poundsign_match.end('directive')]) m = DIRECTIVE_RE.match( # parse the directive PAIRED_COMMENT_RE.sub( # remove possible paired comments "", BACKSLASH_RE.sub( # get rid of lines ending in backslash "", file_contents[poundsign_match.start('directive'): poundsign_match.end('directive')]))) if m: try: groupdict = m.groupdict() if groupdict['include'] == 'include' or \ groupdict['include'] == 'import': if groupdict['quote']: quote_includes.append(includepath_map_index(m.group('quote'))) elif groupdict['angle']: angle_includes.append(includepath_map_index(m.group('angle'))) elif groupdict['expr']: expr_includes.append(m.group('expr').rstrip()) else: assert False elif groupdict['include'] == 'include_next': # We do not, in fact, distinguish between the two kinds of # include_next's, because we conservatively assume that they are of # the quote variety. if groupdict['quote']: next_includes.append(includepath_map_index(m.group('quote'))) elif groupdict['angle']: next_includes.append(includepath_map_index(m.group('angle'))) # The following restriction would not be too hard to remove. elif groupdict['expr']: NotCoveredError( "For include_next: cannot deal with computed include here.") else: assert False raise NotCoveredError("include_next not parsed") elif groupdict['define']: if not groupdict['lhs']: raise NotCoveredError("Unexpected macro definition with no LHS.") else: lhs = m.group('lhs') rhs = groupdict['rhs'] and groupdict['rhs'] or None InsertMacroDefInTable(lhs, rhs, symbol_table, self.define_callback) except NotCoveredError, 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 # # 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) distcc-3.1/source/include_server/include_analyzer_memoizing_node_test.py0000750000175000017500000002045711115326647026213 0ustar wolffwolff#! /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 client_root_keeper = basics.ClientRootKeeper() self.include_analyzer = ( include_analyzer_memoizing_node.IncludeAnalyzerMemoizingNode( client_root_keeper)) self.includepath_map = self.include_analyzer.includepath_map self.canonical_path = self.include_analyzer.canonical_path self.directory_map = self.include_analyzer.directory_map self.realpath_map = self.include_analyzer.realpath_map def test__CalculateIncludeClosureExceptSystem(self): """Construct a summary graph, then calculate closure and check.""" includepath_map = self.includepath_map canonical_path = self.canonical_path directory_map = self.directory_map realpath_map = self.realpath_map # Create summary graph with structure A -> B -> C -> B and B -> D -> C' -> # E. Note that B has two immediate successors. Assume the current dir is # /curr (for all nodes). The include graph is made for a searchlist [src, /, # /dirlink]. Note that the first directory in the searchlist is relative. # For simplicity, we consider angled resolution only. Here is a description # of the nodes. # # - Nodes A, B correspond to includepaths a.h and b.h, which are relatively # resolved because they are found in src, which means absolute # directory /curr/src. These filepaths are thus resolved to src/a.h and # src/b.h and their corresponding realpaths are /curr/src/a.h and # /curr/src/b.h. The realpaths are all what is recorded in the include # closure, because the files are relatively resolved. # # - Nodes C, C', and E are absolutely resolved includepaths. More # specifically: # # - Nodes C and C' correspond to includepath dir/c.h and c.h, which # during resolution were found in / and /dirlink, respectively. # However, /dirlink is a symbolic link to /dir, which is a real # directory, so C and C' in fact correspond to the same realpath # namely /dir/c.h. # # - Node E corresponds to includepath dir/e.h and was found during # resolution to be in /. So, the realpath of this node is /dir/e.h. # # - Node D is a dummy and it is not recorded in the include closure. Still, # its non-dummy descendants are recorded. src_idx = directory_map.Index("src") curr_idx = directory_map.Index("/curr") root_idx = directory_map.Index("/") dirlink_idx = directory_map.Index("/dirlink") curr_src_idx = directory_map.Index("/curr/src") dir_idx = directory_map.Index("/dir") A_children = [] A = (realpath_map.Index("/curr/src/a.h"), (src_idx, includepath_map.Index("a.h")), A_children) B_children = [] B = (realpath_map.Index("/curr/src/b.h"), (src_idx, includepath_map.Index("b.h")), B_children) C_children = [] C = (realpath_map.Index("/dir/c.h"), (root_idx, includepath_map.Index("dir/c.h")), C_children) C__children = [] C_ = (realpath_map.Index("/dir/c.h"), (dirlink_idx, includepath_map.Index("c.h")), C__children) D_children = [] D = (None, None, D_children) E_children = [] E = (realpath_map.Index("/dir/e.h"), (root_idx, includepath_map.Index("dir/e.h")), E_children) A_children.extend([B]) B_children.extend([C, D]) C_children.extend([B]) C__children.extend([E]) D_children.extend([C_]) E_children.extend([]) include_closure = {} self.include_analyzer._CalculateIncludeClosureExceptSystem(A, include_closure) stringified_include_closure = self._ToString(include_closure) # /curr/src/a.h is not known under absolute pathnames. self.assertEqual(stringified_include_closure['/curr/src/a.h'], []) # Neither is /curr/src/b.h. self.assertEqual(stringified_include_closure['/curr/src/b.h'], []) # But, /dir/c.h is known under two different absolute names. self.assertEqual(stringified_include_closure['/dir/c.h'], [('/dirlink/', 'c.h'), ('/', 'dir/c.h')]) # And, dir/e.h is known under exactly one absolute name. self.assertEqual(stringified_include_closure['/dir/e.h'], [('/', 'dir/e.h')]) # That is all and nothing more. self.assertEqual(len(stringified_include_closure), 4) def _ConstructDistccCommandLine(self, src_stem): # A command line, which is more or less the one found in the # generated Makefile for distcc. We don't need the exact form of # the command." return ("gcc -DHAVE_CONFIG_H -D_GNU_SOURCE" + " -I./src" + ' -DSYSCONFDIR="/usr/local/etc"' + ' -DPKGDATADIR="/usr/local/share/distcc"' + " -Isrc" + " -I./lzo" + " -include include_me.h " + " -o src/%s.o" + " -c src/%s.c") % (src_stem, src_stem) def test__CalculateIncludeClosureExceptSystem_on_distcc(self): includepath_map = self.includepath_map canonical_path = self.canonical_path directory_map = self.directory_map realpath_map = self.realpath_map include_analyzer = self.include_analyzer current_dir = os.path.realpath("test_data/distcc") os.chdir(current_dir) src_stem = "distcc" cmd = self._ConstructDistccCommandLine(src_stem) parsed_command = ( parse_command.ParseCommandArgs( parse_command.ParseCommandLine(cmd), current_dir, include_analyzer.includepath_map, include_analyzer.directory_map, include_analyzer.compiler_defaults)) (include_analyzer.quote_dirs, include_analyzer.angle_dirs, include_analyzer.include_files, translation_unit, include_analyzer.result_file_prefix, _) = parsed_command self.assertEqual(translation_unit, "src/%s.c" % src_stem) expected_suffixes = [ "src/include_me.h", "src/implicit.h", "src/distcc.c", "src/config.h", "src/distcc.h", "src/state.h", "src/compile.h", "src/trace.h", "src/exitcode.h", "src/util.h", "src/hosts.h", "src/bulk.h", "src/emaillog.h"] include_closure = ( include_analyzer.ProcessCompilationCommand(current_dir, parsed_command)) expected_prefix = os.getcwd() + '/' expected = set([ expected_prefix + expected_suffix for expected_suffix in expected_suffixes ]) self.assertEqual(set([realpath_map.string[key] for key in include_closure.keys()]), expected) for rp_idx in include_closure: self.assertEqual(len(include_closure[rp_idx]), 0) # TODO(klarlund): massage command so as to test that with a # different search path files are reported as absolute. That is, # provoke pairs (directory_idx, includepath_idx) to exist in # include_closure[rp_idx]. def tearDown(self): pass unittest.main() distcc-3.1/source/include_server/basics.py0000750000175000017500000003533211115326647020003 0ustar wolffwolff#!/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 glob import os.path import resource import signal import shutil import sys import tempfile # MANAGEMENT OF TEMPORARY LOCATIONS FOR GENERATIONS OF COMPRESSED FILES class ClientRootKeeper(object): """Determine the tmp directory to use for compressed files. Use the RAM disk-like /dev/shm as default place to store compressed files if available. The protocol between the include server and distcc client stipulates that the top three directories constitute the prefix prepended to absolute file paths. Instance vars: client_tmp: a path, the place for creation of temporary directories. client_root: a path, the current such temporary directory _client_root_before_padding: a path kept for testing purposes A typical client root looks like: - /tmp/tmpBDoZQV.include_server-6642-13/padding, or - /dev/shm/tmpBDoZQV.include_server-6642-19 Note that each path has exactly three directory components to it. This is an invariant. Some client roots are padded with '/padding' to satisfy the invariant. """ # This constant is embedded in names of client root directories. INCLUDE_SERVER_NAME = 'include_server' def __init__(self): """Constructor.""" if 'DISTCC_CLIENT_TMP' in os.environ: self.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): self.client_tmp = '/dev/shm' else: self.client_tmp = '/tmp' if not self.client_tmp or self.client_tmp[0] != '/': sys.exit("""DISTCC_CLIENT_TMP must start with '/'.""") self.client_tmp = self.client_tmp.rstrip('/') # 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(self.client_tmp.split('/')) > 3: sys.exit('DISTCC_CLIENT_TMP must have at most two directory levels.') self.number_missing_levels = 3 - len(self.client_tmp.split('/')) self.client_root = None def Glob(self, pid_expr): """Glob unpadded client roots whose pid is matched by pid expression.""" return glob.glob('%s/*.%s-%s-*' % (self.client_tmp, self.INCLUDE_SERVER_NAME, pid_expr)) def ClientRootMakedir(self, generation): """Make a new client directory for a generation of compressed files. Arguments: generation: a natural number, usually 1 or slightly bigger; this number, minus 1, indicates how many times a reset of the caches has taken place. """ try: # Create a unique identifier that will never repeat. Use pid as suffix for # cleanout mechanism that wipes files not associated with a running pid. self._client_root_before_padding = tempfile.mkdtemp( '.%s-%s-%d' % (self.INCLUDE_SERVER_NAME, os.getpid(), generation), dir=self.client_tmp) self.client_root = (self._client_root_before_padding + '/padding' * self.number_missing_levels) if not os.path.isdir(self.client_root): os.makedirs(self.client_root) except (IOError, OSError), why: sys.exit('Could not create client root directory %s: %s' % (self.client_root, why)) def CleanOutClientRoots(self, pid=None): """Delete client root directories pertaining to this process. Args: pid: None (which means 'pid of current process') or an integer """ if not pid: pid = os.getpid() for client_root in self.Glob(str(pid)): shutil.rmtree(client_root, ignore_errors=True) def CleanOutOthers(self): """Search for left-overs from include servers that have passed away.""" # Find all client root subdirectories whether abandoned or not. distcc_directories = self.Glob('*') for directory in distcc_directories: # Fish out pid from end of directory name. hyphen_ultimate_position = directory.rfind('-') assert hyphen_ultimate_position != -1 hyphen_penultimate_position = directory.rfind('-', 0, hyphen_ultimate_position) assert hyphen_penultimate_position != -1 pid_str = directory[hyphen_penultimate_position + 1: hyphen_ultimate_position] try: pid = int(pid_str) except ValueError: continue # Happens only if a spoofer is around. try: # Got a pid; does it still exist? os.getpgid(pid) continue except OSError: # Process pid does not exist. Nuke its associated files. This will # of course only succeed if the files belong the current uid of # this process. if not os.access(directory, os.W_OK): continue # no access, not ours Debug(DEBUG_TRACE, "Cleaning out '%s' after defunct include server." % directory) self.CleanOutClientRoots(pid) # COMPILATION SERVER # An upper bound on the number of directory components in the temporary # directory on the distccd server that corresponds to the root directory # on the client machine. Normally the server root is /tmp/distccd_XXXXXX. # But it could be something different if TMPDIR is set when distccd is # started. See dcc_get_tmp_top() in ../src/tempfile.c. # It turns out that our own test infrastructure (test/testdistcc.py) # sets TMPDIR before invoking distccd, so this needs to be reasonably # high, otherwise 'make distcheck' will fail. MAX_COMPONENTS_IN_SERVER_ROOT = 20 # EMAILS # For automated emails, see also src/emaillog.h. DCC_EMAILLOG_WHOM_TO_BLAME = os.getenv('DISTCC_EMAILLOG_WHOM_TO_BLAME', 'distcc-pump-errors') EMAIL_SUBJECT = 'distcc-pump include server email' CANT_SEND_MESSAGE = """Please notify %s that the distcc-pump include server tried to send them email but failed.""" % DCC_EMAILLOG_WHOM_TO_BLAME MAX_EMAILS_TO_SEND = 3 # TIME QUOTAS (SOLVING THE HALTING PROBLEM) # The maximum user time the include server is allowed handling one request. This # is a critical parameter because all caches are reset if this time is # exceeded. And if all caches are reset, then the next request may take much # longer time, possibly again exceeding the quota. The parameter is also of # importance to builds that involve compilations that distcc-pump does not grok: # an amount of time roughly equal to this quota is wasted before CPP is invoked # instead. USER_TIME_QUOTA = 3.8 # seconds # How often the following question is answered: has too much user time been # spent in the include handler servicing the current request? # # FIXME(klarlund): SIGALRM should not be raised in code that has I/O. Fix # include server so that this is guaranteed not to happen. Until then, we are # careful to wait a full 4 s before issuing SIGALRM. USER_TIME_QUOTA_CHECK_INTERVAL_TIME = 4 # seconds, an integer # ALGORITHMS SIMPLE = 0 # not implemented MEMOIZING = 1 # only one currently implemented ALGORITHMS = [SIMPLE, MEMOIZING] # PYTHON TUNING # The default for the first parameter of gc.set_threshold is 700; see # http://www.isi.edu/~chiang/python.html for a discussion of why this parameter # can be bumped up considerably for speed-up. The new default of 10000 was # tested on a very large application, where include server time CPU time drops # from 151s to 118s (best times out of 10 runs). There was no seeming changes to # memory usage. Trying with 100,000 did not speed up the application further. GC_THRESHOLD = 10000 # FLAGS FOR COMMAND LINE OPTIONS opt_algorithm = MEMOIZING # currently, only choice opt_debug_pattern = 1 # see DEBUG below opt_email_bound = MAX_EMAILS_TO_SEND opt_exact_analysis = False # use CPP instead of include analyzer opt_print_times = False opt_path_observation_re = None opt_send_email = False opt_simple_algorithm = False opt_stat_reset_triggers = {} opt_statistics = False opt_unsafe_absolute_includes = False opt_verify = False # whether to compare calculated include closure to that # produced by compiler opt_write_include_closure = False # write include closures to file # HELPER FUNCTION FOR STAT_RESET_TRIGGERS def Stamp(path): """Return a stamp characterizing a file and its modification time.""" try: st_inf = os.stat(path) # The inode and device identify a file uniquely. return (st_inf.st_mtime, st_inf.st_ino, st_inf.st_dev) except OSError: return None # LANGUAGES AND FILE EXTENSIONS # The languages that we recognize. LANGUAGES = set(['c', 'c++', 'objective-c', 'objective-c++']) # The suffixes, following last period, used for source files and # preprocessed files, each with their corresponding source language. TRANSLATION_UNIT_MAP = { # C 'c': 'c', 'i': 'c', # C++ 'cc': 'c++', 'cpp': 'c++', 'cxx': 'c++', 'C': 'c++', 'CXX': 'c++', 'ii': 'c++', # Objective C 'm': 'objective-c', 'mi': 'objective-c', # Objective C++ 'mm': 'objective-c++', 'M': 'objective-c++', 'mii': 'objective-c++', } # All languages are described by suffixes. assert set(TRANSLATION_UNIT_MAP.values()) == LANGUAGES # DEBUG # Debugging is controlled by the 5 least significant bits of # opt_debug_pattern. DEBUG_WARNING = 1 # For warnings DEBUG_TRACE = 2 # For tracing functions (upper level) DEBUG_TRACE1 = 4 # For tracing functions (medium level) DEBUG_TRACE2 = 8 # For tracing functions (lower level) DEBUG_DATA = 16 # For printing data DEBUG_NUM_BITS = 5 # The cardinality of {1,2,4,8,16} def Debug(trigger_pattern, message, *params): """Print message to stderr depending on trigger pattern. Args: trigger_pattern: a bit vector (as an integer) message: a format string params: arguments to message """ # TODO(klarlund): use Python's logging module. triggered = opt_debug_pattern & trigger_pattern if triggered: i = 1 for unused_j in range(DEBUG_NUM_BITS): if i & DEBUG_WARNING & triggered: print >> 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): """For include server errors.""" pass class NotCoveredError(Error): """Exception for included file not covered by include processing.""" def __init__(self, message, source_file=None, line_number=None, send_email=True): """Constructor. Arguments: message: text of error message source_file: name of source_file if known line_number: an integer, if known send_email: a Boolean, if False then never send email These arguments are all stored in the exception. However, the source_file and line_number are appended, in a syntax defined here, to the message before it is stored as self.args[0] through invocation of the Error constructor. """ assert not line_number or source_file self.source_file = None self.line_number = None self.send_email = send_email if source_file: # Mark this exception as mentioning the source_file. self.source_file = source_file # Line numbers are not currently used. if line_number: self.line_number = line_number message = ("""File: '%s', line: %s: %s""" % (source_file, line_number, message)) else: message = """File: '%s': %s""" % (source_file, message) # Message, a string, becomes self.args[0] Error.__init__(self, message) class NotCoveredTimeOutError(NotCoveredError): """Raised when spending too much time analyzing dependencies.""" pass class IncludeAnalyzerTimer(object): """Start a timer limiting CPU time for servicing a single request. We use user time so that a network hiccup will not entail a cache reset if, say, we are using NFS. An object of this class must be instantiated so that, no matter what, the Cancel method is eventually called. This reinstates the original timer (if present). """ def __init__(self): self.start_utime = resource.getrusage(resource.RUSAGE_SELF).ru_utime self.old = signal.signal(signal.SIGALRM, self._TimeIsUp) signal.alarm(USER_TIME_QUOTA_CHECK_INTERVAL_TIME) def _TimeIsUp(self, unused_sig_number, unused_frame): """Check CPU time spent and raise exception or reschedule.""" if (resource.getrusage(resource.RUSAGE_SELF).ru_utime > self.start_utime + USER_TIME_QUOTA): raise NotCoveredTimeOutError(('Bailing out because include server ' + 'spent more than %3.1fs user time ' + 'handling request') % USER_TIME_QUOTA) else: # Reschedule ourselves. signal.alarm(USER_TIME_QUOTA_CHECK_INTERVAL_TIME) def Stop(self): signal.alarm(0) def Start(self): signal.alarm(USER_TIME_QUOTA_CHECK_INTERVAL_TIME) def Cancel(self): """Must be called eventually. See class documentation.""" sys.stdout.flush() signal.alarm(0) signal.signal(signal.SIGALRM, self.old) class SignalSIGTERM(Error): pass def RaiseSignalSIGTERM(*unused_args): """Raise SignalSIGTERM. Use signal.signal for binding this function to SIGTERM. """ raise SignalSIGTERM # COMMON FUNCTIONS def SafeNormPath(path): """Safe, but limited, version of os.path.normpath. Args: path: a string Returns: a string Python's os.path.normpath is an unsafe operation; the result may not point to the same file as the argument. Instead, this function just removes initial './'s and a final '/'s if present. """ if path == '.': return '' else: while path.startswith('./'): path = path[2:] return path.rstrip('/') distcc-3.1/source/include_server/basics_test.py0000750000175000017500000001035011115326647021033 0ustar wolffwolff#! /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 tempfile import unittest import basics class BasicsTest(unittest.TestCase): def setUp(self): basics.opt_debug_pattern = 1 def tearDown(self): pass def test_ClientRootKeeper(self): os.environ['DISTCC_CLIENT_TMP'] = 'to/be' self.assertRaises(SystemExit, basics.ClientRootKeeper) os.environ['DISTCC_CLIENT_TMP'] = '/to/be/or' self.assertRaises(SystemExit, basics.ClientRootKeeper) try: tempfile_mkdtemp = tempfile.mkdtemp os_makedirs = os.makedirs def Mock_tempfile_mkdtemp(pat, dir): self.assert_((pat, dir) in [('.%s-%s-%d' % (basics.ClientRootKeeper.INCLUDE_SERVER_NAME, os.getpid(), generation), prefix) for generation, prefix in [(1,'/to/be'), (2, '/to')]]) return (dir == '/to/be' and '/to/be/xxxxxx' or dir == '/to' and '/to/xxxxxxx') def Mock_os_makedirs(f, *unused_args): if not f.startswith('/to/'): raise Exception, f tempfile.mkdtemp = Mock_tempfile_mkdtemp os.makedirs = Mock_os_makedirs os.environ['DISTCC_CLIENT_TMP'] = '/to/be' client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(1) self.assertEqual(os.path.dirname(client_root_keeper.client_root), "/to/be") os.environ['DISTCC_CLIENT_TMP'] = '/to' client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(2) self.assertEqual(os.path.dirname( os.path.dirname(client_root_keeper.client_root)), "/to") self.assertEqual(os.path.basename(client_root_keeper.client_root), "padding") self.assertEqual(len( [ None for ch in client_root_keeper.client_root if ch == '/' ]), 3) finally: tempfile.mkdtemp = tempfile_mkdtemp os.makedirs = os_makedirs def test_ClientRootKeeper_Deletions(self): """Test whether directories emerge and go away appropriately.""" # Test with a one-level value of DISTCC_CLIENT_TMP. os.environ['DISTCC_CLIENT_TMP'] = '/tmp' client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(117) self.assert_(os.path.isdir(client_root_keeper._client_root_before_padding)) self.assert_(os.path.isdir(client_root_keeper.client_root)) self.assert_(client_root_keeper.client_root.endswith('/padding')) client_root_keeper.ClientRootMakedir(118) client_root_keeper.CleanOutClientRoots() # Directories must be gone now! self.assert_(not os.path.isdir( client_root_keeper._client_root_before_padding)) # Test with a two-level value of DISTCC_CLIENT_TMP. try: os.environ['DISTCC_CLIENT_TMP'] = tempfile.mkdtemp('basics_test', dir='/tmp') client_root_keeper = basics.ClientRootKeeper() client_root_keeper.ClientRootMakedir(117) self.assert_(os.path.isdir( client_root_keeper._client_root_before_padding)) self.assert_(os.path.isdir(client_root_keeper.client_root)) client_root_keeper.ClientRootMakedir(118) client_root_keeper.CleanOutClientRoots() self.assert_(os.path.isdir, client_root_keeper._client_root_before_padding) finally: os.rmdir(os.environ['DISTCC_CLIENT_TMP']) unittest.main() distcc-3.1/source/include_server/__init__.py0000750000175000017500000000000011115326647020256 0ustar wolffwolffdistcc-3.1/source/include_server/test_data/0000750000175000017500000000000011115327762020123 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/test_computed_includes/0000750000175000017500000000000011115327763024671 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/test_computed_includes/srcA.c0000640000175000017500000000017111115326646025724 0ustar wolffwolff#define INCL "inclA.h" #include "helper.c" #include int main() { printf(MSG); printf("\n"); return 0; } distcc-3.1/source/include_server/test_data/test_computed_includes/incl.h0000640000175000017500000000002411115326646025763 0ustar wolffwolff#define MSG "hello" distcc-3.1/source/include_server/test_data/test_computed_includes/src.c0000640000175000017500000000016711115326646025630 0ustar wolffwolff#define INCL "incl.h" #include "helper.c" #include int main() { printf(MSG); printf("\n"); return 0; } distcc-3.1/source/include_server/test_data/test_computed_includes/helper.c0000640000175000017500000000001611115326646026311 0ustar wolffwolff#include INCL distcc-3.1/source/include_server/test_data/test_computed_includes/inclA.h0000640000175000017500000000002611115326646026066 0ustar wolffwolff#define MSG "hello A" distcc-3.1/source/include_server/test_data/contains_abs_include.c0000640000175000017500000000003411115326647024434 0ustar wolffwolff#include "/love/of/my/life" distcc-3.1/source/include_server/test_data/maps/0000750000175000017500000000000011115327763021064 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/maps/foo.tpl.varnames.h0000640000175000017500000000000111115326645024417 0ustar wolffwolff distcc-3.1/source/include_server/test_data/dfoo/0000750000175000017500000000000011115327762021052 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/dfoo/foo2.h0000640000175000017500000000015511115326645022071 0ustar wolffwolff#define dfoo_foo2_h // The include below is not valid syntax and should be ignored. #include ../dbar/foo.h distcc-3.1/source/include_server/test_data/dfoo/i_am_perhaps_a_directory.h0000640000175000017500000000000011115326645026224 0ustar wolffwolffdistcc-3.1/source/include_server/test_data/dfoo/foo.h0000750000175000017500000000006111115326645022005 0ustar wolffwolff#include "foo2.h" #include "../dbar/dbar1/bar.h" distcc-3.1/source/include_server/test_data/dfoo/stat_triggers.h0000640000175000017500000000000011115326645024072 0ustar wolffwolffdistcc-3.1/source/include_server/test_data/dfoo/include_next_foo.h0000750000175000017500000000002611115326645024547 0ustar wolffwolff#include_next distcc-3.1/source/include_server/test_data/dfoo/include_dotdot_foo0000640000175000017500000000002211115326645024632 0ustar wolffwolff#include "../foo" distcc-3.1/source/include_server/test_data/more_macros.c0000640000175000017500000000052311115326647022577 0ustar wolffwolff #define TEMPLATE_VARNAME(_filename_) \ AS_STRING\ (maps/_filename_.tpl.varnames.h) #define ILLFORMED(_filename_,(x)) \ AS_STRING(maps/_filename_.tpl.varnames.h, NOTHANDLED(_filename_)) // #define BEHINDCOMMENT(x) x + x #define AS_STRING(x) AS_STRING_INTERNAL(x) #define AS_STRING_INTERNAL(x) #x #include TEMPLATE_VARNAME(foo) distcc-3.1/source/include_server/test_data/distcc/0000750000175000017500000000000011115327763021375 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/distcc/src/0000750000175000017500000000000011115327763022164 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/distcc/src/hosts.h0000640000175000017500000000507611115326646023505 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /** * @file * * Declarations for distcc host selection stuff. **/ /** * A simple linked list of host definitions. All strings are mallocd. **/ struct dcc_hostdef { enum { DCC_MODE_TCP = 1, DCC_MODE_SSH, DCC_MODE_LOCAL } mode; char * user; char * hostname; int port; char * ssh_command; /** Mark the host as up == 1, by default, or down == 0, if !hostname */ int is_up; /** Number of tasks that can be dispatched concurrently to this machine. */ int n_slots; /** The full name of this host, taken verbatim from the host * definition. **/ char * hostdef_string; enum dcc_protover protover; /** The kind of compression to use for this host */ enum dcc_compress compr; /** Where are we doing preprocessing? */ enum dcc_cpp_where cpp_where; struct dcc_hostdef *next; }; /** Static definition of localhost **/ extern struct dcc_hostdef *dcc_hostdef_local; extern struct dcc_hostdef *dcc_hostdef_local_cpp; /* hosts.c */ int dcc_get_hostlist(struct dcc_hostdef **ret_list, int *ret_nhosts); int dcc_free_hostdef(struct dcc_hostdef *host); int dcc_get_features_from_protover(enum dcc_protover protover, enum dcc_compress *compr, enum dcc_cpp_where *cpp_where); int dcc_get_protover_from_features(enum dcc_compress compr, enum dcc_cpp_where cpp_where, enum dcc_protover *protover); /* hostfile.c */ int dcc_parse_hosts_file(const char *fname, struct dcc_hostdef **ret_list, int *ret_nhosts); distcc-3.1/source/include_server/test_data/distcc/src/bulk.h0000640000175000017500000000357511115326646023304 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78; -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ int dcc_r_file(int ifd, const char *filename, unsigned, enum dcc_compress); int dcc_r_fifo(int ifd, const char *fifo_name, size_t len); int dcc_x_file(int ofd, const char *fname, const char *token, enum dcc_compress compression, off_t *); int dcc_r_file_timed(int ifd, const char *fname, unsigned size, enum dcc_compress); int dcc_r_token_file(int ifd, const char *token, const char *fname, enum dcc_compress compr); int dcc_open_read(const char *fname, int *ifd, off_t *fsize); int dcc_copy_file_to_fd(const char *in_fname, int out_fd); /* clirpc.c */ int dcc_x_many_files(int ofd, unsigned int n_files, char **fnames); /* srvrpc.c */ int dcc_r_many_files(int in_fd, const char *dirname, enum dcc_compress compr); distcc-3.1/source/include_server/test_data/distcc/src/compile.h0000640000175000017500000000274211115326646023772 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /* remote.c */ int dcc_compile_remote(char **argv, char *input_fname, char *cpp_fname, char **file_names, char *output_fname, char *deps_fname, char *server_stderr_fname, pid_t cpp_pid, int local_cpu_lock_fd, struct dcc_hostdef *host, int *status); int dcc_build_somewhere_timed(char *argv[], int sg_level, int *status); distcc-3.1/source/include_server/test_data/distcc/src/util.h0000640000175000017500000000366211115326646023321 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #include /* util.c */ int dcc_getcurrentload(void); void dcc_getloadavg(double loadavg[3]); int argv_contains(char **argv, const char *s); int dcc_redirect_fd(int, const char *fname, int); int str_startswith(const char *head, const char *worm); char *dcc_gethostname(void); void dcc_exit(int exitcode) NORETURN; int dcc_getenv_bool(const char *name, int def_value); int set_cloexec_flag (int desc, int value); int dcc_ignore_sigpipe(int val); int dcc_remove_if_exists(const char *fname); int dcc_trim_path(const char *compiler_name); int dcc_set_path(const char *newpath); char *dcc_abspath(const char *path, int path_len); int dcc_get_dns_domain(const char **domain_name); #define str_equal(a, b) (!strcmp((a), (b))) void dcc_get_proc_stats(int *num_D, int *max_RSS, char **max_RSS_name); void dcc_get_disk_io_stats(int *n_reads, int *n_writes); int dcc_dup_part(const char **psrc, char **pdst, const char *sep); #ifndef HAVE_STRLCPY size_t strlcpy(char *d, const char *s, size_t bufsize); #endif int dcc_tokenize_string(const char *in, char ***argv_ptr); distcc-3.1/source/include_server/test_data/distcc/src/distcc.c0000640000175000017500000001461311115326646023606 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /* 4: The noise of a multitude in the * mountains, like as of a great people; a * tumultuous noise of the kingdoms of nations * gathered together: the LORD of hosts * mustereth the host of the battle. * -- Isaiah 13 */ #include "config.h" #include #include #include #include #include #include #include #include "distcc.h" #include "trace.h" #include "exitcode.h" #include "util.h" #include "hosts.h" #include "bulk.h" #include "implicit.h" #include "compile.h" #include "emaillog.h" /* Name of this program, for trace.c */ const char *rs_program_name = "distcc"; /** * @file * * Entry point for the distcc client. * * There are three methods of use for distcc: explicit (distcc gcc -c * foo.c), implicit (distcc -c foo.c) and masqueraded (gcc -c foo.c, * where gcc is really a link to distcc). * * Detecting these is relatively easy by examining the first one or * two words of the command. We also need to make sure that when we * go to run the compiler, we run the one intended by the user. * * In particular, for masqueraded mode, we want to make sure that we * don't invoke distcc recursively. **/ static void dcc_show_usage(void) { dcc_show_version("distcc"); printf( "Usage:\n" " distcc [COMPILER] [compile options] -o OBJECT -c SOURCE\n" " distcc --help\n" "\n" "Options:\n" " COMPILER defaults to \"cc\"\n" " --help explain usage and exit\n" " --version show version and exit\n" "\n" "Environment variables:\n" " See the manual page for a complete list.\n" " DISTCC_VERBOSE=1 give debug messages\n" " DISTCC_LOG send messages to file, not stderr\n" " DISTCC_SSH command to run to open SSH connections\n" " DISTCC_DIR directory for host list and locks\n" "\n" "Server specification:\n" "A list of servers is taken from the environment variable $DISTCC_HOSTS, or\n" "$DISTCC_DIR/hosts, or ~/.distcc/hosts, or %s/distcc/hosts.\n" "Each host can be given in any of these forms, see the manual for details:\n" "\n" " localhost run in place\n" " HOST TCP connection, port %d\n" " HOST:PORT TCP connection, specified port\n" " @HOST SSH connection\n" " USER@HOST SSH connection to specified host\n" " --randomize Randomize the server list before execution\n" "\n" "distcc distributes compilation jobs across volunteer machines running\n" "distccd. Jobs that cannot be distributed, such as linking or \n" "preprocessing are run locally. distcc should be used with make's -jN\n" "option to execute in parallel on several machines.\n", SYSCONFDIR, DISTCC_DEFAULT_PORT); } static RETSIGTYPE dcc_client_signalled (int whichsig) { signal(whichsig, SIG_DFL); #ifdef HAVE_STRSIGNAL rs_log_info("%s", strsignal(whichsig)); #else rs_log_info("terminated by signal %d", whichsig); #endif dcc_cleanup_tempfiles_from_signal_handler(); raise(whichsig); } static void dcc_client_catch_signals(void) { signal(SIGTERM, &dcc_client_signalled); signal(SIGINT, &dcc_client_signalled); signal(SIGHUP, &dcc_client_signalled); } /** * distcc client entry point. * * This is typically called by make in place of the real compiler. * * Performs basic setup and checks for distcc arguments, and then kicks off * dcc_build_somewhere(). **/ int main(int argc, char **argv) { int status, sg_level, tweaked_path = 0; char **compiler_args; char *compiler_name; int ret; dcc_client_catch_signals(); atexit(dcc_cleanup_tempfiles); atexit(dcc_remove_state_file); dcc_set_trace_from_env(); dcc_setup_log_email(); dcc_trace_version(); compiler_name = (char *) dcc_find_basename(argv[0]); /* Ignore SIGPIPE; we consistently check error codes and will * see the EPIPE. */ dcc_ignore_sigpipe(1); sg_level = dcc_recursion_safeguard(); rs_trace("compiler name is \"%s\"", compiler_name); if (strstr(compiler_name, "distcc") != NULL) { /* Either "distcc -c hello.c" or "distcc gcc -c hello.c" */ if (argc <= 1 || !strcmp(argv[1], "--help")) { dcc_show_usage(); ret = 0; goto out; } if (!strcmp(argv[1], "--version")) { dcc_show_version("distcc"); ret = 0; goto out; } dcc_find_compiler(argv, &compiler_args); /* compiler_args is now respectively either "cc -c hello.c" or * "gcc -c hello.c" */ #if 0 /* I don't think we need to call this: if we reached this * line, our invocation name is something like 'distcc', and * that's never a problem for masquerading loops. */ if ((ret = dcc_trim_path(compiler_name)) != 0) goto out; #endif } else { /* Invoked as "cc -c hello.c", with masqueraded path */ if ((ret = dcc_support_masquerade(argv, compiler_name, &tweaked_path)) != 0) goto out; dcc_copy_argv(argv, &compiler_args, 0); compiler_args[0] = compiler_name; } if (sg_level - tweaked_path > 0) { rs_log_crit("distcc seems to have invoked itself recursively!"); ret = EXIT_RECURSION; goto out; } ret = dcc_build_somewhere_timed(compiler_args, sg_level, &status); out: dcc_maybe_send_email(); dcc_exit(ret); } distcc-3.1/source/include_server/test_data/distcc/src/implicit.h0000640000175000017500000000177011115326646024154 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * $Header: /data/cvs/distcc/src/implicit.h,v 1.3 2002/09/18 06:57:45 mbp Exp $ * * Copyright (C) 2002 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ int dcc_find_compiler(char **argv, char ***); distcc-3.1/source/include_server/test_data/distcc/src/trace.h0000640000175000017500000001614111115326646023436 0ustar wolffwolff/*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- * * librsync -- generate and apply network deltas * * Copyright (C) 2000, 2001, 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** * @file * * Reusable trace library. * * @todo A function like perror that includes strerror output. Apache * does this by adding flags as well as the severity level which say * whether such information should be included. * * @todo Also check in configure for the C9X predefined identifier `_function', or * whatever it's called. **/ /* Provide simple macro statement wrappers (adapted from glib, and originally from Perl): * RS_STMT_START { statements; } RS_STMT_END; * can be used as a single statement, as in * if (x) RS_STMT_START { ... } RS_STMT_END; else ... * * For gcc we will wrap the statements within `({' and `})' braces. * For SunOS they will be wrapped within `if (1)' and `else (void) 0', * and otherwise within `do' and `while (0)'. */ #if !(defined (RS_STMT_START) && defined (RS_STMT_END)) # if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) # define RS_STMT_START (void)( # define RS_STMT_END ) # else # if (defined (sun) || defined (__sun__)) # define RS_STMT_START if (1) # define RS_STMT_END else (void)0 # else # define RS_STMT_START do # define RS_STMT_END while (0) # endif # endif #endif #include /* unconditionally on */ #define DO_RS_TRACE /** * Log severity levels. * * These have the same numeric values as the levels for syslog, at * least in glibc. * * Trace may be turned off. * * Error is always on, but you can return and continue in some way. */ typedef enum { RS_LOG_EMERG = 0, /**< System is unusable */ RS_LOG_ALERT = 1, /**< Action must be taken immediately */ RS_LOG_CRIT = 2, /**< Critical conditions */ RS_LOG_ERR = 3, /**< Error conditions */ RS_LOG_WARNING = 4, /**< Warning conditions */ RS_LOG_NOTICE = 5, /**< Normal but significant condition */ RS_LOG_INFO = 6, /**< Informational */ RS_LOG_DEBUG = 7 /**< Debug-level messages */ } rs_loglevel; int rs_loglevel_from_name(const char *name); enum { RS_LOG_PRIMASK = 7, /**< Mask to extract priority part. \internal */ RS_LOG_NONAME = 8, /**< \b Don't show function name in message. */ RS_LOG_NO_PROGRAM = 16, RS_LOG_NO_PID = 32 }; /** * \typedef rs_logger_fn * \brief Callback to write out log messages. * \param level a syslog level. * \param msg message to be logged. * * \param private Opaque data passed in when logger was added. For * example, pointer to file descriptor. */ typedef void rs_logger_fn(int flags, const char *fn, char const *msg, va_list, void *private_ptr, int private_int); void rs_format_msg(char *buf, size_t, int, const char *, const char *fmt, va_list); void rs_trace_set_level(rs_loglevel level); void rs_add_logger(rs_logger_fn *, int level, void *, int); void rs_remove_logger(rs_logger_fn *, int level, void *, int); void rs_remove_all_loggers(void); void rs_logger_file(int level, const char *fn, char const *fmt, va_list va, void *, int); void rs_logger_syslog(int level, const char *fn, char const *fmt, va_list va, void *, int); /** Check whether the library was compiled with debugging trace 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); distcc-3.1/source/include_server/test_data/distcc/src/state.h0000640000175000017500000000475311115326646023466 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2003 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #ifndef _DISTCC_STATE_H #define _DISTCC_STATE_H #ifdef __cplusplus extern "C" { #endif int dcc_get_state_dir (char **p); int dcc_open_state_file (int *p_fd); /* Note that these must be in the order in which they are encountered * for the state file to work properly. It's OK if some are skipped * though. */ enum dcc_phase { DCC_PHASE_STARTUP, DCC_PHASE_BLOCKED, DCC_PHASE_CONNECT, DCC_PHASE_CPP, DCC_PHASE_SEND, DCC_PHASE_COMPILE, /**< or unknown */ DCC_PHASE_RECEIVE, DCC_PHASE_DONE /**< MUST be last */ }; int dcc_note_state (enum dcc_phase state, const char *file, const char *host); void dcc_remove_state_file (void); extern const char *dcc_state_prefix; #define DCC_STATE_MAGIC 0x44494800 /* DIH\0 */ /** * State and history of a distcc process. Used in memory and also in native * format for binary state files. * * This should be <4kB, so that it will normally be written out * atomically. **/ struct dcc_task_state { size_t struct_size; unsigned long magic; unsigned long cpid; /**< Client pid */ char file[128]; /**< Input filename */ char host[128]; /**< Destination host description */ int slot; /**< Which CPU slot for this host */ enum dcc_phase curr_phase; /** In memory, point to the next in a list of all tasks. In the * file, undefined. */ struct dcc_task_state *next; }; const char *dcc_get_phase_name(enum dcc_phase); void dcc_note_state_slot(int slot); #ifdef __cplusplus } #endif #endif /* _DISTCC_STATE_H */ distcc-3.1/source/include_server/test_data/distcc/src/emaillog.h0000640000175000017500000000047111115326646024130 0ustar wolffwolff#ifndef DCC_EMAILLOG_H #define DCC_EMAILLOG_H #define DCC_EMAILLOG_WHOM_TO_BLAME "distcc-pump-errors@google.com" void dcc_please_send_email(void); void dcc_setup_log_email(void); void dcc_maybe_send_email(void); int dcc_add_file_to_log_email(const char *description, const char *fname); #endif /* EMAILLOG_H */ distcc-3.1/source/include_server/test_data/distcc/src/exitcode.h0000640000175000017500000000424011115326646024141 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ #ifndef _DISTCC_EXITCODE_H #define _DISTCC_EXITCODE_H /** * @file * * Common exit codes. **/ /** * Common exit codes for both client and server. * * These need to be in [1,255] so that they can be used as exit() * codes. **/ enum dcc_exitcode { EXIT_DISTCC_FAILED = 100, /**< General failure */ EXIT_BAD_ARGUMENTS = 101, EXIT_BIND_FAILED = 102, EXIT_CONNECT_FAILED = 103, EXIT_COMPILER_CRASHED = 104, EXIT_OUT_OF_MEMORY = 105, EXIT_BAD_HOSTSPEC = 106, EXIT_IO_ERROR = 107, EXIT_TRUNCATED = 108, EXIT_PROTOCOL_ERROR = 109, EXIT_COMPILER_MISSING = 110, /**< Compiler executable not found */ EXIT_RECURSION = 111, /**< distcc called itself */ EXIT_SETUID_FAILED = 112, /**< Failed to discard privileges */ EXIT_ACCESS_DENIED = 113, /**< Network access denied */ EXIT_BUSY = 114, /**< In use by another process. */ EXIT_NO_SUCH_FILE = 115, EXIT_NO_HOSTS = 116, EXIT_GONE = 117, /**< No longer relevant */ EXIT_TIMEOUT = 118 }; #endif /* _DISTCC_EXITCODE_H */ distcc-3.1/source/include_server/test_data/distcc/src/distcc.h0000640000175000017500000002172311115326646023613 0ustar wolffwolff/* -*- c-file-style: "java"; indent-tabs-mode: nil; fill-column: 78 -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /* distcc.h -- common internal-use header file */ #include #ifdef NORETURN /* nothing */ #elif defined(__GNUC__) # define NORETURN __attribute__((noreturn)) #elif defined(__LCLINT__) # define NORETURN /*@noreturn@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define NORETURN #endif /* !__GNUC__ && !__LCLINT__ */ #ifdef UNUSED /* nothing */ #elif defined(__GNUC__) # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) #elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x #else /* !__GNUC__ && !__LCLINT__ */ # define UNUSED(x) x #endif /* !__GNUC__ && !__LCLINT__ */ #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) /* This works on Gentoo's (patched?) gcc 3.3.3 but not 3.2.3, and not Debian's * 3.3.4. It should be standard on 3.4. */ # define WARN_UNUSED __attribute__((warn_unused_result)) #else # define WARN_UNUSED #endif #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif struct dcc_hostdef; #include "state.h" enum dcc_compress { /* 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 distcc-3.1/source/include_server/test_data/distcc/src/include_me.h0000640000175000017500000000000011115326646024427 0ustar wolffwolffdistcc-3.1/source/include_server/test_data/distcc/src/config.h0000640000175000017500000001572211115326646023611 0ustar wolffwolff/* src/config.h. Generated by configure. */ /* src/config.h.in. Generated from configure.ac by autoheader. */ /* Use getaddrinfo(), getnameinfo(), etc */ /* #undef ENABLE_RFC2553 */ /* Your gnu-style host triple */ #define GNU_HOST "x86_64-unknown-linux-gnu" /* Define to 1 if you have the header file. */ #define HAVE_ALLOCA_H 1 /* Define to 1 if you have the header file. */ #define HAVE_ARPA_NAMESER_H 1 /* Define to 1 if you have the `asprintf' function. */ #define HAVE_ASPRINTF 1 /* define if vsnprintf is C99 compliant */ #define HAVE_C99_VSNPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_CTYPE_H 1 /* Define to 1 if you have the declaration of `asprintf', and to 0 if you don't. */ #define HAVE_DECL_ASPRINTF 1 /* Define to 1 if you have the declaration of `snprintf', and to 0 if you don't. */ #define HAVE_DECL_SNPRINTF 1 /* Define to 1 if you have the declaration of `strndup', and to 0 if you don't. */ #define HAVE_DECL_STRNDUP 1 /* Define to 1 if you have the declaration of `vasprintf', and to 0 if you don't. */ #define HAVE_DECL_VASPRINTF 1 /* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you don't. */ #define HAVE_DECL_VSNPRINTF 1 /* Define to 1 if you have the header file. */ #define HAVE_FLOAT_H 1 /* Define to 1 if you have the `flock' function. */ #define HAVE_FLOCK 1 /* Define to 1 if you have the `getaddrinfo' function. */ #define HAVE_GETADDRINFO 1 /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `geteuid' function. */ #define HAVE_GETEUID 1 /* Define to 1 if you have the `getloadavg' function. */ #define HAVE_GETLOADAVG 1 /* Define to 1 if you have the `getnameinfo' function. */ #define HAVE_GETNAMEINFO 1 /* Define to 1 if you have the `getrusage' function. */ #define HAVE_GETRUSAGE 1 /* Define to 1 if you have the `gettimeofday' function. */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the `getuid' function. */ #define HAVE_GETUID 1 /* Define to 1 if you have the `getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define to 1 if you have the `getwd' function. */ #define HAVE_GETWD 1 /* Define to 1 if you have the `hstrerror' function. */ #define HAVE_HSTRERROR 1 /* Define to 1 if you have the `inet_ntoa' function. */ #define HAVE_INET_NTOA 1 /* Define to 1 if you have the `inet_ntop' function. */ #define HAVE_INET_NTOP 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if the system has the type `in_addr_t'. */ #define HAVE_IN_ADDR_T 1 /* Define to 1 if the system has the type `in_port_t'. */ #define HAVE_IN_PORT_T 1 /* Define to 1 if you have the `lockf' function. */ #define HAVE_LOCKF 1 /* Define to 1 if you have the `mcheck' function. */ #define HAVE_MCHECK 1 /* Define to 1 if you have the header file. */ #define HAVE_MCHECK_H 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `mmap' function. */ #define HAVE_MMAP 1 /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_RESOLV_H 1 /* Define to 1 if you have the `sendfile' function. */ #define HAVE_SENDFILE 1 /* Define to 1 if you have the `setgroups' function. */ #define HAVE_SETGROUPS 1 /* Define to 1 if you have the `setreuid' function. */ #define HAVE_SETREUID 1 /* Define to 1 if you have the `setsid' function. */ #define HAVE_SETSID 1 /* Define to 1 if you have the `setuid' function. */ #define HAVE_SETUID 1 /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 /* define if you have struct sockaddr_storage */ #define HAVE_SOCKADDR_STORAGE 1 /* define if you have a working socketpair */ #define HAVE_SOCKETPAIR 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcpy' function. */ /* #undef HAVE_STRLCPY */ /* Define to 1 if you have the `strndup' function. */ #define HAVE_STRNDUP 1 /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_LOADAVG_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_MMAN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SELECT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SENDFILE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SIGNAL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SOCKET_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define if your cpp has vararg macros */ #define HAVE_VARARG_MACROS /* Define to 1 if you have the `vasprintf' function. */ #define HAVE_VASPRINTF 1 /* Whether __va_copy() is available */ #define HAVE_VA_COPY 1 /* Define to 1 if you have the `vsnprintf' function. */ #define HAVE_VSNPRINTF 1 /* Define to 1 if you have the `wait3' function. */ #define HAVE_WAIT3 1 /* Define to 1 if you have the `wait4' function. */ #define HAVE_WAIT4 1 /* Define to 1 if you have the `waitpid' function. */ #define HAVE_WAITPID 1 /* Define if MAP_FAILED constant not available */ #define MAP_FAILED (void *)-1L /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "distcc-pump@google.com" /* Define to the full name of this package. */ #define PACKAGE_NAME "distcc" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "distcc 2.18.3-17gg-pump6" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "distcc" /* Define to the version of this package. */ #define PACKAGE_VERSION "2.18.3-17gg-pump6" /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Use GNOME */ /* #undef WITH_GNOME */ /* Use GTK+ */ /* #undef WITH_GTK */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* type to use in place of socklen_t if not defined */ /* #undef socklen_t */ distcc-3.1/source/include_server/test_data/distcc/README0000640000175000017500000000007011115326646022252 0ustar wolffwolffThis is just part of the distcc code, used for testing. distcc-3.1/source/include_server/test_data/dbar/0000750000175000017500000000000011115327763021034 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/dbar/foo.h0000750000175000017500000000002211115326646021764 0ustar wolffwolff#include "foo2.h" distcc-3.1/source/include_server/test_data/dbar/dbar1/0000750000175000017500000000000011115327763022025 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/dbar/dbar1/bar.h0000640000175000017500000000003211115326646022735 0ustar wolffwolff#define dbar_dbar1_bar_h distcc-3.1/source/include_server/test_data/p1.h0000750000175000017500000000000111115326647020607 0ustar wolffwolff distcc-3.1/source/include_server/test_data/i_am_perhaps_a_directory.h/0000750000175000017500000000000011115327763025365 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/i_am_perhaps_a_directory.h/empty_file0000640000175000017500000000000011115326646027433 0ustar wolffwolffdistcc-3.1/source/include_server/test_data/computed_includes.c0000750000175000017500000000021411115326647023776 0ustar wolffwolff#define A "p1.h" #include A #ifdef C #define m(a) #else #define m(a) #endif #include m(abc) // distcc-3.1/source/include_server/test_data/symlink_farm/0000750000175000017500000000000011115327763022617 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/symlink_farm/dfoo0000777000175000017500000000000011216333421024546 2../dfooustar wolffwolffdistcc-3.1/source/include_server/test_data/symlink_farm/sub_farm/0000750000175000017500000000000011115327763024415 5ustar wolffwolff././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootdistcc-3.1/source/include_server/test_data/symlink_farm/sub_farm/link_to_dd_dd_dfoo_include_dotdot_foodistcc-3.1/source/include_server/test_data/symlink_farm/sub_farm/link_to_dd_dd_dfoo_include_dotdot_f0000777000175000017500000000000011216333421040644 2../../dfoo/include_dotdot_fooustar wolffwolffdistcc-3.1/source/include_server/test_data/symlink_farm/dbar0000777000175000017500000000000011216333421024510 2../dbarustar wolffwolffdistcc-3.1/source/include_server/test_data/symlink_farm/p1.h0000777000175000017500000000000011216333421024204 2../p1.hustar wolffwolffdistcc-3.1/source/include_server/test_data/symlink_farm/computed_includes.c0000777000175000017500000000000011216333421032546 2../computed_includes.custar wolffwolffdistcc-3.1/source/include_server/test_data/symlink_farm/parse.c0000777000175000017500000000000011216333421025556 2../parse.custar wolffwolffdistcc-3.1/source/include_server/test_data/symlink_farm/abc_pre.c0000777000175000017500000000000011216333421026320 2../abc_pre.custar wolffwolffdistcc-3.1/source/include_server/test_data/symlink_farm/test_directory_probing.c0000777000175000017500000000000011216333421034700 2../test_directory_probing.custar wolffwolffdistcc-3.1/source/include_server/test_data/symlink_farm/test_include_next0000777000175000017500000000000011216333421032130 2../test_include_nextustar wolffwolffdistcc-3.1/source/include_server/test_data/symlink_farm/foo0000640000175000017500000000007211115326645023323 0ustar wolffwolff#include "sub_farm/link_to_dd_dd_dfoo_include_dotdot_foo" distcc-3.1/source/include_server/test_data/symlink_farm/abc_post.c0000777000175000017500000000000011216333421026716 2../abc_post.custar wolffwolffdistcc-3.1/source/include_server/test_data/parse.c0000640000175000017500000000021011115326647021374 0ustar wolffwolff#includenext "incnext.h" #include #include "quote.c" # include \ /* comment */ "quote1\ .c" #include "foo.h" // in dfoo distcc-3.1/source/include_server/test_data/stat_triggers.h0000640000175000017500000000000011115326647023145 0ustar wolffwolffdistcc-3.1/source/include_server/test_data/abc_pre.c0000750000175000017500000000004311115326647021663 0ustar wolffwolff/* Used by computed_includes.c */ distcc-3.1/source/include_server/test_data/test_directory_probing.c0000640000175000017500000000025111115326647025052 0ustar wolffwolff// For the include: should not be distracted by the directory // i_am_perhaps_a_directory.h in the present directory (test_data). #include "i_am_perhaps_a_directory.h" distcc-3.1/source/include_server/test_data/test_include_next/0000750000175000017500000000000011115327762023643 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/test_include_next/biz/0000750000175000017500000000000011115327762024427 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/test_include_next/biz/x.h0000750000175000017500000000001411115326644025043 0ustar wolffwolffNow biz/x.h distcc-3.1/source/include_server/test_data/test_include_next/bar/0000750000175000017500000000000011115327762024407 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/test_include_next/bar/x.h0000750000175000017500000000004111115326644025023 0ustar wolffwolffNow bar/x.h #include_next "x.h" distcc-3.1/source/include_server/test_data/test_include_next/bar/y.h0000750000175000017500000000004111115326644025024 0ustar wolffwolffNow bar/y.h #include_next "y.h" distcc-3.1/source/include_server/test_data/test_include_next/baz/0000750000175000017500000000000011115327762024417 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/test_include_next/baz/x.h0000750000175000017500000000004411115326644025036 0ustar wolffwolffNow in baz/x.h #include_next "x.h" distcc-3.1/source/include_server/test_data/test_include_next/baz/start_y.c0000750000175000017500000000005011115326644026244 0ustar wolffwolffNow baz/start_y.h #include "../foo/y.h" distcc-3.1/source/include_server/test_data/test_include_next/baz/y.h0000750000175000017500000000010511115326644025035 0ustar wolffwolffNow baz/y.h #ifndef baz_y_h #define baz_y_h #include y.h #endif distcc-3.1/source/include_server/test_data/test_include_next/baz/start_x.c0000750000175000017500000000004111115326644026243 0ustar wolffwolffNow baz/start_x.h #include "x.h" distcc-3.1/source/include_server/test_data/test_include_next/foo/0000750000175000017500000000000011115327762024426 5ustar wolffwolffdistcc-3.1/source/include_server/test_data/test_include_next/foo/x.h0000750000175000017500000000004111115326644025042 0ustar wolffwolffNow: foo/x.h #include_next "x.h" distcc-3.1/source/include_server/test_data/test_include_next/foo/y.h0000750000175000017500000000004111115326644025043 0ustar wolffwolffNow: foo/y.h #include_next "y.h" distcc-3.1/source/include_server/test_data/include_include_next_foo.h0000750000175000017500000000003611115326647025326 0ustar wolffwolff#include "include_next_foo.h" distcc-3.1/source/include_server/test_data/stat_triggers.c0000640000175000017500000000003311115326647023146 0ustar wolffwolff#include "stat_triggers.h" distcc-3.1/source/include_server/test_data/func_macro.c0000640000175000017500000000003111115326647022377 0ustar wolffwolff#include FINCLUDE(foo.h) distcc-3.1/source/include_server/test_data/abc_post.c0000750000175000017500000000004211115326647022061 0ustar wolffwolff/* Used by computed_includes.c */ distcc-3.1/source/include_server/include_analyzer.py0000750000175000017500000004055211115326647022067 0ustar wolffwolff#! /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(self.client_root_keeper.client_root)) # Migrate the cache stuff to self namespace. self.includepath_map = caches.includepath_map self.directory_map = caches.directory_map self.realpath_map = caches.realpath_map self.canonical_path = caches.canonical_path self.dirname_cache = caches.dirname_cache self.compiler_defaults = caches.compiler_defaults self.systemdir_prefix_cache = caches.systemdir_prefix_cache self.simple_build_stat = caches.simple_build_stat self.build_stat_cache = caches.build_stat_cache self.IsIncludepathIndex = caches.IsIncludepathIndex self.IsSearchdirIndex = caches.IsSearchdirIndex self.IsCurrdirIndex = caches.IsCurrdirIndex self.IsRealpathIndex = caches.IsRealpathIndex self.IsFilepathPair = caches.IsFilepathPair # Make a cache for the symbolic links encountered; also for their # replication into root directory. self.mirror_path = mirror_path.MirrorPath(self.simple_build_stat, self.canonical_path, self.realpath_map, self.systemdir_prefix_cache) # Make a parser for C/C++. self.parse_file = parse_file.ParseFile(self.includepath_map) # Make a compressor for source files. self.compress_files = compress_files.CompressFiles(self.includepath_map, self.directory_map, self.realpath_map) # A fast cache for avoiding calls into the mirror_path object. self.mirrored = set([]) # For statistics only. We measure the different search lists # (search paths) by accumulating them all in sets. self.quote_dirs_set = set([]) # quote search lists self.angle_dirs_set = set([]) # angle searchlists self.include_dir_pairs = set([]) # the pairs (quote search list, # angle search lists) def __init__(self, client_root_keeper, stat_reset_triggers={}): self.generation = 1 self.client_root_keeper = client_root_keeper self.client_root_keeper.ClientRootMakedir(self.generation) self.stat_reset_triggers = stat_reset_triggers self.translation_unit = "unknown translation unit" self.timer = None self.include_server_cwd = os.getcwd() self._InitializeAllCaches() def _ProcessFileFromCommandLine(self, fpath, currdir, kind, search_list): """Return closure of fpath whose kind is "translation unit" or "include". Such files come from the command line, either as the file to compile, or from a "-include" command line option. Arguments: fpath: a filepath (as a string) currdir: a string kind: a string used for an error message if fpath is not found search_list: a tuple of directory indices (for "include" kind files) Returns: an include closure calculated by RunAlgorithm """ # We allow the filepath to be absolute. We do not tolerate absolute # includepaths, in general, and so must be careful here, because we use # build_stat_cache.Resolve. We prepare to use the searchdir parameter of # Resolve. if os.path.isabs(fpath): file_dirpath, file_filename = os.path.split(fpath) else: # Use empty string as directory name (offset from currdir) file_dirpath, file_filename = "", fpath fpath_resolved_pair, fpath_real = self.build_stat_cache.Resolve( self.includepath_map.Index(file_filename), self.currdir_idx, self.directory_map.Index(file_dirpath), search_list) if fpath_resolved_pair == None: raise NotCoveredError("Could not find %s '%s'." % (kind, fpath), send_email=False) # We must inspect the path to replicate directories and symlinks. self.mirror_path.DoPath( os.path.join(currdir, fpath), self.currdir_idx, self.client_root_keeper.client_root) closure = self.RunAlgorithm(fpath_resolved_pair, fpath_real) return closure def ProcessCompilationCommand(self, currdir, parsed_command): """Do the include analysis for parsed_command. Precondition: currdir == os.getcwd() Arguments: currdir: a string denoting an absolute filepath when command is run parsed_command: the value returned by ParseCommandArgs Returns: an include closure as described in RunAlgorithm """ Debug(DEBUG_TRACE, "ProcessCompilationCommand: %s, %s" % (currdir, parsed_command)) assert isinstance(currdir, str) statistics.parse_file_counter_last = statistics.parse_file_counter (self.quote_dirs, self.angle_dirs, self.include_files, translation_unit, self.result_file_prefix, self.d_opts) = parsed_command statistics.translation_unit = translation_unit self.translation_unit = translation_unit self.currdir_idx = self.directory_map.Index(currdir) # Statistics only. self.include_dir_pairs |= set([(self.quote_dirs, self.angle_dirs)]) self.quote_dirs_set.add(self.quote_dirs) self.angle_dirs_set.add(self.angle_dirs) statistics.quote_path_total += len(self.quote_dirs) statistics.angle_path_total += len(self.angle_dirs) total_closure = {} for include_file in self.include_files: total_closure.update( self._ProcessFileFromCommandLine( self.includepath_map.string[include_file], currdir, "include file", self.quote_dirs)) total_closure.update(self._ProcessFileFromCommandLine(translation_unit, currdir, "translation unit", ())) return total_closure def DoStatResetTriggers(self): """Reset stat caches if a glob evaluates differently from earlier. More precisely, if a path of a glob comes in or out of existence or has a new stamp, then reset stat caches.""" trigger_map = self.stat_reset_triggers old_paths = [ path for glob_expr in trigger_map for path in trigger_map[glob_expr] ] for glob_expr in trigger_map: for path in glob.glob(glob_expr): try: old_paths.remove(path) except ValueError: pass new_stamp = basics.Stamp(path) if path in trigger_map[glob_expr]: if new_stamp != trigger_map[glob_expr][path]: Debug(basics.DEBUG_WARNING, "Path '%s' changed. Clearing caches.", path) trigger_map[glob_expr][path] = new_stamp self.ClearStatCaches() return else: Debug(basics.DEBUG_WARNING, "Path '%s' came into existence. Clearing caches.", path) trigger_map[glob_expr][path] = basics.Stamp(path) self.ClearStatCaches() return if old_paths: path = old_paths[0] Debug(basics.DEBUG_WARNING, "Path '%s' no longer exists. Clearing caches.", path) self.ClearStatCaches() def DoCompilationCommand(self, cmd, currdir, client_root_keeper): """Parse and and process the command; then gather files and links.""" self.translation_unit = "unknown translation unit" # don't know yet # Any relative paths in the globs in the --stat_reset_trigger argument # must be evaluated relative to the include server's original working # directory. os.chdir(self.include_server_cwd) self.DoStatResetTriggers() # Now change to the distcc client's working directory. # That'll let us use os.path.join etc without including currdir explicitly. os.chdir(currdir) parsed_command = ( parse_command.ParseCommandArgs(cmd, currdir, self.includepath_map, self.directory_map, self.compiler_defaults, self.timer)) (unused_quote_dirs, unused_angle_dirs, unused_include_files, source_file, result_file_prefix, unused_Dopts) = parsed_command # Do the real work. include_closure = ( self.ProcessCompilationCommand(currdir, parsed_command)) # Cancel timer before I/O in compress_files. if self.timer: # timer may not always exist when testing self.timer.Cancel() # Get name of the initial source file translation_unit = self.translation_unit # Links are accumulated intra-build (across different compilations in a # build). We send all of 'em every time. This will potentially lead to # performance degradation for large link farms. We expect at most a # handful. We add put the system links first, because there should be very # few of them. links = self.compiler_defaults.system_links + self.mirror_path.Links() files = self.compress_files.Compress(include_closure, client_root_keeper) forcing_files = self._ForceDirectoriesToExist() files_and_links = files + links + forcing_files realpath_map = self.realpath_map if basics.opt_verify: # Invoke the real preprocessor. exact_no_system_header_dependency_set = ( ExactDependencies(" ".join(cmd), realpath_map, self.systemdir_prefix_cache, translation_unit)) if basics.opt_write_include_closure: WriteDependencies(exact_no_system_header_dependency_set, self.result_file_prefix + '.d_exact', realpath_map) VerifyExactDependencies(include_closure, exact_no_system_header_dependency_set, realpath_map, translation_unit) if basics.opt_write_include_closure: WriteDependencies(include_closure, self.result_file_prefix + '.d_approx', realpath_map) return files_and_links def _ForceDirectoriesToExist(self): """Force any needed directories to exist. In rare cases, the source files may contain #include "foo/../bar", but may not contain any other files from the "foo" directory. In such cases, we invent a dummy file in (the mirrored copy of) each such directory, just to force the distccd server to create the directory, so that the C compiler won't get an error when it tries to resolve that #include. Returns: A list of files to pass as dummy inputs. """ must_exist_dirs = self.mirror_path.MustExistDirs() # Note: distcc's --scan-includes option needs to # know about this name; see ../src/compile.c. special_name = 'forcing_technique_271828' forcing_files = [d + '/' + special_name for d in must_exist_dirs] for forcing_file in forcing_files: # If for extremly obscure reasons the file already exists and is useful, # then don't change it: that's why we open in "append" mode. open(forcing_file, "a").close() return forcing_files def RunAlgorithm(self, filepath_resolved_pair, filepath_real_idx): """Run FindNode on filepath; then compute include closure. Arguments: filepath_resolved_pair: (directory_idx, includepath_idx) filepath_real: the realpath_map index corresponding to filepath_resolved_pair Returns: include_closure: a dictionary. The include_closure consists of entries of the form realpath_idx: [(searchdir_idx_1, includepath_idx_1), (searchdir_idx_2, includepath_idx_2), ...] where searchdir_i is an absolute path. realpath_idx is a realpath index corresponding to a single #include (more exactly, it's the index of the path that the #include resolves to). This include closure calculation omits any system header files, that is, header files found in a systemdir (recall systemdirs are those searchdirs that are built into the preprocessor, such as "/usr/include"). It concentrates only on header files users might edit. The keys are the most important part of the include_closure; the values are used only to munge the preprocessor output to give more useful filenames via the #line directive. The issue here is that source files in the distcc system are not in their "proper" locations: for instance, /usr/X11R6/include/X11.h might be in /tmp/distcc/usr/X11R6/include/X11.h rather than in /usr/X11R6/include. As the example above suggests, relative position of .h files is preserved in distcc-land, so if the #include ends up being a relative include, we do not need to do any munging, so we don't bother to store anything in the value-list corresponding to realpath_idx. If, however, the #include ends up being an absolute include, we do store the "real" name (as an index-pair) in the list. For debugging purposes, we may store more than one "real" name if there are several, which can happen when multiple symlinks point to the same place. TODO(csilvers): change the code to only store one. Here's a concrete example: suppose we're trying to resolve #include "bar.h", and the searchdir_list is ["reldir/foo", "/usr/foo"]. If "/reldir/foo/bar.h" exists, then realpath_idx will resolve to that, and the preprocessor will emit code like "#line 1 reldir/foo/bar.h". That's correct as-is, no munging needed, so we don't bother to put a value in the include_closure entry for this realpath. If, however, "/reldir/foo/bar.h" does not exist, but "/usr/foo/bar.h" exists, then realpath_idx will resolve to that, and the preprocessor will emit code like "#line 1 /tmp/distcc/usr/foo/bar.h". We'll want to munge that to be "/usr/foo/bar.h", so we do put a value in the include_closure entry for this realpath, to tell us what to munge to. (Note we *could* use realpath to tell us the "real" filename, without needing a separate index-pair, but that's not as user-friendly, since realpath is the filename after symlinks are resolved. Thus, on some setups the realpath of /usr/foo/bar.h could be /netapp1/mnt/foo/bar.h or something equally unhelpful.) This method to be overridden by derived class. """ raise Exception, "RunAlgorithm not implemented." def ClearStatCaches(self): """Clear caches used for, or dependent on, stats.""" self.generation += 1 # Tabula rasa: for this analysis, we must forget everything recorded in the # client_root directory about source files, directories, and symbolic links. # But we cannot delete any such information, because slow-poke distcc # clients that have received earlier include manifests perhaps only now get # around to reading a previous generation client root directory. self.client_root_keeper.ClientRootMakedir(self.generation) self._InitializeAllCaches() distcc-3.1/source/include_server/macro_eval.py0000750000175000017500000003664211115326647020654 0ustar wolffwolff#! /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 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)) distcc-3.1/source/include_server/setup.py0000750000175000017500000001451711115326647017701 0ustar wolffwolff#!/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. The version number should be passed to this script through the environment variable DISTCC_VERSION. Also, the CPPFLAGS of the Makefile must be passed through the enviroment. This is how we figure out the locations of include directories. SRCDIR must be passed as well; it explains where to find the C sources and the include_server directory of Python source files and C extensions. Because SRCDIR is appended to build location and we don't want to end up outside this location through a relative SRCDIR path with '..'s, SRCDIR is absolutized. """ __author__ = 'Manos Renieris and Nils Klarlund' import distutils.core import distutils.extension import doctest import os import shlex import sys OPTIONS_NOT_ALLOWED = ['-Iquote', '-Isystem', '-I-'] # We include a partial command line parser instead of using the more the more # complicated one in parse_command.py. This cuts down on dependencies in the # build system itself. def GetIncludes(flags): """Parse a flags string for includes of the form -I. Args: flags: a string in shell syntax denoting compiler options Returns: a list of s of the includes Raises: ValueError: In the doctests below, note that a single quoted backslash takes four backslashes to represent if it is inside a single quoted string inside this present triple-quoted string. >>> GetIncludes('-I x -X -I"y" -Y') ['x', 'y'] >>> GetIncludes('-Ix -Dfoo -Iy') ['x', 'y'] >>> GetIncludes(r'-Ix -I"y\\z" -I"y\\\\z" -Y') ['x', 'y\\\\z', 'y\\\\z'] >>> GetIncludes('-DX -Iquote Y') Traceback (most recent call last): ... ValueError: These options are not allowed: -Iquote, -Isystem, -I-. >>> GetIncludes('-DX -I x -I') Traceback (most recent call last): ... ValueError: Argument expected after '-I'. """ flags = shlex.split(flags) if set(OPTIONS_NOT_ALLOWED) & set(flags): raise ValueError('These options are not allowed: %s.' % ', '.join(OPTIONS_NOT_ALLOWED)) # Fish out the directories of '-I' options. i = 0 inc_dirs = [] while i < len(flags): if flags[i].startswith('-I'): inc_dir = flags[i][len('-I'):] if inc_dir: # "-Idir" inc_dirs.append(inc_dir) i += 1 continue else: # "-I dir" if i == len(flags) - 1: raise ValueError("Argument expected after '-I'.") inc_dirs.append(flags[i+1]) i += 2 else: i += 1 return inc_dirs cpp_flags_env = os.getenv('CPPFLAGS', '') if not cpp_flags_env: # Don't quit; perhaps the user is asking for help using '--help'. # CPPFLAGS checking. print >> sys.stderr, 'setup.py: CPPFLAGS must be defined.' # CPPFLAGS is passed to us as it's used in the Makefile: a string that the shell # will interpret. GetInclude uses shlex to do the same kind of interpretation # in order to identify the include directory options. cpp_flags_includes = GetIncludes(cpp_flags_env) python_cflags_env = os.getenv('PYTHON_CFLAGS', '') if not python_cflags_env: # Don't quit; perhaps the user is asking for help using '--help'. print >> sys.stderr, 'setup.py: PYTHON_CFLAGS must be defined.' # SRCDIR checking. if not os.getenv('SRCDIR'): # Don't quit; perhaps the user is asking for help using '--help'. print >> sys.stderr, 'setup.py: SRCDIR must be defined.' srcdir = 'UNDEFINED' srcdir_include_server = 'UNDEFINED' else: # The distutils build system appends the source location to the build # location, and so to avoid that relative source paths with '..' make built # files end up outside the build location, the location is changed to an # absolute path. srcdir = os.path.abspath(os.getenv('SRCDIR')) if not os.path.isdir(srcdir): sys.exit("""Could not cd to SRCDIR '%s'.""" % srcdir) srcdir_include_server = os.path.join(srcdir, 'include_server') # Specify extension. ext = distutils.extension.Extension( name='include_server.distcc_pump_c_extensions', sources=[os.path.join(srcdir, source) for source in ['src/clirpc.c', 'src/clinet.c', 'src/state.c', 'src/srvrpc.c', 'src/pump.c', 'src/rpc.c', 'src/io.c', 'src/include_server_if.c', 'src/trace.c', 'src/snprintf.c', 'src/util.c', 'src/tempfile.c', 'src/filename.c', 'src/bulk.c', 'src/sendfile.c', 'src/compress.c', 'src/argutil.c', 'src/cleanup.c', 'src/emaillog.c', 'src/timeval.c', 'src/netutil.c', 'lzo/minilzo.c', 'include_server/c_extensions/distcc_pump_c_extensions_module.c', ]], include_dirs=cpp_flags_includes, define_macros=[('_GNU_SOURCE', 1)], library_dirs=[], libraries=[], runtime_library_dirs=[], extra_objects=[], extra_compile_args=python_cflags_env.split() ) args = { 'name': 'include_server', # The 'include_server' package is in the srcdir_include_server. 'package_dir': {'include_server': srcdir_include_server}, 'version': os.getenv('DISTCC_VERSION') or 'unknown', 'description': """Include server for distcc's pump-mode""", 'author': 'Nils Klarlund', 'author_email': 'opensource@google.com', 'url': 'http://code.google.com/p/distcc', 'long_description': 'The include server is part of distcc.', 'packages': ['include_server'], 'ext_modules': [ext], } # First, do a little self-testing. doctest.testmod() # Second, do the setup. distutils.core.setup(**args) distcc-3.1/source/include_server/c_extensions/0000750000175000017500000000000011115327757020660 5ustar wolffwolffdistcc-3.1/source/include_server/c_extensions/distcc_pump_c_extensions_module.c0000640000175000017500000002560511115326644027467 0ustar wolffwolff/* Copyright 2007 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ // Author: Nils Klarlund /* distcc_pump_c_extensions_module.c -- Python bindings for distcc-pump * extensions */ #include "Python.h" static const char *version = ".01"; /* To suppress compiler warnings */ #define UNUSED(v) ((void)&v) const char *rs_program_name = "distcc_include_server"; #include "distcc.h" #include "rpc.h" static PyObject *distcc_pump_c_extensionsError; void initdistcc_pump_c_extensions(void); /*********************************************************************** CompressFileLZO1Z ***********************************************************************/ static char CompressLzo1xAlloc_doc__[] = "CompressFileLZO1Z__(in_buf):\n" "Compress file according to distcc lzo protocol.\n" "\n" " Arguments:\n" " in_buf: a string\n" " Raises:\n" " distcc_pump_c_extensions.Error\n" " Returns:\n" " a string, compressed according to distcc protocol\n."; static PyObject * CompressLzo1xAlloc(PyObject *dummy, PyObject *args) { PyObject *string_object; const char *in_buf; int in_len; char *out_buf; size_t out_len; UNUSED(dummy); if (!PyArg_ParseTuple(args, "s#", &in_buf, &in_len)) return NULL; if (in_len < 0) return NULL; if (dcc_compress_lzo1x_alloc(in_buf, in_len, &out_buf, &out_len)) { PyErr_SetString(distcc_pump_c_extensionsError, "Couldn't compress that."); return NULL; } string_object = 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; /* We explictly allocate memory for the output 'resolved' of 'realpath' -- otherwise, some systems will make trouble because they do not accept passing the second argument NULL (as GNU does) for automatic buffer allocation. The glib function 'realpath' comes with the warning to not use it because it's difficult to predict the size of the output. We need the function, however, in its C version --- it's much, much faster than the Python implementation. (We measured about a factor 20 under Linux.) */ # if defined (PATH_MAX) # define DISTCC_PUMP_PATH_MAX PATH_MAX # elif defined (MAXPATHLEN) # define DISTCC_PUMP_PATH_MAX MAXPATHLEN # else # define DISTCC_PUMP_PATH_MAX 4096 // seems conservative for max filename len! # endif char resolved[DISTCC_PUMP_PATH_MAX]; # undef DISTCC_PUMP_PATH_MAX char *res; PyObject *result_str; UNUSED(dummy); if (!PyArg_ParseTuple(args, "s", &in)) return NULL; res = realpath(in, resolved); if (res) { /* On Solaris this result may be a relative path, if the argument was relative. Fail hard if this happens. */ assert(res[0] == '/'); result_str = 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( (char *)"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); } distcc-3.1/source/include_server/include_server.py0000750000175000017500000006416111115326647021552 0ustar wolffwolff#!/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 gc import getopt import glob import os import re import shutil import signal import SocketServer import sys import tempfile import traceback # Include server imports import basics import distcc_pump_c_extensions import include_analyzer_memoizing_node import statistics # The default size passed to listen by a streaming socket server of # SocketServer is only 5. Make it 128 (which appears to be the hard # built-in limit for Linux). This enables requests to the include # server to be buffered better. REQUEST_QUEUE_SIZE = 128 Debug = basics.Debug DEBUG_TRACE = basics.DEBUG_TRACE DEBUG_WARNING = basics.DEBUG_WARNING # Exceptions. SignalSIGTERM = basics.SignalSIGTERM NotCoveredError = basics.NotCoveredError NotCoveredTimeOutError = basics.NotCoveredTimeOutError # USAGE def Usage(): print """Usage: include_server --port INCLUDE_SERVER_PORT [OPTIONS] where INCLUDE_SERVER_PORT is a socket name. Fork the include server for incremental include analysis. The include server answers queries from the distcc client about which files to include in a C/C++ compilation. This command itself terminates as soon as the include server has been spawned. OPTIONS: -dPAT, --debug_pattern=PAT Bit vector for turning on warnings and debugging 1 = warnings 2 = trace some functions other powers of two: see basics.py. -e, --email Send email to discc-pump developers when include server gets in trouble. --email_bound NUMBER Maximal number of emails to send (in addition to a final email). Default: 3. --no-email Do not send email. --path_observation_re=RE Issue warning message whenever a filename is resolved to a realpath that is matched by RE, which is a regular expression in Python syntax. This is useful for finding out where files included actually come from. Use RE="" to find them all. Note: warnings must be enabled with at least -d1. --pid_file FILEPATH The pid of the include server is written to file FILEPATH. -s, --statistics Print information to stdout about include analysis. --stat_reset_triggers=LIST Flush stat caches when the timestamp of any filepath in LIST changes or the filepath comes in or out of existence. LIST is a colon separated string of filepaths, possibly containing simple globs (as allowed by Python's glob module). Print a warning whenever such a change happens (if warnings are enabled). This option allows limited exceptions to distcc_pump's normal assumption that source files are not modified during the build. -t, --time Print elapsed, user, and system time to stderr. --unsafe_absolute_includes Do preprocessing on the compilation server even if includes of absolute filepaths are encountered. Such includes are then ignored for the purposes of gathering the include closure. See the include_server(1) man page for futher information. Using this option may lead to incorrect results. -v, --verify Verify that files in CPP closure are contained in closure calculated by include processor. -w, --write_include_closure Write a .d_approx file which lists all the included files calculated by the include server; with -x, additionally write the included files as calculated by CPP to a .d_exact file. -x, --exact_analysis Use CPP instead, do not omit system headers files. """ # TODO(klarlund) # --simple_algorithm not currently implemented # UTILITIES def _PrintStackTrace(fd): """Print stacktrace to file object.""" print >> 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() 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, include_analyzer.client_root_keeper)) finally: # The timer should normally be cancelled during normal execution # flow. Still, we want to make sure that this is indeed the case in # all circumstances. include_analyzer.timer.Cancel() except NotCoveredError, 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) # Print out observed paths. if basics.opt_path_observation_re: include_analyzer.build_stat_cache.WarnAboutPathObservations( include_analyzer.translation_unit) # Finally, stop the clock and report statistics if needed. statistics.EndTiming() if basics.opt_statistics: statistics.PrintStatistics(include_analyzer) return IncludeHandler def _ParseCommandLineOptions(): """Parse arguments and options for the include server command. Returns: (include_server_port, pid_file), where include_server_port is a string and pid_file is a string or None Modifies: option variables in module basics """ try: opts, args = getopt.getopt(sys.argv[1:], "d:estvw", ["port=", "pid_file=", "debug_pattern=", "email", "no-email", "email_bound=", "exact_analysis", "path_observation_re=", "stat_reset_triggers=", "simple_algorithm", "statistics", "time", "unsafe_absolute_includes", "verify", "write_include_closure"]) except getopt.GetoptError: # Print help information and exit. Usage() sys.exit(1) pid_file = None include_server_port = None for opt, arg in opts: try: if opt in ("-d", "--debug_pattern"): basics.opt_debug_pattern = int(arg) if opt in ("--port",): include_server_port = arg if opt in ("--pid_file",): pid_file = arg if opt in ("-e", "--email"): basics.opt_send_email = True if opt in ("--no-email",): basics.opt_send_email = False if opt in ("--email_bound",): basics.opt_email_bound = int(arg) if opt in ("--path_observation_re",): basics.opt_path_observation_re = re.compile(arg) if opt in ("--stat_reset_triggers",): basics.opt_stat_reset_triggers = ( dict([ (glob_expr, dict ([ (path, basics.Stamp(path)) for path in glob.glob(glob_expr) ])) for glob_expr in arg.split(':') ])) if opt in ("--simple_algorithm",): basics.opt_simple_algorithm = True sys.exit("Not implemented") if opt in ("--unsafe_absolute_includes",): basics.opt_unsafe_absolute_includes = True if opt in ("-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.") client_root_keeper = basics.ClientRootKeeper() # Clean out any junk left over from prior runs. client_root_keeper.CleanOutOthers() Debug(DEBUG_TRACE, "Starting socketserver %s" % include_server_port) # Create the analyser. include_analyzer = ( include_analyzer_memoizing_node.IncludeAnalyzerMemoizingNode( client_root_keeper, basics.opt_stat_reset_triggers)) include_analyzer.email_sender = _EmailSender() # Wrap it inside a handler that is a part of a UnixStreamServer. server = QueuingSocketServer( include_server_port, # Now, produce a StreamRequestHandler subclass whose new objects has # a handler which calls the include_analyzer just made. DistccIncludeHandlerGenerator(include_analyzer)) return (include_analyzer, server) def _CleanOut(include_analyzer, include_server_port): """Prepare shutdown by cleaning out files and unlinking port.""" if include_analyzer and include_analyzer.client_root_keeper: include_analyzer.client_root_keeper.CleanOutClientRoots() try: os.unlink(include_server_port) except OSError: pass def Main(): """Parse command line, fork, and start stream request handler.""" # Remember the time spent in the parent. times_at_start = os.times() include_server_port, pid_file = _ParseCommandLineOptions() # Get locking mechanism. include_server_port_ready = _IncludeServerPortReady() # Now spawn child so that parent can exit immediately after writing # the process id of child to the pid file. times_at_fork = os.times() pid = os.fork() if pid != 0: # In parent. # if pid_file: pid_file_fd = open(pid_file, "w") print >> pid_file_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: gc.set_threshold(basics.GC_THRESHOLD) # Use commented-out line below to have a message printed for each # collection. # gc.set_debug(gc.DEBUG_STATS + gc.DEBUG_COLLECTABLE) server.serve_forever() except KeyboardInterrupt: print >> 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() distcc-3.1/source/include_server/parse_file_test.py0000750000175000017500000001210111115326647021674 0ustar wolffwolff#! /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 client_root_keeper = basics.ClientRootKeeper() include_server.write_include_closure_file = True self.include_analyzer = include_analyzer.IncludeAnalyzer(client_root_keeper) def tearDown(self): pass def test_RegularExpressions(self): self.assertEqual(parse_file.POUND_SIGN_RE.match( """ #\tinclude blah. blah.""" ).group(0), " #\tinclude blah. blah.") self.assertEqual(parse_file.POUND_SIGN_RE.match( """ # gggg include blah. blah.""" ), None) self.assertEqual(parse_file.POUND_SIGN_RE.match( """ */ /**/ /* a */ # include blah. blah.""" ).group(0), ' */ /**/ /* a */ # \tinclude blah. blah.') self.assertEqual( parse_file.MACRO_EXPR_RE.search("m(a, b) + c + n(d)").groupdict(), {'args': 'a, b', 'symbol': 'm'}) # The expression we recognize do not include nested parenthesis self.assertEqual( parse_file.MACRO_EXPR_RE.search("m(a, (b)) + c + n(d)").groupdict(), {'args': None, 'symbol': 'm'}) self.assertEqual(parse_file.MACRO_EXPR_RE.match("random()").group('symbol'), "random") self.assert_(parse_file.DIRECTIVE_RE.match( """ # include """).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) """).group('rhs'), '') self.assertEqual( parse_file.DIRECTIVE_RE.match("#define xmlRealloc(ptr, size)" + " xmlReallocLoc((ptr), (size)," + " __FILE__, __LINE__)").group('lhs'), "xmlRealloc(ptr, size)") self.assertEqual( parse_file.DIRECTIVE_RE.match("#define random() rand()").group('lhs'), "random()") self.assertEqual( parse_file.DIRECTIVE_RE.match("#define ABBA ").group('lhs'), "ABBA") self.assertEqual( parse_file.DIRECTIVE_RE.match("#define ABBA").group('lhs'), "ABBA") self.assertEqual(parse_file.BACKSLASH_RE.sub("", """a\ b\ c\ d"""), "abcd") self.assertEqual(parse_file.BACKSLASH_RE.sub("", """a b """), """a b """) self.assertEqual(parse_file.PAIRED_COMMENT_RE.sub("", "ab/*./*..*/cd"), "abcd") self.assertEqual(parse_file.PAIRED_COMMENT_RE.sub("", "ab/*/cd"), "ab/*/cd") self.assertEqual(parse_file.COMMENT_RE.match("ab/*cd").group(), "ab") self.assertEqual(parse_file.COMMENT_RE.match("ab//cd").group(), "ab") self.assertEqual(parse_file.COMMENT_RE.match("ab/cd").group(), "ab/cd") self.assertEqual(parse_file. INCLUDE_STRING_RE.match(""" < ab.c>""").group('angle'), "ab.c") def test_ParseFile(self): includepath_map = cache_basics.MapToIndex() canonical_path = cache_basics.CanonicalPath() parse_file_obj = parse_file.ParseFile(includepath_map) symbol_table = {} self.assertEqual(parse_file_obj.Parse( "test_data/more_macros.c", symbol_table), ([], [], ['TEMPLATE_VARNAME(foo)'], [])) 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() distcc-3.1/source/include_server/compiler_defaults.py0000750000175000017500000003357511115326647022247 0ustar wolffwolff#! /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 os import re import sys import basics import shutil import subprocess Debug = basics.Debug DEBUG_TRACE = basics.DEBUG_TRACE DEBUG_DATA = basics.DEBUG_DATA NotCoveredError = basics.NotCoveredError def _RealPrefix(path): """Determine longest directory prefix and whether path contains a symlink. Given an absolute path PATH, figure out the longest prefix of PATH where every component of the prefix is a directory -- not a file or symlink. Args: path: a string starting with '/' Returns: a pair consisting of - the prefix - a bool, which is True iff PATH contained a symlink. """ prefix = "/" parts = path.split('/') while prefix != path: part = parts.pop(0) last_prefix = prefix prefix = os.path.join(prefix, part) if os.path.islink(prefix): return last_prefix, True if not os.path.isdir(prefix): return last_prefix, False return path, False def _MakeLinkFromMirrorToRealLocation(system_dir, client_root, system_links): """Create a link under client root what will resolve to system dir on server. See comments for CompilerDefaults class for rationale. Args: system_dir: a path such as /usr/include or /usr/lib/gcc/i486-linux-gnu/4.0.3/include client_root: a path such as /dev/shm/tmpX.include_server-X-1 system_links: a list of paths under client_root; each denotes a symlink The link is created only if necessary. So, /usr/include/gcc/i486-linux-gnu/4.0.3/include is not created if /usr/include is already in place, since it's a prefix of the longer path. If a link is created, the symlink name will be appended to system_links. For example, if system_dir is '/usr/include' and client_root is '/dev/shm/tmpX.include_server-X-1', then this function will create a symlink in /dev/shm/tmpX.include_server-X-1/usr/include which points to ../../../../../../../../../../../../usr/include, and it will append '/dev/shm/tmpX.include_server-X-1/usr/include' to system_links. """ if not system_dir.startswith('/'): raise ValueError("Expected absolute path, but got '%s'." % system_dir) if os.path.realpath(system_dir) != system_dir: raise NotCoveredError( "Default compiler search path '%s' must be a realpath." %s) rooted_system_dir = client_root + system_dir # Typical values for rooted_system_dir: # /dev/shm/tmpX.include_server-X-1/usr/include real_prefix, is_link = _RealPrefix(rooted_system_dir) parent = os.path.dirname(rooted_system_dir) if real_prefix == rooted_system_dir: # rooted_system_dir already exists as a real (non-symlink) path. # Make rooted_system_dir a link. # # For example, this could happen if /usr/include/c++/4.0 and # /usr/include are both default system directories. # First we'd call this function with /usr/include/c++/4.0, # and it would call os.mkdirdirs() to create # /dev/shm/tmpX.include_server-X-1/usr/include/c++, # and then it would create a symlink named 4.0 within that. # Then we'd call this function again with /usr/include. # In this case, we can replace the whole subtree with a single symlink # at /dev/shm/tmpX.include_server-X-1/usr/include. shutil.rmtree(rooted_system_dir) system_links[:] = filter(lambda path : not path.startswith(rooted_system_dir), system_links) elif real_prefix == parent: # The really constructed path does not extend beyond the parent directory, # so we're all set to create the link if it's not already there. if os.path.exists(rooted_system_dir): assert os.path.islink(rooted_system_dir) return elif not is_link: os.makedirs(parent) else: # A link above real_prefix has already been created with this routine. return assert _RealPrefix(parent) == (parent, False), parent depth = len([c for c in system_dir if c == '/']) # The more directories on the path system_dir, the more '../' need to # appended. We add enough '../' to get to the root directory. It's OK # if we have too many, since '..' in the root directory points back to # the root directory. # TODO(klarlund,fergus): do this in a more principled way. # This probably requires changing the protocol. os.symlink('../' * (basics.MAX_COMPONENTS_IN_SERVER_ROOT + depth) + system_dir[1:], # remove leading '/' rooted_system_dir) system_links.append(rooted_system_dir) def _SystemSearchdirsGCC(compiler, language, canonical_lookup): """Run gcc on empty file; parse output to figure out default paths. This function works only for gcc, and only some versions at that. Arguments: compiler: a filepath (the first argument on the distcc command line) 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 clear the environment, because otherwise, directories # declared by CPATH, for example, will be incorporated into the # result. (See the CPP manual for the meaning of CPATH.) The only # thing we keep is PATH, so we can be sure to find the compiler. # NOTE: having the full PATH can be tricky: what if there's a gcc # -> distcc symlink somewhere on the PATH, before the real gcc? # We think the right thing will happen here, but it's complicated. # TODO(csilvers): it's possible we could need to pass in some # other environment vars, like LD_LIBRARY_PATH. Instead of adding # in more env-vars by hand, consider just removing from os.environ # all the env-vars that are meaningful to gcc, such as CPATH. See # http://docs.freebsd.org/info/gcc/gcc.info.Environment_Variables.html, # or the "Environment Variables Affecting GCC" section of the gcc # info page. if 'PATH' in os.environ: trimmed_env = {'PATH': os.environ['PATH']} else: trimmed_env = {} p = subprocess.Popen(command, shell=False, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=trimmed_env) 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 search dirs and creates symlink farm. This function works only for gcc, and only some versions at that, because we parse the output from gcc to determine the default search dirs. The 'default' searchdirs are those on the search-path that are built in, that is known to the preprocessor, as opposed to being set on the commandline via -I et al. When we pass an option such as -I/foo/bar to the server, the server will rewrite it to say -I/server/path/root/foo/bar, where /server/path/root is the temporary directory on the server that corresponds to root on the client (e.g. typically /dev/shm/distccd_nnn). This causes problems in this case of -I options such as -I/usr/include/foo, where the path contains a 'default' search directory (in this case /usr/include) as a prefix. Header files under the system default directories are assumed to exist on the server, and it would be expensive to send them to the server unnecessarily (we measured it, and it slowed down the build of Samba by 20%). So for -I options like -I/usr/include/foo, we want the server to use /usr/include/foo on the server, not /server/path/root/usr/include/foo. Because the server unconditionally rewrites include search paths on the command line to be relative to the server root, we must take corrective action when identifying default system dirs: references to files under these relocated system directories must be redirected to the absolute location where they're actually found. To do so, we create a symlink forest under client_root. This will contain symlinks of the form usr/include -> ../../../../../../../../../../../../usr/include After being sent to the server, the server will rewrite them as /server/path/root/usr/include -> /server/path/root/../../../../../../../../../../../../usr/include which will make /server/path/root/usr/include become a symlink to /usr/include Consequently, an include search directory such as -I /usr/include/foo will work on the server, even after it has been rewritten to: -I /server/path/root/usr/include/foo """ def __init__(self, canonical_lookup, client_root): """Constructor. Instance variables: system_dirs_real_paths: a dictionary such that system_dirs_real_paths[c][lang] is a list of directory paths (strings) for compiler c and language lang system_dirs_default: a list of all such strings, subjected to realpath-ification, for all c and lang client_root: a path such as /dev/shm/tmpX.include_server-X-1 system_links: locations under client_root representing system default dirs """ self.canonical_lookup = canonical_lookup self.system_dirs_default_all = set([]) self.system_dirs_default = {} self.system_links = [] self.client_root = client_root def SetSystemDirsDefaults(self, compiler, language, timer=None): """Set instance variables according to compiler, and make symlink farm. Arguments: compiler: a filepath (the first argument on the distcc command line) language: 'c' or 'c++' or other item in basics.LANGUAGES timer: a basis.IncludeAnalyzerTimer or None The timer will be disabled during this routine because the select involved in Popen calls does not handle SIGALRM. See also the class documentation for this class. """ assert isinstance(compiler, str) assert isinstance(language, str) Debug(DEBUG_TRACE, "SetSystemDirsDefaults with CC, LANG: %s, %s" % (compiler, language)) if compiler in self.system_dirs_default: if language in self.system_dirs_default[compiler]: return else: self.system_dirs_default[compiler] = {} 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][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(self.system_dirs_default[compiler][language])) # Construct the symlink farm for the compiler default dirs. for system_dir in self.system_dirs_default[compiler][language]: _MakeLinkFromMirrorToRealLocation(system_dir, self.client_root, self.system_links) finally: if timer: timer.Start() distcc-3.1/source/include_server/cache_basics.py0000750000175000017500000011063511115326647021126 0ustar wolffwolff#! /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 " it looks for a file named "bar.h" in many directories: /usr/include/foo/bar.h, ./foo/bar.h, and so forth. More precisely, the preprocessor is given a "search path", which is a list of directory-names. (By default, the search-path looks like ['/usr/include', '/usr/local/include', ...], but it's often extended via gcc flags like -I, -isystem, -iprefix, etc.) To resolve a single #include like "#include ", the preprocessor goes through every directory in the search path, running os.stat(os.path.join(current_working_dir, search_dir, 'foo/bar.h')) until the stat call succeeds. With dozens of search-dirs to look through, dozens of #include lines per source file, and hundreds of source files per compilation, this can add up to millions of stat calls. Many of these calls are exactly the same, so caching is a big win. The cache of stat calls takes a filename as input and produces a bool as output, saying if the filename exists. For reasons that will become clear in a moment, we actually represent the input filename as a triple that breaks the filename into its three components: 1) currdir: the current working directory (usually os.path.absdir('.')) 2) searchdir: an element of the search path (eg '/usr/include', 'base') 3) includepath: the thing that comes after "#include" in source files ("foo/bar.h" in our examples above). Why do we break the input into three parts? Consider what cache-lookups we have to do for a single source file: cache[os.path.join(currdir, searchdir1, includepath1)] # #include cache[os.path.join(currdir, searchdir2, includepath1)] # #include cache[os.path.join(currdir, searchdir3, includepath1)] # #include [etc...until the cache-lookup returns True] cache[os.path.join(currdir, searchdir1, includepath2)] # #include cache[os.path.join(currdir, searchdir2, includepath2)] # #include cache[os.path.join(currdir, searchdir3, includepath2)] # #include [etc] By having the key be a triple, we avoid all those unnecessary os.path.join calls. But even if we do this, we notice bigger fish to fry: the Python interpreter still has to do a string-hash of currdir for every lookup, and also has to string-hash searchdirX and includepathX many times. It would be much more efficient if we did those hashes ourselves, reducing the number of string-hashes from O(|search-path| * |#include lines|) to O(|search-path| + |#include lines|). This motivates (finally!) the data structures in this file. We have three string-to-number maps, for mapping each currdir, searchdir, and includepath to a small integer. We put that all together in a cache, that takes a triple of integers as its key and produces True if the file exists, False if it does not, or None if its status is unknown. The String-to-number Map(s) --------------------------- The basic map that converts a filepath-path -- a currdir, searchdir, or includepath -- to a small integer is called MapToIndex. MapToIndex provides mapping in both directions: index: a dictionary mapping paths (strings) to indices in 1..N, and string: an array of size N + 1 that implements the reverse mapping So: obj.string[obj.index[path_as_string]] == path_as_string obj.index[obj.string[path_as_number]] == path_as_number Note we map from 1..N, and not 0..N-1, which leave us 0 free to use as a synonym for None or False. There are also classes that specialize MapToIndex for specific purposes. DirectoryMapToIndex assumes the input is a directory, and in particular a directory that does not have a slash at the end of it (eg "/etc"). It adds the trailing slash before inserting into the map. This is useful because it allows us to use + to join this directory with a relative filename, rather than the slower os.path.join(). RelpathMapToIndex assumes the input is a relative filepath, that is, one that does not start with /. When combined with DirectoryMapToIndex entries, + can be used as a fast alternative to os.path.join(). CanonicalMapToIndex is a MapToIndex that canonializes its input before inserting it into the map: resolving symlinks, getting rid of ..'s, etc. It takes an absolute path as input. Other Caches ------------ Besides the maps from strings to integers, there are three other caches. One is the realpath-cache, that takes a filename and returns os.path.realpath(filename). We cache this because os.path.realpath() is very slow. This is called CanonicalPath. The second cache, the DirnameCache, maps an arbitrary pathname to dirname(pathname), that is, the directory the pathname is in. The input pathname is represented by a (currdir_idx, searchdir_idx, includepath_idx) triple. The output is likewise represented as a number: an index into the DirectoryMapToIndex structure. The third cache is called SystemdirPrefixCache. It tells you, for a given absolute filepath, whether it is prefixed by a systemdir (that is, one of the searchdirs that's built into cpp, such as /usr/include). This is useful to cache because there are several systemdirs, and it's expensive to check them all each time. Naming Conventions ------------------ currdir: the current working dir. searchdir: an element of the search-path (places cpp looks for .h files). includepath: the string a source file #includes. realpath: a full filepath with all its symlinks resolved: os.path.realpath(os.path.join(currdir, searchdir, includepath)) FOO_idx: the small integer associated with the string FOO. includepath_map: the map that takes includepaths to their idx and back (a RelpathMapToIndex). directory_map: the map that takes currdirs and searchdirs to their idx and back. It also is used to store dirname(filepath) for arbitrary filepaths -- basically, anything we know is a directory (a DirectoryMapToIndex). realpath_map: the map that takes full filepaths to their idx and back, canonicalizing them first (by resolving symlinks) (a CanonicalMapToIndex). searchlist: a list of searchdirs. In gcc/cpp documentation, this is called the "search path", but for consistency, in this code we reserve the name "path" to mean "filesystem component," never "list of dirs". (A list of strings). systemdir: a searchdir that's built into cpp, rather than set via -I. (A string.) resolved_filepath: given an includepath, and a (possibly implicit) currdir and searchlist, the resolved_filepath is os.path.join(currdir, searchdir, includepath) for the first searchdir in searchlist for which the joined string exists. This path can be represented in many ways: 1) a string like "foo/bar/baz.h" (if so, this string has been canonicalized to resolve symlinks and the like); 2) an index into realpath_map associated with that string; 3) a triple of indices; or 4) a pair of indices plus an assumption that os.getcwd() == currdir. Pair 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 DEBUG_WARNING = basics.DEBUG_WARNING NotCoveredError = basics.NotCoveredError #### #### SIMPLE CACHES #### class CanonicalPath(object): """Memoizing calculation of realpaths. realpath(x) is the 'canonical' version of x, with all symbolic links eliminated. """ def __init__(self): self.cache = {} def Canonicalize(self, filepath): """Find a really canonical path, possibly memoized. Arguments: filepath: a filepath (string) Returns: the realpath of filepath (string) The following is irrelevant if we always use the distcc_pump_c_extensions realpath function. --- Apparently, in some versions of Python 2.4 at least, realpath does *not* resolve the last component of a filepath if it is a link: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1213894&group_id=5470 Make up for that: follow that final link until a real realpath has been found. Also, realpath is not idempotent. Solution (?): turn filepath into abspath before applying realpath; then we can cache results as well (without worring about value of current directory). The final problem -- that os.path.realpath is very slow, at least an order of magnitude slower than the gnu libc one --- is solved through caching all uses through an object of the present class. """ assert isinstance(filepath, str) try: return self.cache[filepath] except KeyError: if _path_realpath_works: r = _PathRealpath(filepath) self.cache[filepath] = r return r # Fix for os.path.realpath idempotencey bug (Python 2.4). filepath_ = os.path.abspath(filepath) filepath_ = _PathRealpath(filepath_) # Fix for os.path.realpath bug (Python 2.4): symlinks at end not # resolved. for unused_i in range(10): if not os.path.islink(filepath_): break filepath_ = os.path.join(os.path.dirname(filepath_), os.readlink(filepath_)) else: raise NotCoveredError("Too many symlinks in '%s'." % filepath) self.cache[filepath] = filepath_ return filepath_ class DirnameCache(object): """Cache the mapping from filepath pairs to index of their directory names. The key is a triple (currdir_idx, searchdir_idx, includepath_idx). The value is (dir_idx, dir_realpath_idx) where dir_idx is the index of dirname of the corresponding filepath, which possibly is relative, and dir_realpath_idx is the realpath index of the absolute location of the dirname. The value currdir_idx is of possible importance for deteterming dir_realpath_idx, but plays no role in determining dir_idx.""" def __init__(self, includepath_map, directory_map, realpath_map): """Constructor. Arguments: includepath_map: the map used to construct the includepath_idx that will be passed in as arguments to Lookup(). directory_map: the map used to construct both the currdir_idx and searchdir_idx that will be passed in as arguments to Lookup(). It's also the data structure that produces dir_idx. realpath_map: a string-to-int map of canonicalized filepaths """ self.includepath_map = includepath_map self.directory_map = directory_map self.realpath_map = realpath_map self.cache = {} def Lookup(self, currdir_idx, searchdir_idx, includepath_idx): """Return the directory and realpath indices of the dirname of the input. Arguments: currdir_idx: the directory index of the current directory searchdir_idx: a directory_map index includepath_idx: an includepath index Returns: a pair (directory map index, realpath index) See class documentation. Example: if the strings of the arguments indices put together make '/usr/include/foo/bar.h', then this routine will insert '/usr/include/foo/' into self.directory_map, and then return the corresponding pair (directory index of /usr/include/foo/, real path index of /usr/include/foo/). If the arguments put together form "foo.h", then the directory index returned is that of "", the current directory, and the realpath index is that of currdir. """ try: return self.cache[(currdir_idx, searchdir_idx, includepath_idx)] except KeyError: directory = os.path.dirname(os.path.join( self.directory_map.string[searchdir_idx], self.includepath_map.string[includepath_idx])) dir_idx = self.directory_map.Index(directory) rp_idx = self.realpath_map.Index( os.path.join(self.directory_map.string[currdir_idx], directory)) self.cache[(currdir_idx, searchdir_idx, includepath_idx)] = (dir_idx, rp_idx) return (dir_idx, rp_idx) class SystemdirPrefixCache(object): """A cache of information about whether a file exists in a systemdir. A systemdir is a searchdir that is built in to the C/C++ preprocessor. That is, when the preprocessor is figuring out what directory an #include is in, these are the directories it's hard-coded in to check (you can add other directories via -I). This cache records, for a given filepath, whether it starts with a systemdir. This is useful to identify whether the path is likely to correspond to a system include-file (such as stdio.h). Such files are unlikely to change, and are likely to already exist on the distcc servers, both of which are useful things to know for optimization. For speed, users can access self.cache directly, rather than going through the StartsWithSystemdir API. Be sure to call FillCache() to make sure the cache is populated, before accessing it! """ def __init__(self, systemdirs): """Constructor. Argument: systemdirs: the list of system-directories the preprocessor uses. It's a list of strings, probably extracted from the preprocessor itself. Each systemdir should end in a slash. In practice, systemdirs will start empty, and later some routine (in parse_command.py) will magically fill it. So be sure to wait for that before calling FillCache! TODO(csilvers): normalize this; ideally pass systemdirs in to FillCache. """ self.systemdirs = systemdirs # self.cache[i] will be True, False, or None for not-yet-checked. self.cache = [None] def FillCache(self, realpath_map): """Ensures that there's a cache entry for every index in realpath_map. Argument: realpath_map: a string-to-int map of canonicalized filepaths we know. After this function is called, the cache entry is True iff realpath.startswith(systemdir) is True for any of the systemdirs passed in to our constructor. """ if len(self.cache) >= realpath_map.Length(): return # we're already all full for realpath_idx in 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 +. We actually do allow storing absolute paths if option --unsafe_absolute_includes is in use. But, then, we're careful in Resolve (below) to bail out. """ def Index(self, relpath, ignore_absolute_path_warning=False): """Return index d > 0 of relative path. Args: directory: a string not starting with /. ignore_absolute_path_warning: a Boolean The variable ignore_absolute_path_warning is set to True in order to override the requirement that filepaths are relative. This is useful for the compilation unit filepath and filepaths of -include's: they are permitted to be absolute because the command line can still be rewritten on the server. The server tweaks their location to become relative to the server root. """ if os.path.isabs(relpath) and not ignore_absolute_path_warning: if basics.opt_unsafe_absolute_includes: Debug(DEBUG_WARNING, "absolute filepath '%s' was IGNORED" " (correctness of build may be affected)", relpath) else: raise NotCoveredError("Filepath must be relative but isn't: '%s'." " Consider setting INCLUDE_SERVER_ARGS='--" "unsafe_absolute_includes'." % relpath, send_email=False) # Now, remove leading "./" so as not to start an infinite regression when # say foo.c contains: # # #include "./foo.c" # # which mighy seduce a recursive include analyzer down the forbidden path: # # "foo.c", # "./foo.c", "././foo.c." etc. while relpath.startswith("./"): relpath = relpath[2:] return MapToIndex.Index(self, relpath) class CanonicalMapToIndex(MapToIndex): """Like a normal MapToIndex, but assumes the keys are absolute filepaths, and canonicalizes them before inserting into the map. 'Canonicalize' means to do the equivalent of os.path.realpath(), which mostly involves resolving symlinks in the filepath. """ def __init__(self, canonicalize): """Constructor. Argument: canonicalize: an instance of the CanonicalPath cache.""" MapToIndex.__init__(self) self.canonicalize = canonicalize def Index(self, filepath): """Return the realpath index r of filepath. filepath should be an absolute filename. """ return MapToIndex.Index(self, self.canonicalize(filepath)) def RetrieveDirectoriesExceptSys(directory_map, realpath_map, systemdir_prefix_cache, directory_idxs): """Calculate the set of non-system directories of an index list. Arguments: directory_map: a DirectoryMapToIndex cache realpath_map: a CanonicalMapToIndex cache directory_idxs: a list or tuple of directory_map indices Returns: the corresponding tuple of directories except for those whose realpath has a prefix that is a sysdir The directories in the returned list have their trailing '/' stripped. """ result = [] for dir_idx in directory_idxs: # Index the absolute path; this will let us know whether dir_idx is under a # default systemdir of the compiler. rp_idx = realpath_map.Index(os.path.join( os.getcwd(), directory_map.string[dir_idx])) systemdir_prefix_cache.FillCache(realpath_map) if not systemdir_prefix_cache.cache[rp_idx]: result.append(directory_map.string[dir_idx].rstrip('/')) return tuple(result) #### #### THE STAT CACHES #### class SimpleBuildStat(object): """Stat cache that works with strings, not indices.""" def __init__(self): self.cache = {} def Lookup(self, filepath): """Returns true if filepath exists.""" try: return self.cache[filepath] except KeyError: result = self.cache[filepath] = _OsPathExists(filepath) return result class BuildStatCache(object): """A highly optimized mechanism for stat queries of filepaths, as represented by a triple of indexes: currdir_idx, searchdir_idx, filepath_idx. Given this input, we can say whether a regular file represented by this triple exists on the filesystem, and if so, what its canonical pathname is: that is, the pathname after all symlinks have been resolved. The hash table is three-level structure: - build_stat[currdir_idx] contains an array for each includepath_idx - build_stat[currdir_idx][includepath_idx] is this array, and - build_stat[currdir_idx][includepath_idx][searchdir_idx] is either * False if os.path.join(currdir, searchdir, includepath) does not exist * True if it does * None when it is not known whether it exists or not In addition, we keep a parallel structure for the realpath, that lets us quickly map from a filepath to os.path.realpath(filepath). - real_stat[currdir_idx] contains an array for each fp - real_stat[currdir_idx][includepath_idx] is this array, and - real_stat[currdir_idx][includepath_idx][searchdir_idx] is either * realpath_idx, such that realpath_map.string[realpath_idx] = os.path.realpath(os.path.join(currdir, searchdir, includepath)) when build_stat[currdir_idx][includepath_idx][searchdir_idx] = True * None, otherwise """ def __init__(self, includepath_map, directory_map, realpath_map): self.build_stat = {} self.real_stat = {} self.includepath_map = includepath_map self.directory_map = directory_map self.realpath_map = realpath_map self.path_observations = [] def _Verify(self, currdir_idx, searchdir_idx, includepath_idx): """Verify that the cached result is the same as obtained by stat call. Prerequisite: we've done a chdir(currdir) before this call. """ assert 1 <= includepath_idx < self.includepath_map.Length() assert 1 <= searchdir_idx < self.directory_map.Length() if __debug__: statistics.sys_stat_counter += 1 # Since we know directory_map entries end in /, and includepaths don't # start with / (who does "#include "??), we can # use + instead of the more expensive os.path.join(). # Make sure $PWD is currdir, so we don't need to include it in our stat(). assert os.getcwd() + '/' == self.directory_map.string[currdir_idx] really_exists = _OsPathIsFile( self.directory_map.string[searchdir_idx] + self.includepath_map.string[includepath_idx]) cache_exists = self.build_stat[currdir_idx][includepath_idx][searchdir_idx] assert isinstance(cache_exists, bool) if cache_exists != really_exists: filepath = os.path.join(self.directory_map.string[currdir_idx], self.directory_map.string[searchdir_idx], self.includepath_map.string[includepath_idx]) sys.exit("FATAL ERROR: " "Cache inconsistency: '%s' %s, but earlier this path %s." % ( filepath, really_exists and "exists" or "does not exist", cache_exists and "existed" or "did not exist")) def WarnAboutPathObservations(self, translation_unit): """Print new paths found according to path observation expression option. Args: translation_unit: a string embedded in warning """ for (includepath, relpath, realpath) in self.path_observations: Debug(DEBUG_WARNING, "For translation unit '%s'," " lookup of file '%s' resolved to '%s' whose realpath is '%s'.", translation_unit, includepath, relpath, realpath) self.path_observations = [] def Resolve(self, includepath_idx, currdir_idx, searchdir_idx, searchlist_idxs): """Says whether (currdir_idx, searchdir_idx, includepath_idx) exists, and if so what its canonicalized form is (with symlinks resolved). TODO(csilvers): rearrange the order of the arguments. Args: includepath_idx: The index of an includepath, from e.g. "#include " currdir_idx: The index of the current working dir. Note that we require os.getcwd() == currdir before calling Resolve! searchdir_idx: A single searchdir, which is prepended to searchlist, or None to not prepend to the searchlist. searchlist_idxs: A list of directory indices. Returns: 1) (None, None) if, for all sl_idx in [searchdir_idx] + searchlist_idxs, os.path.join(currdir, sp, includepath) does not exist. 2) ((sl_idx, includepath_idx), realpath_idx) if, for some sl_idx in [searchdir_idx] + searchlist_idxs, os.path.join(currdir, sp, includepath) does exist. In this case, sl_idx is the index of the first searchlist entry for which the exists-test succeeds, and realpath_idx is the index into the realpath_map of os.path.join(currdir, sp, includepath). Again, we require as a prequesite that os.getcwd() must equal currdir: os.getcwd() + '/' == self.directory_map.string[currdir_idx] """ includepath = self.includepath_map.string[includepath_idx] if includepath.startswith('/'): # We really don't want to start exploring absolute includepaths; what's # the sl_idx to return for example? And what about the use of '+' # (as an optimization) below instead of os.path.join. return (None, None) dir_map_string = self.directory_map.string # memoize the fn pointer build_stat = self.build_stat real_stat = self.real_stat if __debug__: dir_map = self.directory_map assert 0 < includepath_idx < self.includepath_map.Length() assert 0 < currdir_idx < dir_map.Length() assert searchdir_idx is None or 1 <= searchdir_idx < dir_map.Length() for sl_idx in searchlist_idxs: assert sl_idx < dir_map.Length() assert os.getcwd() + '/' == dir_map_string[currdir_idx], ( "'%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 # regular expression path_observation_re. if basics.opt_path_observation_re: realpath = self.realpath_map.string[realpath_idx] if basics.opt_path_observation_re.search(realpath): self.path_observations.append((includepath, relpath, realpath)) return ((sl_idx, includepath_idx), realpath_idx) else: searchdir_stats[sl_idx] = False if __debug__: Debug(DEBUG_TRACE2, "Resolve: failed") return (None, None) class SetUpCaches(object): """Erect the edifice of caches. Instance variables: includepath_map: RelpathMapToIndex directory_map: DirectoryMapToIndex realpath_map: CanonicalMapToIndex canonical_path: CanonicalPath build_stat_cache: BuildStatCache dirname_cache: DirnameCache simple_build_stat: SimpleBuildStat client_root: a path such as /dev/shm/tmpX.include_server-X-1 (used during default system dir determination) IsFilepathIndex: test for filepath index IsDirectoryIndex: test for director index IsRealpathIndex: test for realpath index IsFilepathPair: test for filepath pair """ def __init__(self, client_root): # A memoizing (caching) class to canonicalize a path: mostly by # resolving any symlinks in the path-component. self.canonical_path = CanonicalPath() # The index-map for includepath names: things seen after '#include'. self.includepath_map = RelpathMapToIndex() # The index-map for searchdir names and currdir as well. Also used any # other time we have something we know is a directory (eg dirname(foo)). self.directory_map = DirectoryMapToIndex() # The index-map for realpaths: the full pathname of an include, with # symlinks resolved and such (hence the name realpath). self.realpath_map = CanonicalMapToIndex(self.canonical_path.Canonicalize) # A cache of the directory part of filepaths. Note it uses the # directory_map to actually store the mapping. self.dirname_cache = DirnameCache(self.includepath_map, self.directory_map, self.realpath_map) # A cache of whether a realpath starts with a system searchdir or # not. Note: at this time, system_dirs_default_all will be empty. # It will get filled via processing in parse_command.py. This is # why we need to store the compiler_defaults instance, to make # sure "our" system_dirs_default_all is updated. # TODO(csilvers): get rid of this once prefix_cache TODO is cleaned up self.compiler_defaults = compiler_defaults.CompilerDefaults( self.canonical_path.Canonicalize, client_root) self.systemdir_prefix_cache = SystemdirPrefixCache( self.compiler_defaults.system_dirs_default_all) # The main caches, that say whether a file exists or not. We have # two: a simple one that takes a filepath (string) as an argument, # and the complicated one that works with index-triples. self.simple_build_stat = SimpleBuildStat() self.build_stat_cache = BuildStatCache(self.includepath_map, self.directory_map, self.realpath_map) # Convenient function closures to test for various semantic datatypes. self.IsIncludepathIndex = (lambda x: isinstance(x, int) and 0 < x < self.includepath_map.Length()) self.IsSearchdirIndex = (lambda x: isinstance(x, int) and 0 < x < self.directory_map.Length()) self.IsCurrdirIndex = (lambda x: isinstance(x, int) and 0 < x < self.directory_map.Length()) self.IsFilepathPair = (lambda x: isinstance(x, tuple) and len(x) == 2 and self.IsSearchdirIndex(x[0]) and self.IsIncludepathIndex(x[1])) self.IsRealpathIndex = (lambda x: isinstance(x, int) and 0 < x < self.realpath_map.Length()) distcc-3.1/source/include_server/mirror_path.py0000750000175000017500000001347711115326647021073 0ustar wolffwolff#!/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. Also, remember all directories that had to be followed to find out what paths mean. This is of particular importance to the '..' operator, which may involve temporary excursions into directories that otherwise contain no files of relevance to the build. But the directories must still be replicated on the server for the semantics of '..' to work. These are called must_exist_dirs. """ def __init__(self, simple_build_stat, canonical_path, realpath_map, systemdir_prefix_cache): """Constructor. Arguments: simple_build_stat: object of type SimpleBuildStat canonical_path: function of type CanonicalPath realpath_map: a CanonicalMapToIndex; see cache_basics.py systemdir_prefix_cache: a SystemdirPrefixCache; see cache_basics.py. """ assert isinstance(simple_build_stat, cache_basics.SimpleBuildStat) assert isinstance(canonical_path, cache_basics.CanonicalPath) # All links encountered so far. self.links = [] # We cache tuples (filepath, current_dir_idx) for which we've already fixed # up the symbolic links. self.link_stat = set([]) # Usual abbreviations. self.simple_build_stat = simple_build_stat self.canonical_path = canonical_path self.must_exist_dirs = [] self.realpath_map = realpath_map self.systemdir_prefix_cache = systemdir_prefix_cache def Links(self): """Return the list of symbolic links created.""" return self.links def MustExistDirs(self): return self.must_exist_dirs def DoPath(self, filepath, current_dir_idx, root): """Mirror the parts of filepath not yet created under root. Arguments: filepath: a string, which is relative or absolute filename current_dir_idx: a directory index root: a string denoting an absolute path for an existing directory """ assert isinstance(filepath, str) assert isinstance(current_dir_idx, int) assert isinstance(root, str) assert root[0] == '/' and root[-1] != '/' assert os.path.isdir(root), root link_stat = self.link_stat lookup = self.simple_build_stat.Lookup # Working from the end (in the hope that a cache lookup will reveal # the futility of further work), make sure that intermediate # destinations exist, and replicate symbolic links where necessary. while filepath and filepath != '/': if (filepath, current_dir_idx) in link_stat: # Filepath is already mirrored return link_stat.add((filepath, current_dir_idx)) # Process suffix of filepath by # - making sure that the mirrored real path of the prefix exists, # - and that the suffix if a symbolic link # is replicated as a symbolic link. assert filepath[-1] != '/', filepath # Now identify the potential symbolic link at the end of filepath (prefix_filepath, suffix) = os.path.split(filepath) # Calculate the real position of the destination of the prefix prefix_real = self.canonical_path.Canonicalize(prefix_filepath) if prefix_real == '/': prefix_real = '' # And, its counterpart under root root_prefix_real = root + prefix_real # Make sure that the parent, root_prefix_real, is there if not lookup(root_prefix_real): # We have not been in this real location before. if not os.path.isdir(root_prefix_real): # Now check that the parent of the link is not under a default system # dir. If it is, then we assume that the parent and indeed the # link itself exist on the server as well, and thus, don't need to # be mirrored. realpath_map = self.realpath_map realpath_idx = realpath_map.Index(prefix_real) if not self.systemdir_prefix_cache.StartsWithSystemdir(realpath_idx, realpath_map): # Not under default system dir. Mark this directory as one that # must always be created on the server. self.must_exist_dirs.append(root_prefix_real) # Create parent path in mirror directory. os.makedirs(root_prefix_real) else: break self.simple_build_stat.cache[root_prefix_real] = True assert os.path.isdir(root_prefix_real) # Create the mirrored symbolic link if applicable. if os.path.islink(filepath): link_name = root_prefix_real + '/' + suffix if not os.path.exists(link_name): os.symlink(self.canonical_path.Canonicalize(filepath), link_name) self.links.append(link_name) filepath = prefix_filepath distcc-3.1/source/include_server/parse_command_test.py0000750000175000017500000001500211115326647022376 0ustar wolffwolff#! /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 shutil import tempfile import unittest NotCoveredError = basics.NotCoveredError class ParseCommandUnitTest(unittest.TestCase): def setUp(self): basics.opt_debug_pattern = 1 self.tmp = tempfile.mkdtemp() caches = cache_basics.SetUpCaches(self.tmp) self.includepath_map = caches.includepath_map self.canonical_path = caches.canonical_path self.directory_map = caches.directory_map self.realpath_map = caches.realpath_map self.systemdir_prefix_cache = caches.systemdir_prefix_cache mock_compiler = '/usr/crosstool/v8/gcc-4.1.0-glibc-2.2.2/blah/gcc' self.mock_compiler = mock_compiler def Mock_SetSystemDirsDefaults(compiler, language, 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): shutil.rmtree(self.tmp) def test__SplitMacroArg(self): self.assertEqual(parse_command._SplitMacroArg("="), ["="]) self.assertEqual(parse_command._SplitMacroArg("A="), ["A", ""]) self.assertEqual(parse_command._SplitMacroArg("A=B=C"), ["A", "B=C"]) def _RetrieveDirectoriesExceptSys(self, directory_idxs): return cache_basics.RetrieveDirectoriesExceptSys( self.directory_map, self.realpath_map, self.systemdir_prefix_cache, directory_idxs) def test_ParseCommandLine(self): self.assertEqual(parse_command.ParseCommandLine( """ "a"b"\\"c" "a"\n"b" a b\\"c"""), ['ab"c', 'a', 'b', 'a', 'b"c']) self.assertEqual(parse_command.ParseCommandLine( """this is a test"""), ['this', 'is', 'a', 'test']) self.assertEqual(parse_command.ParseCommandLine( """ this is a test"""), ['this', 'is', 'a', 'test']) self.assertEqual(parse_command.ParseCommandLine( """this is a test """), ['this', 'is', 'a', 'test']) self.assertEqual(parse_command.ParseCommandLine( 'this " is" a"test" '), ['this', ' is', 'atest']) self.assertEqual(parse_command.ParseCommandLine( r'this " \"is" a"test" '), ['this', ' "is', 'atest']) self.assertEqual(parse_command.ParseCommandLine( 'this " is" a"test"'), ['this', ' is', 'atest']) self.assertRaises(NotCoveredError, parse_command.ParseCommandLine, """this is" a"test" """) self.assertRaises(NotCoveredError, parse_command.ParseCommandLine, 'this is" a"test"') def test_ParseCommandArgs(self): quote_dirs, angle_dirs, include_files, filepath, _incl_clos_f, _d_opts = ( parse_command.ParseCommandArgs( parse_command.ParseCommandLine( self.mock_compiler + " -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')) unittest.main() distcc-3.1/source/include_server/run.py0000750000175000017500000000700211115326647017334 0ustar wolffwolff#! /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:])) distcc-3.1/source/include_server/statistics.py0000750000175000017500000001215111115326647020723 0ustar wolffwolff#! /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 distcc-3.1/source/include_server/macro_eval_test.py0000750000175000017500000001676211115326647021714 0ustar wolffwolff#! /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 shutil import tempfile import unittest NotCoveredError = basics.NotCoveredError class MacroEvalTest(unittest.TestCase): def setUp(self): basics.opt_debug_pattern = 1 self.tmp = tempfile.mkdtemp() caches = cache_basics.SetUpCaches(self.tmp) self.includepath_map = caches.includepath_map self.canonical_path = caches.canonical_path self.directory_map = caches.directory_map self.realpath_map = caches.realpath_map def tearDown(self): shutil.rmtree(self.tmp) def test__SubstituteSymbolInString(self): self.assertEqual( macro_eval._SubstituteSymbolInString("X", "f(y)", "X+(X, X##Y)"), "f(y)+(f(y), f(y)##Y)") self.assertEqual( macro_eval._SubstituteSymbolInString("a", "b", "c(a, aa)"), "c(b, aa)") def test_MassageAccordingToPoundSigns(self): self.assertEqual(macro_eval._MassageAccordingToPoundSigns('#aa##bb'), '"aabb"') self.assertEqual(macro_eval._MassageAccordingToPoundSigns('# a(.)'), '"a(.)"') def test__ParseArgs(self): self.assertEqual(macro_eval._ParseArgs("(a,m(c, n(d)), c)", 0), (["a", "m(c, n(d))", " c"], 17)) self.assertEqual(macro_eval._ParseArgs("""(a","m(c, n(d)), c)""", 0), (["""a","m(c, n(d))""", " c"], 19)) def test__PrependToSet(self): self.assertEqual( macro_eval._PrependToSet("x", set(["y", "z"])), set(["xy", "xz"])) def test__BigUnion(self): self.assertEqual(macro_eval._BigUnion([set([]), set([1,2]), set([3])]), set([1,2,3])) def test_EvalExprDirs(self): self.assertEqual( macro_eval.EvalExpression("A", { 'A': ['b'] }), set(['A', 'b'])) self.assertEqual( macro_eval.EvalExpression("A", { 'A': ['B'], 'B': ['A'] }), set(['A', 'B'])) self.assertEqual( macro_eval.EvalExpression("A", { 'A': ['B'], 'B': ['c'] }), set(['A', 'B', 'c'])) self.assertEqual( macro_eval.EvalExpression("max(2, 4)", { 'max': [ ( ['x', 'y'], "x < y? y: x") ] }), set(['max(2, 4)', '2 < 4? 4: 2'])) self.assertEqual( macro_eval.EvalExpression("F(2, 4)", { 'F': ['max'], 'max': [ ( ['x', 'y'], "x < y? y: x") ] }), set(['max(2, 4)', 'F(2, 4)', '2 < 4? 4: 2'])) self.assertEqual( macro_eval.EvalExpression("max(max(1,2), 3)", { 'max': [ ( ['x', 'y'], "(x < y? y: x)") ] }), set(['((1 < 2? 2: 1) < 3? 3: (1 < 2? 2: 1))', 'max(max(1,2), 3)', '(max(1,2) < 3? 3: max(1,2))', 'max((1 < 2? 2: 1), 3)'])) self.assertEqual( macro_eval.EvalExpression("A", { 'A': ['"a.c"'] }), set(['A', '"a.c"'])) # The ## operator only works in rhs of function-like macros. Check # that it doesn't work stand-alone. self.assertEqual( macro_eval.EvalExpression("A##A", { 'A': ['a.c'] }), set(['A##A', 'a.c##A', 'A##a.c', 'a.c##a.c'])) self.assertEqual( macro_eval.EvalExpression("A(y)A(z)", { 'A': [(['x'], 'x##a.c')] }), set(['A(y)A(z)', 'A(y)za.c', 'ya.cza.c', 'ya.cA(z)'])) self.assertEqual( macro_eval.EvalExpression("m(abc)", { 'm': [( ['a'], "" )] }), set(['m(abc)', ''])) self.assertEqual( macro_eval.EvalExpression("myfile(hello)", { 'myfile': [(['x'], "myquote(myplace/x)")], 'myquote': [(['y'], """#y""")] }), set(['myfile(hello)', '"myplace/hello"', 'myquote(myplace/hello)'])) def test_FromCPPInternals(self): # This little example works. # # #define foo(x) bar x # # foo(foo) (2) == bar foo (2) # # Let us check that. self.assertEqual( macro_eval.EvalExpression("foo(foo) (2)", {'foo':[(['x'], "bar x")]}), set(['bar foo (2)', 'foo(foo) (2)'])) # The next one does not work, because we are not inserting spaces. # # From : # http://gcc.gnu.org/onlinedocs/cppinternals/Token-Spacing.html#Token-Spacing # # #define PLUS + # #define EMPTY # #define f(x) =x= # # +PLUS -EMPTY- PLUS+ f(=) # ==> + + - - + + = = = # # We do not insert spaces as CPP does. But we generate a lot of # combinations! self.assertEqual( macro_eval.EvalExpression("+PLUS -EMPTY- PLUS+ f(=)", { 'PLUS':['+'], 'EMPTY':[""], 'f':[(['x'], '=x=')] }), set(['++ -EMPTY- ++ ===', '++ -EMPTY- PLUS+ ===', '+PLUS -- ++ f(=)', '+PLUS -EMPTY- ++ ===', '++ -EMPTY- PLUS+ f(=)', '+PLUS -EMPTY- PLUS+ f(=)', '+PLUS -- ++ ===', '++ -EMPTY- ++ f(=)', '+PLUS -- PLUS+ ===', '+PLUS -- PLUS+ f(=)', '++ -- PLUS+ ===', '++ -- ++ ===', '+PLUS -EMPTY- PLUS+ ===', '++ -- PLUS+ f(=)', '+PLUS -EMPTY- ++ f(=)', '++ -- ++ f(=)'])) def test_ResolveExpr(self): # Erect the edifice of caches. caches = cache_basics.SetUpCaches(self.tmp) parse_file_obj = parse_file.ParseFile(caches.includepath_map) symbol_table = {} # Set up symbol_table by parsing test_data/more_macros.c. self.assertEqual(parse_file_obj.Parse( "test_data/more_macros.c", symbol_table), ([], [], ['TEMPLATE_VARNAME(foo)'], [])) # Check what we got in symbol_table. self.assertEqual( macro_eval.EvalExpression("TEMPLATE_VARNAME(foo)", symbol_table), set(['TEMPLATE_VARNAME(foo)', '"maps/foo.tpl.varnames.h"', 'AS_STRING(maps/foo.tpl.varnames.h)', 'AS_STRING_INTERNAL(maps/foo.tpl.varnames.h)'])) # Verify that resolving this expression yields one actual file (which we # have placed in test_data/map). [((d, ip), rp)], symbols = macro_eval.ResolveExpr( caches.includepath_map.Index, caches.build_stat_cache.Resolve, 'TEMPLATE_VARNAME(foo)', caches.directory_map.Index(os.getcwd()), # current dir caches.directory_map.Index(""), # file directory [caches.directory_map.Index("test_data")], # search directory [], symbol_table) self.assertEqual(caches.directory_map.string[d], "test_data/") self.assertEqual(caches.includepath_map.string[ip], "maps/foo.tpl.varnames.h") self.assertEqual(symbols, set(['TEMPLATE_VARNAME', 'maps', 'AS_STRING', 'AS_STRING_INTERNAL', 'tpl', 'varnames', 'h', 'foo'])) unittest.main() distcc-3.1/source/include_server/c_extensions_test.py0000750000175000017500000001043311115326647022272 0ustar wolffwolff#!/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 os.path import random import sys import time import distcc_pump_c_extensions def RunTest(random_filename): def _MakeTempFile(mode): return open(random_filename, mode) # Exercise metainformation and documentation strings assert distcc_pump_c_extensions.__file__ assert distcc_pump_c_extensions.__doc__ assert distcc_pump_c_extensions.__author__ assert distcc_pump_c_extensions.RTokenString.__doc__ assert distcc_pump_c_extensions.RArgv.__doc__ assert distcc_pump_c_extensions.XArgv.__doc__ assert distcc_pump_c_extensions.OsPathExists.__doc__ assert distcc_pump_c_extensions.OsPathIsFile.__doc__ assert distcc_pump_c_extensions.Realpath.__doc__ # RTokenString and RArgv # Pack something and try sending it fd = _MakeTempFile('wb') fd.write('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 unused_i in range(10000): distcc_pump_c_extensions.OsPathExists(f) print 'Stat', time.time() - t t = time.time() for unused_i in range(10000): os.path.exists(f) print 'os.path.exists', time.time() - t for unused_i in range(10000): distcc_pump_c_extensions.Realpath(f) print 'c_realpath', time.time() - t t = time.time() for unused_i in range(10000): os.path.realpath(f) print 'os.path.realpath', time.time() - t print 'c_extenstions_test passed' def main(): # Module tempfile doesn't work with distcc. Work-around follows. random_testdir = ('/tmp/distcc-pump-c-extensions-test-%s.%s' % (os.getuid(), random.random() * time.time())) try: if os.path.exists(random_testdir): os.removedirs(random_testdir) os.mkdir(random_testdir, 0700) except (IOError, OSError), why: sys.exit('Unable to create test dir %s: %s.' % (random_testdir, why)) random_filename = os.path.join(random_testdir, 'test') assert not os.path.exists(random_filename), random_filename try: RunTest(random_filename) finally: if os.path.exists(random_filename): os.unlink(random_filename) if os.path.exists(random_testdir): os.removedirs(random_testdir) main() distcc-3.1/source/include_server/mirror_path_test.py0000750000175000017500000001174611115326647022127 0ustar wolffwolff#! /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 shutil import tempfile import unittest NotCoveredError = basics.NotCoveredError class MirrorPathTest(unittest.TestCase): """We construct a mock-up world of a file system in order to unittest the DoPath function of mirror_path.""" def setUp(self): basics.debug_pattern = 3 self.tmp = tempfile.mkdtemp() caches = cache_basics.SetUpCaches(self.tmp) self.canonical_path = caches.canonical_path self.simple_build_stat = caches.simple_build_stat self.mirror_path = mirror_path.MirrorPath(self.simple_build_stat, self.canonical_path, caches.realpath_map, caches.systemdir_prefix_cache) self.directories = ['/', '/a', '/link', '/a/link', '/a/b', '/link/link', '/root'] self.links = ['/a/link', '/link', '/link/link'] self.exists = self.directories + self.links self.realpaths = {'/' :'/', '/a' :'/a', '/a/link' :'/a/b', '/link' :'/a', '/link/link':'/a/b'} def tearDown(self): shutil.rmtree(self.tmp) def test_MirrorPath(self): try: def isdir(path): return path in self.directories def exists(path): return path in self.exists def islink(path): return path in self.links def realpath(path): if path.startswith('/root'): self.fail("Not expected that '%s' 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() distcc-3.1/source/include_server/include_analyzer_test.py0000750000175000017500000004670311115326647023132 0ustar wolffwolff#! /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 shutil import tempfile import unittest import basics import cache_basics import parse_command import statistics import include_analyzer_memoizing_node class IncludeAnalyzerTest(unittest.TestCase): def setUp(self): statistics.StartTiming() self.global_dirs = [] basics.opt_print_statistics = False basics.opt_debug_pattern = 1 client_root_keeper = basics.ClientRootKeeper() if algorithm == basics.MEMOIZING: self.include_analyzer = ( include_analyzer_memoizing_node.IncludeAnalyzerMemoizingNode( client_root_keeper)) else: self.fail("Algorithm not known.") statistics.StartTiming() self.directory_map = self.include_analyzer.directory_map self.compiler_defaults = self.include_analyzer.compiler_defaults self.canonical_path = self.include_analyzer.canonical_path def tearDown(self): if basics.opt_print_statistics: statistics.EndTiming() statistics.PrintStatistics(self.include_analyzer) def ProcessCompilationCommandLine(self, cmd, cwd): return ( self.include_analyzer.ProcessCompilationCommand( cwd, parse_command.ParseCommandArgs( parse_command.ParseCommandLine(cmd), cwd, self.include_analyzer.includepath_map, self.include_analyzer.directory_map, self.include_analyzer.compiler_defaults))) def CanonicalPathsForTestData(self, dirs, test_data_dir='test_data'): """Absolutize names relative to test_data_dir of current directory.""" return set([ self.canonical_path.Canonicalize(test_data_dir + '/' + f) for f in dirs ]) def RetrieveCanonicalPaths(self, files): return set([ self.include_analyzer.realpath_map.string[f] for f in files ]) def test_AdvancedComputedIncludes(self): includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc test_data/test_computed_includes/src.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData(['test_computed_includes/src.c', 'test_computed_includes/helper.c', 'test_computed_includes/incl.h'])) includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc test_data/test_computed_includes/srcA.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData(['test_computed_includes/srcA.c', 'test_computed_includes/helper.c', 'test_computed_includes/incl.h', 'test_computed_includes/inclA.h'])) # Test: FindNode is called once only if previous query is repeated. That is, # include graph is not calculated for this query. old_FindNode = self.include_analyzer.FindNode class mock_FindNode(object): def __init__(self): self.count = 0 def FindNode(self, *_): self.count += 1 if self.count == 2: raise Exception, "Did not expect 2 calls of FindNode." return old_FindNode(*_) self.include_analyzer.FindNode = mock_FindNode().FindNode try: includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc test_data/test_computed_includes/srcA.c", os.getcwd())) finally: self.include_analyzer.FindNode = old_FindNode # Test: if a -D option affecting the value of the computed include is # presented then include graph is recalculated --- and correctly so. includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( r"""gcc -DINCL=\"../dfoo/foo2.h\" """ + " test_data/test_computed_includes/src.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData(['test_computed_includes/src.c', 'test_computed_includes/helper.c', 'test_computed_includes/incl.h', 'test_computed_includes/inclA.h', 'dfoo/foo2.h'])) # Test: functional macros can be passed on the command line. includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( """gcc -D"STR(X)=# X" """ + """-D"FINCLUDE(P)=STR(../MY_TEST_DATA/dfoo/P)" """ + """-DMY_TEST_DATA=test_data """ + "test_data/func_macro.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['func_macro.c', 'dfoo/foo.h', 'dfoo/foo2.h', 'dbar/dbar1/bar.h' ])) def test_AbsoluteIncludes(self): try: opt_unsafe_absolute_includes = basics.opt_unsafe_absolute_includes basics.opt_unsafe_absolute_includes = True tmp_dir = tempfile.mkdtemp() def WriteProgram(name, text): base = os.path.dirname(os.path.join(tmp_dir, name)) if not os.path.isdir(base): os.makedirs(base) fd = open(os.path.join(tmp_dir, name), 'w') fd.write(text) fd.close() WriteProgram('foo.c', """#include "%s/bar/baz.h" blah blah. """ % tmp_dir) # We don't want to get entangled in absolute includes. # The baz.h program is not supposed to be found (although # real preprocessing will). WriteProgram('baz.h', """#include "../foobar.h" blah blah. """) includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc %s" % os.path.join(tmp_dir, 'foo.c'), os.getcwd())) self.assertEqual( includes, set([os.path.realpath('%s/foo.c' % tmp_dir)])) finally: basics.opt_unsafe_absolute_includes = opt_unsafe_absolute_includes shutil.rmtree(tmp_dir) def test_StatResetTriggers(self): """Check that the include analysis of a file is done from scratch after a trigger path went from non-existing to existing. """ def CheckGeneration(lst, expected): for f_name in lst: self.failUnless( re.match(r"%s/.+[.]include_server[-][0-9]+[-]%s" % (self.include_analyzer.client_root_keeper.client_tmp, expected), f_name), f_name) def GetFileNamesFromAbsLzoName(lst): """Transform lists with elements like: '/dev/shm/tmpsn6NQT.include_server-12272-X/.../test_data/foo.c.lzo' to lists with elements like: 'test_data/foo.c'""" return [ f_name.split('/')[-2] + '/' + f_name.split('/')[-1][:-4] for f_name in lst if f_name.endswith('.lzo') ] self.include_analyzer.stat_reset_triggers = {"seven*": {}, "ate": {"ate": (1,111,2)}, "nine": {} } try: real_glob_glob = glob.glob def Mock_GlobGlob(f): if f in ["seven*", "nine"]: return [] if f == 'ate': return ["ate"] return real_glob_glob(f) glob.glob = Mock_GlobGlob real_os_stat = os.stat def Mock_OsStat(f): # Return the same as initial value in two cases below. if f in ["seven", "nine"]: raise OSError if f == 'ate': obj = lambda: None obj.st_mtime = 1 obj.st_ino = 111 obj.st_dev = 2 return obj return real_os_stat(f) os.stat = Mock_OsStat real_cache_basic_OsPathIsFile = cache_basics._OsPathIsFile def Mock_OsPathIsFile(f): # We postulate that the test_data/stat_reset_triggers.h file does not # yet exists. Moreover, we pretend that a version ind test_data/dfoo is # in existence. return f in [ "test_data/stat_triggers.c", "test_data/dfoo/stat_triggers.h"] cache_basics._OsPathIsFile = Mock_OsPathIsFile files_and_links = self.include_analyzer.DoCompilationCommand( "gcc -Itest_data/dfoo test_data/stat_triggers.c".split(), os.getcwd(), self.include_analyzer.client_root_keeper) # Check that we picked up the dfoo version of the .h file! self.assertEqual(GetFileNamesFromAbsLzoName(files_and_links), ['test_data/stat_triggers.c', 'dfoo/stat_triggers.h']) # The generation should still be the original, namely 1. self.assertEqual(self.include_analyzer.generation, 1) CheckGeneration(files_and_links, 1) def New_Mock_OsStat(f): if f in ["seven", "nine"]: raise OSError if f == 'ate': obj = lambda: None obj.st_mtime = 1 obj.st_ino = 111 obj.st_dev = 3 # so, this component changed from previous value return obj return real_os_stat(f) os.stat = New_Mock_OsStat def New_Mock_OsPathIsFile(f): return f in [ "test_data/stat_triggers.c", "test_data/stat_triggers.h", "test_data/dfoo/stat_triggers.h"] cache_basics._OsPathIsFile = New_Mock_OsPathIsFile files_and_links = self.include_analyzer.DoCompilationCommand( "gcc -Itest_data/dfoo test_data/stat_triggers.c".split(), os.getcwd(), self.include_analyzer.client_root_keeper) self.assertEqual(self.include_analyzer.generation, 2) CheckGeneration(files_and_links, 2) # Now, check that we picked up the test_data version of the .h file, not # the dfoo one! self.assertEqual(GetFileNamesFromAbsLzoName(files_and_links), ['test_data/stat_triggers.c', 'test_data/stat_triggers.h']) # Third time. def New_Mock_GlobGlob(f): if f in ["seven*"]: return ["seventy"] if f in ["nine"]: return [] if f == 'ate': return ["ate"] return real_glob_glob(f) glob.glob = New_Mock_GlobGlob def New_New_Mock_OsStat(f): if f in ["seven", "nine"]: raise OSError if f == 'ate': obj = lambda: None obj.st_mtime = 1 obj.st_ino = 111 obj.st_dev = 3 return obj if f == 'seventy': obj = lambda: None obj.st_mtime = 2 obj.st_ino = 222 obj.st_dev = 3 return obj return real_os_stat(f) os.stat = New_New_Mock_OsStat # Revert _OsPathIsFile cache_basics._OsPathIsFile = Mock_OsPathIsFile files_and_links = self.include_analyzer.DoCompilationCommand( "gcc -Itest_data/dfoo test_data/stat_triggers.c".split(), os.getcwd(), self.include_analyzer.client_root_keeper) # Now, check that we again picked up the dfoo version of the .h file. self.assertEqual(GetFileNamesFromAbsLzoName(files_and_links), ['test_data/stat_triggers.c', 'dfoo/stat_triggers.h']) self.assertEqual(self.include_analyzer.generation, 3) CheckGeneration(files_and_links, 3) finally: glob.glob = real_glob_glob os.stat = real_os_stat cache_basics._OsPathIsFile = real_cache_basic_OsPathIsFile def test_DotdotInInclude(self): """Set up tricky situation involving an "#include "../foo" occurring in a file accessed through a symbolic link. This include is to be resolved relative to the file directory, namely where the link is, not where the file is. Also, the include processor tries to identify files by their relatives names. This may lead to an infinite recursion according to an increasing sequence of filepath names involving "../" So if the included file includes the original file, an infinite loop may occur.""" # In test_data, we find # # symlink_farm/sub_farm/link_to_dd_dd_dfoo_include_dotdot_foo # # which is a link to ../../dfoo/include_dotdot_foo, that is, to # # dfoo/include_dotdot_foo # # which is a file that contains: # # #include "../foo" # # Here ../foo must refer to the file in location symlink_farm/sub_farm/foo, # which we have made a real file (not a symlink). # # We check that this "foo" is included. Moreover, we have put: # # #include "sub_farm/link_to_dd_dd_dfoo_include_dotdot_foo" # # into symlink_farm/sub_farm/foo, so that a nice infinite inclusion chain # is modeled. That should not faze the include server. In particular, we # do not want to see an infinitude of paths of the form: # # symlink_farm/sub_farm/../sub_farm/../ # ... # /sub_farm/../sub_farm/foo includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc -xc test_data/symlink_farm/sub_farm/" + "link_to_dd_dd_dfoo_include_dotdot_foo", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['dfoo/include_dotdot_foo', 'symlink_farm/foo'], "test_data")) def helper_test_IncludeAnalyzer(self, test_data_dir): """Test basic functionality assuming test data is in test_data_dir.""" # Simple stuff: quoted and angled directories, recursion includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc -Itest_data/dfoo test_data/parse.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['parse.c', 'dfoo/foo2.h', 'dfoo/foo.h', 'dfoo/../dbar/dbar1/bar.h'], test_data_dir)) # Computed includesgg includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc -Itest_data/dfoo test_data/computed_includes.c", os.getcwd())) # The path to the computed angle includes was not provided, so # they were not found. self.assertEqual( includes, self.CanonicalPathsForTestData( ['computed_includes.c', 'p1.h'], test_data_dir)) # Check that symbol_table has been updated. self.assertEqual(self.include_analyzer.symbol_table, {'dfoo_foo2_h': [None], 'A': ['"p1.h"'], 'dbar_dbar1_bar_h': [None], 'm': [(['a'], ''), (['a'], '')]}) # The include path to the angle includes, -Itest_data, is # provided at our next try. This should include abc_pre.c and # abc_post.c. This is especially challenging for incremental # analysis because the previous cached result of include analyzing # computed_includes.c cannot in fact be reused here. That is an # unusual case. includes = self.RetrieveCanonicalPaths( self.ProcessCompilationCommandLine( "gcc -Itest_data/dfoo -Itest_data" + " test_data/computed_includes.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['computed_includes.c', 'p1.h', 'abc_post.c', 'abc_pre.c'], test_data_dir)) # The inclusion chain is baz/start_x -> baz/x.h -> foo/x.h -> # bar/x.h -> baz.h. Only the final #include_next "x.h" in baz/x.h # does not Resolve because we just used -Ibaz for resolution, the # last in the list. This should not raise an exception, because the # failure may in reality not happen: the bad include_next could be # guarded by a conditional for example. self.assertEqual( self.RetrieveCanonicalPaths(self.ProcessCompilationCommandLine( "gcc -E -Itest_data/test_include_next/foo" + " -Itest_data/test_include_next/bar" + " -Itest_data/test_include_next/baz" + " test_data/test_include_next/baz/start_x.c", os.getcwd())), self.CanonicalPathsForTestData( ['test_include_next/baz/start_x.c', 'test_include_next/baz/x.h', 'test_include_next/foo/x.h', 'test_include_next/bar/x.h', 'test_include_next/baz/x.h'], test_data_dir)) # In contrast to previous example, the #final include_next in baz # resolves this time, namely to biz/x.h. self.assertEqual( self.RetrieveCanonicalPaths(self.ProcessCompilationCommandLine( "gcc -E -Itest_data/test_include_next/foo" + " -Itest_data/test_include_next/bar" + " -Itest_data/test_include_next/baz" + " -Itest_data/test_include_next/biz" + " test_data/test_include_next/baz/start_x.c", os.getcwd())), self.CanonicalPathsForTestData( ['test_include_next/baz/start_x.c', 'test_include_next/baz/x.h', 'test_include_next/foo/x.h', 'test_include_next/bar/x.h', 'test_include_next/biz/x.h'], test_data_dir)) includes = self.RetrieveCanonicalPaths(self.ProcessCompilationCommandLine( "gcc -E -Itest_data/test_include_next/foo" + " -Itest_data/test_include_next/bar" + " -Itest_data/test_include_next/baz" + " test_data/test_include_next/baz/start_y.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['test_include_next/baz/start_y.c', 'test_include_next/baz/../foo/y.h', 'test_include_next/bar/y.h', 'test_include_next/foo/y.h', 'test_include_next/baz/y.h'], test_data_dir)) # Test that a directory that has a name matching an include is not picked. # Here the directory is test_data/i_am_perhaps_a_directory.h, which is in # the file directory of the translation unit. Instead, # test_data/dfoo/i_am_perhaps_a_directory.h should be picked: it is a # regular file. includes = self.RetrieveCanonicalPaths(self.ProcessCompilationCommandLine( "gcc -E -Itest_data/dfoo test_data/test_directory_probing.c", os.getcwd())) self.assertEqual( includes, self.CanonicalPathsForTestData( ['test_directory_probing.c', 'dfoo/i_am_perhaps_a_directory.h'], test_data_dir)) def test_IncludeAnalyzer(self): """Run helper_test_IncludeAnalyzer 'directly' without complications of symbolic links.""" self.helper_test_IncludeAnalyzer('test_data') def test_IncludeAnalyzer_from_symlink_farm(self): """Run helper_test_IncludeAnalyzer through a link farm to exercise include processors ability to handle links.""" self.helper_test_IncludeAnalyzer('test_data/symlink_farm') for algorithm in [ basics.MEMOIZING ]: try: print "TESTING ALGORITHM %s" % algorithm unittest.main() except: raise distcc-3.1/source/ChangeLog0000640000175000017500000276072311115326647014737 0ustar wolffwolff2008-12-02 21:44 Fergus Henderson * Makefile.in, NEWS, configure.ac, include_server/setup.py: 1. Fix some compilation errors arising from the use of -Wwrite-strings when compiling the python extension module, due to lack of const correctness in the Python 2.2 "Python.h" header file. This problem was introduced by the fix for distcc issue 26 . The solution was to explicitly disable these warnings with -Wno-write-strings. 2. Centralize the use of gcc-specific compilation options in conditional code in configure.ac that is only executed if we're using gcc. Previously include_server/setup.py was hard-coding gcc-specific options, regardless of whether we're using gcc. 3. Don't use -Wuninitialized if CFLAGS doesn't contain "-O*", because -Wuninitialized only works if optimization is enabled. This avoids a gcc warning (and hence an error with -Werror) about -Wuninitialized not having any effect when distcc is configured with "CFLAGS=-g ./configure". 4. Add a new configure option "--disable-Werror". For the 3.0 release of distcc, some people porting distcc resorted to patching distcc to remove the -Werror option. -Werror is useful, so I want to keep it enabled by default, but I'd prefer that people are able to port distcc easily, hence the configure option. This addresses distcc issue 20 . Reviewers: Craig Silverstein 2008-12-01 23:44 Fergus Henderson * ChangeLog, NEWS, configure.ac: Bump version number to 3.1, and update the NEWS file and ChangeLog. Reviewed by Craig Silverstein. 2008-10-27 22:11 Fergus Henderson * Makefile.in: Apply matsuu's patch to fix issue 26 "missing CFLAGS for include-server" . 2008-10-27 14:38 Fergus Henderson * include_server/c_extensions/distcc_pump_c_extensions_module.c: Applied matsuu's patch for issue 27 "failed to make distcc" , which was a build problem on "Gentoo, x86-64, gcc-4.1.2, glibc-2.6.1, python-2.5.2". 2008-10-27 14:17 Fergus Henderson * Makefile.in: Include the "m4" directory in the source distribution tarball, so that users of the source distribution can (re)run "autogen.sh". Reviewers: Craig Silverstein 2008-10-05 16:43 Fergus Henderson * src/arg.c: Fix a silly mistake (missing "== 0" after strcmp() call) that broke the parsing of "-Wp,-MMD,..." options. This fixes . 2008-09-27 01:57 Fergus Henderson * include_server/test_data/gws-main.o.cmd[DEL]: Delete an unused test data file; it became dead after my previous change which deleted the test that used it. 2008-09-27 01:55 Fergus Henderson * include_server/parse_command_test.py: Delete an unused test case: the test was hard-coded to always pass anyway, so it wasn't testing anything useful. 2008-09-13 17:23 Fergus Henderson * doc/web/man/distcc_1.html, man/distcc.1, src/exitcode.h: Incorporate 01_distcc_man.dpatch from debian distribution. This patch adds documentation of all of the exit codes to the man page. Also add comment to exitcode.h reminding maintainers to update the man page. Also update the HTML versions of the man pages. 2008-09-11 18:48 Fergus Henderson * NEWS, include_server/include_analyzer.py, man/distcc.1, src/clirpc.c, src/compile.c, src/compile.h, src/distcc.c, src/distcc.h, src/include_server_if.c, src/include_server_if.h, src/util.c, test/testdistcc.py: Provides a simple shell API to the include server: add a new "--scan-includes" option to distcc which shows which headers distcc would send to the remote machine in pump mode, without actually compiling anything. 2008-09-10 02:39 Fergus Henderson * pump.in: Fix : the pump script was hard-coding /etc/distcc/hosts rather than using the prefix specified to configure. Reviewed by Craig Silverstein. 2008-09-08 17:51 Fergus Henderson * Makefile.in, src/hosts.c: Report a better error message if a host specification contains ",cpp" but not ",lzo". Previously, setting ",cpp" without ",lzo" would quietly set the protocol version to -1, which the server would then quietly reject (logging as "REJ_BAD_REQ"), and then the client would guess (poorly) at why the server had dropped the connection. Reviewed by Craig Silverstein. 2008-08-07 22:58 Fergus Henderson * doc/web/man/distcc_1.html, doc/web/man/pump_1.html: Update the HTML versions of the man pages. 2008-08-07 22:50 Fergus Henderson * doc/web/index.html: Delete a duplicate link in the side-bar. 2008-08-06 20:37 Fergus Henderson * ChangeLog, NEWS, configure.ac: Change version number to "3.0", and update NEWS file and ChangeLog. 2008-08-06 15:37 Fergus Henderson * man/distcc.1, man/pump.1: Some final documentation updates before 3.0. In the distcc man page: - remove description of a bug that's been fixed now (distcc issue 7) - make it a little clearer that in pump mode we don't ship the header files from the default system header directories to the server - add a new section header "RESTRICTIONS OF PUMP MODE" - some typographical corrections. In the pump man page: - add a prominent pointer to the distcc man page, in particular to the "RESTRICTIONS OF PUMP MODE" section. Reviewers: Craig Silverstein ## distcc 3.0rc4. 2008-08-02 19:54 Fergus Henderson * ChangeLog, NEWS, configure.ac: Time for another release candidate. 2008-08-02 19:49 Fergus Henderson * test/testdistcc.py: Add C++ version of the SystemIncludeDirectories test. Also, reduce code duplication a little by adding a compileOpts() function to the CompilationCase class, and overriding that, rather than compileCmd(), in various derived classes. 2008-08-02 17:50 Fergus Henderson * include_server/compiler_defaults.py: Fix a TODO in compiler_defaults.py that was responsible for a bug that broke pump mode when one of the default system include directories was a subdirectory of another, as turns out to be the case for GNU C++. The CPlusPlus_SystemIncludeDirectories_Case, which was failing before this change, now passes. (TODO: re-enable it.) Reviewers: Craig Silverstein 2008-08-02 01:30 Fergus Henderson * bench/benchmark.py: Make the benchmarking script's stdout and stderr line buffered. Reviewers: Craig Silverstein 2008-08-02 01:27 Fergus Henderson * test/testdistcc.py: Add a test of C++ compilation, and refactor the tests of Objective-C and Objective-C++ to share the common code. Also, fix some bugs in the tests of Objective-C and Objective-C++. These tests were never being activated, even when the right compiler is installed, because in the test compilation (not using distcc) it was compiling with "-o /dev/null" and then testing that testtmp.o exists, which it never did. There was also a missing "std::" in the Objective-C++ test. I still haven't run the Objective-C++ test, because I still haven't figured out how to install Objective-C++, but it's pretty similar to the C++ and Objective-C tests, and both of those now run and pass. Reviewers: Craig Silverstein 2008-08-01 20:59 Fergus Henderson * bench/ProjectDefs.py: Update a stale URL. ## distcc 3.0rc3. 2008-08-01 03:42 Fergus Henderson * include_server/basics.py: Increase MAX_COMPONENTS_IN_SERVER_ROOT from 10 to 20. It turns out that our own test infrastructure (test/testdistcc.py) sets TMPDIR before invoking distccd, so this needs to be reasonably high, otherwise 'make distcheck' will fail. 2008-08-01 03:11 Fergus Henderson * Makefile.in: List va_copy.h in HEADERS, so that it gets included in the source distribution. 2008-07-31 19:19 Fergus Henderson * ChangeLog, NEWS, configure.ac: Bump version number to 3.0rc3, and update NEWS file and ChangeLog. Reviewed by Craig Silverstein. 2008-07-31 05:40 Fergus Henderson * src/distcc.h, src/filename.c: Fix issue 10 : add a work-around for a spurious gcc warning. Also, add a missing check for strdup() returning NULL. 2008-07-30 22:56 Fergus Henderson * src/dotd.c, src/serve.c, src/strip.c, test/testdistcc.py: Add a test case to test "-MT" and "-MF" without spaces after them. Some more bug fixes to make the test case pass. Also, make the DashWpMD_Case test a bit more strict: disable fallbacks, so that it tests that we can distribute such jobs. 2008-07-30 02:28 Fergus Henderson * src/fix_debug_info.c, src/netutil.c, src/snprintf.c, src/srvnet.c: Fix some warnings with -Wcast-align that show up only on machines that don't support unaligned accesses. Fix some const correctness warnings that show up only on machines that don't have vsnprintf(). Reviewers: Craig Silverstein 2008-07-30 02:27 Fergus Henderson * src/arg.c: Fix issue 13 : allow distcc to distribute commands that use "-MF" rather than "-MF ", and likewise for -MT and -MQ. 2008-07-30 01:13 Fergus Henderson * src/clirpc.c, src/tempfile.c: Apply patch from e...@jessies.org in : use S_ISLNK and S_ISDIR macros, to make the code more readable. 2008-07-29 23:04 Fergus Henderson * Makefile.in: In the Makefile, add a target for running a single test in pump mode. 2008-07-29 22:19 Fergus Henderson * include_server/basics.py, include_server/cache_basics.py, include_server/compiler_defaults.py, include_server/include_analyzer.py, include_server/macro_eval_test.py, include_server/mirror_path.py, include_server/mirror_path_test.py, include_server/parse_command_test.py, src/srvrpc.c, src/tempfile.c, test/testdistcc.py: This is based on klarlund's original version of this patch (klarlund/d3b3): gvn --project https://distcc.googlecode.com/svn/trunk review klarlund/d3b3 Fix Issue 7: Compiling with -I/usr/include/FOO or ... in pump mode Problem: Default system include directories are the directories on the default include search path, such as /usr/include, that is determined by the compiler. Distcc will not send default system include directories to the distcc compilation servers. Nevertheless, distcc on the server blindly rewrites -I options such as -I/usr/include/foo to -I/tmp/distccNNN/usr/include/foo. This doesn't work, since the files in /usr/include/foo are not sent to the distccd server. Solution: The present solution keeps the rewriting on the server, because we would like to not manage starting the compiler, parsing its output, and storing the default system paths on the server Instead, we use the existing mechanism for defining relative symbolic links under the server root. We escape from the root by using a sufficient number of '../'s. All this is tremendously complicated by: -- The possibility that other links encountered may point into the system default dirs in which case the usual mirroring of the reachable places should not take place, because the routing of such links will go through the link created for the system directory. -- The fact that determination of default-system-dirness is lazy: a deeply-seated link in a default system dir may become obsolete if it is later determined that a higher directory than the parent directory of the link is in fact also a default system dir. In that case, a new symlink, sitting in a place higher than the previous one will need to be created. Tests: make check benchmarks: samba (still 3X faster than with distcc), linux 2.6 kernel, and a couple of others TODO: better testing TODO: > In compiler_defaults.py, _MakeLinkFromMirrorToRealLocation: > Maybe comment each of the 'if' cases with an example of how this case > might be triggered. eg the real_prefix == rooted_system_dir is > triggered when we see /usr/include/foo, and the later see > /usr/include. 2008-07-29 22:17 Fergus Henderson * configure.ac, src/snprintf.c, src/trace.c, src/va_copy.h: Fix a bug that caused "make check" to fail: MissingCompiler_Case was reporting an unexpected exit status: 139 instead of 110. This was caused by a seg fault in distccd, deep in the bowels of vsnprintf(), which appears to be due to calling vsnprintf() twice on the same va_list. The fix is to use va_copy() in src/trace.c. Of course it's never quite as easy as that. va_copy() exists only in C99, not in C89. Some implementations have __va_copy() but not va_copy(). So we need to autoconf it. There was already an autoconf test for this, but only for __va_copy. I've moved the code which defined VA_COPY from snprintf.c to a new header file va_copy.h, and added a VA_COPY_END macro. Also, fix another bug that I noticed at the same time: snprintf.c was using va_copy(), but was not matching each call to va_copy with a corresponding call to va_end(), as required by the C99 standard. 2008-07-17 21:59 Lei Zhang * configure.ac: This adds an option for disabling avahi and friends. This is useful for building distcc targeted to machines without libavahi on a machine with libavahi. Reviewed by Fergus Henderson. 2008-07-02 00:34 Fergus Henderson * Makefile.in: Fix a bug reported by Aaron P. Perez where "make install" was failing on Cygwin. The problem was due to the install.log file generated by Python's distutils being generated in DOS text mode format rather than Unix text mode format. The fix is to use 'sed' to convert DOS text format to Unix text format when generating install.log. Note: this fix is slightly different than the original patch that I posted to the distcc mailing list. This patch is better because it fixes the install.log file, rather than just the grep command; this is important because the install.log file is also used for "make uninstall". Reviewers: Craig Silverstein 2008-06-30 17:10 Nils Klarlund * include_server/include_analyzer.py, include_server/include_analyzer_memoizing_node.py, include_server/include_analyzer_memoizing_node_test.py, include_server/include_analyzer_test.py, include_server/parse_command.py, include_server/parse_command_test.py: Revert r393. This change is mostly reverted -- some variable renamings are not changed back. A subsequent CL proposes a less arbitrary way to solve the problem of -I, which involves sending no system default header files at all. Tests: make pump-check and make include-server-check 2008-06-27 21:59 Fergus Henderson * NEWS: Delete a duplicate entry from the NEWS file. Reviewers: Craig Silverstein 2008-06-24 22:06 Fergus Henderson * packaging/googlecode_upload.py: Fix wrong description for uploaded distcc-.tar{.gz,.bz2} files. Reviewers: Craig Silverstein ## distcc 3.0rc2. 2008-06-20 15:17 Fergus Henderson * ChangeLog, NEWS: Update NEWS file and ChangeLog for distcc 3.0rc2. Also mention new website, repository and maintainer in NEWS file. 2008-06-20 02:54 Fergus Henderson * configure.ac: Bump version number to 3.0rc2. 2008-06-19 22:25 Fergus Henderson * src/gcc-id.c, src/zeroconf-reg.c, src/zeroconf.c: Add "Copyright (C) 2007 Lennart Poettering" to zeroconf.c, zeroconf-reg.c, and gcc-id.c. Remove Google copyright notice from src/gcc-id.c, since the Google changes to that file were very minor. 2008-06-19 20:55 Fergus Henderson * Makefile.in, packaging/deb.sh, packaging/rpm.sh: Change the deb.sh and rpm.sh scripts to remove old .deb or .rpm files (for the same package and version) before generating the new ones. Similarly change "make install-deb" and "make upload-dist" so that they are more selective in which files they install. This fixes a bug where "make install-deb" tried to install the wrong .deb files, because it just did "rpm -i *.deb", and there can be old .deb files lying around. It also fixes a similar problem in "make upload-dist". Also, add a "tags" target to the Makefile. Reviewers: Craig Silverstein 2008-06-18 03:30 Fergus Henderson * include_server/compiler_defaults.py: Fix bug where the include server would crash if the PATH environment variable wasn't set. 2008-06-18 02:23 Fergus Henderson * packaging/RedHat/conf/clients.allow: Fix a missing word in a comment. 2008-06-17 20:26 Fergus Henderson * src/compile.c, src/lock.c, src/remote.c, src/where.c, src/where.h: Fix for a deadlock bug that I observed (once!) when compiling the Linux kernel in pump mode: - Ensure that locks are acquired in the reverse order that they will be released: acquire remote lock before local lock. - Ensure that locks are released on all fallback paths. - Rename dcc_pick_host_from_list() as dcc_pick_host_from_list_and_lock_it(), so that its locking effect is clearer. - Document the lock ordering invariants. - Document the unlocking behaviour of dcc_compile_remote(). Reviewers: Craig Silverstein, Nils Klarlund 2008-06-17 18:32 Fergus Henderson * man/distcc.1: Document the limitations of pump mode w.r.t. debugging on systems with non-ELF object files. Reviewers: Craig Silverstein, Nils Klarlund 2008-06-11 16:10 Fergus Henderson * src/arg.c: Apply patch from Maks Verver which fixes a bug where distcc was not doing the right thing when invoked with "-march=native" or "mtune=native". This fixes . 2008-06-10 21:21 Fergus Henderson * doc/web/faq.html: Document the use of ssh connection sharing. 2008-06-10 05:51 Craig Silverstein * pump.in: When I moved the envvar declarations to inside the 'eval', I had to quote them to protect them from the extra level of evaluation, but I had failed to do this. This change makes it so I do. Tested by running 'make pump-maintainer-check on linux (ubuntu). Detected and reviewed by fergus ## distcc 3.0rc1. ## The following changes were made internally to Google, and not integrated ## into the main distcc distribution until 2008. The dates here are ## the dates they were applied to the internal-Google branch, and ## interleave with the changes to the main branch, below. 2008-06-10 02:20 Nils Klarlund * doc/web/benchmark.html: Improve wording and accuracy of claims. Just various relatively minor suggestions. I didn't understand the remarks about the importance of having 'beefier' remote machines (their raw CPU power are not different although RAM and number of CPUs per machine differ), so I took them out. Instead, a made a separate point about what would have happened if we'd used multiple-CPU clients. I put in a reference to our gws:gws benchmark, which drove our work. Also, -- Add side point about possible configurations issues and link to man pages. -- The number 'four' (for # of hello compilations) was obtained by inspection of the distcc log. Review: csilvers and fergus (at Google). 2008-06-10 00:52 Craig Silverstein * pump.in: Apparently, for freebsd's sh at least, "eval FOO=a bar" lets bar see FOO=a, while "FOO=a eval bar" does not. So change from the latter formulation to the former. Tested by running 'make pump-maintainer-check' on freebsd and on linux (ubuntu). Reviewed by klarlund 2008-06-10 00:09 Craig Silverstein * test/testdistcc.py: While testdistcc.py tries to use port 42000 to communicate, if it fails it tries 42001, etc. When checking output, make sure we match the port we actually ended up binding on. Tested by running 'make check' on a wide variety or architectures, including a FreeBSD machine where make check failed before this change. Reviewed by fergus 2008-06-09 23:12 Craig Silverstein * man/distcc.1, man/distccd.1, man/include_server.1, man/pump.1: Update date to june 9 instead of june 2. 2008-06-09 23:08 Craig Silverstein * configure.ac: I had talked Fergus into changing the version number from 3.0rc1 to 3.0-rc1. But now rpm is complaining that - is illegal in a version string, so I'm changing it back to 3.0rc1. Sorry Fergus... 2008-06-09 23:07 Craig Silverstein * ChangeLog: I had talked Fergus into changing the version number from 3.0rc1 to 3.0-rc1. But now rpm is complaining that - is illegal in a version string, so I'm changing it back to 3.0rc1. Sorry Fergus... 2008-06-09 22:02 Fergus Henderson * configure.ac: Change version number to 3.0rc1 (for "release candidate 1"). Reviewers: Craig Silverstein 2008-06-09 21:22 Craig Silverstein * Makefile.in, doc/web/man/distcc_1.html, doc/web/man/include_server_1.html, packaging/RedHat/rpm.spec: Update the html version of the man pages, based on the .1 updates. Add include_server, which is a new man page. Update the Makefile to know about the new man page, include it in the distribution, etc. Also update the rpm spec to include it too. 2008-06-09 20:31 Fergus Henderson * TODO: Some updates to the TODO list to mark as done issues which are addressed in distcc 3.0. Reviewers: Craig Silverstein 2008-06-09 20:28 Fergus Henderson * pump.in: Rename "Critique" function as "ReportDiscrepancies", to make it clearer what the function does. Reviewers: Craig Silverstein, Nils Klarlund 2008-06-09 19:59 Nils Klarlund * include_server/include_server.py, man/distcc.1, man/include_server.1, pump.in: The missing include_server(1) man page and additional material about the basic assumptions of distcc-pump added to man/distcc.1 as well. The BUGS section of distcc.1 has been updated. A spelling error correction is made to man/distcc.1. The pump.in script is changed so that it does not introduce other certain defaults than those mentioned in the manual (which are those of the of include server). Finally, I changed the order of the options in the include server source code to be alphabetical in accordance with include_server(1) man page. Reviewers: fergus, csilvers. 2008-06-09 19:53 Nils Klarlund * find_c_extension.sh: Correct obscure bug (that quoting a variable eliminates the conversion of newlines to spaces). Reviewers: fergus and csilvers (at Google). 2008-06-09 16:38 Lei Zhang * src/lsdistcc.c, test/testdistcc.py: lsdistcc should print non-default port numbers. Reviewed by fergus 2008-06-09 15:04 Fergus Henderson * pump.in: Fix typo in Nils' previous change. 2008-06-09 14:14 Nils Klarlund * pump.in, src/compile.c: Add necessary message to pump script with warning that compilations were forced from distcc-pump mode into plain mode. I had resisted doing this at first, because of the max_discrepancies_before_demotion constant in src/compile.c, which actually controls whether there were sufficiently many discrepancies to force a demotion. The problem is that the constant is not known to the pump script. It should be made configurable, through gosh, another env var. But that'll be for later. This constant is currently 1 and it shouldn't be changed. Reviewers: fergus and csilvers. 2008-06-07 01:21 Craig Silverstein * doc/web/benchmark.html, doc/web/compared.html, doc/web/compilers.html, doc/web/faq.html, doc/web/index.html, doc/web/results.html, doc/web/scenarios.html, doc/web/security.html: Add a link to the man pages from the side-bar. Also, fixed up the side-bar from a few non-top-level pages to be consistent with the top-level-pages bars: compilers.html and compared.html. 2008-06-07 01:16 Craig Silverstein * Makefile.in: When uploading the package, we try to update the website as well. Since the website contents are checked into svn, that's just a matter of checking in any auto-generated html-ized pages (eg the man pages). 2008-06-07 01:13 Craig Silverstein * doc/web/benchmark.html, doc/web/man/distcc_1.html, doc/web/man/distccd_1.html, doc/web/man/distccmon_text_1.html, doc/web/man/pump_1.html: Oops, the attribute is called svn:mime-type, not svn:content-type. 2008-06-07 01:10 Craig Silverstein * doc/web/man/distcc_1.html: Update from the empty file. 2008-06-07 01:08 Craig Silverstein * doc/web/man, doc/web/man/distcc_1.html, doc/web/man/distccd_1.html, doc/web/man/distccmon_text_1.html, doc/web/man/pump_1.html: Html version of the man pages, auto-generated. 2008-06-04 07:06 Craig Silverstein * Makefile.in: The avahi files (zeroconf.c, etc), were being left out of the distribution tarball. Add them in. Tested by running 'make distcheck' on a machine with avahi libs installed. Reviewed by fergus 2008-06-04 06:04 Craig Silverstein * pump.in: Get rid of setting is_in_installation; that variable isn't used anywhere anymore, so no reason to set it. Tested by running 'make pump-maintainer-check'. Reviewed by klarlund 2008-06-04 05:17 Craig Silverstein * Makefile.in: It turns out setup.py has a bug(?) in its --record output: in theory, the paths of the --record fields should start with --prefix, but sometimes the paths remove the leading / from --prefix: % env CPPFLAGS='-Isrc -Ilzo -Ipopt' SRCDIR=`pwd` include_server/setup.py install --prefix=/tmp/distcc-bar --record=/dev/stdout --root=/var/ tmp/distcc-bar/lib/python2.4/site-packages/include_server/parse_file_test.pyc [...] % env CPPFLAGS='-Isrc -Ilzo -Ipopt' SRCDIR=`pwd` include_server/setup.py install --prefix=/tmp/distcc-bar --record=/dev/stdout --root=/var /tmp/distcc-bar/lib/python2.4/site-packages/include_server/parse_file_test.pyc [...] It's hard to predict how, when and why it does this (--root=/ and --root="" are particularly confusing cases), but luckily we know we always want the leading slash: configure dies if --prefix isn't an absolute path. So with this change, we just let setup.py write whatever it wants to, and then add a leading slash before each line of the --record output if it's missing. Tested by running ./configure --prefix=/tmp/distcc rm -rf /tmp/distcc; make install rm -rf /var/tmp/tmp/distcc; make install DESTDIR=/var/tmp rm -rf /var/tmp/tmp/distcc; make install DESTDIR=/var/tmp/ and verified that files ended up where expected, and the pump script looked like expected (with pump's sibling files living in /tmp/distcc/...). Reviewed by fergus 2008-06-03 23:06 Craig Silverstein * Makefile.in, configure.ac: Fix up the list of zeroconf files needed to actually compile distcc and distccd. Tested by installing avahi and running 'make' plus 'make check'. Reviewed by klarlund 2008-06-03 21:00 Craig Silverstein * src/zeroconf.h: Fix up the top-of-file comments to look the same as for all the other files. 2008-06-03 20:58 Craig Silverstein * src/zeroconf-reg.c, src/zeroconf.c: Fix some extra comment specifiers that shouldn't have been there. 2008-06-03 12:30 Nils Klarlund * man/distcc.1, man/distccd.1, man/pump.1: Various edits: -- refer to pump(1) credits (and remove distcc(1) credits from pump(1) credentials) -- detail fundamental include server assumption -- clean up incl server discussion -- refer to include_server(1) for hairy stuff (this man page is to follow shortly in separate CL) -- discuss shell scripts instead of symlinks -- change date to June 2 2008 -- other minor edits 2008-06-03 05:43 Craig Silverstein * NEWS: Update the release date. 2008-06-03 05:32 Craig Silverstein * bench/ProjectDefs.py: Add some new benchmark routines (including C++ projects like yate and ACE), and normalize syntax for existing ones. I've tested that we can at least build all of these projects locally, as long as all neccesary dependent packages are installed. Reviewed by fergus 2008-06-03 03:45 Fergus Henderson * bench/Build.py, pump.in: Fix a bug in the pump script where it wasn't waiting for the include server to terminate before exiting. Reviewers: Nils Klarlund, Craig Silverstein 2008-06-03 00:32 Craig Silverstein * doc/web/faq.html, doc/web/index.html, doc/web/results.html, doc/web/scenarios.html, doc/web/security.html: Revamp the toc sidebar to organize the categories a bit better. Also added a benchmark line. 2008-06-03 00:32 Craig Silverstein * doc/web/benchmark.html: Add benchmark results, and a discussion of same. Reviewed by klarlund 2008-06-02 22:38 Fergus Henderson * src/clirpc.c: Fix spelling error and punctuation in warning message. Reviewers: Craig Silverstein 2008-06-02 19:35 Nils Klarlund * include_server/basics.py, include_server/cache_basics.py, include_server/include_server.py, pump.in: Fix option real_path_warning_re not working. I renamed the option to path_observation_re. Now by prefixing INCLUDE_SERVER_ARGS='-d1 --path_observation_re="/usr/.*"' to say make include-server-maintainer-check, one gets a message each time the include server finds a path whose realpath name matches the regular expression. That results in messages like: WARNING include server: For translation unit 'src/testtmp.c', lookup of file 'bits/stdio_lim.h' resolved to '/usr/include/bits/stdio_lim.h' whose realpath is '/usr/include/bits/stdio_lim.h'. To make the interpretation of quoted arguments within INCLUDE_SERVER_ARGS correct, I added 'eval' to the command that cranks up the include server. I remembered to put extra quoted quotes inside the parameters that should be considered a token after the double interpretation that eval implies. 2008-05-31 00:38 Nils Klarlund * test/comfychair.py, test/testdistcc.py: Tidy-up testing framework to overcome recently introduced bug. Testing on cygwine revealed that as tests were being issued the temporary testing directory would suffer from longer and longer prefixes until a 'filename too long' error would stop the party. This is result of an earlier attempt to avoid too much printing to stdout during tests, spefically during recursive test invocations. The problem is that the teardown mechanism of the comfychair enviroment is not expressed -- by any name at all (it could be 'teardown' for example). So, I added a name --- but because there's no expectation that the TestCase class defined there has its teardown method called from derived classes --- I chose the name CleanUps, which corresponds to the private variable. I also made an abstraction for running a test. This new Comfychair.runtest function can the conveniently by called to carry out a subtest. With this CL, 'make pump-maintainer-check' now works on cygwin. 2008-05-30 22:57 Craig Silverstein * AUTHORS, INSTALL, README, README.pump, configure.ac, doc/example/init, doc/web/compared.html, doc/web/compilers.html, doc/web/faq.html, doc/web/favicon.ico, doc/web/index.html, doc/web/results.html, doc/web/scenarios.html, doc/web/security.html, man/distcc.1, man/distccd.1, man/distccmon-text.1, man/pump.1: Documentation fixes: 1) Replace http://distcc.samba.org with the new google code location 2) Add favicon.ico from the distcc.samba.org site 3) Use distcc@lists.samba.org as the only distcc mailing list (there were at least three mailing lists scattered around the docs, some of which don't even exist anymore!) 4) Update man pages and other docs to not use "distcc-pump" anywhere; it's now "pump mode" or "distcc's pump mode", or "distcc-pump mode". I also add, to the README, some discussion of scaling to hundreds of machines. Reviewed by fergus and klarlund 2008-05-30 07:46 Fergus Henderson * Makefile.in, packaging/RedHat/rpm.spec: Fix a bug where the "pump" man page was not included in the RPM and Debian packages. Also, fix a bug where the Makefile rules for building HTML files were not working when srcdir != builddir. Tested by "make install-deb; man pump". Reviewers: Craig Silverstein 2008-05-29 21:44 Nils Klarlund * bench/Build.py: Add include server option '--unsafe_absolute_includes' to all benchmarks in pump mode. This is harmless I think, and it's easy to forget this option. It is of importance to at least Samba-2.2.7. 2008-05-29 18:51 Nils Klarlund * bench/benchmark.py, bench/compiler.py: Tigthen how compilers are located. This overcomes issues on Cygwin. I also changed default C++ compiler to 'c++' instead of 'cxx'. 'c++' is the more common name I believe. Witht this change, both compilers must exist for benchmark.py to run. REVIEW: Craig Silverstein 2008-05-29 18:51 Nils Klarlund * bench/Build.py, bench/Summary.py, bench/statistics.py: Enhance performance reporting for benchmarking. This CL adds reporting of: - number of processors - total cpu time - cpu utilization - include server cpu time I corrected issues with overly loose specification of compiler locations. (I developed this CL under Cygwin and encountered new problems.) This resulted in evil recursive invocations of distcc. I also: -- removed an unnecessary parameter from Build(..) -- pruned the number of decimals reported from 4 to 1. -- removed the dependency of 'Numeric', which is a non-standard package and rewrote the math do to std deviation -- use shell built-in 'time' instead of Python time functionality -- corrected deficient error reporting: builds would fail with non-zero status and not be reported as failing. REVIEW: Craig Silverstein TESTS: DISTCC_HOSTS="--randomize `/home/klarlund/svn-distcc/distcc/lsdistcc -P1 -k100 -d`" PATH=`pwd`:$PATH bench/benchmark.py --cc='/usr/crosstool/v10/gcc-4.2.1-glibc-2.3.2/x86_64-unknown-linux-gnu/bin/x86_64-unknown-linux-gnu-gcc' -n 1 -c 'pump,h40,j120' -c 'dist,h40,j32' linux-2.6.25 Part of the printout for hello-2.1.1: Local number of CPUs: 4 Linux klarlund-warp.nyc.corp.google.com 2.6.18.5-gg34workstation-mixed64-32 #1 SMP Thu May 8 01:31:23 UTC 2008 x86_64 GNU/Linux project compiler time s.d. CPU time CPU util incl serv hello-2.1.1 pump_h39_j120 0.9s 0.0s 0.5s 13.5% 0.2s hello-2.1.1 dist_h39_j32 0.4s 0.1s 0.3s 18.1% (For this small program, pump is a disadvantage.) 2008-05-29 05:38 Craig Silverstein * bench/Build.py, bench/Project.py, bench/actions.py, bench/benchmark.py, bench/compiler.py: Some changes to the benchmark framework to not redo work unnecessarily. Most prominently, no longer re-run 'tar xf && configure' every benchmark run. Instead, if configure was successfully executed last benchmark run, just do 'make clean'. This is equivalent to what we do now between build runs, when the repeat-count is > 1. This feature is not turned on by default, but must be enabled with the new --force=0 flag. --force=1 keeps the same behavior as before: we always re-run configure in each build-directory. --force=2 adds more repeat-work than before; in --force=2 mode, we always re-download the package from the web, even if we had successfully downloaded it before. Note that the 'tar' command currently warms the file-cache, which makes build times more consistent, so there is so cost to setting --force=0, in terms of the data collected. Reviewed by klarlund 2008-05-29 02:04 Nils Klarlund * bench/Build.py, bench/Project.py, bench/ProjectDefs.py: Add include server args to benchmarking framework. This makes the linux kernel build with pump-mode when the benchmark script is used. Also, include the '-t' option to the include server; that prints out the elapsed and CPU times at the end of the build. REVIEW: Craig Silverstein TESTS: (on quad-cpu workstation) DISTCC_HOSTS="--randomize `/home/klarlund/svn-distcc/distcc/lsdistcc -P1 -k100 -d`" PATH=`pwd`:$PATH bench/benchmark.py --cc='/usr/crosstool/v10/gcc-4.2.1-glibc-2.3.2/x86_64-unknown-linux-gnu/bin/x86_64-unknown-linux-gnu-gcc' --cxx='void' -n 5 -c 'pump,h40,j120' -c 'dist,h40,j32' linux-2.6.25 project compiler time s.d. linux-2.6.25 pump_h39_j120 69.6525s 3.0969s linux-2.6.25 dist_h39_j32 103.8416s 10.8041s 2008-05-29 01:57 Nils Klarlund * pump.in: Add critique of pump-mode when include server shuts down. Print a message like: __________Warning: 1 pump-mode compilation(s) failed on server, but succeeded locally. when compile discrepancies have occurred. Currently, a user may think that all is well because we do not terminate a build when discrepancies occur and the warning messages occurring in the middle of a build may easily be overlooked. REVIEW: Craig Silverstein TESTS: make linux-kernel without stat reset triggers to observe message 2008-05-29 01:46 Craig Silverstein * src/dotd.c, src/dotd.h, src/emaillog.c, src/emaillog.h: Fix some of the written-on dates for some google patches. Pointed out by fergus. 2008-05-28 13:12 Nils Klarlund * pump.in: Fix unproctected invocation of distcc and numeric designation of one with a plural noun. I discovered this bug by deleting /usr/bin/distcc. I did that after I found out that the Linux kernel compilation is suffering from a similar issue (amongst others), because the PATH is apparently rewritten. 2008-05-28 02:32 Nils Klarlund * include_server/cache_basics.py, include_server/parse_command.py: Remove spurious warning messages about absolute filepaths. During compilation of the Linux kernel messages like: absolute filepath blabla.h was IGNORED (correctness of build may be affected) are issued. They are wrong. The problem is that -include or -imacro or even source file names with absolute filepaths trigger a complaint from the caching mechanism usually used for relative file names. We correct this problem. We also substitute fp_map for includepath_map, which is the now preferred term. REVIEWER: Craig Silverstein TESTS: make pump-maintainer-check make include-server-maintainer-check 2008-05-28 02:19 Nils Klarlund * src/compile.c: Fix race condition that may prevent the warning message that pump-mode is no longer used from being displayed. This is the current crop of error messages. A couple of them *really* should be suppressed, but not the last one, which the CL is about. distcc[4333] ERROR: compile arch/x86/kernel/syscall_64.c on distcc4.nyc.corp.google.com,lzo,cpp failed distcc[4333] (dcc_build_somewhere) Warning: remote compilation of 'arch/x86/kernel/syscall_64.c' failed, retrying locally distcc[4333] Warning: failed to distribute arch/x86/kernel/syscall_64.c to distcc4.nyc.corp.google.com,lzo,cpp, running locally instead distcc[4333] (dcc_please_send_email_after_investigation) Warning: remote compilation of 'arch/x86/kernel/syscall_64.c' failed, retried locally and got a different result. distcc[4333] (dcc_please_send_email_after_investigation) Warning: file 'include/asm/asm-offsets.h', a dependency of arch/x86/kernel/syscall_64.c, changed during the build distcc[4333] (dcc_note_discrepancy) Warning: now using plain distcc, possibly due to inconsistent file system changes during build The last message may not occur: the code contains a race condition, because more processes may increment the unary file, after it has reached the size of max_discrepancies_before_demotion, preventing the equality from ever becoming true. 2008-05-27 20:33 Nils Klarlund * include_server/include_analyzer.py, include_server/include_analyzer_memoizing_node.py, include_server/include_analyzer_memoizing_node_test.py, include_server/include_analyzer_test.py, include_server/parse_command.py, include_server/parse_command_test.py: Make the Linux 2.6 kernel build with distcc-pump mode. Add a new piece of command line parse information: send_systemdirs. This boolean is normally false. It is true if there is a -isystem option with a default system directory (one known to the compiler). With send_systemdirs true, the compiler headers of system headers are sent to the servers and mounted under the server root. The isystem option is as usual rewritten to be relative to the root. Without this flag setting, distcc quickly decides that pump mode is not viable because remote compilations fail. Also, fixed the comment: # TODO(klarlund): Make mechanism for handling -U, -undef options, along with # default symbols. (-D options are handled.) --------------- TESTS: make pump-maintainer-check make include-server-maintainer-check make 'linux kernel' in a directory made by the benchmark script (as shown below) DISTCC_EMAILLOG_WHOM_TO_BLAME=Nils Klarlund DISTCC_ENABLE_DISCREPANCY_EMAIL=1 INCLUDE_SERVER_ARGS='-d1 -t --email --unsafe_absolute_includes --send_systemdirs --stat_reset_triggers=include/linux/*' DISTCC_HOSTS="--randomize `/home/klarlund/svn-distcc/distcc/lsdistcc -P3 -k100 -d`" PATH=/home/klarlund/svn-distcc/distcc:$PATH ./masquerade pump make -j120 REVIVIEWER: Craig Silverstein TRIVIA: the about 1000 files in the kernel build involve on average 400 headers. The build time on a quad-cpu machine drops from about 1m40 s to 1m20s. With pump-mode, the machine is underutilized judging from the total sys + user time, which is around only 2m20s. NOTE: this is a successor to 'g6n8', which simply introduced a command line option to force sending of system files. A bug in gvn did not allow me to resuse that change list. 2008-05-23 22:24 Craig Silverstein * bench/Build.py, bench/Project.py, bench/Summary.py, bench/actions.py, bench/benchmark.py, bench/buildutil.py, bench/compiler.py, bench/statistics.py, include_server/basics.py, include_server/basics_test.py, include_server/c_extensions_test.py, include_server/cache_basics.py, include_server/compiler_defaults.py, include_server/compress_files.py, include_server/include_analyzer.py, include_server/include_analyzer_memoizing_node.py, include_server/include_analyzer_memoizing_node_test.py, include_server/include_analyzer_test.py, include_server/include_server.py, include_server/include_server_test.py, include_server/macro_eval.py, include_server/macro_eval_test.py, include_server/mirror_path.py, include_server/mirror_path_test.py, include_server/parse_command.py, include_server/parse_command_test.py, include_server/parse_file.py, include_server/parse_file_test.py, include_server/run.py, include_server/setup.py, include_server/statistics.py, src/access.c, src/access.h, src/arg.c, src/argutil.c, src/backoff.c, src/bulk.c, src/bulk.h, src/cleanup.c, src/climasq.c, src/clinet.c, src/clinet.h, src/clirpc.c, src/compile.c, src/compile.h, src/compress.c, src/cpp.c, src/daemon.c, src/daemon.h, src/distcc.c, src/distcc.h, src/dopt.c, src/dopt.h, src/dotd.c, src/dotd.h, src/dparent.c, src/dsignal.c, src/emaillog.c, src/emaillog.h, src/exec.c, src/exec.h, src/exitcode.h, src/filename.c, src/fix_debug_info.c, src/fix_debug_info.h, src/gcc-id.c, src/h_argvtostr.c, src/h_compile.c, src/h_dotd.c, src/h_exten.c, src/h_hosts.c, src/h_issource.c, src/h_parsemask.c, src/h_sa2str.c, src/h_scanargs.c, src/h_strip.c, src/help.c, src/history.c, src/hostfile.c, src/hosts.c, src/hosts.h, src/implicit.c, src/implicit.h, src/include_server_if.c, src/include_server_if.h, src/io.c, src/loadfile.c, src/lock.c, src/lock.h, src/lsdistcc.c, src/mon-gnome.c, src/mon-notify.c, src/mon-text.c, src/mon.c, src/mon.h, src/ncpus.c, src/netutil.c, src/netutil.h, src/prefork.c, src/pump.c, src/remote.c, src/renderer.c, src/renderer.h, src/rpc.c, src/rpc.h, src/rslave.c, src/rslave.h, src/safeguard.c, src/sendfile.c, src/serve.c, src/setuid.c, src/snprintf.h, src/srvnet.c, src/srvnet.h, src/srvrpc.c, src/ssh.c, src/state.c, src/state.h, src/stats.c, src/stats.h, src/stringmap.c, src/stringmap.h, src/strip.c, src/tempfile.c, src/timefile.c, src/timefile.h, src/timeval.c, src/timeval.h, src/trace.c, src/trace.h, src/traceenv.c, src/types.h, src/util.c, src/util.h, src/where.c, src/where.h, src/zeroconf-reg.c, src/zeroconf.c, src/zeroconf.h, test/comfychair.py, test/testdistcc.py: Normalize the copyright text, to the latest version of the GPLv2 text (typically the only change is in the FSF street address). Add Google copyright line in some places it was missing. Add GPLv2 notice to avahi patches. OKed by fergus 2008-05-23 20:43 Craig Silverstein * packaging/RedHat/rpm.spec: Update install-message wording. Reviewed by fergus 2008-05-23 07:33 Craig Silverstein * configure.ac: Update copyright and GPL notice. 2008-05-23 07:29 Craig Silverstein * pump.in, test/onetest.py: Fix author lines. Also, add gpl text. OKed by fergus and klarlund 2008-05-23 06:30 Fergus Henderson * packaging/RedHat/conf/clients.allow, packaging/RedHat/rpm.spec: Do not include 127.0.0.1 in clients.allow by default, because it is a security risk: it may allow other users on the machine to execute arbitrary code as the distcc user. Instead, leave clients.allow empty by default, and require the system admistrator to edit clients.allow manually, if they want to use distcc in TCP mode. We still install distccd as a service, but distccd will exit immediately unless you've already added some hosts to clients.allow. Reviewers: Craig Silverstein 2008-05-23 03:19 Fergus Henderson * include_server/include_analyzer_memoizing_node.py: Fix a typo in a comment. 2008-05-23 03:18 Fergus Henderson * src/dopt.c: Fix a bug: --wizard is supposed to imply --log-level debug, but this wasn't working, because the code that handles --wizard wasn't setting opt_log_level_num. Reviewers: Craig Silverstein 2008-05-23 03:12 Nils Klarlund * include_server/include_analyzer.py, include_server/mirror_path.py: Fix unsoundess of directory replication. Testing of distcc-pump mode on the Linux kernel showed that the computed include closure was sometimes wrong: header files were missing. Further testing showed that sometimes apparently not even the compilation unit made it across to the server or rather, the c-file in its real location would come across, but the path designating it would not. Take as an example: compilation unit is designated by the path ../bar/baz.c and the current directory is /foo but no files in /foo are in actuality referenced during include processing. Then the compilation server will get /PREFIX/bar/baz.h -- the image of the real file -- but /PREFIX/foo, the image of the current directory, will not even be created! So, this CL corrects an oversight in the way that the include processor explores files: although it does take into account the chasing of symbolic links, no provisions are in place to properly model '..' for climbing up directories. Specifically, to climb up a directory, it must exist! Usually, the directory in fact would exist on the server, because it would be replicated thanks to the header files it contains. But there is no guarentee. We solve this problem by forcing the creation of dummy .c files the first time a path is explored. Because paths are being investigated backwards (from the end), forcing results in extra files only at the "deep" levels. Since files are usually clustered together in directories, the addition of a dummy file per deep directory should be inconsequential for performance. TBD: integration level tests that this really work. I will either include that later or in a separate CL. Tested: make pump-maintainer-check build the Linux 2.6 kernel in true pump-mode (with extra patch, to be described separately that sends compiler system files to the server) [all files but a few towards the end suffer from absolute includes are preprocessed and compiled on the compile servers!] The command I used is: DISTCC_EMAILLOG_WHOM_TO_BLAME=Nils Klarlund DISTCC_ENABLE_DISCREPANCY_EMAIL=1 INCLUDE_SERVER_ARGS='-d1 -t --email --stat_reset_triggers=include/linux/compile.h' DISTCC_HOSTS="--randomize `/home/klarlund/svn-distcc/distcc/lsdistcc -P3 -k100 -d`" PATH=/home/klarlund/svn-distcc/distcc:$PATH ./masquerade pump make -j120 I had to delete /usr/bin/distcc for this work, because of the PATH acrobatics that the kernel makefiles apparently exercise. Otherwise, /usr/bin/distcc would sometimes get called. Reviewed: Fergus Henderson , Craig Silverstein 2008-05-23 03:03 Fergus Henderson * INSTALL: Some trivial style changes. 2008-05-23 02:35 Nils Klarlund * bench/Build.py, bench/benchmark.py, bench/compiler.py: Set-up masquerading for benchmarks. Follow the advice of the distcc man page for executing the benchmarks to not rely on CC and CXX variables by also routing naked calls of 'cc', 'gcc', etc to a 'farm' of tiny shell scripts. Also, provide a little wrapper script that does this for people who have to debug a benchmark build. This change is convenient for running the benchmark on the linux kernel, because building the kernel uses naked 'gcc' calls. Testing: Building the linux kernel. 2008-05-23 01:41 Fergus Henderson * Makefile.in: Fix a bug which broke the Debian and RPM distributions: the generated pump script was referring to DESTDIR. Files should be installed into DESTDIR, but they should never refer to DESTDIR, because it is only a temporary location used for constructing the RPM file; when the package is actually installed, the files will get put in e.g. /usr rather than DESTDIR/usr. Tested with "make install-deb && make daemon-installcheck". Reviewers: Nils Klarlund 2008-05-23 01:11 Manos Renieris * NEWS, README.pump, doc/protocol-3-impl.txt, doc/protocol-3.txt, man/distcc.1, man/pump.1: Minor documentation changes. 2008-05-22 19:06 Fergus Henderson * src/dotd.h, src/include_server_if.h: Remove "svn:executable" property (the "+x" permission bit) from header files. Reviewers: Manos Renieris 2008-05-22 05:36 Fergus Henderson * survey.txt: Direct survey response to distcc-survey@google.com rather than to Martin Pool. Reviewers: Craig Silverstein 2008-05-22 05:35 Fergus Henderson * INSTALL: A major overhaul of the INSTALL file. Describe pump mode better, and explain the effects of installing via RPM or Debian package. Also a bunch of other minor edits. Reviewers: Craig Silverstein 2008-05-22 04:51 Fergus Henderson * configure.ac: Bump version number to 3.0-prerelease3. Reviewers: Craig Silverstein 2008-05-22 04:49 Fergus Henderson * include_server/include_analyzer_test.py: Fix a test case that was failing on MacOS X. The test was implicitly assuming that /tmp == realpath(/tmp). But in MacOS X, /tmp is a symbolic link to /private/tmp. Reviewers: Craig Silverstein, Nils Klarlund 2008-05-22 04:40 Fergus Henderson * doc/web/index.html: Update the "60 second instructions" to use pump mode. I considered mentioning both regular mode and pump mode in the 60 second instructions, but 60 seconds doesn't really give you much time to describe the difference between the two, so I thought it was simpler to just go with pump mode. Reviewers: Craig Silverstein 2008-05-21 22:42 Fergus Henderson * test/testdistcc.py: Disable the Gdb_Case test in non-pump mode when using gcc versions that don't preserve the source directory in the preprocessed output. Reviewers: Nils Karlund, Craig Silverstein 2008-05-21 20:28 Nils Klarlund * src/clirpc.c: Make an obscure and common error message more informative. Currently, our users get the following error message when their workstation is not in the allowed domains as specified in the server configuration: distcc[20742] (dcc_readx) ERROR: unexpected eof on fd5 distcc[20742] (dcc_r_token_int) ERROR: read failed while waiting for token "DONE" With this change, a message explains some likely causes of the problem. 2008-05-21 16:37 Fergus Henderson * test/testdistcc.py: Disable some tests that were failing if you don't have a C++ compiler installed. Also, tidy up the output from the DotD_Case test: instead of DotD_Case TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK TempCompile_Case OK OK you now get just DotD_Case OK Also, fix a problem where ObjectiveCPlusPlus_Case test was on some systems being run even though the system didn't have Objective C++ installed. Reviewers: Nils Klarlund 2008-05-21 16:26 Nils Klarlund * include_server/basics.py, include_server/cache_basics.py, include_server/include_analyzer_test.py, include_server/include_server.py: Add '--unsafe_absolute_includes' option so that more can be compiled in pump-mode. An occurrence of say #include "/usr/include/acl.h" will normally force the include processor to abort (even when this include is platform-specific and #ifdef'ed away), because there are no guarantees that the file /usr/include/acl.h exists on the host. With this option, these includes will be ignored. A message like: WARNING include server: absolute filepath '/usr/include/acl.h' was IGNORED (correctness of build may be affected) will be printed. The normal message raised when this option is off, the default, has been modified. It now mentions the option. An include server manual page is to follow, which explains the consequences in detail of using this option. Testing: this makes the samba-2.2.7 benchmark build without hiccups using distcc pump. Without the change many compilations fail because the include server bails out and because another unrelated bug in the include server makes it later dish up with include closures that are too small. Revievers: Craig Silverstein , Fergus Henderson 2008-05-21 09:04 Fergus Henderson * Makefile.in, pump.in, src/include_server_if.c: Some usability improvements, in particular better diagnostics for common setup errors. In pump script: - If DISTCC_HOSTS is set, print out a message saying how many hosts there are (similar to the one that we already print if you instead set DISTCC_POTENTIAL_HOSTS) and how many of them have pump enabled. - Report an error if you run pump using a host list containing no hosts with ',cpp'. (Should this be a warning instead?) - Report an error if you run pump using an empty host list. (Should this be a warning instead?) In distcc client: - Improve the warning messages that you get if you run distcc using hosts with ",cpp" without running pump. 2008-05-21 06:13 Craig Silverstein * bench/Project.py, bench/ProjectDefs.py: Document the options that the Package constructor takes. Get rid of source_name, which isn't used anywhere. Also, add a few more benchmark projects. These are big(ish) and written in C++, to test distcc on C++ code. Reviewed by Nils Klarlund 2008-05-20 21:49 Craig Silverstein * bench/Build.py, bench/benchmark.py: In the benchmark code, make sure a directory exists before cd-ing into it. This is to handle projects like ACE, which require you to build from an entirely new directory. Also fix up an obsolete help-text sentence. Reviewed by Fergus Henderson 2008-05-20 20:23 Fergus Henderson * include_server/basics.py, include_server/compiler_defaults.py, include_server/parse_command.py, include_server/parse_command_test.py, test/testdistcc.py: Re-enable Objective C and Objective C++ support. This required the following changes: - Compute the default search paths for each language lazily, when the language is first encountered, rather than computing it for 'c' and 'c++'. - Make the tests of Objective C and Objective C++ conditional on the relevant compiler being installed. Tested by "make check" on two systems: - One with Objective C installed, but not Objective C++. - One with neither installed. I didn't test on a system with Objective C++ installed, because I didn't have one easily available. Reviewers: Craig Silverstein, Nils Klarlund. 2008-05-20 20:19 Fergus Henderson * test/testdistcc.py: Disable part of the DashWpMD_Case test, because it doesn't pass :-( Tested with "make check"; fails before this CL, passes afterwards. Reviewers: Nils Klarlund, Craig Silverstein. 2008-05-20 18:16 Craig Silverstein * src/access.c, src/access.h, src/arg.c, src/backoff.c, src/bulk.c, src/bulk.h, src/cleanup.c, src/climasq.c, src/clinet.c, src/clinet.h, src/clirpc.c, src/compile.c, src/compile.h, src/compress.c, src/cpp.c, src/daemon.c, src/daemon.h, src/distcc.c, src/distcc.h, src/dopt.c, src/dopt.h, src/dotd.c, src/dotd.h, src/dparent.c, src/dsignal.c, src/emaillog.c, src/emaillog.h, src/exec.c, src/exec.h, src/exitcode.h, src/fix_debug_info.c, src/fix_debug_info.h, src/gcc-id.c, src/h_hosts.c, src/h_parsemask.c, src/help.c, src/history.c, src/hostfile.c, src/hosts.c, src/hosts.h, src/implicit.c, src/implicit.h, src/include_server_if.c, src/include_server_if.h, src/io.c, src/loadfile.c, src/lock.c, src/lock.h, src/lsdistcc.c, src/mon-gnome.c, src/mon-notify.c, src/mon-text.c, src/mon.c, src/mon.h, src/ncpus.c, src/netutil.c, src/netutil.h, src/prefork.c, src/pump.c, src/remote.c, src/renderer.c, src/renderer.h, src/rpc.c, src/rpc.h, src/rslave.c, src/rslave.h, src/safeguard.c, src/sendfile.c, src/serve.c, src/setuid.c, src/snprintf.c, src/snprintf.h, src/srvnet.c, src/srvnet.h, src/srvrpc.c, src/ssh.c, src/state.c, src/state.h, src/stats.c, src/stats.h, src/stringmap.c, src/stringmap.h, src/strip.c, src/tempfile.c, src/timefile.c, src/timefile.h, src/timeval.c, src/timeval.h, src/trace.c, src/trace.h, src/traceenv.c, src/types.h, src/util.c, src/util.h, src/where.c, src/where.h, src/zeroconf-reg.c, src/zeroconf.c, src/zeroconf.h: Change C++-style // comments to /**/. Also, fix the emacs var-setting line: it was missing a semicolon before, which means the entire line was being ignored. No contentful change. Reviewed by Fergus Henderson 2008-05-20 06:13 Craig Silverstein * src/access.c, src/access.h, src/arg.c, src/argutil.c, src/backoff.c, src/bulk.c, src/bulk.h, src/climasq.c, src/clinet.c, src/clinet.h, src/clirpc.c, src/compile.c, src/compile.h, src/compress.c, src/cpp.c, src/daemon.c, src/daemon.h, src/distcc.c, src/distcc.h, src/dopt.c, src/dopt.h, src/dotd.c, src/dotd.h, src/dparent.c, src/dsignal.c, src/emaillog.c, src/emaillog.h, src/exec.c, src/exec.h, src/exitcode.h, src/filename.c, src/fix_debug_info.c, src/fix_debug_info.h, src/gcc-id.c, src/h_argvtostr.c, src/h_compile.c, src/h_dotd.c, src/h_exten.c, src/h_hosts.c, src/h_issource.c, src/h_parsemask.c, src/h_sa2str.c, src/h_scanargs.c, src/h_strip.c, src/help.c, src/history.c, src/hostfile.c, src/hosts.c, src/hosts.h, src/implicit.c, src/implicit.h, src/include_server_if.c, src/include_server_if.h, src/io.c, src/loadfile.c, src/lock.c, src/lock.h, src/lsdistcc.c, src/mon-gnome.c, src/mon-notify.c, src/mon-text.c, src/mon.c, src/mon.h, src/ncpus.c, src/netutil.c, src/netutil.h, src/prefork.c, src/pump.c, src/remote.c, src/renderer.c, src/renderer.h, src/rpc.c, src/rpc.h, src/rslave.c, src/rslave.h, src/safeguard.c, src/sendfile.c, src/serve.c, src/setuid.c, src/snprintf.c, src/snprintf.h, src/srvnet.c, src/srvnet.h, src/srvrpc.c, src/ssh.c, src/state.c, src/state.h, src/stats.c, src/stats.h, src/stringmap.c, src/stringmap.h, src/strip.c, src/tempfile.c, src/timefile.c, src/timefile.h, src/timeval.c, src/timeval.h, src/trace.c, src/trace.h, src/traceenv.c, src/types.h, src/util.c, src/util.h, src/where.c, src/where.h, src/zeroconf-reg.c, src/zeroconf.c, src/zeroconf.h: Turned all tabs into 4 spaces. Got rid of whitespace at the end of lines. Fixed up resulting mis-indented code I noticed (mostly in files that used 8 space indents, or used 4-space and 8-space indents in the same file (!)). Added the emacs tab-var setting for all files, not just some of them. I also added in copyright notices for files I noticed that didn't have them. We'll want to do another pass-through to fix these up properly, though. I used the following perl snippet to check for mis-indented code after converting tabs to whitespace: $ for i in *.{c,h}; do echo $i; perl -nle 'if ($indent > 0) {$sp=" " x $indent; /^$sp[^ ]/ && print "$.: $_"; $indent=0;}; if (/^( *).*{/ ) {$indent=length($1);} else {$indent=0;}' $i; done | less It had false positives, but hopefully didn't miss anything. Reviewed by Nils Klarlund 2008-05-20 05:58 Craig Silverstein * bench/benchmark.py: Add --output to benchmark.py, to print the final timing summary to a file in addition to stdout. Also made sure we don't try to access opt_cc and opt_cxx until after all flags are read, so flag order doesn't matter. Finally, fixed indentation so we only print the default actions when --help is specified (as intended). Tested by running make benchmark. Reviewed by Nils Klarlund 2008-05-20 03:32 Nils Klarlund * src/emaillog.c: Fix polarity of condition. Reviewers: Fergus Henderson Tests: manual (both with and without DISTCC_EMAILLOG_WHOM_TO_BLAME set). 2008-05-20 03:31 Nils Klarlund * bench/benchmark.py: Corrent option name. The option is said to be 'distcc', but it's actually implemented as 'dist'. The latter is fine with me: we have 'dist' and 'pump', with 'pump' being a more advanced 'dist'. 2008-05-20 03:31 Nils Klarlund * test/testdistcc.py: Improve assert message. Revievers: Fergus Henderson 2008-05-19 10:00 Fergus Henderson * bench/compiler.py, test/testdistcc.py: Add 'DashWpMD_Case' to the list of test cases that actually get run. Also, an unrelated change to the benchmarking scripts: fix a cut-and-paste error in an error message. Reviewers: Craig Silverstein 2008-05-19 09:58 Fergus Henderson * src/arg.c: Whitespace change: make indentation more consistent. 2008-05-18 06:06 Fergus Henderson * src/arg.c, src/argutil.c, src/compile.c, src/distcc.c, src/dotd.c, src/implicit.c, src/strip.c: Fix bugs in my previous change to handle "-Wp," options: arguments to str_startswith() were in the wrong order, and in one place I had wrongly passed 'argv' instead of 'new_argv'. Move the call to dcc_expand_preprocessor_options() from dcc_get_dotd_info() to gcc_build_somewhere(), so that it is pretty much the first thing done to argv. Not sure if this is really needed, but it seems like a good idea. Fix various memory management problems, including some introduced by moving the call to dcc_expand_preprocessor_options(). One problem was that dcc_find_compiler() was producing a result that was sometimes allocated with malloc() and sometimes not, so the caller couldn't safely deallocate it. I changed dcc_find_compiler to always return a dynamically allocated result. Fix some places where return values were being ignored. Also fix one place where distcc was inconsistenly calling exit() rather than returning a return code. Like my previous change, this one is necessary, but perhaps not sufficient, for building the Linux kernel with distcc-pump. Tested by "make valgrind-check", and by building and installing the debian package and the building Linux 2.6.25 in pump mode using the benchmark.py script. Reviewers 2008-05-18 06:03 Fergus Henderson * packaging/RedHat/init.d/distcc: Fix a bug where "/etc/init.d/distcc stop" was not working when you had installed a new distcc. It wasn't working properly because the call to "start-stop-daemon --stop" used the "--exec /usr/bin/distccd" option, and (perhaps due to a bug in start-stop-daemon?) that option checks /proc//exe against /usr/bin/distccd by comparing inode numbers. Comparing inode numbers doesn't work, because when we install a new distccd, we create a fresh file with a new inode number, so the inode number used by running processes won't match the inode number of /usr/bin/distccd on disk after you've installed a new version. The fix was to remove the "--exec /usr/bin/distccd" option from the call to start-stop-daemon. We're already passing "--name distccd", which is sufficient to indentify the running distccd processes. Reviewers: Craig Silverstein 2008-05-17 16:24 Fergus Henderson * src/compile.c, src/compile.h, src/h_compile.c, test/testdistcc.py: Fix a typo: s/ddc_/dcc_/ Reviewers: Craig Silverstein 2008-05-17 15:18 Nils Klarlund * include_server/basics.py, include_server/include_server.py: Tune gc for 25% speed-up of include processor. Set first parameter of gc.set_threshold to 10000 instead of default 700. See comments in program text. Notes ----- I used a little script to find the include server timings as a function of this parameter. This script executes: "DISTCC_PUMP_INSTALLATION=/tmp/distcc3.0 INCLUDE_SERVER_ARGS='-t --gc_threshold=700' \ /usr/bin/time -p make-dbg -j120 -r -experimental-ld -g0 gws:gws" with various values of gc_threshold. The measurement were done on a four processor system (dual Opterons), loaded with an nxserver process. Files were served through Fuse. gc include server user + sys time setting 700 155.1s 154.0s 164.7s 186.1s 154.3s Mean: 162.8 10000 123.8s 125.4s 120.6s 120.4s 121.0s Mean: 122.2 100000 123.4s 123.3s 122.2s 123.3s 116.5s Mean: 121.7 700 166.5s 156.4s 150.8s 153.4s 155.4s Mean: 156.5 10000 120.7s 142.1s 118.3s 117.7s 119.2s Mean: 123.6 100000 140.3s 117.1s 149.7s 116.7s 141.6s Mean: 123.6 The corresponding elapsed times: 371.0s 363.3s 361.9s 370.8s 369.0s Mean: 367.2 341.8s 346.1s 336.3s 338.3s 340.5s Mean: 340.6 345.9s 338.5s 342.9s 374.4s 340.0s Mean: 348.3 377.4s 379.9s 387.1s 377.4s 373.2s Mean: 379.0 332.1s 337.7s 336.5s 332.2s 314.7s Mean: 330.6 341.1s 334.6s 357.8s 338.5s 352.4s Mean: 344.9 Note that the saving in include server time is around 35s, but the savings in elapsed time is around 44s. These numbers are uncertain. Even so, they strongly indicate that the include server is a signifcant bottleneck. BTW, for comparison with plain distcc: 821.4s 822.0s 842.4s 821.5s 852.0s Mean: 831.9 878.7s 857.2s 860.3s 880.1s 856.0s Mean: 866.5 Thus, pump-mode 2.5X is faster than plain distcc (with the set_threshold = 10000 of this CL). Revievers: Fergus Henderson , Craig Silverstein 2008-05-16 23:12 Craig Silverstein * src/exec.c: There's cygwin-specific code in exec.c, but it seems to assume that when running under cygwin, we'll be using a native windows app to compile. But sometimes we're using a cygwin app (eg /bin/gcc). Trying to use native-windows forking routines with cygwin apps causes a segfault (and takes a while to do it); we need to use unix forking routines there. With this change, when we're asked to spawn a sub-process, we try to guess whether the sup-process app is windows or cygwin, based on its path location (this benefits from using absolute paths): /bin/gcc vs C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\cl.exe or even C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/bin/cl.exe If we decide it's a windows app but are wrong, then the windows-forking code should eventually fail with "file not found"; in that case, we fall through to the normal unix-fork case, to give cygwin a chance to find the binary. I also took the opportunity to clean up some of the code (handles should be initialized to ILLEGAL_HANDLE values, not NULL). I also replaced the crazy permissions the code was asking for before, with normal GENERIC_READ/GENERIC_WRITE. This allows the code to work when the tmpdir is c:\windows, which was failing before. Tested on cygwin using /bin/gcc as the compiler, like so: ./distcc /bin/gcc -c testtmp.c -o testtmp.o where testtmp.c is a simple "hello world" program. I also tested by running 'make check'. With this change, 'make check' passes on cygwin! (Using gcc to do compilations.) Reviewed by Fergus Henderson 2008-05-16 22:00 Fergus Henderson * Makefile.in, src/compile.c: Two bug fixes: - Fix a bug where 'valgrind-check' was invoking 'pump-check', but 'pump-check' was disabling valgrind. - Fix an off-by-one error caught by valgrind. Tested by "make check" and "make valgrind-check". Reviewers: Craig Silverstein 2008-05-16 21:54 Fergus Henderson * src/arg.c, src/distcc.h, src/dotd.c, test/testdistcc.py: Handle '-Wp,-MD,' option. This is needed to build the Linux kernel. Reviewers: Craig Silverstein 2008-05-16 20:46 Fergus Henderson * bench/ProjectDefs.py: In the list of projects to benchmark: - comment out Linux 2.5.51, because it doesn't compile - add Linux 2.6.25. Reviewers: Nils Klarlund, Craig Silverstein 2008-05-16 20:44 Fergus Henderson * bench/actions.py: In the benchmarking script, don't remove the build directories by default, because the log files get stored in the build directories, and it's useful to have the log files around afterwards. Reviewers: Craig Silverstein 2008-05-16 18:08 Craig Silverstein * src/dotd.c: Comment the need to handle gcc's -Wp flag. Reviewed by Fergus Henderson 2008-05-16 01:15 Nils Klarlund * include_server/include_analyzer_test.py: Fix freak name collision on OSs that do not distinguish upper and lowercase in file names. The symbol 'TESTING' is potentially unevaluated according to the overapproximation semantics of the include server. So if this symbol is used in a file name and if 'TESTING' really means 'testing' according to the OS and if in fact 'testing' does exist as file, then there is trouble. Revievewers: Craig Silverstein Testing: make include-server-maintainer-check (on Linux) 2008-05-16 01:10 Nils Klarlund * pump.in: Fix: speed-up the include processor a few times by exporting PYTHONOPTIMIZE. This took a little while: fortunately, the tracing information is dependent on the PYTHONOPTIMIZE setting, so after a diff on the outputs of the gws example before and after, it finally dawned upon me what was wrong. Tested: manually on the gws example with 600 include directories. 2008-05-16 00:59 Nils Klarlund * Makefile.in: Fix removal of 'pump'. Review: Craig Silverstein 2008-05-16 00:52 Nils Klarlund * Makefile.in, pump.in: Fix variable that denotes the source location. (1) It was not documented. I rewrote the documentation for a couple of associated variables. (2) There was no default value. Now, the variable does not need to be set from 'make', so I've removed it from Makefile.in. And, I've made it into a standard shell lowercase variable. Reviewers: Fergus Henderson, Craig Silverstein Tests: (1) make distcheck (2) Running the pump script out of the build directory. 2008-05-15 21:45 Craig Silverstein * find_c_extension.sh, test/testdistcc.py: Modifications to the pump and test framework for cygwin. 1) find_c_extension looks for .dll files in addition to .so files. 2) Likewise, testdistcc.py has to check whether binary names might end in .exe. Usually that doesn't matter, but sometimes (eg when running cp on them), it does. 3) testdistcc.py adds a routine to detect PE binaries. These, like dwarf binaries, do not always give reproducible output on the same input, so take that into account in the gdb tests. 4) In the lsdistcc test, we assumed that when the ping failed, 127.0.0.2 isn't available. But it's also possible ping is just broken (or different) on that machine. So in the failed-ping case, we no longer make any assumption about 127.0.0.2, one way or the other. Tested by running 'make check' on cygwin. Most every test passes! Reviewed by Fergus Henderson 2008-05-15 20:11 Nils Klarlund * Makefile.in: Add 'pump' to 'all' target. Add 'rm pump' to 'clean' target. - 'pump' is a dependency of 'install'. - 'include_server' is a dependency of 'all. So I propose that 'pump' should be a dependency of 'all'. Reviewers: Fergus Henderson Test: make distcheck 2008-05-15 19:39 Craig Silverstein * Makefile.in, configure.ac, pump.in: Instead of a hack to figure out if pump is installed or not -- one that fails on macs with python 2.5 (at least) because of weirdnesses with distutils installation on that platform -- just rewrite pump at install-time to indicate it's installed. We take the opportunity to tell pump where the installed include_server.py is, because it needs to know, and we know that during 'make install'. Tested by running 'make distcheck' on linux (ubuntu) with python 2.4, and mac 10.5 with python 2.5. I also tested by running, on the linux machine, ./configure --prefix=/tmp/distcc.install && make install && make DISTCC_INSTALLATION=/tmp/distcc.install/bin installcheck Furthermore, I manually inspected the installed pump file after that to make sure it looked correct. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-15 02:53 Craig Silverstein * include_server/compiler_defaults.py: Add a comment. From Nils Klarlund : "Assume that: (1) 'gcc' is a link to 'distcc' earlier on PATH than the real gcc. (2) gcc is invoked; in fact that invokes distcc, which will rewrite the PATH in src/climasq.c before invoking 'gcc' again. That will make calls by distcc such as 'gcc -E' for preprocessing work OK, but the include processor will in fact be calling the 'distcc' as 'gcc' again! But because the input argument is an I/O redirection, distcc will then correctly call 'gcc'. In args.c it fails to recognize an input file." 2008-05-15 02:40 Craig Silverstein * src/access.c, src/access.h, src/arg.c, src/backoff.c, src/bulk.c, src/bulk.h, src/cleanup.c, src/climasq.c, src/clinet.c, src/clinet.h, src/clirpc.c, src/compile.h, src/compress.c, src/cpp.c, src/daemon.c, src/daemon.h, src/distcc.c, src/distcc.h, src/dopt.c, src/dopt.h, src/dparent.c, src/dsignal.c, src/exec.h, src/exitcode.h, src/h_hosts.c, src/h_parsemask.c, src/help.c, src/history.c, src/hostfile.c, src/hosts.c, src/hosts.h, src/implicit.c, src/implicit.h, src/io.c, src/loadfile.c, src/lock.c, src/lock.h, src/mon-gnome.c, src/mon-notify.c, src/mon-text.c, src/mon.c, src/mon.h, src/ncpus.c, src/netutil.c, src/netutil.h, src/prefork.c, src/pump.c, src/remote.c, src/renderer.c, src/renderer.h, src/rpc.c, src/rpc.h, src/safeguard.c, src/sendfile.c, src/serve.c, src/setuid.c, src/srvnet.c, src/srvnet.h, src/srvrpc.c, src/ssh.c, src/state.c, src/state.h, src/stats.c, src/stats.h, src/strip.c, src/tempfile.c, src/timefile.c, src/timefile.h, src/traceenv.c, src/types.h, src/util.c, src/util.h, src/where.c, src/where.h: Add a consistent emacs-variable header to all source files. This affects the way emacs users will see these files, when visiting them in emacs. In particular, tabs will show up as 4 spaces, which is (clearly) the setting the original distcc author used when writing the code. We also set an emacs variable to never insert new tabs, but use spaces instead. This will help stop the problem we have now with mixed tabs and spaces. In a future cleanup, we may replace all tabs with 4 spaces, and make other whitespace improvements. The final new variable set, is to set line-wrapping at 78 chars. Personally, I would have made it more like 72, but some existing files already had the 78 limit, so I just do that everywhere, to be consistent. Reviewed by Fergus Henderson 2008-05-15 01:58 Craig Silverstein * test/testdistcc.py: The gdb tests was making two assumptions that the input was ELF, which was failing on OS X (Which uses Mach-O). One is that two identical link commands always produce the same output, which is not true for mach-o. The other is just a test of ELF-specific code, without an "iself" check. Now I check the object-file type and run the appropriate test, based on the type, in each case. Tested by running 'make check' on linux (ubuntu 6) and OS X (10.5). Reviewed by Fergus Henderson 2008-05-15 01:36 Craig Silverstein * include_server/compiler_defaults.py: When running gcc -v, we were clearing the environment too aggressively: in particular, we were clearing $PATH, which is needed to find gcc when it's in an unusual location. Now we clear everything but $PATH. Tested by running 'make include-server-maintainer-check' on solaris x86, which has gcc outside the standard path, and on linux (ubuntu), which does not. Reviewed by Fergus Henderson 2008-05-15 01:15 Craig Silverstein * src/tempfile.c: The tmpdir-creation routine has an (undocumented) invariant that the tmpdir should not end in a slash -- at least, inside distcc, you see code like this: snprintf("%s/%s", tmpdir, filename) On the other hand, windows's routine to create a tempdir guarantees it will end with a slash. I'm not sure it really matters, but get rid of the slash in that case. That way we don't have to worry about how filenames are interpreted (since // does have a special meaning for filenames in windows, though probably not in a way this code could generate before; still, no harm in normalizing to one slash). Tested by running 'make check' on cygwin. Reviewed by Fergus Henderson 2008-05-14 21:01 Craig Silverstein * test/comfychair.py: Replace an os.system calls ('rm -rf') with python (shutil.rmtree). This should improve portability. It seems to help on cygwin, for instance. I also got rid of anotehr os.system call that was redundant: it did a "mkdir -p foo" after the previous line had done a "mkdir -p foo/bar". Tested by running 'make check on linux (ubuntu) and cygwin. Reviewed by Fergus Henderson 2008-05-14 19:48 Craig Silverstein * Makefile.in: 1) Fix up a PATH= assignment that would fail if builddir had spaces in it (because the output of `cd "$builddir" && pwd` was not being quoted). As a bonus, make the PATH= fit on one line, which makes some shells happier. 2) Fixed up some install targets. On some systems, tar without -f reads from stdin, but that's non-standard (it should read from some tape-drive device in /dev in that case). Add -f- to $(TAR) in that case, which should work everywhere. 3) cp -a isn't supported on all systems. I checked what automake does, and it emits cp -pR, so that's what I do too. We don't have any internal symlinks that I need to worry about -P or anything like that. Tested by running 'make installcheck' on a freebsd 6.0 system. Reviewed by Fergus Henderson 2008-05-14 19:22 Craig Silverstein * include_server/include_server_test.py: Show more data when an assert fails, to help in debugging. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-14 18:59 Craig Silverstein * m4/acx_pthread.m4: Update acx_pthread to the latest version we use internally. This is like the one on the cryp.to autoconf repository website, but with the avahi patches added in to deal with some compiler quirks. However, these patches have been rewritten internally within google to make them more robust. In particular, the new code now works with cygwin, which it previously didn't (resulting in the spurious error: "Unable to determine how to use pthreads with shared libraries"). Tested by running configure on cygwin. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-14 14:26 Nils Klarlund * configure.ac, include_server/include_server_test.py: Make distcc 3.0 compatible with Python 2.5. Tests: I made PATH=$PATH:/usr/python/bin (where python2.5 resides on my machine). I ran autogen and reconfigured. Then I did: make include-server-maintainer-check make pump-maintainer-check and I made sure that -Is now are set according to Python2.5. 2008-05-14 08:03 Craig Silverstein * pump.in: Ick. On some systems test is in /bin, and in others /usr/bin. Now figure out where it is before running it, and fall back on the shell test if no binary can be found. Tested by running 'make check' on a FreeBSD machine (/bin/test) and linux (/usr/bin/test). Reviewed by Fergus Henderson 2008-05-14 07:28 Craig Silverstein * src/compile.c: getc returns an int, not a char. We're checking whether a char == EOF, which isn't kosher, and on systems where -funsigned-char is true, dangerous. Change the type of the var to an int. Tested by running on linux (ubuntu) and on linux ppc (debian), the latter of which complained at compile time. Reviewed by Fergus Henderson 2008-05-14 07:15 Fergus Henderson * packaging/RedHat/init.d/distcc: Fix problems where distcc's init script was using the wrong exit status and giving misleading messages as a result. Reviewers: Craig Silverstein 2008-05-14 07:14 Fergus Henderson * packaging/RedHat/conf/commands.allow.sh: Increase the set of commands allowed by default: allow cc, c++, c89, c99, and g++, in addition to gcc. Reviewers: Craig Silverstein 2008-05-14 02:27 Craig Silverstein * pump.in: Fix a test to work on solaris sh. Tested by running 'make check' on linux (ubuntu) and solaris 10 x86. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-14 01:00 Nils Klarlund * include_server/basics.py, include_server/basics_test.py, include_server/include_server.py: Finish refactoring and add tests. Move _CleanOutClientRoot and _CleanOutOthers to the ClientRootKeeper package in basics. Replace _RemoveDirectoryTree with shutil function. Add tests to see that directories are created and deleted. Add a couple of title headers to basics.py. Remove a couple of now irrelevant comments. Tests: make pump-maintainer-check make include-server-maintainer-check Reviewer: Craig Silverstein 2008-05-14 00:42 Craig Silverstein * include_server/setup.py: Include snprintf.c in the source-list for the python extension. This is needed on systems that don't define asprintf/etc on their own. Tested by running 'make check' on a linux ubuntu machine and on a solaris machine. Reviewed by Fergus Henderson 2008-05-14 00:31 Craig Silverstein * Makefile.in, find_c_extension.sh, pump.in: A few more cleanups: 1) No ! outside of a 'test' (sh-compatibility). 2) grep >/dev/null instead of grep -q (solaris portability). 3) Improved the quote hygenie a little. 4) prepend to PYTHONPATH instead of overriding it. Tested by running on a solaris machine, and on a machine where PYTHONPATH is needed to locate the python distribution (which is not in the standard location). Reviewed by Fergus Henderson 2008-05-13 23:53 Craig Silverstein * test/testdistcc.py: On some systems (FreeBSD), it looks like connect() can return EINVAL. This isn't documented, but there's some talk about it on the web, eg http://mail-index.netbsd.org/netbsd-bugs/2003/08/18/0002.html It looks like the cause is that the first connect fails for whatever reason, and then subsequent ones fail with EINVAL. I've detected that in the NoDetachDaemon_Case, both on FreeBSD and OS X machines. The symptom is that sock.connect_ex(('127.0.0.1', self.server_port) continually returns EINVAL, and no amount of time will fix things. I'm not exactly sure why, but I figure one possible problem is the connect is happening before distccd has started listening, and that causes problems. So I put in a bit of a delay to give distccd time to start up. I figure it can't hurt, and may well help. Tested by running 'make check' on a ubuntu machine (not subject to this problem) and a freebsd machine (which sometimes is). It certainly didn't hurt, though I can't tell if it solved the problem for good. Reviewed by Fergus Henderson 2008-05-13 23:36 Craig Silverstein * include_server/setup.py: I found a machine whose python was compiled with _FORTIFY_SOURCE, which -- on linux FC5 at least -- gives warnings (which we turn into errors via -Werror) on distcc code for libc functions where we ignore the return value. Unfortunately, setup.py always uses the same flags that python was compiled with on the local machine, so _FORTIFY_SOURCE is always set when compiling distcc extensions via setup.py, and that compilation fails. Without getting into a philosophical debate about the merits of the warn-unused warnings, we'd rather the code compile, so I turn off _FORTIFY_SOURCE when it exists. Tested by running 'make check' on a goobuntu machine (no _FORTIFY_SOURCE) and an FC5 machine (with _FORTIFY_SOURCE). Reviewed by Fergus Henderson 2008-05-13 20:33 Nils Klarlund * src/compile.c: Fix buglet: insert (void) in call of strcpy to avoid gcc 4.1.1. making trouble. gcc 4.1.1 with glibc 2.2.2. insists that the return value must be used. That appears to be a bug in gcc. Reviewers: Fergus Henderson, Craig Silverstein. 2008-05-13 18:59 Craig Silverstein * test/testdistcc.py: Two changes to robustify the unittests: 1) Don't try to run the gdb tests on machines that don't have gdb installed. Likewise, don't try to run the implicit-cc test on a machine that doesn't have cc installed (it happens! Sometimes there's only gcc.) 2) Raise the file-descriptor limit if we can. Mac OS X likes to keep the limit at 256, but some of these tests need more. Tested by running 'make check' on linux and mac os x 10.5. On linux, I ran on both a machine with gdb installed, and one without. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-13 18:40 Craig Silverstein * src/exec.c: We were logging a char* that could be NULL. With glibc, the printf would just print "(null)", but on solaris libc it would segfault. Explicitly test that case now. Tested by running 'make check' on linux and solaris x86. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-13 17:49 Nils Klarlund * include_server/basics.py, include_server/basics_test.py, include_server/compress_files.py, include_server/include_analyzer.py, include_server/include_analyzer_memoizing_node.py, include_server/include_analyzer_memoizing_node_test.py, include_server/include_analyzer_test.py, include_server/include_server.py, include_server/include_server_test.py, include_server/parse_file_test.py: Clean-up the handling of directories for storing compressed files. The code was lacked encapsulation and proper object-orientation. (I wrote it -- it had started out much simpler.) For example, key parameteres were communicated through file name patterns expressed in file names on disk. These patterns were then inferred from reading file names. Now the patterns are properly abstracted away in a class. There should be no semantic changes. Testing: make include-server-maintainer-check make pump-maintainer-check DISTCC_CLIENT_TMP='/tmp' make pump-maintainer-check The latter test exercices the padding gymnastics. 2008-05-13 07:02 Craig Silverstein * pump.in: Rewrite 'pump' to remove bash-isms. This should now work with standard sh. This involved the following changes: 1) `cmd` instead of $(cmd). 2) [ -n "$VAR" ] instead of [ "$VAR" ] 3) "Here document" (< * test/testdistcc.py: printenv doesn't exist on all systems. 'env' does, and does the same thing as printenv when no arguments are given, so just use env instead of printenv. Tested by running 'make check' on a linux machine (which has both env and printenv). To be reviewed by Fergus Henderson 2008-05-13 05:28 Craig Silverstein * include_server/include_server.py: Be more informative on an assert. Reviewed by Fergus Henderson and Nils Klarlund 2008-05-13 01:49 Craig Silverstein * Makefile.in, configure.ac: In the non-included popt case, POPT_INCLUDES was the empty string, leading to a compile command that had -I"" in it. Who knows what that means? Now the -I is part of POPT_INCLUDES, so when it's absent we don't add anything to CPPFLAGS. Tested on a machine where POPT_INCLUDES is not empty and one where it is. Reviewed by Nils Klarlund 2008-05-12 23:53 Fergus Henderson * bench/benchmark.py: Fix a typo in my previous change: s/parse_opt_compiler/parse_compiler_opt/ 2008-05-12 23:07 Fergus Henderson * include_server/parse_command.py, test/testdistcc.py: Handle gcc's "-MF" option in the include server. This option only affects the name of the ".d" file, not the include closure, so the include server doesn't need to do anything for this option; the actual handling of this option in distcc is done by the distcc client, which already handles it correctly. This change just stops the include server from throwing an exception whenever '-MF' is encountered. Reviewers: Nils Klarlund 2008-05-12 23:02 Fergus Henderson * bench/benchmark.py, bench/compiler.py: Add new options '--cc' and '--cxx' for specifying the paths to use for the C and C++ compilers. Also, update the help message to document the new format for the --compiler option. Reviewers: Craig Silverstein 2008-05-12 20:18 Nils Klarlund * include_server/c_extensions/distcc_pump_c_extensions_module.c: Fix call of 'realpath' to work on FreeBSD. Also fix memory leak. Reviewer: Craig Silverstein, Fergus Henderson. Tests: make pump-maintainer-check make include-server-maintainer-check 2008-05-12 19:11 Fergus Henderson * bench/Build.py, bench/ProjectDefs.py, bench/Summary.py, bench/buildutil.py, bench/compiler.py, bench/statistics.py: Add support for pump mode to the benchmarking scripts. Also add support for setting the number of hosts to use. Fix division by zero error that occurred when running benchmark script with the "-a" option. Fix broken URL for GNU hello package. Reviewers: Craig Silverstein, Nils Klarlund 2008-05-12 18:32 Nils Klarlund * pump.in: Fix 'ps' invocation to be more FreeBSD friendly. Reviewers: Fergus Henderson, Craig Silverstein Tests: make pump-maintainer-check 2008-05-12 16:19 Nils Klarlund * include_server/include_analyzer_test.py: Fix include server test so that it passes on system w/o /dev/shm. Reviewers: Craig Silverstein, Fergus Henderson Tests: make include-server-maintainer-check 2008-05-12 16:15 Nils Klarlund * pump.in: Get rid of 'readlink -f', which is a Gnuism. The purpose of the readlink -f was to give the absolute path of the installation; that happens to reveal the installation date given the way we set up distcc-pump at Google. But this does not work under FreeBSD. The installation information can be communicated in different ways (for example by explicit actions of the build system). Reviewers: Fergus Henderson, Craig Silverstein 2008-05-11 19:06 Craig Silverstein * test/testdistcc.py: Annoyingly, different versions of gcc are inconsistent in how they treat a non-existent #include file when invoked with "-MMD": some versions treat it as an error (rc 1), some as a warning (rc 0). When distcc is responsible for preprocessing (_server_options includes 'cpp'), we need to figure out which our gcc does, in order to verify distcc is doing the same thing. Before this change, we just hard-coded in one sort of gcc behavior (that it always warns). This change actually tries gcc out to see which it does, to make sure distcc does the same. Tested by running 'make pump-maintainer-check' on both Linux gcc 4.0.3 (which warns) and FreeBSD gcc 3.4.4 (which errors). Reviewed by Fergus Henderson 2008-05-10 06:54 Craig Silverstein * src/sendfile.c: No matter what the reason, if we can't use sendfile() but it's still safe to fall back on readwrite(), do that. Before we only did this for certain errors, but we might as well do it for any error we don't expect to be able to recover from. Tested by running on mac os x 10.4, which has a problem with sendfile failing sometimes. The relevant test succeeds after this patch. Reviewed by Fergus Henderson 2008-05-10 00:58 Nils Klarlund * Makefile.in: Double-quote unprotected directory reference. Reviewers: csilvers Tests: make distcheck 2008-05-10 00:56 Nils Klarlund * Makefile.in: Cosmetic clean-up of Makefile.in. -- Put a @ in front of a comment shell command (it shouldn't be printed). It is the only comment in the action part of a build rule in the whole Makefile. In Emacs, this comment is flagged as a syntax issue. -- Group all .PHONYs at beginning of section. Tests: make distcheck Reviewers: fergus, csilvers 2008-05-09 23:19 Nils Klarlund * configure.ac, pump.in: Make the identification of Python 'binaries' more robust. Use the distutil function that generates the library name for locating the Python stuff in an installation. Reviewers: Fergus Henderson, Craig Silverstein Test: make distcheck 2008-05-09 23:17 Nils Klarlund * test/testdistcc.py: Speed-up integration/systems tests. 2008-05-09 21:02 Fergus Henderson * Makefile.in: Add "daemon-installcheck" target. This tests that the distcc daemon is running, and that it and distcc and the pump script have been installed correctly, by compiling a simple hello world program with distcc and distcc-pump. 2008-05-09 20:36 Craig Silverstein * src/lsdistcc.c: A whitespace-only change. Got rid of spaces at the end of lines, and also of tabs. Went through to normalize indents and so forth (some functions were using 4-space indents, and others were using 8-space indents, which were probably actually originally written as tabs on a system with 4-space tabs). diff -w shows no diffs; this is really whitespace-only. Tested by making sure the file still compiles. 2008-05-09 20:33 Craig Silverstein * src/lsdistcc.c: Modify lsdistcc to reduce the number of concurrent fd's it tries to open, when the system doesn't support a lot of concurrent fd's (which we see by default in freebsd). It uses getrlimit and setrlimit to get as many fd's as it can, and then stick to that number. I modified the main search loop to work in stages, where each stage uses at most maxfd's fd's. In the common -- almost universal -- case there will only need to be one stage, and the code will behave the same as before. In some limited environments, you might see multiple stages. You can reproduce this artificially via code like this: $ ulimit -SH -n 32 # in sh-like shells $ ./lsdistcc Tested by running manually on a configuration that gives 141 hosts. Tested both with many fd's available, and arbitrarily limited to 32 (via the ulimit command above). Reviewed by Nils Klarlund 2008-05-09 19:45 Fergus Henderson * packaging/RedHat/init.d/distcc: Fix a bug in my changes to add 'commands.allow.sh' that broke the Debian distribution. There was a spurious assignment to CMDLIST. CMDLIST used for the output of /etc/distcc/commands.allow.sh; it is supposed to be set to /var/state/distcc/commands.allow. But due to the spurious assignment, CMDLIST was being set to /etc/distcc/commands.allow.sh, causing the script to overwrite itself. Reviewers: Craig Silverstein 2008-05-09 19:24 Nils Klarlund * packaging/RedHat/rpm.spec: Fix so that include server record can be found. 2008-05-09 19:23 Fergus Henderson * src/stringmap.c: Fix what appears to be a bug in the handling of DISTCC_CMDLIST. The documentation is not very clear, but distccd was documented as matching against the last DISTCC_CMDLIST_NUMWORDS words of the command, where I think by words they meant directory components. For example, if the file refered to by DISTCC_CMDLIST contains the line "/usr/bin/i686-blah-blah/gcc", and DISTCC_CMDLIST_NUMWORDS=2, only commands which end in "/i686-blah-blah/gcc" would be matched. The bug is that a command "i686-blah-blah/gcc" should be considered to match. Likewise, if DISTCC_CMDLIST contains the line "/usr/bin/gcc", and DISTCC_CMDLIST_NUMWORDS is 1 (or not set), then plain "gcc" should be allowed to match. Reviewers: Dan Kegel, Craig Silverstein 2008-05-09 18:15 Nils Klarlund * Makefile.in, configure.ac, popt/system.h, src/access.c, src/arg.c, src/argutil.c, src/backoff.c, src/bulk.c, src/cleanup.c, src/climasq.c, src/clinet.c, src/clirpc.c, src/compile.c, src/compress.c, src/cpp.c, src/daemon.c, src/distcc.c, src/dopt.c, src/dparent.c, src/dsignal.c, src/exec.c, src/filename.c, src/fix_debug_info.c, src/gcc-id.c, src/h_argvtostr.c, src/h_compile.c, src/h_dotd.c, src/h_exten.c, src/h_hosts.c, src/h_issource.c, src/h_parsemask.c, src/h_sa2str.c, src/h_scanargs.c, src/h_strip.c, src/help.c, src/history.c, src/hostfile.c, src/hosts.c, src/implicit.c, src/io.c, src/loadfile.c, src/lock.c, src/mon-gnome.c, src/mon-notify.c, src/mon-text.c, src/mon.c, src/ncpus.c, src/netutil.c, src/prefork.c, src/pump.c, src/remote.c, src/renderer.c, src/rpc.c, src/safeguard.c, src/sendfile.c, src/serve.c, src/setuid.c, src/snprintf.c, src/srvnet.c, src/srvrpc.c, src/ssh.c, src/state.c, src/stats.c, src/strip.c, src/tempfile.c, src/timefile.c, src/trace.c, src/traceenv.c, src/util.c, src/where.c, src/zeroconf-reg.c, src/zeroconf.c: Make handling of config.h sound. (1) Correct order of -Is in Makefile. (2) remove unnessary PATH modification in configure.ac (this is fergus's suggestion -- hopefully this will do, this replaces a circumvention mechanism I had originally concocted. (3) Fix place of the include of popt in CPPFLAGS. (4) Convert quoted includes of config.h to angle bracket includes so that the build version, not the source version, of this file is picked up. The order of -Is in the build system is wrong: it contradicts the VPATH mechanism. This means that builds in a build directory different from that of the source (distribution) directory will find wrong files even after the hapless developer has issued only a 'configure' command in the source directory (but not actually 'made' any thing there). For in that case, the src/config.h will be generated in the source directory and this will be the file picked in the build directory even if that directory has it's own src/config.h. This can lead to wrong builds and it can be hard to diagnose the problem. Currently, this what CPPFLAGS end up being (as found in the generated Makefile): CPPFLAGS = -DHAVE_CONFIG_H -D_GNU_SOURCE \ -I../distcc/popt -I../distcc/src \ ${DIR_DEFS} \ -Isrc -Ilzo \ -I"$(srcdir)/src" -I"$(srcdir)/lzo" \ Here my source dir was ../distcc. The presence of '-I../distcc/popt' in front of -Isrc is the exact opposite of the semantics of VPATH mechanism, which looks for files in the build directory, then in the source directory. Also, note the remarks in: http://www.gnu.org/software/autoconf/manual/autoconf.html#Configuration-Headers (they do not quite correctly discuss the search path, btw). TESTING: I verified that with a corrupted config.h file in the source directory, building now succeeds. Also: make distcheck (it fails the same place as before: this is corrected in another change of mine --- I'll verify that with that change in place, this change makes 'make distcheck' succeed.) REVIEWERS: Fergus Henderson, Craig Silverstein 2008-05-09 18:00 Nils Klarlund * Makefile.in, find_c_extension.sh, include_server/setup.py, pump.in: Rewrite setup.py and associated logic to fix multiple build problems. The recent distcheck revealed that paths were set incorrectly for the setup.py script. Also, as I dug deeper, it turned out that built files were placed in the src directory (thanks to os.path.join I found in the distutil's source code, that trips up the location if relative paths contains too many '..'s.). [The distccheck revealed this!] I didn't like either that setup was run in the source directory and not from the build directory (that's asking for trouble). I did't like either that the search path, the list of includes, in setup.py was handcoded and not simply that of CPPFLAGS. Finally, I was confused by _builddir being another build directory under $(buildir). I renamed the former _include_server to better explain its role. So, I rewrote most of setup.py (correcting some of the documentation strings along the way). Also, I partly removed the 'jumping through the hoops' gymnastics from the Makefile. TESTING: 'make distcheck' REVIEWERS: csilvers, fergus 2008-05-08 23:18 Fergus Henderson * doc/web/compared.html, doc/web/compilers.html, doc/web/faq.html, doc/web/security.html: Update web pages to correct statements that are no longer accurate for distcc 3.0. Reviewers: Craig Silverstein 2008-05-08 19:41 Fergus Henderson * doc/example/README, doc/example/default, doc/example/hosts.allow, doc/example/logrotate, doc/example/services, doc/example/xinetd, packaging/RedHat/logrotate.d/distcc, packaging/RedHat/rpm.spec: Revise the doc/example directory: - Add README file to the doc/example directory. - Add files in doc/example for every system configuration file installed or modified by the RPM installation script (rpm.spec). - Update some comments in rpm.spec. - Some whitespace changes to doc/example/logrotate and packaging/RedHat/logrotate.d/distcc to make those two files match. - Copy warning from packaging/RedHat/xinetd.d/distcc to doc/examples/xinetd. Reviewers: Craig Silverstein 2008-05-08 16:33 Nils Klarlund * include_server/basics.py: Make this file mostly conformant with gpylint. There should be no semantic consequences. TESTS: make distcheck REVIEWER: Fergus Henderson 2008-05-07 23:50 Craig Silverstein * NEWS, doc/web/compared.html, doc/web/compilers.html, doc/web/faq.html, doc/web/index.html, doc/web/results.html, doc/web/scenarios.html, doc/web/security.html: Change NEWS links to point to the actual NEWS file, rather than the svn history-log for the NEWS file. Also changed the NEWS file itself to use ^L instead of a ^ + L, for the top instance. 2008-05-07 23:03 Fergus Henderson * man/pump.1: Add a man page for the "pump" script. The contents are similar to the output of "pump --help", but with a bit more mark-up, and with additional sections "INVOKING LSDISTCC", "BUGS", "AUTHORS", "LICENSE", and "SEE ALSO". Reviewers: Craig Silverstein, Nils Klarlund. 2008-05-07 18:54 Craig Silverstein * test/testdistcc.py: The DaemonBadPort test case was not passing in --allow, which is a new flag required by distcc 3 (all other tests had been modified to add it). We never noticed until now because the distccd command is *expected* to fail with a "bad arguments" error code -- though the bad argument is supposed to be --port, not --allow. So this change gets this test actually testing what it's supposed to, again. Reviewed by Fergus Henderson 2008-05-07 18:21 Fergus Henderson * include_server/include_server.py: Insert "Usage: " at the start of the usage message for the include server. 2008-05-07 18:01 Craig Silverstein * doc/web, doc/web/compared.html, doc/web/compilers.html, doc/web/distcc-green.css, doc/web/distcc-lca-2004.html, doc/web/distcc-lca-2004.pdf, doc/web/distcc-lca2003.ps.gz, doc/web/distccmon-gnome-2003-09-23-01.png, doc/web/faq.html, doc/web/index.html, doc/web/results.html, doc/web/scenarios.html, doc/web/security.html: Add the documentation files, as downloaded from distcc.samba.org. I then modified the files slightly, mostly by deleting content that referred to files on the samba.org server and replacing them by files (or, usually, links) to Google Code. For instance, the 'source' link now points to the Google Code svn page for distcc, rather than a page holding tarball information. Likewise, the News page now just points to the svn trunk's NEWS file. For the record, here's email from Martin Pool OK-ing this move/copy: --- From: Martin Pool Date: Sun, May 4, 2008 at 9:31 PM Subject: Re: sources for distcc web site To: Fergus Henderson > Hi, The sources are at You are welcome to either work from these or scrape the web site. You can make any reasonable use of the text in making a new web site. -- Martin > --- Reviewed by Fergus Henderson 2008-05-05 15:31 Fergus Henderson * man/distcc.1, man/distccd.1: Document Zeroconf support: the "--zeroconf" option to distccd and the "+zeroconf" entry in the distcc hosts list. Reviewers: Craig Silverstein, Nils Klarlund. 2008-05-05 15:26 Fergus Henderson * man/distcc.1: Document the -j and --show-hosts options in the man page. Also mention that pump mode requires release 3.0 or later, and a few other minor corrections. 2008-05-02 23:07 Fergus Henderson * test/testdistcc.py: Change Lsdistcc_Case to work on hosts for which 127.0.0.2 is not a loopback address. Tested by "(g)make TESTNAME=Lsdistcc_Case single-test" on both Linux and FreeBSD. Reviewers: Craig Silverstein, Nils Klarlund. 2008-05-02 21:11 Fergus Henderson * test/testdistcc.py: Fix EmptySource_Case test so that it passes with gcc 3.4.x. Tested by "(g)make SINGLETEST=EmptySource_Case single-test" on both FreeBSD (gcc 3.4.4) and Linux (gcc 4.0.3). Reviewers: Craig Silverstein 2008-05-02 19:54 Nils Klarlund * configure.ac, lzo/.stamp-conf.in, popt/.stamp-conf.in: Explain stamp files and remove unneeded @src_dir@ (which was misspelled?). TESTED: make distcheck REVIEWED: Craig Silverstein, Fergus Henderson 2008-05-02 19:09 Craig Silverstein * Makefile.in, configure.ac: For machines without python installed, before this change we'd check for that case, but still give an error rc in that case, so the make would fail. Now I make sure we don't fail just because we don't have python installed. Also, some machines (solaris 10) don't have a grep with -q, so just use >/dev/null insteasd. Third, we had left out a file to add to the tarball: ontest.py. Fourth, 'make distcheck' fails a bit on the pump-installcheck. I've addressed some of the problems, but others remain. Finally -- and this is the bulk of the change, line-count wise, I added quotes around all variables, so we do the right thing when variables have spaces or other shell-meaningful characters in them, as indeed they often do on windows machines. Tested by running 'make check' on various architectures, including solaris 10 x86 and cygwin. Reviewed by Nils Klarlund and Fergus Henderson 2008-05-02 18:49 Fergus Henderson * src/sendfile.c: Treat ENOTSOCK errors from sendfile() the same way that we treat ENONSYS and EINVAL errors: fall back to using read() and write(). This fixes the failure of SyntaxError_Case and MissingCompiler_Case on FreeBSD. Tested by "make check". Reviewers: Craig Silverstein 2008-05-02 18:17 Nils Klarlund * test/testdistcc.py: Remove .d test case for which gcc stumbles on Mac OS. 2008-05-02 18:11 Craig Silverstein * src/distcc.h: This adds an #two that's technically needed to compile. Cygwin happened to notice this was missing. Tested by compiling (via 'make') on cygwin and ubuntu. Reviewed by Fergus Henderson 2008-05-02 18:10 Craig Silverstein * test/testdistcc.py: Four improvements to the test framework: 1) While pump-mode requires python 2.4, the test framework is designed to work with python 2.2 and later. A few non-2.2 features have snuck in though. I replaced them with 2.2-compatible code. 2) The test system used the --ex flag to gdb, which is only supported in more recent gdb's. I've changed the code to use --command instead, which is supported in old gdb's as well. I also added a workaround for a buggy error-message that gdb sometimes emits. See http://www.archlinux.org/pipermail/arch/2007-January/013366.html 3) I fixed a regexp for the gcc-options case, to handle correctly systems that don't name gcc "gcc" (for instance, they might name it powerpc-apple-darwin8-gcc-4.0.1). 4) Use shell quoting, when appropriate, to deal with paths that have spaces (eg on windows) or other weird characters in them. Tested by running 'make maintainer-check' on a variety of architectures, including os x and cygwin. The tests successfully run on all of them (though not all tests successfully pass yet...) Reviewed by Fergus Henderson and Nils Klarlund 2008-05-02 00:10 Craig Silverstein * Makefile.in: Small wording change, suggested by Nils Klarlund 2008-05-01 23:52 Craig Silverstein * configure.ac: This test was broken before: I needed to escape [ and ] from m4. Tested by running configure on a machine with python 2.2 installed. Reviewed by Fergus Henderson 2008-05-01 23:51 Craig Silverstein * Makefile.in: Previously, 'make check' was a noop because we do not require python to be installed for distcc, but the tests require python. Therefore, to run the tests you had to run 'make maintainer-check' instead (since maintainers of distcc *do* have to have python installed). Now, I have 'make check' check if python is installed. If so, it runs the tests. Otherwise, it prints a message and exits. Tested by running 'make check' and 'make installcheck' manually, on systems with the various pythons installed as well as a few without. Code reviewed by Fergus Henderson 2008-05-01 23:02 Craig Silverstein * Makefile.in, configure.ac: Include-server requires python 2.4 or higher, but the test framework only requires python 2.2. Check for both, so for folks with python 2.2 or python 2.3, they can at least run the tests, even if they can't install the include-server. 2008-05-01 00:58 Nils Klarlund * include_server/c_extensions_test.py: Clean up Python code. -- Do TODOs. -- Heed most pylint warnings. 2008-04-30 22:46 Nils Klarlund * Makefile.in, find_c_extension.sh, include_server/c_extensions_test.py, pump.in: Make install-checks work and a lot of clean-up in regards to the 'checking' targets. - Remove temporary installation for include server tests. The current scheme doesn't make too much sense: when testing a real installation, the include server is tested in the separate temporary installation. Instead, we propose to make the installation tests run only the regression tests in the 'test' directory, unpumped and pumped. The include server is now tested as part of maintainer-check only, but run out of the source directory, except for the C extension module. - The maintainer-check and the maintainer-install-check now run the integration test (test/testdistcc.py) also in pump mode. - A new script, find_c_extension.sh, is added; it finds the location of the shared library. It is used for both running the include server tests and the regression tests out of the built (not installed) version of the software. It was cut of the 'pump' script, which now has been simplified. - Reorganize the order of affected targets. Introduce '###############...' as separator between sections of Makefile in a more consistent way. Make each section consistently declare all the phony targets at the beginning of the section. - Introduce DISTCC_INSTALLATION variable to account for the precise location of the tested binaries in an installation. - Add verify-binaries-installcheck target to ensure that binaries are in this location. - Also, this target reports the location to users: Make sure all paths below are where you expect them to be: ********************************************************** /home/klarlund/svn-distcc/mybin/installation/bin/distcc /home/klarlund/svn-distcc/mybin/installation/bin/distccd /home/klarlund/svn-distcc/mybin/installation/bin/distccmon-text /home/klarlund/svn-distcc/mybin/installation/bin/lsdistcc ********************************************************** - Absolutize a couple of relative directory references before they are passed to scripts, because otherwise things won't work with the disciplined approach to DISTCC_INSTALLATION. - Change a randomly generated filename so that it resides in /tmp (in c_extensions_test.py) and not inside the build directory tree. Fix up logic for filenaming to be more secure. This makes 'make distcheck' pass w/o permission problems. Also, delete the temporary file and directory when test passes. - Make include-server-maintainer-check remove the .out file when test passes. This makes 'make distcheck' pass the final test of the clean-out. - Remove the 'Filtering' of the c_extensions_test output. This filtering was necessary in a previous version that printed all output to stdout to reduce user confusion. But now the test results go to intermediate files. This change was forced by the removal of the .out files (above). REVIEWED: fergus, csilvers. TESTS: make distcheck make maintainer-installcheck make include-server-maintainer-check make maintainer-check 2008-04-28 21:52 Craig Silverstein * src/sendfile.c: OS X added sendfile support in 10.5, so add this case to sendfile.c. Looking at the man pages, it looks like os x sendfile is pretty much the same as BSD's, so I copied much of the code from the existing BSD case. Tested by ensuring the code compiles and links on os x 10.5. No attempt to see if it runs correctly, though. Reviewed by Fergus Henderson 2008-04-28 19:23 Craig Silverstein * Makefile.in, configure.ac, include_server/setup.py, src/compile.c, src/distcc.h, src/dotd.c, src/emaillog.c, src/exec.c, src/fix_debug_info.c, src/io.c, src/lsdistcc.c, src/netutil.c, src/snprintf.c, src/srvrpc.c, src/tempfile.c, src/trace.c, src/util.c: These changes are enough to get code to compile, and at least some of the unittests to pass, on FreeBSD 6.0, Solaris 10 x86, and OS X Leopard. You have to use gmake instead of standard bsd make, though, because neither bsd nor solari make understand 'include */*.d' and 'CFLAGS += $(POPT_FLAGS).' These may be fixable later. Most changes fall into four categories: 1) #include differences 2) New errors due to some #ifdef paths being taken differently 3) Undefined functions (see, eg, the new HAVE_STRSEP) 4) Type differences (eg tv_usec is an int on os x, not a long int) As one concrete example, snprintf.c is an empty file on linux, where all the functionality is part of glibc. But on Solaris, some of its functionality is useful. This turned up a bug where if you have vsnprintf on your system but not vasnprintf, then dopr() was not being used but was being defined, leading to an "unused static function" warning in gcc. As another, solaris would complain about "index" being used as a variable, since it's also a function name. The var was renamed idx. Tested by compiling on FreeBSD, Solaris 10, and OS X leopard (x86). I also compiled and ran unittests under Linux Ubuntu, to make sure this change didn't break anything there. Reviewed by Fergus Henderson 2008-04-25 06:29 Craig Silverstein * include_server/include_analyzer_test.py, include_server/test_data/symlink_farm/foo, include_server/test_data/symlink_farm/sub_farm/link_to_dd_dd_dfoo_include_dotdot_foo[CPY], include_server/test_data/symlink_farm/sub_farm/link_to_dotdot_dotdot_dfoo_include_dotdot_foo[DEL]: Some older versions of tar have problems with filenames > 100 characters. To maximize compatibility, I renamed the only file we have that is close to that limitation, to be shorter. 2008-04-24 06:40 Craig Silverstein * configure.ac: Neglected to commit this with the Makefile.am changes from last time, though it's needed to define UNINSTALL_GNOME. Reviewed by Fergus Henderson 2008-04-24 05:39 Craig Silverstein * Makefile.in: Add uninstall targets, to undo the effects of 'make install'. I try to be semi-smart about deleting empty directories. Unfortunately, python's setup.py does not have an --uninstall mode, so I can only uninstall the include-server if a python-record-file was preserved during make install. This record-file must be passed in for make uninstall as well. Tested by running 'make install' followed by 'make uninstall' on my local machine. Reviewed by Fergus Henderson 2008-04-23 00:40 Craig Silverstein * TODO: Update the TODO file to add an entry on better non-ELF support. Also get rid of the TODO for Latte, since we're not going to be using any doc-template system on Google Code. While in the area, normalize a little bit the number of blank lines between entries (I try to make it 2). 2008-04-19 23:40 Craig Silverstein * Makefile.in, configure.ac, packaging/googlecode_upload.py: Fix some bugs in the googlecode-upload script, and modify the upload target in the Makefile to call it. Also added googlecode_upload.py to the dist tarball. Also update the version number to prerelease2. As part of testing this change, I actually uploaded the tarballs and rpm files to code.google.com. Reviewed by Fergus Henderson 2008-04-18 19:19 Nils Klarlund * Makefile.in, test/comfychair.py: Rename directory testtmp to _testtmp in line with our current practice for generated directories. 2008-04-18 18:51 Craig Silverstein * .: Another auto-generated file I had forgotten last time. 2008-04-18 18:32 Fergus Henderson * Makefile.in, packaging/RedHat/conf, packaging/RedHat/conf/clients.allow, packaging/RedHat/conf/commands.allow.sh, packaging/RedHat/conf/hosts, packaging/RedHat/default, packaging/RedHat/default/distcc, packaging/RedHat/init.d/distcc, packaging/RedHat/rpm.spec: A bunch of changes to the configuration files and installation: (1) Remove the Google crosstool-specific stuff from packaging/RedHat/init.d/distcc; instead, make it source a new configuration file "commands.allow.sh". (2) Install default versions of all the configuration files in $(sysconfdir), i.e. /etc: distcc/hosts, distcc/clients.allow, commands.allow.sh, and defaults/distcc. (3) Fix a bug in Makefile.in: "make install" didn't work when you configured with srcdir != builddir. Added "$(srcdir)/" in various places to make it work. (There's similar problems with "make dist", but I gave up on those for now.) (4) Add "install-deb" rule, to install the ".deb" files. (5) Don't run install-for-include-server-tests as part of "make install". That target is part of "make check", not "make install". (6) Add missing dependency on "include-server" to "pump-check" rule. (7) Remove some bash-isms from the "init.d/distcc" script. Tested by running "make install-deb" followed by "distcc /usr/bin/gcc -c foo.c" - this now works "out-of-the-box"! :-> Also ran "make maintainer-check" and "make pump-check". 2008-04-18 16:01 Fergus Henderson * autogen.sh: Address review comments on an earlier change: - autogen.sh now uses "#!/bin/sh -e" rather than "|| exit 1" everywhere. - autogen.sh now determines srcdir automatically from $0 - autogen.sh no longer tells you to run "./configure --srcdir=.". 2008-04-18 15:13 Nils Klarlund * test/testdistcc.py: Fix-up test in regard to angle bracket includes of non-existent files in order to explicitly accommodate the rather strange difference between running gcc locally and running it remotely in pump mode. In the former case, gcc fails with an error message; in the latter it succeeds and the error has been demoted to a warning. TESTING: make maintainer-check make pump-check 2008-04-18 08:59 Fergus Henderson * man/distccd.1: The --allow option to distccd is no longer optional. Update the distccd man page to better reflect that. 2008-04-18 06:53 Craig Silverstein * ., lzo, packaging, popt, src, test: Update the svn:ignore property on these directories, so 'svn status' doesn't show the auto-generated files that can show up, such as distcc.d or config.h.in. 2008-04-18 06:37 Craig Silverstein * packaging/googlecode_upload.py: Add distcc-specific code to googlecode_upload. This allows us to upload all the package files we create in one fell swoop (they must be specified on the commandline). We figure out the summary to give to each file and the label to apply, and then upload each in turn. I've also turned off the feature to figure out the name and password directly from the local svn repository, because that feature is broken (alas), with the current python-subversion bindings. Instead, I prompt for them, but at least it's only once per upload as opposed to once per file! Not yet tested (will do so when I add to the Makefile to actually use it). Reviewed by Fergus Henderson 2008-04-18 01:12 Nils Klarlund * Makefile.in: Add missing dependency on pump for target pump-check and pump-installcheck. To do so, introduce new phony intermediate target. Add TODO about the `pwd` in maintainer-installcheck target. 2008-04-18 01:08 Fergus Henderson * Makefile.in: Fix missing line continuation in a Makefile rule. Also, use "@" to avoid printing out a line with disturbing contents ("ERROR") during normal successful test execution. 2008-04-18 01:05 Fergus Henderson * autogen.sh: Support running autogen.sh in the build directory, rather than the source directory. Now the source directory should be completely untouched, so we should be able to autogen, configure, and build even if the source directory is read-only. 2008-04-18 01:03 Craig Silverstein * Makefile.in: Quick fix to my previous commit: I have to make sure every Make line ends in success, when it in fact succeeds. Thus you need to use || sometimes instead of &&. 2008-04-18 01:00 Craig Silverstein * Makefile.in: Augment 'make distcheck' to ensure that 'make', 'make check', 'make install', etc. only write into builddir and instdir, not srcdir. In the process, fixed up a typo -- introduced when I merged all the Makefile.in's -- that affected us in the (common) case DISTDIR is the empty string. Tested by running 'make distcheck'. Reviewed by Fergus Henderson 2008-04-18 00:07 Craig Silverstein * packaging/googlecode_upload.py: Add googlecode_upload.py, a script to help upload tarballs and package files to the Google Code location of distcc. This is the version as downloaded from the web, at http://support.googlecode.com/svn-history/r57/trunk/scripts/googlecode_upload.py After this pristine version is checked in, we'll hack on it to add some distcc-specific features (multiple uploads, etc). We'll also add it to the Makefile at that time, both to use ('make upload') and as part of the distribution (hey, why not). 2008-04-17 22:27 Craig Silverstein * Makefile.in, build-distcc.sh[DEL], distcc.spec[DEL], packaging/RedHat/rpm.spec[CPY], packaging/deb.sh, packaging/rpm.sh[CPY]: Add 'make rpm' to make the rpm files for this project (much like 'make dist' makes a tar.gz file), and 'make deb' to make the deb files. 'make alldist' will make all three (well, four): .tar.gz, .tar.bz2, .rpm, and .deb. The rpm.spec file that's used is based on the old distcc.spec file, which is now deleted. However, it's reordered to look a bit more like other spec files for Google projects, removes the obsolete 'include-server' package (that's now part of the distcc package proper), and takes out all the ChangeLog entries that don't relate to the spec file in particular. I also added a script, rpm.sh, to build the rpm file, which is a combination of the rpm.sh script used to build other google projects, and the existing build-distcc.sh, which is now deleted. Mostly it just calls rpmbuild with the right flags. deb.sh could have re-done all the work that rpm.spec and rpm.sh does, but instead we just use "alien" to convert the rpm to a deb file. Tested by installing the deb files (both client and server) on my home machine and then running 'make maintainer-installcheck'. Reviewed by Fergus Henderson 2008-04-17 05:42 Fergus Henderson * README.pump: Avoid referring to "the distcc-pump". Reviewed by Nils Klarlund. 2008-04-17 02:45 Craig Silverstein * INSTALL, Makefile.in, configure.ac, include_server/setup.py: Resolve some TODO's in the Makefile (and, to a lesser extent, in configure.ac): 1) Create a .gz tarfile as well as a .bz2 tarfile, with "make dist". I've also added a few more dist rules: "make rpm", "make deb", and "make alldist", though currently they're commented out since the scripts they call have yet to be written. 2) setup.py looks at os.environ("BUILDDIR"), so make sure that environment variable is always set properly. 3) setup.py was hard-coding the version number. Instead, have it get it from the environment ("DISTCC_VERSION"), and set that envvar before calling setup.py in the Makefile. (The alternate solution, of making a setup.py.in and having configure set the version number in setup.py, did not work well because the Makefile really wants setup.py to be in $srcdir, that the configure option puts it in builddir.) 4) Clean up distcheck to have three separate directories: src, build, and install. Before src and build were the same. This pulled up several places that were using srcdir instead of builddir, which I fixed. 5) Clean up distcheck to make sure that 'make distclean' cleans all the build files created during the build. At first it didn't quite, so I fixed that up as well. 6) Added some new files to 'make dist': particularly, the files used to build rpm and deb files. 7) Have maintainer-check and maintainer-installcheck both call the same routine (via recursive make) rather than copy all that code. This simplifies things surprisingly, especially since the main check logic no longer has be inside a big "if $(PYTHON)". 8) (Various rules:) replace $^, which is not very portable, with a repetition of the dependency line. 9) Rename GZIP to GZIP_BIN, since GZIP as an envvar is read by gzip and parsed as gzip options. 10) In include_server/setup.py, we weren't setting builddir/src as an include dir, and it needs to be (as 'make distcheck' shows). I'm not sure builddir/../../src really needs to be anymore, but I guess it can't hurt, so I've left it in. 11) Updated INSTALL to refer to autogen.sh, which will create configure if it's not already there. 2008-04-15 02:23 Nils Klarlund * pump.in: Clean logic and error messaging in pump script. - There were missing error messages. - Some of them did not go to stderr. - Global variable include_server_started_successfully was ugly. Changed to a status variable. - Also, joined some lines that were joinable. - Fixed a spurious parameter to a function ExportDISTCC_HOSTS. Added a parameter to same function. Tests ----- Can run 'pump-check'. Also, when I forced more than one C extension, I get the following tirade. __________Using distcc-pump from /home/klarlund/svn-distcc/distcc __________Shared libraries for multiple architectures discovered. __________Cannot determine which one to use among: ./_builddir/lib.blah/include_server/distcc_pump_c_extensions.so ./_builddir/lib.linux-x86_64-2.4/include_server/distcc_pump_c_extensions.so __________Could not start distcc-pump include server 2008-04-14 23:17 Craig Silverstein * ChangeLog: Added some Google-branch changes to the ChangeLog file, now that we've integrated them back into the main branch in preparation for distcc 3.0. These messages were taken from the rpm.spec ChangeLog, where they had been living before. I can't say that it's a complete list of google-branch patches, but it's a good started. Reviewed by Fergus Henderson 2008-04-14 17:11 Nils Klarlund * pump.in: Fix up pump.in: - Rename DISTCC_PUMP_LOCATION because there is now no distinct such entity. - Comment 'return 0'. - Fix logic in Main so that script aborts when include server not started. - Add missing line: include_server_started_successfully=0. 2008-04-12 00:58 Craig Silverstein * Makefile.in, autogen.sh, bench/Build.py, bench/Project.py, bench/ProjectDefs.py, bench/Summary.py, bench/actions.py, bench/benchmark.py, bench/buildutil.py, bench/compiler.py, bench/statistics.py, configure.ac, distcc[DEL], include_server/basics.py, include_server/setup.py, pump.in: The second part of my change to hoist everything in the distcc/ directory up to the top level: delete the distcc directory (I already copied it all to the top level in my last commit). This requires changing all files that refer to distcc/FOO to refer directly to FOO instead. Mostly this is Makefile.in and setup.py, but there are a few other changes in scripts that have to hard-code paths, like configure.ac and pump.in. Also, several files changed their comments to refer to the new location, which isn't strictly necessary but I did anyway. The only other change I made was to get rid of the hack I had put in before, which renamed distcc to distcc-bin. I had needed to do that before, temporarily, because "distcc" was already the name of a directory, and couldn't also be the name of a binary. Now that the distcc directory is going away, I can rename the target back to distcc. Tested by running './autogen; ./configure; make maintainer-check'. I also ran 'make pump-check' and 'make distcheck'. To be reviewed (post-facto) by Nils Klarlund and Fergus Henderson 2008-04-11 22:36 Craig Silverstein * bench[CPY], contrib[CPY], doc[CPY], gnome[CPY], lzo[CPY], m4[CPY], m4/pkg.m4[CPY], man[CPY], packaging[CPY], popt[CPY], src[CPY], survey.txt[CPY], test[CPY]: The first step of moving everything in the distcc directory to the top level. I'm doing this in two stages, because I don't understand svn enough to be confident to do it in one. This first stage just copies all the files from distcc/FOO to FOO. Now there are two copies of each file under distcc; the Makefile/etc uses the one in distcc and ignores the one at the top level. The next commit will delete everything under distcc, and rewrite the Makefile/etc to use the top-level versions instead. 2008-04-11 22:20 Craig Silverstein * INSTALL, Makefile.in[CPY], autogen.sh[CPY], build-distcc.sh, config.guess[CPY], config.sub[CPY], configure.ac[CPY], distcc/Makefile.in[DEL], distcc/autogen.sh[DEL], distcc/config.guess[DEL], distcc/config.sub[DEL], distcc/configure.ac[DEL], distcc/install-sh[DEL], distcc/m4/pkg.m4, distcc/mkinstalldirs[DEL], include_server/Makefile.in[DEL], include_server/configure.ac[DEL], include_server/setup.py, install-sh[CPY], mkinstalldirs[CPY], pump.in, run_all_autoconf.sh[DEL], version.sh[DEL]: Merge configure.ac, distcc/configure.ac, and include_server/configure.ac into a single, top-level configure.ac script. Likewise with the three Makefile.in scripts. Now one config file at the top level controls everything. I had to rewrite quite a bit of code to account for the new level-up. In particular, I had to add "distcc/" in front of many things in order to refer to the same files I used to refer to when the configure.ac/Makefile.in text lived in the distcc/ directory rather than the top-level directory. Likewise (though to a lesser extent) for include_server. I also had to do a bit of merge work. Typically I'd leave the originally-distcc-directory content as close to the original as possible, and then try to put in the include_server directory stuff. Most of the top-level configure.ac and Makefile.in could go away, since they were glue before. I also could get rid of other top-level helper scripts that were used for the glue, such as version.sh. I also fixed a number of typos and other bugs: Makefile.in: 1) Removed obsolete CVS comment (we're 3 source-control systems past that now!) 2) distcc/Makefile.in was using top_builddir without importing it from the configure script. 3) Add zeroconf.h to HEADERS, which is needed for 'make dist'. I also added all the include_server files to 'make dist'. 4) "make dist" was passing 'h' ("no symlinks") to tar. This does not work with the include_server test-suite, which includes symlinks. I verified no other part of the distribution uses symlinks. Removed the h. 5) "make dist" was missing a lot of stuff (including almost all the include-server files). Updated it to get it all now. Likewise, updated "make clean" and its cousins to be more precise. Also made "make distcheck" more careful in checking that kind of thing. 6) Declared more phony targets .PHONY. 7) The include-server build commands do a lot of 'cd'-ing (since setup.py requires it), and then using make variables that might store relative directory paths. I now go through some hoops to make those directory paths absolute before the cd. 8) "make pump-check" was not setting the path, so it was using the installed distcc instead of the local one in the client. Fixed that, and added a new target, "make pump-installcheck", to use the installed distcc instead (parallel to the maintainer-check and maintainer-installcheck targets). configure.ac: 1) popt test was using $srcdir rather than required ${srcdir}, and thus was always getting the empty string. (Luckily, srcdir is usually ".", and the empty string is usually equivalent.) Likewise when setting CPPFLAGS, which again didn't matter because it turns out the relevant code was redundant with what autoconf already does automatically. 2) A merge error: apparently the avahi check was added twice. Get rid of the second one. 3) Was using obsolete AC_OUTPUT format. Use AC_CONFIG_FILES instead. 4) Added pkg.m4 to the m4/ directory. Before it only lived in autoconf.m4. But my system, at least, doesn't have it. 5) include-server requires python2.4, so remove checks for earlier pythons. autogen.sh: 1) Added aclocal call. I think it was a bug that it was left out before. pump.in: 1) Fixed it to notice when it can't find the .so file it needs. I also modified INSTALL to point to the new file locations, and the new instructions to run them (eg no more run_all_autoconf.sh). Despite all these bugfixes, I made the minimal changes possible to get things to work. I marked with "TODO" further improvements I'd like to make later. One particular TODO is that I had to rename the "distcc" target -- the main executable -- because it conflicts with the existing distcc directory. This is a temporary breakage which will be fixed in the next submit after this one, where I move the subdirs under distcc to the top level, getting rid of the artificial extra directory introduced. Tested by running 'make maintainer-check', 'make distcheck', and 'make pump-check' on my local machine, which passed. I've not tested all the various configurations and options (including using avahi, using the library popt library, building without python, etc). I've also not tried 'make benchmark'. Reviewed by Nils Klarlund and Fergus Henderson 2008-04-11 20:40 Fergus Henderson * README.pump: Update README.pump to better describe performance on small clusters. 2008-04-11 18:45 Fergus Henderson * distcc/Makefile.in: In the rule for 'make pump-check', set DISTCC_HOSTS, so that 'pump' won't complain that it isn't set. 2008-04-10 00:27 Craig Silverstein * distcc/README[DEL]: I meant to delete this as part of my last commit, but apparently neglected to... 2008-04-09 23:19 Craig Silverstein * AUTHORS[CPY], ChangeLog[CPY], INSTALL, NEWS[CPY], README, README.packaging[CPY], README.pump[CPY], TODO[CPY], distcc/AUTHORS[DEL], distcc/COPYING[DEL], distcc/ChangeLog[DEL], distcc/ChangeLog.old[DEL], distcc/INSTALL[DEL], distcc/NEWS[DEL], distcc/README.packaging[DEL], distcc/TODO[DEL]: Take these human-readable files and normalize their content and location: README Our blurp, tooting our horn INSTALL The run_all_autoconf and friends incantations COPYING GPL 2.0 license distcc/README Martin's blurp distcc/INSTALL Also: more on masquerading, host lists, distcc/COPYING GPL 2.0 license distcc/NEWS Recently updated distcc/AUTHORS Martin Pool distcc/README.packaging Various advice (version numbering etc) distcc/TODO A very long list (not updated) distcc/ChangeLog All changes under arch and under bzr distcc/ChangeLog.old All changes from before arch. Now all live in the top-level directory. This is the first step towards our eventual goal of getting rid of the second-level distcc and include_server directories, and just having everything under one top-level directory. We're all part of the same project now! Here's how I merged and updated content: . README became README.pump. It was slightly edited for clarity. (I also redid all the line-wrapping, which makes diff-ing difficult. :-( ) distcc/README became README, with a small amount of text added to describe 'pump' mode, and point to README.pump. . distcc/NEWS became NEWS. pump functionality was added (a new "distcc-3.0" entry). I also added all new features and bug-fixes since we moved from arch to bzr. It looks like NEWS was well-maintained before the move to bzr, so this might be pretty complete. There may be some more pump-developed bugfixes we need to add, though. . I got rid of distcc/COPYING. Now COPYING is the only license in this directory. This file was not changed. It remains the GPL 2.0 license. . distcc/AUTHORS became AUTHORS. I changed Martin to maintainer emeritus. I added the Google authors as authors of the "pump" functionality, and current maintainers. I set the Google email address to be distcc@googlegroups.com, which is a new group I've set up to be the clearinghouse for distcc discussions. . distcc/README.packaging became README.packaging. It was not otherwise changed. . distcc/TODO became TODO. It was not otherwise changed, except I added that folks should look for FIXMEs in source files, not just TODOs. . I merged INSTALL and distcc/INSTALL (in that order). I rearranged the text a little bit to remove redundancy (both talked about running 'configure'), but did not make any contentful changes. . I merged distcc/ChangeLog and distcc/ChangeLog.old to have a single changelog again going all the way to 2002. Comments now separate the various version control systems used. (svn is #4!) The single ChangeLog file now lives in the top-level directory. 2008-04-09 23:11 Craig Silverstein * distcc/ChangeLog, distcc/Makefile.in, distcc/configure.ac, distcc/m4, distcc/m4/acx_pthread.m4, distcc/src/distcc.c, distcc/src/distcc.h, distcc/src/dopt.c, distcc/src/dopt.h, distcc/src/dparent.c, distcc/src/gcc-id.c, distcc/src/help.c, distcc/src/hostfile.c, distcc/src/hosts.c, distcc/src/io.c, distcc/src/tempfile.c, distcc/src/zeroconf-reg.c, distcc/src/zeroconf.c, distcc/src/zeroconf.h: Integrate the following post-bzr (post 2.18.3) patch from the mainline distcc sources (http://bazaar.launchpad.net/%7Embp/distcc/trunk/): % bzr log -r3 message: merge avahi patch from Lennart Poettering (This patch comes from http://0pointer.de/public/distcc-avahi.patch, which is the version of the patch I applied, since the one in the bzr repository was missing the new files from the avahi patch.) I've also manually updated ChangeLog, which is not automatically updated by bzr the same way it is by arch. I've also added a new m4 directory, including non-standard autoconf macros that we use. For now, it only includes ACX_PTHREAD (added by the avahi patch) which I got from 0pointer.de. See the notes at the top of m4/acx_pthread.m4 for more details. I removed the change to Makefile.in that added in distccmon-gnome.1. This file is not actually added in as part of this patch (it seems to be part of a separate patch, at http://patches.ubuntu.com/d/distcc/extracted/02_distccmongnome_man.dpatch), and may have gotten in here by accident. Tested by running 'make maintainer-check'. However, I did not test with avahi installed, so I don't know how well that works. Reviewed by Fergus Henderson and Nils Klarlund 2008-04-09 16:21 Fergus Henderson * version.sh: Change the version number from "distcc 2.18.3-17gg1.pump20" (ugh!) to "distcc 3.0-prerelease1". 2008-04-09 00:38 Craig Silverstein * distcc/ChangeLog, distcc/NEWS, distcc/src/lock.c: Integrate the following post-bzr (post 2.18.3) patches -- all of them, so far -- from the mainline distcc sources (http://bazaar.launchpad.net/%7Embp/distcc/trunk/): % bzr log -r2 message: Add more ignored files % bzr log -r4 message: Locks taken through F_SETLK or lockf() must be explicitly released, because closing the file does not do so. (Sascha Demetrio) r2 is a noop for us, since it just updates a .bzr config file (which we may want to update in svn-land too, one day, but not for now). r3, not part of this CL, is the "avahi" patch (http://0pointer.de/public/distcc-avahi.patch). It was imperfectly applied: the new files that are part of this patch were not added to the bzr repository. We're following up with the patch-applier to see if these files can be taken verbatim from the patch in the 0pointer website. We'll also have to audit this patch to make sure it works with distcc-pump without needing any changes. For those reasons, we'll apply that patch in a separate change. I've also manually updated ChangeLog, which is not automatically updated by bzr the same way it is by arch. Tested by running 'make maintainer-check'. Reviewed by Nils Klarlund 2008-03-31 04:38 Craig Silverstein * distcc/ChangeLog, distcc/Makefile.in, distcc/NEWS, distcc/man/distcc.1, distcc/src/clinet.c: Integrate the following post-2.18.3 patches from the mainline distcc sources (distcc--devel--2/mbp@sourcefrog.net--2004): % tla cat-log patch-179: Summary: More details on error 110 % tla cat-log patch-180: Summary: draft patch for substituting compiler command name % tla cat-log patch-181: Summary: fix error check in dcc_connect_by_add % tla cat-log patch-182: Summary: build fix for --as-needed % tla cat-log patch-183: Summary: ignore tags file Note only one of these (patch-181) affects code in the src/ directory. Tested by running 'make maintainer-check'. Reviewed by Fergus Henderson 2008-03-29 19:19 Craig Silverstein * distcc/ChangeLog, distcc/NEWS, distcc/autogen.sh, distcc/bench/ProjectDefs.py, distcc/configure.ac, distcc/src/exec.c, distcc/src/exitcode.h, distcc/src/io.c, distcc/src/tempfile.c, distcc/test/comfychair.py, distcc/test/testdistcc.py: Integrate the following post-2.18.3 patches from the mainline distcc sources (distcc--devel--2/mbp@sourcefrog.net--2004): % tla cat-log patch-167: Summary: - better autogen message % tla cat-log patch-168: Summary: use python2.4 if available % tla cat-log patch-169: Summary: bump version number % tla cat-log patch-170: Summary: return error on timeout in dcc_select_for_write % tla cat-log patch-171: Summary: doc % tla cat-log patch-172: Summary: doc % tla cat-log patch-173: Summary: [patch] cygwin improvements from Alex Besogonov % tla cat-log patch-174: Summary: update patch to fix up gdb line numbers % tla cat-log patch-175: Summary: [patch] update stale benchmark source URLS (Dongmin Zhang) % tla cat-log patch-176: Summary: update benchmark project urls and md5s % tla cat-log patch-177: Summary: Update more benchmark project definitions % tla cat-log patch-178: Summary: set locale when running make maintainer-check Note only two of these (patch-170 and patch-173) affect non-comment code in the src/ directory. patch-173 introduced an "unused variable" warning in tempfile.c when run in non-cygwin mode, which I fixed up separate to the above patches. Tested by running 'make maintainer-check'. Reviewed by Fergus Henderson 2008-03-29 04:40 Craig Silverstein * run_all_autoconf.sh: Replace the sanity-check in run_all_autoconf.sh with a more accurate one. Reviewed by Nils Klarlund 2008-03-28 22:38 Craig Silverstein * distcc/ChangeLog, distcc/NEWS, distcc/TODO, distcc/man/distcc.1, distcc/src/arg.c, distcc/src/clinet.c, distcc/test/testdistcc.py: Integrate the following post-2.18.3 patches from the mainline distcc sources (distcc--devel--2/mbp@sourcefrog.net--2004): % tla cat-log patch-160: Summary: note on .incbin from asm() % tla cat-log patch-161: Summary: args: -d must be local % tla cat-log patch-162: Summary: manpage correction from Frerich % tla cat-log patch-163: Summary: todo % tla cat-log patch-164: Summary: add note that the mDNS patch cannot be legally merged % tla cat-log patch-165: Summary: add hosts-from-dnsdomain patch from dan % tla cat-log patch-166: Summary: [patch] better checking for errors on connect() Note only two of these (patch-161 and patch-166) affect the src/ or test/ directories. Tested via 'make maintainer-check'. 2008-03-28 17:39 Fergus Henderson * distcc/Makefile.in: Fix typo. 2008-03-28 17:38 Fergus Henderson * distcc/src/fix_debug_info.c: Work around spurious gcc warning that was causing trouble with -Werror. 2008-03-28 17:30 Fergus Henderson * distcc/src/lsdistcc.c: Fix a portability issue: compile error on 64-bit platform. ## This is the point at which the code was moved to the svn repository. ## The changes below this were made in an internal Google repository. 2008/03/03 11:35:34 Fergus Henderson Add extra "-I" option that seems to be needed when building distcc-pump with Blaze: we need _two_ ".."'s to get from $BUILDDIR/include_server/build to $BUILDDIR/distcc/src/config.h. Without this change, building distcc fails with a compilation error about "config.h" not found when run in a fresh workspace. R=klarlund DELTA=2 (2 added, 0 deleted, 0 changed) * include_server/setup.py: edit 2007/12/14 19:17:16 Fergus Henderson Fix a bug which showed up if the include server was run from a different directory than the distcc clients: in that case, it was at some times wrongly interpreting relative paths in the --stat_reset_trigger option as relative to the distcc client's cwd, rather than the include server's cwd. TODO(fergus): add a regression test. R=klarlund CC=distcc-pump APPROVED=klarlund DELTA=20 (18 added, 2 deleted, 0 changed) * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node_test.py: edit 2007/12/14 10:26:29 Nils Klarlund Fix location of stamp file that record autoconf execution. The location was incorrect: the stamp file that pertains to autoconf must necessarily be in the source code directory because autoconf'ing is the process of generating the configure script. Only the result of configuring is to be carried out in the object directory. R=fergus DELTA=1 (0 added, 0 deleted, 1 changed) * Makefile.in: edit 2007/12/13 21:52:59 Nils Klarlund Fix typos in Makefile.in. R=fergus DELTA=2 (0 added, 0 deleted, 2 changed) * include_server/Makefile.in: edit 2007/12/07 16:19:16 Nils Klarlund This file is generated by run_all_autoconf.sh and should not be checked in. (Because that leads to Perforce complaints about 'clobbering'.) R=fergus DELTA=262 (0 added, 262 deleted, 0 changed) * distcc/src/config.h.in: delete 2007/12/07 12:57:55 Nils Klarlund Fix bug caused by non-idempotency of 'ln' and ensuing falsely positive test result. So, it turns out that 'ln -sf' is not idempotent. If C/D and E are directories, then ln -sf $(readlink -f C/D) E/D creates a link E/D -> realpath(C/D) and subsequent ln -sf $(readlink -f C/D) E/D creates a link C/D/D -> realpath(C/D), a self-reference of sorts. This is nasty because the second link created is in C/D, which was supposed to be just a target directory, not something to be modified! This bug enabled a faulty test to pass: the directory structure created by the non-potency bug is not cleaned on make clean. And the existence of the inserted extra directory made resolution of a certain include path possible when it should not have. R=fergus CC=manos DELTA=11 (9 added, 0 deleted, 2 changed) * include_server/Makefile.in: edit * include_server/include_analyzer_test.py: edit 2007/12/03 18:37:17 Nils Klarlund This version is to incorporate: ' Fix bug that leads to concurre' Change 2007/12/03 by Nils Klarlund R=fergus DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/12/03 16:36:06 Nils Klarlund Fix bug that leads to concurrent build interference: one distcc-pump build will severely affect another. The logic for naming the root directory was flawed: it used the pid of the parent, not the child, which is where the include server resides. Also fix less severe bug that allowed the cleaning up to end prematurely. The code is refactored at the same time -- for better readability and to address the parent/child pid confusion. The fix also includes the introduction of an additional communication mechanism, a semaphor: the child is now starting the include server and it must tell the parent that it has done so before the parent is allowed to exit. Testing: - 'make check' - Made several concurrent runs and verified that interference no longer takes place. R=fergus DELTA=65 (45 added, 1 deleted, 19 changed) * include_server/include_server.py: edit 2007/11/29 12:30:45 Nils Klarlund Add more meta-dependencies (those that involve autoconf) to the Makefile.in files and add sanity check to run_all_autoconf.sh. These dependencies should help prevent builds that do not reflect the configuration changes such as to version.sh or configure.ac. Dependencies are added, so this should be a conservative CL: making this build system less fragile. Tests: patched this CL into a clean client and rebuilt software: ./run_all_autoconf.sh ./configure --prefix=$(pwd)/installation make make install R=fergus DELTA=73 (62 added, 0 deleted, 11 changed) * Makefile.in: edit * distcc/Makefile.in: edit * include_server/Makefile.in: edit * run_all_autoconf.sh: edit 2007/11/06 15:58:38 Nils Klarlund Prepare 'pump19'. It contains: 'Add basics_test rule to include' Change 2007/11/06 12:43:59 by Nils Klarlund ' Fix typo and missing condition' Change 2007/11/06 11:51:01 by Nils Klarlund 'Fix an infinite loop in the inc' Change 2007/11/05 14:11:47 by Nils Klarlund ' Bump up length of interval tha' Change 2007/11/05 07:25:13 by Nils Klarlund ' Make the _CleanOutOthers routi' Change 2007/11/02 12:36:27 by Nils Klarlund ' Increase include server timeou' Change 2007/11/01 14:46:44 by Nils Klarlund 'Fix buglet: when the contents o' Change 2007/11/01 14:28:22 by Nils Klarlund R=fergus DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/11/06 15:43:59 Nils Klarlund Add basics_test rule to include_server/Makefile.in. This enables 'make check' to run all tests. Test: ./run_all_autoconf.sh; ./configure --prefix=$(pwd)/installation make basics_test make -C include_server basics_test make check R=fergus DELTA=4 (4 added, 0 deleted, 0 changed) * include_server/Makefile.in: edit 2007/11/06 14:51:01 Nils Klarlund Fix typo and missing conditional of a previous change, which "broke" the build. Tests: - make -C include_server check R=fergus DELTA=3 (1 added, 0 deleted, 2 changed) * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/11/05 17:11:47 Nils Klarlund Fix an infinite loop in the include server. FindNode would call itself ad infinitum prompted by unusual link structures and includes. This change is non-trivial. In particular, it relates to a previous bug fix which is rolled-back as part of the present change -- and then the problem reported in the bug report is solved instead by properly mending the code that was removed in that change. The fix consists of making the memoization removed in that change cognizant of the file directory or rather the absolute path of the file directory, see extensive new comments in class IncludeAnalyzerMemoizingNode. Small stuff: we change 'filepath' to 'fp' in all identifiers in FindNode. That's because the identifiers were otherwise getting too long in the new code. And, we used that abbreviation already. Testing: a test_DotdotInInclude test case specifically exercices the situation in the bug. [Plus additional Google-specific correctness and performance tests.] Additionally, we're now doing the test_IncludeAnalyzer in two ways: directly and through a symlink farm. This helps us test regression against subtle bugs that may occur with symbolic links. R=fergus DELTA=327 (194 added, 12 deleted, 121 changed) * include_server/cache_basics.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_analyzer_test.py: edit * include_server/test_data/dfoo/include_dotdot_foo: add * include_server/test_data/symlink_farm/abc_post.c: add * include_server/test_data/symlink_farm/abc_pre.c: add * include_server/test_data/symlink_farm/computed_includes.c: add * include_server/test_data/symlink_farm/dbar: add * include_server/test_data/symlink_farm/dfoo: add * include_server/test_data/symlink_farm/foo: add * include_server/test_data/symlink_farm/p1.h: add * include_server/test_data/symlink_farm/parse.c: add * include_server/test_data/symlink_farm/sub_farm/link_to_dotdot_dotdot_dfoo_include_dotdot_foo: add * include_server/test_data/symlink_farm/test_directory_probing.c: add * include_server/test_data/symlink_farm/test_include_next: add 2007/11/05 10:25:13 Nils Klarlund Bump up length of interval that determines when SIGALRM is raised. Testing showed that with srcfs -- which increases user time -- I/O between distcc and include server (in the C extension part) would be tripped up by SIGALRM when it is raised every 2s. This results in a Python exception such as IOError, which is wrong and even harmful, because it terminates the include server. The interval in the currently released version is 3s, so 4s is better. This is to be followed up by CL that makes the algorithmic code "protected" by SIGALRM free of I/O. R=fergus DELTA=5 (4 added, 0 deleted, 1 changed) * include_server/basics.py: edit 2007/11/02 15:36:27 Nils Klarlund Make the _CleanOutOthers routine be called. Before this CL, this routine was not called at all, because a variable describing the tmp directory has not been initialized. We split the InitializeTmpDirectories function into two parts to distinguish between creation of the temporary directory and the creation of client root under it. Also, fixed bug in the glob expression. Also, don't write out warning when cleaning -- that's just bound to confuse users. Demote message to TRACE level. Also, fix basics_test.py and make sure it's called as part of 'make check'. R=fergus DELTA=97 (52 added, 17 deleted, 28 changed) * include_server/Makefile.in: edit * include_server/basics.py: edit * include_server/basics_test.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node_test.py: edit * include_server/include_analyzer_test.py: edit * include_server/include_server.py: edit * include_server/include_server_test.py: edit * include_server/parse_file_test.py: edit 2007/11/01 17:46:44 Nils Klarlund Increase include server timeout to 3.8s. We are still getting emails about the include server running out of time for gws files and many others. R=fergus DELTA=2 (0 added, 0 deleted, 2 changed) * include_server/basics.py: edit 2007/11/01 17:28:22 Nils Klarlund Fix buglet: when the contents of the file descriptor would contain percent signs the call to DEBUG would fail. R=fergus DELTA=1 (0 added, 0 deleted, 1 changed) * include_server/include_server.py: edit 2007/10/23 17:56:23 Nils Klarlund Prepare new release, pump18, changing a timing constant in include server. R=fergus CC=distcc-pump DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/10/23 17:53:40 Nils Klarlund Increase time quota introduced in a previous change for handling a request. We released pump17 10/22. One day later, it turns out that there are a cases where the include server spends more than 2s processsing a compilation unit. Here we increase the 2s to 3s. R=fergus DELTA=9 (4 added, 0 deleted, 5 changed) * include_server/basics.py: edit 2007/10/22 13:43:09 Nils Klarlund Limit the time that the includer analyzer is allowed to spend servicing a request. We use the rudimentary SIGALRM mechanism, because generally Python does not allow one thread to raise an exception in another. Experiments show that SIGALRM interferes with the use of Popen. When determining the default compiler, the include server uses Popen to invoke gcc. If the SIGALRM is raised, then it be caught in the 'select', which then aborts. Therefore, we stop the timer while the include server determines default compilers. The timeout exception is raised according to utime passed, not real time. That prevents the include server from going bananas, restarting again and again, because of NFS delays. The risk with this CL is that something else breaks in unexpected ways, perhaps a file operation, with the signaling. However, we've put the first signal to occur 2s after the start of the request. That should be more than ample time. In practice, we have not seen the include server using more than 2s per request (but this is based on limited measurements). We have also tested this change with a 1s timer. That showed the SIGALRM problem with Popen. After, we fixed that this CL seems to work fine. R=manos CC=distcc-pump DELTA=110 (89 added, 1 deleted, 20 changed) * include_server/basics.py: edit * include_server/compiler_defaults.py: edit * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/10/22 12:46:42 Nils Klarlund Make version 'pump17'. R=fergus CC=distcc-pump DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/10/22 12:39:29 Nils Klarlund Fix name of stamp file. Remove initial '.'. R=manos CC=fergus DELTA=1 (0 added, 0 deleted, 1 changed) * run_all_autoconf.sh: edit 2007/10/22 11:06:40 Fergus Henderson Partial rollback of a previous change. In particular, comment out the code to support the Objective-C file extensions and the Objective-C test case. Currently Objective-C support breaks things if you don't have an Objective-C compiler installed, even if distcc is used only to compile C/C++ code; we try to compute the default include paths for all languages at startup, and barf it if fails. Leave in place the support for "#import". It turns out that "#import" can be used in GNU C/C++ code, as a GNU extension, and some Google code makes use of this. *** Original change description *** Add support for Objective-C to distcc-pump. In particular, recognize the Objective-C file extensions (".m", ".mi") and the "#import" declaration. (#import is like #include, but never includes the same file twice. So for the distcc-pump include server, processing of #import is exactly the same as processing of #include.) Tested with "make maintainer-check" (all tests pass) and "make pump-check" (no regressions). Also added a test of Objective-C compilation. R=klarlund CC=distcc-pump APPROVED=klarlund DELTA=21 (11 added, 0 deleted, 10 changed) * distcc/test/testdistcc.py: edit * include_server/basics.py: edit 2007/10/19 16:52:44 Nils Klarlund Loosen assumption about the syntax -D options. A user had written something the include server couldn't understand. It provoked a rare internal error. The compilation did not succeed locally either. The include server must remain unfazed when confronted with weird syntax. Also, corrected comment for ParseCommandArgs. R=fergus CC=distcc-pump * include_server/include_analyzer_memoizing_node.py: edit * include_server/parse_command.py: edit * include_server/parse_command_test.py: edit 2007/10/19 16:28:57 Nils Klarlund When storing warning messages in temporary file, we are using 'print >>', which appends a newline. Then, when presenting the errors to the user, we'd also use 'print', which appends another newline. With this fix, the newline is not append the first time around (we append ','). The other use of the contents of the temporary file, in the mail sending routines, should not be affected by one less newline. R=manos CC=fergus DELTA=3 (0 added, 0 deleted, 3 changed) * include_server/include_server.py: edit 2007/10/19 10:57:39 Nils Klarlund Fix so that 'make' fails when version.sh is out of date. We remade the dependency checking in the makefile so that the need to autoreconf is expressed as a depedency on something certainly produced by autoreconf when run through our script, namely a time stamp file. R=fergus DELTA=27 (4 added, 12 deleted, 11 changed) * Makefile.in: edit * run_all_autoconf.sh: edit 2007/10/19 10:15:14 Nils Klarlund Don't send email when a file that exists cannot be read. Also, slight correction to error message. R=fergus DELTA=5 (4 added, 0 deleted, 1 changed) * include_server/parse_file.py: edit 2007/10/18 15:56:20 Fergus Henderson Fix a missing word in a comment. R=klarlund DELTA=5 (0 added, 2 deleted, 3 changed) * distcc/src/compile.c: edit 2007/10/18 11:41:46 Fergus Henderson Add support for Objective-C to distcc-pump. In particular, recognize the Objective-C file extensions (".m", ".mi") and the "#import" declaration. (#import is like #include, but never includes the same file twice. So for the distcc-pump include server, processing of #import is exactly the same as processing of #include.) Tested with "make maintainer-check" (all tests pass) and "make pump-check" (no regressions). Also added a test of Objective-C compilation. R=klarlund CC=distcc-pump APPROVED=klarlund DELTA=136 (100 added, 8 deleted, 28 changed) * distcc/test/testdistcc.py: edit * include_server/basics.py: edit * include_server/parse_command.py: edit * include_server/parse_file.py: edit 2007/10/12 14:10:36 Nils Klarlund This corrects description of the previous change. Prepare a new release, pump16. Deploy in NYC only. To be installed under 2007.10.12 in buildstatic. This release includes: 'Rather than just replacing the ' Change 2007/10/11 by Fergus Henderson 'Prevent distcc-pump from revert' Change 2007/10/11 by Nils Klarlund R=fergus CC=manos DELTA=2 (2 added, 0 deleted, 0 changed) * version.sh: edit 2007/10/12 11:30:45 Nils Klarlund Prepare a new release, pump16, to include the change "Prevent distcc-pump from reverting to local compilations". Deploy in NYC only. To be installed under 2007.10.11 in buildstatic. R=fergus CC=manos DELTA=2 (0 added, 0 deleted, 2 changed) * version.sh: edit 2007/10/11 22:06:33 Fergus Henderson Rather than just replacing the server's current working directory with the clients' current working directory, we need to replace the server's root directory with the client's root directory. This is needed because the problems with gdb arise not only from the "current working directory" field (DW_AT_comp_dir), but also with the file names (DW_AT_file_name). These file names can be absolute paths to files that are outside of the current working directory. This change is basically just a one-line fix in serve.c, but for clarity I've also changed some variable names and comments in fix_debug_info.c. R=klarlund CC=distcc-pump DELTA=36 (13 added, 0 deleted, 23 changed) * distcc/src/fix_debug_info.c: edit * distcc/src/serve.c: edit 2007/10/11 16:20:33 Nils Klarlund Prevent distcc-pump from reverting to local compilations hundreds or thousands of times. Such a situation should never occur but if it occurs, we want to fall back to distcc behavior. For example, this is desirable if the include server for reason picks up files that don't exist any more or symbolic links that changed surreptiously during the build. A typical output is shown below (where we have tampered with the include server to produce too few files). Note that ERRORs still occur in the output (from the remote server). distcc[7791] ERROR: compile third_party/pcre/pcre-7.3/pcre_globals.c on 192.168.1.137,lzo,cpp failed distcc[7791] (dcc_build_somewhere) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_globals.c' failed, retrying locally distcc[7791] Warning: failed to distribute third_party/pcre/pcre-7.3/pcre_globals.c to 192.168.1.137,lzo,cpp, running locally instead distcc[7708] (dcc_please_send_email_note_discrepancy_except_fresh_dependency) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_chartables.c' failed, retried locally and got a different result. distcc[7708] (dcc_note_discrepancy) Warning: now using plain distcc, possibly due to inconsistent file system changes during build distcc[7708] Warning: Will send an email to distcc-pump-errors@google.com distcc[7780] ERROR: compile third_party/pcre/pcre-7.3/pcre_get.c on 192.168.1.135,lzo,cpp failed distcc[7780] (dcc_build_somewhere) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_get.c' failed, retrying locally distcc[7780] Warning: failed to distribute third_party/pcre/pcre-7.3/pcre_get.c to 192.168.1.135,lzo,cpp, running locally instead distcc[7869] ERROR: compile third_party/pcre/pcre-7.3/pcre_ord2utf8.c on 192.168.1.124,lzo,cpp failed distcc[7869] (dcc_build_somewhere) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_ord2utf8.c' failed, retrying locally distcc[7869] Warning: failed to distribute third_party/pcre/pcre-7.3/pcre_ord2utf8.c to 192.168.1.124,lzo,cpp, running locally instead __________Compiling obj/gcc-4.2.1-glibc-2.2.2-piii-linux-dbg/bin/third_party/pcre/pcre-7.3/pcre_ucp_searchfuncs.c.o distcc[7780] (dcc_please_send_email_note_discrepancy_except_fresh_dependency) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_get.c' failed, retried locally and got a different result. distcc[7780] Warning: Will send an email to distcc-pump-errors@google.com distcc[7791] (dcc_please_send_email_note_discrepancy_except_fresh_dependency) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_globals.c' failed, retried locally and got a different result. distcc[7791] Warning: Will send an email to distcc-pump-errors@google.com __________Compiling obj/gcc-4.2.1-glibc-2.2.2-piii-linux-dbg/bin/third_party/pcre/pcre-7.3/pcre_valid_utf8.c.o distcc[7723] (dcc_please_send_email_note_discrepancy_except_fresh_dependency) Warning: remote compilation of 'third_party/pcre/pcre-7.3/pcre_compile.c' failed, retried locally and got a different result. distcc[7723] Warning: Will send an email to distcc-pump-errors@google.com R=fergus,manos DELTA=211 (174 added, 8 deleted, 29 changed) * distcc/src/compile.c: edit * distcc/src/compile.h: edit * distcc/src/h_compile.c: edit * distcc/test/testdistcc.py: edit 2007/10/09 12:40:31 Nils Klarlund The obvious radical approach to clearing all caches. With this CL, we run all the initialization code of the major include analyzer object. This changes passes all usual tests and some third_party tests. All to be run before release. R=fergus,manos DELTA=52 (17 added, 32 deleted, 3 changed) * include_server/cache_basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/mirror_path.py: edit 2007/10/09 12:38:53 Nils Klarlund Introduce a time analysis of source files in order to improve S/N ratio of automatically generated error emails. Currently, we send an email in situations where: -- the remote compilation fails because a file contains something bad, -- the file is changed to not contain bad stuff, and consequently the -- the local compilation succeeds. This makes it sometimes impossible for us to determine accurately from the email whether some error really occurred or whether the user changed source files during the build. We can carry out the analysis only if there is a .d file. We check each dependency descriped there. If anyone changed after the build started, then we really don't want to hear about distcc-pump errors, because dependencies shouldn't change. The generated files are exceptions. To disregard these, the distcc user may specify a glob pattern in environment variable DISTCC_EXCLUDE_FRESH_FILES defined when invoking distcc. R=fergus APPROVED=fergus,sunq DELTA=378 (362 added, 4 deleted, 12 changed) * distcc/Makefile.in: edit * distcc/configure.ac: edit * distcc/src/compile.c: edit * distcc/src/compile.h: edit * distcc/src/emaillog.c: edit * distcc/src/h_compile.c: add * distcc/test/testdistcc.py: edit * pump.in: edit 2007/10/09 12:08:14 Nils Klarlund Release pump15 to buildstatic under name 2007.10.09. To include: Fix a bug with the check to see whether /usr/lib/rpm/... The obvious radical approach to... Ensure that the build process reruns... Introduce a time analysis of source files... R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/10/08 22:56:48 Fergus Henderson Fix a bug with the check to see whether /usr/lib/rpm/find-requires has been patched to special-case the linux-gate.so dependency. The sense of the check was inverted. On my system, find-requires had been properly patched already, but build-distcc.sh was incorrectly telling me that I needed to patch it. R=klarlund CC=distcc-pump DELTA=1 (0 added, 0 deleted, 1 changed) * build-distcc.sh: edit 2007/10/08 22:49:19 Fergus Henderson Ensure that the build process reruns autoconf and autoheader. This is needed in case configure.ac has been changed since the last build. R=klarlund CC=distcc-pump DELTA=1 (1 added, 0 deleted, 0 changed) * distcc.spec: edit 2007/10/08 10:35:13 Nils Klarlund Start a new snaphost of the file system when caches are cleared as part of the stat trigger mechanism. The stat reset is supposed to mean: ``don't trust anything about previous analyses of includes.'' So files, directories, and symbolic links, as known to the include server, are all invalid. In particular, all information gathered in the client root directory is stale. (This is where we compress source file and mirror the directory and link structure of the part of the file system explored for include analysis.) With this CL, we make the client root concept generational, as indicated by a new suffix, a generation number, added to the automatically generated root name. A trigger event bumps the generation number by one. R=manos,fergus DELTA=86 (60 added, 4 deleted, 22 changed) * include_server/basics.py: edit * include_server/compress_files.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_test.py: edit * include_server/include_server.py: edit * include_server/mirror_path.py: edit 2007/10/04 18:18:18 Manos Renieris Update the init script. Major difference is the understanding of comments. R=klarlund CC=ahyun,distcc-pump DELTA=248 (25 added, 62 deleted, 161 changed) * distcc/packaging/RedHat/init.d/distcc: edit 2007/10/04 15:05:43 Fergus Henderson Tidy up the output from c_extensions_test. Also change the test so that it will die if some unreachable code is reached, rather than quietly ignoring the error condition, and avoid using the message "internal error 3" for two different errors. R=manos CC=distcc-pump APPROVED=klarlund DELTA=8 (5 added, 0 deleted, 3 changed) * include_server/Makefile.in: edit * include_server/c_extensions_test.py: edit 2007/10/04 13:25:56 Nils Klarlund Warning message clean-up. 1) Change all information printed by Debug to go to stderr. 2) When an exception is raised it should generally be reported as a new warning (as defined by Debug called with DEBUG_WARNING, so that this output is controllable), not just printed to stderr. In particular, this change makes situations not covered by the include processor (such as absolute filepaths in #include's) be reported as warnings. 3) We removed an unnecessary try/except block for totally unexpected siutations. Those are to be handled by the general except clause of the 'handler'. Fatal issues and timing information (not normally used) is still reported to stderr through print statements. R=fergus,manos DELTA=18 (0 added, 4 deleted, 14 changed) * include_server/basics.py: edit * include_server/include_server.py: edit 2007/10/04 13:06:01 Fergus Henderson Include h_fix_debug_info in the list of check_programs, so that it gets removed by "make clean". R=klarlund DELTA=1 (1 added, 0 deleted, 0 changed) * distcc/Makefile.in: edit 2007/10/04 11:37:39 Nils Klarlund If Ctrl-c is issued while the include server is running in 'handle', then an unfortunate double error message would sometimes occur, along with a stack trace. Fixed here by propagating exception to outer handler in 'Main'. [While we're at it, we change 'main' to 'Main'. There's no reason to lowercase it.] Also, we fix the situations where the exception raised in 'handle' is an internal error or the one corresponding to SIGTERM. Both situations are uncommon. And, in both cases, we raise SIGTERM for Main to catch, so that include server can be terminated without stack traces to be printed out. R=fergus,manos DELTA=6 (0 added, 0 deleted, 6 changed) * include_server/include_server.py: edit 2007/10/04 10:13:58 Fergus Henderson Set VPATH. This is needed to make things work if you run configure in a different directory than the source directory. R=klarlund CC=distcc-pump DELTA=1 (1 added, 0 deleted, 0 changed) * Makefile.in: edit 2007/10/04 01:10:42 Fergus Henderson Add the header file for a source file I added in a previous change. I had accidentally omitted this file from that CL. R=iant CC=distcc-pump APPROVED=iant DELTA=10 (10 added, 0 deleted, 0 changed) * distcc/src/fix_debug_info.h: add 2007/10/03 20:41:00 Nils Klarlund Version 14 will contain: - a server update (for .o rewriting), to be installed 10/4 in NYC - fix for include server failure to update symbolic links when clearing caches - minor changes to messages in exception circumstances - possibly, change that analyzes .d files before sending emails about discrepancies between server and client R=fergus,manos * version.sh: edit 2007/10/03 15:03:24 Nils Klarlund Add clarifying comment. R=fergus,manos APPROVED=manos DELTA=1 (1 added, 0 deleted, 0 changed) * include_server/test_data/dfoo/foo2.h: edit 2007/10/03 12:04:55 Fergus Henderson Change distcc so that it generates the correct value for the "current directory" field in the debug info. I do this by mmapping the ".o" file into memory, parsing the ELF headers to find the ".debug_info" section, and then doing a blind string search and replace in that section. This should be quite safe: although there is a remote possibility of false hits, they will only affect the debug_info section. R=iant,klarlund CC=distcc-pump APPROVED=klarlund DELTA=628 (594 added, 5 deleted, 29 changed) * distcc/Makefile.in: edit * distcc/configure.ac: edit * distcc/src/config.h.in: edit * distcc/src/fix_debug_info.c: add * distcc/src/serve.c: edit * distcc/test/testdistcc.py: edit 2007/09/28 17:52:51 Nils Klarlund Fix .d target error. This error was unfortunately introduced with a previous change, which corrected other errors and attempted to put this logic into a unit test straightjacket. R=fergus,manos DELTA=2 (0 added, 1 deleted, 1 changed) * distcc/src/dotd.c: edit * distcc/test/testdistcc.py: edit 2007/09/28 17:13:53 Nils Klarlund Prepare release of pump13 to overcome bug in yesterday's release. R=fergus,manos * version.sh: edit 2007/09/27 14:18:09 Nils Klarlund Prepare new release. R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/09/26 22:31:54 Nils Klarlund Allow globs in trigger path expressions. R=fergus,manos DELTA=101 (85 added, 0 deleted, 16 changed) * include_server/include_analyzer.py: edit * include_server/include_analyzer_test.py: edit * include_server/include_server.py: edit * pump.in: edit 2007/09/26 22:01:05 Nils Klarlund Fix parsing of -D options to allow for function-like macros. R=fergus,manos DELTA=88 (55 added, 28 deleted, 5 changed) * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_analyzer_test.py: edit * include_server/parse_file.py: edit * include_server/test_data/func_macro.c: add 2007/09/26 21:51:45 Nils Klarlund The interpretation of the # operator of CPP was incorrect because whitespace after # was not ignored. For example, # a must expand to "a" not "" a We fix this problem here. R=fergus,manos DELTA=3 (2 added, 0 deleted, 1 changed) * include_server/macro_eval.py: edit * include_server/macro_eval_test.py: edit 2007/09/21 22:57:17 Fergus Henderson Fix two compiler warnings, one of them serious: - The type of the "len" argument in a call to PyArg_ParseType("#s", &string, &len) must be "int", not "size_t". This could cause serious problems for a 64-bit architecture. - Include "distcc.h" before the other header file, so that we get the definition of 'enum dcc_protover' before it is used. R=klarlund CC=distcc-pump DELTA=4 (1 added, 2 deleted, 1 changed) * include_server/c_extensions/distcc_pump_c_extensions_module.c: edit 2007/09/21 22:56:33 Fergus Henderson When compiling the distcc code and the extension module, enable C compiler warnings ("-Wall -Wextra"), and enforce them ("-Werror"). Also make sure that we compile with "-D_GNU_SOURCE", since distcc uses that, and we need that to avoid some compiler warnings. R=klarlund CC=distcc-pump DELTA=3 (0 added, 0 deleted, 3 changed) * include_server/setup.py: edit 2007/09/21 22:56:08 Fergus Henderson Pass the "-v" (verbose) option to "autoreconf". R=klarlund DELTA=1 (0 added, 0 deleted, 1 changed) * run_all_autoconf.sh: edit 2007/09/21 13:41:36 Nils Klarlund Fix bugs in dcc_get_dotd_info that give rise to erroneous .d file names or erroneous target names in .d files. - If derived from the file name given by -o, then the suffix must be stripped before .d is appended. - If the file name ends in '.', then only "d" is appended. - If an -o name is given and the name ends in '.', then this name, not the input filename, is still to be used for the name of the .d file. - If a target is provided in DEPENDENCIES_OUTPUT, then this target must be returned -- otherwise the .d file computed on the server will be incorrect if the target happens not to be the object file. Extra: a test for the length of the string in variable extension was unnecessary. Tests: We made a unit test that exercices the function in a number of ways. Heuristics about the names of .d files, expressed as globs, are used to pinpoint the actual naming conventions used by gcc. R=manos,fergus DELTA=255 (217 added, 20 deleted, 18 changed) * distcc/Makefile.in: edit * distcc/src/dotd.c: edit * distcc/src/h_dotd.c: add * distcc/test/testdistcc.py: edit 2007/09/20 11:36:58 Nils Klarlund Fix sending of emails by include server. Avoid sending emails when translation unit could not be found or if command line is malformed. Also, fix buglet that made the previous translation unit name appear in the case of malformed command line. R=fergus,manos DELTA=6 (2 added, 0 deleted, 4 changed) * include_server/include_analyzer.py: edit * include_server/include_server_test.py: edit * include_server/parse_command.py: edit 2007/09/20 11:33:48 Nils Klarlund Prepare new release to include "Reset caches more aggressively". R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/09/20 07:54:03 Nils Klarlund Reset caches more aggressively. According to a bug report, there are uncommon build situations where distcc-pump fails. We address this by: -- Making sure to reset the cache use by the link-gathering mechanism of mirror_path in the include server. This is a real bug although probably not the culprit. -- Also monitoring 'includes/third_party/stl/third_party/stl', which is the symbolic link changed (with path-doubling) by the set symlink mechanism of the third_party/stl/BUILD file. R=fergus,manos DELTA=6 (5 added, 0 deleted, 1 changed) * include_server/include_analyzer.py: edit * include_server/mirror_path.py: edit * pump.in: edit 2007/09/18 13:03:49 Nils Klarlund Prepare 'pump10' release. This release is to correct minor issues such as interaction with ccache and the handling of command line -D options. R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/09/18 12:59:45 Nils Klarlund Correct two mistakes in the handling of filepaths: -- an elementary one in basics.py: the rstrip() function of string is functional -- a more tricky one: in an include of the form "#include ./foo.h", we must normalize the file name to 'foo.h', otherwise an infinite regression would occur if foo.h includes ./foo.h. R=fergus,manos DELTA=13 (10 added, 1 deleted, 2 changed) * include_server/basics.py: edit * include_server/cache_basics.py: edit 2007/09/17 14:51:56 Nils Klarlund Fix client to change protocol version from 3 (pump) to 2 (plain) in situations involving already preprocessed code, such as arising from ccache use, or involving certain insidious environment variables. Test: make -C distcc valgrind-check R=fergus,manos DELTA=41 (40 added, 1 deleted, 0 changed) * distcc/src/compile.c: edit 2007/09/17 13:56:56 Nils Klarlund When announcing pump installation, show the real location -- unmasked by symbolic links. R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * pump.in: edit 2007/09/17 13:26:48 Fergus Henderson Fix a bug in "pump --startup": don't print out a setting for DISTCC_HOSTS if we didn't set DISTCC_HOSTS. (Note: this is not an urgent fix, because I've made Blaze work around the bug. But worth fixing nevertheless.) R=klarlund CC=distcc-pump DELTA=3 (2 added, 0 deleted, 1 changed) * pump.in: edit 2007/09/17 12:33:21 Nils Klarlund Make 'pump' executable. R=fergus,manos DELTA=2 (1 added, 0 deleted, 1 changed) * configure.ac: edit 2007/09/17 09:48:08 Nils Klarlund Propagate symbols defined through -D options to include analyzer. This makes computed includes operable wtih values provided on the command line. Tests: 1. New tests exercise that when reissuing an analysis for the same file and with same search directories, but with a symbol definition affecting a previously computed include, the include graph is recalculated, not reused, and the new value of the symbol is used for resolving the computed include. 2. The new code was also verified to solve the problem reported in a bug report (I used a workstation in ZRH to build the actual code that cause the issue). 3. I did 'make maintainer-check'. R=fergus,manos DELTA=66 (56 added, 0 deleted, 10 changed) * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_analyzer_memoizing_node_test.py: edit * include_server/include_analyzer_test.py: edit * include_server/parse_command.py: edit * include_server/parse_command_test.py: edit 2007/09/15 21:47:49 Nils Klarlund Update a comment as per Fergus's review comment for a previous change. R=fergus,manos DELTA=3 (1 added, 0 deleted, 2 changed) * include_server/compiler_defaults.py: edit 2007/09/13 23:40:04 Nils Klarlund Introduces mechanism for monitoring the real paths that are resolved during include analysis. Invoke as --realpath_warning_re=RE. For more, see include_server.py, Usage() in this CL. This allows a user to find out which source files are actually picked out by the include analysis during the build. Such information can useful if it is suspected that include directories are wrong. TESTING: this CL passes make check and make maintainer-check. It was tested earlier on Google software as part of the discussion of this feature now found on the distcc-pump wiki. From the wiki: INCLUDE_SERVER_ARGS='--realpath_warning_re=RE' make-dbg .... makes the include server write a warning to stderr whenever a filename is resolved to a realpath (a canonicalized absolute pathname - see 'man realpath') that is matched by RE, which is a regular expression in Python syntax. For example, to find out which C/C++ files from /home/build/buildonly are used during a build of gws:gws, do: INCLUDE_SERVER_ARGS='--realpath_warning_re=/auto/buildonly' make-dbg -distcc_pump -g0 gws:gws Then, you will see messages like: WARNING include server: For translation unit 'foo/bar.cc' while processing 'foo/bar.cc' lookup of file 'baz.h' resolved to '../whatever/baz.h' whose realpath is '/auto/whatever/blah/blah/baz.h'. (Here we have formatted the message from it's one-liner original.) Note that the include server currently does not identify the header file containing the #include for which the realpath matched, but only the translation unit. Also, because of caching in the include server, a message for a particular resolution appears usually only once. Thus this analysis cannot be used to find out which files a particular compilation unit uses. R=fergus,manos DELTA=42 (40 added, 0 deleted, 2 changed) * include_server/basics.py: edit * include_server/cache_basics.py: edit * include_server/include_server.py: edit 2007/09/13 23:15:37 Nils Klarlund Introduce flag for NotCoveredError exceptions that specify whether email is to be sent or not. We use this parameter to suppress warnings that related to #include "/foo/bar.h" and similar uses. Also, clean up of some error messages (add '.'). We fix a few typos and unneeded variables (e.g.: opt_build_stat_verify), while we're looking at these files. Additionally, improve NotCovered messages by adding the file name (in most cases). Finally, introduce option --no-email to negate the default of --email in the pump script if so desired through INCLUDE_SERVER_ARGS. TESTING: This change passes 'make check' and 'make maintainer-check'. We also ran system tests and verified that occurences of #include "/foo/bar.h" now does not result in mail being generated. These tests are not part of this changelist, but contained in another change. R=manos,fergus DELTA=186 (93 added, 49 deleted, 44 changed) * include_server/basics.py: edit * include_server/cache_basics.py: edit * include_server/include_server.py: edit * include_server/include_server_test.py: edit * include_server/parse_file.py: edit 2007/09/13 18:18:25 Nils Klarlund Reorganize and extend tests: - move existing tests in include_server.py to new include_server_test.py - test the main 'handler' in include_server, including how exceptions, such as internal error, affect automated email generation R=fergus,manos DELTA=613 (374 added, 198 deleted, 41 changed) * include_server/Makefile.in: edit * include_server/include_analyzer_test.py: add * include_server/include_server_test.py: edit * include_server/test_data/contains_abs_include.c: add 2007/09/13 14:54:43 Nils Klarlund Prepare for release; bump to version 'pump9'. R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * version.sh: edit 2007/09/13 14:41:34 Nils Klarlund Remove Google crosstool specification (which made the build fail anyway). R=manos,fergus DELTA=1 (0 added, 0 deleted, 1 changed) * build-distcc.sh: edit 2007/09/13 14:38:24 Nils Klarlund Correct flawed configuration scripts and introduce configuration sanity checks. autoconfig assumes that if an .ac script has not changed then the resulting configure scripts do not need to change. This assumption is untrue because we use a shell escape. (This escape has been rewritten according to Fergus's suggestion.) Moreover, m4 caches processed files. This royally messes up things beyond and in addition to just the aforementioned problem. We fix this by using autoreconf (suggested by Fergus). It seems to address these issues. We have verified that: ./run_all_autoconf.sh; ./configure; make clean; make all works and embeds a changed version number (in version.sh) in the right places. With further CLs "Remove Google crosstool specification" and "Introduce needed cast.", it is possible to use ./build-distcc.sh to make RPM and .deb packages. R=fergus,manos DELTA=76 (36 added, 20 deleted, 20 changed) * Makefile.in: edit * configure.ac: edit * distcc/configure.ac: edit * include_server/configure.ac: edit * run_all_autoconf.sh: edit * version.sh: edit 2007/09/13 14:21:11 Nils Klarlund Introduce needed cast. This problem was detected with gcc version 4.0.3 (Ubuntu 4.0.3-1ubuntu5). R=fergus,manos DELTA=3 (2 added, 0 deleted, 1 changed) * distcc/src/stats.c: edit 2007/09/13 14:18:44 Nils Klarlund Not deleting .d files breaks the build sometimes. R=fergus,manos DELTA=4 (1 added, 0 deleted, 3 changed) * distcc/Makefile.in: edit 2007/09/12 21:08:29 Fergus Henderson Use the standard autoconf substitution process to create pump from pump.in, rather than a hand-crafted Makefile rule. R=klarlund CC=distcc-pump DELTA=16 (4 added, 6 deleted, 6 changed) * Makefile.in: edit * configure.ac: edit * pump.in: edit 2007/09/12 20:49:57 Fergus Henderson Fix a Posix conformance bug: we were passing the same fd set to select() for both the writeable fd set and the error fd set, but according to Posix (specifically The Open Group Base Specifications Issue 6, available at ), the arguments to select() are declared with the "restrict" attribute, which means they must not be aliased. Also, issue a trace message in the case when select() returns due to an error condition on the fd rather than because the fd has become writable. R=manos CC=distcc-pump DELTA=23 (18 added, 0 deleted, 5 changed) * distcc/src/io.c: edit 2007/09/12 18:57:03 Fergus Henderson Fix manual memory management bugs, and simplify the memory management a bit. dcc_set_output() was inconsistent about whether it copied its input argument or aliased it, about whether it freed the previous value in that slot. I changed the function so that it always copies the input argument, and always frees the previous value in the argv array slot that it is about to overwrite. I likewise changed dcc_set_input to copy its argument. dcc_set_output() was also inconsistent about whether or not it logged the change to the argument; I fixed that too, by always logging it. In serve.c I simplified the code and comments a little - there is no longer any aliasing going on, so the deallocation logic is simpler. R=manos CC=distcc-pump DELTA=35 (9 added, 12 deleted, 14 changed) * distcc/src/arg.c: edit * distcc/src/serve.c: edit 2007/09/12 18:51:05 Fergus Henderson Add support for running a single test case at a time, rather than running all of them. This is useful for debugging. R=manos CC=distcc-pump APPROVED=klarlund DELTA=46 (46 added, 0 deleted, 0 changed) * distcc/Makefile.in: edit * distcc/test/onetest.py: add 2007/09/12 18:48:53 Fergus Henderson Fix a timing dependence in the distcc test suite that caused the 'NoDetachDaemon_Case' test case to sometimes fail when run under valgrind. Specifically, when running the server in --no-detach mode, wait until the server starts accepting connections before running the test, rather than just waiting 0.5 seconds, which under valgrind is not always long enough. R=klarlund CC=distcc-pump DELTA=6 (3 added, 0 deleted, 3 changed) * distcc/test/testdistcc.py: edit 2007/09/12 18:47:34 Fergus Henderson Add "--startup" and "--shutdown" options to the pump script, for use by Blaze. Blaze can't use the ordinary mode of the pump script, because the Blaze server's lifetime is greater than the lifetime of the include server. R=klarlund CC=distcc-pump DELTA=181 (119 added, 12 deleted, 50 changed) * pump.in: edit 2007/09/11 13:59:25 Nils Klarlund Annul enviroment when probing for built-in include path. Fixes subtle problem reported in a bug report. R=fergus,manos DELTA=6 (3 added, 0 deleted, 3 changed) * include_server/compiler_defaults.py: edit 2007/09/11 12:37:56 Nils Klarlund Fix leftover comment from earlier fix: delete it. R=manos DELTA=3 (0 added, 3 deleted, 0 changed) * include_server/include_analyzer_memoizing_node.py: edit 2007/09/06 16:02:39 Nils Klarlund Improve mechanishm for overcoming unsoundness in build system. Change the semantics of stat_reset_triggers so that the changing of a symbolic link during the build triggers a reset of all include server caches. R=fergus,manos DELTA=57 (28 added, 1 deleted, 28 changed) * include_server/basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_server.py: edit * include_server/include_server_test.py: edit 2007/09/05 15:50:58 Fergus Henderson Make distcc warning-free: - Remove "-Wconversion" from CFLAGS; this warning was useful for writing code that had to be compatible with pre-C89 C compilers that didn't support prototypes, but that isn't needed anymore, and it causes too many spurious warnings for perfectly legitimate code. - Add "-Wno-unused" to cflags for popt/*.c; those files have a bunch of unused parameters. - Eliminate all the remaining compiler warnings. - Add "-Werror" to CFLAGS so we won't get any regressions! TESTED = make maintainer-check valgrind-check R=manos CC=distcc-pump APPROVED=manos DELTA=56 (27 added, 6 deleted, 23 changed) * distcc/Makefile.in: edit * distcc/configure.ac: edit * distcc/popt/popt.c: edit * distcc/popt/popt.h: edit * distcc/popt/popthelp.c: edit * distcc/src/bulk.c: edit * distcc/src/emaillog.c: edit * distcc/src/exec.c: edit * distcc/src/hosts.c: edit * distcc/src/include_server_if.c: edit * distcc/src/lsdistcc.c: edit * distcc/src/prefork.c: edit * distcc/src/srvnet.c: edit * distcc/src/stats.c: edit 2007/08/30 14:01:37 Manos Renieris When receiving a string, print it out. R=klarlund,fergus DELTA=2 (2 added, 0 deleted, 0 changed) * distcc/src/rpc.c: edit 2007/08/30 13:58:45 Nils Klarlund Make tracing for client print out strings that are sent, not just their lengths. R=manos DELTA=1 (0 added, 0 deleted, 1 changed) * distcc/src/rpc.c: edit 2007/08/29 21:44:15 Nils Klarlund Fix bug in include server that gives rise to the include server being unable to find the translation unit. Also, delete some unneeded variables and make the remaining ones lowercased. R=manos,fergus DELTA=86 (73 added, 0 deleted, 13 changed) * include_server/basics.py: edit * include_server/basics_test.py: add * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/08/29 21:35:45 Nils Klarlund Prepare new release. R=manos,fergus DELTA=3 (2 added, 0 deleted, 1 changed) * version.sh: edit 2007/08/28 17:56:22 Nils Klarlund Fix typos incidentally introduced in a previous change -- and fix a function that scrubs file names in a test; it didn't work with links. R=manos DELTA=10 (1 added, 0 deleted, 9 changed) * include_server/include_server.py: edit * include_server/include_server_test.py: edit 2007/08/28 17:50:46 Nils Klarlund Add test files, missing from a previous change. R=manos,fergus APPROVED=manos DELTA=1 (1 added, 0 deleted, 0 changed) * include_server/test_data/dfoo/stat_triggers.h: add * include_server/test_data/stat_triggers.c: add * include_server/test_data/stat_triggers.h: add 2007/08/28 17:47:06 Manos Renieris Observe the HAVE_SENDFILE config variable. R=klarlund DELTA=7 (6 added, 0 deleted, 1 changed) * distcc/src/bulk.c: edit 2007/08/28 16:23:43 Nils Klarlund Make a central place for defining versions. Remove various generated files from source control. R=manos,fergus DELTA=13450 (41 added, 13401 deleted, 8 changed) * INSTALL: edit * build-distcc.sh: edit * configure: delete * configure.ac: edit * distcc/configure: delete * distcc/configure.ac: edit * include_server/configure: delete * include_server/configure.ac: edit * run_all_autoconf.sh: add * version.sh: add 2007/08/28 12:41:59 Nils Klarlund New option --stat_reset_triggers. The --stat_reset_triggers argument is a list of path names. If any such path changes from non-existing to existing during the build, then all stat-related caches are cleared. A test in include_server_test.py checks that the include analysis of a file is done from scratch after a trigger path went from non-existing to existing. R=manos,fergus DELTA=229 (174 added, 44 deleted, 11 changed) * include_server/basics.py: edit * include_server/cache_basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_server.py: edit * include_server/include_server_test.py: edit * pump.in: edit 2007/08/27 14:05:26 Manos Renieris Part of a change from Nils, with a test added. This once fixes the #include"foobar" case. R=klarlund,fergus APPROVED=klarlund DELTA=5 (4 added, 0 deleted, 1 changed) * include_server/parse_file.py: edit * include_server/parse_file_test.py: edit 2007/08/27 13:56:47 Manos Renieris Part of a change from Nils. This one adds support for the -include flag. I've moved the test data and added a test for parse_command.py. R=klarlund,fergus APPROVED=klarlund DELTA=1545 (1498 added, 9 deleted, 38 changed) * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node_test.py: edit * include_server/parse_command_test.py: edit * include_server/test_data/distcc/README: add * include_server/test_data/distcc/src/bulk.h: add * include_server/test_data/distcc/src/compile.h: add * include_server/test_data/distcc/src/config.h: add * include_server/test_data/distcc/src/distcc.c: add * include_server/test_data/distcc/src/distcc.h: add * include_server/test_data/distcc/src/emaillog.h: add * include_server/test_data/distcc/src/exitcode.h: add * include_server/test_data/distcc/src/hosts.h: add * include_server/test_data/distcc/src/implicit.h: add * include_server/test_data/distcc/src/include_me.h: add * include_server/test_data/distcc/src/state.h: add * include_server/test_data/distcc/src/trace.h: add * include_server/test_data/distcc/src/util.h: add 2007/08/27 13:05:08 Manos Renieris Report the client ip if we refuse a connection. R=dkegel,klarlund,fergus CC=ahyun DELTA=14 (7 added, 1 deleted, 6 changed) * distcc/src/srvnet.c: edit 2007/08/20 13:21:57 Manos Renieris Add include_analyzer_memoizing_node_test to the list of tests. R=klarlund,fergus DELTA=2 (1 added, 0 deleted, 1 changed) * include_server/Makefile.in: edit 2007/08/20 12:00:47 Manos Renieris Minimize the output during tests; it obscures the test results. R=klarlund,fergus APPROVED=klarlund DELTA=22 (1 added, 1 deleted, 20 changed) * include_server/c_extensions_test.py: edit * include_server/include_server_test.py: edit * include_server/macro_eval_test.py: edit 2007/08/10 11:21:02 Nils Klarlund Fix a bug: memoization in the central FindNode algorithm was too optimistic. R=fergus,manos DELTA=20 (0 added, 20 deleted, 0 changed) * include_server/include_analyzer_memoizing_node.py: edit 2007/08/08 17:42:57 Nils Klarlund Make include server not write a stack trace when the exception is NotCovered. Such a situation is not bad. Also, remove a couple of unnecessary imports. R=manos,fergus DELTA=19 (5 added, 4 deleted, 10 changed) * include_server/include_server.py: edit 2007/08/08 15:22:54 Nils Klarlund More missing test files. This time for computed includes. R=fergus,manos APPROVED=manos DELTA=21 (21 added, 0 deleted, 0 changed) * include_server/test_data/test_computed_includes/helper.c: add * include_server/test_data/test_computed_includes/incl.h: add * include_server/test_data/test_computed_includes/inclA.h: add * include_server/test_data/test_computed_includes/src.c: add * include_server/test_data/test_computed_includes/srcA.c: add 2007/08/08 00:58:27 Nils Klarlund Fix the problem that stat's in the main 'Resolve' routine of cache_basics were based on os.path.exists, not on os.path.isfile. Write new test to verify that the behavior is now correct. Fix little problem in compress_files.py R=fergus,manos APPROVED=fergus,manos DELTA=88 (66 added, 0 deleted, 22 changed) * include_server/c_extensions/distcc_pump_c_extensions_module.c: edit * include_server/c_extensions_test.py: edit * include_server/cache_basics.py: edit * include_server/compress_files.py: edit * include_server/include_server_test.py: edit * include_server/test_data/dfoo/i_am_perhaps_a_directory.h: add * include_server/test_data/i_am_perhaps_a_directory.h/empty_file: add * include_server/test_data/test_directory_probing.c: add 2007/08/07 23:06:24 Nils Klarlund 'make test' was failing --- this CL fixes that. R=fergus,manos DELTA=1 (1 added, 0 deleted, 0 changed) * include_server/setup.py: edit 2007/08/07 23:06:00 Nils Klarlund Make release subversion = pump6. R=fergus,manos DELTA=31 (0 added, 0 deleted, 31 changed) * build-distcc.sh: edit * configure: edit * configure.ac: edit * distcc/configure: edit * distcc/configure.ac: edit * include_server/configure: edit * include_server/configure.ac: edit 2007/08/07 16:26:27 Manos Renieris a) Include the server side error messages in the maintainer email b) Don't output them on the screen. R=fergus,klarlund DELTA=116 (107 added, 1 deleted, 8 changed) * distcc/src/bulk.c: edit * distcc/src/bulk.h: edit * distcc/src/clirpc.c: edit * distcc/src/compile.c: edit * distcc/src/compile.h: edit * distcc/src/distcc.h: edit * distcc/src/emaillog.c: edit * distcc/src/emaillog.h: edit * distcc/src/remote.c: edit 2007/08/07 16:20:57 Manos Renieris For testing purposes, add a way to stub out the include server. R=fergus,klarlund DELTA=73 (72 added, 1 deleted, 0 changed) * distcc/src/include_server_if.c: edit * distcc/src/util.c: edit * distcc/src/util.h: edit 2007/08/06 23:07:25 Nils Klarlund Reintroduced 'introspection' so that an installed package can be moved from say buildstaticrw to buildstatic with all references to executables moving along. Added overide mechanism as well. Also, introduced a necessary check when running off source directory so see whether there's more than on .so file. Finally, changed messages so that we're printing a message that the include server has started instead of one indicating that is starting. R=fergus,manos DELTA=74 (52 added, 9 deleted, 13 changed) * Makefile.in: edit * pump.in: edit 2007/08/06 21:56:31 Nils Klarlund Various minor changes in response to comment by Fergus for a previous change. R=fergus DELTA=12 (3 added, 0 deleted, 9 changed) * include_server/include_server.py: edit 2007/08/06 14:29:44 Nils Klarlund Check that /dev/shm is actually writable and executable. Also, correct two very, very minor mistakes. R=fergus,manos DELTA=14 (4 added, 1 deleted, 9 changed) * include_server/basics.py: edit * include_server/compress_files.py: edit * include_server/include_server.py: edit 2007/08/02 16:15:06 Nils Klarlund Add email notifications from include server. Delete email notifications from distcc client when caused by include server providing an error indication. Features: - new command line flags for enabling emails for exception conditions - a limit on the number of emails sent due to NotCovered exception - stack trace is included Testing: - tested new commnand line arguments - tested for each of the three exception handlers where email is sent that email is indeed being sent - 'make test' for include_server R=fergus,manos DELTA=106 (86 added, 2 deleted, 18 changed) * distcc/src/compile.c: edit * include_server/basics.py: edit * include_server/include_server.py: edit * pump.in: edit 2007/08/02 14:40:27 Nils Klarlund Add option -t or --time for total time spent in include server to be printed on stderr. Example: Include server timing. Elapsed: 18.2s User: 0.1s System: 0.0s Total: 0.1s R=fergus,manos DELTA=47 (32 added, 0 deleted, 15 changed) * include_server/basics.py: edit * include_server/include_server.py: edit 2007/08/01 17:33:50 Nils Klarlund Make the handling of computed includes sound. Upto now, the include server failed to reprocess a file F with the property: - F transitively includes a file G - G contains a computed include and the support of its expression contains a symbol X - X is defined or redefined after G is processed the first time We hope to compile OpenOffice with this fix. Little things: - Fixed include_analyzer_memoizing_node_test.py to allow regression test for distcc itself to pass. - Removed dead code EvalExprDirs in include_analyzer.py. Correctness testing: - In include_server: 'make test' works. - Function test_AdvancedComputedIncludes is added in 'include_server/include_server_test.py'. It contains the basic scenario we are correcting for. - We ran multiple tests 'make-dbg -r -j80 third_party/lzo'; every test succeeded. These did not succeed with existing version. - We built gws:gws and localsearch/mustang Performance testing: For make-dbg gws:gws -g0, the best time before the change: make-dbg real 7m44.230s user 7m0.494s sys 2m25.385s Include server Elapsed: 463.9s User: 72.5s System: 37.3s Total: 109.9s The best time after: make-dbg real 7m44.772s user 6m46.249s sys 2m2.944s Include server Elapsed: 464.6s User: 87.4s System: 36.9s User + System: 124.3s Thus, it seems that we've added 15s or about 8% to the include server time. (These times are on a hyperthreaded machine and therefore hard to interpret.) Remarks: the central algorithm still is in the need of refactoring. That 8% running time was added because of the current change adds to my impression that the refactoring must be done with care. R=fergus,manos DELTA=316 (237 added, 25 deleted, 54 changed) * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_analyzer_memoizing_node_test.py: edit * include_server/include_server_test.py: edit * include_server/macro_eval.py: edit * include_server/macro_eval_test.py: edit * include_server/parse_file.py: edit 2007/07/30 17:10:04 Manos Renieris Bump up the release number. R=klarlund,fergus DELTA=1 (0 added, 0 deleted, 1 changed) * build-distcc.sh: edit 2007/07/27 20:23:30 Manos Renieris Push declaration to the top of block so that it's more portable. TBR=klarlund,fergus DELTA=4 (2 added, 2 deleted, 0 changed) * distcc/src/compile.c: edit * distcc/src/serve.c: edit 2007/07/27 19:40:59 Manos Renieris Respect the second part of the DEPENDENCIES_OUTPUT env variable. R=fergus,klarlund DELTA=79 (65 added, 5 deleted, 9 changed) * distcc/src/compile.c: edit * distcc/src/distcc.h: edit * distcc/src/dotd.c: edit * distcc/src/dotd.h: edit * distcc/src/serve.c: edit 2007/07/27 09:09:53 Nils Klarlund This file went MIA. This CL will make 'make -C include_server test' pass. R=fergus,manos DELTA=14 (14 added, 0 deleted, 0 changed) * include_server/test_data/more_macros.c: add 2007/07/26 21:25:25 Manos Renieris Print the protocol description even if opt_numeric is true. R=fergus,klarlund DELTA=4 (1 added, 0 deleted, 3 changed) * distcc/src/lsdistcc.c: edit 2007/07/26 15:39:00 Manos Renieris Explicitly rewrite the .d file dependency on the server; -MT does not work quite as advertised (see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12448): gcc adds the argument of -MT to the list of object files in the dependencies, rather than replacing the default object file name with the argument of -MT; dotd does not tolerate two object files in the .d file. R=fergus,klarlund DELTA=71 (59 added, 5 deleted, 7 changed) * distcc/src/compile.c: edit * distcc/src/dotd.c: edit * distcc/src/dotd.h: edit * distcc/src/serve.c: edit 2007/07/26 15:07:34 Fergus Henderson Add -Wuninitialized to CFLAGS. TESTED= Ran "autoconf && configure && make clean && make" and verified that no new warnings were generated. R=manos CC=distcc-pump DELTA=2 (2 added, 0 deleted, 0 changed) * distcc/configure: edit * distcc/configure.ac: edit 2007/07/25 11:28:33 Manos Renieris Don't output the statistics for the doti file if there is no doti file. R=fergus,klarlund DELTA=1 (0 added, 0 deleted, 1 changed) * distcc/src/remote.c: edit 2007/07/25 11:26:03 Manos Renieris Fix a (serious) bug. sets_dotd was not initialized, and we were not rewritting the dependency in the .d file. R=fergus,klarlund DELTA=2 (1 added, 0 deleted, 1 changed) * distcc/src/compile.c: edit * distcc/src/dotd.c: edit 2007/07/24 17:33:23 Manos Renieris Always close the file descriptors after communicating with the server, regardless of how soon we bail out. R=fergus,klarlund DELTA=19 (9 added, 9 deleted, 1 changed) * distcc/src/remote.c: edit 2007/07/18 19:49:54 Manos Renieris Don't try to send the preprocessed file to the server if the local preprocessing failed. Otherwise, either the file sent to the server is wrong, or it does not exist at all. In the first case, the result of the compilation is wrong. In the second, trying to send an existing file is considered a communication or remote error, and we end up thinking that the remote host is down or in some other way unresponsive. Under the current fallback mode, this ends up printing the erro messages from local preprocessing twice, once while its trying to preprocess the file to send it to the server, and once while trying to compile locally. I think that's ok. R=fergus,klarlund DELTA=3 (3 added, 0 deleted, 0 changed) * distcc/src/remote.c: edit 2007/07/18 16:21:35 Manos Renieris Added some notes on the implementation of protocol version 3. R=fergus,klarlund DELTA=61 (61 added, 0 deleted, 0 changed) * distcc/doc/protocol-3-impl.txt: add 2007/07/13 14:22:13 Manos Renieris Tiny change to use the phony feature directly for the pump target. R=klarlund,fergus DELTA=5 (1 added, 3 deleted, 1 changed) * Makefile.in: edit 2007/07/12 15:17:54 Nils Klarlund Addressing Fergus's comments for a previous change + more changes. R=fergus,manos DELTA=45 (27 added, 6 deleted, 12 changed) * README: edit 2007/07/10 17:18:31 Manos Renieris Added a description for protocol version 3. R=klarlund,fergus DELTA=82 (82 added, 0 deleted, 0 changed) * distcc/doc/protocol-3.txt: add 2007/07/09 16:01:36 Nils Klarlund New subversion number for packages. R=fergus,manos DELTA=1 (0 added, 0 deleted, 1 changed) * build-distcc.sh: edit 2007/07/09 13:50:11 Nils Klarlund When using --verbose, the variable denoting the option level is not touched. So, --verbose is not equivalent to setting the option level to 'debug' as the manual says. This is fixed. R=fergus,manos DELTA=1 (1 added, 0 deleted, 0 changed) * distcc/src/dopt.c: edit 2007/07/09 13:41:11 Nils Klarlund Simplify memory allocation strategy in dcc_run_job. Tests: 'make valgrind-check'. R=fergus,manos DELTA=22 (9 added, 3 deleted, 10 changed) * distcc/src/serve.c: edit 2007/07/05 14:38:09 Nils Klarlund Fix server and include server to allow absolute translation unit. I refactored a bit to cut down the length of dcc_run_job (which is still too long). TESTING: I have verified that regexp-options.cc now compiles on pump server. I have compiled several hundred other files. Also, I verified that 'make valgrind-check' passes. Note: a problem occurred in an lsdistcc test. The output from lsdistcc was not in the expected order. I changed the test to sort the output before the comparison. R=fergus,manos DELTA=241 (145 added, 76 deleted, 20 changed) * distcc/src/serve.c: edit * distcc/test/testdistcc.py: edit * include_server/include_analyzer.py: edit 2007/06/29 15:19:42 Nils Klarlund Fix email address in comments and code by introducing an abstraction. R=fergus,manos DELTA=7 (1 added, 0 deleted, 6 changed) * distcc/src/compile.c: edit * distcc/src/emaillog.c: edit * distcc/src/emaillog.h: edit 2007/06/29 15:15:39 Nils Klarlund Fix problem that a stack trace was produced for Ctrl-C. In particular, we discovered that printing out args[0] of the instance object is not wise, because an index error may ensue. R=fergus,manos DELTA=20 (9 added, 5 deleted, 6 changed) * include_server/include_server.py: edit 2007/06/28 18:30:54 Nils Klarlund Remove offensive code. I'm now handling configuring of pump in an auxiliary script, also called 'pump'. R=fergus,manos DELTA=11 (0 added, 8 deleted, 3 changed) * Makefile.in: edit * pump.in: edit 2007/06/28 15:51:09 Manos Renieris Change the address we send errors to. R=fergus,klarlund DELTA=1 (0 added, 0 deleted, 1 changed) * distcc/src/emaillog.c: edit 2007/06/26 22:03:23 Manos Renieris Added -Pprotocol option, which will print out only the servers that support (at least) the given protocol. lsdistcc wll now print the protocol type out with the host i.e. host.domain.com,lzo. R=fergus,klarlund CC=distcc-pump DELTA=134 (116 added, 9 deleted, 9 changed) * distcc/Makefile.in: edit * distcc/src/lsdistcc.c: edit 2007/06/21 17:45:39 Manos Renieris Tell the user why they are seeing error messages twice. R=fergus,klarlund DELTA=3 (2 added, 0 deleted, 1 changed) * distcc/src/compile.c: edit 2007/06/21 16:40:25 Manos Renieris Forgot emaillog.h. Oops! R=fergus,klarlund DELTA=8 (8 added, 0 deleted, 0 changed) * distcc/src/emaillog.h: add 2007/06/21 13:04:17 Manos Renieris Add email logging. R=klarlund,fergus DELTA=170 (137 added, 15 deleted, 18 changed) * distcc/Makefile.in: edit * distcc/src/compile.c: edit * distcc/src/distcc.c: edit * distcc/src/emaillog.c: add * distcc/src/trace.c: edit * distcc/src/traceenv.c: edit 2007/06/20 16:10:59 Nils Klarlund Fix spelling error in Makefile.in, bump-up subversion number. R=fergus,manos DELTA=2 (0 added, 0 deleted, 2 changed) * build-distcc.sh: edit * include_server/Makefile.in: edit 2007/06/20 15:36:43 Nils Klarlund Further enviroment variables for controlling behavior of include server when invoked through pump. Also, we fixed the problem that for the common situation that configure is run in the top level directory of the source tree it was impossible to run 'pump'. The solution is to regard the script alteration by the Makefile rule for 'pump' something that regards mainly the installed version. The source tree version of pump finds its Python files in the source directory and its .so file under the 'build/lib.xxx/include_server' subdirectory of th scr directory. Finally, we took out the hardcoding for values of the potential distcc servers. When the make rule for 'pump' is run, the environment variable DISTCC_POTENTIAL_HOSTS with its current value is copied into 'pump' -- if it is set. So, now I prepare distribution by doing: DISTCC_POTENTIAL_HOSTS="test-distcc1.ame test-distcc2.ame test-distcc3.ame test-distcc4.ame test-distcc5.ame pump1.ame pump2.ame pump3.ame pump4.ame pump5.ame pump6.ame pump7.ame pump8.ame pump9.ame distcc1" make pump This also of course makes the 'pump' script work in the source directory, where it'll now pick up the servers I specified for the ad hoc and regression tests I run. With this machinery, I was again able to easily test the other pending changelists for the include server. * Makefile.in: edit * pump.in: edit 2007/06/20 01:38:51 Fergus Henderson When aborting, make sure we exit with a non-zero exit status. TBR=klarlund * include_server/include_server.py: edit 2007/06/19 23:44:15 Nils Klarlund Fix the problem that source was nuked by 'make clean'. R=manos,fergus DELTA=6 (0 added, 1 deleted, 5 changed) * include_server/Makefile.in: edit 2007/06/19 23:41:55 Nils Klarlund Reapplying after rollback. Make --verify mode work with the include server and improve error reporting. An internal error would now look like: WARNING: Preprocessing locally. Include server internal error: 'exceptions.TypeError: expected string or buffer' for translation unit 'maps/frontend/geocode_api_renderer.cc' We also fix a bug regarding TERM signal that would not properly terminate an include server. R=fergus,manos DELTA=58 (38 added, 2 deleted, 18 changed) * include_server/cache_basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/06/19 23:39:46 Nils Klarlund We fix several bugs in the include server. - The macro evaluator has been completely rewritten. In particular, it can now be used to parse files in maps/frontend that involve computed includes like: #include MAPS_TEMPLATE_VARNAMES(map_kml_results) - We also now parse macro calls on arguments that contain macro calls. - We implement the 'disabled' semantics of macro invocation (for infinite recursion prevention). - We now apply # and ## only as part of expanding function-like macros. - We added several new tests, in part taken from the CPP Internals document. - A test for ResolveExpr with pedagodical value has been added (and another file for this test to work). - The macro evaluator has been thouroughly commented. - The parser has been updated so that it no longer thinks that '//' within a filepath is a C++ comment. - The parser's handling of macro calls (and definitions) was improved. Note that we now only use the parser's understanding of macros for function-like defines, not for macro invocations, which are treated in a new routine in macro_eval. R=fergus,manos DELTA=531 (373 added, 68 deleted, 90 changed) * include_server/macro_eval.py: edit * include_server/macro_eval_test.py: edit * include_server/parse_file.py: edit * include_server/parse_file_test.py: edit * include_server/test_data/maps/foo.tpl.varnames.h: add * include_server/test_data/parse.c: edit 2007/06/19 13:27:49 Manos Renieris Update the rpm prefix to be /usr, because that's where the init.d scripts expect it. R=klarlund,fergus DELTA=4 (0 added, 0 deleted, 4 changed) * distcc.spec: edit 2007/06/18 23:10:26 Fergus Henderson Give better error messages in cases where we can't determine the compiler's default search path(s). Also don't try to terminate the include server in those cases (it wasn't actually terminating anyway, since the sys.exit() exception was being caught by the SocketServer class, I think). R=karlund CC=distcc-pump DELTA=17 (9 added, 0 deleted, 8 changed) * include_server/compiler_defaults.py: edit 2007/06/15 15:07:45 Fergus Henderson Another change towards getting "make check" working again. TBR=manos * include_server/Makefile.in: edit 2007/06/15 14:58:27 Fergus Henderson Make the "pump" target depend on the "Makefile" target, so that it gets rebuilt if you configure with a different prefix. This is in response to manos' verbal post-submit review comments on a previous change. TBR=manos * Makefile.in: edit 2007/06/15 14:52:08 Nils Klarlund This CL was submitted too early. Automated g4 rollback of a previous change: Make --verify mode work with the include server and improve error reporting. An internal error would now look like: WARNING: Preprocessing locally. Include server internal error: 'exceptions.TypeError: expected string or buffer' for translation unit 'maps/frontend/geocode_api_renderer.cc' We fix a bug regarding TERM signal that would not properly terminate an include server. * include_server/cache_basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/06/15 14:35:39 Fergus Henderson Fix bugs with the generation of the "pump" script from "pump.in": - $ was not properly escaped and was being interpreted by Make rather than the shell - the pump.in script that is being copied could be read-only and we did not (a) remove the old read-only copy nor (b) make the new copy writable. - pump should be a real target, not a phony target - we need a dependency "all: pump" P.S. After syncing this change, you need to run "autoconf" (or sync Manos' change which updated the configure script), "configure", and then "make". TBR=manos CC=distcc-pump DELTA=5 (1 added, 0 deleted, 4 changed) * Makefile.in: edit 2007/06/15 14:33:52 Fergus Henderson Temporary work-around for problem where "make clean" nukes the source tree. TBR=manos,klarlund * include_server/Makefile.in: edit 2007/06/15 14:26:45 Fergus Henderson Add support for running tests in lzo mode or in pump mode. R=manos CC=distcc-pump DELTA=38 (27 added, 2 deleted, 9 changed) * distcc/Makefile.in: edit * distcc/test/testdistcc.py: edit 2007/06/15 13:34:48 Manos Renieris Update the configure script. Remove pump, which is now generated by make. R=klarlund,fergus DELTA=272 (52 added, 219 deleted, 1 changed) * configure: edit * pump: delete 2007/06/15 07:13:52 Nils Klarlund Fix file permission to +x. R=manos * build-distcc.sh: edit 2007/06/14 22:51:35 Nils Klarlund Make --verify mode work with the include server and improve error reporting. An internal error would now look like: WARNING: Preprocessing locally. Include server internal error: 'exceptions.TypeError: expected string or buffer' for translation unit 'maps/frontend/geocode_api_renderer.cc' We fix a bug regarding TERM signal that would not properly terminate an include server. R=fergus,manos * include_server/cache_basics.py: edit * include_server/include_analyzer.py: edit * include_server/include_server.py: edit 2007/06/14 17:21:22 Manos Renieris Script and spec file for building rpm. R=fergus,klarlund DELTA=490 (490 added, 0 deleted, 0 changed) * build-distcc.sh: add * distcc.spec: add 2007/06/14 16:10:47 Manos Renieris Add DESTDIR so that rpm building can find the pump script. R=fergus,klarlund DELTA=6 (3 added, 0 deleted, 3 changed) * Makefile.in: edit 2007/06/14 14:06:05 Manos Renieris Revamp the configure/make/make install process: - the python building and installation is done by setup.py. - include_server is now a python package. - include_server/c_extensions is not buildable by itself anymore. - include_server tests are build into their own directory. - the pump script is "finished" at make time, before install. - run.py is not needed anymore R=fergus,klarlund DELTA=633 (456 added, 147 deleted, 30 changed) * Makefile.in: edit * configure.ac: edit * distcc/configure: edit * distcc/configure.ac: edit * include_server/Makefile.in: edit * include_server/__init__.py: add * include_server/c_extensions/Makefile.in: delete * include_server/c_extensions/setup.py: delete * include_server/c_extensions_test.py: edit * include_server/configure: edit * include_server/configure.ac: edit * include_server/setup.py: add * pump.in: add 2007/06/11 16:30:54 Nils Klarlund Improving start-up time. It turns out that the include server is not the bottleneck -- it's about 200ms to start it. But lsdistcc is. So with change I'm just trying to save that amount of time by starting the include server while doing lsdistcc. R=fergus,manos DELTA=106 (70 added, 2 deleted, 34 changed) * pump: edit 2007/06/11 16:22:37 Nils Klarlund Fix "ERROR: failed to connect to UNIX-DOMAIN /dev/shm/include-server: Resource temporarily unavailable". The former assignment to server.request_queue_size was ineffectual because this parameter is used by the constructor for a server. The parameter is passed to socket.listen. R=manos,fergus DELTA=22 (17 added, 2 deleted, 3 changed) * include_server/include_server.py: edit 2007/06/08 18:15:16 Fergus Henderson Some minor fixes to avoid warnings from gcc. Also a small bug fix: when cleanup_tempfiles is invoked from a signal handler, we should not call free(), because it is unsafe to call free() from an asynchronous signal handler that could be executed in the middle of another call to malloc() or free(). Also fix the use of volatile in cleanup_tempfiles. R=manos CC=distcc-pump DELTA=87 (42 added, 16 deleted, 29 changed) * distcc/src/cleanup.c: edit * distcc/src/distcc.c: edit * distcc/src/distcc.h: edit * distcc/src/dsignal.c: edit * distcc/src/trace.c: edit * distcc/src/util.c: edit 2007/06/08 17:52:40 Fergus Henderson Allow ".i" and ".ii" file names as inputs to the include server. Also some improvements to the messages produced by the include server. R=klarlund CC=distcc-pump DELTA=26 (11 added, 7 deleted, 8 changed) * include_server/basics.py: edit * include_server/include_server.py: edit * include_server/parse_command.py: edit * include_server/parse_file.py: edit * include_server/run.py: edit 2007/06/08 16:40:16 Nils Klarlund Improve warning messages regarding include server failures. R=fergus,manos DELTA=3 (2 added, 0 deleted, 1 changed) * distcc/src/compile.c: edit * distcc/src/include_server_if.c: edit 2007/06/07 21:41:25 Manos Renieris Put all declarations before executable code, for compatibility with older C compilers. R=fergus,klarlund DELTA=15 (6 added, 7 deleted, 2 changed) * distcc/src/clirpc.c: edit * distcc/src/include_server_if.c: edit * distcc/src/srvrpc.c: edit * include_server/c_extensions/distcc_pump_c_extensions_module.c: edit 2007/06/07 15:47:57 Nils Klarlund Check that execution of gcc to find defaults succeeds and warns appropriately if not. R=fergus,manos DELTA=17 (11 added, 5 deleted, 1 changed) * include_server/compiler_defaults.py: edit 2007/06/07 15:41:55 Nils Klarlund Fixed bugs from the autoconf conversions. Now, the include server extension builds. R=fergus,manos DELTA=8 (0 added, 3 deleted, 5 changed) * distcc/Makefile.in: edit * include_server/c_extensions/setup.py: edit 2007/06/05 14:50:22 Nils Klarlund Fixes: so that we can find the include server, also in installation. Note that we erase previous value of PYTHONPATH for performance reasons. R=fergus DELTA=137 (91 added, 23 deleted, 23 changed) * include_server/run.py: edit * pump: edit 2007/06/04 17:46:36 Nils Klarlund This is to repair a previous change, which I submitted by mistake. This CL together with the previous CL fix bugs: - check that include_server_pid exists before killing it - don't strip \n before stuffing hosts into temporary variable Also fixes a couple of minor syntax issues in comments. R=manos,fergus DELTA=4 (1 added, 0 deleted, 3 changed) * pump: edit 2007/06/04 16:04:51 Fergus Henderson Fix a bug where we were attempting to use memory that had already been freed. (I detected this by running the tests under valgrind.) R=manos CC=distcc-pump DELTA=19 (13 added, 0 deleted, 6 changed) * distcc/src/serve.c: edit 2007/06/04 14:53:03 Nils Klarlund Fixed bug: 'opts' were appended to only last host. Fixed very minor syntax issues in comments. * pump: edit 2007/06/04 14:32:33 Fergus Henderson 1. Use srcdir rather than top_srcdir to locate the mkinstalldirs script; now that distcc_pump has its own autoconf-generated configure script, top_srcdir is now "distcc_pump" rather than "distcc". 2. Add USE_VALGRIND variable, and use it in the maintainer-check rule, so that you can do 'make USE_VALGRIND=--valgrind" maintainer-check' to run the tests under valgrind. R=manos CC=distcc-pump DELTA=7 (5 added, 0 deleted, 2 changed) * distcc/Makefile.in: edit 2007/06/04 13:43:00 Manos Renieris Make lsdistcc 80 columns wide. R=klarlund,fergus DELTA=199 (113 added, 5 deleted, 81 changed) * distcc/src/lsdistcc.c: edit 2007/06/04 11:40:08 Fergus Henderson Add support for running tests under valgrind. R=manos CC=distcc-pump DELTA=108 (59 added, 3 deleted, 46 changed) * distcc/test/testdistcc.py: edit 2007/06/04 11:31:24 Fergus Henderson Add "install" targets to the makefiles. Use autoconf-generated configure scripts, in order to support the standard configure options such as '--prefix', etc. R=klarlund CC=distcc-pump DELTA=4959 (4816 added, 110 deleted, 33 changed) * Makefile: delete * Makefile.in: add * configure: edit * configure.ac: add * include_server/Makefile: delete * include_server/Makefile.in: add * include_server/c_extensions/Makefile: delete * include_server/c_extensions/Makefile.in: add * include_server/configure: add * include_server/configure.ac: add 2007/06/04 11:20:11 Fergus Henderson Rewrite the pump script using functions. Use lowercase names for shell variables that are local to this process. Document the DISTCC_PUMP_LOCATION environment variable in the usage message. Ensure error messages go to stderr rather than stdout. Fix some problems with the cleanup: the order of cleanup was wrong. It was doing "rmdir $SOCKET_DIR" before "rm $SOCKET", which meant the rmdir could fail since the directory isn't empty yet. Check for "lsdistcc" in the same directory as "pump", if it isn't found in the "distcc" subdirectory. R=klarlund CC=manos,distcc-pump DELTA=197 (119 added, 51 deleted, 27 changed) * pump: edit 2007/06/04 00:27:53 Fergus Henderson Use gcc's automatic dependency generation. Without this change, the Makefile was missing dependencies on all the header files, so editing say src/distcc.h and then running "make" would not cause a recompile. R=manos CC=distcc-pump DELTA=5 (3 added, 0 deleted, 2 changed) * distcc/Makefile.in: edit * distcc/configure: edit * distcc/configure.ac: edit 2007/06/01 19:24:28 Nils Klarlund Handshake mechanism for starting include server. Introduce os.fork() in include server, so that the parent returns right after starting the child. The child becomes the real include server. Change options so as to allow the parent to write the child pid to a file. That will allow an invoking script to send SIGTERM to the include server later. Fix missing deletion of temp file in include_server. Also, fixed bug: the initialization of the temp directory was done twice, from two different modules. R=fergus,manos DELTA=168 (85 added, 8 deleted, 75 changed) * include_server/basics.py: edit * include_server/include_server.py: edit * pump: edit 2007/06/01 19:06:50 Nils Klarlund Change file permission to +x. * distcc/contrib/distccd-on-servers: edit 2007/06/01 19:04:28 Nils Klarlund New tests for include analyzer; corrections to DirNameCache. DirnameCache was hardcoded to return absolute directories -- that was wrong. Also, define helper function RetrieveDirectoriesExceptSys in cache_basic for test purposes. Make _CalculateIncludeClosureExceptSystem call Fillcache so as to avoid prerequisite condition. Fix missing deletion of temp file in include_server. Fix another couple of minor bugs. R=fergus,manos DELTA=331 (266 added, 21 deleted, 44 changed) * include_server/Makefile: edit * include_server/cache_basics.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_analyzer_memoizing_node_test.py: add * include_server/include_server_test.py: edit * include_server/parse_command_test.py: edit * include_server/run.py: edit 2007/06/01 15:48:51 Nils Klarlund Fixes bug so that 'status' works as intended. Also fixes bugs that meant that the return command was given a non-integer argument. R=fergus,manos DELTA=17 (3 added, 0 deleted, 14 changed) * distcc/contrib/distccd-on-servers: edit 2007/06/01 13:22:00 Manos Renieris Plug memory leaks in the server. R=klarlund,fergus CC=distcc-pump DELTA=111 (54 added, 26 deleted, 31 changed) * distcc/src/arg.c: edit * distcc/src/serve.c: edit * distcc/src/srvrpc.c: edit 2007/05/31 20:26:35 Nils Klarlund Initial submission: script for handling distccd on servers. R=fergus,manos DELTA=142 (142 added, 0 deleted, 0 changed) * distcc/contrib/distccd-on-servers: add 2007/05/31 19:14:53 Fergus Henderson Change the distcc_pump Makefile and configure script to support building with the build directory being different than the source directory, e.g. mkdir obj cd obj ../configure make R=klarlund CC=distcc-pump DELTA=144 (91 added, 14 deleted, 39 changed) * INSTALL: edit * Makefile: edit * configure: edit * distcc/Makefile.in: edit * include_server/Makefile: edit * include_server/c_extensions/Makefile: edit * include_server/c_extensions/setup.py: edit * include_server/run.py: edit 2007/05/31 15:32:41 Manos Renieris Retry connecting if we get EAGAIN. R=klarlund,fergus DELTA=5 (4 added, 0 deleted, 1 changed) * distcc/src/clinet.c: edit 2007/05/30 20:13:37 Nils Klarlund Continuing "Continuing cleanup of the code...", we fix various tiny buglets and wipe unnecessary variables from mirror-path. TESTED=(cd include_closure; make test) R=fergus CC=csilvers DELTA=24 (0 added, 17 deleted, 7 changed) * include_server/compiler_defaults.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/macro_eval.py: edit * include_server/mirror_path.py: edit * include_server/mirror_path_test.py: edit 2007/05/30 16:59:02 Craig Silverstein Continuing cleanup of the code, mostly to get varnames to be consistent. But also some functionality changes: 1) Separated out the realpath_map into two data structures, one that canonicalizes the paths, and the other that keeps the systemdir-prefix information. Both are now part of the mondo-cache object. There's still a bit more work to be done to get the systemdir-prefix cache working intuitively. 2) Added RelpathMapToIndex, which requires that its keys not start with a /. Use this new class for includepaths, so we get better error checking; we'll now correctly fail when we see code like #include , which we can't handle properly. 3) [smaller] We now fall back on the python equivalents if we don't have the C-speedups for realpath and stat(). 4) [smaller] Modified the convenience functions to be per data-type rather than per varialbe: we have SearchdirIndex and CurrdirIndex rather than just DirectoryIndex. (Since this function is never used, it doesn't really matter, but...) These were more syntactic cleanup: 1) Use currdir everywhere to mean the current directory, to match cache_basics.py. 2) I started some comment changes to be more consistent. For instance, every time we had a realpath_map argument, I try to say what a realpath_map is (in one line!) rather than just say its type -- which is, admittedly, better than nothing. Only small work done here; still lots more. 3) Some places are still using fp instead of includepath. I've fixed up most, but for some I'm not sure that the fp is an includepath exactly, so I'm waiting to clean those up. 4) Several places would pass a list in to a routine by reference, so the procedure would fill the passed-in list rather than returning a new list. This can be more efficient, but is harder to follow, especially in python where pass-by-value is expected. Change to a more natural control-flow in situations where efficiency isn't critical. I also corrected the following deviations from the style guide: 1) (Almost) no "naked" exceptions. Before there was lots of "try: os-operation except: die". Now we actually check that it's an IOError or an OSError. We also now print out the 'why' status as part of the error message. 2) Got rid of unused imports. 3) Made sure there was at least two spaces between code and end-of-line comments. Still more places to fix this one... 4) Nixed trailing whitespace (at the end of each line). R=klarlund DELTA=719 (297 added, 193 deleted, 229 changed) * include_server/basics.py: edit * include_server/cache_basics.py: edit * include_server/compiler_defaults.py: edit * include_server/compress_files.py: edit * include_server/include_analyzer.py: edit * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_server.py: edit * include_server/include_server_test.py: edit * include_server/macro_eval.py: edit * include_server/macro_eval_test.py: edit * include_server/mirror_path.py: edit * include_server/mirror_path_test.py: edit * include_server/parse_command_test.py: edit * include_server/parse_file.py: edit * include_server/parse_file_test.py: edit 2007/05/25 18:35:29 Nils Klarlund The sed -i command I ran to perform renaming according to cache_basics.py tricked me; these files were not added to my CL that took care of several little changes. I have verified that make -C include_server test now works. R=fergus,csilvers DELTA=8 (0 added, 0 deleted, 8 changed) * include_server/include_analyzer_memoizing_node.py: edit * include_server/include_server_test.py: edit * include_server/mirror_path_test.py: edit 2007/05/25 17:53:45 Nils Klarlund Installation and use improvements. Now the 'pump' wrapper is generic; no-hardcoded hosts, but a an environment variable must be set. Also, it uses lsdistcc to discover which potential hosts are actually ready. The INSTALL instructions are still rudimentary, but improved. The 'configure' script simply calls 'configure' in distcc subdir. R=fergus,csilvers DELTA=82 (47 added, 33 deleted, 2 changed) * INSTALL: edit * configure: add * pump: edit 2007/05/25 16:05:37 Nils Klarlund Add test targets. R=fergus DELTA=26 (26 added, 0 deleted, 0 changed) * include_server/Makefile: edit 2007/05/25 15:49:30 Nils Klarlund It turns out that the gcc system path discovery command creates a temporary file. Make tempdir to overcome this problem. R=fergus,manos DELTA=14 (4 added, 0 deleted, 10 changed) * include_server/compiler_defaults.py: edit 2007/05/25 15:48:56 Nils Klarlund Make safer tempdir mechanism. R=fergus DELTA=4 (1 added, 0 deleted, 3 changed) * include_server/basics.py: edit 2007/05/25 15:47:27 Nils Klarlund Lots of little changes for final integration. One theme: names changes. R=fergus,manos DELTA=145 (51 added, 26 deleted, 68 changed) * include_server/include_analyzer.py: edit * include_server/include_server.py: edit * include_server/macro_eval_test.py: edit * include_server/mirror_path.py: edit * include_server/parse_command_test.py: edit * include_server/parse_file.py: edit * include_server/parse_file_test.py: edit * include_server/statistics.py: edit * include_server/test_data/gws-main.o.cmd: edit 2007/05/25 15:17:51 Nils Klarlund This CL should have accompanied "This CL is in response to csilvers's questions.." * include_server/parse_command.py: edit 2007/05/25 15:15:43 Nils Klarlund Initial submission: "Compress files in an include closure." * include_server/compress_files.py: add 2007/05/25 13:47:00 Nils Klarlund A unittest for module mirror_path, featuring dependency injection. This version is working. It replaces something that didn't. R=fergus,manos DELTA=121 (87 added, 3 deleted, 31 changed) * include_server/mirror_path_test.py: edit 2007/05/25 11:38:56 Nils Klarlund Initial submit of module to compute approximation of include dependencies for C/C++. Also, some accompanying changes to basics.py * include_server/basics.py: edit * include_server/include_server.py: add * include_server/include_server_test.py: add 2007/05/25 11:29:51 Nils Klarlund Wrapper script for distcc-pump test users. R=fergus,manos DELTA=80 (80 added, 0 deleted, 0 changed) * pump: add 2007/05/24 21:49:42 Fergus Henderson Add -r option to lsdistcc to specify which port to connect to. ("-p", "-o", and "-t" were already taken.) Fix a bug where "lsdistcc distcc%d" was only returning the first host. Add some unit tests for lsdistcc. Also tidy up the usage message a little. R=manos CC=distcc-pump,dkegel,aaw DELTA=57 (47 added, 0 deleted, 10 changed) * distcc/src/lsdistcc.c: edit * distcc/test/testdistcc.py: edit 2007/05/24 18:12:30 Fergus Henderson Fix a bug that broke "cd distcc; configure; make": move definition of the "echo_common_obj" target to the end of the file, so that it doesn't become the default target (Make treats the first rule in the file as the default target). R=klarlund CC=distcc-pump DELTA=10 (5 added, 5 deleted, 0 changed) * distcc/Makefile.in: edit 2007/05/24 14:17:43 Nils Klarlund Fix "Usage" logic and printing error. Improve error reporting when path to execute is not found. R=fergus,manos DELTA=12 (7 added, 0 deleted, 5 changed) * include_server/run.py: edit 2007/05/24 09:14:17 Nils Klarlund Tests for distcc_pump_c_extensions. Writes out doc strings and calls some distcc rpc functions. Also, times the speed-up of using libc versions of os.path.realpath and os.path.exists. R=fergus,manos DELTA=115 (115 added, 0 deleted, 0 changed) * include_server/c_extensions_test.py: add 2007/05/24 09:11:50 Nils Klarlund A file used for testing parse_command.py. Should not be part of open source release. * include_server/test_data/gws-main.o.cmd: add 2007/05/24 09:03:57 Nils Klarlund Wrapper for running include server and tests. Initial submission. R=fergus,manos DELTA=49 (49 added, 0 deleted, 0 changed) * include_server/run.py: add 2007/05/23 23:48:11 Nils Klarlund directory and link structure." R=fergus,manos DELTA=159 (159 added, 0 deleted, 0 changed) * include_server/mirror_path.py: add * include_server/mirror_path_test.py: add 2007/05/23 23:12:36 Nils Klarlund Initial submission: CPP macro evaluation. This admittedly needs a little more work as explained. But there are some tests. R=manos,fergus DELTA=338 (338 added, 0 deleted, 0 changed) * include_server/macro_eval.py: add * include_server/macro_eval_test.py: add 2007/05/23 22:31:52 Nils Klarlund Initial submission. include_analyzer: "The skeleton, including caches, of an include analyzer." include_analyzer_memoizing_node: "An graph-based algorithm for memoizing include closure calculations. R=fergus,csilvers DELTA=545 (545 added, 0 deleted, 0 changed) * include_server/include_analyzer.py: add * include_server/include_analyzer_memoizing_node.py: add 2007/05/23 19:01:57 Craig Silverstein Augment comments and normalize variable names. In addition, clean up the code a bit, mostly by removing redundant code. That said, with the variable-name changing, almost every line in this file is affected by this CL. The file now is at a point where it makes sense to me!, though I am perhaps too close to the algorithm these days to be a good 'outside observer' judge. I think it's more consistent in its naming, in any case. That said, I left in many TODOs where I still need some clarification of functionality, or have cleanups to do later (I tried not to change the functionality too much). Some outside-visible function/variable names may have changed as a result of this CL, so other changes may be needed to get the system working again after this. R=klarlund DELTA=411 (108 added, 35 deleted, 268 changed) * include_server/cache_basics.py: edit 2007/05/22 15:25:09 Nils Klarlund This bunch of files is used for various tests of the include server. I submit them as a bundle for further perusal with the various *_test.py code. R=fergus,manos DELTA=52 (52 added, 0 deleted, 0 changed) * include_server/test_data/abc_post.c: add * include_server/test_data/abc_pre.c: add * include_server/test_data/computed_includes.c: add * include_server/test_data/dbar/dbar1/bar.h: add * include_server/test_data/dbar/foo.h: add * include_server/test_data/dfoo/foo.h: add * include_server/test_data/dfoo/foo2.h: add * include_server/test_data/dfoo/include_next_foo.h: add * include_server/test_data/include_include_next_foo.h: add * include_server/test_data/p1.h: add * include_server/test_data/parse.c: add * include_server/test_data/test_include_next/bar/x.h: add * include_server/test_data/test_include_next/bar/y.h: add * include_server/test_data/test_include_next/baz/start_x.c: add * include_server/test_data/test_include_next/baz/start_y.c: add * include_server/test_data/test_include_next/baz/x.h: add * include_server/test_data/test_include_next/baz/y.h: add * include_server/test_data/test_include_next/biz/x.h: add * include_server/test_data/test_include_next/foo/x.h: add * include_server/test_data/test_include_next/foo/y.h: add 2007/05/21 18:37:57 Manos Renieris Change the test regexp to match the version text. R=fergus,klarlund DELTA=4 (2 added, 0 deleted, 2 changed) * distcc/test/testdistcc.py: edit 2007/05/21 18:29:41 Nils Klarlund Initial submission. "How to find system path defaults for gcc." R=fergus,manos APPROVED=fergus DELTA=136 (136 added, 0 deleted, 0 changed) * include_server/compiler_defaults.py: add 2007/05/21 17:01:16 Nils Klarlund Initial submissin. Statistics gathering for the distcc-pump include server. R=fergus,manos DELTA=110 (110 added, 0 deleted, 0 changed) * include_server/statistics.py: add 2007/05/21 12:09:10 Nils Klarlund This CL is in response to csilvers's questions about the use of indices and caches in the include server. I've tried to make the terminology coherent and to make the distinction between indexed and string representation clearer. Also, I moved the actual use of the classes into function SetUpCaches that constructs the intended hierarchy for memoization. Now: also includes parse_command. R=fergus,csilvers CC=manos DELTA=410 (184 added, 40 deleted, 186 changed) * include_server/cache_basics.py: edit 2007/05/21 11:59:41 Manos Renieris Initialize needs_dotd. R=klarlund,fergus DELTA=1 (0 added, 0 deleted, 1 changed) * distcc/src/compile.c: edit 2007/05/21 11:59:13 Manos Renieris Fix the cleanup function. R=klarlund,fergus DELTA=3 (0 added, 0 deleted, 3 changed) * distcc/src/cleanup.c: edit 2007/05/18 17:22:48 Manos Renieris Added the new files and one missing file to the Makefile. R=klarlund,fergus DELTA=8 (3 added, 0 deleted, 5 changed) * distcc/Makefile.in: edit 2007/05/18 11:37:55 Manos Renieris Undo the local_cpu lock if we are using the include server. R=fergus,klarlund DELTA=6 (5 added, 0 deleted, 1 changed) * distcc/src/compile.c: edit 2007/05/17 18:21:26 Nils Klarlund Initial check-in of directives-only C/C++ parser. R=manos,fergus DELTA=395 (395 added, 0 deleted, 0 changed) * include_server/parse_file.py: add * include_server/parse_file_test.py: add 2007/05/17 17:27:24 Nils Klarlund This change accompanies a previous change. It allows the extension module to extract the needed .o files from the distcc Makefile. R=fergus,manos DELTA=5 (5 added, 0 deleted, 0 changed) * distcc/Makefile.in: edit 2007/05/17 16:15:36 Nils Klarlund This CL enables us to compile distcc and to install the Python extension module that provides access to some distcc rpc functions as well as lzo. It no longer uses the Python interface that is part of the lzo distribution. The CL also include some initial attempts a Makefile's. R=fergus,manos DELTA=467 (467 added, 0 deleted, 0 changed) * INSTALL: add * Makefile: add * include_server/Makefile: add * include_server/c_extensions/Makefile: add * include_server/c_extensions/distcc_pump_c_extensions_module.c: add * include_server/c_extensions/setup.py: add 2007/05/17 11:09:39 Nils Klarlund Include server for distcc-pump. The basic stuff. Initial submit. The basic caching mechanisms for distcc-pump. Initial submit. R=manos,fergus DELTA=596 (596 added, 0 deleted, 0 changed) * include_server/basics.py: add * include_server/cache_basics.py: add 2007/05/16 17:03:03 Fergus Henderson Update the output from "distcc --version". 1. src/help.c: mention that it supports version 3 of the protocol, i.e. distcc_pump 2. configure.ac: change version to "distcc 2.18.3-13gg-pump1" rather than "distcc 2.18.3", i.e. include both a. "-13gg" to show it has all the existing Google patches, and b. "-pump1" for the distcc_pump extensions that support preprocessing on the server. 3. configure: regenerate based on the new configure.ac. This resulted in some slight differences due to different autoconf versions, but they appear innocuous. TESTED=Ran make and manually verified the output of "distcc --version" and "distccd --version". Tried running "make maintainer-check"; that failed, but I think the failures are unrelated to my change (probably they're due to problems with the merge of distcc-pump with the Google distcc patches). R=manos CC=distcc-pump DELTA=135 (24 added, 86 deleted, 25 changed) * distcc/configure: edit * distcc/configure.ac: edit * distcc/src/help.c: edit 2007/05/16 15:04:29 Manos Renieris Change the name of the temp directories to reflect that they are server-side. R=fergus,klarlund DELTA=1 (0 added, 0 deleted, 1 changed) * distcc/src/tempfile.c: edit 2007/05/14 17:16:41 Craig Silverstein Rewrite the argument-parser to be more efficient: this code now runs about 50% faster than it used to (tested by time_ParseCommandArguments.py). I can't totally vouch for the fact the output is the same now as before, since there's not a complete test for this code yet, but it seems to be on the one example I tried. Also, a few TODOs remain to deal with some obscure cases I didn't understand (how does "-iquote=foo" differ from "-iquote foo"?). But the basics should be right on. R=klarlund,fergus DELTA=295 (153 added, 76 deleted, 66 changed) * include_server/parse_command.py: edit * include_server/parse_command_test.py: edit 2007/05/14 17:05:15 Manos Renieris Improve the robustness of cleanup. R=klarlund,fergus DELTA=33 (18 added, 1 deleted, 14 changed) * distcc/src/cleanup.c: edit * distcc/src/srvrpc.c: edit * distcc/src/tempfile.c: edit 2007/05/14 11:37:26 Manos Renieris Mark the top tmp directory for deletion. R=fergus,klarlund DELTA=3 (3 added, 0 deleted, 0 changed) * distcc/src/tempfile.c: edit 2007/05/14 11:22:04 Manos Renieris Close the file descriptors after being done talking to the include server. R=klarlund,fergus DELTA=14 (11 added, 1 deleted, 2 changed) * distcc/src/include_server_if.c: edit 2007/05/10 10:04:32 Nils Klarlund The routines for interpreting a gcc command, along with tests. Two issues still to be resolved: - This code is too slow. - For computed includes, we need to parse -D etc. R=fergus,manos DELTA=518 (518 added, 0 deleted, 0 changed) * include_server/parse_command.py: add * include_server/parse_command_test.py: add 2007/05/09 23:13:18 Fergus Henderson Update Makefile.in to fix some bugs introduced in CL a previous change (which just applied the Google and LSB-specific patches). Some object files had been moved into $(common_obj), but were still listed in h_*_obj, resulting in duplicate symbol errors when running "make maintainer-check". R=manos CC=dkegel,klarlund DELTA=3 (0 added, 1 deleted, 2 changed) * distcc/Makefile.in: edit 2007/05/09 19:12:09 Manos Renieris A bit more const-correctness. R=fergus DELTA=6 (2 added, 0 deleted, 4 changed) * distcc/src/serve.c: edit 2007/05/09 18:41:10 Manos Renieris Distcc-pump first implementation. Various little changes, making functions from static into global, all around the code; a bug fix in argutil.c. Important changes are: - On the protocol, which is extended as "version 3", that supports compression and also cpp on the server. - distcc.h: Added the enum for where to do the cpp. - hosts.c: Map a set of features (currently a subset of where to do cpp and whether to do compression) onto a protocol number. - rpc.c: The client sometimes sends either a file, or a link to the server. The server needs to be able to accept either, so dcc_r_sometoken_int allows some alternation to the protocol. - Talking to the include server: - compile.c: dcc_build_somewhere tries to talk to the include server, and pushes the information about the dotd file to dcc_compile_remote. This is where the fallback-to-the-original-protocol code lives. - include_server_if.c: Talk to the include server. - The communication from client to server. The client needs to send multiple files, and perhaps links, to the server; the client also needs to sent its current working directory, - remote.c: Entry points for sending multiple files to the server. - rpc.c: The server needs to handle not only files, but also links (directories are handled implicitly). - clirpc.c: Added a function to send the current working directory. Added a function, dcc_x_many_files. It sends multiple files to the server. In addition, it changes the filenames to chop off the additions of the include server. - serve.c: Added a function to receive the current working directory. - On the server side, the server receives multiple files, and the working directory, builds a directory structure (which it keeps of, to clean it up at the end) - srvrpc.c: Added a function, dcc_r_many_files, to receive multiple files. In addition, it changes the filenames to put all the files under a "fake root" directory. - serve.c: lots of work to set up "fake root" directories, chdir to the right place, produce a .d file, and absolutize include directives. - tempfile.c: Creation of whole temp directories, not just files. - cleanup.c: Since we are receiving multiple files, we need to keep a dynamic list of what temporary files we create. It can now handle directories. - ".d" files: the client needs to find out where the dotd file should go; the server needs to produce it, remove all references to the local filesystem (gcc can't do that from the outside) and send it back to the client. - dotd.c: Most of the code that handles the dotd: figuring out if we need it, and where it should go; also, cleaning it up after it gets created on the server. - clirpc.c Changed dcc_retrieve_results to retrieve the dotd file. R=klarlund,fergus DELTA=1208 (1058 added, 36 deleted, 114 changed) * distcc/Makefile.in: edit * distcc/README.google: add * distcc/src/arg.c: edit * distcc/src/argutil.c: edit * distcc/src/bulk.c: edit * distcc/src/bulk.h: edit * distcc/src/cleanup.c: edit * distcc/src/clinet.c: edit * distcc/src/clinet.h: edit * distcc/src/clirpc.c: edit * distcc/src/compile.c: edit * distcc/src/compile.h: edit * distcc/src/compress.c: edit * distcc/src/distcc.h: edit * distcc/src/dotd.c: add * distcc/src/dotd.h: add * distcc/src/filename.c: edit * distcc/src/hosts.c: edit * distcc/src/hosts.h: edit * distcc/src/include_server_if.c: add * distcc/src/include_server_if.h: add * distcc/src/lock.c: edit * distcc/src/remote.c: edit * distcc/src/rpc.c: edit * distcc/src/rpc.h: edit * distcc/src/serve.c: edit * distcc/src/srvrpc.c: edit * distcc/src/tempfile.c: edit 2007/05/08 17:53:54 Manos Renieris A few "\n\" were missing. R=fergus,klarlund DELTA=4 (0 added, 0 deleted, 4 changed) * distcc/src/lsdistcc.c: edit ## More changes that were made internally to Google, and not integrated ## into the main distcc distribution until 2008. These log messages ## are from the RPM spec file's changlog. * Thu Jun 14 2007 Manos Renieris - Added all the distcc-pump related parts to distcc.spec. - Changed the way the package is built. - Remove source package generation. - Man pages are now unzipped. * Mon Feb 8 2007 Dongmin Zhang - Added hosts list option to lsdistcc, such that lsdistcc can check only the hosts listed on the given list. The host list is given in command line. * Wed Jan 31 2007 Dongmin Zhang - Added _libdir definition in rpms.epc. - Changed Name, Version, and Release to the ones passed by --define. - Updated the server init script to give different path of ACL files for grhat and goobuntu as suggested by Arthur Hyun . * Mon Jan 22 2007 Dongmin Zhang - Fixed a bug in timeout patch. Added sigaction to catch SIGCHLD such that the select() in dcc_collect_child() could break out when the file is finished to compile. * Fri Dec 1 2006 Ollie Wild - Removed the 01-distcc-gdb-20051210.patch patch. The parser in this was too naive to deal with output generate with the -directives-only flag. Also, it should no longer be needed with recent versions of gcc. - Removed the 10-distcc-before-cpp_locking-sub-gdb.patch and 12-distcc-after-cpp_locking-add-gdb.patch patches. These were just modifying the former patch. * Fri Sep 8 2006 Michael Moss - Update install and init scripts to work on Debian and Red Hat (allowing the .rpm to be converted to .deb with alien, and then installed on Debian). Some noteworthy changes: - Deb - Remove unused defaults file /etc/default/distcc. - Deb - No longer uses debconf. - RH - useradd is run in post- rather than pre- install. - RH - distcc server is automatically started. - Added enable/disable commands to init scripts so the daemon can be "permanently" disabled on misbehaving hosts. - Added patches to allow building LSB-compliant binaries. - Reorganized some existing patches to better partition functionality. * Tue Feb 28 2006 Dan Kegel - removed cache again * Mon Feb 20 2006 Dan Kegel - added cache * Mon Feb 6 2006 Dan Kegel - use Josh's randomize patch instead of Michael's, since Josh's seems to perform better in our tests - added disk space statistic on http interface - lsdistcc now has -x option to output info even on down hosts (will be useful for server side caching) * Tue Jan 2 2006 Dan Kegel - removed load shedding patch (we have swap turned on, so overload isn't as bad) - added stats for timeout * Wed Dec 8 2005 Dan Kegel - lsdistcc now has -l option, better -v output - distccd now has nicer logging, --limit-load option, bugfixes in load shedding * Tue Nov 22 2005 Dan Kegel - rejects jobs if load too high - serves up stats via http on port 3633 - lsdistcc now has new -p and -c0 options * Wed Nov 2 2005 Dan Kegel - updated lsdistcc to use the longer of the two of HOST and HOSTNAME to handle shells that set HOST to the nonqualified hostname, but HOSTNAME to the FQDN * Thu Oct 13 2005 Dan Kegel - updated lsdistcc patch - removed gcc as a dependency, since we want to use it with a wide range of other compilers (and in our case, not the standard gcc), and it's impractical to list them all as dependencies * Fri Sep 16 2005 Dan Kegel - now reads /etc/distcc/hosts instead of /usr/etc/distcc/hosts - replaced distcc-2.18.3-rhl.patch with distcc-2.18.3-stringmap.patch The stringmap patch updates the rhl init.d script to know about all installed crosstool toolchains, and enables fuzzy path matching This is useful if the toolchains are not installed at the same prefix on all systems - removed distcc-domain.patch - added distcc-2.18.3-lsdistcc.patch * Sat Sep 3 2005 Dan Kegel - now reads /etc/distcc/hosts instead of /usr/etc/distcc/hosts - applied distcc-domain-2.patch * Thu Jun 15 2005 Dan Kegel - Updated to 2.18.3 - applied --randomize patch and cpp_locking patch - redhat init.d script reads /etc/distccd.allow to construct --allow arguments - added scriptlets from dag's package, but don't start service on install, and call it distcc rather than distccd (to match the current packaging's old practice) ## These changes are from when development was done under bzr. ## bzr branch: http://bazaar.launchpad.net/%7Embp/distcc/trunk/ 2008-03-14 13:31:23 +1100 Martin Pool revno: 4 message: Locks taken through F_SETLK or lockf() must be explicitly released, because closing the file does not do so. (Sascha Demetrio) 2007-09-22 21:32:03 +1000 Martin Pool revno: 3 message: merge avahi patch from Lennart Poettering (http://0pointer.de/public/distcc-avahi.patch) 2007-09-22 21:32:03 +1000 Martin Pool revno: 2 message: Add more ignored files ## These changes are from when development was done under arch. ## arch-tag: automatic-ChangeLog--mbp@sourcefrog.net--2004/distcc--devel--2 2006-04-05 23:35:36 GMT Martin Pool patch-183 Summary: ignore tags file Revision: distcc--devel--2--patch-183 modified files: ChangeLog {arch}/=tagging-method 2006-04-03 17:56:54 GMT Martin Pool patch-182 Summary: build fix for --as-needed Revision: distcc--devel--2--patch-182 modified files: ChangeLog Makefile.in NEWS 2006-03-03 00:10:56 GMT Martin Pool patch-181 Summary: fix error check in dcc_connect_by_add Revision: distcc--devel--2--patch-181 Found in code review from recent list thread -- error check was done incorrectly for nonblocking commits. modified files: ChangeLog src/clinet.c 2006-02-21 05:38:41 GMT Martin Pool patch-180 Summary: draft patch for substituting compiler command name Revision: distcc--devel--2--patch-180 new files: patches/.arch-ids/distcc-substitute-command.diff.id patches/distcc-substitute-command.diff modified files: ChangeLog 2006-01-20 23:40:53 GMT Martin Pool patch-179 Summary: More details on error 110 Revision: distcc--devel--2--patch-179 modified files: ChangeLog man/distcc.1 2006-01-11 04:03:16 GMT Martin Pool patch-178 Summary: set locale when running make maintainer-check Revision: distcc--devel--2--patch-178 modified files: ChangeLog NEWS test/comfychair.py 2006-01-11 03:58:36 GMT Martin Pool patch-177 Summary: Update more benchmark project definitions Revision: distcc--devel--2--patch-177 modified files: ChangeLog bench/ProjectDefs.py test/testdistcc.py 2006-01-05 00:20:52 GMT Martin Pool patch-176 Summary: update benchmark project urls and md5s Revision: distcc--devel--2--patch-176 modified files: ChangeLog bench/ProjectDefs.py 2006-01-05 00:12:56 GMT Martin Pool patch-175 Summary: [patch] update stale benchmark source URLS (Dongmin Zhang) Revision: distcc--devel--2--patch-175 modified files: ChangeLog bench/ProjectDefs.py 2005-12-12 05:47:20 GMT Martin Pool patch-174 Summary: update patch to fix up gdb line numbers Revision: distcc--devel--2--patch-174 Updated patch from Dan Kegel to workaround wrong source file names in debug symbols for older versions of gcc. new files: patches/.arch-ids/fix-line-numbers.diff.id patches/fix-line-numbers.diff removed files: patches/.arch-ids/distcc-line3.diff.id patches/.arch-ids/timj-line1.diff.id patches/distcc-line3.diff patches/timj-line1.diff modified files: ChangeLog 2005-11-28 03:00:58 GMT Martin Pool patch-173 Summary: [patch] cygwin improvements from Alex Besogonov Revision: distcc--devel--2--patch-173 modified files: ChangeLog NEWS src/exec.c src/tempfile.c 2005-11-28 02:50:23 GMT Martin Pool patch-172 Summary: doc Revision: distcc--devel--2--patch-172 modified files: ChangeLog src/exitcode.h 2005-11-28 02:49:19 GMT Martin Pool patch-171 Summary: doc Revision: distcc--devel--2--patch-171 modified files: ChangeLog src/exitcode.h 2005-10-05 00:44:49 GMT Martin Pool patch-170 Summary: return error on timeout in dcc_select_for_write Revision: distcc--devel--2--patch-170 modified files: ChangeLog src/io.c 2005-10-05 00:14:16 GMT Martin Pool patch-169 Summary: bump version number Revision: distcc--devel--2--patch-169 modified files: ChangeLog configure.ac 2005-10-05 00:07:50 GMT Martin Pool patch-168 Summary: use python2.4 if available Revision: distcc--devel--2--patch-168 modified files: ChangeLog NEWS configure.ac 2005-10-05 00:05:20 GMT Martin Pool patch-167 Summary: - better autogen message Revision: distcc--devel--2--patch-167 modified files: ChangeLog autogen.sh 2005-10-05 00:04:18 GMT Martin Pool patch-166 Summary: [patch] better checking for errors on connect() Revision: distcc--devel--2--patch-166 modified files: ChangeLog NEWS src/clinet.c 2005-09-05 01:36:22 GMT Martin Pool patch-165 Summary: add hosts-from-dnsdomain patch from dan Revision: distcc--devel--2--patch-165 new files: patches/.arch-ids/kegel-distcc-domain.patch.id patches/kegel-distcc-domain.patch modified files: ChangeLog 2005-08-16 01:39:54 GMT Martin Pool patch-164 Summary: add note that the mDNS patch cannot be legally merged Revision: distcc--devel--2--patch-164 modified files: ChangeLog patches/howl-mdns.diff 2005-06-10 09:58:57 GMT Martin Pool patch-163 Summary: todo Revision: distcc--devel--2--patch-163 modified files: ChangeLog TODO 2005-01-19 03:17:27 GMT Martin Pool patch-162 Summary: manpage correction from Frerich Revision: distcc--devel--2--patch-162 modified files: ChangeLog man/distcc.1 2004-12-21 02:11:57 GMT Martin Pool patch-161 Summary: args: -d must be local Revision: distcc--devel--2--patch-161 modified files: ChangeLog NEWS src/arg.c test/testdistcc.py 2004-12-20 12:40:10 GMT Martin Pool patch-160 Summary: note on .incbin from asm() Revision: distcc--devel--2--patch-160 new files: doc/todo/.arch-ids/unhandled-cases.txt.id doc/todo/unhandled-cases.txt modified files: ChangeLog 2004-12-15 00:11:05 GMT Martin Pool patch-159 Summary: remove obsolete web targets from makefile Revision: distcc--devel--2--patch-159 modified files: ChangeLog Makefile.in 2004-12-14 07:07:01 GMT Martin Pool patch-158 Summary: add pending Howl mDNS patch from Lennart Poettering Revision: distcc--devel--2--patch-158 new files: patches/.arch-ids/howl-mdns.diff.id patches/howl-mdns.diff modified files: ChangeLog 2004-11-30 19:05:36 GMT Martin Pool patch-157 Summary: Add freshmeat submission data Revision: distcc--devel--2--patch-157 new files: freshmeat/.arch-ids/2.18.3.id freshmeat/.arch-ids/=id freshmeat/2.18.3 modified files: ChangeLog new directories: freshmeat freshmeat/.arch-ids 2004-11-30 12:25:10 GMT Martin Pool patch-156 Summary: Fix for -x and -specs bug Revision: distcc--devel--2--patch-156 modified files: ChangeLog NEWS src/arg.c 2004-11-30 12:11:30 GMT Martin Pool patch-155 Summary: Better text for -x and -specs Revision: distcc--devel--2--patch-155 modified files: ChangeLog NEWS TODO configure.ac test/testdistcc.py 2004-11-12 03:33:34 GMT Martin Pool patch-154 Summary: Prepare for 2.18.2 release Revision: distcc--devel--2--patch-154 modified files: ChangeLog NEWS configure.ac 2004-11-12 03:32:54 GMT Martin Pool patch-153 Summary: Notes on performance influence of mmap Revision: distcc--devel--2--patch-153 new files: doc/.arch-ids/mmap-influence.txt.id doc/mmap-influence.txt modified files: ChangeLog 2004-11-12 03:31:51 GMT Martin Pool patch-152 Summary: fix size_t/unsigned mismatch Revision: distcc--devel--2--patch-152 modified files: ChangeLog NEWS src/distcc.h 2004-11-12 03:23:15 GMT Martin Pool patch-151 Summary: fix for checking uninitialized errno Revision: distcc--devel--2--patch-151 modified files: ChangeLog NEWS src/clinet.c 2004-11-03 02:20:56 GMT Martin Pool patch-150 Summary: gcc -specs must also be run locally Revision: distcc--devel--2--patch-150 modified files: ChangeLog NEWS src/arg.c test/testdistcc.py 2004-11-02 07:12:57 GMT Martin Pool patch-149 Summary: mon-gnome: fix tree_model warning Revision: distcc--devel--2--patch-149 modified files: ChangeLog NEWS src/mon-gnome.c 2004-10-23 08:42:53 GMT Martin Pool patch-148 Summary: fold io.h into distcc.h Revision: distcc--devel--2--patch-148 removed files: src/.arch-ids/io.h.id src/io.h modified files: ChangeLog Makefile.in src/arg.c src/argutil.c src/backoff.c src/bulk.c src/clinet.c src/clirpc.c src/compress.c src/daemon.c src/distcc.h src/dopt.c src/dparent.c src/exec.c src/h_exten.c src/h_issource.c src/h_scanargs.c src/h_strip.c src/hostfile.c src/io.c src/loadfile.c src/lock.c src/mon-gnome.c src/mon-notify.c src/mon-text.c src/mon.c src/prefork.c src/pump.c src/remote.c src/renderer.c src/rpc.c src/safeguard.c src/sendfile.c src/serve.c src/srvnet.c src/srvrpc.c src/ssh.c src/state.c src/strip.c src/timefile.c src/util.c 2004-10-23 08:23:22 GMT Martin Pool patch-147 Summary: fix some signedness/type warnings Revision: distcc--devel--2--patch-147 modified files: ChangeLog src/bulk.c src/climasq.c src/clirpc.c src/distcc.h src/hosts.c src/io.h src/mon-gnome.c src/netutil.c src/netutil.h src/rpc.c src/trace.c src/util.c src/where.c 2004-10-23 08:11:25 GMT Martin Pool patch-146 Summary: Turn off -Wunreachable-code Revision: distcc--devel--2--patch-146 modified files: ChangeLog configure.ac 2004-10-23 08:00:12 GMT Martin Pool patch-145 Summary: turn on more warnings Revision: distcc--devel--2--patch-145 modified files: ChangeLog configure.ac 2004-10-21 23:06:54 GMT Martin Pool patch-144 Summary: Allow for host files containing \r Revision: distcc--devel--2--patch-144 modified files: ChangeLog NEWS src/hosts.c test/testdistcc.py 2004-10-13 02:37:50 GMT Martin Pool patch-143 Summary: Return errors, rather than aborting. Revision: distcc--devel--2--patch-143 Don't call rs_fatal; instead return an error. It was giving warnings on non-gcc compilers because it wasn't seen as noreturn, and anyhow aborting is a bit untidy. modified files: ChangeLog src/arg.c src/bulk.c src/cleanup.c src/cpp.c src/dopt.c src/h_ccvers.c src/history.c src/hosts.c src/io.c src/lock.c src/mon.c src/pump.c src/remote.c src/rpc.c src/serve.c src/ssh.c src/trace.h src/util.c 2004-10-13 02:23:11 GMT Martin Pool patch-142 Summary: fix header problem for Solaris Revision: distcc--devel--2--patch-142 * src/distcc.h: Need sys/types.h for pid_t. modified files: ChangeLog NEWS bench/Build.py bench/Project.py bench/ProjectDefs.py src/distcc.h 2004-10-12 06:28:10 GMT Martin Pool patch-141 Summary: Add samba 3.0.7 as benchmark project Revision: distcc--devel--2--patch-141 modified files: ChangeLog bench/ProjectDefs.py 2004-10-12 05:41:38 GMT Martin Pool patch-140 Summary: benchmark: scrub results on completion by default Revision: distcc--devel--2--patch-140 modified files: ChangeLog bench/actions.py 2004-10-12 05:37:21 GMT Martin Pool patch-139 Summary: advance version to 2.19pre Revision: distcc--devel--2--patch-139 modified files: ChangeLog configure.ac 2004-10-12 05:13:54 GMT Martin Pool patch-138 Summary: Prepare for release Revision: distcc--devel--2--patch-138 modified files: ChangeLog NEWS configure.ac 2004-10-12 05:10:31 GMT Martin Pool patch-137 Summary: Always build conftest.c locally Revision: distcc--devel--2--patch-137 Problem: configure tests are typically very quick to build; also configure can be very sensitive to stderr warnings or other small variations between machines. Fix: To make things faster and safer, build conftest.* locally; also tmp.conftest.* used by ccache. * src/filename.c (dcc_source_needs_local): New function. * src/arg.c (dcc_scan_args): Check. * cases/conftest.c: Manual test case. new files: cases/conftest.c modified files: ChangeLog NEWS TODO src/arg.c src/distcc.h src/filename.c 2004-10-12 04:50:41 GMT Martin Pool patch-136 Summary: Reset PATH when running maintainer-check Revision: distcc--devel--2--patch-136 Problem: Installed copies of distcc and/or ccache were getting invoked from inside the test suite in a confusing way. Fix: Force the path to just /bin:/usr/bin:`pwd` modified files: ChangeLog Makefile.in 2004-10-12 04:43:39 GMT Martin Pool patch-135 Summary: Remove mmap when receiving uncompressed data Revision: distcc--devel--2--patch-135 Problem: Calling msync seems likely to force disk IO, but not calling it is unsafe. Fix: In fact, we can probably do fine by just using plain IO to receive data. This is already done for compressed data. * src/pump.c (dcc_r_bulk_plain): Remove. * src/pump.c (dcc_r_bulk): Just pump bytes through when receiving data; don't worry about mmap. Doc. * src/bulk.c (dcc_r_file): Output files can be WRONLY if we're not using mmap. * src/io.c (dcc_want_mmap): Remove. * man/distcc.1, man/distccd.1: No more mmap! modified files: ChangeLog NEWS man/distcc.1 man/distccd.1 src/bulk.c src/io.c src/pump.c src/sendfile.c 2004-10-12 04:38:27 GMT Martin Pool patch-134 Summary: fix headers Revision: distcc--devel--2--patch-134 modified files: ChangeLog src/history.c 2004-10-12 04:27:45 GMT Martin Pool patch-133 Summary: todo: conftest.c Revision: distcc--devel--2--patch-133 modified files: ChangeLog TODO 2004-10-12 04:20:05 GMT Martin Pool patch-132 Summary: doc Revision: distcc--devel--2--patch-132 modified files: ChangeLog src/pump.c 2004-10-12 04:10:49 GMT Martin Pool patch-131 Summary: Select-based non-blocking connect() Revision: distcc--devel--2--patch-131 * src/clinet.c (dcc_connect_by_addr): Make socket non-blocking at connect time and impose a timeout on connection attempts; currently hardcoded to 5s. modified files: ChangeLog NEWS src/clinet.c src/io.c 2004-10-12 03:10:31 GMT Martin Pool patch-130 Summary: ssh: doc Revision: distcc--devel--2--patch-130 modified files: ChangeLog src/ssh.c 2004-10-12 03:02:18 GMT Martin Pool patch-129 Summary: Ignore HTML manpages Revision: distcc--devel--2--patch-129 new files: man/.arch-inventory modified files: ChangeLog 2004-10-12 02:59:16 GMT Martin Pool patch-128 Summary: ssh: doc Revision: distcc--devel--2--patch-128 modified files: ChangeLog src/ssh.c 2004-10-12 02:15:39 GMT Martin Pool patch-127 Summary: remove signal-based timeouts Revision: distcc--devel--2--patch-127 Problem: Using alarms to enforce timeouts is inherently unsafe, because it might leave e.g. the resolver or C library in an inconsistent state. Fix: Don't use signals. We can do something simpler and safer using select() in a future commit. We no longer have a timeout on name resolution; the best fix for this is to set an appropriate timeout in resolv.conf. removed files: src/.arch-ids/timeout.c.id src/timeout.c modified files: ChangeLog Makefile.in man/distcc.1 src/distcc.h src/remote.c src/serve.c 2004-10-11 09:09:47 GMT Martin Pool patch-126 Summary: distcc(1): mention timeouts Revision: distcc--devel--2--patch-126 modified files: ChangeLog man/distcc.1 2004-10-11 08:15:05 GMT Martin Pool patch-125 Summary: no timeout on cpp Revision: distcc--devel--2--patch-125 Refactor code that waits for cpp to finish, and disarm the timeout during this phase. modified files: ChangeLog NEWS src/remote.c 2004-10-11 07:28:00 GMT Martin Pool patch-124 Summary: Adjust timeouts Revision: distcc--devel--2--patch-124 Short 5s CONNECT timeout covers only name resolution and TCP connection. SEND phase and timeout should include sending the header, and waiting for cpp to complete. 60s to send. Allow up to 20mins for compilation. modified files: ChangeLog src/remote.c src/serve.c 2004-10-11 07:17:31 GMT Martin Pool patch-123 Summary: fix timeout crash bug Revision: distcc--devel--2--patch-123 Problem: Was using longjmp() from the SIGALRM handler to return an error. This is not safe. Fix: Use siglongjmp() instead. That may not be completely safe either, but it might fix the problem. modified files: ChangeLog NEWS src/timeout.c 2004-10-11 06:24:35 GMT Martin Pool patch-122 Summary: Add test case for siglongjmp Revision: distcc--devel--2--patch-122 new files: cases/.arch-ids/.arch-inventory.id cases/.arch-ids/tryjump.c.id cases/.arch-inventory cases/tryjump.c modified files: ChangeLog NEWS 2004-10-11 06:21:43 GMT Martin Pool patch-121 Summary: todo: problems with state file sharing Revision: distcc--devel--2--patch-121 modified files: ChangeLog TODO 2004-10-09 13:26:15 GMT Martin Pool patch-120 Summary: distccmon-text(1): Clarify client requirements Revision: distcc--devel--2--patch-120 modified files: ChangeLog man/distccmon-text.1 2004-09-25 10:01:05 GMT Martin Pool patch-119 Summary: doc Revision: distcc--devel--2--patch-119 modified files: ChangeLog TODO 2004-09-25 09:57:52 GMT Martin Pool patch-118 Summary: distcc.1: make it clearer this is a client-side monitor Revision: distcc--devel--2--patch-118 modified files: ChangeLog man/distccmon-text.1 2004-09-17 00:41:14 GMT Martin Pool patch-117 Summary: --allow is now mandatory Revision: distcc--devel--2--patch-117 modified files: ChangeLog NEWS src/daemon.c src/dopt.c 2004-09-16 05:58:09 GMT Martin Pool patch-116 Summary: sa_family_t Tru64 portability cleanup -- just remove test Revision: distcc--devel--2--patch-116 modified files: ChangeLog NEWS configure.ac src/distcc.h 2004-09-16 05:20:08 GMT Martin Pool patch-115 Summary: include state.h from within distcc.h Revision: distcc--devel--2--patch-115 modified files: ChangeLog src/compile.c src/distcc.c src/distcc.h src/history.c src/mon-gnome.c src/mon-notify.c src/mon-text.c src/mon.c src/remote.c src/renderer.c src/serve.c src/state.c src/timeout.c src/where.c 2004-09-16 05:12:42 GMT Martin Pool patch-114 Summary: doc Revision: distcc--devel--2--patch-114 modified files: ChangeLog src/distcc.h 2004-09-16 05:08:07 GMT Martin Pool patch-113 Summary: Improved check for gcc>=3.4 for warn_unused_result Revision: distcc--devel--2--patch-113 modified files: ChangeLog src/distcc.h 2004-09-16 04:55:26 GMT Martin Pool patch-112 Summary: fix enum type warning from Dmitri Revision: distcc--devel--2--patch-112 modified files: ChangeLog src/distcc.h src/timeout.c 2004-09-16 04:46:42 GMT Martin Pool patch-111 Summary: fix unused var warning Revision: distcc--devel--2--patch-111 modified files: ChangeLog src/state.c 2004-09-16 04:46:26 GMT Martin Pool patch-110 Summary: bump version Revision: distcc--devel--2--patch-110 modified files: ChangeLog configure.ac 2004-08-24 12:12:50 GMT Martin Pool patch-109 Summary: Prepare for 2.17.1 release Revision: distcc--devel--2--patch-109 modified files: ChangeLog NEWS 2004-08-24 12:10:43 GMT Martin Pool patch-108 Summary: Update version to 2.17.1 Revision: distcc--devel--2--patch-108 modified files: ChangeLog configure.ac 2004-08-24 12:07:55 GMT Martin Pool patch-107 Summary: Don't use warn_unused_result on old gcc Revision: distcc--devel--2--patch-107 modified files: ChangeLog src/distcc.h 2004-08-13 22:06:05 GMT Martin Pool patch-106 Summary: distcc.1: better explanation of using distcc with ccache Revision: distcc--devel--2--patch-106 modified files: ChangeLog Makefile.in man/distcc.1 2004-08-06 00:34:21 GMT Martin Pool patch-105 Summary: doc Revision: distcc--devel--2--patch-105 modified files: ChangeLog src/compile.c 2004-08-05 23:29:15 GMT Martin Pool patch-104 Summary: Fix dcc_trace bug Revision: distcc--devel--2--patch-104 modified files: ChangeLog NEWS src/clinet.c 2004-08-02 18:41:07 GMT Martin Pool patch-103 Summary: doc Revision: distcc--devel--2--patch-103 modified files: ChangeLog src/distcc.h 2004-08-01 05:52:01 GMT Martin Pool patch-102 Summary: fix usage of dcc_timeout_arm Revision: distcc--devel--2--patch-102 modified files: ChangeLog src/serve.c 2004-08-01 05:50:45 GMT Martin Pool patch-101 Summary: prepare for 2.17 release Revision: distcc--devel--2--patch-101 modified files: ChangeLog 2004-08-01 05:49:42 GMT Martin Pool patch-100 Summary: add server-side timeouts Revision: distcc--devel--2--patch-100 modified files: ChangeLog Makefile.in NEWS src/serve.c 2004-08-01 05:45:46 GMT Martin Pool patch-99 Summary: fix usage of dcc_timeout_arm Revision: distcc--devel--2--patch-99 modified files: ChangeLog src/remote.c 2004-08-01 05:43:10 GMT Martin Pool patch-98 Summary: merge from happy Revision: distcc--devel--2--patch-98 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--patch-26 dcc_timeout_arm: add WARN_UNUSED * mbp@sourcefrog.net--happy/distcc--devel--2--patch-27 merge to devel * mbp@sourcefrog.net--happy/distcc--devel--2--patch-28 add WARN_UNUSED to some functions modified files: ChangeLog src/distcc.h new patches: mbp@sourcefrog.net--happy/distcc--devel--2--patch-26 mbp@sourcefrog.net--happy/distcc--devel--2--patch-27 mbp@sourcefrog.net--happy/distcc--devel--2--patch-28 2004-08-01 05:39:19 GMT Martin Pool patch-97 Summary: add WARN_UNUSED to some functions Revision: distcc--devel--2--patch-97 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--patch-26 dcc_timeout_arm: add WARN_UNUSED * mbp@sourcefrog.net--happy/distcc--devel--2--patch-27 merge to devel modified files: ChangeLog src/distcc.h 2004-07-29 21:38:23 GMT Martin Pool patch-96 Summary: cleanups Revision: distcc--devel--2--patch-96 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--patch-23 check return codes from dcc_timeout_arm * mbp@sourcefrog.net--happy/distcc--devel--2--patch-24 ifdef __attribute__ on GNUC * mbp@sourcefrog.net--happy/distcc--devel--2--patch-25 dcc_build_somewhere: cleanup modified files: ChangeLog src/compile.c src/distcc.h new patches: mbp@sourcefrog.net--happy/distcc--devel--2--patch-23 mbp@sourcefrog.net--happy/distcc--devel--2--patch-24 mbp@sourcefrog.net--happy/distcc--devel--2--patch-25 2004-07-29 21:32:11 GMT Martin Pool patch-95 Summary: doc Revision: distcc--devel--2--patch-95 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--patch-16 update todo items * mbp@sourcefrog.net--happy/distcc--devel--2--patch-17 merged to devel * mbp@sourcefrog.net--happy/distcc--devel--2--patch-18 doc * mbp@sourcefrog.net--happy/distcc--devel--2--patch-19 notes on timeouts * mbp@sourcefrog.net--happy/distcc--devel--2--patch-20 timeouts are done * mbp@sourcefrog.net--happy/distcc--devel--2--patch-21 correct version number * mbp@sourcefrog.net--happy/distcc--devel--2--patch-22 treat emacs temporary files as backups modified files: ChangeLog NEWS TODO configure.ac doc/roadmap.txt src/remote.c {arch}/=tagging-method new patches: mbp@sourcefrog.net--happy/distcc--devel--2--patch-16 mbp@sourcefrog.net--happy/distcc--devel--2--patch-17 mbp@sourcefrog.net--happy/distcc--devel--2--patch-18 mbp@sourcefrog.net--happy/distcc--devel--2--patch-19 mbp@sourcefrog.net--happy/distcc--devel--2--patch-20 mbp@sourcefrog.net--happy/distcc--devel--2--patch-21 mbp@sourcefrog.net--happy/distcc--devel--2--patch-22 2004-07-29 19:35:33 GMT Martin Pool patch-94 Summary: more timeouts and cleanups Revision: distcc--devel--2--patch-94 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--patch-11 portability fix for WCOREDUMP * mbp@sourcefrog.net--happy/distcc--devel--2--patch-12 remove obsolete patch * mbp@sourcefrog.net--happy/distcc--devel--2--patch-13 dcc_compile_remote: add more client-side timeouts * mbp@sourcefrog.net--happy/distcc--devel--2--patch-14 dcc_connect_by_addr: handle EINTR from connect() * mbp@sourcefrog.net--happy/distcc--devel--2--patch-15 bump version number removed files: patches/.arch-ids/resolver-timeout.diff.id patches/resolver-timeout.diff modified files: ChangeLog NEWS configure.ac src/clinet.c src/distcc.h src/exec.c src/remote.c new patches: mbp@sourcefrog.net--happy/distcc--devel--2--patch-11 mbp@sourcefrog.net--happy/distcc--devel--2--patch-12 mbp@sourcefrog.net--happy/distcc--devel--2--patch-13 mbp@sourcefrog.net--happy/distcc--devel--2--patch-14 mbp@sourcefrog.net--happy/distcc--devel--2--patch-15 2004-07-29 19:12:49 GMT Martin Pool patch-93 Summary: alarm-based connection timeout Revision: distcc--devel--2--patch-93 Patches applied: * mbp@sourcefrog.net--happy/distcc--devel--2--base-0 import from ozlabs * mbp@sourcefrog.net--happy/distcc--devel--2--patch-1 tweak version output more * mbp@sourcefrog.net--happy/distcc--devel--2--patch-2 Add EXIT_TIMEOUT * mbp@sourcefrog.net--happy/distcc--devel--2--patch-3 Add overall connection timeout * mbp@sourcefrog.net--happy/distcc--devel--2--patch-4 remove docs for deleted DISTCC_CONNECT_TIMEOUT * mbp@sourcefrog.net--happy/distcc--devel--2--patch-5 fold in backoff.h * mbp@sourcefrog.net--happy/distcc--devel--2--patch-6 remove select-based timeout in client connect * mbp@sourcefrog.net--happy/distcc--devel--2--patch-7 dcc_connect_by_addr: remove host and port params * mbp@sourcefrog.net--happy/distcc--devel--2--patch-8 dcc_connect_by_addr: cleanup trace * mbp@sourcefrog.net--happy/distcc--devel--2--patch-9 dcc_build_somewhere: better message on fallback * mbp@sourcefrog.net--happy/distcc--devel--2--patch-10 dcc_timeout_arm: doc new files: src/.arch-ids/timeout.c.id src/timeout.c removed files: src/.arch-ids/backoff.h.id src/backoff.h modified files: ChangeLog Makefile.in NEWS man/distcc.1 src/backoff.c src/clinet.c src/compile.c src/distcc.h src/exitcode.h src/help.c src/remote.c src/ssh.c src/util.c src/util.h src/where.c new patches: mbp@sourcefrog.net--happy/distcc--devel--2--base-0 mbp@sourcefrog.net--happy/distcc--devel--2--patch-1 mbp@sourcefrog.net--happy/distcc--devel--2--patch-2 mbp@sourcefrog.net--happy/distcc--devel--2--patch-3 mbp@sourcefrog.net--happy/distcc--devel--2--patch-4 mbp@sourcefrog.net--happy/distcc--devel--2--patch-5 mbp@sourcefrog.net--happy/distcc--devel--2--patch-6 mbp@sourcefrog.net--happy/distcc--devel--2--patch-7 mbp@sourcefrog.net--happy/distcc--devel--2--patch-8 mbp@sourcefrog.net--happy/distcc--devel--2--patch-9 mbp@sourcefrog.net--happy/distcc--devel--2--patch-10 2004-07-28 18:38:20 GMT Martin Pool patch-92 Summary: mention miniLZO in --version Revision: distcc--devel--2--patch-92 modified files: ChangeLog src/help.c 2004-07-23 13:47:05 GMT Martin Pool patch-91 Summary: Manpage fix from Jean Delvare. Revision: distcc--devel--2--patch-91 modified files: ChangeLog NEWS man/distcc.1 2004-07-15 08:27:57 GMT Martin Pool patch-90 Summary: Add CVE number for netmask problem Revision: distcc--devel--2--patch-90 modified files: ChangeLog NEWS 2004-07-14 05:32:41 GMT Martin Pool patch-89 Summary: notes on mod_backhand load balancing Revision: distcc--devel--2--patch-89 new files: doc/todo/.arch-ids/backhand.txt.id doc/todo/backhand.txt modified files: ChangeLog 2004-07-14 05:32:16 GMT Martin Pool patch-88 Summary: dcc_set_row_idle: reduce unnecessary tree model updates Revision: distcc--devel--2--patch-88 modified files: ChangeLog src/mon-gnome.c 2004-07-14 05:27:54 GMT Martin Pool patch-87 Summary: dcc_build_somewhere: don't retry if remote compiler crashed Revision: distcc--devel--2--patch-87 modified files: ChangeLog NEWS src/compile.c 2004-07-12 07:39:35 GMT Martin Pool patch-86 Summary: Cleanup Revision: distcc--devel--2--patch-86 modified files: ChangeLog src/mon-gnome.c 2004-07-12 07:23:46 GMT Martin Pool patch-85 Summary: make sure idle periods get drawn in history Revision: distcc--devel--2--patch-85 modified files: ChangeLog src/renderer.c 2004-07-12 07:21:41 GMT Martin Pool patch-84 Summary: mon-gnome: Use circular array not GQueue for history Revision: distcc--devel--2--patch-84 Using a doubly-linked list to hold integers uses a lot of time and memory. Instead we use just a simple circular array. history.c: New file holding this. new files: src/.arch-ids/history.c.id src/history.c modified files: ChangeLog Makefile.in NEWS src/mon-gnome.c src/mon.h src/renderer.c 2004-07-12 06:53:56 GMT Martin Pool patch-83 Summary: s/dcc_history/dcc_task_state/ Revision: distcc--devel--2--patch-83 modified files: ChangeLog src/mon-fake.c src/mon-gnome.c src/mon-text.c src/mon.c src/mon.h src/state.c src/state.h 2004-07-12 06:49:54 GMT Martin Pool patch-82 Summary: s/dcc_state/dcc_phase/ Revision: distcc--devel--2--patch-82 modified files: ChangeLog src/mon-fake.c src/mon-gnome.c src/mon-text.c src/mon.c src/mon.h src/renderer.c src/renderer.h src/state.c src/state.h 2004-07-12 06:46:16 GMT Martin Pool patch-81 Summary: Rename DCC_STATE_* to DCC_PHASE_* Revision: distcc--devel--2--patch-81 modified files: ChangeLog src/clirpc.c src/compile.c src/mon-fake.c src/mon-gnome.c src/mon-text.c src/mon.c src/remote.c src/renderer.c src/renderer.h src/state.c src/state.h src/where.c 2004-07-12 06:45:29 GMT Martin Pool patch-80 Summary: Fix warning Revision: distcc--devel--2--patch-80 modified files: ChangeLog src/daemon.h 2004-07-12 06:39:40 GMT Martin Pool patch-79 Summary: Doc Revision: distcc--devel--2--patch-79 modified files: ChangeLog src/mon-gnome.c 2004-07-12 06:20:10 GMT Martin Pool patch-78 Summary: dcc_draw_state_stripe: inline into the only caller Revision: distcc--devel--2--patch-78 modified files: ChangeLog src/renderer.c 2004-07-12 05:24:32 GMT Martin Pool patch-77 Summary: Doc Revision: distcc--devel--2--patch-77 modified files: ChangeLog src/renderer.c 2004-07-09 05:16:20 GMT Martin Pool patch-76 Summary: todo: monitor ideas Revision: distcc--devel--2--patch-76 new files: doc/todo/.arch-ids/monitor-clear.txt.id doc/todo/.arch-ids/monitor-count.txt.id doc/todo/monitor-clear.txt doc/todo/monitor-count.txt modified files: ChangeLog 2004-07-09 04:56:11 GMT Martin Pool patch-75 Summary: benchmark: notes on building glibc Revision: distcc--devel--2--patch-75 modified files: ChangeLog bench/ProjectDefs.py 2004-07-08 07:40:50 GMT Martin Pool patch-74 Summary: fix warnings about sockaddr Revision: distcc--devel--2--patch-74 modified files: ChangeLog src/netutil.h 2004-07-08 07:39:35 GMT Martin Pool patch-73 Summary: setuid.h: remove Revision: distcc--devel--2--patch-73 removed files: src/.arch-ids/setuid.h.id src/setuid.h modified files: ChangeLog Makefile.in src/daemon.c src/daemon.h src/dopt.c src/setuid.c 2004-07-08 07:36:08 GMT Martin Pool patch-72 Summary: filename.h: remove Revision: distcc--devel--2--patch-72 removed files: src/.arch-ids/filename.h.id src/filename.h modified files: ChangeLog Makefile.in src/arg.c src/argutil.c src/cpp.c src/distcc.c src/distcc.h src/filename.c src/h_exten.c src/h_issource.c src/implicit.c src/mon-notify.c src/mon-text.c src/mon.c src/serve.c src/srvrpc.c src/state.c 2004-07-08 07:32:43 GMT Martin Pool patch-71 Summary: cpp.h: removed Revision: distcc--devel--2--patch-71 removed files: src/.arch-ids/cpp.h.id src/cpp.h modified files: ChangeLog Makefile.in src/compile.c src/cpp.c src/distcc.h 2004-07-08 07:31:15 GMT Martin Pool patch-70 Summary: strip.h: removed Revision: distcc--devel--2--patch-70 removed files: src/.arch-ids/strip.h.id src/strip.h modified files: ChangeLog doc/roadmap.txt src/compile.c src/cpp.c src/distcc.h src/h_strip.c src/strip.c 2004-07-08 06:02:34 GMT Martin Pool patch-69 Summary: doc Revision: distcc--devel--2--patch-69 modified files: ChangeLog src/mon-text.c 2004-07-08 05:57:05 GMT Martin Pool patch-68 Summary: note leak fixes Revision: distcc--devel--2--patch-68 modified files: ChangeLog 2004-07-08 05:56:54 GMT Martin Pool patch-67 Summary: distccmon-text: fix memory leak Revision: distcc--devel--2--patch-67 modified files: ChangeLog src/mon-text.c 2004-07-08 05:52:06 GMT Martin Pool patch-66 Summary: dcc_history_free: Fix memory leak Revision: distcc--devel--2--patch-66 modified files: ChangeLog src/mon.c 2004-07-08 05:48:31 GMT Martin Pool patch-65 Summary: mon-gnome: fix leak in setting title; don't set title twice Revision: distcc--devel--2--patch-65 modified files: ChangeLog src/mon-gnome.c 2004-07-08 05:10:10 GMT Martin Pool patch-64 Summary: dcc_mon_load_state: fix leak on error path Revision: distcc--devel--2--patch-64 modified files: ChangeLog NEWS src/mon.c 2004-07-08 04:56:58 GMT Martin Pool patch-63 Summary: Prepare for 2.16 release Revision: distcc--devel--2--patch-63 modified files: ChangeLog NEWS configure.ac 2004-07-08 04:52:43 GMT Martin Pool patch-62 Summary: distccmon-gnome: use a GNOME status bar with a grab handle Revision: distcc--devel--2--patch-62 Patch from Nathan Fredrickson. modified files: ChangeLog NEWS src/mon-gnome.c 2004-07-08 04:32:35 GMT Martin Pool patch-61 Summary: testdistcc.py: update to work on ia64 linux Revision: distcc--devel--2--patch-61 modified files: ChangeLog NEWS test/testdistcc.py 2004-07-08 04:31:44 GMT Martin Pool patch-60 Summary: Rephrase news Revision: distcc--devel--2--patch-60 modified files: ChangeLog NEWS 2004-07-07 05:49:15 GMT Martin Pool patch-59 Summary: testdistcc: allow for --version output to have more than two lines Revision: distcc--devel--2--patch-59 modified files: ChangeLog test/testdistcc.py 2004-07-07 05:44:23 GMT Martin Pool patch-58 Summary: dcc_parse_mask: fix 64-bit bugs Revision: distcc--devel--2--patch-58 modified files: ChangeLog NEWS src/access.c 2004-07-07 05:21:02 GMT Martin Pool patch-57 Summary: h_parsemask: stub for trace Revision: distcc--devel--2--patch-57 modified files: ChangeLog src/h_parsemask.c 2004-07-07 04:47:00 GMT Martin Pool patch-56 Summary: dcc_show_version: Include copyright and licence Revision: distcc--devel--2--patch-56 modified files: ChangeLog NEWS src/distcc.c src/distcc.h src/dopt.c src/help.c 2004-07-07 04:38:53 GMT Martin Pool patch-55 Summary: configure: if using system popt, need to use -lpopt Revision: distcc--devel--2--patch-55 modified files: ChangeLog configure.ac 2004-07-07 02:14:54 GMT Martin Pool patch-54 Summary: dcc_log_child_exited: Fix bizarre syntax bug, remove #ifdef Revision: distcc--devel--2--patch-54 modified files: ChangeLog NEWS src/dparent.c 2004-07-07 02:07:47 GMT Martin Pool patch-53 Summary: draft patch for faster polling when blocked Revision: distcc--devel--2--patch-53 new files: patches/.arch-ids/shorter-boredom-poll.diff.id patches/shorter-boredom-poll.diff modified files: ChangeLog 2004-07-07 02:06:53 GMT Martin Pool patch-52 Summary: doc: note popt fix Revision: distcc--devel--2--patch-52 modified files: ChangeLog NEWS 2004-07-07 01:59:58 GMT Martin Pool patch-51 Summary: doc: benchmarks Revision: distcc--devel--2--patch-51 modified files: ChangeLog doc/results.txt 2004-07-07 01:59:39 GMT Martin Pool patch-50 Summary: configure.ac: fix problem detecting popt.h Revision: distcc--devel--2--patch-50 Problem: Some people might have libpopt, but no popt.h, in which case we tried to use the system copy and failed. Fix: Check for popt.h. If not present, use ./popt. modified files: ChangeLog configure.ac 2004-07-06 13:05:12 GMT Martin Pool patch-49 Summary: Prepare for 2.15 release Revision: distcc--devel--2--patch-49 modified files: ChangeLog NEWS configure.ac 2004-07-06 13:00:16 GMT Martin Pool patch-48 Summary: Notes on version checking Revision: distcc--devel--2--patch-48 modified files: ChangeLog doc/todo/version-check.txt 2004-07-06 12:47:38 GMT Martin Pool patch-47 Summary: Doc Revision: distcc--devel--2--patch-47 new files: doc/todo/.arch-ids/monitor-legend.txt.id doc/todo/monitor-legend.txt modified files: ChangeLog 2004-07-06 09:03:44 GMT Martin Pool patch-46 Summary: compress: assume a larger decompression buffer by default so less likely to retry Revision: distcc--devel--2--patch-46 modified files: ChangeLog src/compress.c 2004-07-06 08:50:24 GMT Martin Pool patch-45 Summary: remove mmap/lzo support Revision: distcc--devel--2--patch-45 modified files: ChangeLog NEWS doc/results.txt src/compress.c 2004-07-06 08:27:44 GMT Martin Pool patch-44 Summary: dcc_r_bulk_lzo1x: fix nasty bug in mmap recv lzo Revision: distcc--devel--2--patch-44 When reading in compressed data, our initial buffer might not be large enough for the actual compressed data, so we need to free it and make a larger one. When freeing the mmapped buffer, we need to pass both address and length of the mapping. The bug was that we increased the length before unmapping and therefore randomly unmapped some block of memory, causing a crash later on. Fix: don't increase the length until we're done with the old value. This code is really too complex to be safe. modified files: ChangeLog src/compress.c 2004-07-06 08:09:27 GMT Martin Pool patch-43 Summary: fix warning Revision: distcc--devel--2--patch-43 modified files: ChangeLog src/daemon.c 2004-07-06 08:09:03 GMT Martin Pool patch-42 Summary: tempfile.h: remove Revision: distcc--devel--2--patch-42 removed files: src/.arch-ids/tempfile.h.id src/tempfile.h modified files: ChangeLog Makefile.in src/backoff.c src/cleanup.c src/cpp.c src/daemon.c src/distcc.c src/distcc.h src/dparent.c src/dsignal.c src/hosts.c src/lock.c src/mon-notify.c src/mon-text.c src/mon.c src/prefork.c src/remote.c src/serve.c src/state.c src/tempfile.c src/timefile.c src/where.c 2004-07-06 08:06:57 GMT Martin Pool patch-41 Summary: distccd: chdir to $TMPDIR not / at startup Revision: distcc--devel--2--patch-41 modified files: ChangeLog NEWS src/daemon.c 2004-07-06 08:05:30 GMT Martin Pool patch-40 Summary: dcc_get_tmp_top: make public Revision: distcc--devel--2--patch-40 modified files: ChangeLog src/tempfile.c src/tempfile.h 2004-07-06 08:00:29 GMT Martin Pool patch-39 Summary: dcc_log_child_exited: indicate if core was produced Revision: distcc--devel--2--patch-39 modified files: ChangeLog src/dparent.c 2004-07-06 05:10:05 GMT Martin Pool patch-38 Summary: Revision: distcc--devel--2--patch-38 modified files: ChangeLog src/arg.c src/argutil.c src/distcc.c src/distcc.h src/implicit.c 2004-07-06 05:03:25 GMT Martin Pool patch-37 Summary: argutil.c: Doc Revision: distcc--devel--2--patch-37 modified files: ChangeLog src/argutil.c 2004-07-06 05:00:57 GMT Martin Pool patch-36 Summary: arg.h: fold into distcc.h Revision: distcc--devel--2--patch-36 removed files: src/.arch-ids/arg.h.id src/arg.h modified files: ChangeLog Makefile.in src/arg.c src/argutil.c src/clirpc.c src/compile.c src/cpp.c src/distcc.c src/distcc.h src/exec.c src/h_argvtostr.c src/h_ccvers.c src/h_scanargs.c src/h_strip.c src/implicit.c src/serve.c src/srvrpc.c src/ssh.c src/strip.c 2004-07-06 04:54:15 GMT Martin Pool patch-35 Summary: dcc_free_argv: new function Revision: distcc--devel--2--patch-35 modified files: ChangeLog src/arg.h src/argutil.c 2004-07-06 04:47:46 GMT Martin Pool patch-34 Summary: Remove redundant temporary file cleanup in non-forking mode. Revision: distcc--devel--2--patch-34 modified files: ChangeLog NEWS src/dparent.c src/serve.c 2004-06-18 23:47:56 GMT Martin Pool patch-33 Summary: roadmap update Revision: distcc--devel--2--patch-33 modified files: ChangeLog doc/roadmap.txt 2004-06-17 04:15:48 GMT Martin Pool patch-32 Summary: Doc Revision: distcc--devel--2--patch-32 modified files: ChangeLog src/lock.c 2004-06-12 08:47:59 GMT Martin Pool patch-31 Summary: dcc_service_job: Doc Revision: distcc--devel--2--patch-31 modified files: ChangeLog src/serve.c 2004-06-11 08:31:22 GMT Martin Pool patch-30 Summary: protocol-3: I think there's no need for hash after all Revision: distcc--devel--2--patch-30 modified files: ChangeLog doc/protocol-3.txt 2004-06-11 08:19:20 GMT Martin Pool patch-29 Summary: protocol-3: describe request format; propose adding CRC Revision: distcc--devel--2--patch-29 modified files: ChangeLog doc/protocol-3.txt 2004-06-10 04:55:25 GMT Martin Pool patch-28 Summary: protocol-3 design development Revision: distcc--devel--2--patch-28 modified files: ChangeLog doc/protocol-3.txt 2004-06-10 03:18:55 GMT Martin Pool patch-27 Summary: todo: notes on file permissions Revision: distcc--devel--2--patch-27 new files: doc/todo/.arch-ids/permissions.txt.id doc/todo/permissions.txt modified files: ChangeLog TODO 2004-06-10 02:47:13 GMT Martin Pool patch-26 Summary: cases/hello.c: Include more headers to trigger compression Revision: distcc--devel--2--patch-26 modified files: ChangeLog cases/hello.c 2004-06-01 06:52:14 GMT Martin Pool patch-25 Summary: distccmon-text(1) typo fix from Lisa Revision: distcc--devel--2--patch-25 modified files: ChangeLog man/distccmon-text.1 2004-05-30 05:54:37 GMT Martin Pool patch-24 Summary: Add fixme comments for places where memory is probably leaked Revision: distcc--devel--2--patch-24 modified files: ChangeLog src/arg.c src/compile.c src/cpp.c src/where.c 2004-05-30 05:48:09 GMT Martin Pool patch-23 Summary: Doc Revision: distcc--devel--2--patch-23 new files: doc/todo/.arch-ids/gnome-leak.txt.id doc/todo/gnome-leak.txt modified files: ChangeLog 2004-05-29 05:10:27 GMT Martin Pool patch-22 Summary: More TODO notes on scheduling Revision: distcc--devel--2--patch-22 new files: doc/todo/.arch-ids/host-selection.txt.id doc/todo/.arch-ids/randomize-order.txt.id doc/todo/host-selection.txt doc/todo/randomize-order.txt modified files: ChangeLog 2004-05-28 23:42:32 GMT Martin Pool patch-21 Summary: patch from joshh to randomize host list Revision: distcc--devel--2--patch-21 In http://lists.samba.org/archive/distcc/2004q2/002250.html, Dan proposed randomizing the hosts list. Here's a patch to add that feature, controlled by a special --randomize option in the hosts list. On a large shared build cluster, this helps spread the load without requiring separate hosts lists for each user. Martin, what do you think? new files: patches/.arch-ids/joshh-random.diff.id patches/joshh-random.diff modified files: ChangeLog 2004-05-08 12:16:47 GMT Martin Pool patch-20 Summary: Update plans Revision: distcc--devel--2--patch-20 new files: doc/todo/.arch-ids/window-geometry.txt.id doc/todo/window-geometry.txt modified files: ChangeLog doc/roadmap.txt 2004-05-06 03:20:08 GMT Martin Pool patch-19 Summary: 'make uninstall' note Revision: distcc--devel--2--patch-19 new files: doc/todo/.arch-ids/make-uninstall.txt.id doc/todo/make-uninstall.txt modified files: ChangeLog 2004-05-05 06:34:07 GMT Martin Pool patch-18 Summary: Doc Revision: distcc--devel--2--patch-18 modified files: ChangeLog NEWS src/remote.c 2004-05-03 00:41:02 GMT Martin Pool patch-17 Summary: Red Hat fix from Colin Revision: distcc--devel--2--patch-17 Patches applied: * walters@verbum.org--2003/distcc--devel--2.14--patch-5 merge from mbp * walters@verbum.org--2003/distcc--devel--2.14--patch-6 actually expand variables modified files: ChangeLog contrib/redhat/init contrib/redhat/logrotate contrib/redhat/xinetd new patches: walters@verbum.org--2003/distcc--devel--2.14--patch-5 walters@verbum.org--2003/distcc--devel--2.14--patch-6 2004-05-02 10:42:57 GMT Martin Pool patch-16 Summary: Note rate calculation Revision: distcc--devel--2--patch-16 modified files: ChangeLog NEWS 2004-05-02 10:40:35 GMT Martin Pool patch-15 Summary: Client calculates overall compilation rate for remote jobs Revision: distcc--devel--2--patch-15 modified files: ChangeLog src/bulk.c src/distcc.h src/remote.c 2004-05-02 10:30:00 GMT Martin Pool patch-14 Summary: Collect SSH child even when it fails Revision: distcc--devel--2--patch-14 modified files: ChangeLog src/remote.c 2004-05-02 10:22:22 GMT Martin Pool patch-13 Summary: Remove unnecessary check that cpp produced output Revision: distcc--devel--2--patch-13 modified files: ChangeLog src/remote.c 2004-05-02 10:20:01 GMT Martin Pool patch-12 Summary: Pass back size of transmitted files Revision: distcc--devel--2--patch-12 Also fix printf formats for file sizes. Remove old prototype for dcc_x_file_timed. modified files: ChangeLog src/bulk.c src/bulk.h src/remote.c src/serve.c 2004-05-02 10:06:11 GMT Martin Pool patch-11 Summary: Ignore gtags temporaries Revision: distcc--devel--2--patch-11 modified files: ChangeLog src/.arch-inventory 2004-05-02 10:05:11 GMT Martin Pool patch-10 Summary: Remove dcc_send_job_corked wrapper Revision: distcc--devel--2--patch-10 Just insert/remove corks at the right places. modified files: ChangeLog src/remote.c 2004-05-02 10:00:52 GMT Martin Pool patch-9 Summary: Split out code to wait for cpp Revision: distcc--devel--2--patch-9 modified files: ChangeLog src/remote.c 2004-05-02 09:58:22 GMT Martin Pool patch-8 Summary: Refactor code to send requests into remote.c Revision: distcc--devel--2--patch-8 modified files: ChangeLog src/clirpc.c src/distcc.h src/remote.c 2004-05-02 09:49:23 GMT Martin Pool patch-7 Summary: Plan for calculating rate Revision: distcc--devel--2--patch-7 new files: doc/todo/.arch-ids/show-rate.txt.id doc/todo/show-rate.txt modified files: ChangeLog 2004-05-02 09:38:40 GMT Martin Pool patch-6 Summary: Remove relic zip.c Revision: distcc--devel--2--patch-6 removed files: src/.arch-ids/zip.c.id src/zip.c modified files: ChangeLog Makefile.in 2004-05-02 09:35:26 GMT Martin Pool patch-5 Summary: Remove old prototypes Revision: distcc--devel--2--patch-5 modified files: ChangeLog src/daemon.h src/dparent.c 2004-05-02 08:46:14 GMT Martin Pool patch-4 Summary: Remove non-prefork mode Revision: distcc--devel--2--patch-4 Only choices now are preforking, or not forking at all. modified files: ChangeLog NEWS src/dopt.c src/dparent.c 2004-05-02 08:35:51 GMT Martin Pool patch-3 Summary: Set version to 2.15pre Revision: distcc--devel--2--patch-3 modified files: ChangeLog NEWS configure.ac 2004-05-02 08:34:49 GMT Martin Pool patch-2 Summary: Plans for upcoming releases Revision: distcc--devel--2--patch-2 modified files: ChangeLog doc/roadmap.txt 2004-05-02 08:25:17 GMT Martin Pool patch-1 Summary: New ChangeLog for new revision Revision: distcc--devel--2--patch-1 new files: ChangeLog renamed files: ChangeLog ==> ChangeLog-2.14 2004-05-02 05:07:46 GMT Martin Pool base-0 Summary: tag of mbp@sourcefrog.net--2004/distcc--devel--2.14--version-0 Revision: distcc--devel--2--base-0 (automatically generated log message) new patches: mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--base-0 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-1 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-2 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-3 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-4 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-5 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-6 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-7 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-8 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-9 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-10 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-11 mbp@sourcefrog.net--2004-happy/distcc--devel--2.14--patch-12 mbp@sourcefrog.net--2004/distcc--cvs--0--base-0 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-1 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-2 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-3 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-4 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-5 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-6 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-7 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-8 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-9 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-10 mbp@sourcefrog.net--2004/distcc--cvs--0--patch-11 mbp@sourcefrog.net--2004/distcc--devel--2.14--base-0 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-1 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-2 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-3 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-4 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-5 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-6 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-7 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-8 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-9 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-10 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-11 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-12 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-13 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-14 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-15 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-16 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-17 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-18 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-19 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-20 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-21 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-22 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-23 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-24 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-25 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-26 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-27 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-28 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-29 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-30 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-31 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-32 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-33 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-34 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-35 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-36 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-37 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-38 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-39 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-40 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-41 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-42 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-43 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-44 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-45 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-46 mbp@sourcefrog.net--2004/distcc--devel--2.14--patch-47 mbp@sourcefrog.net--2004/distcc--devel--2.14--version-0 mbp@sourcefrog.net--2004/distcc--release--2.13--base-0 walters@verbum.org--2003/distcc--devel--2.14--base-0 walters@verbum.org--2003/distcc--devel--2.14--patch-1 walters@verbum.org--2003/distcc--devel--2.14--patch-2 walters@verbum.org--2003/distcc--devel--2.14--patch-3 walters@verbum.org--2003/distcc--devel--2.14--patch-4 ## These changes are from before development was done under arch. 2004-04-10 Martin Pool * src/mon-gnome.c (dcc_gnome_make_mainwin): Check gtk version and don't use gtk_window_set_icon_from_file before 2.2.0. Reported by Dag Wieers. 2004-03-21 Martin Pool * src/exec.c (dcc_critique_status): Log input filename. * src/clirpc.c (dcc_send_job): Log input filename, * src/remote.c (dcc_compile_remote): Log input filename. * src/serve.c (dcc_run_job): Log input filename. * src/compile.c (dcc_compile_local): Log input filename. 2004-03-03 Martin Pool * src/mon-gnome.c: Quieten g_messages. * src/distcc.c (dcc_show_usage): Describe DISTCC_DIR and other things. * man/distcc.1: Document DISTCC_DIR and fix some spelling errors. Patch from Thomas Schwinge. * src/hosts.c (dcc_get_hostlist): Get hosts from $DISTCC_DIR/hosts, rather than hardcoding to ~/.distcc. * src/tempfile.c (dcc_get_top_dir): Make this public. Just log a warning if $HOME is not set. 2004-03-02 Martin Pool * src/srvnet.c (dcc_listen_by_addr): Don't create the socket, just listen() on it. (dcc_check_client): Do access control checks on ipv4-mapped or ipv4-compat IPv6 addresses. * src/srvnet.c (dcc_socket_listen) [ENABLE_RFC2553]: Try creating sockets in every returned address family until we get one that works. Fix leak of addrinfo list. * src/srvnet.c (dcc_socket_listen) [!ENABLE_RFC2553]: Create socket here. 2004-03-01 Martin Pool * src/cleanup.c (dcc_cleanup_tempfiles): If DISTCC_SAVE_TEMPS is set, then we still need to remove temp files from the list or it will overflow. * src/mon-gnome.c, src/mon.c: Don't include netutil. * src/dparent.c (dcc_standalone_server): Set defer-accept bit. * man/distccd.1: Document DISTCC_TCP_DEFER_ACCEPT. * src/netutil.c (dcc_defer_accept): New function. 2004-02-29 Martin Pool * test/testdistcc.py (ScanArgs_Case): Test -Wa,-xarch=v8. * src/arg.c (dcc_scan_args): Allow "-Wa,-xarch=v8" to be remote. Reported by Ben Scarlet. * test/testdistcc.py (ScanArgs_Case): Add test cases for -x handling. * src/arg.c (dcc_scan_args): Handle invocations like "-xcpp" with no space after -x. Suggested by Ben Scarlet. * test/testdistcc.py (CompressedCompile_Case): Add a test of compression. * src/mon-gnome.c: Include sys/loadavg.h if available. * configure.ac: Check for sys/loadavg.h. Suggested by Dimitri Papadopoulos. * man/distcc.1: Document comments in host files. * test/testdistcc.py (ParseHostSpec_Case): Add test for "localhostbutnotreally". * src/hosts.c (dcc_parse_hosts): Fix matching of hosts with names like "localhost2". 2004-02-20 Martin Pool * src/compress.c (dcc_r_bulk_lzo1x): ftruncate the file after munmapping, rather than before. Might be better on HP-UX which has problems with IO on mapped files. * README.packaging: Update description of why packagers should change version numbers. 2004-02-19 Martin Pool * src/netutil.c (dcc_sockaddr_to_string): Handle null sockaddr. * src/srvnet.c (dcc_check_client): Handle null sockaddr. * src/daemon.c (dcc_inetd_server): If there is no sockaddr, pass it as NULL. * src/netutil.c (dcc_sockaddr_to_string) [ENABLE_RFC2553]: Failure to convert the address to a string should be just a warning, not an error. Add special cases for unix-domain sockets and unknown address families. Possibly fixes SSH connections with ENABLE_RFC2553. * src/daemon.c (dcc_inetd_server): Downgrade warning on getpeername failure to just a notice message. 2004-02-19 Albert China * test/testdistcc.py: Get test suite working on most of the platforms we support: 1. Not much use in testing with the native compiler so we *force* the test suite to use gcc. 2. Rather than picking up gcc from $PATH, we pass the full path to GCC. This avoids problems when distccd is running. 3. I've added known failures on some platforms. For example, the assembler test should only run on Linux x86. Where we know the test will fail, we print: DashONoSpace_Case NOTRUN, GCC mips-tfile wants space after -o ... RemoteAssemble_Case NOTRUN, Linux x86 only PreprocessAsm_Case NOTRUN, Linux x86 only ... The tests pass on: HP-UX 10.20, 11.00, 11i; IRIX 6.5; Redhat Linux 7.1, 9; Solaris 7, 8, 9; Tru64 UNIX 4.0d, 5.1 2004-02-18 Albert China These patches were tested on: AIX 4.3.2, 5.1; HP-UX 10.20, 11.00, 11i; IRIX 6.5; Redhat Linux 7.1, 9; Solaris 2.5.1, 2.6, 7, 8, 9; Tru64 UNIX 4.0D, 5.1: * src/exitcode.h: IBM C compiler doesn't like trailing commas after last enum constant. * src/clinet.c: Define h_errno for HP-UX 10.20. * src/distcc.h: Forward declaration of 'struct sockaddr' gives problems with IBM C compiler. And, it's not needed. * src/serve.c: Forgot to include Needed on HP-UX 10.20, 11.00, 11i. * src/types.h: Remove definition of socklen_t if unavailable. We not declare it correctly via autoconf. * configure.ac: a) Better detection for socklen_t. This code is taken from curl but we submitted it so we own the copyright. Feel free to use as you please. b) Existence of mmap() doesn't imply MAP_FAILED exists. So, test and define it if unavailable. c) Replace the AC_CHECK_FUNCS(connect) mess. 2004-01-30 Martin Pool * src/hosts.c (dcc_parse_hosts): Fix problem where we accidentally detected localhost at end of string. * src/h_hosts.c (main): Fix up verbose mode. * test/testdistcc.py (ParseHostSpec_Case.runtest): Test parsing of comments in host specifications. * src/hosts.c (dcc_parse_hosts): Skip over hash comments in host specifications. 2004-01-11 Martin Pool * src/srvnet.c (dcc_check_client): Take list of allowed addresses as a new parameter so that this file doesn't depend on opt.c. * src/h_sa2str.c: New test harness. * Makefile.in (h_sa2str): new test. 2004-01-09 Martin Pool * configure.ac: Make --without-gnome, --without-gtk, --disable-profile all turn the relevant options off rather than on. * Makefile.in: Add man/distccmon-text.1, and clean up manpage handling. * man/distccmon-text.1: Fix some typos. * src/dopt.c (distccd_parse_options): Option arguments should be held in (const char *). * src/setuid.c (dcc_discard_root): Must setuid after setgid, not before. Fix from Wayne Davison. * src/mon.c (dcc_mon_check_orphans): When checking if a process exists, accept EPERM as indicating it exists but isn't ours. This allows watching the directory of a different user. Reported by Ernst Bachmann. 2003-12-21 Shri Shrikumar * man/distccmon-text.1: New manpage. 2003-12-15 Martin Pool * man/distccd.1: Mention TMPDIR. * man/distcc.1: We don't use a subdirectory of TMPDIR anymore. 2003-11-28 Harold L Hunt II * configure.ac, Makefile.in: Add --with-docdir=PATH option to set install location for documents. The default is the same as previously: ${datadir}/doc/distcc. 2003-11-28 Martin Pool * src/distcc.h (dcc_sockaddr_storage): Different method for choosing the type for dcc_sockaddr_storage. We now use a plain sockaddr unless RFC2553 was requested, in which case we use sockaddr_storage. HAVE_SOCKADDR_STORAGE is only used as a check that the RFC2553 implementation is reasonable. * src/distcc.h (dcc_sockaddr_storage): Use a new type name for our replacement of sockaddr_storage, rather than calling it sockaddr_storage, to make it more clear that it's determined by autoconf. * src/prefork.c (dcc_preforked_child): Use dcc_sockaddr_storage. * src/dparent.c (dcc_forking_parent): Likewise. * src/daemon.c (dcc_inetd_server): Likewise. 2003-11-23 Martin Pool * src/netutil.c (dcc_sockaddr_to_string) [ENABLE_RFC2553]: Include the port number in the returned string, as for !ENABLE_RFC2553. This looks a bit wierd for IPv6 but is legible and unambiguous at least for output. Increase static buffer size. * src/clinet.c (dcc_connect_timed): Check SO_ERROR to see if the connection failed so that we can trap it at this point rather than waiting until we start doing IO. * src/distcc.h [ENABLE_RFC2553]: sockaddr_storage is required for RFC2553. * src/dparent.c (dcc_nofork_parent, dcc_forking_parent): Socket addresses should be stored on the stack in sockaddr_storage so that IPv6 addresses will fit. We always have this type, or can simulate it. * src/prefork.c (dcc_preforked_child): Likewise. * src/srvnet.c (dcc_socket_listen) [ENABLE_RFC2553]: Don't prefer to listen on IPv4 addresses, just use whatever the operating system thinks is best. * INSTALL: Suggest using --with-gnome and --enable-rfc2553. * man/distccd.1: Add description of --log-level. * src/dopt.c: New --log-level option to accomodate people who only want to log errors. * src/trace.c, src/trace.h (rs_loglevel_from_name): New function. * configure.ac, Makefile.in: Check pkg-config information for GNOME/GTK+ at configure time, not build time. This is a bit quicker than running the script for every file we build, and means that PKG_CONFIG_PATH only needs to be set for configure. * src/lock.c: Doc. 2003-11-17 Lionel Sausin * man/fr/distcc.1, man/fr/distccd.1: French translations of the manual pages. 2003-11-17 Martin Pool * distcc.h: MAXPATHLEN is not defined on GNU/Hurd, so supply a reasonable default value of 4096. Reported by Santiago Vila. 2003-11-17 Martin Pool * sendfile.c: Documentation updates. 2003-11-17 Allan Saddi * sendfile.c (sys_sendfile): BSD implementation of this function needs to return -1 when transmission fails with EAGAIN and no bytes were sent. 2003-11-17 Martin Pool * setuid.c (dcc_discard_root): Wayne suggests calling setgid()/setuid() before doing setgroups(). setgroups() on Mac OS X Jaguar can't seem to handle setting to 0 groups, so just set it to the same as the regular group. 2003-10-30 19:02 Martin Pool * doc/release-names.txt: [no log message] 2003-10-28 11:38 Martin Pool * configure.ac: Bump version. 2003-10-23 13:36 Martin Pool * autogen.sh: Remove check on autoconf version because it breaks on non-numeric versions like "2.57a". 2003-10-23 10:50 Martin Pool * man/distccd.1: Add some description of search paths. 2003-10-23 10:44 Martin Pool * man/distcc.1: Add some description of search paths. 2003-10-23 10:14 Martin Pool * TODO: More tasks to do. 2003-10-23 09:56 Martin Pool * NEWS, configure.ac: Prepare for 2.11.2 release 2003-10-14 14:23 Martin Pool * gnome/distccmon-gnome.desktop, NEWS: Desktop file corrections from Dag Wieers. 2003-10-13 23:57 Martin Pool * TODO: Notes on current bugs. 2003-10-13 20:05 Martin Pool * src/distcc.c: Don't trim the path at all when our invocation name is "distcc". 2003-10-13 19:52 Martin Pool * src/util.c: dcc_trim_path: Trace the compiler name. 2003-10-13 19:51 Martin Pool * src/util.c: dcc_trim_path: Doc. 2003-10-13 19:39 Martin Pool * src/distcc.c: Doc. 2003-10-13 19:24 Martin Pool * src/climasq.c: Doc. 2003-10-13 19:03 Martin Pool * NEWS, src/distcc.c, src/dsignal.c: Fatal signal handlers for client and daemon should reset the signal vector before doing anything else, to protect against an (unlikely) spin if the signal is re-sent. 2003-10-13 19:00 Martin Pool * src/distcc.c: Doc typo 2003-10-13 18:39 Martin Pool * src/: distcc.c, dsignal.c: Use AC_TYPE_SIGNAL to set signal handler return type for portability. 2003-10-13 18:38 Martin Pool * doc/example/xinetd, NEWS: Add type = UNLISTED to cope without an /etc/services entry. 2003-10-13 18:34 Martin Pool * configure.ac: Doc * Add check for signal return type. 2003-10-13 17:56 Martin Pool * man/distcc.1: Bump date. 2003-10-13 17:56 Martin Pool * man/distcc.1, NEWS: Clear up meaning of UNCACHED_ERR_FD. 2003-10-13 17:37 Martin Pool * README.packaging: Suggest adding to /etc/services. 2003-10-13 17:06 Martin Pool * man/distccd.1: Clarifications/corrections to --allow description. 2003-10-13 16:52 Martin Pool * NEWS: IRIX fixes. 2003-10-13 16:42 Martin Pool * src/serve.c: dcc_check_compiler_masq: Remove dead variable. 2003-10-13 16:40 Martin Pool * src/dparent.c: dcc_log_child_exited: Use appropriate log severity to match the signal severity, even on machines that don't have strsignal(). 2003-10-13 16:37 Martin Pool * TODO: Notes on better scheduling. 2003-10-13 16:26 Martin Pool * NEWS: Remove dependency on libglade. * Fix --without-gnome. 2003-10-13 16:24 Martin Pool * gnome/: distccmon-gnome.glade, distccmon-gnome.gladep: Remove Glade packages. 2003-10-13 16:20 Martin Pool * src/mon-gnome.c: Set icon on monitor window from png file. 2003-10-13 16:15 Martin Pool * src/mon-gnome.c: Remove dependency on Glade by rolling back to by-hand construction of window components, based on the code in 2.10. 2003-10-13 16:10 Martin Pool * Makefile.in: Don't require libglade. 2003-10-13 16:09 Martin Pool * configure.ac: Correct the handling of --without-gnome, etc. Previously this was treated the same as --with-gnome. * Don't require libglade. 2003-10-13 15:31 Martin Pool * configure.ac: Bump version 2003-10-08 15:47 Martin Pool * NEWS, configure.ac: Prepare for 2.11.1 release. 2003-10-08 15:45 Martin Pool * NEWS, src/arg.c, test/testdistcc.py: C++ compilation with -frepo must be local, because it emits .rpo files. 2003-10-07 16:12 Martin Pool * src/bulk.c: dcc_x_file_lzo1x should return any errors that occur. 2003-10-07 16:07 Martin Pool * src/exec.c: dcc_inside_child should be void and should never return. 2003-10-07 16:01 Martin Pool * src/: util.c, util.h: dcc_exit can be void. 2003-10-07 15:52 Martin Pool * man/distcc.1: Typo fix from Lionel Sausin. 2003-10-01 13:56 Martin Pool * src/mon.h, NEWS: Description from Frerich of how to write monitor programs, with some edits by me. 2003-09-30 12:54 Martin Pool * NEWS: Put Gnome data files into PKGDATADIR, e.g. /usr/local/share/distcc/, rather than the top-level datadir. 2003-09-30 12:49 Martin Pool * Makefile.in, src/mon-gnome.c: Put Gnome data files into PKGDATADIR, e.g. /usr/local/share/distcc/, rather than the top-level datadir. 2003-09-30 12:42 Martin Pool * configure.ac, Makefile.in: New @INSTALL_GNOME@ substitution so that Gnome/GTK data files are only installed when necessary. 2003-09-30 12:40 Martin Pool * INSTALL: Give dependencies for --with-gtk. 2003-09-30 09:54 Martin Pool * src/state.h: Remove stdint.h. We don't use it, and it does not exist on FreeBSD 4-STABLE, according to Frerich Raabe. 2003-09-29 22:23 Martin Pool * man/distcc.1: Set datestamp. 2003-09-29 22:21 Martin Pool * NEWS: Fix for state.h 2003-09-29 22:19 Martin Pool * man/distcc.1: Documentation corrections from Lionel Sausin. 2003-09-29 16:57 Martin Pool * src/tempfile.c, NEWS: Check that we have permission to write to the specified TMPDIR, or otherwise fail. 2003-09-29 16:46 Martin Pool * src/mon.h: Doc rename to dcc_history. 2003-09-29 16:44 Martin Pool * src/mon.h: Explain why dnotify is cut out. 2003-09-29 16:33 Martin Pool * NEWS: stdint.h is not on iricks or sloaris either. 2003-09-29 16:30 Martin Pool * src/access.c, src/h_parsemask.c, src/mon-text.c, src/state.c, configure.ac: Remove stdint.h. We don't use it, and it does not exist on FreeBSD 4-STABLE, according to Frerich Raabe. 2003-09-29 16:16 Martin Pool * configure.ac: Make it just --with-gtk. 2003-09-29 16:15 Martin Pool * configure.ac: Fix help string for --with-gtk+. 2003-09-29 16:13 Martin Pool * NEWS, configure.ac: Add support for building with either GNOME or plain GTK+. 2003-09-29 16:08 Martin Pool * src/mon-gnome.c: Remove unnecessary inclusion of headers for pango. * Allow compilation with either GNOME or plain GTK+, depending on WITH_GNOME and WITH_GTK. 2003-09-29 16:06 Martin Pool * src/renderer.c: Remove unnecessary inclusion of headers for gnome, pango and glade, and use of gettext macro. 2003-09-27 23:13 Martin Pool * src/state.h: Fix state.h for use with C++. Patch from Frerich Raabe. 2003-09-27 19:42 Martin Pool * configure.ac: Bump version. 2003-09-25 13:39 Martin Pool * src/mon-gnome.c: Include GTK as well. 2003-09-24 15:33 Martin Pool * Makefile.in: Change for new log archiving method. 2003-09-23 16:12 Martin Pool * NEWS: Prepare for release. 2003-09-23 15:58 Martin Pool * configure.ac: Run tests for GNOME packages when --with-gnome is set. 2003-09-23 15:51 Martin Pool * configure.ac: Bump to version 2.11. 2003-09-23 15:43 Martin Pool * NEWS, src/distcc.c: Client catches SIGINT, SIGHUP and SIGTERM and cleans up temporary files before terminating. 2003-09-23 15:26 Martin Pool * NEWS: Make directories and state files with weak mode bits, to try to avoid conflicts in shared distcc_dirs. 2003-09-23 15:24 Martin Pool * src/tempfile.c: dcc_mkdir: Make directory with weak mode bits, to try to avoid conflicts in shared distcc_dirs. 2003-09-23 15:22 Martin Pool * src/lock.c: dcc_open_lockfile: Open lockfile with weak mode bits, to try to avoid conflicts in shared distcc_dirs. 2003-09-23 15:18 Martin Pool * gnome/: .cvsignore, distccmon-gnome-icon.png, distccmon-gnome.desktop, distccmon-gnome.glade, distccmon-gnome.gladep: Merge from branch-pretty. Update desktop file to include the right name. 2003-09-23 15:12 Martin Pool * Makefile.in: Distribute and install GNOME data files. 2003-09-23 15:00 Martin Pool * NEWS: Change to --with-gnome for consistency with other packages. 2003-09-23 14:57 Martin Pool * test/testdistcc.py: The access mask 1.2.3.4/0 should match anything. 2003-09-23 14:53 Martin Pool * src/distcc.c: Fix bad bug in main() that caused us to exit through the wrong path. 2003-09-23 14:38 Martin Pool * configure.ac, INSTALL: Change to --with-gnome for consistency with other packages. 2003-09-23 14:28 Martin Pool * configure.ac: LINUXDOC is no longer a special variable. 2003-09-23 14:23 Martin Pool * INSTALL, Makefile.in, NEWS, TODO, configure.ac, doc/release-names.txt, src/clirpc.c, src/compile.c, src/distcc.c, src/distcc.h, src/mon-fake.c, src/mon-gnome.c, src/mon-text.c, src/mon.c, src/mon.h, src/remote.c, src/renderer.c, src/renderer.h, src/state.c, src/state.h, src/util.c, src/util.h, src/where.c: Merge the new GNOME monitor back from 'branch-pretty': * GNOME monitor now uses a custom GtkCellRenderer subclass (renderer.c, renderer.h) to draw a scarf-style history of the states for the slot. * Now uses binary state files that are quicker to write out and read in. Not compatible with monitors from the previous version. * Structure renamed from dcc_mon_list to dcc_history. Text fields are held directly in the structure to allow it to be directly written out. * State files are written and rewritten in place, rather than always being renamed into place. We cope reasonably gracefully when reading back files that are truncated. * New strlcpy() utility. * Clean up cruft in dcc_lock_one() from when we had transmission lock files. * Better handling of EXEEXT to allow tab completion to work in Makefiles. * GNOME monitor is now constructed using libglade-2, rather than the hard way. * New --enable-profile option for gprof. * Depends on libglade, pango, libgnome, libgnomeui, at least if you want the graphical monitor. * Change UNUSED() macro to make sure the variable is not accidentally used. * Rename state tags to consistent DCC_STATE_* 2003-09-23 14:02 Martin Pool * Makefile.in: Doc. 2003-09-23 14:00 Martin Pool * src/mon-gnome.c: Change colors to a set selected from the GNOME palette that are easier to distinguish. 2003-09-23 13:44 Martin Pool * gnome/distccmon-gnome.glade, src/mon-gnome.c: Remove About and Key windows, which don't do anything very useful at the moment. 2003-09-22 17:33 Martin Pool * src/mon.c: Check structure size when loading binary state files. 2003-09-22 17:32 Martin Pool * src/: state.c, state.h, where.c: Don't make the client's state structure global. * Don't need dcc_timeval_to_microseconds anymore. 2003-09-22 17:29 Martin Pool * TODO: Remove done items. 2003-09-22 17:24 Martin Pool * src/state.h: Add a size field to the state struct. 2003-09-22 17:22 Martin Pool * src/mon.h: Don't need dcc_timeval_to_double 2003-09-22 17:13 Martin Pool * src/mon-gnome.c: Don't need sys/time.h 2003-09-22 17:12 Martin Pool * src/lock.c: Don't need state.h anymore. 2003-09-22 17:10 Martin Pool * src/: compile.c, distcc.c: Don't use STARTUP state anymore. 2003-09-22 16:50 Martin Pool * INSTALL: Note gnome dependencies. 2003-09-22 15:53 Martin Pool * src/mon-gnome.c: Lower the priority of scanning for changes, so that we're more likely to keep the UI responsive. 2003-09-22 14:53 Martin Pool * src/mon-gnome.c: Doc 2003-09-22 14:51 Martin Pool * src/remote.c: Store hostname in state file, not the host definition string. 2003-09-20 19:36 Martin Pool * NEWS: Try safe lzo decompressor, to try to catch cases where the compressed data is corrupt or our output buffer is too small. 2003-09-20 16:42 Martin Pool * src/compress.c: Try safe lzo decompressor, to try to catch cases where the compressed data is corrupt or our output buffer is too small. 2003-09-19 17:23 Martin Pool * gnome/: distccmon-gnome-icon.png, distccmon-gnome.glade, distccmon-gnome.gladep: Move icons. * Add menu item to show color key. * Set size through allocation of scroll area, not through the window default_size. 2003-09-19 17:21 Martin Pool * src/mon-gnome.c: Add menu option to show chart key. 2003-09-19 17:21 Martin Pool * src/: renderer.c, renderer.h: Set bar width so that the whole history cell is filled. 2003-09-19 16:53 Martin Pool * gnome/.cvsignore: Rename icon PNG 2003-09-19 16:51 Martin Pool * gnome/distccmon-gnome.glade: Rename icon png. 2003-09-19 16:35 Martin Pool * gnome/distccmon-gnome.desktop: Add draft FreeDesktop .desktop definition. 2003-09-19 16:02 Martin Pool * src/renderer.c: Choose bar width such that the complete history roughly fills the cell. 2003-09-19 15:40 Martin Pool * src/mon.c: Quieten warnings when polling state files. 2003-09-19 15:39 Martin Pool * src/state.c: Change state name to "Preprocess". 2003-09-19 15:15 Martin Pool * src/renderer.c: Doc. 2003-09-19 14:57 Martin Pool * src/: mon-gnome.c, renderer.c, renderer.h: Create graphics contexts for drawing state strips just once at startup, rather than every time we draw a rectangle. Ought to be much more efficient. 2003-09-19 14:43 Martin Pool * configure.ac: Add --enable-profile option. * Cleanup CPPFLAGS generation. 2003-09-19 14:29 Martin Pool * src/dparent.c, NEWS: In non-forking mode, make sure to close the accepted fd after processing a request. 2003-09-19 14:01 Martin Pool * NEWS: Allow access masks like 0.0.0.0/0, meaning allow access from anywhere. Some adjustments required to allow for behaviour of C bitshift operators. 2003-09-19 13:58 Martin Pool * src/access.c: Allow access masks like 0.0.0.0/0, meaning allow access from anywhere. Some adjustments required to allow for behaviour of C bitshift operators. 2003-09-19 13:07 Martin Pool * Makefile.in: Use an autoconf substitution for EXEEXT, rather than a Make variable, so that bash's tab completion doesn't get confused by the targets. 2003-09-19 12:45 Martin Pool * NEWS: Manpage updates. 2003-09-19 12:44 Martin Pool * man/distcc.1: Suggest using SCons. 2003-09-19 12:41 Martin Pool * man/distcc.1: [no log message] 2003-09-19 12:35 Martin Pool * man/distcc.1: More explanation of Make and compiler errors. 2003-09-19 12:30 Martin Pool * man/distcc.1: More discussion of where to place localhost in the list. 2003-09-19 12:21 Martin Pool * src/tempfile.c: [no log message] 2003-09-19 12:06 Martin Pool * NEWS: [no log message] 2003-09-19 12:03 Martin Pool * patches/: backlog-sample.c, colorgcc, compression.patch, connect-timeout-02.diff, daemon-address-binding.diff, distcc-ethereal.diff, distcc-hostlist.diff, distcc-hostopt.patch, distccd-clean-path.diff, prefork-sample.c, state-in-home.diff, trylzo.c: Remove obsolete patches. 2003-09-19 11:47 Martin Pool * NEWS: [no log message] 2003-09-18 19:53 Martin Pool * src/mon-gnome.c: Retain history of 100 states. 2003-09-18 18:58 Martin Pool * src/renderer.c: Draw "DONE" states as empty. 2003-09-18 18:32 Martin Pool * src/renderer.c: Render the slot history as a set of state stripes. This looks great! 2003-09-18 18:18 Martin Pool * src/renderer.c: Kill dead code. 2003-09-18 18:01 Martin Pool * src/mon-gnome.c: Trim the history queue length every time we add to it. 2003-09-18 17:58 Martin Pool * src/renderer.c: Cope with the "history" property being a GQueue of state values, rather than a list of dcc_history structures. * Just the first state is drawn through the whole cell at the moment. 2003-09-18 17:57 Martin Pool * src/mon-gnome.c: Fix pointer error in prepending to an existing history queue. 2003-09-18 17:55 Martin Pool * src/mon-gnome.c: Fix up code to insert at end. 2003-09-18 17:48 Martin Pool * src/mon-gnome.c: Actually go ahead and store the state history in a queue in all rows. Create this queue when the row is first inserted. * Change appended rows to go through dcc_insert_row_from_task() so that we can set up the queue. 2003-09-18 17:25 Martin Pool * src/mon-gnome.c: Doc * Store a GQueue of state values in the table row, so that the cell renderer can easily read back all of them and draw them. * Split out code to insert a row into dcc_insert_row_from_task(), because it needs to construct a new GQueue. * rename dcc_clear_row -> dcc_set_row_idle() 2003-09-18 17:05 Martin Pool * src/mon-gnome.c: Fix number of columns. 2003-09-18 17:04 Martin Pool * src/mon-gnome.c: Add textual State column. 2003-09-18 17:00 Martin Pool * src/mon.c: Don't sort localhost specially. I think this was buggy. 2003-09-18 16:28 Martin Pool * src/mon-gnome.c: After we finish the task list, clear any rows remaining in the table. 2003-09-18 16:21 Martin Pool * src/mon-gnome.c: dcc_update_store_from_tasks: Fix bug that caused it to lock up when it hit a host with no name or file or in DONE state. 2003-09-18 16:13 Martin Pool * src/renderer.c: Silently ignore NULL "history" properties. 2003-09-18 16:12 Martin Pool * src/mon-gnome.c: Add a "Slot" column, visible in the list. * First cut at a method for updating the tree model in place, rather than deleting it and creating a new one. Takes advantage of the tree model and the task list being in the same order to detect changed, added or deleted rows. Partially working. 2003-09-18 15:40 Martin Pool * src/mon-gnome.c: Typo 2003-09-18 15:38 Martin Pool * src/mon-gnome.c: Split code for merging task list into list store into new function dcc_update_store_From_tasks(), in preparation for doing an update-in-place rather than clearing it and reloading. * COLUMN_HISTORY is currently set to NULL. It will become a pointer to a list of state values. * task_list is no longer global. It is held in memory only during the update. 2003-09-18 15:22 Martin Pool * gnome/distccmon-gnome.glade: Vertical scrollbar auto; horizontal scrollbar never. 2003-09-18 15:20 Martin Pool * src/mon-gnome.c: Doc. * Move gtk_list_store_new() to near the column number declarations to help keep them in step. * Drop unused dcc_timeval_to_double(). 2003-09-18 15:06 Martin Pool * src/renderer.c: Render the state cell solidly filled with the color for the current state. 2003-09-18 15:02 Martin Pool * src/renderer.c: Remove dead code. 2003-09-18 14:59 Martin Pool * src/mon-gnome.c: Show file name in the table too. 2003-09-18 14:54 Martin Pool * Makefile.in, gnome/distccmon-gnome.glade, src/mon-gnome.c, src/renderer.c: Roll back to using a table and cellrenderer. I think the immediately previous approach of having the monitor keep track of state history and draw an unlabelled striped bar is probably pretty good. However, I'd like to also rely on the regular table widget to give us space to draw it. This code builds and gives an empty table. The renderer is here but disabled. 2003-09-18 14:14 Martin Pool * src/compress.c: Fix up types for printing size_ts and for interfacing with minilzo. Detected when building on ia64 for Debian. 2003-09-18 10:48 Martin Pool * autogen.sh: "sed 1q" is more portable than using head to chop the version out of autoconf. Reported by Alexandre Oliva. 2003-09-18 10:39 Martin Pool * AUTHORS: [no log message] 2003-09-18 10:20 Martin Pool * NEWS: Note portability fixes. 2003-09-18 10:17 Martin Pool * src/ncpus.c, NEWS: In all cases, if we failed to determine the number of CPUs using sysconf, then assume 1. 2003-09-18 10:15 Martin Pool * src/ncpus.c: If we failed to determine the number of CPUs using sysconf, then assume 1. 2003-09-18 10:14 Martin Pool * src/ncpus.c: bsdi can use the BSD method of finding NCPUs as well. Reported by Nick Amato. 2003-09-17 17:24 Martin Pool * src/mon-gnome.c: Accumulate all task lists in a GSList (currently never truncated) and draw striped bars showing past tasks. Currently they are not placed on the right row, so the stripes are all pushed up towards the top. 2003-09-17 16:10 Martin Pool * src/: mon-gnome.c, state.c, state.h: Rework monitor yet again: :-/ * State files no longer hold a history of that process's state, just its current information, and they are removed when the process exits. This means that we cannot get very fine-grained plots of transitions between states, but it seemed to be hard to get that information displayed smoothly without burning a lot of CPU. In addition, we were getting hundreds of leftover state files, which slow down traversing the directory and are not really necessary. I'll try instead putting the burden of remembering and painting history onto the monitor, since it's the only program that really needs that information. 2003-09-17 15:44 Martin Pool * src/mon.c: Files only 60s old are now considered too old. 2003-09-17 15:41 Martin Pool * NEWS, autogen.sh: Fix autogen.sh for recent versions of GNU coreutils. Reported by Lisa Seelye. 2003-09-17 15:36 Martin Pool * src/: state.c, distcc.c: Move back towards removing state files when the client process that they belong to exits. 2003-09-17 12:27 Martin Pool * src/mon-gnome.c: Skip tasks on no host * Draw labels again * Refresh every 300ms 2003-09-17 12:24 Martin Pool * src/renderer.c: GtkCellRenderer is no longer needed 2003-09-17 12:21 Martin Pool * COPYING.FDL: The GNU FDL need not be included, because the SGML manual is gone. All the documentation is in the manpages, which are GPL'd. 2003-09-17 12:16 Martin Pool * man/distcc.1: Set date. 2003-09-17 12:14 Martin Pool * man/: distccd.1, distcc.1: Add no-warranty statement. 2003-09-17 12:11 Martin Pool * Makefile.in: COPYING.FDL is no longer included, because the manpages are GPL'd. 2003-09-16 19:27 Martin Pool * src/mon-gnome.c: Only draw rectangles of >=1 width. 2003-09-16 19:17 Martin Pool * src/: mon-gnome.c, mon.c, state.c, state.h: Handle times as microseconds-since-epoch rather than doubles. * Rework task drawing routine to correctly handle tasks that have already completed. Currently working but a bit slow. 2003-09-16 19:06 Martin Pool * patches/lisa--recursive-mkdir-uid-distccdir.patch: Patch from Lisa. 2003-09-16 19:00 Martin Pool * src/mon-gnome.c: Better attempt at drawing current and previous tasks. 2003-09-16 18:38 Martin Pool * src/distcc.c: Make a better attempt at always recording DONE when we are. 2003-09-16 18:13 Martin Pool * src/mon-gnome.c: Center text labels in bars. * Set bar height to 1.5x text height. * Draw host name once per row. 2003-09-16 18:03 Martin Pool * src/: mon-gnome.c, state.h: Much simpler fix for identifying multiple tasks in the same slot: now that things are sorted properly, we can just find neighbouring history reports and check if they're the same. That should make drawing past tasks easy... 2003-09-16 15:57 Martin Pool * src/state.h: Add a pointer to the next on this slot. 2003-09-16 15:55 Martin Pool * src/mon-gnome.c: Update every 200ms * Allocate rows for each host slot, so that we can draw multiple tasks onto each line. 2003-09-16 15:08 Martin Pool * src/mon.c: Sort localhost to the front of the list of tasks. 2003-09-16 15:04 Martin Pool * src/mon.c: Return list of running tasks sorted by hostname and slot to make monitor displays more likely to keep tasks in a stable position. 2003-09-16 14:36 Martin Pool * src/mon.c: Don't need signal.c 2003-09-16 14:23 Martin Pool * NEWS: Note that we should now work on BSD/OS. 2003-09-16 14:20 Martin Pool * NEWS: Call getpgrp() rather than getpgid(), because it's the POSIX.1 standard function. Suggestion from Nick Amato. 2003-09-16 14:19 Martin Pool * src/exec.c: Call getpgrp() rather than getpgid(), because it's the POSIX.1 standard function. 2003-09-16 13:56 Martin Pool * src/mon-gnome.c: Don't draw border. * Do get proper alignment between host names and task bars. * Include slot number in the name. 2003-09-16 13:28 Martin Pool * src/mon-gnome.c: Draw host names on left. (Not very well. :-) 2003-09-16 13:24 Martin Pool * src/mon-gnome.c: Leave space on the left to draw hostnames, and draw a splitter bar at that point. * Draw a border around the drawingarea. 2003-09-16 13:10 Martin Pool * Makefile.in: Roll back to using a GtkDrawingArea rather than a table. renderer.c is no longer needed. 2003-09-16 13:08 Martin Pool * src/mon-gnome.c: Fix up rollback. 2003-09-16 13:07 Martin Pool * src/mon-gnome.c: Roll back to 1.43.2.37, using a GtkDrawingArea rather than a table. 2003-09-16 12:42 Martin Pool * gnome/distccmon-gnome.glade: Merge back to DrawingArea in 1.1.2.14. No other changes. 2003-09-15 17:57 Martin Pool * src/mon-gnome.c: Redraw the chart more frequently than we reload the task list, so that scrolling seems smoother. 2003-09-15 17:32 Martin Pool * src/renderer.c: Fix horizontal gaps between stripes. 2003-09-15 17:30 Martin Pool * src/mon-gnome.c: Update every 200ms 2003-09-15 17:23 Martin Pool * src/renderer.c: Draw tasks as multiple strips for each state. 2003-09-15 17:18 Martin Pool * src/: mon-gnome.c, mon.h: Remove old GCs * Make dcc_timeval_to_double global 2003-09-15 17:14 Martin Pool * src/mon-fake.c: Split out code for fake monitor data; currently not used. 2003-09-15 17:02 Martin Pool * src/renderer.c: Partially merge some code from the old GtkDrawingArea implementation, so that we have better-factored code for drawing state strips. 2003-09-15 16:50 Martin Pool * src/renderer.c: Fix unused params. 2003-09-15 16:36 Martin Pool * src/distcc.h: UNUSED macro should mangle the variable name to make sure that parameters marked UNUSED are not accidentally used. 2003-09-15 16:34 Martin Pool * src/renderer.c: Draw state color and filename from the history record. 2003-09-15 16:29 Martin Pool * src/mon-gnome.c: Go back to a "history" property, being a pointer to a list of tasks. 2003-09-15 16:21 Martin Pool * src/: renderer.c, mon-gnome.c: Go back to a "history" property, being a pointer to a list of tasks. 2003-09-15 16:04 Martin Pool * src/where.c: Only enter BLOCKED state when we need to sleep waiting for a slot. 2003-09-15 16:03 Martin Pool * src/where.c: Sleep only 1s when bored. 2003-09-15 16:02 Martin Pool * src/state.h: Expose client state. 2003-09-15 16:01 Martin Pool * src/where.c: Fix code that caused us not to record the right slot number for local builds. Remove old code left over from transmission locks. 2003-09-15 15:53 Martin Pool * src/: lock.c, mon-gnome.c, renderer.c, state.c, state.h, where.c: * Store slot number as an integer in the state file. 2003-09-15 15:51 Martin Pool * src/mon-text.c: Show slot number in text display. 2003-09-15 15:33 Martin Pool * src/: mon-gnome.c, renderer.c, state.h: Change to storing slot name in the state file so that we can easily work out which tasks to draw on which line. Use a global variable to publish that information to the cell renderer. 2003-09-15 14:54 Martin Pool * src/renderer.c: Make the colored region fill the whole strip. 2003-09-15 14:46 Martin Pool * src/renderer.c: Draw text for jobs vertically centered within their rectangle. 2003-09-15 00:41 Martin Pool * src/renderer.c: Draw text into the task blocks. 2003-09-14 20:17 Martin Pool * src/renderer.c: Draw a border around the state rectangle, and try to take the padding into account when drawing. 2003-09-14 19:48 Martin Pool * Makefile.in: Cosmetic 2003-09-14 19:24 Martin Pool * src/: mon-gnome.c, renderer.c: Renderer now draws process states in something like the right color. 2003-09-14 17:43 Martin Pool * src/renderer.c: Add get/set code for history property. 2003-09-14 17:40 Martin Pool * src/: renderer.c, renderer.h: The implementation structures for the cell renderer can be more private. 2003-09-14 17:38 Martin Pool * src/renderer.c: Add a "task-history" property to the CellRenderer, currently storing only an integer that will be the current task's state. We don't handle sets/gets on it yet. 2003-09-14 17:33 Martin Pool * src/mon-gnome.c: Allow sorting by host name. * Make the tasks column in the list model store an integer, so that we can give it the current task's state. Bind this cell to the "task-history" property of the renderer. 2003-09-14 17:18 Martin Pool * src/: mon-gnome.c, mon-text.c, mon.c, mon.h, state.c, state.h: Rename dcc_client_history to just dcc_history. 2003-09-14 17:17 Martin Pool * NEWS: Add release header. 2003-09-14 17:09 Martin Pool * src/renderer.c: Doc 2003-09-12 17:23 Martin Pool * src/renderer.h: Add state field to _DccCellRendererChart 2003-09-12 17:16 Martin Pool * src/renderer.c: Implement dcc_cell_renderer_chart_get_size 2003-09-12 17:08 Martin Pool * src/renderer.c: Add a simpleminded implementation of dcc_cell_renderer_chart_render() that can draw the chart cells as black rectangles. 2003-09-12 15:58 Martin Pool * src/renderer.c: Implement the get_property and set_property methods. 2003-09-12 15:49 Martin Pool * src/renderer.c: Fix call to g_type_register_static, which needs a reference to the parent type. 2003-09-12 15:46 Martin Pool * src/: renderer.c, renderer.h: Add GTK Type boilerplate to create a new GtkCellRenderer. 2003-09-12 13:08 Martin Pool * Makefile.in, src/mon-gnome.c, src/renderer.c, src/renderer.h: Put renderer interface into renderer.h 2003-09-12 13:05 Martin Pool * Makefile.in, src/mon-gnome.c, src/renderer.c: Split out draft GtkCellRenderer into its own file. 2003-09-11 19:07 Martin Pool * src/mon-gnome.c: Start adding a custom renderer. Doesn't do anything yet. 2003-09-11 18:57 Martin Pool * src/mon-gnome.c: As an experiment, draw pixbufs into the task cells using a GtkCellRendererPixmap, rather than text. This seems to be working OK. 2003-09-11 18:47 Martin Pool * src/mon-gnome.c: Put hostname and state into the tree model as they're updated. 2003-09-11 18:47 Martin Pool * gnome/distccmon-gnome.glade: Turn off rules_hint on table. 2003-09-11 18:23 Martin Pool * src/mon-gnome.c: Add a task column. 2003-09-11 18:17 Martin Pool * gnome/distccmon-gnome.glade, src/mon-gnome.c: Move back towards using a table, but now with space for our own GtkCellRenderer to draw a chart for each host slot. At the moment nothing is in the table, just a column for host names. 2003-09-11 17:44 Martin Pool * src/mon-gnome.c: Cut out trace messages. 2003-09-11 17:31 Martin Pool * src/mon-gnome.c: Use real task information. * Avoid coloring in areas that will be hidden by the border. * Make the border the correct width. 2003-09-11 17:15 Martin Pool * src/mon-gnome.c: Draw text labels in black. * Add a second file to the fake information. * Set the start time on fake files. * Draw all states for a file, using the old code but adapted to drawing on the DrawingArea not a canvas. 2003-09-11 15:19 Martin Pool * src/mon-gnome.c: Draw tasks from a faked up list, rather than just drawing arbitrary rectangles. * Redraw window using gtk_widget_queue_draw rather than Gdk. This seems to fix a problem with redraw. Perhaps we were passing the wrong rectangle. 2003-09-11 15:02 Martin Pool * src/mon-gnome.c: Set bar height from font height. Now when you change the GNOME system font, all the bars redraw to the right height. That is so cool. :-) 2003-09-10 22:51 Martin Pool * src/mon-gnome.c: Cut out expose trace events. 2003-09-10 22:48 Martin Pool * src/mon-gnome.c: Stub out display of tasks so that we do get something correctly drawn again. 2003-09-10 18:27 Martin Pool * Makefile.in, configure.ac: We need Pango as well for GNOME. 2003-09-10 18:27 Martin Pool * src/mon-gnome.c: Start adding support for fake monitor data for testing. 2003-09-10 17:03 Martin Pool * src/mon-gnome.c: Draw tasks from the task list. 2003-09-10 16:25 Martin Pool * src/mon-gnome.c: Draw tasks by creating a new PangoLayout each time using the GTK+ helper. 2003-09-10 16:13 Martin Pool * src/mon-gnome.c: Draw labels onto file rectangles using Pango. How cool! 2003-09-10 15:27 Martin Pool * gnome/distccmon-gnome.glade: Put the chart drawing into a GtkAlignment so that we can get a 6px border around it. It was looking a bit cramped against the window border. 2003-09-10 15:17 Martin Pool * src/mon-gnome.c: Allocate GCs for all states. * Draw nice gray outlines around all task rectangles. 2003-09-10 15:05 Martin Pool * src/mon-gnome.c: Invalidate/repaint the chart widget every time we update the list. 2003-09-10 15:00 Martin Pool * src/mon-gnome.c: Factor out code for drawing state rectangles (back) into dcc_draw_state_rect(). * Draw a whole array of dummy tasks. 2003-09-10 14:55 Martin Pool * src/mon-gnome.c: Allocate a graphics context in the appropriate color and use it to draw our dummy tasks. 2003-09-10 14:32 Martin Pool * src/mon-gnome.c: Stub for on_chart_drawing_expose(). 2003-09-10 14:19 Martin Pool * gnome/distccmon-gnome.glade, src/mon-gnome.c: Rework again: * Start adding a 'key' window showing all the state colors. * Go back to a DrawingArea for showing the chart (just experimental). * Delete table view from monitor. 2003-09-09 18:17 Martin Pool * src/state.h: States must be listed in the order in which they're run. 2003-09-09 18:15 Martin Pool * src/mon-gnome.c: Update every 150ms. * Don't update the table. * Don't include DONE tasks. * Left-align filename. * Don't outline tasks. * Reorder color list for new state enum. * Make sure all states are drawn properly. This is leaking memory badly! 2003-09-09 17:54 Martin Pool * src/compile.c: Record input filename as soon as it is known. 2003-09-09 17:53 Martin Pool * src/state.c: Don't update state times that are already recorded. 2003-09-09 17:52 Martin Pool * src/where.c: Go into BLOCKED state at the start of the locking phase, so that we don't need to update repeatedly. 2003-09-09 17:29 Martin Pool * src/mon-gnome.c: Draw compilation tasks as striated rectangles. Handling of DONE tasks is not OK yet. 2003-09-09 17:14 Martin Pool * src/: compile.c, distcc.c: Go into STARTUP state earlier in the client process. 2003-09-09 17:09 Martin Pool * src/state.c: Make sure the time is recorded even for state 0. In fact, always update the time whenever dcc_note_state() is called. 2003-09-09 16:57 Martin Pool * src/compile.c: Please do use DCC_STATE_STARTUP so that we know when we started. 2003-09-09 16:43 Martin Pool * src/mon-gnome.c: Factor out code to create canvas items for the task 2003-09-09 16:21 Martin Pool * src/mon-gnome.c: Color task bars according to current state. 2003-09-08 21:12 Martin Pool * src/mon-gnome.c: Check for glade definition file in ., ./gnome, and DATADIR. 2003-09-08 21:10 Martin Pool * Makefile.in: Fix Make syntax 2003-09-08 21:09 Martin Pool * Makefile.in: Pass in DATADIR (e.g. /usr/local/share) when installing. 2003-09-08 18:11 Martin Pool * src/mon-gnome.c: More experiments in drawing. 2003-09-08 18:10 Martin Pool * gnome/distccmon-gnome.glade: Try a Canvas in a GtkAlignment 2003-09-08 17:47 Martin Pool * src/mon-gnome.c: More progress on canvas display * Skip done tasks * Show a nice vertical stack of running tasks, with the file name in each, and drawn with reasonable colors. 2003-09-08 17:33 Martin Pool * src/mon-gnome.c: More progress on canvas display * Put all bars into an overall group, so that they can all be removed every time we redraw. * Create all process bars in one group each time. 2003-09-08 16:39 Martin Pool * src/mon-gnome.c: More fixups for new state mechanism * Convert state to a string before putting it into the table. * Skip done tasks. 2003-09-08 16:26 Martin Pool * src/mon-gnome.c: Fix up (mostly renames) for new monitor interface. 2003-09-08 16:21 Martin Pool * src/mon-text.c: Skip display of Done tasks. 2003-09-08 16:20 Martin Pool * src/state.c: Add missing state names. 2003-09-08 16:19 Martin Pool * src/state.c: Make sure to actually record our state! 2003-09-08 16:12 Martin Pool * src/: state.c, state.h, mon-text.c: Put state names into a new function dcc_get_state_name, rather than into constants. 2003-09-08 16:08 Martin Pool * src/mon.c: Processes that have exited can still be returned. 2003-09-08 16:01 Martin Pool * src/mon.c: Now that we're storing client history, it's OK to return information about processes that have already exited. We just need to make sure that their state gets set to DCC_STATE_DONE. 2003-09-08 15:59 Martin Pool * src/state.c: Put the client pid into the state file. 2003-09-08 15:57 Martin Pool * src/: mon.c, state.c, state.h: Store a magic number in the binary state file as a little protection. * Align magic and pid fields to unsigned longs. 2003-09-08 15:51 Martin Pool * src/state.c: Store history of state transitions in the state file. 2003-09-08 15:48 Martin Pool * NEWS, src/clirpc.c, src/compile.c, src/distcc.c, src/mon-text.c, src/mon.c, src/mon.h, src/remote.c, src/state.c, src/state.h, src/where.c: Many changes to the representation of the client state to make it easier to draw a history. * State is now stored as a natively encoded struct in a disk file, rather than using our network protocol. This is slightly faster, makes it easier to store multiple fields, and avoids tangling up the state file handling (which ought to ignore errors) with network IO. * States can now be written and read with one atomic IO, and we don't use temporary files. * States are represented by integers not strings. * There is space in the state file for a history of times that it entered particular states. 2003-09-08 15:29 Martin Pool * src/: util.h, util.c: Add strlcpy() if missing. 2003-09-08 15:29 Martin Pool * configure.ac: Add check for strlcpy(). 2003-09-08 13:17 Martin Pool * src/mon-gnome.c: Draw rectangles onto the canvas for each job that's currently running. 2003-09-08 13:11 Martin Pool * src/mon-gnome.c: Set canvas scroll region at startup. 2003-09-08 13:04 Martin Pool * src/mon-gnome.c: Draw little rectangles into the chart from the timer callback to prove that we can. 2003-09-08 12:51 Martin Pool * src/mon-gnome.c: Prepare to update both table and chart from one timer callback. Refactor into a part that gets the process list and a new function that updates the table model. * Add some prototypes for functions called by glade to silence compiler warnings. 2003-09-08 12:45 Martin Pool * src/mon-gnome.c: Rename setup_proc_view -> setup_table_view. * Doc. 2003-09-08 12:44 Martin Pool * src/mon-gnome.c: Document design of chart view. 2003-09-07 22:54 Martin Pool * src/mon-gnome.c: Draw a rectangle onto the chart to see it working. 2003-09-07 19:09 Martin Pool * gnome/distccmon-gnome.glade: Swich from a DrawingArea to a Canvas for the chart view. 2003-09-07 19:04 Martin Pool * src/mon-gnome.c: Swich from a DrawingArea to a Canvas for the chart view. 2003-09-07 19:03 Martin Pool * Makefile.in: Move mon-gnome.c back to src/ * Pull out common list of packages to be passed to pkg-config. * Compile mon-gnome.c separate from linking. 2003-09-07 18:53 Martin Pool * gnome/mon-gnome.c, src/mon-gnome.c: Move mon-gnome.c back to src/ 2003-09-05 17:01 Martin Pool * gnome/mon-gnome.c: Abort if we can't find the glade XML file. 2003-09-04 15:20 Martin Pool * man/distcc.1: Clear up explanation of --allow option. * Note that "gcc hello.c" is not split. 2003-09-03 12:41 Martin Pool * src/where.c, NEWS: Sleep only one second when blocked, to try to reduce idle time when recovering from an overloaded period. 2003-09-01 23:20 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Draw big black ellipse in the chart area. 2003-09-01 23:15 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Try to make View menu items toggle each other. Not working yet. 2003-09-01 23:09 Martin Pool * gnome/distccmon-gnome.glade: Put tabs on the notebook just for the time being. 2003-09-01 23:02 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Flip between view notebook pages when view menu items are chosen. 2003-09-01 22:47 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Add a cute monkey icon. * Add an About box and hook it up appropriately. 2003-09-01 22:23 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Hook up process table to Glade. The existing processs monitoring functions are now working again. 2003-09-01 22:09 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: Get load bar hooked up for Gnome monitor. 2003-09-01 22:04 Martin Pool * gnome/: distccmon-gnome.glade, mon-gnome.c: More merges of monitor code into Glade interface. * Set size of Glade window at startup and tweak scrollbars. 2003-09-01 21:39 Martin Pool * gnome/mon-gnome.c: Merge in all the GNOME monitor code from HEAD. 2003-09-01 21:23 Martin Pool * configure.ac: Check for other necessary libraries when --enable-gnome is given. * Bump version. 2003-09-01 13:33 Martin Pool * TODO: Idea of using gkrellm 2003-09-01 11:30 Martin Pool * man/distccd.1: Add a little more explanation of --allow. 2003-08-28 15:05 Martin Pool * TODO: Update for done tasks. 2003-08-28 15:02 Martin Pool * man/distccd.1: Note that ccache can't be called from distccd. 2003-08-28 14:33 Martin Pool * NEWS, man/distcc.1: Note about problems with no_subtree_check. 2003-08-28 14:31 Martin Pool * TODO: DEPENDENCIES_OUTPUT is not directly a problem for distcc. 2003-08-28 12:48 Martin Pool * cases/mmaptest.c: Bug has been isolated; no longer need this test case. 2003-08-28 12:45 Martin Pool * cases/mmaptest.c: More tests for NFS bug. 2003-08-26 15:56 Martin Pool * cases/mmaptest.c: Do the mmapped IO in a child process, to be more similar to ccache/distcc. 2003-08-26 12:01 Martin Pool * cases/: .cvsignore, mmaptest.c: Add test for mmap-on-NFS problems 2003-08-25 16:06 Martin Pool * src/pump.c: Doc 2003-08-25 12:48 Martin Pool * src/: arg.c, compile.c, compress.c, serve.c: Patch from Wayne Davison to fix Solaris warnings 2003-08-25 11:55 Martin Pool * src/: compress.c, io.c, io.h, pump.c: Add DISTCC_MMAP option, defaults to on. May be useful in working around bugs with mmap on NFS. 2003-08-25 11:13 Martin Pool * man/distcc.1, man/distccd.1, NEWS: Document DISTCC_MMAP. 2003-08-15 14:17 Martin Pool * Makefile.in, gnome/distccmon-gnome.glade, gnome/distccmon-gnome.gladep, gnome/mon-gnome.c: Initial stub version of the monitor. 2003-08-15 14:16 Martin Pool * src/mon-gnome.c: Move gnome monitor into its own directory. 2003-08-14 18:12 Martin Pool * TODO, gnome/distccmon-gnome.glade, gnome/distccmon-gnome.gladep, gnome/mon-gnome.c: Start doing a better GNOME monitor. 2003-08-13 13:05 Martin Pool * TODO: Note problem with DEPENDENCIES_OUTPUT. 2003-08-13 12:57 Martin Pool * configure.ac: Bump version. 2003-08-12 13:34 Martin Pool * man/distcc.1: Update manpage date. 2003-08-12 13:27 Martin Pool * test/testdistcc.py: Set DISTCC_DIR when running tests to give better isolation between tests and anything else that might be happening on the machine. 2003-08-12 13:18 Martin Pool * Makefile.in: make distcheck ought to run maintainer-check and also check that the directory can be cleaned. 2003-08-12 13:10 Martin Pool * NEWS: Note "make clean" problem is fixed. 2003-08-12 13:09 Martin Pool * configure.ac: Bump version to 2.10.1 2003-08-12 11:42 Martin Pool * Makefile.in: Fix "make clean" problem in lzo. Reported by Lisa Marie Seelye. 2003-08-11 16:09 Martin Pool * cases/hello.c: Make hello actually say hello 2003-08-11 16:07 Martin Pool * distcc-check: Allow the compiler to be changed. 2003-08-11 16:05 Martin Pool * NEWS, configure.ac: Prepare for release. 2003-08-11 15:51 Martin Pool * TODO: Suggestions from Lisa on the monitor. 2003-08-11 15:46 Martin Pool * src/tempfile.c: Fix from wayned for crash when DISTCC_DIR is set. 2003-08-11 15:43 Martin Pool * src/tempfile.c: Doc. 2003-08-11 15:40 Martin Pool * test/testdistcc.py: [no log message] 2003-08-11 15:33 Martin Pool * NEWS: [no log message] 2003-08-11 15:32 Martin Pool * man/distcc.1: Corrections from Frerich Raabe. 2003-08-11 15:18 Martin Pool * src/exec.c, NEWS: For simple compile failures, don't say "with exit code 1". 2003-08-11 15:15 Martin Pool * src/exec.c: Doc. 2003-08-07 15:42 Martin Pool * TODO: [no log message] 2003-08-05 12:09 Martin Pool * src/exitcode.h: Add include guard. 2003-08-05 11:56 Martin Pool * Makefile.in: Remove roadmap page, because it's now largely complete. 2003-08-05 11:53 Martin Pool * Makefile.in: Make sure examples get installed into doc/example. 2003-08-05 11:48 Martin Pool * doc/example-init, doc/example/init, doc/example/init-suse, doc/example/logrotate, doc/example/xinetd, Makefile.in, doc/example.xinetd: Move all example files into doc/example. 2003-07-25 17:34 Martin Pool * doc/results.txt: [no log message] 2003-07-25 17:25 Martin Pool * bench/Summary.py: Show summary table properly. 2003-07-25 15:50 Martin Pool * src/state.c, NEWS: Roll back to writing state into temporary files. 2003-07-25 15:36 Martin Pool * test/testdistcc.py: Doc 2003-07-25 15:35 Martin Pool * test/testdistcc.py: If the daemon fails to bind to the desired port, keep trying other ones. 2003-07-25 15:21 Martin Pool * NEWS: Store state files by writing and rewriting them directly, rather than renaming every time. That was starting to take a fair fraction of our syscalls. 2003-07-25 15:15 Martin Pool * src/state.c: Fix state file names. 2003-07-25 15:14 Martin Pool * src/state.c: Store state files by writing and rewriting them directly, rather than renaming every time. That was starting to take a fair fraction of our syscalls. 2003-07-25 14:56 Martin Pool * NEWS: [no log message] 2003-07-25 14:53 Martin Pool * src/tempfile.c: Make temp filenames more random. 2003-07-25 14:51 Martin Pool * src/tempfile.c: Check return code when closing the temporary file after creating it. 2003-07-25 14:47 Martin Pool * src/tempfile.c: O_NOFOLLOW is not needed with O_EXCL and O_CREAT, because they never follow symlinks. * Doc. 2003-07-25 14:39 Martin Pool * src/tempfile.c: dcc_make_tmpnam: Fix the case where the chosen name already exists. 2003-07-25 14:34 Martin Pool * src/tempfile.c: Create temporary files in a loop, with O_EXCL and O_NOFOLLOW to try to guard against collision with existing files or links. 2003-07-25 14:15 Martin Pool * src/: cpp.c, serve.c: Better template names for temporary files. 2003-07-25 14:08 Martin Pool * configure.ac: Check for gettimeofday 2003-07-25 13:52 Martin Pool * src/: tempfile.c, tempfile.h: dcc_get_top_dir can be static, and does not need to return a newly-allocated string. 2003-07-25 13:32 Martin Pool * src/: lock.c, mon.c, state.c, tempfile.c, tempfile.h: Make sure lock dir and state dir are only created the first time we use them. 2003-07-25 13:22 Martin Pool * NEWS, src/lock.c, src/mon.c, src/state.c, src/tempfile.c, src/tempfile.h: Temporary directory is now gone. Working files are created directly under $TMPDIR, as they are for gcc. Lock files and state files are stored under DISTCC_DIR. 2003-07-25 13:18 Martin Pool * src/distcc.c: Temporary directory is no longer used. 2003-07-25 12:35 Martin Pool * Makefile.in: cleanup.c is also needed by monitors. 2003-07-25 11:53 Martin Pool * src/tempfile.c: Daemon runs from root directory, not the temporary directory. * Doc. 2003-07-25 11:51 Martin Pool * src/daemon.c, src/tempfile.h, NEWS: Daemon runs from root directory, not the temporary directory. 2003-07-24 18:58 Martin Pool * src/tempfile.c: Doc 2003-07-24 18:46 Martin Pool * src/tempfile.c: Remove dead fifo code. 2003-07-24 18:45 Martin Pool * Makefile.in, src/cleanup.c, src/tempfile.c, src/tempfile.h: Factor out tempfile cleanup into a new file cleanup.c 2003-07-24 18:43 Martin Pool * patches/ccache-uncached-err.diff: Patch to ccache to avoid caching network errors. 2003-07-24 18:20 Martin Pool * NEWS: Note about tmpdir fixes. 2003-07-24 18:17 Martin Pool * src/tempfile.c: dcc_get_tempdir: Make sure that if we fail the first time we don't pass back a bogus directory on future attempts. 2003-07-24 18:12 Martin Pool * src/distcc.c: Check up front in the client that the working directory can be created, otherwise we get a whole pile of errors when it fails. 2003-07-24 17:58 Martin Pool * src/: cpp.c, lock.c, lock.h, serve.c, state.c, tempfile.c, tempfile.h, timefile.c: Change temporary filename handling to consistently use error returns and check them. 2003-07-23 17:19 Martin Pool * src/: state.c, tempfile.c, tempfile.h: dcc_make_dir: Rename to dcc_safe_mkdir. Check the ownership of the directory after it is created to help guard against an attacker creating the directory. 2003-07-23 17:18 Martin Pool * TODO: [no log message] 2003-07-23 16:56 Martin Pool * src/tempfile.c: Doc. 2003-07-23 16:11 Martin Pool * src/tempfile.c: Don't check that TMPDIR starts with '/'. * dcc_setup_tempdir can be static. 2003-07-23 16:11 Martin Pool * src/tempfile.h: dcc_setup_tempdir can be static. 2003-07-23 16:09 Martin Pool * NEWS: Don't check that TMPDIR starts with '/'. 2003-07-22 18:02 Martin Pool * src/pump.c: Doc. 2003-07-22 17:36 Martin Pool * src/lock.c: Be strict about enums. 2003-07-22 17:35 Martin Pool * src/: clirpc.c, rpc.c, rpc.h: waitstatus is not unsigned. 2003-07-22 17:34 Martin Pool * src/filename.c: dcc_output_from_source: Remove dead variable. 2003-07-22 17:33 Martin Pool * configure.ac: Remove doubled CFLAG. 2003-07-22 17:30 Martin Pool * src/exec.c: waitstatus is not unsigned. 2003-07-22 17:25 Martin Pool * src/: exec.h, distcc.h: waitstatus is not unsigned. 2003-07-22 17:24 Martin Pool * src/compile.c: Signedness warning correction; reported by Dimitri Papadopoulos. 2003-07-22 17:21 Martin Pool * src/remote.c: timeval.h is not needed. 2003-07-22 17:19 Martin Pool * src/tempfile.c: Snip out dcc_mkfifo 2003-07-22 16:58 Martin Pool * NEWS: [no log message] 2003-07-22 16:57 Martin Pool * man/distcc.1: Document UNCACHED_ERR_FD. 2003-07-22 16:55 Martin Pool * man/distcc.1: Note that ccache doesn't handle compilation from .i files. 2003-07-22 16:47 Martin Pool * src/daemon.c: Factor out code for setting the daemon's path. * Show path for daemon at startup. 2003-07-22 16:43 Martin Pool * src/daemon.c: daemon/main: The daemon no longer trims its path, because it will emit warnings if a masqueraded directory is detected. 2003-07-22 16:42 Martin Pool * src/util.c: dcc_trim_path: This is no longer called by the server, only by the client. So remove support for detecting ccache, and require the compiler name to always be specified. 2003-07-22 16:38 Martin Pool * TODO: [no log message] 2003-07-22 16:35 Martin Pool * src/distcc.c: Remove duplicated dcc_find_basename(). 2003-07-22 14:16 Martin Pool * distcc-check: Doc 2003-07-22 14:13 Martin Pool * NEWS: Default niceness is 5. 2003-07-22 14:11 Martin Pool * src/: daemon.c, dopt.c, dopt.h, util.c: Increment niceness by 5 by default. 2003-07-22 14:08 Martin Pool * man/distccd.1: Clarify that niceness is an increment not an absolute value. * Default niceness is 5. 2003-07-22 13:58 Martin Pool * NEWS: Nasty note about SCO. 2003-07-22 13:53 Martin Pool * doc/results.txt: SSH results. 2003-07-22 12:43 Martin Pool * README.packaging: More suggestions about cross compiling from Dag Wieers. 2003-07-21 17:37 Martin Pool * src/serve.c: dcc_run_job: Before executing the compiler, check the server's path and emit a warning if it looks like a symlink to distcc. 2003-07-21 17:36 Martin Pool * NEWS: Note about finding the right compiler on the volunteer. 2003-07-21 17:14 Martin Pool * src/distcc.c: Doc. 2003-07-21 16:35 Martin Pool * src/: distcc.c: Doc. 2003-07-21 16:31 Martin Pool * src/distcc.c: distcc/main: Rename variable. 2003-07-21 16:25 Martin Pool * src/distcc.c: dcc_get_my_basename: Rename to dcc_find_basename, which is a better name, and just make it work on a string, rather than looking in an argv. This function is really no longer distcc-specific. 2003-07-21 16:06 Martin Pool * configure.ac: Bump version. 2003-07-21 15:50 Martin Pool * man/distcc.1: Remove PP 2003-07-21 15:24 Martin Pool * configure.ac, NEWS: 2.9 release. 2003-07-21 15:14 Martin Pool * configure.ac: Make sure GNOME_BIN actually gets set. 2003-07-21 15:10 Martin Pool * Makefile.in: lzoconf.h needs to be distributed. 2003-07-21 15:07 Martin Pool * doc/results.txt: [no log message] 2003-07-21 14:59 Martin Pool * src/util.c, NEWS: When trimming the path to avoid recursive invocations, stop as soon as we find one non-symlink compiler. This should help avoid the path getting trimmed down far too much on the server. Patch from Wayne Davison. 2003-07-21 14:49 Martin Pool * man/distccd.1: Suggest inetd limit be raised to 6000 2003-07-21 14:42 Martin Pool * NEWS: [no log message] 2003-07-21 14:40 Martin Pool * src/compress.c: dcc_compress_lzo1x_alloc can be static. 2003-07-21 14:20 Martin Pool * src/distcc.h: dcc_compress_lzo1x_alloc can be static. 2003-07-21 12:45 Martin Pool * NEWS: Note about documentation. 2003-07-21 12:35 Martin Pool * src/compress.c: Trace message for use of mmap. 2003-07-21 12:31 Martin Pool * src/pump.c: Trace message for receipt using mmap. 2003-07-21 12:23 Martin Pool * src/daemon.c: Tweak daemon startup message. 2003-07-21 12:21 Martin Pool * src/daemon.c: Show gnu-host in daemon startup message. 2003-07-21 12:13 Martin Pool * src/: daemon.c, daemon.h, dparent.c: Factor out code to show daemon startup message, and include the daemon mode in it. 2003-07-21 12:08 Martin Pool * TODO: [no log message] 2003-07-21 12:02 Martin Pool * src/hosts.c: Update host grammar from manpage. 2003-07-21 12:01 Martin Pool * man/distcc.1: Grammar fixes: * Be consistent about quoting. * Add LOCAL_HOST. * Make USER option in SSH production. 2003-07-21 11:59 Martin Pool * man/distcc.1: Add ccache URL * Cleanup 2003-07-21 11:56 Martin Pool * man/distccd.1: Some cleanups from Tim and myself. 2003-07-21 11:42 Martin Pool * man/distcc.1: Many suggestions from Tim: * Add quickstart section. * Consistent capitalization of "make" * Grammar/readability fixes. * Move up section about ccache with distcc * Clear up host grammar section. * What to do about broken makefiles. 2003-07-21 11:21 Martin Pool * NEWS: Note mmap support. * Delete trailing whitespace. 2003-07-21 11:17 Martin Pool * man/distcc.1: Add information about compression. 2003-07-18 16:50 Martin Pool * src/pump.c: dcc_r_bulk_plain: For uncompressed data coming in, we know the exact right length and so we only need to truncate the file once. 2003-07-18 16:48 Martin Pool * src/pump.c: Receive bulk data by writing into an mmaped file, or otherwise reading in and writing out one big buffer. 2003-07-18 16:41 Martin Pool * doc/results.txt: [no log message] 2003-07-18 16:39 Martin Pool * src/pump.c: Start implementing dcc_r_bulk_plain 2003-07-18 16:32 Martin Pool * src/: bulk.c, clirpc.c, io.c, io.h, pump.c: Rename dcc_pump_in for consistency. * Doc. 2003-07-18 16:21 Martin Pool * src/: bulk.c, compress.c, compress.h, distcc.h, pump.c: Make compression function naming consistent. * Remove compress.h 2003-07-18 16:00 Martin Pool * test/testdistcc.py: Fix silly error in ParseHostSpec_Case. 2003-07-18 15:59 Martin Pool * test/testdistcc.py: Fix VersionOption_Case for new version string that mentions two protocols. 2003-07-18 15:58 Martin Pool * test/testdistcc.py: Add partial test for parsing host specifications with the LZO option. 2003-07-18 15:57 Martin Pool * src/hosts.c: ',' should also terminate TCP hostnames. 2003-07-18 15:48 Martin Pool * NEWS: More about compression. 2003-07-18 15:45 Martin Pool * NEWS: Add support for ",lzo" option at the end of host specifications. 2003-07-18 15:43 Martin Pool * src/hosts.c: ',' should also terminate SSH hostnames. 2003-07-18 15:42 Martin Pool * src/hosts.c: Add support for ",lzo" option at the end of host specifications. 2003-07-18 15:02 Martin Pool * doc/results.txt: Results from 3.4 snapshot. 2003-07-18 13:16 Martin Pool * src/: rpc.h, rpc.c: Remove obsolete dcc_compr_for_proto() 2003-07-18 13:15 Martin Pool * src/: clirpc.c, distcc.h, hosts.c, hosts.h, lock.c, remote.c: Store both protocol and compression method in the host definition. Simpler than converting between them all the way through. 2003-07-18 12:21 Martin Pool * src/distcc.h: Reorder enums to top. 2003-07-18 12:18 Martin Pool * src/distcc.h: Make dcc_compress values not be 0-based. 2003-07-18 12:01 Martin Pool * Makefile.in, src/clirpc.c, src/clirpc.h, src/distcc.h, src/remote.c: Remove clirpc.h. 2003-07-18 11:35 Martin Pool * src/: clirpc.c, distcc.h, help.c, hosts.h, lock.c, mon-gnome.c, mon-text.c, mon.c, remote.c, rpc.c, rpc.h, serve.c, srvrpc.c, state.c: Start adding support for talking either protocol 1 or 2. Store protocol in host specification and propagate it through relevant functions. 2003-07-17 22:09 Martin Pool * src/hosts.c: Document upcoming compression option for host specifications. 2003-07-17 22:01 Martin Pool * doc/protocol-2.txt: [no log message] 2003-07-17 22:00 Martin Pool * Makefile.in: Include description of protocol version 2. 2003-07-17 21:59 Martin Pool * doc/protocol-2.txt: Description of protocol version 2. 2003-07-17 17:18 Martin Pool * src/bulk.c: Doc. 2003-07-17 17:16 Martin Pool * src/: compile.c, compile.h, remote.c: Pass source filename to dcc_compile_remote and set the state file from there so that we can get the filename in the first status message. 2003-07-17 17:11 Martin Pool * src/compress.c: Doc. * Only use mmap for buffers larger than 64k. 2003-07-17 17:04 Martin Pool * TODO: [no log message] 2003-07-17 17:03 Martin Pool * man/distcc.1: Add hostspec grammar * Some formatting changes. 2003-07-17 17:00 Martin Pool * src/hosts.c: Fix grammar nit. 2003-07-17 16:39 Martin Pool * man/distccd.1, src/dopt.c: Document --wizard. 2003-07-17 16:35 Martin Pool * NEWS, man/distccd.1: Change to starting 2+NCPUS jobs by default. 2003-07-17 16:31 Martin Pool * src/dparent.c: Change to starting 2+NCPUS jobs by default. 2003-07-17 16:24 Martin Pool * Makefile.in: Clean lzo/ directory. Patch from Wayne Davison. 2003-07-17 15:52 Martin Pool * distcc-check: Doc 2003-07-17 10:37 Martin Pool * man/distccd.1: There was some confusion about the meaning of "proportional to" in the description of -j. Now make it clearer that the number of jobs is higher than the number of CPUs. 2003-07-16 12:33 Martin Pool * Makefile.in: Remove the "tested" page. 2003-07-15 19:00 Martin Pool * src/mapfile.c: Remove mapfile; mmap is now called directly. 2003-07-15 18:51 Martin Pool * src/compress.c: Quieten warning. 2003-07-15 18:50 Martin Pool * src/compress.c: Doc * dcc_receive_lzo1x: Pass the right value to munmap(). 2003-07-15 18:47 Martin Pool * src/bulk.c: dcc_r_file: We need to open the file read/write, not just wronly, to be able to mmap it. 2003-07-15 18:45 Martin Pool * src/compress.c: dcc_compress_lzo1x_file: Make sure to return an error if the munmap failed, because we might not have managed to write everything out. * dcc_receive_lzo1x: First cut at decompressing into a writable mmap'd buffer. 2003-07-15 18:23 Martin Pool * src/compile.c: Disable "startup" state. 2003-07-15 18:21 Martin Pool * src/compress.c: dcc_compress_lzo1x_file: Try to use mmap() to read the input file if mmap() is available. If not, fall back to using malloc and read(). 2003-07-15 18:20 Martin Pool * doc/results.txt: Results from compilation on 10Mbps network. 2003-07-15 18:18 Martin Pool * Makefile.in: mapfile is no longer needed -- we just mmap as necessary. 2003-07-15 18:10 Martin Pool * configure.ac, NEWS: Don't check for GTK+ unless --enable-gnome is requested, because it's a needless portability risk on platforms that don't have it. 2003-07-15 18:04 Martin Pool * configure.ac: Check for mmap() 2003-07-15 18:02 Martin Pool * src/: bulk.c, compress.c, compress.h: Factor out code to compress from a file. 2003-07-15 17:57 Martin Pool * src/bulk.c: dcc_calc_rate: Guard against division by zero (which never seems to happen). * Doc. 2003-07-15 17:51 Martin Pool * NEWS: Note compression. 2003-07-15 17:40 Martin Pool * src/: distcc.h, dopt.h, srvnet.c: Clean up dopt headers. 2003-07-15 17:38 Martin Pool * doc/results.txt: Notes on testing compression. 2003-07-15 17:23 Martin Pool * src/distcc.h: Change protocol version to 2 so that incompatibilities with old servers are trapped. Eventually we need to switch intelligently. 2003-07-15 17:12 Martin Pool * src/mon-gnome.c: Make columns in the GNOME monitor resizable, as well as auto-resizing. 2003-07-15 11:32 Martin Pool * src/bulk.c: dcc_r_file: Doc. Fix uninitialized variable for 0-length files. 2003-07-14 22:02 Martin Pool * src/compress.c: Show decompression ratio as small:large. 2003-07-14 21:51 Martin Pool * src/pump.c: dcc_pump_in: Handle 0-byte optimization too. 2003-07-14 21:45 Martin Pool * src/bulk.c: Add optimization of not doing any compression for 0-byte files. 2003-07-14 21:39 Martin Pool * src/pump.c: dcc_pump_out: No longer needed because dcc_x_file now switches based on compression. * Fix parameter ordering bug for dcc_pump_in 2003-07-14 21:38 Martin Pool * src/io.h: compress.h: New header. 2003-07-14 21:38 Martin Pool * src/dopt.c: Fix --wizard. 2003-07-14 21:38 Martin Pool * src/: compress.c, compress.h: dcc_compress_lzo1x_alloc: New function to just compress in memory without doing IO. * compress.h: New header. 2003-07-14 21:36 Martin Pool * src/bulk.c: New dcc_x_file_lzo1x: Read in the file, compress it, and then write out that buffer. This has to be done in a single level because the token has to include the compressed length. * dcc_x_file: Handle compression. 2003-07-14 21:24 Martin Pool * src/dopt.c: Rename to --wizard. 2003-07-14 21:22 Martin Pool * src/dopt.c: Add -X, --maintainer option that adds all settings for running under gdb. 2003-07-14 18:10 Martin Pool * src/: bulk.c, bulk.h, clirpc.c, serve.c: dcc_x_file doesn't need to return the file size anymore. 2003-07-14 18:07 Martin Pool * src/: bulk.c, bulk.h, remote.c, serve.c: Set default compression to LZO1X -- which is not working now, and breaks compatibility * Start factoring out code for receiving a token and file into dcc_r_token_file 2003-07-14 17:55 Martin Pool * src/: bulk.c, bulk.h, clirpc.c, clirpc.h, remote.c, serve.c: Propagate compression setting through all routines. 2003-07-14 17:49 Martin Pool * src/: bulk.c, bulk.h, clirpc.c, compress.c, distcc.h, io.h, pump.c: Start moving bulk data receipt through dcc_pump_in, which does decompression if needed. Remove null dcc_r_file_body. 2003-07-14 17:43 Martin Pool * src/: compress.c, io.h, pump.c: Rename compression functions to lzo_1x, the generic name for the algorithm family we're using. 2003-07-14 17:38 Martin Pool * src/compress.c: Doc 2003-07-14 17:35 Martin Pool * doc/results.txt: [no log message] 2003-07-14 17:35 Martin Pool * man/.cvsignore: Ignore built HTML files. 2003-07-14 16:56 Martin Pool * man/distccd.1: [no log message] 2003-07-14 16:52 Martin Pool * Makefile.in: Don't install README.packaging or SuSE example init script. 2003-07-14 16:49 Martin Pool * Makefile.in: Strip out linuxdoc, because all the information there has been merged into the manpages. 2003-07-14 16:47 Martin Pool * Makefile.in: Add upload-man target to make the manual available on the web page. * There's no need to install README.popt. * Fix targets to build html from troff. 2003-07-14 16:44 Martin Pool * man/: distccd.1, distcc.1: Credit other people. 2003-07-14 16:35 Martin Pool * man/distccd.1: Document DISTCC_SAVE_TEMPS 2003-07-14 16:34 Martin Pool * man/distccd.1: Merge option descriptions and other things. 2003-07-14 16:15 Martin Pool * man/distcc.1: Merge more information. 2003-07-14 15:50 Martin Pool * man/distccd.1: Merge more information. 2003-07-14 15:44 Martin Pool * man/distcc.1: Merge more information. 2003-07-14 15:16 Martin Pool * man/distcc.1: Merge more information. 2003-07-14 14:54 Martin Pool * Makefile.in: Add targets to build HTML from manpages. 2003-07-14 14:47 Martin Pool * man/distccd.1: Start adding more details about the server. 2003-07-14 14:46 Martin Pool * man/distcc.1: Merge stuff about cross-compiling. * More about security. 2003-07-14 14:41 Martin Pool * INSTALL: More about how to install distccd. 2003-07-14 14:33 Martin Pool * man/distcc.1: More manpage documentation. 2003-07-14 13:45 Martin Pool * man/distcc.1: Put a lot more useful information into the manual page. 2003-07-14 12:42 Martin Pool * linuxdoc/distcc.sgml: Information on reporting bugs has been merged into a separate file. 2003-07-14 12:35 Martin Pool * doc/reporting-bugs.txt: Merge more information on reporting problems from the SGML manual. 2003-07-14 12:32 Martin Pool * Makefile.in: Include information on how to report bugs effectively. 2003-07-14 12:31 Martin Pool * doc/reporting-bugs.txt: Information on how to report bugs effectively. 2003-07-14 12:20 Martin Pool * Makefile.in: Include example-init in package. 2003-07-14 12:14 Martin Pool * src/mon.c: Increase allowable age of state files to 300s. 2003-07-14 12:09 Martin Pool * Makefile.in: mon-notify.o is not currently used by the monitors. 2003-07-14 11:53 Martin Pool * bench/compiler.py: Don't put commas in path names because they can cause trouble with some linker command. 2003-07-14 10:51 Martin Pool * src/: mon-gnome.c, mon-notify.c, mon.c: Fix header ordering. 2003-07-14 10:47 Martin Pool * configure.ac: Remove standard GTK test macros because we don't use them. 2003-07-13 18:40 Martin Pool * Makefile.in: Clean up files which were duplicated in dist_files and pkgdoc_DOCS. 2003-07-13 18:09 Martin Pool * patches/.cvsignore: Add built program. 2003-07-13 18:08 Martin Pool * src/: distcc.h, h_argvtostr.c, h_exten.c, h_issource.c, h_scanargs.c, h_strip.c, io.h, mon-text.c, state.c: Clean up header inclusions. 2003-07-13 18:07 Martin Pool * src/arg.c: Doc 2003-07-13 17:57 Martin Pool * TODO: [no log message] 2003-07-13 17:55 Martin Pool * DEPENDENCIES, Makefile.in: Remove DEPENDENCIES file, which is being merged into INSTALL. 2003-07-13 17:30 Martin Pool * INSTALL: Rewrite installation instructions to be specific to distcc and to cover all the main steps. 2003-07-13 12:44 Martin Pool * configure.ac, NEWS: Autodetect the right behaviour for --enable-gnome: If explicitly enabled, insist that the GTK+ libraries be present. If explicitly disabled, don't even look for them. Otherwise, build the GTK+ monitor if possible. 2003-07-12 22:57 Martin Pool * man/distcc.1: Correction for duplicated word by Tobias Stoeckmann. 2003-07-12 17:04 Martin Pool * test/testdistcc.py: Doc. 2003-07-12 16:57 Martin Pool * test/testdistcc.py: Fix up checks for remote assembly listings: we *can* distribute these, unless a filename is specified. 2003-07-12 16:52 Martin Pool * src/arg.c, NEWS: Add checks for -Wa options that produce an assembler listing file. 2003-07-12 11:45 Martin Pool * test/testdistcc.py: Add tests for new -o and -Wa,-al handling. 2003-07-12 01:31 Martin Pool * src/compress.c: Add implementation of LZO decompression. 2003-07-12 01:30 Martin Pool * TODO: [no log message] 2003-07-12 00:58 Martin Pool * src/arg.c: Doc. 2003-07-11 18:21 Martin Pool * bench/Build.py: Make sure full paths are generated for log files. * Add support for programs that use C++. 2003-07-11 18:20 Martin Pool * bench/compiler.py: Make default compiler setups consistent with ones specified by -c * Add support for programs that use C++ 2003-07-11 18:19 Martin Pool * bench/ProjectDefs.py: Add other definitions needed for building firebird. 2003-07-11 18:18 Martin Pool * cases/simple.c: Simple test with no header files. 2003-07-11 17:27 Martin Pool * bench/compiler.py: New/better naming of build directories: now just 'dist,2'. 2003-07-11 17:26 Martin Pool * bench/ProjectDefs.py: Comment out Mozilla, which is having trouble on Debian. * Add MozillaFirebird. 2003-07-11 17:25 Martin Pool * bench/Build.py: Put build logs in the build directory so they're easier to find and use. 2003-07-11 15:19 Martin Pool * bench/ProjectDefs.py: Fix unpacked_subdir for Mozilla 2003-07-11 15:15 Martin Pool * distcc-check: Make sure we do move into the right scratch directory * Remove with -f on completion so that we don't fail if the files were never created. 2003-07-11 15:14 Martin Pool * bench/Project.py: We need wget --continue to get the intended behaviour. 2003-07-11 15:10 Martin Pool * bench/Summary.py: Don't give an error when trying to print a summary table of no compilations. 2003-07-11 15:06 Martin Pool * doc/results.txt: More benchmark stuff. 2003-07-11 14:50 Martin Pool * bench/Summary.py: Fix uname usage. 2003-07-11 14:50 Martin Pool * bench/Project.py: Use wget not snarf, because its progress bar works better with tty and non-tty setups. 2003-07-11 14:47 Martin Pool * bench/benchmark.py: Show -a in help. 2003-07-11 14:47 Martin Pool * bench/ProjectDefs.py: Fix apache 2.0.43 link, which has moved. * Add Mozilla 1.4 (not tested yet) 2003-07-11 14:28 Martin Pool * NEWS: When run as "distcc foo.o -o foo", work out that foo.o is an object file not a compiler name. This can happen with Mozilla. 2003-07-11 14:28 Martin Pool * src/implicit.c: When run as "distcc foo.o -o foo", work out that foo.o is an object file not a compiler name. This can happen with Mozilla. * Many documentation updates to reflect the way that masquerade invocation now works -- a lot of the comments in this file were written before it was added. 2003-07-11 14:20 Martin Pool * src/: filename.h, distcc.h, implicit.c: Move declarations for filename.c into filename.h. 2003-07-11 14:18 Martin Pool * src/filename.h: dcc_is_object: New function. 2003-07-11 14:17 Martin Pool * src/filename.c: dcc_is_object: New function. * filename.c: Doesn't need sys/stat.h. * Doc. 2003-07-11 14:13 Martin Pool * Doxyfile: Don't produce LaTeX 2003-07-11 14:10 Martin Pool * src/filename.c: Doc 2003-07-11 14:09 Martin Pool * patches/.cvsignore: Ignore built programs. 2003-07-11 13:34 Martin Pool * src/: exec.c, exec.h: dcc_execvp() can be static 2003-07-09 18:30 Martin Pool * src/compress.c, TODO: Start a decompressor. 2003-07-09 18:06 Martin Pool * src/compress.c: First cut at implementation of dcc_send_lzo1x1. 2003-07-09 18:05 Martin Pool * src/mapfile.c: Finish implementing dcc_map_input_file. 2003-07-09 17:52 Martin Pool * src/mapfile.c, Makefile.in, src/io.h: Add simple mmap routine for reading input files. 2003-07-09 17:42 Martin Pool * configure.ac: Check for sys/mman.h 2003-07-09 17:39 Martin Pool * src/pump.c: Call dcc_send_lzo1x1 for compressed mode. 2003-07-09 17:38 Martin Pool * src/: hostfile.c, io.h, loadfile.c: Rename dcc_load_file to dcc_load_file_string to be more clear. 2003-07-09 17:17 Martin Pool * patches/trylzo.c: Simple test harness to measure lzo1x1 compression. 2003-07-09 16:49 Martin Pool * src/compress.c: Stub file for doing bulk compression. 2003-07-09 16:28 Martin Pool * Makefile.in, src/bulk.c, src/bulk.h, src/clirpc.c, src/clirpc.h, src/io.c, src/io.h, src/pump.c, src/remote.c, src/serve.c: Refactor bulk-IO code, and start adding support for compression. Nothing is actually compressed yet. 2003-07-09 16:25 Martin Pool * src/timebuild: Remove 'timebuild' script because it's replaced by a better benchmark script. 2003-07-09 15:54 Martin Pool * src/sendfile.c: Handle EINTR from sendfile(). 2003-07-09 15:44 Martin Pool * configure.ac: Remove check for poptGetContext that made us get an unnecessary second -lpopt option. 2003-07-09 15:39 Martin Pool * Makefile.in: Doc 2003-07-09 15:38 Martin Pool * Makefile.in: Start including lzo support: include it on the include path and in the distribution and build minilzo.o. 2003-07-09 15:37 Martin Pool * configure.ac: Bump version. 2003-07-09 14:31 Martin Pool * TODO: Notes on distcc-check and globally visible state. 2003-07-09 14:17 Martin Pool * TODO: Update for current progress. 2003-07-09 13:41 Martin Pool * TODO: 0-length output files are now handled OK. 2003-07-09 13:13 Martin Pool * NEWS: Correction to NEWS: in fact the GNOME monitor is not smart about making updates only when visible. 2003-07-09 13:04 Martin Pool * NEWS: Credit Marcelo Matus. 2003-07-09 12:46 Martin Pool * NEWS: Bump version to 2.8 2003-07-09 12:01 Martin Pool * configure.ac: Bump version to 2.8 2003-07-08 17:02 Martin Pool * doc/results.txt: More results from SSH 2003-07-08 16:58 Martin Pool * src/md.c, Makefile.in: Remove md.c because we can't do anything very useful here. 2003-07-08 16:49 Martin Pool * src/arg.c: Doc. 2003-07-08 16:49 Martin Pool * Makefile.in, src/cpp.h: Remove md.c 2003-07-08 16:45 Martin Pool * Makefile.in: Add security page. 2003-07-08 16:11 Martin Pool * NEWS: [no log message] 2003-07-08 15:59 Martin Pool * src/cpp.c: Doc. 2003-07-08 15:45 Martin Pool * src/: arg.c, arg.h, argutil.c, clirpc.c, compile.c, cpp.c, distcc.c, distcc.h, exec.c, implicit.c, md.c, serve.c, srvrpc.c, ssh.c, strip.c: Move argument-handing prototypes to arg.h 2003-07-08 15:41 Martin Pool * src/arg.h, Makefile.in: arg.h: new file. 2003-07-08 15:17 Martin Pool * src/arg.c: Doc. 2003-07-08 15:11 Martin Pool * src/md.c: Doc 2003-07-08 15:05 Martin Pool * src/cpp.c: dcc_cpp_maybe: Call dcc_fudge_md. 2003-07-08 15:03 Martin Pool * src/: md.c, cpp.h: md.c: new file for dependency generation. 2003-07-08 14:59 Martin Pool * Makefile.in: md.c: new file. 2003-07-08 14:53 Martin Pool * src/strip.c: Doc. 2003-07-08 14:49 Martin Pool * src/cpp.c: Doc. 2003-07-08 14:44 Martin Pool * src/arg.c: Doc. 2003-07-08 14:36 Martin Pool * src/: arg.c, argutil.c: Move functions that are to do with handling argv[] arrays but not really distcc-specific intelligence from arg.c to argutil.c. * Delete dcc_deepcopy_argv which is no longer used. 2003-07-08 14:34 Martin Pool * Makefile.in: argutil.c: New file containing argv[] utilities. * Clean up harness object lists to use $(common_obj) 2003-07-08 14:31 Martin Pool * src/argutil.c: New file containing argv[] utilities. 2003-07-08 14:24 Martin Pool * test/testdistcc.py: Add test for distcc cc -otesttmp.o 2003-07-08 14:01 Martin Pool * NEWS: dcc_set_output: Add support for -ofoo.o. Based on a patch from Tsutomu Yasuda. 2003-07-08 13:57 Martin Pool * src/arg.c: dcc_set_output: Add support for -ofoo.o. Based on a patch from Tsutomu Yasuda. 2003-07-08 13:46 Martin Pool * distcc-check: Simple sanity-check script. 2003-07-08 13:23 Martin Pool * doc/example-init: Example Red Hat init file from Andrew Morton. 2003-07-08 13:20 Martin Pool * NEWS: Example xinetd configuration from akpm. 2003-07-08 13:19 Martin Pool * doc/example.xinetd: Doc 2003-07-08 13:16 Martin Pool * doc/example.xinetd, Makefile.in: Example xinetd configuration from akpm. 2003-07-08 13:06 Martin Pool * src/remote.c: Doc. 2003-07-08 12:42 Martin Pool * src/: clinet.c, io.c, io.h, sendfile.c: dcc_select_for_write, dcc_select_for_read: Both now take a timeout parameter, which is set by default to 15 for opening connections, and 300s for IO during a transfer. This should reduce problems with timeouts during an SSH connection. 2003-07-08 12:39 Martin Pool * NEWS: [no log message] 2003-07-08 12:18 Martin Pool * src/clinet.c: dcc_connect_timed: When connecting, we need to select() until the new socket is writeable, not readable. This bug was previously masked by the inverted call in dcc_select_for_read(). 2003-07-08 12:14 Martin Pool * src/remote.c: dcc_remote_connect: Factor out code to open a connection from dcc_compile_remote. 2003-07-07 23:57 Martin Pool * NEWS: dcc_run_job: Use separate input and output file descriptors, to support sshds that use pipes to run programs rather than local sockets. Suggestion from Felix Lee. 2003-07-07 23:53 Martin Pool * src/io.c: Handle EINTR from read and write. 2003-07-07 23:44 Martin Pool * src/io.c: dcc_select_for_write: Handle EINTR. * Doc. 2003-07-07 23:37 Martin Pool * src/io.c, NEWS: dcc_select_for_read: Fix silly parameter ordering mistake. 2003-07-07 23:31 Martin Pool * src/io.c: dcc_select_for_read: Fix warning. 2003-07-07 23:27 Martin Pool * src/io.c: dcc_select_for_read: Better trace messages. 2003-07-07 23:17 Martin Pool * src/: daemon.c, daemon.h, dparent.c, prefork.c, serve.c: dcc_run_job: Use separate input and output file descriptors, to support sshds that use pipes to run programs rather than local sockets. Suggestion from Felix Lee. 2003-07-07 23:15 Martin Pool * configure.ac: Don't give a warning about linuxdoc, because we do it during installation. 2003-07-07 23:03 Martin Pool * src/: serve.c: Doc. 2003-07-07 22:57 Martin Pool * NEWS: If Linuxdoc was not detected, just give a small warning and not an error while installing. 2003-07-07 22:25 Martin Pool * Makefile.in: If Linuxdoc was not detected, just give a small warning and not an error while installing. 2003-07-07 18:35 Martin Pool * doc/protocol-1.txt: Document the changes to support 0-byte output. 2003-07-07 18:34 Martin Pool * TODO: [no log message] 2003-07-07 18:33 Martin Pool * test/badcc: Add mode to generate empty output. 2003-07-07 18:08 Martin Pool * src/clirpc.c: Retrieval of the output file is now determined by the remote compiler status, not the DOTO length. This allows us to correctly get back a 0-length output file from a successful compile. 2003-07-07 18:03 Martin Pool * src/remote.c: Doc. 2003-07-07 17:59 Martin Pool * src/serve.c: Doc. 2003-07-07 17:48 Martin Pool * src/: bulk.h, bulk.c: Be more careful about treating token parameters as unsigned. 2003-07-07 17:28 Martin Pool * configure.ac, NEWS: Better test for vararg macro support that correctly identifies apple gcc brokenness. From Matt Watson . 2003-07-07 16:44 Martin Pool * NEWS: distccmon-text: Output should always be line-buffered, even if not writing to a terminal. 2003-07-07 15:27 Martin Pool * src/mon-text.c: distccmon-text: Output should always be line-buffered, even if not writing to a terminal. 2003-07-07 15:23 Martin Pool * src/mon-gnome.c: Doc. 2003-07-07 13:50 Martin Pool * src/state.c: dcc_note_state: Quote strings in trace message. 2003-07-07 12:55 Martin Pool * src/mon.h, NEWS: Protect against repeated inclusion. Suggestion from Fr'ed'eric Forjan. 2003-07-07 12:53 Martin Pool * src/mon.h: mon.h now uses "extern C" so that it can be included from C++ programs. Suggestion from Fr'ed'eric Forjan. 2003-06-25 17:50 Martin Pool * src/mon-gnome.c: Doc. 2003-06-25 17:48 Martin Pool * src/mon-gnome.c: Always update load, even if not onscreen, so that we don't show a dummy message at startup. 2003-06-25 17:46 Martin Pool * src/mon-gnome.c: Increase niceness at startup. 2003-06-25 17:43 Martin Pool * src/mon-gnome.c, NEWS: distccmon-gnome: Prevent selection of rows in the treeview. Emphasize horizontal rows ("rules-hint"). 2003-06-25 17:28 Martin Pool * NEWS: distccmon-gnome: Check whether the window is iconified or withdrawn, and if so then don't update. This slightly reduces the load in those cases. 2003-06-25 17:12 Martin Pool * src/mon-gnome.c: Expose a reference to the GtkTreeView widget and use that in the update callback. * Check whether the window is iconified or withdrawn, and if so then don't update. This slightly reduces the load in those cases. 2003-06-25 11:31 Martin Pool * NEWS: Prepare for 2.7.1 2003-06-25 11:28 Martin Pool * patches/state-in-home.diff: Store rolled-back ~/.distcc/state patch. 2003-06-25 11:27 Martin Pool * Makefile.in: Fix EXEEXT on gnome binaries. 2003-06-25 11:26 Martin Pool * configure.ac: Prepare for 2.7.1 * Fix EXEEXT on gnome binaries. 2003-06-25 10:59 Martin Pool * src/state.c, NEWS: Roll back: put the state in the temporary directory, because storing it in home does not seem to fix ebuild. 2003-06-24 13:40 Martin Pool * patches/hosts-from-file-raabe.diff: hosts-from-file-raabe.diff Has been merged 2003-06-21 14:21 Martin Pool * DEPENDENCIES: Note that libgnome is no longer required. 2003-06-21 13:45 Martin Pool * TODO: Updates based on work done recently. 2003-06-21 13:42 Martin Pool * NEWS, src/state.c: State files now in ~/.distcc/state 2003-06-21 13:13 Martin Pool * src/arg.c: Fix constness. 2003-06-20 17:32 Martin Pool * src/mon-gnome.c: Doc. 2003-06-20 17:29 Martin Pool * configure.ac: Add autoconf test for GTK+-2.0 (but don't call it yet.) * Change --enable-gnome to just check for GTK+. 2003-06-20 17:25 Martin Pool * src/mon-gnome.c: stdint.h is not needed. 2003-06-20 17:23 Martin Pool * Makefile.in, NEWS: distccmon-gnome now depends only on gtk+-2.0 2003-06-20 17:18 Martin Pool * src/mon-gnome.c: Follow the advice in the GTK+ 2.2 API: * Don't call gtk_widget_set_usize and gtk_window_set_policy, but instead just gtk_window_set_default_size. This gives us the same default size and allows the user to shrink the window, but doesn't let them shrink it right down to zero. 2003-06-20 17:15 Martin Pool * src/mon-gnome.c: Add some other necessary headers. 2003-06-20 17:14 Martin Pool * src/mon-gnome.c: Update to use just the GTK+ 2.0 API, and nothing from libgnomeui. 2003-06-16 18:40 Martin Pool * Makefile.in: Remove stupid autom4te.cache from distclean 2003-06-16 18:36 Martin Pool * src/arg.c: Remove TODO about -MD because the information is in TODO and I think I know how to fix it now. 2003-06-16 18:33 Martin Pool * src/cpp.c: Doc 2003-06-16 18:30 Martin Pool * configure.ac: Bump version 2003-06-16 17:51 Martin Pool * configure.ac, NEWS: Release 2.7. 2003-06-16 17:50 Martin Pool * src/arg.c: Doc 2003-06-16 17:39 Martin Pool * TODO: [no log message] 2003-06-16 17:06 Martin Pool * TODO: Notes on dnotify. 2003-06-16 16:59 Martin Pool * NEWS: [no log message] 2003-06-16 16:50 Martin Pool * Makefile.in: Need to link LIBS in to get functions like inet_ntoa on Solaris, etc. 2003-06-16 16:31 Martin Pool * src/mon-gnome.c: Make the tree sortable. 2003-06-16 14:39 Martin Pool * src/mon-gnome.c: Doc. 2003-06-16 14:38 Martin Pool * src/mon-gnome.c: Put commas in load average line. 2003-06-16 14:37 Martin Pool * src/mon-gnome.c: Load bar now actually shows the system load as we go. * Load bar is initialized at startup. 2003-06-16 14:31 Martin Pool * src/mon-gnome.c: Add a callback to update the load indicator. 2003-06-16 14:26 Martin Pool * src/mon-gnome.c: Fix up load indicator. 2003-06-16 14:17 Martin Pool * src/mon-gnome.c: Start adding a load indicator at the bottom of the window. 2003-06-16 13:48 Martin Pool * src/mon-notify.c, Makefile.in, src/mon.c: mon-notify.c: New file to keep the dnotify stuff out of mon.c 2003-06-16 13:41 Martin Pool * src/mon-gnome.c: Remove dnotify support, because the signals seem to cause trouble with GNOME, and too-frequent updates are bad for our CPU usage. 2003-06-16 13:15 Martin Pool * src/tempfile.c: Doc 2003-06-16 13:07 Martin Pool * NEWS: Check for sys/select.h, which is not present on HP-UX. 2003-06-16 13:03 Martin Pool * configure.ac, src/io.c: Check for sys/select.h, which is not present on HP-UX. 2003-06-16 12:48 Martin Pool * src/mon-gnome.c: Doc. 2003-06-16 12:43 Martin Pool * src/mon.c: Doc. 2003-06-16 12:33 Martin Pool * src/: clirpc.c, clirpc.h, compile.c, exec.c, exec.h, mon.c, rpc.c, rpc.h, serve.c, srvrpc.c: Store all token parameter values, including lengths and waitstatuses to unsigned throughout the program. Fixes some warnings on Sun and probably a bit safer. 2003-06-16 12:25 Martin Pool * src/arg.c: dcc_note_compiled: Fix constness. 2003-06-16 12:25 Martin Pool * src/util.c: snprintf.h is needed. 2003-06-16 12:24 Martin Pool * src/distcc.h: Change dcc_trace_argv macro to try to quieten warnings on Sun. 2003-06-16 12:21 Martin Pool * src/trace.h: Add RS_STMT_START macros from glib, to quieten warnings on Sun. 2003-06-16 12:19 Martin Pool * src/hosts.c: snprintf.h is needed. 2003-06-16 12:17 Martin Pool * src/: mon-gnome.c, mon.c, mon.h: Rename dcc_gnome_setup_dnotify to dcc_gnome_setup_notify to be less Linux-specific. * Add documentation on the mon interface to help people writing new monitors. 2003-06-16 12:08 Martin Pool * src/tempfile.c: Doc 2003-06-16 12:05 Martin Pool * configure.ac: Fix configure messages. 2003-06-16 12:04 Martin Pool * configure.ac: Only check for libgnomeui-2.0 if --enable-gnome was specified. 2003-06-16 11:27 Martin Pool * doc/results.txt: Notes on performance of monitor with dnotify. 2003-06-14 20:09 Martin Pool * TODO: IPv6 is now done. 2003-06-14 20:08 Martin Pool * TODO: Notes on nicely handling gcc -MD. 2003-06-13 17:30 Martin Pool * src/clinet.c: Doc. 2003-06-13 14:57 Martin Pool * src/mon-gnome.c: Change default size * Print out a star when we reread the directory. 2003-06-13 14:39 Martin Pool * src/mon-gnome.c: Even if we can use dnotify, still poll every 10s to clean up dead files. 2003-06-13 14:33 Martin Pool * src/mon.c: Also listen for deletion notifications to make sure that we notice when the last compiler quits. 2003-06-13 14:31 Martin Pool * src/mon-gnome.c: Attach to dnotify prompts from mon.c and drain them as they arrive. 2003-06-13 14:28 Martin Pool * src/mon.c: dcc_mon_setup_dnotify: Check that the fcntl to set F_NOTIFY suceeded -- this can fail on linux systems that don't have dnotify in the kernel. 2003-06-13 12:55 Martin Pool * NEWS: Fix spelling mistake. 2003-06-13 12:18 Martin Pool * src/mon.c: Dnotify stuff now actually writes to the dummy pipe when the state changes. 2003-06-13 12:14 Martin Pool * src/: mon.c, state.c: Doc. 2003-06-12 22:02 Martin Pool * src/mon.c: Doc 2003-06-12 21:58 Martin Pool * src/mon.c: Fix up half-committed code. 2003-06-12 21:55 Martin Pool * configure.ac, src/mon-gnome.c: Fix up half-committed code. 2003-06-12 18:13 Martin Pool * TODO, src/mon-gnome.c, src/mon.c, src/mon.h: Start adding dnotify support for monitor rather than polling. 2003-06-12 18:02 Martin Pool * Makefile.in: Fix distccmon-gnome 2003-06-12 18:00 Martin Pool * Makefile.in: Make sure to use the right cpp flags when building distccmon-gnome 2003-06-12 17:56 Martin Pool * Makefile.in: distccmon-gnome needs nonblocking routines from netutil.o 2003-06-12 17:50 Martin Pool * src/mon-gnome.c: Refactor 2003-06-12 17:37 Martin Pool * src/mon-gnome.c: Doc. 2003-06-12 17:27 Martin Pool * src/mon-gnome.c: GTK 2.0 manual says that gtk_timeout_add is deprecated in favour of g_timeout_add. 2003-06-12 17:26 Martin Pool * src/mon-gnome.c: Show USER@HOST in monitor title bar, because it's possible people will run this remotely. 2003-06-12 16:57 Martin Pool * NEWS: If --enable-gnome was specified, then check that libgnomeui is actually present. 2003-06-12 16:52 Martin Pool * configure.ac: Bump version * If --enable-gnome was specified, then check that libgnomeui is actually present. 2003-06-12 16:38 Martin Pool * src/mon-gnome.c: Doc 2003-06-12 16:27 Martin Pool * DEPENDENCIES: Describe dependencies for GNOME. 2003-06-12 16:25 Martin Pool * src/mon-gnome.c: The GTK tree model is now updated on each new monitor state. It seems to be working correctly. 2003-06-12 16:09 Martin Pool * src/mon-gnome.c: Reindent only. 2003-06-12 16:06 Martin Pool * src/mon-gnome.c: Add a callback every 0.5s. At the moment it does nothing. 2003-06-12 15:56 Martin Pool * TODO: More small updates. 2003-06-12 15:51 Martin Pool * TODO: Remove many done TODO items, and add notes on some continuing ones. 2003-06-12 15:40 Martin Pool * src/clirpc.c: Doc 2003-06-12 13:47 Martin Pool * src/compile.c: dcc_build_somewhere: input_fname must be initialized to NULL so that in the case of a very early fallback to local compilation we don't read an invalid pointer and crash. 2003-06-12 13:44 Martin Pool * src/: clirpc.c, remote.c, state.c: Remove infrequently-hit states. 2003-06-12 13:42 Martin Pool * src/compile.c: Remove "Startup" state because it's very unlikely to be hit. 2003-06-12 12:53 Martin Pool * configure.ac: Prepare for 2.6 release. 2003-06-12 12:41 Martin Pool * src/prefork.c: dcc_preforking_parent: Put in another 1s sleep between collecting dead children and starting new ones. 2003-06-12 12:35 Martin Pool * NEWS: Reorder sections. Patch from Sean MacLennan: * dcc_ncpus for Linux: make sure that we don't return 0 cpus. 2003-06-12 12:34 Martin Pool * src/ncpus.c: Patch from Sean MacLennan: * dcc_ncpus for Linux: make sure that we don't return 0 cpus. 2003-06-12 12:14 Martin Pool * NEWS: Get ready for 2.66 release. 2003-06-12 12:04 Martin Pool * Makefile.in: Include doc/status-1.txt in distribution. 2003-06-12 12:00 Martin Pool * doc/status-1.txt: Update to describe the implemented monitor design. 2003-06-12 09:53 Martin Pool * NEWS: Reorder items 2003-06-12 09:30 Martin Pool * NEWS: Note changed tmpdir name. 2003-06-12 00:34 Martin Pool * src/mon.c: Skip state files for which the process no longer exists. 2003-06-12 00:29 Martin Pool * src/state.c: Call the blocked state "starved". 2003-06-12 00:28 Martin Pool * src/state.c: Call the blocked state "bored" 2003-06-12 00:26 Martin Pool * src/mon.c: Doc. 2003-06-12 00:17 Martin Pool * src/clirpc.c: Doc. 2003-06-12 00:15 Martin Pool * src/clirpc.c: Add more states: distinguish more states: waiting for preprocessor, sending source, and receiving object. 2003-06-12 00:12 Martin Pool * src/: state.h, state.c: Add more states. 2003-06-12 00:09 Martin Pool * src/mon-text.c: Clip columns to appropriate widths. 2003-06-12 00:04 Martin Pool * src/: compile.c: Note input filename as soon as it has been determined. 2003-06-12 00:03 Martin Pool * src/: compile.c, compile.h, remote.c, where.c, where.h: Roll back the rest of the xmit lock code. * Rely on state code to keep track of what source file we're compiling. 2003-06-11 22:41 Martin Pool * src/: compile.c, state.c, state.h: Show another state during startup. 2003-06-11 22:38 Martin Pool * src/state.c: Doc 2003-06-11 22:37 Martin Pool * src/clirpc.c: dcc_retrieve_results: Try to keep the right file name when updating state. 2003-06-11 22:36 Martin Pool * TODO: Thoughts on -MD support. 2003-06-11 22:36 Martin Pool * NEWS: [no log message] 2003-06-11 22:34 Martin Pool * src/remote.c: Doc 2003-06-11 22:31 Martin Pool * src/remote.c: dcc_compile_remote: Try to keep the right file name when updating state. 2003-06-11 22:30 Martin Pool * src/where.c: dcc_lock_pause: Set state notification when blocked. 2003-06-11 22:29 Martin Pool * src/: state.c, state.h: dcc_note_state: constness 2003-06-11 22:29 Martin Pool * src/: filename.h, filename.c: dcc_find_basename: constness 2003-06-11 22:26 Martin Pool * src/state.c: dcc_note_state: Remember the previously-set filename and host, so that we can just change state without needing to always know the filename. 2003-06-11 22:22 Martin Pool * src/: state.c, state.h: Add STATE_BLOCKED. 2003-06-11 22:21 Martin Pool * src/state.h: Delete garbage comment. 2003-06-11 17:22 Martin Pool * src/mon.c: Doc. 2003-06-11 17:20 Martin Pool * Makefile.in: Remove done todo 2003-06-11 17:19 Martin Pool * doc/results.txt: Measurements with state notes turned on. 2003-06-11 17:18 Martin Pool * src/: compile.c, compile.h, remote.c: dcc_compile_remote: Input filename is passed in for use in state notes. 2003-06-11 17:17 Martin Pool * src/remote.c: dcc_compile_remote: xmit_lock_fd is unused for now. 2003-06-11 17:14 Martin Pool * src/remote.c: Doc. 2003-06-11 17:07 Martin Pool * src/mon-text.c: Doc. 2003-06-11 17:02 Martin Pool * NEWS: [no log message] 2003-06-11 16:59 Martin Pool * src/mon-text.c: Take one optional parameter, which sets a time to wait between refreshes. Currently done using usleep(), which may not be portable. 2003-06-11 16:58 Martin Pool * src/mon.c: dcc_mon_poll: Fix memory scribble. 2003-06-11 16:53 Martin Pool * src/state.c: Doc. 2003-06-11 16:46 Martin Pool * NEWS: [no log message] 2003-06-11 16:29 Martin Pool * src/state.c: Only unlink file before replacing on cygwin. 2003-06-11 16:24 Martin Pool * src/state.c: Write state out into temporary files and rename into place, to try to avoid monitors ever seeing half-full files. 2003-06-11 15:19 Martin Pool * src/mon.c: Reduce max age to 30s. 2003-06-11 15:06 Martin Pool * src/tempfile.c: Include hostname in tempdir name, to avoid problems when /tmp is shared. 2003-06-11 15:03 Martin Pool * NEWS: Note distccmon-text. 2003-06-11 15:00 Martin Pool * src/tempfile.c: dcc_make_tmpnam: Just use asprintf() now we have it, rather than doing the equivalent by hand. Use the plain pid in temporary filenames rather than zero-filling it. 2003-06-11 14:55 Martin Pool * src/mon-text.c: Dump out the monitor list in a simple text table form. 2003-06-11 14:50 Martin Pool * src/mon.c: Doc * dcc_mon_kill_old: Always close fd on failure. * Build up a list of dcc_mon_list structures as the files are read in. * dcc_mon_list_free: Walk down the list, freeing each link. 2003-06-11 14:24 Martin Pool * src/mon.c: Read host and file variabels from state. 2003-06-11 14:22 Martin Pool * src/mon.c: Put in constant for the time to allow statefiles to live, and reduce to 60s. * Read state string. 2003-06-11 14:19 Martin Pool * src/mon.c: Check for and kill old state files. * Read in the start of the state file. 2003-06-11 14:15 Martin Pool * src/: rpc.c, rpc.h, srvrpc.c: dcc_r_token_string: New function factored out. 2003-06-11 14:06 Martin Pool * src/exitcode.h: Add EXIT_GONE 2003-06-11 12:41 Martin Pool * src/mon-text.c: distccmon-gnome: Emit blank at end. 2003-06-11 12:41 Martin Pool * src/mon.c: dcc_mon_do_file: Open each state file and handle missing ones. * dcc_mon_poll: Fix reference to freed memory. 2003-06-11 12:35 Martin Pool * src/: state.c, state.h: dcc_state_prefix: Export identifying prefix for state files. 2003-06-11 12:35 Martin Pool * src/mon.c: dcc_mon_do_file: New function. Skip everything but state files. 2003-06-11 12:31 Martin Pool * src/mon.c: dcc_mon_poll: Partial implementation that just traverses the directory. 2003-06-11 12:30 Martin Pool * src/mon-text.c: Set trace level from environment. 2003-06-11 12:30 Martin Pool * src/distcc.c, src/distcc.h, src/traceenv.c, Makefile.in: dcc_set_trace_from_env: Split out into new file src/traceenv.c, so that this can also be used from monitor programs. 2003-06-11 12:29 Martin Pool * .cvsignore: Ignore distccmon-text binary. 2003-06-11 12:24 Martin Pool * src/trace.c: Default trace should get all messages allowed by log level. 2003-06-11 12:22 Martin Pool * Makefile.in: Build and install distccmon-text 2003-06-11 12:19 Martin Pool * src/trace.c: Typo 2003-06-11 12:18 Martin Pool * src/trace.c: If no logger has been initialized when the first message goes out, then write to stderr. 2003-06-11 12:13 Martin Pool * src/mon.h: Declare part of the monitor API 2003-06-11 12:13 Martin Pool * src/mon-text.c: Hook in to trace code. 2003-06-11 12:11 Martin Pool * Makefile.in: More routines are needed for monitors 2003-06-11 12:06 Martin Pool * src/mon-text.c: Hook in to trace code. * Doc. 2003-06-11 12:04 Martin Pool * src/: exec.c, util.c: dcc_remove_if_exists: Move to util.c 2003-06-11 12:04 Martin Pool * Makefile.in: Add mon_obj variable for building monitor programs. 2003-06-11 11:58 Martin Pool * src/mon-text.c: src/mon-text.c: New file. 2003-06-11 11:57 Martin Pool * Makefile.in: Include src/mon-gnome.c in distribution * src/mon-text.c: New file. 2003-06-11 11:51 Martin Pool * src/state.c: dcc_note_state: Put client pid in state. 2003-06-11 11:50 Martin Pool * Makefile.in, src/mon.c, src/mon.h: src/mon.c, src/mon.h: New files. 2003-06-11 11:48 Martin Pool * src/: clirpc.c, remote.c: Add more calls to publish state. 2003-06-11 11:43 Martin Pool * src/state.c: dcc_note_state: Handle null file or host names. 2003-06-11 11:39 Martin Pool * src/: distcc.c, state.c, state.h: Call dcc_remove_state_file from atexit in client. 2003-06-11 11:37 Martin Pool * src/state.c: dcc_remove_state_file: Implement. 2003-06-11 11:35 Martin Pool * src/state.c: dcc_open_state_file: Release memory after use. 2003-06-11 11:32 Martin Pool * src/: rpc.c, rpc.h: dcc_x_token_string: Make buffer const. 2003-06-11 11:31 Martin Pool * src/state.c: dcc_note_state: Include file and host too. 2003-06-11 11:28 Martin Pool * src/state.c: dcc_note_state: Include state string as well. 2003-06-11 11:26 Martin Pool * src/clirpc.c: dcc_x_argv: Call dcc_x_token_string rather than doing it inline. 2003-06-11 11:22 Martin Pool * src/: rpc.h, rpc.c: dcc_x_token_string: New function factored out. 2003-06-11 11:06 Martin Pool * Makefile.in: Subst in LINUXDOC. 2003-06-11 11:02 Martin Pool * configure.ac: AC_ARG_VAR LINUXDOC 2003-06-11 11:00 Martin Pool * configure.ac: Add a check for existence of linuxdoc. 2003-06-11 10:47 Martin Pool * src/snprintf.h: snprintf.h needs to include stdarg.h to get va_list. Possibly fixes IRIX. 2003-06-10 18:23 Martin Pool * NEWS: Patch from Paul Russell: * If the compiler is not found on the server and is a fully-qualified name, then strip off the full name and just look for it on the path. 2003-06-10 18:16 Martin Pool * src/exec.c: Doc. 2003-06-10 18:15 Martin Pool * src/exec.c: Patch from Paul Russell: * If the compiler is not found on the server and is a fully-qualified name, then strip off the full name and just look for it on the path. 2003-06-10 18:00 Martin Pool * doc/release-names.txt: [no log message] 2003-06-10 18:00 Martin Pool * NEWS: Note new state files. 2003-06-10 17:57 Martin Pool * src/stat.c, src/stat.h, src/state.c, src/state.h, Makefile.in, src/compile.c: Rename stat.* to state.* 2003-06-10 17:57 Martin Pool * src/stat.h: dcc_remove_state_file: New function. 2003-06-10 17:56 Martin Pool * src/stat.c: dcc_get_state_file: New function to return the name of the state file for this process. * dcc_note_state: Start writing into state file. 2003-06-10 17:43 Martin Pool * src/compile.c: Update state directory when compiling locally. 2003-06-10 17:42 Martin Pool * src/arg.c: Factor out "compile from %s to %s" message into its own function, and log only the basename. Should prevent page-widening in server logs. 2003-06-10 17:41 Martin Pool * src/: stat.c, stat.h: dcc_note_state only logs the basename of the file. 2003-06-10 17:39 Martin Pool * src/stat.c: dcc_note_state: Trim filename down to basename. 2003-06-10 17:37 Martin Pool * NEWS: Try to fix UTF-8 coding, which seemed to be mangled by CVS. 2003-06-10 17:31 Martin Pool * NEWS: In compilation log message, just show the basename of the file to make it more compact. 2003-06-10 17:23 Martin Pool * src/: stat.h, stat.c: Add compile state constants. 2003-06-10 17:16 Martin Pool * src/: filename.h, filename.c: dcc_find_basename: New function. 2003-06-10 16:57 Martin Pool * src/compile.c: Remove unneeded header. 2003-06-10 16:55 Martin Pool * src/: stat.c, stat.h: dcc_note_state: New function to record what the client's up to. 2003-06-10 16:54 Martin Pool * src/: bulk.c, distcc.h: Move O_BINARY ifdef to distcc.h 2003-06-10 15:56 Martin Pool * Makefile.in: New file stat.h 2003-06-10 15:55 Martin Pool * src/: stat.c, stat.h: New file stat.h * Add routine to open a state file. 2003-06-10 15:55 Martin Pool * .cvsignore: Ignore distccmon-gnome. 2003-06-10 15:49 Martin Pool * src/stat.c: Doc * Add function to create/return state directory. 2003-06-10 15:47 Martin Pool * src/tempfile.h: Split code for idempotent directory creation out into a new function dcc_make_dir, so that it can be used by state file code. 2003-06-10 15:33 Martin Pool * src/tempfile.c: Split code for idempotent directory creation out into a new function dcc_make_dir, so that it can be used by state file code. 2003-06-10 15:23 Martin Pool * src/mon-gnome.c: Add columns for file and host * Add more sample data * Refactor code to create table view. 2003-06-10 15:14 Martin Pool * src/mon-gnome.c: Set a more reasonable default size. 2003-06-10 15:09 Martin Pool * src/mon-gnome.c: Refactor into smaller functions * Remove horizontal scrollbar; vertical only as needed. * Remove dummy text entry 2003-06-10 15:00 Martin Pool * NEWS: Start adding a GNOME-based monitor. 2003-06-10 14:58 Martin Pool * Makefile.in: make clean: Remove distccmon-gnome, even if it's currently not configured on. 2003-06-10 14:57 Martin Pool * Makefile.in, configure.ac: Add --enable-gnome configure option. When set, build and install distccmon-gnome. 2003-06-09 23:09 Martin Pool * src/mon-gnome.c: Add more sample data. 2003-06-09 23:07 Martin Pool * Makefile.in: Add hardcoded rule for distccmon-gnome. 2003-06-09 23:05 Martin Pool * doc/status-1.txt: Update status indicator notes. 2003-06-09 23:03 Martin Pool * src/stat.c: Stub for status indicator. 2003-06-09 19:23 Martin Pool * src/mon-gnome.c: Start of a monitor implementation in GTK+-2.2. Displays a window with a list containing only "42". 2003-06-09 18:37 Martin Pool * src/: mon-gnome.c, mon-gtk.c: Stub implementation of GNOME monitor. 2003-06-09 18:35 Martin Pool * src/: netutil.c, netutil.h: Add implementation of hstrerror() for systems that don't have it. 2003-06-09 18:28 Martin Pool * Makefile.in: src/stat.c: New file. 2003-06-09 15:23 Martin Pool * src/mon-gtk.c: Add a stub GTK+ monitor interface -- compiles and shows an empty window but does nothing. 2003-06-09 14:26 Martin Pool * NEWS: Note that hstrerror() is now supplied. 2003-06-09 12:47 Martin Pool * src/remote.c: Remove more unneeded headers. 2003-06-09 12:43 Martin Pool * src/: distcc.c, compile.c: Remove more unneeded headers. 2003-06-09 12:36 Martin Pool * src/distcc.c: Remove more unneeded headers. 2003-06-09 12:33 Martin Pool * src/distcc.c: Remove unneeded headers. 2003-06-08 20:05 Martin Pool * test/testdistcc.py, NEWS: Fix silly typo that made maintainer-check fail in ParseHostSpec_Case. 2003-06-08 19:52 Martin Pool * Makefile.in, src/compile.c, src/compile.h, src/distcc.c: Split other client-side compile functionality into src/compile.c. src/distcc.c now only has the top-level client code. * src/compile.c: New file. 2003-06-08 19:43 Martin Pool * Makefile.in, src/compile.h, src/distcc.c, src/remote.c: Split dcc_compile_remote into src/remote.c, and make it public. * compile.h, remote.c: New files. 2003-06-08 19:36 Martin Pool * TODO: Multiple updates to TODO file. 2003-06-08 19:19 Martin Pool * src/distcc.c, NEWS: Look for UNCACHED_ERR_FD environment variable, to allow distcc networking errors to avoid being cached by ccache. 2003-06-06 13:07 Martin Pool * TODO: OpenMOSIX autodiscovery 2003-06-05 17:44 Martin Pool * TODO: Rearrange comments on DNS A and SRV records. * Move question about --enable-final to web. 2003-06-05 17:34 Martin Pool * TODO: 2.5 bug is fixed. 2003-06-05 17:26 Martin Pool * Makefile.in: Include doc/protocol-1.txt in distribution. 2003-06-05 17:21 Martin Pool * configure.ac: Bump version back to 2.6cvs 2003-06-05 17:03 Martin Pool * NEWS: Note connection timeout added in 2.5.1. 2003-06-05 16:53 Martin Pool * NEWS, configure.ac: Prepare for 2.5.1 release. 2003-06-05 16:48 Martin Pool * src/io.c, NEWS: sys/time.h might be needed for select on SuSE 7.1 (spe158). 2003-06-05 16:45 Martin Pool * src/hosts.c, NEWS: dcc_parse_multiplier must advance over the multiplier to be able to read things like "angry/30:3000" correctly. Patch from Wayne Davison. 2003-06-05 16:43 Martin Pool * linuxdoc/distcc.sgml: Get out these fixes in 2.5.1. 2003-06-05 16:42 Martin Pool * test/testdistcc.py, NEWS: Add check for support of old multiplier format. (angry/44:300) 2003-06-05 16:41 Martin Pool * test/testdistcc.py: Doc 2003-06-05 16:39 Martin Pool * configure.ac: Get out these fixes in 2.5.1. 2003-06-05 16:36 Martin Pool * NEWS: Get out these fixes in 2.5.1. 2003-06-05 16:17 Martin Pool * src/: clinet.c, netutil.c, netutil.h, srvnet.c: Rename everything called 'sa_len' because this is #defined on IRIX. (Yuk) 2003-06-05 16:12 Martin Pool * NEWS: Fix IRIX. 2003-06-05 16:09 Martin Pool * NEWS: Recode as UTF-8. 2003-06-05 16:08 Martin Pool * NEWS: Solaris fixes from Tomas. 2003-06-05 16:08 Martin Pool * src/daemon.h: dcc_master_pid is really a pid_t. 2003-06-05 16:07 Martin Pool * src/netutil.c: Can't use "sun" as an identifier on gcc Solaris 8. 2003-06-05 16:03 Martin Pool * doc/release-names.txt: [no log message] 2003-06-04 23:19 Martin Pool * src/dparent.c: Doc. 2003-06-04 11:22 Martin Pool * doc/status-1.txt: Notes on design possibilities. 2003-06-03 08:37 Martin Pool * doc/noent.txt: Transient bug while compiling. 2003-06-03 08:23 Martin Pool * doc/status-1.txt: Notes on status reporting 2003-06-02 15:48 Martin Pool * src/netutil.c: This file needs snprintf.h * AF_LOCAL might be missing on Solaris. 2003-06-02 15:45 Martin Pool * TODO: [no log message] 2003-06-02 14:46 Martin Pool * doc/release-names.txt: [no log message] 2003-06-02 13:20 Martin Pool * src/dparent.c: Clarify "%d CPUs online" message. http://groups.google.com/groups?q=distcc&hl=en&lr=&ie=UTF-8&oe=UTF-8&scoring=d&selm=1054494726.347698%40auth2.dns.griffin.net.uk&rnum=1 2003-06-02 13:13 Martin Pool * survey.txt: Clarify privacy clause for survey. 2003-06-02 13:11 Martin Pool * NEWS: [no log message] 2003-05-31 00:29 Martin Pool * doc/protocol-1.txt: Start handling empty output files. 2003-05-31 00:29 Martin Pool * TODO: [no log message] 2003-05-30 23:49 Martin Pool * src/: bulk.c, distcc.h: dcc_open_read can be static. 2003-05-30 23:47 Martin Pool * src/bulk.c: Remove dead code. 2003-05-30 12:58 Martin Pool * linuxdoc/distcc.sgml: Add section about Mailing lists. 2003-05-30 12:45 Martin Pool * src/dsignal.c: Doc. 2003-05-29 09:00 Martin Pool * src/access.c: Doc 2003-05-28 17:34 Martin Pool * src/: clinet.c, io.c: Increase timeout to 15s. * Move select() check into dcc_select_for_read 2003-05-28 17:28 Martin Pool * src/clinet.c: dcc_connect_timed: Add trace. 2003-05-28 17:16 Martin Pool * src/clinet.c: Doc 2003-05-28 17:13 Martin Pool * TODO, doc/results.txt: [no log message] 2003-05-28 17:01 Martin Pool * src/clinet.c: Impose 5s timeout on opening TCP connections. Change to using nonblocking sockets (just while opening). 2003-05-28 16:16 Martin Pool * Makefile.in: Move check functionality to maintainer-check, because I don't want it to run by default on the build farm. 2003-05-28 16:13 Martin Pool * NEWS: [no log message] 2003-05-28 16:11 Martin Pool * src/distcc.c: Include hostdef string in "failed to distribute" warning. 2003-05-28 16:03 Martin Pool * src/: netutil.h, ssh.c, netutil.c: dcc_set_nonblocking, dcc_set_blocking: Move to netutil.h 2003-05-28 15:57 Martin Pool * TODO: The server in fact already generates the right extension name for temporary files. But this might be a problem for the proposed new protocol. 2003-05-28 15:50 Martin Pool * src/serve.c: dcc_run_job: Split some code out into dcc_input_tmpnam. 2003-05-28 15:50 Martin Pool * doc/results.txt: [no log message] 2003-05-28 15:46 Martin Pool * TODO: Preforking is now done. 2003-05-28 15:45 Martin Pool * TODO: Thoughts on boredom and temporary file extensions. 2003-05-28 15:29 Martin Pool * linuxdoc/distcc.sgml, NEWS: Document use from inetd. * Document -j option. 2003-05-28 15:08 Martin Pool * linuxdoc/distcc.sgml: Notes on running daemon from init and standalone. 2003-05-28 14:51 Martin Pool * NEWS: dcc_setpgid: Rename to dcc_new_pgrp. * dcc_new_pgrp: Don't call setpgid() if we're already a process group leader, because this fails with EPERM if we happen to also be a session group leader. 2003-05-28 14:42 Martin Pool * src/: dparent.c, exec.c, exec.h: dcc_setpgid: Rename to dcc_new_pgrp. * dcc_new_pgrp: Don't call setpgid() if we're already a process group leader, because this fails with EPERM if we happen to also be a session group leader. 2003-05-28 14:31 Martin Pool * configure.ac: Bump version 2003-05-28 14:13 Martin Pool * NEWS: Need types.h 2003-05-28 14:03 Martin Pool * src/daemon.c: Need types.h 2003-05-27 19:18 Martin Pool * src/serve.c: Tweak trace message. 2003-05-27 19:17 Martin Pool * src/bulk.c: Disable dcc_x_file_timed, which is no longer called. 2003-05-27 19:12 Martin Pool * configure.ac, NEWS, doc/release-names.txt: Prepare for 2.5 release. 2003-05-27 19:11 Martin Pool * src/daemon.c: Doc. * If getpeername() fails on a socket then continue anyhow. 2003-05-27 19:08 Martin Pool * TODO: SSH child is now collected by the client. 2003-05-27 18:55 Martin Pool * NEWS: [no log message] 2003-05-27 18:54 Martin Pool * src/distcc.c: Only collect SSH child if we actually started one. (How embarrassing.) 2003-05-27 18:48 Martin Pool * src/distcc.c: Log elapsed time for whole compilation. 2003-05-27 18:42 Martin Pool * src/: serve.c, clirpc.c: Don't time transmission of a file: because a large fraction of it can be stuck in network buffers it is not a very accurate measure. 2003-05-27 18:39 Martin Pool * TODO: [no log message] 2003-05-27 18:35 Martin Pool * TODO: Note on handling SIGCHLD from cpp. 2003-05-27 18:17 Martin Pool * src/: distcc.c: Doc. 2003-05-27 18:16 Martin Pool * src/: clirpc.c, distcc.c, exec.c, exec.h, serve.c: dcc_report_rusage: Merge into dcc_collect_child because they're coupled. * dcc_collect_child: Don't pass back rusage. Do take a descriptive name for the child. * dcc_compile_remote: Collect the SSH child after the connection is closed. 2003-05-27 18:06 Martin Pool * src/distcc.c: Add pointer to manual in usage message. 2003-05-27 17:54 Martin Pool * src/netutil.c: dcc_sockaddr_to_string: Remove "INET" from IP address. 2003-05-27 17:54 Martin Pool * src/clinet.c: dcc_connect_by_addr: Print sockaddr in raw form. 2003-05-27 15:11 Martin Pool * test/testdistcc.py: ParseMask_Case: Better error message. 2003-05-27 14:58 Martin Pool * doc/results.txt: Notes on prefork mode. 2003-05-27 14:43 Martin Pool * src/daemon.h: Fix decl. 2003-05-27 14:42 Martin Pool * src/hosts.c: Fix C syntax. 2003-05-27 14:41 Martin Pool * TODO: Update notes on fsh/ssh. 2003-05-27 12:26 Martin Pool * src/serve.c: Tweak log messages. 2003-05-27 11:44 Martin Pool * linuxdoc/distcc.sgml: Recommend using log files. 2003-05-27 11:41 Martin Pool * src/prefork.c: dcc_preforked_child can be static. 2003-05-27 11:07 Martin Pool * src/exec.c: dcc_critique_status: Tweak log output. 2003-05-27 11:05 Martin Pool * src/exec.c: dcc_critique_status: Better message for termination by signal. 2003-05-27 11:00 Martin Pool * src/lock.c: Show lock fd in trace messages. 2003-05-27 10:59 Martin Pool * src/srvnet.c: dcc_sockaddr_to_ip now indicates which AF it is. 2003-05-27 10:58 Martin Pool * src/netutil.c: Better description of AF_UNIX sockets. 2003-05-27 10:54 Martin Pool * src/netutil.c: dcc_sockaddr_to_string: Handle AF_LOCAL and unknown AF addresses. Return "INET 1.2.1.2:323" to distinguish AFs. 2003-05-27 10:49 Martin Pool * src/: netutil.c, netutil.h, srvnet.c: dcc_sockaddr_to_ip: Rename to dcc_sockaddr_to_string. 2003-05-27 10:46 Martin Pool * src/bulk.c: Doc 2003-05-27 10:43 Martin Pool * src/bulk.c: Tweak trace message. 2003-05-27 10:42 Martin Pool * src/sendfile.c: Doc. 2003-05-27 10:28 Martin Pool * src/: distcc.c, where.c: Disable XMIT locks for the moment. 2003-05-26 18:43 Martin Pool * doc/results.txt: More testing. 2003-05-26 18:39 Martin Pool * doc/results.txt: More testing. 2003-05-26 18:09 Martin Pool * NEWS: Client no longer considers NCPUs. 2003-05-26 18:08 Martin Pool * src/bulk.c: Tweak trace message. 2003-05-26 17:53 Martin Pool * TODO: [no log message] 2003-05-26 17:45 Martin Pool * src/hosts.c: Fix warning. 2003-05-26 17:44 Martin Pool * src/hosts.c, Makefile.in: Don't look at the number of CPUs on the client; it's too expensive. 2003-05-26 17:39 Martin Pool * src/srvnet.c, src/dparent.c, NEWS: Log full passive sockaddr in listen message. 2003-05-26 17:36 Martin Pool * src/dparent.c: Shuffle startup messages. 2003-05-26 17:34 Martin Pool * src/dsignal.c, NEWS: Make sure to remove handler before re-raising signal, or Valgrind gets its kickers in a knot. 2003-05-26 17:30 Martin Pool * src/serve.c: dcc_service_job: Split off code for checking access control. 2003-05-26 17:13 Martin Pool * src/: daemon.c, daemon.h, distcc.h, dparent.c, prefork.c, serve.c, srvnet.c, srvnet.h: Use the sockaddr passed in by accept() when a connection is accepted, rather than doing an extra getpeername() call. * dcc_accept_job: Rename to dcc_service_job, since accept() is no longer called from here. 2003-05-26 17:00 Martin Pool * NEWS: dcc_listen_by_addr: Show sockaddr if bind fails. 2003-05-26 16:58 Martin Pool * src/netutil.c: dcc_sockaddr_to_ip: sin_port is in network byte order. 2003-05-26 16:57 Martin Pool * src/srvnet.c: Fix silly typo. 2003-05-26 16:56 Martin Pool * src/srvnet.c: dcc_listen_by_addr: Show sockaddr if bind fails. 2003-05-26 16:53 Martin Pool * src/netutil.c: dcc_sockaddr_to_ip: Show port number as well as IP address. 2003-05-26 16:46 Martin Pool * src/srvnet.c: Split out "address family" part from "connection from" message. 2003-05-26 16:35 Martin Pool * src/daemon.c: Fix syntax problem and missing header. 2003-05-26 16:34 Martin Pool * NEWS: Move daemon into temporary directory during startup. 2003-05-26 16:33 Martin Pool * src/daemon.c: Doc. 2003-05-26 16:32 Martin Pool * src/daemon.c: main: Refactor error handling. * Move daemon into temporary directory during startup. 2003-05-26 16:29 Martin Pool * src/: tempfile.c, tempfile.h: dcc_enter_tempdir: New function. 2003-05-26 16:27 Martin Pool * src/tempfile.c, NEWS: Just use decimal userid rather than username in temporary directory. 2003-05-26 16:22 Martin Pool * src/setuid.c: Undo 1.3 2003-05-26 16:21 Martin Pool * src/setuid.c: Move opt_user to somewhere it can be reached by tmpfile. 2003-05-26 16:19 Martin Pool * NEWS: Use username or decimal userid for temporary directory name. 2003-05-26 15:55 Martin Pool * src/serve.c: Doc. 2003-05-26 15:54 Martin Pool * src/serve.c: Fix naming of stdout, stderr temporary files. * Call server object file .o. 2003-05-26 15:51 Martin Pool * src/serve.c: dcc_accept_job: Close down ecolog connection to server error log, so that we don't leak fds in prefork mode. 2003-05-26 15:48 Martin Pool * src/trace.c: rs_remove_logger: New function to allow turning off loggers without shutting everything down. 2003-05-26 15:42 Martin Pool * src/trace.h: rs_remove_logger: New function. 2003-05-26 15:38 Martin Pool * src/prefork.c: Message when child exits. 2003-05-26 15:13 Martin Pool * test/testdistcc.py: Add tests for new host multiplicity specifications. 2003-05-26 15:12 Martin Pool * src/dsignal.c: Remove unneeded headers. 2003-05-26 15:07 Martin Pool * linuxdoc/distcc.sgml: TCP hosts can now be specified in the more logical form of HOST:PORT/MUL. * Explain when and where to list localhost. 2003-05-26 15:02 Martin Pool * src/hosts.c, NEWS: TCP hosts can now be specified in the more logical form of HOST:PORT/MUL. 2003-05-26 14:58 Martin Pool * src/h_hosts.c: Log to stderr. 2003-05-26 14:54 Martin Pool * src/hosts.c: dcc_parse_multiplier: Remove unnecessary string copy. 2003-05-26 14:51 Martin Pool * src/hosts.c: Doc. 2003-05-26 14:48 Martin Pool * src/dsignal.c: dcc_parent_terminate: Rename to dcc_daemon_terminate because it's now done in both parent and children. 2003-05-26 14:47 Martin Pool * test/testdistcc.py: Run tests in prefork mode. 2003-05-26 14:46 Martin Pool * src/: daemon.h, dparent.c, dsignal.c, prefork.c, serve.c: Don't change the signal handler when starting a child, because this is racy and not straightforward. Instead, keep track of the pid of the master daemon, and in the signal handler check if that's who we are when running cleanup. 2003-05-26 14:34 Martin Pool * NEWS: Call server-side output object files .o, not .out. Patch from rishikesh shetty. 2003-05-26 14:28 Martin Pool * src/prefork.c: Doc. 2003-05-26 14:24 Martin Pool * test/testdistcc.py: Assume localhost has one CPU when checking host parsing. 2003-05-26 14:20 Martin Pool * test/testdistcc.py: Wait status for a terminated daemon is now TERM, not 0. * Use --no-prefork for the moment to check nothing was broken. 2003-05-26 14:13 Martin Pool * src/dparent.c: Don't catch signals until we've established our own process group, because we don't want to accidentally kill the caller's process group. * More trace messages. 2003-05-26 14:12 Martin Pool * src/: exec.h, exec.c: dcc_setpgid: Return an error if we fail to create a process group, because we rely on being separated for proper shutdown. 2003-05-26 13:55 Martin Pool * src/exec.c: dcc_setpgid: Return an error if we fail to create a process group, because we rely on being separated for proper shutdown. 2003-05-26 13:34 Martin Pool * src/tempfile.c: Fix warning 2003-05-26 13:14 Martin Pool * src/tempfile.c: tmpfile list must be volatile. 2003-05-26 13:10 Martin Pool * src/dparent.c: dcc_standalone_server: Even in --no-detach mode, create a new process group. 2003-05-26 13:09 Martin Pool * src/prefork.c: dcc_preforking_parent: We don't need to create a new process group because it has already been done at a higher level. 2003-05-26 13:08 Martin Pool * src/exec.c: Doc. 2003-05-26 12:15 Martin Pool * Makefile.in: h_hosts now needs ncpus.c 2003-05-26 12:08 Martin Pool * NEWS: Note prefork support. 2003-05-26 12:06 Martin Pool * src/: srvrpc.c, serve.c: Split server-specific RPC code into its own file. 2003-05-26 12:05 Martin Pool * Makefile.in, src/rpc.h: src/srvrpc.c: New file. 2003-05-26 12:00 Martin Pool * src/daemon.c: Doc. 2003-05-26 11:53 Martin Pool * NEWS: Kill process group on termination signal. 2003-05-26 11:50 Martin Pool * src/: prefork.c, dparent.c: "up to n children" is only a debug message. 2003-05-26 11:49 Martin Pool * src/dparent.c: Split out code for logging terminated children. * Show signal names if appropriate when a child exits. * If a child is terminated, this is just an info log not an error. 2003-05-26 11:49 Martin Pool * src/daemon.c: Doc 2003-05-26 11:44 Martin Pool * src/dsignal.c: dcc_child_terminate: No log message when the child is terminated, the parent can do it. 2003-05-26 11:40 Martin Pool * src/dsignal.c: Termination signal handlers re-raise the signal and therefore should not _exit, because the signal is blocked until we try to return. 2003-05-26 08:38 Martin Pool * src/: daemon.h, dparent.c, dsignal.c, prefork.c: Use a separate signal handler for daemon children, that cleans up temporary files but doesn't kill the group. 2003-05-25 21:10 Martin Pool * src/: daemon.h, dparent.c, dsignal.c, prefork.c, serve.c, util.c: Rework some daemon signal handling designs to better suit a preforking server. * Daemon now runs in a single process group in all modes. * Use signal() rather than sigaction() for simplicity. * Killing the daemon kills all running children. This is more consistent with other daemons like Apache. Any clients ought to fall back to local compilation, as they will have to do anyhow. Daemon is killed by reraising the signal, rather than exiting. * Print a message when terminated by a signal that fits better with the strsignal() output. * When terminated, explicitly run cleanups rather than relying on exit(). * Accepted children are not run in a separate group, because this will not work for preforked jobs. 2003-05-25 17:39 Martin Pool * src/prefork.c: Doc * dcc_preforking_parent: Should wait until a child exits before bothering about starting a new one. 2003-05-25 17:32 Martin Pool * src/prefork.c: Doc 2003-05-25 17:29 Martin Pool * src/: daemon.h, dparent.c, prefork.c: dcc_reap_kids: Flags ought to allow distinguishing between needing to reap at least one child, and just checking for any of them. We don't want to wait until all the children exited. This fixes the problem of the preforked parent waiting until all the children have exited before starting any more. 2003-05-25 16:34 Martin Pool * linuxdoc/distcc.sgml: Note that DISTCC_LOG doesn't change the server. * Add section on how to shut down distccd. 2003-05-25 16:23 Martin Pool * linuxdoc/distcc.sgml: Bump version to 2.5. * Add descriptions of some new error codes. 2003-05-23 19:19 Martin Pool * src/dparent.c: Doc 2003-05-23 19:15 Martin Pool * src/daemon.c, NEWS: Make sure that the right syslog facility is opened. 2003-05-23 19:04 Martin Pool * src/: .cvsignore, daemon.c, daemon.h, distcc.h, dparent.c, dsignal.c, prefork.c: Split prefork stuff into prefork.c. * Split daemon stuff into daemon.h. 2003-05-23 19:03 Martin Pool * Makefile.in: No more recursive Make. 2003-05-23 18:33 Martin Pool * src/: distcc.h, dopt.c, dopt.h, dparent.c: New option --no-prefork * Add simple implementation of preforking: just create max_jobs children and let them all accept connections. They time out after a few requests. 2003-05-23 15:50 Martin Pool * NEWS, src/dopt.c, src/dopt.h, src/dparent.c: Add new --jobs, -j option to server to set limit on incoming jobs. 2003-05-23 15:48 Martin Pool * configure.ac: Bump version to 2.5cvs 2003-05-23 15:48 Martin Pool * README.libiberty: Remove libiberty stuff 2003-05-23 14:54 Martin Pool * src/dparent.c: Remove quote. 2003-05-23 14:51 Martin Pool * src/dparent.c: dcc_reap_kids: Add option to block until a child exits. * dcc_forking_parent: Block waiting for a child to complete before accepting any new connections when we've exceeded the maximum number of connections. 2003-05-23 14:30 Martin Pool * src/dparent.c: Rename /_loop/_parent/ 2003-05-23 14:29 Martin Pool * src/dparent.c: max_kids: New variable to impose a limit on concurrent servers. 2003-05-23 14:21 Martin Pool * src/dparent.c: Fix prototype 2003-05-23 14:20 Martin Pool * src/dparent.c: Refactor daemon parent loop into separate versions for nofork and forking mode, so that we don't need checks for mode at more than one place. 2003-05-23 14:05 Martin Pool * src/hosts.c: Doc 2003-05-23 14:04 Martin Pool * src/hosts.c: Set default local task limit to twice the number of CPUs. 2003-05-23 13:38 Martin Pool * TODO: Remove done items. 2003-05-23 13:02 Martin Pool * NEWS, configure.ac: Prepare for 2.4.2 release 2003-05-23 12:58 Martin Pool * src/serve.c: Doc. 2003-05-23 12:47 Martin Pool * src/netutil.c, NEWS: Fix string allocation bug in dcc_sockaddr_to_ip that could cause a server crash. 2003-05-23 12:17 Martin Pool * NEWS, src/distcc.h, src/hostfile.c, src/hosts.c: Better error messages if DISTCC_HOSTS or host files are empty. Patch from Wayne Davison. 2003-05-22 19:06 Martin Pool * doc/results.txt: [no log message] 2003-05-22 19:05 Martin Pool * TODO: More notes on feeding from a FIFO. 2003-05-22 17:39 Martin Pool * src/sendfile.c: Doc. 2003-05-22 16:40 Martin Pool * Makefile.in: libiberty is no longer used by distcc. 2003-05-22 16:24 Martin Pool * src/bulk.c, NEWS: Open output files in the same way that GNU as does, by only trying to remove them if they're >0 bytes, and ignoring failure to remove. This fixes compilation directed to /dev/null, which is used by some configure scripts. Reported by Hal Duston. 2003-05-22 16:12 Martin Pool * cases/fooey.c: Another developer scratch test. 2003-05-22 16:09 Martin Pool * test/testdistcc.py: Fix /dev/null test. 2003-05-22 15:51 Martin Pool * test/testdistcc.py: Add test case for "-o /dev/null", reported by Hal Duston. Currently fails. 2003-05-22 15:48 Martin Pool * configure.ac: Update to 2.5cvs 2003-05-22 15:24 Martin Pool * configure.ac: Update to 2.4.1 2003-05-22 15:21 Martin Pool * NEWS: Patch from Frerich Raabe: * Add strndup on platforms that don't have it. 2003-05-22 11:25 Martin Pool * src/hosts.c, NEWS: Patch from Frerich Raabe: * Add strndup on platforms that don't have it. 2003-05-22 11:13 Martin Pool * configure.ac: Bump version to 2.4.1cvs * Check for function and declaration of strndup. 2003-05-22 10:03 Martin Pool * man/: distcc.1, distccd.1: Add email addresses. 2003-05-21 16:57 Martin Pool * TODO: Note on waking up bored clients. 2003-05-21 16:47 Martin Pool * configure.ac, NEWS: Get ready for 2.4 release 2003-05-21 16:45 Martin Pool * test/testdistcc.py: NoHosts_Case needs to reset DISTCC_FALLBACK=1 to test the desired behaviour. 2003-05-21 16:41 Martin Pool * src/: clirpc.c, distcc.c, exec.c, exec.h, serve.c: dcc_critique_status: Add butt-ugly verbose parameter, so that diagnostics on command completion are only given high status in cases where the user is likely to want to see them. 2003-05-21 16:39 Martin Pool * doc/results.txt: Notes on backoff. 2003-05-21 16:30 Martin Pool * src/timefile.c: dcc_remove_timefile: Better messages. 2003-05-21 16:26 Martin Pool * src/h_hosts.c: Renamed to dcc_get_hostlist 2003-05-21 16:25 Martin Pool * NEWS: [no log message] 2003-05-21 16:24 Martin Pool * src/clinet.c: Doc. 2003-05-21 16:16 Martin Pool * src/distcc.c: dcc_build_somewhere: Allow for the fallback code to be invoked because of failure to choose a host, e.g. because they're all down or none were defined. 2003-05-21 16:10 Martin Pool * src/where.c: dcc_pick_host_from_list: Return EXIT_NO_HOSTS on failure, not 0. This makes sure that all failures are caught in common code and that DISTCC_FALLBACK is always applied. 2003-05-21 16:09 Martin Pool * src/exitcode.h: New code EXIT_NO_HOSTS 2003-05-21 16:07 Martin Pool * src/: where.h, where.c, distcc.c: dcc_pick_host_from_env: rename to dcc_pick_host_from_list, since hosts can now come from files too. 2003-05-21 16:04 Martin Pool * src/where.c: If removing disliked hosts leaves us with nothing, then use localhost instead. 2003-05-21 15:55 Martin Pool * src/backoff.c: Doc 2003-05-21 15:55 Martin Pool * doc/results.txt: [no log message] 2003-05-21 15:54 Martin Pool * src/: backoff.c, backoff.h, hosts.c, where.c: Backoff from disliked hosts for 60 seconds. 2003-05-21 15:53 Martin Pool * NEWS: Note sleep changes and backoff. 2003-05-21 15:38 Martin Pool * src/: hosts.h, hosts.c: dcc_free_hostdef: New function. 2003-05-21 15:25 Martin Pool * src/: hosts.h, hosts.c, where.c: Rename dcc_preferred_hosts to dcc_get_hostlist. 2003-05-21 15:23 Martin Pool * src/where.c: Sleep for just 2s if a host is not free. 2003-05-21 14:09 Martin Pool * src/where.c, NEWS: dcc_lock_pause: Replace simple 0.1s sleep with a truncated exponential backoff starting at 1s and going up to 8s. 0.1s is very short compared to the period a compile typically takes to complete, and if we hit this code at all then we're probably overloaded. 2003-05-21 14:01 Martin Pool * src/lock.c: Doc. 2003-05-21 14:00 Martin Pool * src/timefile.c: dcc_mark_timefile: Fix error check 2003-05-21 13:57 Martin Pool * src/: backoff.c, distcc.c: backoff.c, backoff.h: New files. 2003-05-21 13:56 Martin Pool * src/distcc.c: dcc_build_somewhere: Remember when a server failed or not. 2003-05-21 13:55 Martin Pool * src/: backoff.h, backoff.c: dcc_enjoyed_host, dcc_disliked_host: New function that remember when a server failed. 2003-05-21 13:51 Martin Pool * Makefile.in: backoff.c, backoff.h: New files. 2003-05-21 13:44 Martin Pool * src/timefile.c: dcc_remove_timefile, dcc_check_timefile: Cope with timestamp files that don't exist. 2003-05-21 13:35 Martin Pool * src/timefile.c: dcc_mark_timefile, dcc_remove_timefile: add trace messages. 2003-05-21 13:34 Martin Pool * src/: timefile.c, timefile.h: dcc_remove_timefile, dcc_check_timefile: New functions. 2003-05-21 13:30 Martin Pool * src/timefile.h, Makefile.in, src/lock.h: timefile.h: New header for timefile.c 2003-05-21 13:22 Martin Pool * doc/release-names.txt: [no log message] 2003-05-21 13:21 Martin Pool * Makefile.in, src/lock.c, src/lock.h, src/timefile.c: timefile.c: New file. * Export some functions from lock.c needed to do timestamps. * dcc_mark_timefile: Very simple implementation of time markers. 2003-05-21 13:19 Martin Pool * src/climasq.c: Doc 2003-05-21 13:14 Martin Pool * test/testdistcc.py: Doc. 2003-05-21 11:49 Martin Pool * doc/release-names.txt: [no log message] 2003-05-20 22:35 Martin Pool * doc/release-names.txt: [no log message] 2003-05-20 12:00 Martin Pool * survey.txt: Add request to send misconfigurations to the list rather than to the survey. 2003-05-19 18:21 Martin Pool * TODO: Describe use of SSH. * Notes about localhost scheduling. 2003-05-19 18:17 Martin Pool * linuxdoc/distcc.sgml: Bump version. 2003-05-19 18:16 Martin Pool * linuxdoc/distcc.sgml, NEWS: Describe use of SSH. 2003-05-19 18:02 Martin Pool * doc/results.txt: Results from SSH. 2003-05-19 17:50 Martin Pool * src/lock.c: dcc_lock_host: Use hostdef_string, not hostname. 2003-05-19 17:47 Martin Pool * TODO, src/hosts.c: Move notes about multi-A-records to TODO, since it probably won't happen. 2003-05-19 17:43 Martin Pool * NEWS: dcc_critique_status now takes a hostdef, not a hostname, so that it can give better error messages. Update all callers. 2003-05-19 17:41 Martin Pool * src/exec.c: dcc_critique_status: Don't print function name in errors. 2003-05-19 17:39 Martin Pool * src/: clirpc.c, distcc.c, exec.c, exec.h, hosts.c, serve.c: dcc_critique_status now takes a hostdef, not a hostname, so that it can give better error messages. Update all callers. 2003-05-19 17:29 Martin Pool * src/: distcc.c, exec.c, exec.h, lock.c: Move towards passing around hostdefs, rather than hostnames, because they provide better explanations now that we have multiple protocols and different ports. At the moment done just for dcc_note_execution. 2003-05-19 17:20 Martin Pool * src/hosts.h: Add verbatim name to hostdef struct. 2003-05-19 17:18 Martin Pool * NEWS: If remote compilation fails, give an error rather than just a notice. People might want to know. 2003-05-19 17:16 Martin Pool * cases/bad.c: Test case for errors. 2003-05-19 17:15 Martin Pool * src/exec.c: If remote compilation fails, give an error rather than just a notice. People might want to know. 2003-05-19 17:10 Martin Pool * src/arg.c: Doc. 2003-05-19 16:58 Martin Pool * src/: filename.c: Doc. 2003-05-19 16:43 Martin Pool * NEWS, src/clinet.c, src/netutil.c, src/srvnet.c: Don't use the RFC2553 getaddrinfo/getnameinfo API by default, because it seems to be slower on OS X and possibly problematic on other systems. It can be enabled with --enable-rfc2553 if you want to use IPv6, multi-homed servers, or want to test the new API. 2003-05-19 16:08 Martin Pool * doc/results.txt: Notes on getaddrinfo vs gethostinfo. 2003-05-19 16:08 Martin Pool * configure.ac: Add --enable-rfc2553 configuration option. 2003-05-19 16:08 Martin Pool * TODO: Notes on name handling and statistics. 2003-05-19 16:07 Martin Pool * NEWS: Patch from Paul Green to start supporting VOS: * Use autoconf EXEEXT in Makefile. Remove sbin_programs. * Add VOS implementation of dcc_ncpus. * Once socklen_t, in_addr_t and in_port_t have been typedef'd, set the feature macros for them. * src/util.c needs netdb.h 2003-05-19 13:08 Martin Pool * src/hosts.c, TODO: Merge comment from Alexandre about keeping the HOSTS syntax such that it can be handled from the shell. 2003-05-19 12:25 Martin Pool * Makefile.in, src/ncpus.c, src/types.h, src/util.c: Patch from Paul Green to start supporting VOS: * Use autoconf EXEEXT in Makefile. Remove sbin_programs. * Add VOS implementation of dcc_ncpus. * Once socklen_t, in_addr_t and in_port_t have been typedef'd, set the feature macros for them. * src/util.c needs netdb.h 2003-05-16 17:52 Martin Pool * src/where.c, NEWS: If an IO error occurs while trying to get a lock, bail out rather than getting stuck. 2003-05-16 17:47 Martin Pool * src/filename.c: Doc. 2003-05-16 17:43 Martin Pool * src/cpp.c: dcc_cpp_maybe: Doc, add trace. 2003-05-16 17:40 Martin Pool * src/cpp.c: dcc_cpp_maybe: Pull out all the preprocessor-extension logic and just call dcc_preproc_exten, which already knows all about C++ and ObjC and ObjC++. 2003-05-16 17:37 Martin Pool * src/cpp.c: Logic cleanup on Dara's patch. * For C++ source files, call the preprocessor output .ii. 2003-05-16 17:24 Martin Pool * Makefile.in: Fix upload-dist. 2003-05-16 17:23 Martin Pool * src/cpp.c, src/filename.c, NEWS: Merge cleaned-up patch from Dara Hazeghi to recognize ObjC extensions. Still not clear. 2003-05-16 17:18 Martin Pool * doc/results.txt: Update from experiments today on kernel. 2003-05-16 17:16 Martin Pool * NEWS: Bump to 2.4cvs. * Merge patch to recognize Objective C files, by Dara Hazeghi. 2003-05-16 17:14 Martin Pool * configure.ac: Bump to 2.4cvs. 2003-05-16 17:10 Martin Pool * cases/hello-objc.m: Add compile-command. 2003-05-16 17:09 Martin Pool * cases/hello-objc.m: Example case for Objective C, from Dara Hazeghi. 2003-05-16 15:15 Martin Pool * src/distcc.c: Fix typo in usage message. 2003-05-16 15:07 Martin Pool * doc/release-names.txt: [no log message] 2003-05-16 14:46 Martin Pool * linuxdoc/distcc.sgml: Prepare for 2.3 release. 2003-05-16 14:09 Martin Pool * NEWS: Prepare for 2.3 release. 2003-05-16 13:43 Martin Pool * configure.ac: Prepare for 2.3 release. 2003-05-15 15:14 Martin Pool * src/util.c: Update trace message. 2003-05-14 10:47 Martin Pool * src/util.c: dcc_trim_path: More trace information. 2003-05-13 15:47 Martin Pool * src/srvnet.c: HAVE_GETADDRINFO version of dcc_socket_listen: check that the port is in range, because getaddrinfo doesn't trap it. 2003-05-13 15:37 Martin Pool * src/: daemon.c, distcc.c, util.c, util.h: Patch from Wayne Davison: * When trimming our path, look for the name we were invoked under rather than "cc". 2003-05-13 15:26 Martin Pool * NEWS: Doc updates. 2003-05-13 11:46 Martin Pool * TODO: [no log message] 2003-05-11 12:31 Martin Pool * src/daemon.c, NEWS: dcc_setup_startup_log: Send startup errors to stderr, unless that is a socket. Perhaps a better heuristic for working out when we can stand to have e.g. bad option warnings go there. 2003-05-11 12:21 Martin Pool * src/daemon.c: dcc_set_lifetime: Remove "set alarm for" message, which tends to leak into syslog when testing. 2003-05-11 12:18 Martin Pool * NEWS: Update status of IPv6. 2003-05-11 12:17 Martin Pool * src/srvnet.c: Coallesce log entries. * Doc. 2003-05-11 12:04 Martin Pool * TODO: [no log message] 2003-05-09 14:05 Martin Pool * linuxdoc/distcc.sgml: Remove chapter on "internals", because this is covered in the protocol documentation file, etc. 2003-05-08 18:02 Martin Pool * linuxdoc/distcc.sgml: Document DISTCC_SSH, host list files, and execution over SSH. 2003-05-08 17:17 Martin Pool * NEWS: Updates to manual. 2003-05-08 17:13 Martin Pool * linuxdoc/distcc.sgml: Better description of how --help and --version work with the client. * Document DISTCC_FALLBACK. 2003-05-08 17:05 Martin Pool * linuxdoc/distcc.sgml: Rename "Invoking" section to "Setting up", because this is what it's really about now. * Add SGML markup. * Rephrase some sections about masquerading. 2003-05-08 17:01 Martin Pool * linuxdoc/distcc.sgml: Update section about security to describe ssh and new options. 2003-05-08 16:52 Martin Pool * src/srvnet.c: Restore access control checking for IPv4 connections. 2003-05-08 16:51 Martin Pool * test/testdistcc.py: AccessDenied_Case depends on falling back to local compilation. 2003-05-08 16:44 Martin Pool * src/h_hosts.c: dcc_parse_hosts_env renamed to dcc_preferred_hosts. 2003-05-08 16:43 Martin Pool * src/clinet.c: non-GETADDRINFO version of dcc_connect_by_name: Pass the right socklen. 2003-05-08 16:42 Martin Pool * test/testdistcc.py: Set DISTCC_FALLBACK=0 for most compilations so that we can be more sure that distribution failures will be visible. 2003-05-08 15:47 Martin Pool * src/clinet.c: Remove unused vars. 2003-05-07 17:27 Martin Pool * src/srvnet.c: dcc_socket_listen, dcc_prefer_ipv4: Try to listen on an IPv4 address if there is an acceptable one, because that's the least disruptive change from the previous code and it avoids ugly "::127.0.0.1" strings. 2003-05-07 17:02 Martin Pool * src/srvnet.c: dcc_check_client: Update to be AF-indepedent. Does not do checks yet. 2003-05-07 16:58 Martin Pool * src/: netutil.c, netutil.h: dcc_sockaddr_to_hostname renamed to dcc_sockaddr_to_ip, which is more accurate. Add a non-getnameinfo() implementation. 2003-05-07 16:48 Martin Pool * Makefile.in, src/netutil.c, src/netutil.h: netutil.c, netutil.h: New files. * dcc_sockaddr_to_hostname: New function that hides inet_ntoa vs getnameinfo. 2003-05-07 16:38 Martin Pool * configure.ac: Check for sockaddr_storage.ss_family, since ss_len doesn't seem to exist in glibc. If we have it, define HAVE_SOCKADDR_STORAGE. 2003-05-07 16:24 Martin Pool * configure.ac: Check for inet_ntop and inet_ntoa 2003-05-07 16:18 Martin Pool * src/srvnet.c, NEWS: dcc_socket_listen: Dual implementations for getaddrinfo and old API. The new implementation specifies AI_PASSIVE if no --listen address is given, so it should be able to accept connections on all ports or protocols. 2003-05-07 16:06 Martin Pool * src/srvnet.c: dcc_listen_by_addr, dcc_socket_listen: Factor out the code that creates and listens on a socket from the code that works out the address to use, so that we can use getaddrinfo when available. Also, remove assumptions about socket addresses always being IPv4. 2003-05-07 16:04 Martin Pool * src/clinet.c: Doc. 2003-05-07 15:57 Martin Pool * doc/dietlibc-distcc.trace: strace using dietlibc, just for interest. 2003-05-07 15:56 Martin Pool * NEWS, src/clinet.c, src/clinet.h, src/distcc.c: Use getaddrinfo() if it's available for opening connections, to better handle multihomed servers and start supporting IPv6. 2003-05-07 15:26 Martin Pool * src/clinet.c: dcc_open_socket_out: Add a second definition of this function to be used on machines with getaddrinfo. 2003-05-07 15:25 Martin Pool * configure.ac: Check for getaddrinfo, getnameinfo, and struct sockaddr_storage. 2003-05-07 15:20 Martin Pool * src/clinet.c: dcc_open_socket_out: Check client name before creating a socket. (Not a big deal for now, but will be needed for AF-independence.) 2003-05-07 12:23 Martin Pool * NEWS: hostlist.c fix * snprintf.c fixes. 2003-05-07 12:21 Martin Pool * configure.ac: Add check from Samba for va_copy, which is needed for building our snprintf. 2003-05-07 12:21 Martin Pool * cases/.cvsignore: Ignore built programs. 2003-05-07 12:20 Martin Pool * TODO: [no log message] 2003-05-07 12:07 Martin Pool * src/snprintf.c: Update ifdefs to make sure that this file compiles to an (almost) empty object file on systems that already have all the functions we need. 2003-05-07 11:53 Martin Pool * src/hosts.c: dcc_parse_hosts_env: Remove obsolete function. 2003-05-07 11:52 Martin Pool * src/hosts.c: Trace messages when reading in host lists. 2003-05-07 11:50 Martin Pool * src/hostfile.c: Remove unnecessary recursion protection. * Trace message when reading a file. 2003-05-07 11:49 Martin Pool * src/loadfile.c: Fix silly pointer error when loading a host file. 2003-05-07 11:15 Martin Pool * src/snprintf.h: Fix all HAVE_DECL_ uses: these are defined to zero rather than left undefined by autoconf if the decl is missing. 2003-05-07 11:14 Martin Pool * src/snprintf.c: Merge from samba HEAD: * Fix floating point handling. * Make snprintf test work better. * If the system's vsnprintf is not C99 compliant, then we need to override both vsnprintf and snprintf to make sure the correct code is always called. Also: * Make sure LDOUBLE, VA_COPY, etc are defined even if the system already has some snprintf routines. * Always include snprintf.h, so that we get declarations for the functions in this file. 2003-05-07 10:27 Martin Pool * README.packaging: Note about using ./configure options to set directories, and DESTDIR. 2003-05-07 10:23 Martin Pool * linuxdoc/distcc.sgml: "for 2.2" 2003-05-07 10:23 Martin Pool * NEWS, linuxdoc/distcc.sgml: Document --listen, plus other cleanups. Patch from Frerich Raabe. 2003-05-07 10:13 Martin Pool * cases/lzotest.c: Hacky test to examine efficiency of minilzo. 2003-05-06 18:21 Martin Pool * TODO: Merge some stuff. 2003-05-06 18:18 Martin Pool * doc/scheduling.txt: Merge into TODO 2003-05-06 18:16 Martin Pool * doc/new-scheduler.txt: Merged into doc/results.txt 2003-05-06 18:16 Martin Pool * doc/results.txt: Move "new-scheduler.txt" results (from February) into the results.txt file. 2003-05-06 17:36 Martin Pool * doc/protocol-3.txt: Only a draft 2003-05-06 17:34 Martin Pool * doc/protocol-3.txt: Rephrase. * Don't compress 0-length data. * Insert COMP packets. * Questions about how to describe temporaries. 2003-05-06 17:11 Martin Pool * doc/protocol-3.txt: Describe input and output files. * Start updating request and response descriptions. 2003-05-06 16:54 Martin Pool * doc/protocol-3.txt: Describe handshaking on reused connections. * Describe compression. 2003-05-06 16:02 Martin Pool * doc/protocol-3.txt: More updates towards version 3 protocol. 2003-05-06 14:55 Martin Pool * TODO: [no log message] 2003-05-06 13:12 Martin Pool * src/dparent.c, src/ncpus.c, NEWS: Two Mac OS X fixes from Benjamin Reed: Use the BSD method to discover the number of CPUs, and include types.h where it is needed. 2003-05-05 22:42 Martin Pool * src/trace.h: Doc 2003-05-05 22:31 Martin Pool * src/HACKING: Just about everything in this file has been implemented! The ideas which are not done yet are now in TODO. We're almost a year old now. 2003-05-05 22:29 Martin Pool * src/rpc.c: Fix printf formatting error. 2003-05-05 18:46 Martin Pool * src/trace.h: Doc 2003-05-05 18:40 Martin Pool * src/distcc.h: Doc 2003-05-05 18:07 Martin Pool * TODO: Remove page marks 2003-05-05 18:01 Martin Pool * TODO: Notes on feeding from fifo. 2003-05-05 17:56 Martin Pool * TODO: Notes on streaming output 2003-05-05 17:49 Martin Pool * doc/protocol-3.txt: Start writing notes about a version 3 protocol. 2003-05-05 17:44 Martin Pool * NEWS: Better description of network error detection. 2003-05-05 17:36 Martin Pool * src/rpc.c: dcc_explain_mismatch: After a protocol problem, show up to 200 bytes of printable context. 2003-05-05 17:26 Martin Pool * NEWS, src/rpc.c: dcc_explain_mismatch: New function, to give more information in the case of a protocol mismatch. Most importantly, if an unexpected response is seen then we give a bit more text from the network in the hope that it will help diagnose the problem. 2003-05-05 16:58 Martin Pool * src/clirpc.c: Doc. 2003-05-05 16:54 Martin Pool * src/: clirpc.c, rpc.c: dcc_r_result_header, dcc_r_cc_status: These are client-specific, so move them to clirpc.c. 2003-05-05 16:53 Martin Pool * configure.ac: Bump version. 2003-05-05 16:28 Martin Pool * NEWS, configure.ac: Prepare for 2.2 release. 2003-05-05 16:27 Martin Pool * src/hosts.h: Remove CVS tag. 2003-05-05 16:23 Martin Pool * TODO: [no log message] 2003-05-05 16:21 Martin Pool * TODO: Add a basic --listen option, based on a patch by Neil Mansilla. 2003-05-05 16:17 Martin Pool * src/dopt.c, src/dopt.h, src/dparent.c, src/srvnet.c, src/srvnet.h, NEWS: Add a basic --listen option, based on a patch by Neil Mansilla. 2003-05-05 16:05 Martin Pool * patches/andresen-gcc-wrapper-r2.tbz2: Remove Gentoo-only patch. 2003-05-05 15:54 Martin Pool * TODO: Update TODO list. 2003-05-05 15:30 Martin Pool * src/distcc.c: (dcc_show_usage): Describe where the host list comes from -- this is important because it is a configurable option. Add documentation for SSH syntax. 2003-05-05 15:16 Martin Pool * test/testdistcc.py, NEWS: Test host file support. 2003-05-05 15:15 Martin Pool * NEWS: Note about support for host files. 2003-05-05 15:14 Martin Pool * Makefile.in: h_hosts: Now needs hostfile.o and io.o 2003-05-05 15:08 Martin Pool * src/: hosts.c, hosts.h, where.c: If DISTCC_HOSTS is not set, look in ~/.distcc/hosts, or otherwise /etc/distcc/hosts. 2003-05-05 15:03 Martin Pool * src/hostfile.c: Doc 2003-05-05 15:01 Martin Pool * cases/empty.s: Empty assembler file for testing. 2003-05-05 15:01 Martin Pool * Makefile.in: SYSCONFDIR must be quoted for C. 2003-05-05 14:37 Martin Pool * src/: hosts.c, hosts.h, util.c, util.h: (dcc_dup_part): Move to util.c. 2003-05-05 14:35 Martin Pool * TODO: Build .debs or .rpms? 2003-05-05 14:24 Martin Pool * TODO: Build .debs or .rpms? 2003-05-05 14:19 Martin Pool * src/hostfile.c: (dcc_parse_hosts_file): New function. 2003-05-05 12:59 Martin Pool * Makefile.in, src/hostfile.c: New file: src/hostfile.c * where.o and hosts.o don't need to be linked into the server, only the client. 2003-05-05 12:56 Martin Pool * Makefile.in: (SRC): Sort. 2003-05-05 12:53 Martin Pool * src/loadfile.c: dcc_load_file: Move everything back into a single function. Actually allocate a buffer and read into it. 2003-05-04 23:17 Martin Pool * src/loadfile.c: dcc_load_file: Split into a second function to ease error checking. * dcc_load_fd: New function. Allocate a memory buffer for the file after discovering its size. 2003-05-04 23:13 Martin Pool * src/loadfile.c: dcc_load_file: Check size of file and complain about those that are too large. 2003-05-04 23:06 Martin Pool * Makefile.in, src/exitcode.h, src/io.h, src/loadfile.c: Start adding code to load a whole file in to memory, so that we can read hosts from a file. 2003-05-04 23:00 Martin Pool * patches/hosts-from-file-raabe.diff: Old patch from Frerich to read hosts from a file. 2003-05-04 22:48 Martin Pool * src/: arg.c, bulk.c, clinet.c, dopt.c, exec.c, filename.c, h_argvtostr.c, h_exten.c, h_hosts.c, h_issource.c, h_scanargs.c, h_strip.c, help.c, hosts.c, lock.c, rpc.c, sendfile.c, serve.c, srvnet.c, tempfile.c, trace.c, util.c, where.c, zip.c: Remove all dependencies on assert.h. Most of them were not used, and the rest are better written using our standard error handling library. 2003-05-04 22:43 Martin Pool * configure.ac: More spacing in output. 2003-05-04 22:42 Martin Pool * Makefile.in: Start adding support for a host list file: define SYSCONFDIR, and show it when displaying paths. 2003-05-04 22:31 Martin Pool * configure.ac: Bump version to 2.2cvs 2003-05-04 22:29 Martin Pool * TODO: Notes about compression and reading hosts from a file. 2003-05-04 21:38 Martin Pool * doc/protocol-1.txt: Suggestions from Brad Hards: * Correction about SOUT. * Explain a bit more about waitstatus. 2003-05-04 17:24 Martin Pool * NEWS, linuxdoc/distcc.sgml: Add documentation for --allow and --user, by Frerich Raabe. 2003-05-04 12:01 Martin Pool * TODO: Update todo list. 2003-05-04 11:21 Martin Pool * NEWS, news.el: Roll over NEWS for new release. * Move news.el into mode variables at the bottom of the NEWS file. 2003-05-03 23:57 Martin Pool * NEWS, configure.ac: Prepare for 2.1 release. 2003-05-03 17:56 Martin Pool * doc/protocol-1.txt: Ask for questions. * Describe all the packets in the request and the response. 2003-05-03 13:39 Martin Pool * TODO: Note about preprocessing remotely. 2003-05-03 12:05 Martin Pool * TODO: Note about never running locally. 2003-04-30 12:17 Martin Pool * TODO: Link to API for async name lookups. 2003-04-27 00:18 Martin Pool * doc/protocol-1.txt: Add some documentation of the protocol in the current version. Pretty good but does not cover the complete sequence yet. 2003-04-19 23:08 Martin Pool * NEWS: Test harnesses may need snprintf.o linked in as well. Reported by Joe Meslovich as broken on Solaris. 2003-04-19 21:55 Martin Pool * Makefile.in: Test harnesses may need snprintf.o linked in as well. Reported by Joe Meslovich as broken on Solaris. 2003-04-17 12:26 Martin Pool * doc/release-names.txt: [no log message] 2003-04-14 13:05 Martin Pool * TODO: [no log message] 2003-04-14 13:02 Martin Pool * TODO: [no log message] 2003-04-13 19:00 Martin Pool * TODO: Notes from UML. 2003-04-13 17:35 Martin Pool * TODO: Note about setting listen address. 2003-04-13 17:18 Martin Pool * TODO: Notes about DISTCC_HOSTS syntax. 2003-04-10 16:42 Martin Pool * src/help.c: Add quote. 2003-04-08 16:23 Martin Pool * TODO: [no log message] 2003-04-08 13:58 Martin Pool * patches/n_cpus.txt: n_cpus.txt Remove merged code 2003-04-04 17:39 Martin Pool * patches/: distcc-path.patch, distccd-path.patch: distcc-path.patch distccd-path.patch Delete merged patches 2003-04-04 17:38 Martin Pool * TODO: [no log message] 2003-04-04 17:32 Martin Pool * TODO: [no log message] 2003-04-04 17:28 Martin Pool * src/io.c: tcp_cork_sock: Don't complain about ENOTSUPP when uncorking. 2003-04-04 17:24 Martin Pool * src/: rpc.c, io.h: dcc_read_int: Remove dead function. 2003-04-04 17:20 Martin Pool * src/: io.c: Doc. 2003-04-04 17:19 Martin Pool * src/io.c: dcc_pump_readwrite: Increase transfer buffer to 256kB, and move it off the stack. 2003-04-04 17:16 Martin Pool * src/io.c: dcc_pump_readwrite: Doc. 2003-04-04 17:12 Martin Pool * src/io.c, NEWS: dcc_pump_readwrite: Should print an error on unexpected end of input, rather than treating it as success. Why did I do that? 2003-04-04 17:11 Martin Pool * NEWS: Note about nonblocking support. 2003-04-04 16:59 Martin Pool * src/io.c: dcc_pump_readwrite: Only select on file descriptors after we get EAGAIN. * dcc_readx, dcc_writex: Clarify. 2003-04-04 15:54 Martin Pool * linuxdoc/distcc.sgml: Patch from Wayne Davison to document DISTCCD_PATH. 2003-04-04 15:51 Martin Pool * cases/hello.m: Example ObjC program from Dara Hazeghi 2003-04-04 12:19 Martin Pool * TODO: [no log message] 2003-04-04 12:06 Martin Pool * src/util.c: dcc_abspath: Memory overflow ought to be fatal. 2003-04-04 12:00 Martin Pool * NEWS, src/climasq.c, src/daemon.c, src/distcc.c, src/util.c, src/util.h: Merged patch from Wayne Davison: Try to prevent distcc from invoking itself recursively either on the server, or as cc -E on the client. * dcc_trim_path: New code to remove from the PATH any directories that contain "cc" as a link to something that looks like ccache or distcc. * climasq.c: Munge path as appropriate. * daemon.c/main: Use DISTCCD_PATH if set, otherwise trim path. * distcc.c/main: Trim path. 2003-04-04 11:45 Martin Pool * src/daemon.c: Factor out code for checking whether to be inetd. 2003-04-04 10:41 Martin Pool * README.packaging: Note about ssh and path to distccd * Note about --allow * Note about distcc user * Prefer --daemon 2003-04-04 10:33 Martin Pool * TODO: [no log message] 2003-04-04 10:32 Martin Pool * NEWS: Change behaviour of distccd for log messages encountered during startup, before options are parsed. These are now written to stderr only if that is a tty, and otherwise to syslog. This is intended to prevent log messages from distccd getting mixed into the network protocol when it is run from inetd. 2003-04-04 10:21 Martin Pool * test/testdistcc.py: NoDetachDaemon_Case: Specify --daemon to suppress diagnostic message. 2003-04-04 10:19 Martin Pool * src/daemon.c: dcc_setup_startup_log: Split out code for sending startup messages to either stderr or syslog. * distccd/main: refactor code for deciding whether to be inetd or standalone. * dcc_setup_real_log: Rename function for setting final log destination. * Doc. 2003-04-04 10:04 Martin Pool * src/daemon.c: Change behaviour of distccd for log messages encountered during startup, before options are parsed. These are now written to stderr only if that is a tty, and otherwise to syslog. This is intended to prevent log messages from distccd getting mixed into the network protocol when it is run from inetd. 2003-04-04 10:01 Martin Pool * src/: distcc.c, distcc.h, help.c: Show version in log at client startup. 2003-04-04 09:43 Martin Pool * patches/distcc-path.patch: Patch from Wayne to clean path of masquerade links. 2003-04-03 16:21 Martin Pool * NEWS: Note rusage format fix. 2003-04-03 14:39 Martin Pool * TODO: [no log message] 2003-04-03 14:37 Martin Pool * test/comfychair.py: Better log message. 2003-04-03 14:29 Martin Pool * src/distcc.c: Factor out code to find basename from argv. 2003-04-03 10:23 Martin Pool * src/: distcc.h, serve.c: Patch from Wayne Davison: * Removed prototype for dcc_trace_argv() (since it's a define now). * Use "else while(0)" instead of "else {}" so that using the dcc_trace_argv() define doesn't result in two C statements. * Return the "ret" value in dcc_r_request_header() when it's non-0. 2003-04-02 17:26 Martin Pool * src/util.c: dcc_exit: Remove silly printf bug that made all rusage messages inaccurate. 2003-04-02 17:16 Martin Pool * patches/: distcc-hostopt.patch, distccd-path.patch, distccd-version.patch: Patches from Wayne 2003-04-02 17:12 Martin Pool * TODO: More protocol wonderings. 2003-04-02 16:43 Martin Pool * test/testdistcc.py: Update todos. 2003-04-02 16:37 Martin Pool * src/: arg.c, distcc.h: dcc_trace_argv: Convert to a macro so that it shows the right function name in trace messages. 2003-04-02 16:33 Martin Pool * src/: io.c: dcc_readx, dcc_writex: Only select() on the fd after we've got EAGAIN. It might not be necessary in many cases. 2003-04-02 16:30 Martin Pool * src/sendfile.c: dcc_pump_sendfile: Check for select() failure. 2003-04-02 16:27 Martin Pool * src/io.c: Doc 2003-04-02 15:25 Martin Pool * src/: climasq.c, distcc.c, distcc.h: Make dcc_support_masquerade() return standard error codes. 2003-04-02 15:16 Martin Pool * src/: util.c, arg.c: Remove incorrect EXIT_FAULURE 2003-04-02 15:10 Martin Pool * Makefile.in, src/climasq.c, src/distcc.c, src/distcc.h: Split masquerade support into climasq.c 2003-04-02 15:10 Martin Pool * src/safeguard.c: Doc 2003-04-02 15:05 Martin Pool * src/distcc.c: Doc 2003-04-02 14:57 Martin Pool * src/serve.c: Remove one more old "-1" error code. Patch from Wayne Davison. 2003-04-02 14:54 Martin Pool * src/distcc.c: Doc 2003-04-02 14:49 Martin Pool * src/: io.c, rpc.c: Move rpc-specific functions from io.c into rpc.c. 2003-04-02 14:46 Martin Pool * src/dopt.c: Make --no-fork undocumented. 2003-04-02 14:43 Martin Pool * src/sendfile.c: dcc_pump_sendfile: Only select() on the output socket after sendfile has failed with EAGAIN. Otherwise we can miss the case where the remote host has closed the connection on us, as can happen if we connect contrary to --allow. 2003-04-02 14:42 Martin Pool * src/io.c: Trace message when select()ing 2003-04-02 14:41 Martin Pool * src/distcc.h, src/exec.c, src/exec.h, src/safeguard.c, Makefile.in: Split safeguard functions out into their own file. 2003-04-02 12:39 Martin Pool * doc/results.txt: SSH results. 2003-04-02 12:27 Martin Pool * NEWS: Note removal of "return -1". 2003-04-02 11:55 Martin Pool * NEWS: Update SSH news. 2003-04-02 11:00 Martin Pool * TODO: Notes on DISTCC_SSH. 2003-04-02 10:58 Martin Pool * src/ssh.c: Doc 2003-04-02 10:46 Martin Pool * TODO: Note about documenting SSH. 2003-04-01 13:59 Martin Pool * Makefile.in: Split binary downloads onto their own page. 2003-03-31 23:16 Martin Pool * src/bulk.c: Show more precision when printing transfer rates. 2003-03-31 18:48 Martin Pool * src/sendfile.c: Check network is ready to write before attempting sendfile. 2003-03-31 18:47 Martin Pool * src/: io.h, io.c: Export select_for_* 2003-03-31 18:46 Martin Pool * src/io.c: Before reading or writing a socket, select() on it to make sure it's available. Makes things work when our network socket is really a nonblocking connection to ssh. 2003-03-31 18:43 Martin Pool * src/ssh.c: Don't send server log to stderr by default. 2003-03-31 18:36 Martin Pool * src/serve.c: Doc. 2003-03-31 18:36 Martin Pool * src/io.c: dcc_readx: Handle reading from nonblocking socketpairs/pipes. 2003-03-31 18:34 Martin Pool * src/ssh.c: Use nonblocking pipes to ssh. * Add --log-stderr when invoking the remote daemon. 2003-03-31 18:30 Martin Pool * src/bulk.c: Doc. 2003-03-31 18:18 Martin Pool * configure.ac: Bump version 2003-03-31 18:17 Martin Pool * src/distcc.c: For ssh support, we need to allow for separate fds writing to and reading from the network, because our connection to the ssh client may be over pipes, which are one-way connections. Therefore split them out into separate fds in the code. 2003-03-31 18:14 Martin Pool * NEWS: Preliminary support for ssh. 2003-03-31 18:08 Martin Pool * src/ssh.c: Make the dcc end of the socketpairs/pipes talking to ssh be blocking, even if ssh needs blocking ones. Does this work? 2003-03-31 18:02 Martin Pool * src/io.c: dcc_readx: Stub handler for EAGAIN. 2003-03-31 18:00 Martin Pool * src/io.c: Reindent only. 2003-03-31 17:55 Martin Pool * test/testdistcc.py: Fix silly Python bug. 2003-03-31 17:49 Martin Pool * test/testdistcc.py: Giving a bogus port number now gives you EXIT_BAD_ARGUMENTS. 2003-03-31 17:48 Martin Pool * src/: dparent.c, srvnet.c, srvnet.h: open_socket_in: Rename to conventional name 'dcc_socket_listen', and return an exit code. 2003-03-31 17:44 Martin Pool * test/testdistcc.py: Allow default daemon lifetime of 60s, and 300s for BigAssFile. 2003-03-31 17:42 Martin Pool * patches/.cvsignore: Ignore built test programs. 2003-03-31 17:42 Martin Pool * src/: arg.c, bulk.c, clirpc.c, distcc.c, dparent.c, exec.c, filename.c, hosts.c, io.c, sendfile.c, serve.c, srvnet.c, tempfile.c, util.c: Get medieval on "return -1" in old code. Everything ought to return a standard error code now. 2003-03-31 17:30 Martin Pool * src/distcc.c: Doc 2003-03-31 17:22 Martin Pool * src/distcc.c, NEWS: Add DISTCC_FALLBACK environment variable. If set to 0, means that failure to distribute will be considered an overall failure. By default, a networking error means that compilation will be retried locally. 2003-03-31 17:11 Martin Pool * src/io.c, NEWS: Better error handling when corks are not supported on a particular system or socket. 2003-03-31 17:08 Martin Pool * test/testdistcc.py: Revert r1.129: sending logs to stderr doesn't work very well. The daemon can get sigpipe while writing them and similar problems. 2003-03-31 17:02 Martin Pool * test/testdistcc.py, NEWS: Test invalid --allow masks. 2003-03-31 17:00 Martin Pool * src/: distcc.h, ssh.c: dcc_ssh_connect: Fix const-ness of strings. 2003-03-31 17:00 Martin Pool * src/distcc.c: First cut of support for distcc-over-ssh. * dcc_compile_remote: For ssh-mode connections, try to open up using dcc_ssh_connect. 2003-03-31 16:59 Martin Pool * src/arg.c: Undo constness of argv[] arguments, it just doesn't work well in gcc. 2003-03-31 16:55 Martin Pool * src/: distcc.h, ssh.c: Undo constness of argv[] arguments, it just doesn't work well in gcc. 2003-03-31 16:54 Martin Pool * TODO: More notes on new scheduler. 2003-03-31 16:54 Martin Pool * doc/release-names.txt: [no log message] 2003-03-31 16:45 Martin Pool * src/distcc.h: dcc_trace_argv: Fix constness of parameter. * dcc_ssh_connect: Export prototype. 2003-03-31 16:44 Martin Pool * src/arg.c: dcc_trace_argv: Fix constness of parameter. 2003-03-31 16:39 Martin Pool * Makefile.in: Include ssh.o in client build. 2003-03-31 16:38 Martin Pool * src/ssh.c: dcc_ssh_connect: If no username is specified, don't pass the -l option. If no machine is specified, abort. If no path is given, just use "distccd". 2003-03-31 16:33 Martin Pool * src/ssh.c: Remove blocking_io support; it shouldn't be needed if we're only using ssh not rsh. * Update to build cleanly in this tree. * dcc_run_piped_cmd: Make sure pipes are always closed because the program will not necessarily abort if we fail to connect and we don't want to leak file descriptors. * dcc_ssh_connect: Build connection command in argv[] not a string, so that we can avoid invoking a shell. 2003-03-31 16:02 Martin Pool * TODO: Many more notes about single-queue multi-server scheduler. 2003-03-31 15:59 Martin Pool * src/serve.c: Remove dead code. 2003-03-31 15:37 Martin Pool * patches/backlog-sample.c: Sample that tries to use TCP connection backlogs to give the client some information about whether the server is busy. Doesn't seem to work very well. 2003-03-31 14:59 Martin Pool * TODO: Update 2003-03-31 14:54 Martin Pool * test/testdistcc.py: Doc. 2003-03-31 14:53 Martin Pool * test/testdistcc.py: Add new case exercising dcc_check_address and h_parsemask. 2003-03-31 14:48 Martin Pool * src/access.c: Doc 2003-03-31 14:34 Martin Pool * test/testdistcc.py: NoDetachDaemon_Case: prevent logs from background process getting into build process's stderr. 2003-03-31 14:28 Martin Pool * src/dsignal.c, NEWS: dcc_parent_terminate: No need to explicitly remove pid file; it will be cleaned up in atexit(). 2003-03-31 14:25 Martin Pool * test/testdistcc.py: Allow log output from the server into stderr so that it can be presented if a test case fails. 2003-03-31 14:22 Martin Pool * NEWS, test/testdistcc.py: Add test that --allow does in fact deny connections as it should. 2003-03-31 14:14 Martin Pool * TODO, doc/ssh-notes.txt, doc/to-test.txt: Move notes on future design options into ./TODO. 2003-03-31 14:14 Martin Pool * doc/lock-deadlock.txt: Remove old bug report. 2003-03-31 14:10 Martin Pool * test/testdistcc.py: Remove done TODOs 2003-03-31 14:09 Martin Pool * patches/prefork-sample.c: Doc 2003-03-29 11:06 Martin Pool * NEWS: Retrospective release name. 2003-03-28 18:57 Martin Pool * TODO: Notes about preforking. 2003-03-28 18:43 Martin Pool * patches/prefork-sample.c: Experimental code to see if we can just have every preforked child accept() on the socket 2003-03-28 18:20 Martin Pool * doc/interceptor.txt: interceptor.txt Remove old file 2003-03-28 18:12 Martin Pool * configure.ac, NEWS: Prepare for 2.0.1 release. 2003-03-28 18:12 Martin Pool * Makefile.in: Dereference symbolic files when producing tarball. 2003-03-28 17:33 Martin Pool * linuxdoc/distcc.sgml: Masquerade came out in 2.0, not 1.3. 2003-03-28 16:47 Martin Pool * doc/release-names.txt: [no log message] 2003-03-28 16:17 Martin Pool * linuxdoc/distcc.sgml: Get ready for 2.0 release. 2003-03-28 16:13 Martin Pool * NEWS, configure.ac: Get ready for 2.0 release. 2003-03-28 16:11 Martin Pool * Makefile.in: Remove old doc/ files from the distribution. 2003-03-28 16:02 Martin Pool * src/distcc.c: Remove "HOST/MAX:PORT" syntax from --help. I don't want to make this fully "public" yet because I'm not sure this is the ideal way to set this value in the future. 2003-03-28 15:58 Martin Pool * NEWS, test/testdistcc.py: Test DISTCC_LOG being set to an unwriteable file. 2003-03-28 15:55 Martin Pool * NEWS: Test suite now works with Python 1.5 or later. 2003-03-28 15:53 Martin Pool * test/comfychair.py: Remove dependency on os.spawnvp, which is not in Python1.5 2003-03-28 15:52 Martin Pool * test/testdistcc.py: NoHosts_Case: Python 1.5 can't delete environment variables, so just set them to empty. 2003-03-28 15:50 Martin Pool * src/distcc.c, NEWS: If the file specified by DISTCC_LOG can't be opened, then show an error and use stderr. Previously all errors were just lost. 2003-03-28 15:45 Martin Pool * src/distcc.c, NEWS: If DISTCC_LOG is an empty string, treat as undefined. 2003-03-28 15:42 Martin Pool * test/testdistcc.py: runcmd_background now takes a string, not a sequence. * Python1.5 doesn't have ''.split. 2003-03-28 15:27 Martin Pool * test/: comfychair.py, testdistcc.py: Remove dependency on popen4, which is not present in Python 1.5. * runcmd and related functions now return stdout and stderr messages separately. Many tests must be updated to allow for this. * Refactor some tests towards a flatter hierarchy. * Assert that the compiler should not normally produce errors or other messages. 2003-03-28 13:58 Martin Pool * test/comfychair.py: Remove list comprehension, which is not available in Python 1.5. 2003-03-28 13:54 Martin Pool * TODO: Note on static linking. 2003-03-28 13:51 Martin Pool * test/testdistcc.py, NEWS: On BSD, 'true' and 'false' are in /usr/bin (?) not /bin. 2003-03-28 13:44 Martin Pool * NEWS: Notes on test improvments. 2003-03-28 13:40 Martin Pool * Makefile.in: Makefile (check, installcheck): If Python is not found then just print "tests skipped" rather than failing. This should make the results on the build farm a bit more clear. 2003-03-28 13:37 Martin Pool * configure.ac: If Python is not found in the path, then just leave $(PYTHON) blank rather than setting it to 'false'. 2003-03-28 11:59 Martin Pool * Makefile.in: Remove redundant setting of $(LIBS): autoconf puts -lpopt in there if it's needed. 2003-03-28 11:57 Martin Pool * configure.ac: (Hopefully) better check for socket() and gethostbyname() that will avoid unnecessarily linking libnsl on Linux. Taken from Samba, which got it from CVS. 2003-03-27 19:16 Martin Pool * TODO: Note on DNS timeouts. 2003-03-27 15:58 Martin Pool * src/rpc.h: dcc_x_token_int: Token parameters are unsigned. 2003-03-27 15:54 Martin Pool * NEWS: [no log message] 2003-03-27 15:45 Martin Pool * src/rpc.c: dcc_x_token_int: Remove call to snprintf to format outgoing packets. It really sticks out in valgrind and this is a reasonably common function. 2003-03-27 15:33 Martin Pool * src/: io.c, io.h: dcc_write_int: Remove dead function. 2003-03-27 15:31 Martin Pool * src/: io.h, io.c: dcc_write_str: Remove dead function. 2003-03-27 15:29 Martin Pool * src/clirpc.c: dcc_x_argv: Avoid redundant strlen() computation. 2003-03-27 15:08 Martin Pool * src/arg.c, src/distcc.h, src/exec.c, src/serve.c, src/ssh.c, src/strip.c, NEWS: Factor out code for tracing argv[] arrays. By avoiding conversion unless it is actually going to be logged we save a few cycles. This also addresses some cases where the printable form was not freed after creation, although that shouldn't ever matter much in such a short-lived program. 2003-03-27 11:39 Martin Pool * Makefile.in: Allow for implementations of 'install' that can only process one file at a time. GNU's 'install-sh' is one such. 2003-03-27 11:08 Martin Pool * NEWS: Don't install linuxdoc-info by default, either from CVS or distributions. 2003-03-27 10:37 Martin Pool * Makefile.in: Don't install linuxdoc-info by default, either from CVS or distributions. 2003-03-27 10:30 Martin Pool * Makefile.in: Remove overall 'upload' target: we don't want to upload the manual when the web site is uploaded. 2003-03-26 23:36 Martin Pool * linuxdoc/distcc.sgml: Manual is for 1.3cvs. 2003-03-23 12:18 Martin Pool * Makefile.in: Don't ship unmerged patches in the tarball. 2003-03-23 12:17 Martin Pool * patches/resolver-timeout.diff: resolver-timeout.diff Resolver timeout draft patch from Jonas Jensen 2003-03-22 09:44 Martin Pool * patches/connect-timeout.diff: Remove old draft patch. 2003-03-21 19:02 Martin Pool * test/testdistcc.py: Get rid of Python 2 ism. 2003-03-21 18:59 Martin Pool * src/ncpus.c: Try looking for the predefined "__hpux" or "__hpux__" not "hpux". 2003-03-21 18:47 Martin Pool * NEWS, test/testdistcc.py: Use randomly chosen TCP port for the server when running tests. 2003-03-21 18:46 Martin Pool * NEWS: Use --allow=127.0.0.1 when starting daemon 2003-03-21 18:41 Martin Pool * test/testdistcc.py: Use --allow=127.0.0.1 when starting daemon * killDaemon: if the daemon has already exited, perhaps because of an alarmclock, and removed it's pid file, then don't worry about killing it. 2003-03-21 18:32 Martin Pool * test/testdistcc.py: SimpleDistCC_Case.__init__: remove redundant code: logging has moved into comfychair.TestCase. * SimpleDistCC_Case: Allow subclasses to change lifetime of daemon or command used to start it. * By default daemon only lives 10s. For ThousandFold_Case and Concurrent_Case it needs to live up to 2 minutes. 2003-03-21 18:24 Martin Pool * test/testdistcc.py: NoDetachDaemon_Case: Shouldn't need --lifetime for this test. 2003-03-21 18:21 Martin Pool * test/testdistcc.py, NEWS: Specify limited lifetime when running daemon, so that if it is not cleaned up by the tests it will go away after a little while anyhow. 2003-03-21 18:18 Martin Pool * NEWS, configure.ac, src/dsignal.c: If we have strsignal(), then log the signal name rather than number when terminating. 2003-03-21 18:12 Martin Pool * src/dsignal.c: Also print a message when terminating on SIGALRM. 2003-03-21 18:11 Martin Pool * Makefile.in, src/distcc.h, src/dparent.c, src/dsignal.c: Split signal-handling code into new file dsignal.c 2003-03-21 17:56 Martin Pool * src/: daemon.c, distcc.h, dparent.c: Make sure lifetime limit applies even when the daemon detaches: after forking to dissociate from the session, reset the alarm clock. 2003-03-21 17:25 Martin Pool * test/testdistcc.py: NoHosts_Case: Cleanup to get it working with the new framework. 2003-03-21 16:27 Martin Pool * test/testdistcc.py: NoHosts_Case: Better log message. 2003-03-21 16:24 Martin Pool * test/testdistcc.py: NoDetachDaemon_Case: Make sure daemon is killed off. 2003-03-21 16:21 Martin Pool * test/comfychair.py: Update from Subversion 2003-03-21 16:21 Martin Pool * test/testdistcc.py: Move code for entering rundir into comfychair. * Change killing of daemon to be a cleanup rather than part of teardown. 2003-03-21 14:00 Martin Pool * src/: daemon.c, dopt.c, dparent.c, serve.c: Rename opt.h to dopt.h, to be consistent with dopt.c. 2003-03-21 13:59 Martin Pool * TODO: CCACHE_ERR_FD 2003-03-21 13:56 Martin Pool * Makefile.in: Remove "=distcheck" directory on successful completion. 2003-03-21 13:55 Martin Pool * Makefile.in: Include types.h in distribution. 2003-03-21 13:54 Martin Pool * Makefile.in, src/dopt.h, src/opt.h: Rename opt.h to dopt.h, to be consistent with dopt.c. 2003-03-21 13:46 Martin Pool * NEWS, src/daemon.c, src/dopt.c, src/opt.h: * Add new undocumented (heh) "--lifetime" option that causes the daemon to expire after a certain period. 2003-03-21 13:44 Martin Pool * test/comfychair.py: Doc. 2003-03-21 12:58 Martin Pool * src/sendfile.c: printf type correctness. 2003-03-21 12:51 Martin Pool * TODO: [no log message] 2003-03-21 12:34 Martin Pool * NEWS: types.h: New file, to give typedefs for missing systems types. Include this in files that need it. Move typedefs from random source files into here. * Add in_addr_t, which is int by default. 2003-03-21 12:34 Martin Pool * src/types.h: in_addr_t should perhaps be ulong by default. 2003-03-21 12:31 Martin Pool * src/: access.c, clinet.c, dopt.c, h_parsemask.c, srvnet.c, types.h: types.h: New file, to give typedefs for missing systems types. Include this in files that need it. Move typedefs from random source files into here. * Add in_addr_t, which is int by default. 2003-03-21 12:21 Martin Pool * configure.ac: Check for existence of sys/socket.h * Check for in_addr_t 2003-03-21 12:20 Martin Pool * src/srvnet.c: If socklen_t is missing, make it a size_t. 2003-03-21 12:14 Martin Pool * src/snprintf.h, NEWS: Fix incorrect config macro names: should be HAVE_DECL_ASPRINTF not HAVE_ASPRINTF_DECL. Fixes declaration warnings on Solaris. 2003-03-21 12:02 Martin Pool * NEWS: Should build on IRIX. 2003-03-21 11:58 Martin Pool * NEWS: Don't include Info file in the distribution. It's a bit redundant to ship the documentation in three forms (SGML, HTML, Info), and people can build it or download it if they want to. * Don't rebuild all Linuxdoc files for distribution, only the ones which need to be included. 2003-03-21 11:54 Martin Pool * Makefile.in: Don't include Info file in the distribution. It's a bit redundant to ship the documentation in three forms (SGML, HTML, Info), and people can build it or download it if they want to. * Don't rebuild all Linuxdoc files for distribution, only the ones which need to be included. 2003-03-19 09:34 Martin Pool * configure.ac: Change check for in_port_t, which exists on Solaris, but which isn't found in just sys/types.h and netinet/in.h. 2003-03-19 09:28 Martin Pool * src/ncpus.c: Try to fix BSD dcc_ncpus(). 2003-03-18 21:18 Martin Pool * src/ssh.c: piped_child: Update to take an argv[] array rather than a simple command so that we can avoid running a shell. 2003-03-18 18:15 Martin Pool * configure.ac: Check whether the C compiler supports inlining, etc. Needed for popt. 2003-03-18 17:47 Martin Pool * src/tempfile.c: Cast to int when calling printf. 2003-03-18 17:46 Martin Pool * src/snprintf.h: Add conditional declaration of vsnprintf. 2003-03-18 17:45 Martin Pool * src/ncpus.c: Add FreeBSD/OpenBSD/NetBSD implementation. 2003-03-18 17:36 Martin Pool * src/ncpus.c: Fix includes. 2003-03-18 17:35 Martin Pool * src/ncpus.c: Add a separate definition of dcc_ncpus for HP-UX (not tested), and URLs describing this. 2003-03-18 17:27 Martin Pool * src/ncpus.c, NEWS: Add credit to Dimitri PAPADOPOULOS-ORFANOS for reporting how to do this on various systems. 2003-03-18 17:25 Martin Pool * src/ncpus.c: Check for definition of _SC_NPROCESSORS_ONLN (linux), and _SC_NPROC_ONLN (Irix), and call the appropriate sysconf. 2003-03-18 17:21 Martin Pool * src/ncpus.c: Include prototypes for this file. 2003-03-18 17:20 Martin Pool * NEWS: Clean up some warnings on IRIX. 2003-03-18 17:20 Martin Pool * src/ncpu.c, src/ncpus.c, Makefile.in: Rename ncpu.c to ncpus.c to be consistent with the function name. 2003-03-18 17:18 Martin Pool * src/tempfile.c: Cast mode_t to int when passing to printf. 2003-03-18 17:17 Martin Pool * src/: rpc.c, tempfile.c: Include snprintf.h for systems that don't have these functions. 2003-03-18 17:15 Martin Pool * src/: exec.c: Cast pid_t to long when passing to printf. 2003-03-18 17:13 Martin Pool * src/trace.c: Update copyright. * Remove done TODOs. * Include snprintf.h to quieten warning on machines that don't have vsnprintf, such as IRIX. 2003-03-18 17:11 Martin Pool * NEWS, src/dparent.c: Print number of online CPUs when daemon starts up. 2003-03-18 17:09 Martin Pool * src/distcc.h: Add prototype for dcc_ncpus. 2003-03-18 17:04 Martin Pool * Makefile.in, src/ncpu.c: Add basic code to detect the number of online processors, at least on Linux. 2003-03-18 16:56 Martin Pool * NEWS: Reorder news items. 2003-03-18 15:21 Martin Pool * TODO: Add note to try out masquerade with make-kpkg. 2003-03-18 14:27 Martin Pool * patches/daemon-address-binding.diff: Patch from Neil Mansilla: * Add --address option to daemon, to make it bind only a particular address. I don't know if this is bloat (should be done through inetd?) or a good idea. Therefore not merged yet. 2003-03-18 14:24 Martin Pool * test/comfychair.py: Decode waitstatus values when a command fails. 2003-03-17 22:25 Martin Pool * doc/release-names.txt: [no log message] 2003-03-14 15:49 Martin Pool * TODO: Update status: * Kernel 2.5 bug * SQMS scheduler * --allow is done * Distributed caching 2003-03-13 17:33 Martin Pool * NEWS: Note that SIGTERM handling race for server is now fixed. 2003-03-13 17:31 Martin Pool * test/comfychair.py: Merge from svn r30 2003-03-13 17:29 Martin Pool * patches/distccd-clean-path.diff: Draft patch from Wayne Davison to try to keep masquerade connections off the server's $PATH. 2003-03-13 17:28 Martin Pool * patches/: compression.patch, swhite-lzo-compress.diff: Updated draft patch from Stephen White to do LZO compression. 2003-03-13 17:27 Martin Pool * patches/distcc-ethereal.diff: Draft patch to Ethereal to decode/dissect distcc connections. 2003-03-12 19:08 Martin Pool * src/dparent.c: Fix small signal handling race that would occasionally cause distccd not to exit when signalled. Pointed out by Vance Lankhaar, solution advice from Andrew Tridgell. The problem was that a signal could arrive after we checked the global indicator, but before entering accept(). So the daemon would need to wait for the accept to complete before it could respond to the signal. Since the daemon only needs to do very simple cleanup, we now simply do it in line in the signal handler and never return. 2003-03-12 18:56 Martin Pool * src/dparent.c: FIXME about bug reported by Vance: the daemon sometimes doesn't exit on receipt of SIGTERM, which makes the test suite hang. 2003-03-12 17:12 Martin Pool * test/testdistcc.py: assert_regexp renamed to assert_re_search 2003-03-12 17:09 Martin Pool * test/testdistcc.py: Fix incorrect regexp assertion 2003-03-12 16:51 Martin Pool * test/testdistcc.py: explainFailure, fail, assertEquals, assertNotEqual, assertReMatch: these are now present in ComfyChair and don't need to be in this file. 2003-03-12 16:40 Martin Pool * test/comfychair.py: Update from Subversion r24: ------------------------------------------------------------------------ rev 24: mbp | 2003-03-12 16:32:53 +1100 (Wed, 12 Mar 2003) | 4 lines * Fix calls to explain_failure() * comfychair.main: If test names are specified, run them. ------------------------------------------------------------------------ rev 23: mbp | 2003-03-12 16:28:29 +1100 (Wed, 12 Mar 2003) | 2 lines * Fix --help message. 2003-03-12 16:37 Martin Pool * NEWS: Many internal updates to ComfyChair framework. 2003-03-12 16:11 Martin Pool * test/testdistcc.py: Change to using new ComfyChair.main() method, rather than implementing it by hand. 2003-03-12 15:43 Martin Pool * test/comfychair.py: Import updated ComfyChair from Subversion: renamed methods, new main() method, etc. 2003-03-12 15:42 Martin Pool * test/testdistcc.py: SimpleDistCC_Case.__init__ needs to call the base constructor method. * Update for renamed methods in latest ComfyChair. 2003-03-11 17:42 Martin Pool * doc/release-names.txt: [no log message] 2003-03-10 15:34 Martin Pool * src/util.c: IRIX might need sys/time.h before sys/resource.h 2003-03-10 15:13 Martin Pool * src/util.c: Check for sys/resource.h 2003-03-10 15:10 Martin Pool * configure.ac: Check for sys/resource.h 2003-03-10 15:08 Martin Pool * configure.ac: Check for getrusage. 2003-03-10 14:12 Martin Pool * NEWS: Give credit for masquerade mode. 2003-03-10 13:46 Martin Pool * configure.ac: Test for getwd and getcwd 2003-03-10 10:58 Martin Pool * Makefile.in: Remove ssh.o from client for the time being. 2003-03-10 10:16 Martin Pool * patches/: distcc-1.2.1-masquerade.patch, masquerade.patch: Remove merged 'masquerade' patch. 2003-03-10 10:07 Martin Pool * src/io.c: sendfile.h no longer needed here. Thanks to Wayne Davison. 2003-03-09 20:28 Martin Pool * linuxdoc/distcc.sgml: Re-add "if your disks are too empty". 2003-03-09 10:43 Martin Pool * configure.ac: Advance version to 1.3cvs. 2003-03-09 10:14 Martin Pool * Makefile.in: Add ssh module to build. 2003-03-08 22:48 Martin Pool * .cvsignore: Ignore =distcheck directory 2003-03-08 21:53 Martin Pool * NEWS: Note about merged masquerade mode. * Reindent stuff. 2003-03-08 21:47 Martin Pool * doc/release-names.txt: [no log message] 2003-03-08 10:43 Martin Pool * src/sendfile.c: Fix cast in call to sprintf for platforms where ssize_t != int. Found on Alpha Linux in the hp Compaq testdrive. 2003-03-08 10:39 Martin Pool * src/implicit.c: Doc 2003-03-08 10:29 Martin Pool * NEWS: Fix cast in call to sprintf for platforms where ssize_t != int. Found on Alpha Linux in the hp Compaq testdrive. 2003-03-05 13:02 Martin Pool * configure.ac, linuxdoc/distcc.sgml, src/distcc.c, src/exec.c, src/exec.h, src/serve.c, src/util.c, src/util.h: masquerade patch from Wayne Davison: * Add 'masquerade' option, where a link to distcc is created in e.g. /usr/lib/distcc/bin/cc so that it can catch calls to 'cc'. * Check for getwd in configure * Update manual to document 'masquerade' * Update manual to say default port is 3632. * Document /MAX syntax in --help. 2003-03-03 12:42 Martin Pool * doc/release-names.txt: [no log message] 2003-03-02 10:31 Martin Pool * configure.ac: Update for release. 2003-03-02 09:52 Martin Pool * NEWS: Update for release. 2003-03-01 23:54 Martin Pool * README.popt: URL for popt. 2003-03-01 23:49 Martin Pool * src/: setuid.c, setuid.h: Fix constness of opt_user. 2003-03-01 09:12 Martin Pool * src/lock.c, NEWS: SUSv3 says that locking functions can return EACCES for contention. HP-UX does this; perhaps Cygwin does too. 2003-02-28 14:18 Martin Pool * configure.ac, NEWS: Check existence of ctype.h. Pointed out by Tom Matelich. 2003-02-28 14:15 Martin Pool * patches/masquerade.patch: Masquerade patch from Wayne Davison 2003-02-28 10:45 Martin Pool * NEWS: Header for 1.2.3 release. * dcc_make_lock_filename: Windoze can't handle ':' in filenames. Pointed out by Heiko Elger. 2003-02-28 10:41 Martin Pool * src/lock.c: dcc_make_lock_filename: Windoze can't handle ':' in filenames. Pointed out by Heiko Elger. 2003-02-28 10:40 Martin Pool * src/lock.c: Doxygen janitor 2003-02-28 08:02 Martin Pool * src/lock.c: Fix unreachable trace message. Thanks to Dimitri Papadopoulos-Orfanos. 2003-02-27 16:07 Martin Pool * Makefile.in: analog-resolve: Tweak jdresolve invocation 2003-02-27 15:58 Martin Pool * Makefile.in: analog-resolve: Tweak jdresolve invocation 2003-02-27 13:23 Martin Pool * patches/n_cpus.txt: n_cpus.txt Notes on determining NCPUs, from Dimitri PAPADOPOULOS 2003-02-27 13:14 Martin Pool * patches/connect-timeout-02.diff: connect-timeout-02.diff Connection timeout patch from Oscar Esteban 2003-02-27 13:09 Martin Pool * patches/connect-timeout.diff: connect-timeout.diff Connection timeout patch from Oscar Esteban 2003-02-27 12:52 Martin Pool * Makefile.in, OLDNEWS: Remove empty/dead OLDNEWS file. 2003-02-27 12:36 Martin Pool * NEWS: Add missing release comments. 2003-02-27 12:32 Martin Pool * NEWS: Add release date. 2003-02-27 12:20 Martin Pool * test/testdistcc.py: Doc 2003-02-27 12:18 Martin Pool * Makefile.in: Be more selective in uploading linuxdoc files. 2003-02-27 11:52 Martin Pool * Makefile.in: Make distcheck should use $MAKE. 2003-02-27 11:50 Martin Pool * Makefile.in: Distribute the uncompressed info file: this makes patch across the source distribution work, and possibly helps bzip2 compress the whole distribution. 2003-02-27 11:38 Martin Pool * src/sendfile.c: Add HP-UX implementation of sys_sendfile, based on a note from Tom Matelich and the manual. Not tested on an HP-UX machine yet. 2003-02-27 11:17 Martin Pool * Makefile.in: clirpc.h: New header 2003-02-27 11:14 Martin Pool * Makefile.in, NEWS: Add a simple distcheck target. 2003-02-27 11:10 Martin Pool * Makefile.in: Remove deleted tests from $(test_SOURCE) 2003-02-27 11:06 Martin Pool * Makefile.in: Fix command to remove dist dir before building. 2003-02-27 10:25 Martin Pool * src/access.c: The FreeBSD manual suggests might be needed here to make in_addr_t work. 2003-02-27 10:20 Martin Pool * configure.ac: Check for stdint.h 2003-02-27 10:18 Martin Pool * doc/release-names.txt: [no log message] 2003-02-27 10:17 Martin Pool * NEWS: Call this release 1.2.2. * Note about updated Makefile. 2003-02-26 16:36 Martin Pool * test/: basecases.py, testdistcc.py: Move basecases back into testdistcc 2003-02-26 12:35 Martin Pool * test/: setuidcases.py, testdistcc.py: Splitting tests across several files seems not to be a good idea at the moment. It doesn't really make it easier to navigate. A new factoring is desirable. * setuidcases.py merged back into testdistcc.py 2003-02-26 12:33 Martin Pool * test/: EmptySource.py, ScanArgs.py, testdistcc.py: Splitting tests across several files seems not to be a good idea at the moment. It doesn't really make it easier to navigate. A new factoring is desirable. * EmptySource.py, ScanArgs.py merged back into testdistcc.py 2003-02-26 12:28 Martin Pool * test/ScanArgs.py: Remove RunCmd_Case, whose functionality has now migrated up into ComfyChair. 2003-02-26 12:27 Martin Pool * test/.cvsignore: Ignore ./testtmp/ if it happens to be here. 2003-02-26 12:27 Martin Pool * test/testdistcc.py: Remove RunCmd_Case, whose functionality has now migrated up into ComfyChair. * Add GPL. 2003-02-26 12:25 Martin Pool * test/basecases.py: Remove RunCmd_Case, whose functionality has now migrated up into ComfyChair. 2003-02-26 12:22 Martin Pool * test/comfychair.py: runCmdNoWait: add missing "import os" 2003-02-26 12:21 Martin Pool * test/comfychair.py: Copy from distcc HEAD * Make sure to print out any errors that happen while running tests, not only the ComfyChair-specific exceptions. 2003-02-26 12:18 Martin Pool * test/comfychair.py: Merge from tpot's comfychair HEAD checkin: * report failure to construct * add skip_on_noexec to runCmdUnchecked 2003-02-26 12:13 Martin Pool * test/comfychair.py: Add GPL. * Add runCmdNoWait to run things in the background. * Don't use '+=' to support Python 1.5. 2003-02-26 11:52 Martin Pool * NEWS: ./configure should not be removed by distclean, only by maintainer-clean. * Make Makefile work with pmake 2003-02-26 11:51 Martin Pool * Makefile.in: Remove '$^' variable, which doesn't work with pmake. 2003-02-26 11:47 Martin Pool * Makefile.in: ./configure should not be removed by distclean, only by maintainer-clean. 2003-02-26 11:44 Martin Pool * Makefile.in: Change to old-style implicit rules, in the hope of getting this to compile on non-GNU Make. 2003-02-25 23:29 Martin Pool * src/ssh.c: More cleanups/merges. Still not working. 2003-02-25 23:14 Martin Pool * src/ssh.c: Merge more code from rsync. Still not working. 2003-02-25 23:10 Martin Pool * configure.ac: Add socketpair test from rsync. 2003-02-25 22:50 Martin Pool * src/ssh.c: ssh.c Check in non-working skeleton ssh code from rsync and cvs 2003-02-25 22:37 Martin Pool * src/clinet.c: Doc 2003-02-25 22:36 Martin Pool * src/trace.h: Don't use __FUNCTION__ if not building on gnuc. 2003-02-25 22:26 Martin Pool * configure.ac, NEWS: Check for inet_aton in libresolv, which might fix Solaris 2.6. 2003-02-25 22:23 Martin Pool * src/distcc.c: Clear up unused vars * Doc 2003-02-25 22:22 Martin Pool * NEWS, src/distcc.c: Avoid repeatedly locking localhost when it's chosen from the host list, because we don't have reentrant locks on Cygwin. 2003-02-25 22:09 Martin Pool * src/distcc.c: Typo 2003-02-25 22:08 Martin Pool * Makefile.in, src/clirpc.c, src/clirpc.h, src/distcc.c: Split client RPC code into its own file to slim distcc.c. 2003-02-25 22:04 Martin Pool * patches/distcc-1.2.1-masquerade.patch: Patch from Wayne Davison to masquerade as cc. 2003-02-25 22:01 Martin Pool * src/distcc.c: Doc 2003-02-25 21:49 Martin Pool * configure.ac: Bump version to 1.3cvs 2003-02-25 21:26 Martin Pool * .cvsignore: Ignore linbot-report. 2003-02-25 21:25 Martin Pool * Makefile.in: Delete directory used to make distribution tarball before starting to build it. 2003-02-25 21:23 Martin Pool * TODO: Notes about asprintf and Linuxdoc. 2003-02-25 16:59 Martin Pool * NEWS: Note about libiberty redaction. 2003-02-25 16:57 Martin Pool * NEWS, configure.ac: Update for 1.2.1 release. 2003-02-25 16:51 Martin Pool * Makefile.in: Fix typo 2003-02-25 16:48 Martin Pool * src/snprintf.c: Quieten compiler warning. 2003-02-25 16:47 Martin Pool * configure.ac: Also check for snprintf 2003-02-25 16:38 Martin Pool * src/arg.c: Fix small memory leak. 2003-02-25 16:33 Martin Pool * src/exec.c: Remove dead function dcc_close_extra_fds. 2003-02-25 16:28 Martin Pool * Makefile.in: Don't use "python -V" because it apparently doesn't work on 1.5. Just look directly in sys.version. 2003-02-25 16:14 Martin Pool * Makefile.in: Print Python version before running tests to help in debugging remote problems. 2003-02-25 16:08 Martin Pool * test/testdistcc.py: Remove unnecessary 'unittest' import 2003-02-25 16:07 Martin Pool * test/testdistcc.py, NEWS: Return code from running the tests now indicates whether they worked or not. 2003-02-25 16:06 Martin Pool * test/comfychair.py: Refactor function * comfychair.runtests now returns a value that can be returned from system.exit 2003-02-25 15:53 Martin Pool * test/testdistcc.py: Remove += operator not supported in old Pythons. 2003-02-25 15:22 Martin Pool * test/testdistcc.py: Don't use fn(*tup) calling convention, because it's not supported in earlier Python versions. Use apply instead. 2003-02-25 15:18 Martin Pool * configure.ac: Don't worry about -Winline, because nothing in distcc is explicitly inlined. 2003-02-25 15:14 Martin Pool * DEPENDENCIES: We need autoconf >=2.53 2003-02-25 15:13 Martin Pool * configure.ac: Check for vsnprintf as well. 2003-02-25 15:06 Martin Pool * Makefile.in: Make sure snprintf.o actually gets linked in. 2003-02-25 11:28 Martin Pool * src/lock.c: Include local declarations for asprintf if necessary. 2003-02-25 11:27 Martin Pool * Makefile.in, NEWS, configure.ac, src/h_hosts.c, src/hosts.c, src/lock.c, src/tempfile.c, src/trace.c, src/where.c: Remove libiberty asprintf. Might fix problems with headers on Solaris and BSD. * Add asprintf etc from Samba HEAD. * Define _GNU_SOURCE in CPPFLAGS so that it is set for autoconf tests. * Add configure test for C99-compliant vsnprintf from Samba HEAD. 2003-02-25 11:07 Martin Pool * src/: snprintf.c, snprintf.h: Add *printf implementation from Samba HEAD. 2003-02-24 16:39 Martin Pool * configure.ac: Remove -Wredundant-decls, because it causes noise with some system headers. 2003-02-24 16:35 Martin Pool * configure.ac: Remove -W options that are implied by -Wall. 2003-02-24 16:29 Martin Pool * Makefile.in: Include %.o target for Makes that have a wierd built-in definition. 2003-02-24 16:24 Martin Pool * NEWS: Add ansidecl.h from libiberty (from gdb-5.3) 2003-02-24 16:20 Martin Pool * Makefile.in: Add ansidecl.h from libiberty (from gdb-5.3) 2003-02-24 16:15 Martin Pool * NEWS: Update NEWS 2003-02-24 16:12 Martin Pool * src/io.c: Remove redundant inclusion of assert.h 2003-02-24 16:10 Martin Pool * configure.ac, Makefile.in: Try to find Python during configuration. 2003-02-24 15:56 Martin Pool * Makefile.in: Allow installation to complete even if the tools to build Linuxdoc are missing. 2003-02-24 15:05 Martin Pool * Makefile.in: installcheck needs to look in the build directory as well as in the installed path to find the harness programs. In the future perhaps there ought to be a subset of tests that skips the harnesses. 2003-02-24 14:58 Martin Pool * Makefile.in: Add "installcheck" target that can be called by the buildfarm. 2003-02-24 14:48 Martin Pool * configure.ac: Check autoconf >= 2.53 * Don't use AC_CONFIG_LIBOBJ_DIR because it's not in ac 2.53 2003-02-24 14:39 Martin Pool * configure.ac: FIXME 2003-02-24 13:59 Martin Pool * autogen.sh: Merge back from the samba/HEAD autogen.sh 1.2, which jerry updated to work on more systems, including RH7.2. 2003-02-24 13:33 Martin Pool * NEWS: foo 2003-02-24 13:19 Martin Pool * NEWS: foo 2003-02-24 13:15 Martin Pool * NEWS: Dummy checkin to test build farm. 2003-02-24 11:54 Martin Pool * NEWS: Dummy checkin to test build farm. 2003-02-24 09:52 Martin Pool * configure.ac: Update version to 1.2.1cvs. 2003-02-22 20:29 Martin Pool * NEWS: Get ready for 1.2 release. 2003-02-22 20:22 Martin Pool * configure.ac: Set bug report address to the list, not me. 2003-02-22 20:21 Martin Pool * configure.ac: Get ready for 1.2 release. 2003-02-22 12:55 Martin Pool * Makefile.in: Remove Docbook from distribution. 2003-02-22 12:53 Martin Pool * Makefile.in: filename.h: New file. 2003-02-22 12:41 Martin Pool * src/: arg.c, cpp.c, distcc.c, distcc.h, exec.c, exec.h, filename.c, filename.h, hosts.c, implicit.c, lock.c, serve.c, strip.c, trace.h: Cleanups to fix various gcc warnings. 2003-02-22 12:20 Martin Pool * src/distcc.h: Remove redundant decls. 2003-02-22 12:19 Martin Pool * configure.ac: Turn on more compiler warnings. 2003-02-22 12:16 Martin Pool * TODO: Turn on more compiler warnings. * Note about statistics. 2003-02-22 12:07 Martin Pool * src/hosts.c: Refactor code into new function dcc_parse_localhost. 2003-02-22 11:58 Martin Pool * src/hosts.c: Fix comments 2003-02-22 11:56 Martin Pool * NEWS: Roll back to Linuxdoc for the manual. 2003-02-22 11:37 Martin Pool * linuxdoc/distcc.sgml: Ask people to report bugs to the mailing list, not to me. 2003-02-22 11:35 Martin Pool * linuxdoc/distcc.sgml: distcc.sgml Resurrect Linuxdoc manual 2003-02-22 11:25 Martin Pool * Makefile.in: Use rsync --delete when uploading manual to delete unneeded files. 2003-02-22 11:12 Martin Pool * Makefile.in: Roll back to Linuxdoc for the manual. Docbook tools seem to be still too unstable. 2003-02-21 11:54 Martin Pool * Makefile.in: Add "links" web page 2003-02-21 10:13 Martin Pool * patches/distcc-line3.diff: Patch from Tim Janik to absolutize #line directives. 2003-02-21 10:08 Martin Pool * doc/lca2003/slides/.cvsignore: Ignore built Postscript 2003-02-21 10:05 Martin Pool * Makefile.in: Include additional Python files in distribution. 2003-02-19 13:09 Martin Pool * test/testdistcc.py: By default only one job is run locally now. 2003-02-18 17:55 Martin Pool * NEWS: Postscript and PDF turned off for now. 2003-02-18 17:44 Martin Pool * Makefile.in: Add target to build "nochunks" (one big page) manual. 2003-02-18 17:22 Martin Pool * Makefile.in: Add upload-usermanual target. 2003-02-18 15:15 Martin Pool * Makefile.in: Put usermanual files correctly into distribution. 2003-02-18 15:14 Martin Pool * Makefile.in: Add targets/rules to build, distribute and install the Docbook-XML manual. 2003-02-18 14:37 Martin Pool * doc/aoss2002/slides/: README.aoss2002, aoss4.mgp, flow.dia, flow.png: Move AOSS2002 slides 2003-02-14 15:40 Martin Pool * TODO: Add note about slow networks. 2003-02-13 18:10 Martin Pool * src/where.c: Don't use XMIT locks for localhost, because there is no transmission phase. 2003-02-13 18:00 Martin Pool * src/distcc.c: Change completion message for remote compile to "compile on FOO" rather than "gcc on FOO". Easier to grep for. 2003-02-13 17:56 Martin Pool * src/hosts.c: /N syntax now *sets* the number of slots, rather than setting a multiplier. * Default for localhost is now 1. 2003-02-13 17:13 Martin Pool * src/hosts.c: Add HOST/NSLOTS syntax to limit number of tasks. Patch from Rusty. 2003-02-13 16:50 Martin Pool * src/where.c: dcc_lock_one: New implementation: The previous code was far too heavily biased towards the first machine, because it tried to find any empty CPU slot there even if other machines were idle. Now, the outer loop is the slot number, and we try all hosts with at least that many slots. We acquire the CPU lock before getting the XMIT lock. 2003-02-13 16:27 Martin Pool * src/where.c: Typo: didn't set CPU slot properly. 2003-02-13 16:19 Martin Pool * src/: distcc.c, lock.c, where.c, where.h: Update new scheduler to use two locks: one controlling access to the remote machine's CPU, and one serializing the network connection to the machine to avoid inadvertent synchronization. 2003-02-13 15:52 Martin Pool * TODO: Add compiler warnings from Daniel Veilard 2003-02-12 18:24 Martin Pool * test/testdistcc.py: Import new setuidcases module. 2003-02-12 18:12 Martin Pool * test/setuidcases.py: New file to check --user option. 2003-02-12 18:08 Martin Pool * test/comfychair.py: require(), require_root(): New functions that causes a test to be skipped unless particular conditions are met. 2003-02-12 17:46 Martin Pool * test/comfychair.py: Merge from comfychair CVS 2003-02-11 11:18 Martin Pool * src/lock.c: Fixme. 2003-02-07 21:17 Martin Pool * src/: distcc.c, where.c, where.h: Rename dcc_pick_buildhost to dcc_pick_host_from_env 2003-02-05 23:11 Martin Pool * TODO: [no log message] 2003-02-05 23:07 Martin Pool * Makefile.in: Don't delete config.status with plain "make clean", because it's really at the same level as the Makefile. 2003-02-05 23:05 Martin Pool * src/bulk.c, NEWS: Add O_BINARY bit needed for Cygwin. Based on a patch from Helind. 2003-02-05 22:43 Martin Pool * DEPENDENCIES: Note about dietlibc. 2003-02-05 22:41 Martin Pool * Makefile.in: Update "*clean" targets: cleaning should remove configure state files; maintainer-clean should remove all autoconf files that can be regenerated. From a patch by Paul Russell. 2003-02-05 21:52 Martin Pool * TODO: Note about manpages. 2003-02-05 19:14 Martin Pool * src/distcc.h: opt_allowed needs to be declared extern. Found by tcc. 2003-02-05 19:11 Martin Pool * TODO: [no log message] 2003-02-05 19:10 Martin Pool * src/io.c: Change assert to trace call to make dietlibc happy 2003-02-05 19:08 Martin Pool * src/clinet.c: fixme 2003-02-04 23:02 Martin Pool * src/where.c: Cleanup comments. 2003-02-04 22:58 Martin Pool * NEWS, src/bulk.c, src/bulk.h, src/distcc.c, src/serve.c: Show timing on transmission of DOTI and DOTO files. 2003-02-04 22:48 Martin Pool * src/bulk.c: Remove dcc_r_fifo, which is no longer called because we no longer support feeding the compiler from a fifo. 2003-02-04 19:58 Martin Pool * Makefile.in, src/bulk.c, src/bulk.h, src/distcc.c, src/serve.c: Show transfer rate for transmitted files. 2003-02-04 19:55 Martin Pool * src/: timeval.c, timeval.h: Add GNU function for calculating the difference between timevals. 2003-02-04 19:29 Martin Pool * doc/release-names.txt: [no log message] 2003-02-04 19:21 Martin Pool * configure.ac: Add ./lib to include path so libiberty.h can be found. 2003-02-03 12:50 Martin Pool * src/rpc.h: Doc 2003-02-03 12:49 Martin Pool * TODO: [no log message] 2003-02-03 01:15 Martin Pool * doc/new-scheduler.txt: Notes on new scheduler 2003-02-03 00:59 Martin Pool * NEWS: Describe new scheduling algorithm. 2003-02-03 00:44 Martin Pool * src/where.c: Better message 2003-02-03 00:43 Martin Pool * src/distcc.c: Fixme 2003-02-03 00:28 Martin Pool * src/where.c: Doc 2003-02-03 00:27 Martin Pool * src/distcc.c: Hold transmit lock only while sending request. 2003-02-03 00:27 Martin Pool * src/where.c: Doc 2003-02-03 00:27 Martin Pool * src/: lock.c, lock.h: (dcc_unlock): New function. 2003-02-03 00:13 Martin Pool * src/: distcc.c, lock.c, lock.h, where.c, where.h: Lock functions pass back their fd so that it can be released later. * (dcc_lock_host): Clean up error handling. 2003-02-03 00:06 Martin Pool * src/lock.h: Add lock_fd parameter to dcc_lock_host and dcc_lock_local functions 2003-02-03 00:04 Martin Pool * src/lock.c: Doc 2003-02-03 00:04 Martin Pool * src/lock.c: Remove redundant dcc_get_tempdir call. 2003-02-03 00:03 Martin Pool * src/lock.c: Split lockfile creation into dcc_open_lockfile 2003-02-03 00:01 Martin Pool * src/: where.c, where.h: Document locking system. * Add a "lockname" parameter to allow for multiple locks in the future. * WORK IN PROGRESS: Start moving towards new transmission-based locking, where we hold the lock only while sending. Not done yet. 2003-02-03 00:00 Martin Pool * src/: lock.c, lock.h: Document locking system. * Add a "lockname" parameter to allow for multiple locks in the future. 2003-02-02 23:44 Martin Pool * Makefile.in: Remove linuxdoc targets from the Makefile to allow for transition to Docbook. Docbook manual is not built yet because of issues with Debian's xsltproc. 2003-02-02 23:34 Martin Pool * TODO: [no log message] 2003-02-02 23:31 Martin Pool * Makefile.in: Add README.libiberty to distributed files. 2003-02-02 23:31 Martin Pool * README.libiberty: Check in some files from libiberty. 2003-02-02 23:30 Martin Pool * src/lock.c: (dcc_lock_host): Add doc. Change "already locked" to less ambiguous "%s is busy". Update to use standard exit codes. 2003-02-02 23:24 Martin Pool * src/exitcode.h: Add EXIT_BUSY. 2003-02-02 22:56 Martin Pool * src/lock.c: Use libiberty for asprintf(). * (dcc_make_lock_filename): Rewrite to use asprintf() rather than a fixed-length buffer. Safer and simpler. Lock filenames now take into account the port as well as the hostname, and it supports ssh schemes. 2003-02-02 22:54 Martin Pool * NEWS: [no log message] 2003-02-02 22:48 Martin Pool * Makefile.in: Include libiberty source in distribution. 2003-02-02 22:48 Martin Pool * configure.ac: Add lib/ directory * Check for asprintf() and vasprintf() and replace them if not present. 2003-02-02 22:06 Martin Pool * TODO: Notes on Docbook. * Notes on a minimal gcc for clients. 2003-02-02 16:30 Martin Pool * linuxdoc/: distcc.sgml, footer.html: Remove Linuxdoc documentation now that it's been converted to Docbook XML 2003-02-02 16:30 Martin Pool * NEWS: Note conversion of user manual. 2003-02-02 16:18 Martin Pool * patches/timj-line1.diff: Patch from Tim Janik to post-process the preprocessor output to absolutify file names. It works and it's nicely written, but I'm not yet convinced that the benefit is justified. 2003-02-02 14:38 Martin Pool * src/.cvsignore: Don't ignore .d and .i files, since they shouldn't be generated anymore. 2003-02-02 14:37 Martin Pool * Makefile.in, contrib/distcc-absolutify, contrib/netpwd, contrib/stage-cc-wrapper.patch: Additional contributed scripts by Alexandre Oliva useful in building gcc using distcc. From his mail of 14 Aug 2002. 2003-01-31 15:03 Martin Pool * src/where.c: Doc 2003-01-31 11:48 Martin Pool * analog/.cvsignore: Ignore generated files. 2003-01-31 11:17 Martin Pool * TODO: Notes on corks, scheduling, and tcp options. 2003-01-31 10:56 Martin Pool * TODO: Notes about scheduling from BBQ 2003-01-31 10:42 Martin Pool * TODO: Note about #pragma implementation 2003-01-29 15:52 Martin Pool * linuxdoc/distcc.sgml: Grammar fixes. 2003-01-29 12:14 Martin Pool * src/dopt.c: (distccd_show_usage): Remove vestigial argument to printf * (distccd_parse_options): Fix return code handling * Doc 2003-01-29 00:52 Martin Pool * Makefile.in: Typo 2003-01-29 00:50 Martin Pool * test/testdistcc.py: TODO 2003-01-29 00:49 Martin Pool * src/: access.h, distcc.h, dopt.c, srvnet.c: Add --allow, -a option to distccd. Build up a list of allowed client addresses. Check against them when a client connects; drop the connection if it's not allowed. 2003-01-29 00:46 Martin Pool * NEWS: Note new --allow option. 2003-01-29 00:19 Martin Pool * src/: access.c, access.h, h_parsemask.c: Add code to actually check whether access ought to be allowed. 2003-01-29 00:08 Martin Pool * src/: access.c, access.h, h_parsemask.c: Start adding IP-based access control. So far, a function to parse matchers like 10.0.0.0/8. 2003-01-29 00:07 Martin Pool * Makefile.in, .cvsignore: Add new h_parsemask test harness. 2003-01-29 00:02 Martin Pool * doc/lca2003/slides/: .cvsignore, distcc-lca2003.mgp, flow.dia, flow.png: Add LCA2003 slides. 2003-01-28 23:14 Martin Pool * Makefile.in: Add access.c and access.h 2003-01-28 19:57 Martin Pool * NEWS, src/exec.c: * Use putenv() rather than setenv() to fit into SUSv2 and work on Solaris 8. Pointed out by Dimitri Papadopoulos. 2003-01-28 19:52 Martin Pool * test/testdistcc.py: TODO 2003-01-28 01:24 Martin Pool * src/access.c: Empty file 2003-01-28 01:21 Martin Pool * src/lock.c: Doc 2003-01-28 01:19 Martin Pool * src/dopt.c: Fix string syntax problem. 2003-01-28 01:18 Martin Pool * configure.ac: Version to 1.2cvs 2003-01-28 01:18 Martin Pool * src/help.c: Please send bugs to the mailing list 2003-01-28 01:17 Martin Pool * src/help.c: Update copyright 2003-01-28 01:06 Martin Pool * Makefile.in: Add missing Python source. 2003-01-28 01:05 Martin Pool * TODO: [no log message] 2003-01-28 01:01 Martin Pool * src/: dparent.c, daemon.c: srvnet.h: new header 2003-01-28 00:56 Martin Pool * NEWS, configure.ac: Update for 1.1 2003-01-28 00:52 Martin Pool * NEWS: Updates to manual 2003-01-28 00:21 Martin Pool * analog/extract_version_downloads.py: Simple script to show the number of downloads of each version. 2003-01-27 23:23 Martin Pool * src/lock.c: Doc 2003-01-27 23:19 Martin Pool * TODO: Note about taking host list from a file. 2003-01-27 23:16 Martin Pool * src/distcc.h: New srvnet.h header 2003-01-27 23:16 Martin Pool * patches/andresen-gcc-wrapper-r2.tbz2: Patch from Eric Andresen for Gentoo bug #13897 to add some kind of wrapper. 2003-01-27 23:13 Martin Pool * src/distcc.c: Doxygen cleanups 2003-01-27 23:11 Martin Pool * src/dparent.c: Just refuse root once at the top level of distccd. We don't support binding reserved ports so there's no need to do it any later as far as I can see. 2003-01-27 23:06 Martin Pool * src/dopt.c: Doc * Add new --user option. Warning is printed if this is used when not started by root. * Sort option table into alphabetical order. 2003-01-27 23:03 Martin Pool * src/: exec.h, exec.c: Doc 2003-01-27 23:01 Martin Pool * src/exitcode.h: Give the exitcode enum a name * Add EXIT_SETUID_FAILED and EXIT_ACCESS_DENIED 2003-01-27 22:59 Martin Pool * src/hosts.h: Fix Doxygen glitch 2003-01-27 22:58 Martin Pool * src/io.c: Split sendfile wrappers out into src/sendfile.c 2003-01-27 22:55 Martin Pool * src/: setuid.c, setuid.h: New code for discarding privileges when run by root. 2003-01-27 22:54 Martin Pool * src/serve.c: src/srvnet.h: New header * Log client name (and in the future, check access) very early in connection handling. * Doc. 2003-01-27 22:53 Martin Pool * src/trace.h: Update Doxygen. 2003-01-27 22:50 Martin Pool * src/util.h: Move srvnet functions to srvnet.h 2003-01-27 22:41 Martin Pool * src/util.c: Message when exiting should always just be level 'info'. * Just show 4 decimal places in time measurements. Higher than that may not be very meaningful. 2003-01-27 22:36 Martin Pool * src/srvnet.c: src/srvnet.h: New header * Doc * Prepare for IP access-control checks 2003-01-27 22:35 Martin Pool * src/srvnet.h: src/srvnet.h: New header 2003-01-27 22:33 Martin Pool * src/sendfile.c: Move sendfile support into sendfile.c * Doc * Better handling of unsupported systems 2003-01-27 22:30 Martin Pool * Makefile.in: src/sendfile.c: Split sendfile into a separate source file * src/setuid.c, src/setuid.h: Add new ability to change persona when started by root * src/srvnet.h: Move server-side network functions to their own file. 2003-01-27 22:28 Martin Pool * src/daemon.c: Update Doxygen tags * Remove unneeded headers * Discard root privileges if we have them. 2003-01-27 22:27 Martin Pool * src/: arg.c, clinet.c: Update Doxygen tags 2003-01-27 22:25 Martin Pool * NEWS: tcpwrappers isn't in after all, because it's poorly documented and I'm not convinced it's a good fit for distccd. For example, it can only normally be configured by root, but we want to make sure that distccd can be installed and run by ordinary users. 2003-01-27 22:24 Martin Pool * bench/: Build.py, Project.py: Better messages while build is in progress. 2003-01-27 22:23 Martin Pool * bench/ProjectDefs.py: Point at glibc 2.3.1 rather than 2.3 in the hope that this will work better. (It doesn't build yet unfortunately.) 2003-01-27 22:21 Martin Pool * doc/release-names.txt: [no log message] 2003-01-27 22:21 Martin Pool * README.packaging: Please use shlibs * Please use proper gcc names 2003-01-27 22:18 Martin Pool * configure.ac: Doc * Fix help string for --with-included-popt * Some cleanups * Look for setgroups() 2003-01-27 22:17 Martin Pool * NEWS, OLDNEWS: Update NEWS for recent commits * Keep all change notes in the NEWS file per GNU standards. OLDNEWS is now empty. 2003-01-27 22:15 Martin Pool * README: Update performance for current project status 2003-01-27 22:12 Martin Pool * TODO: Many TODO updates. 2003-01-27 22:06 Martin Pool * test/testdistcc.py: Doc 2003-01-27 21:49 Martin Pool * .cvsignore, Doxyfile: Add Doxygen configuration. Not called from Makefile. 2003-01-27 21:35 Martin Pool * linuxdoc/distcc.sgml: Just show CVS date, not version. * Update to version 1.1. * Update: distccd now sends error messages back to the client as well as to its local log file. * Remove "author" section left over from man page. * Describe --verbose option. * Add description of new EXIT_RECURSION code * Move "Compatibility" section into a new chapter. * Move "Cross compilation" into a new chapter, because it's not relevant to many users. * Reformat Huxley quote to make it fit better. * Rearrange introduction. * Warning not to use --no-fork. * Document --no-detach. 2003-01-24 20:16 Martin Pool * NEWS, src/srvnet.c: Don't log client hostname, only the IP address. It's not really necessary and can slow us down. 2003-01-24 20:08 Martin Pool * NEWS, src/distcc.c, src/distcc.h, src/exec.c, src/exec.h, src/exitcode.h: Add environment variable to check for inadvertent recursion. 2003-01-24 20:03 Martin Pool * bench/buildutil.py: Better error message for command failures 2003-01-24 19:54 Martin Pool * NEWS: Add check for inadvertent recursion 2003-01-24 19:52 Martin Pool * TODO: Many updates to TODO 2003-01-24 19:51 Martin Pool * bench/compiler.py: Don't explicitly say "gcc-3.2", because it's not available under that name on Red Hat 8.0. 2003-01-20 11:22 Martin Pool * NEWS, configure.ac: Fix configure test for hstrerror(). (Frerich Raabe) 2003-01-19 20:50 Martin Pool * bench/Summary.py: Fix bugs in printing statistics. 2003-01-19 20:29 Martin Pool * bench/buildutil.py: Better formatting time messages. 2003-01-19 20:27 Martin Pool * bench/Summary.py: Better handling of statistics generation or build failures. 2003-01-19 18:45 Martin Pool * src/arg.c: Doc. 2003-01-19 18:43 Martin Pool * test/: ScanArgs.py, basecases.py, testdistcc.py: Split some Python classes out into separate files. 2003-01-19 18:19 Martin Pool * src/arg.c: Doc. 2003-01-19 15:10 Martin Pool * src/dopt.c: Remove ifdef'd code. 2003-01-18 23:57 Martin Pool * configure.ac: TODO about finding Python. 2003-01-18 23:55 Martin Pool * test/testdistcc.py: Roll back change to version number format. 2003-01-18 23:48 Martin Pool * src/: .cvsignore, config.h.in: Build config.h.in, rather than storing in CVS. 2003-01-18 23:46 Martin Pool * src/io.c, NEWS: Flag platforms that have a sendfile() function, but that aren't explicitly supported, because it seems to vary substantially. At the moment only FreeBSD and Linux are known. 2003-01-18 23:43 Martin Pool * configure.ac: Fix text formatting. 2003-01-18 23:41 Martin Pool * test/testdistcc.py, NEWS: Be less strict in checking the output from the plain text preprocessor, because this seems to have changed in gcc 3.2. 2003-01-18 23:36 Martin Pool * test/testdistcc.py: Update copyright * Allow for new --version output * Fix accidental extra newline in C source, when we wanted the escape sequence "\n" * Change way the preprocessor is called -- not working yet. 2003-01-18 22:53 Martin Pool * .cvsignore: Ignore files produced by autoconf. 2003-01-18 22:51 Martin Pool * bench/benchmark.py, NEWS: Projects can now be selected by unambiguous name prefix 2003-01-18 22:39 Martin Pool * configure.ac: Update copyright 2003-01-18 22:38 Martin Pool * config.guess, config.sub: Update from Debian autotools-dev 2003-01-18 22:27 Martin Pool * config.sub: Resurrect 2003-01-18 22:22 Martin Pool * bench/: Build.py, Summary.py, actions.py, benchmark.py, statistics.py: Make std dev and variance methods handle too-short sequences by returning None, rather than failing. * Add -n option to run benchmarks repeatedly. 2003-01-18 22:21 Martin Pool * aclocal.m4, config.guess, config.sub, configure: Stop storing autoconf junk in CVS 2003-01-18 22:19 Martin Pool * TODO: Need to document benchmark. 2003-01-18 22:10 Martin Pool * Makefile.in: Invite people to pass BENCH_ARGS to Make to control the benchmark. 2003-01-18 22:02 Martin Pool * Makefile.in: Include bench/statistics.py in distribution. 2003-01-18 22:00 Martin Pool * bench/Summary.py, bench/statistics.py, NEWS: Start to add support in the Summary class for repeated runs of a benchmark, plus a new "statistics" library containing code to do mean and std dev. 2003-01-18 21:50 Martin Pool * NEWS: Roll over news 2003-01-18 21:49 Martin Pool * OLDNEWS: Put in correct version of old news file. 2003-01-18 21:36 Martin Pool * OLDNEWS: Roll over NEWS. 2003-01-17 12:05 Martin Pool * configure, configure.ac: Bump version to 1.1cvs 2003-01-17 12:00 Martin Pool * src/daemon.c: FIXME about running as root. 2003-01-17 11:37 Martin Pool * src/daemon.c: fixme 2003-01-16 11:36 Martin Pool * configure: Prepare for 1.0 release. 2003-01-16 11:32 Martin Pool * configure.ac: Prepare for 1.0 release. 2003-01-16 11:28 Martin Pool * NEWS, configure.ac: Prepare for 1.0 release. 2003-01-16 11:06 Martin Pool * Makefile.in: Include benchmark source in tarball. * bzip tarball rather than gzipping it, to save a little space. 2003-01-15 22:22 Martin Pool * bench/benchmark.py: Doc 2003-01-14 16:25 Martin Pool * NEWS: Build .bz2 tarball rather than .tgz * Remove PS and PDF from tarball. 2003-01-14 16:03 Martin Pool * NEWS: [no log message] 2003-01-14 15:46 Martin Pool * Makefile.in: Do not include PDF or PS in the tarball, or install them by default. This may save some space in the distribution. They can be built from source using the Linuxdoc tool, or downloaded. 2003-01-14 15:03 Martin Pool * Makefile.in: Resolve logfile lines in order. 2003-01-14 15:01 Martin Pool * bench/.cvsignore: Ignore bench.log 2003-01-14 00:54 Martin Pool * src/io.c: Correct calling of sendfile on BSD 2003-01-13 14:47 Martin Pool * TODO: [no log message] 2003-01-13 12:24 Martin Pool * Makefile.in: Benchmark must be run from bench/ directory. 2003-01-12 23:59 Martin Pool * bench/Summary.py: Show uname in summary. 2003-01-12 23:51 Martin Pool * bench/Summary.py: Show uname in summary. 2003-01-12 23:40 Martin Pool * bench/Project.py: Doc snarf bug. 2003-01-12 23:24 Martin Pool * Makefile.in, NEWS: * Remove Plucker file: nobody seems to be downloading it, and it's easy enough for people to build if they're interested. 2003-01-12 23:09 Martin Pool * bench/Summary.py: Store results into Summary in the order in which they are generated. 2003-01-12 23:05 Martin Pool * bench/: Build.py, actions.py: Add action to "make clean" if desired. Off by default. 2003-01-12 22:58 Martin Pool * bench/: Build.py, CompilerSpec.py, benchmark.py, compiler.py: Add -c option to specify compilers to run. * Remove 'CompilerSpec' module to 'compiler' so that it can more easily have some static methods. 2003-01-12 22:43 Martin Pool * bench/Summary.py: Print a heading on the results, plus the date and the host list. 2003-01-12 22:37 Martin Pool * bench/: actions.py, benchmark.py: Split intelligence about action selection into a new module. * Auto-generation action help table. * Turn 'scrub' off by default. 2003-01-12 22:20 Martin Pool * bench/: Summary.py, buildutil.py: Show all times in %.4f format -- about the right amount of precision. 2003-01-12 22:18 Martin Pool * bench/: Build.py, Project.py, benchmark.py: Put intelligence about running various Actions in order into the Build and Project classes. * More --help documentation for actions. 2003-01-12 22:10 Martin Pool * bench/: Build.py, Project.py, Summary.py, benchmark.py, buildutil.py: Further refactoring: put the combination of a project and a compiler into a new Build object. * Put each Build in a separate directory, rather than using one directory per Project that is overwritten every time. More scope now for retrying or investigating failed builds. 2003-01-12 22:09 Martin Pool * bench/CompilerSpec.py: Don't use commas in directory names because it causes trouble with some Makefiles. 2003-01-12 21:43 Martin Pool * bench/Project.py: Doc 2003-01-12 21:38 Martin Pool * bench/: CompilerSpec.py, benchmark.py: Split CompilerSpec into its own file. 2003-01-12 21:32 Martin Pool * bench/: Project.py, ProjectDefs.py, Summary.py, benchmark.py: Split Project class and project definitions out into two new source files. * Rename Compiler to CompilerSpec and change name format. 2003-01-12 20:50 Martin Pool * bench/: Summary.py, benchmark.py: Split Summary class out into its own file, and print summaries out in a tabular form rather than as Python data definitions. 2003-01-12 20:50 Martin Pool * bench/.cvsignore: Ignore download directory and .pyc files. 2003-01-09 11:06 Martin Pool * bench/benchmark.py: Run snarf quietly * Doc 2003-01-08 18:28 Martin Pool * bench/benchmark.py: Add GNU Hello so that there's something small for testing the benchmark program. * Add --list-projects option. * Allow selection of actions to perform with --actions=ACTIONS. 2003-01-08 18:03 Martin Pool * bench/benchmark.py: Push mainline code into a main() routine. 2003-01-08 18:01 Martin Pool * bench/benchmark.py: Add Project configuration for Wine * Implement the 'unpacked_subdir' Project option, to handle projects like Wine whose unpacked directory is named differently from the tarball. * Doc. 2003-01-06 15:53 Martin Pool * bench/benchmark.py: Doc 2003-01-06 11:24 Martin Pool * doc/release-names.txt: [no log message] 2003-01-06 11:24 Martin Pool * Makefile.in: Split old news items out into a separate page. 2003-01-02 19:52 Martin Pool * NEWS: Doc macrobenchmark. 2003-01-02 16:31 Martin Pool * TODO: Explanation of KDE's --enable-final option, and impact on parallelism. * Half explain "Supermarket scheduler" idea. * Half explain load balancer. 2003-01-02 15:58 Martin Pool * DEPENDENCIES: Add notes about macrobenchmark. 2003-01-01 10:01 Martin Pool * Makefile.in: Add new "benchmark" target to invoke the macrobenchmark suite. The Makefile prints a notice and checks that the hosts are set up before starting the script. 2003-01-01 09:24 Martin Pool * bench/benchmark.py: Use env(1) to find python2.2. (Frerich Raabe) Really the right way is to call through the Makefile to use $(PYTHON). 2003-01-01 09:22 Martin Pool * bench/: benchmark, benchmark.py: Rename bench/benchmark to bench/benchmark.py. 2003-01-01 09:19 Martin Pool * Makefile.in: Use a $(PYTHON) variable so that it can be overridden if the name varies. 2002-12-17 17:17 Martin Pool * news.el, news.emacs: Store settings in elisp rather than as mode variables. 2002-12-17 10:27 Martin Pool * bench/benchmark: If a build fails, then record that but continue. If the overall build is interrupted, just stop. 2002-12-16 21:29 Martin Pool * bench/benchmark: Doc * Better link for kernel 2002-12-16 21:21 Martin Pool * bench/benchmark: Add gdb * Add md5sum and configure command for linux-2.4.20 * Automatically detect and resume interrupted downloads. Do downloads into a temporary directory and move them on completion. 2002-12-16 21:15 Martin Pool * bench/benchmark: b* Project._rm_files: Do this silently and only as necessary. 2002-12-16 21:12 Martin Pool * bench/benchmark: Remove log files at the start of a build. (We use separate logfiles for each case and phase, so this loses no information.) 2002-12-16 21:08 Martin Pool * bench/benchmark: Rename /SourceTree/Project/ 2002-12-16 21:07 Martin Pool * bench/benchmark: Doc. * Just check for download once when we start working on a project. * Scrub the tree just once when finished on a project. 2002-12-16 21:03 Martin Pool * bench/benchmark: Doc. * Add MD5 for GIMP. * When configuring GIMP, turn off Perl support because it seems not to work on Sid and it's not really necessary. 2002-12-16 20:59 Martin Pool * bench/benchmark: Scrub source directories after successful build to save disk space. * Try boring slow gcc build first, to see if it works. 2002-12-16 20:50 Martin Pool * bench/benchmark: Doc 2002-12-16 20:43 Martin Pool * bench/benchmark: SourceTree.build: Accumulate statistics in Summary object on completion of building. Fix syntax error. * Take list of project names from command line. If none are specified, build all known projects. 2002-12-16 20:38 Martin Pool * bench/benchmark: SourceTree.run_cmd: Return status and elapsed time. * SourceTree.build: Remove obsolete make_args argument. * Summary: New class holding overall results of building. 2002-12-16 20:34 Martin Pool * bench/benchmark: Doc. * Try to make shell commands more readable. * Add GIMP URL. 2002-12-16 20:24 Martin Pool * bench/benchmark: Store separate make and distcc logs for configuring and building, in a per-project per-compiler directory. DISTCC_LOG no longer needs to be set beforehand. * Add more MD5sums. * Add correct configuration and build commands for the kernel. 2002-12-16 20:15 Martin Pool * bench/benchmark: Add new Compiler class, encapsulating $(CC) and Make options. * Add URLs for GNU Make and Linux-2.4.20. * Store build logs into a directory identified by both project and compiler. 2002-12-16 19:59 Martin Pool * bench/benchmark: Add support for packages which need to be built from a subdirectory of their unpacked directory. In particular, Samba needs to be built from "samba-2.2.7/source". 2002-12-16 19:54 Martin Pool * bench/benchmark: Add MD5 sums for other packages. * Add Samba tree. (Doesn't work yet, needs a different configure command to handle source being in source/) 2002-12-16 19:49 Martin Pool * bench/.cvsignore: Ignore output files. 2002-12-16 19:48 Martin Pool * bench/benchmark: Send all build log messages to a persistent file in a standard location. * make_dir: New utility function. * Properly check MD5sum for files before unpacking. 2002-12-16 19:41 Martin Pool * bench/benchmark: Store MD5sum of files in the benchmark source and verify them before use. * Allow overriding $(CC) when the program is configured. * Add glib-2.0.7 test. * Test with distcc and plain cc. 2002-12-16 19:24 Martin Pool * bench/benchmark: (SourceTree.configure, SourceTree.build): Redirect configure and build output into log files so that the display is uncluttered. 2002-12-16 19:21 Martin Pool * bench/benchmark: (SourceTree): Cleaner handling of directories. 2002-12-16 19:11 Martin Pool * bench/benchmark: (SourceTree.run_cmd): Show time to execute each command. * (SourceTree): Don't use the time(1) command, but just measure elapsed time. 2002-12-16 19:03 Martin Pool * bench/benchmark: (SourceTree.run_cmd): Show commands as they're executed. * (SourceTree): Time commands as they're run. * (SourceTree.scrub): Remove build trees before starting to build them. * (SourceTree.build): Allow passing options such as -j to make. 2002-12-16 16:49 Martin Pool * bench/benchmark, NEWS: New macro-benchmark and test suite for distcc. This is the start of a script that runs distcc to build various open source programs, as an overall test of correctness, and to measure performance of a distcc installation. It relies on the user to install and configure distcc servers and clients, but handles the work of downloading, preparing, and building packages by itself. * benchmark: New file. 2002-12-16 16:44 Martin Pool * lzo/.cvsignore: Ignore built files for minilzo 2002-12-16 14:43 Martin Pool * lzo/: Makefile, README.LZO, lzoconf.h, minilzo.c, minilzo.h, testmini.c: Import minilzo-1.08 library. Not linked in to main program yet. 2002-12-16 14:42 Martin Pool * doc/release-names.txt: [no log message] 2002-12-16 11:56 Martin Pool * patches/swhite-lzo-compress.diff: Patch from Stephen White * First cut at adding LZO compression, turned on by client-side environment variable and setting a high bit in the protocol number to indicate its use. Uses static copy of lzo. 2002-12-16 11:40 Martin Pool * src/: h_scanargs.c, h_argvtostr.c: Reindent to java / 4-space style. 2002-12-16 11:32 Martin Pool * patches/README.patches: Disclaim warranty on these patches. 2002-12-13 12:06 Martin Pool * linuxdoc/distcc.sgml: Bump version to 0.16cvs. 2002-12-13 12:04 Martin Pool * NEWS, linuxdoc/distcc.sgml: (Cross-Compilation): The recommended convention for gcc names is -gcc-, and GCC 3.3 will install itself under this name. (Alexandre Oliva, Claes Wallin) 2002-12-13 11:06 Martin Pool * configure, configure.ac: Bump version to 0.16cvs. 2002-12-13 09:58 Martin Pool * NEWS, OLDNEWS: Roll over NEWS. 2002-12-12 20:57 Martin Pool * NEWS, configure, configure.ac: Bump version to 0.15. 2002-12-12 20:45 Martin Pool * doc/results.txt: Current linux-2.4.19 benchmark results. 2002-12-12 20:40 Martin Pool * configure: Run autoconf. 2002-12-12 20:17 Martin Pool * linuxdoc/distcc.sgml: Suggest using qualified compiler names rather than -b and -V options, because those options didn't work very well in earlier gcc versions. Based on an explanation from Alexandre Oliva. 2002-12-12 20:06 Martin Pool * Makefile.in, NEWS: Rename TARGET_ROOT variable to the more standard name of DESTDIR. (Alexandre Oliva) 2002-12-12 20:03 Martin Pool * doc/irc/openprojects-distcc-20020807.txt: Random notes about distcc 2002-12-12 19:45 Martin Pool * src/help.c: [Tests are more useful if they're actually run. :-/] * (dcc_show_version): Use intended syntax in --version output. 2002-12-12 19:41 Martin Pool * test/testdistcc.py, src/help.c: (dcc_show_version, VersionOption_Case): --version now shows default port. 2002-12-12 19:38 Martin Pool * doc/flood.txt: flood.txt: Notes on network performance. 2002-12-12 19:38 Martin Pool * src/: distcc.c, distcc.h, dopt.c, hosts.c: Put default port into DISTCC_DEFAULT_PORT preprocessor constant, rather than copying it everywhere. 2002-12-12 19:34 Martin Pool * aclocal.m4: Rerun autoconf. 2002-12-12 19:33 Martin Pool * TODO: TODO: New file. Many random notes about things to do, moved from the user manual. 2002-12-12 19:31 Martin Pool * src/distcc.c, src/dopt.c, src/hosts.c, test/testdistcc.py, NEWS: * Change default port from 4200 to IANA-assigned standard for distcc service "3632". 2002-12-12 19:30 Martin Pool * analog/.cvsignore: Ignore generated files. 2002-12-12 19:29 Martin Pool * analog/: httplog.py, print_referers: httplog.py: New file to parse Apache logs. * print_referers: Change to using httplog.py library. 2002-12-12 19:19 Martin Pool * analog/day.gnuplot: day.gnuplot: New gnuplot file to plot daily traffic. 2002-12-12 18:59 Martin Pool * linuxdoc/distcc.sgml: (Author): Rephrase. 2002-12-12 18:56 Martin Pool * linuxdoc/distcc.sgml: Move "Reporting Bugs" and "Test Suite" sections into the introduction chapter. 2002-12-12 18:43 Martin Pool * linuxdoc/distcc.sgml: Remove empty tag. 2002-12-12 18:41 Martin Pool * NEWS: Only show non-maintainer names in the NEWS file, as in Subversion. 2002-12-12 18:38 Martin Pool * linuxdoc/distcc.sgml, NEWS: Move "Bugs" chapter into TODO. (Martin Pool) 2002-12-12 18:36 Martin Pool * linuxdoc/distcc.sgml: Remove "results" chapter, because this information is more appropriate for the web site. * Start moving bugs/features into TODO. 2002-12-12 18:12 Martin Pool * NEWS: [no log message] 2002-12-12 18:09 Martin Pool * linuxdoc/distcc.sgml: (distcc Compatibility): Remove section about MOC, because we have nothing at the moment to say. Add a new section describing the complex situation for -MD with gcc 2.95 and 3.2. 2002-12-12 17:55 Martin Pool * Makefile.in: (dist_files): Add TODO to distribution. 2002-12-12 17:39 Martin Pool * linuxdoc/distcc.sgml: (Bugs): Need a performance regression suite. * (Bugs): Perhaps need to migrate the manual from Linuxdoc to Docbook Lite. 2002-12-12 16:53 Martin Pool * analog/traffic.py: traffic.py: Add a new first command line parameter, either 'day' or 'week' to set grouping quantum. 2002-12-12 15:47 Martin Pool * src/lock.c: lock.c: Add quotation. 2002-12-06 11:32 Martin Pool * analog/traffic.gnuplot: traffic.gnuplot: Use log y scale. 2002-12-06 11:29 Martin Pool * analog/traffic.py: traffic.py: New utility to produce weekly counts of downloads and accesses. 2002-12-06 11:07 Martin Pool * analog/traffic.gnuplot: Simple plot of traffic 2002-12-06 10:19 Martin Pool * linuxdoc/distcc.sgml, NEWS: Remove "Results" chapter from manual: there are now many more detailed results on the web site, and this information is better suited to storage there, because it will be updated on a different cycle. End-users don't really need to have it in their reference. 2002-12-05 15:22 Martin Pool * doc/release-names.txt: [no log message] 2002-12-05 14:07 Martin Pool * doc/interceptor.txt: Notes on using an external interceptor 2002-12-05 10:02 Martin Pool * src/srvnet.c: srvnet.c: (dcc_log_clientname): Clearer error messages for failure to look up client hostname. 2002-12-05 10:01 Martin Pool * NEWS: [no log message] 2002-11-28 04:48 Martin Pool * linuxdoc/distcc.sgml: We now use ComfyChair not PyUnit 2002-11-28 04:45 Martin Pool * NEWS: Add section on how to report bugs well 2002-11-28 04:40 Martin Pool * linuxdoc/distcc.sgml: Add section on how to report bugs well 2002-11-28 04:20 Martin Pool * src/dopt.c: Say that --no-fork is for debugging ONLY 2002-11-23 04:35 Martin Pool * linuxdoc/distcc.sgml: Add TODO Bump version to 0.14 2002-11-22 19:00 Martin Pool * NEWS: Add note about -MF 2002-11-21 18:53 Martin Pool * src/cpp.c: Doc 2002-11-21 18:50 Martin Pool * src/cpp.c: Doc 2002-11-21 18:46 Martin Pool * NEWS, src/cpp.c, src/strip.c, src/strip.h: Run the preprocessor with output sent to stdout and redirected to a file, rather than by using the -o option. This should fix some compilers that can't handle "-E -o". It may improve gcc behaviour with -MD, but because gcc behaviour has changed over time it may not be a complete fix. 2002-11-21 18:38 Martin Pool * test/testdistcc.py: Doc 2002-11-21 18:24 Martin Pool * Makefile.in, src/cpp.c, src/cpp.h, src/distcc.c: dcc_cpp_maybe: Split code to run preprocessor into its own file. 2002-11-21 18:09 Martin Pool * test/testdistcc.py: DaemonBadPort_Case: avoid polluting system log files. 2002-11-21 18:06 Martin Pool * src/distcc.c: Doc 2002-11-21 18:02 Martin Pool * Makefile.in: Remove obsolete/uncalled dist-python target Move comfychair into test/ 2002-11-21 17:21 Martin Pool * analog/.cvsignore: Ignore generated refererlog 2002-11-21 17:16 Martin Pool * test/: .cvsignore, comfychair.py: Move comfychair into test/ 2002-11-21 17:06 Martin Pool * cases/empty.i: empty .i file 2002-11-21 17:05 Martin Pool * DEPENDENCIES: popt is now included in package 2002-11-21 17:02 Martin Pool * src/serve.c: Doc 2002-11-21 12:04 Martin Pool * doc/to-test.txt: Add list of trees that would be interesting to test 2002-11-20 11:47 Martin Pool * NEWS, configure, configure.ac, src/config.h.in: Fix autoconf detection of resolv.h on Solaris. (Dimitri Papadopoulos) 2002-11-20 11:30 Martin Pool * NEWS: Add badly-behaved compiler drop-in for use in testing. 2002-11-19 14:23 Martin Pool * test/badcc: Add badly-behaved compiler drop-in for use in testing. 2002-11-19 13:11 Martin Pool * NEWS, src/exec.c: * Fix waitpid() takes three options. Required for Irix. (Michael Santy) 2002-11-19 12:49 Martin Pool * Makefile.in: Remove obsolete comment. 2002-11-19 12:42 Martin Pool * Makefile.in: OK, now we use install-sh 2002-11-19 09:09 Martin Pool * analog/print_referers: Better line parser 2002-11-19 08:57 Martin Pool * analog/distcc.analog: Show more search words. 2002-11-19 08:54 Martin Pool * Makefile.in: Copy new EmptySource.py file into distribution 2002-11-19 08:52 Martin Pool * test/.cvsignore: Ignore .pyc files. 2002-11-19 08:48 Martin Pool * Makefile.in, NEWS, configure, configure.ac: Use the correct autoconf macros to detect whether install(1) is available and working, and if not, fall back to using the included install-sh script. This should fix "make install" on Solaris. (Mike Santy, Martin Pool) 2002-11-19 07:45 Martin Pool * test/testdistcc.py: todo 2002-11-18 13:05 Martin Pool * analog/report/.cvsignore: Ignore built files 2002-11-18 13:03 Martin Pool * NEWS, test/EmptySource.py, test/testdistcc.py: Add test case for transmission of a zero-byte file. 2002-11-18 13:01 Martin Pool * configure: autoconf 2002-11-16 12:27 Martin Pool * analog/images/: analogo.png, barc1.png, barc16.png, barc2.png, barc32.png, barc4.png, barc8.png, html2.png: Add analog images 2002-11-16 12:24 Martin Pool * analog/print_referers: Python script to print web referers 2002-11-16 12:22 Martin Pool * analog/distcc.analog: Get ready to include bar images in cvs 2002-11-16 12:19 Martin Pool * configure.ac: Bump version to 0.16cvs 2002-11-16 12:18 Martin Pool * Makefile.in: Include Scenarios page 2002-11-16 11:13 Martin Pool * OLDNEWS, NEWS: roll over news 2002-11-16 09:57 Martin Pool * configure, configure.ac: Bump version to 0.14 2002-11-15 18:10 Martin Pool * contrib/distccd-init: distccd Debian init.d script contributed by Jason Thomas. (Debian #161136) 2002-11-15 18:07 Martin Pool * NEWS: reformat only 2002-11-15 18:07 Martin Pool * NEWS: distccd Debian init.d script contributed by Jason Thomas. (Debian #161136) 2002-11-15 18:06 Martin Pool * Makefile.in: Include contrib files in distribution. 2002-11-15 10:06 Martin Pool * src/trace.h: Doc 2002-11-14 14:09 Martin Pool * NEWS: Make sure PreprocessPlainText_Case runs in the right directory. 2002-11-14 14:09 Martin Pool * test/testdistcc.py: TODO (thanks Oscar) 2002-11-14 14:00 Martin Pool * test/testdistcc.py: Make sure PreprocessPlainText_Case runs in the right directory. 2002-11-14 12:58 Martin Pool * Makefile.in: Make sure that if Latte processing fails, the output file is removed Remove obsolete maintainer-clean dependencies 2002-11-13 08:56 Martin Pool * configure, configure.ac, src/config.h.in, src/exec.c: Handle machines without wait4 by using waitpid instead. 2002-11-13 08:48 Martin Pool * configure.ac, NEWS: Test for wait4 and wait3, which are missing on IRIX (Mike Santy) 2002-11-13 08:46 Martin Pool * src/serve.c: Fix parameter type (suggestion from Dimitri Papadopoulos) 2002-11-13 07:47 Martin Pool * configure: autoconf 2002-11-13 07:44 Martin Pool * Makefile.in, NEWS: Fix silly bug that caused HTML documentation to be missing from the tarball 2002-11-13 07:43 Martin Pool * configure.ac: Bump version to 0.14 2002-11-13 07:14 Martin Pool * NEWS: Bump version to 0.14 2002-11-13 07:11 Martin Pool * src/distcc.c: Take lock on localhost only when compiling locally, not for all compilations. 2002-11-13 07:03 Martin Pool * OLDNEWS, NEWS: Roll over news 2002-11-13 07:01 Martin Pool * src/where.c: Remove dead code. 2002-11-13 06:02 Martin Pool * configure.ac: Bump version to 0.13.1cvs 2002-11-12 18:40 Martin Pool * README: Update README 2002-11-12 18:38 Martin Pool * configure, configure.ac: Prepare for 0.13 release 2002-11-12 18:34 Martin Pool * NEWS: Prepare for release. 2002-11-12 18:25 Martin Pool * test/testdistcc.py: More ComfyChair merges. 2002-11-12 18:24 Martin Pool * configure: autoconf 2002-11-12 18:23 Martin Pool * configure.ac: Remove --with-extra-includes and --with-extra-libs, because they just don't work well with autoconf, since they can only be specified once and repeated appearances will cause only the last to have effect. The official way for autoconf 2.5 is to set CPPFLAGS and LDFLAGS. 2002-11-12 18:21 Martin Pool * configure.ac: Change --with-included-popt if not specified, use if necessary if specified, then always (or never) use it 2002-11-12 18:20 Martin Pool * NEWS: If popt is missing and not specified, get it 2002-11-12 18:14 Martin Pool * configure.ac: If popt is missing and not specified, get it 2002-11-12 18:11 Martin Pool * Makefile.in: doh 2002-11-12 18:10 Martin Pool * Makefile.in: Clean popt, binaries, and testtmp from "clean" target. 2002-11-12 17:53 Martin Pool * NEWS: Merge tpot's comfychair patch 2002-11-12 17:47 Martin Pool * NEWS, configure, configure.ac, src/config.h.in: Add config options for included popt 2002-11-12 17:39 Martin Pool * configure.ac: Add --with-included-popt option 2002-11-12 17:37 Martin Pool * Makefile.in: Make 'all' the default 2002-11-12 17:36 Martin Pool * Makefile.in: Include other necessary files in distribution 2002-11-12 17:33 Martin Pool * Makefile.in: Clean up some Makefile targets Remove GNU makeisms Include popt in tarball 2002-11-12 17:17 Martin Pool * test/testdistcc.py: Make MissingCompiler_Case actually test what it's meant to test. Doc. 2002-11-12 17:11 Martin Pool * NEWS: Update news 2002-11-12 17:08 Martin Pool * linuxdoc/distcc.sgml: Add new exit codes. Bump version to 0.13. 2002-11-12 17:03 Martin Pool * src/: exitcode.h, exec.c: Add EXIT_COMPILER_MISSING 2002-11-12 16:28 Martin Pool * Makefile.in: Doc 2002-11-12 08:16 Martin Pool * aclocal.m4, configure, configure.ac, src/config.h.in, src/srvnet.c: Make inclusion of arpa/nameser.h and resolv.h conditional 2002-11-08 18:51 Martin Pool * src/distcc.c: Fix prototypes 2002-11-08 18:51 Martin Pool * src/exec.c: Doc 2002-11-08 18:50 Martin Pool * src/distcc.c: On the client, we should take locks only when compiling locally. cpp is cheap enough that it doesn't really need to be taken into account. 2002-11-08 18:49 Martin Pool * src/exec.c: Do not take a lock on localhost when spawning commands. This is intended to get rid of a race condition that will sometimes deadlock the client: Two clients, P1 and P2, are both trying to compile on remote machine R. Therefore, they both need to get a lock on localhost to run cpp, and on R. If they acquire the locks in the opposite order, then they will block holding locks, and deadlock. The ordering is indeterminate because the cpp lock is acquired from the separate process forked to run cpp. This was not evident in 0.12 and earlier because there was no limit on the number of locks that could be taken. On the server side, there are better places to regulate process load than here. We should instead hold off on accepting connections until we have space to handle them. On the client, we should take locks only when compiling locally. cpp is cheap enough that it doesn't really need to be taken into account. 2002-11-08 17:39 Martin Pool * cases/: cpp-set-path.c, foo.h, hello.c: Add small files for exploring gcc behaviour 2002-11-05 05:47 Martin Pool * src/exec.c: BSD needs signal.h. Thanks to Ajay Agrawalla. 2002-11-01 19:12 Martin Pool * test/testdistcc.py: MissingCompiler_Case: Fix function name 2002-11-01 19:11 Martin Pool * src/serve.c: dcc_accept_job: Fix little prototype consistency mistake 2002-11-01 19:08 Martin Pool * test/testdistcc.py: Doc 2002-11-01 19:08 Martin Pool * src/serve.c: Drop support for using fifos on the server. Run compilers in their own process group, and kill them if the daemon is killed. Copy server's output into the error log, and try to always send it back to the client even if something goes wrong. 2002-11-01 19:06 Martin Pool * src/: io.c, rpc.c: Use error codes more consistently 2002-11-01 19:06 Martin Pool * src/exitcode.h: Add EXIT_TRUNCATED and EXIT_PROTOCOL_ERROR 2002-11-01 19:05 Martin Pool * src/: exec.c, exec.h: Add new utilities: dcc_reset_signal, and dcc_setpgid Doc 2002-11-01 19:03 Martin Pool * src/dparent.c: Better doc and messages 2002-11-01 19:02 Martin Pool * src/distcc.c: If cpp returns an error, don't bother trying to run the compilation locally. Upgrade notice -> warning on failure to distribute. Only show warning or higher on the client by default. Don't abruptly close the connection if the remote compiler fails. 2002-11-01 18:58 Martin Pool * src/bulk.c: Tidyup 2002-11-01 18:58 Martin Pool * README: Mention DISTCC_LOG and possible future ssh support 2002-11-01 18:57 Martin Pool * NEWS: Temporarily remove limit on number of local tasks, because this can cause a deadlock. Client does not abruptly drop network connection on compiler failure but rather reads the 0-byte object file token. (Martin Pool) Rework logger library to allow multiple logger callbacks to be active at once. This is used for the server, which can write to its own log files and also send a copy of messages to a buffer to be sent to the client. 2002-11-01 18:53 Martin Pool * samples/: bad.c, badcpp.c, hello.c: Add small sample source files 2002-11-01 17:54 Martin Pool * test/testdistcc.py: * Allow distcc's version to be set to something like "0.13cvs-nofifo". * Add test for handling of a compiler missing from the server. 2002-11-01 17:51 Martin Pool * src/distcc.c, src/dparent.c, src/exec.c, src/serve.c, src/where.c, NEWS: * Remove support for feeding the compiler from a fifo. The gain from using fifos does not seem to justify the maintenance burden. (Martin Pool) - This makes the behaviour more consistent, because some platforms (Cygwin) or filesystems (NFS, strangely) can't use fifos. It removes a code path and a slightly complex autodetection. - Using fifos makes some potential scheduling improvements hard: the server can't make good decisions about how many tasks to run, because each one will only use a fraction of the CPU. The client cannot serialize file transmission, which would probably be desirable. - Using fifos makes reliably handling compiler failures slightly harder: the compiler may crash or exit at any time, which will in turn cause the server to hang if it later tries to open or write to the fifo. In previous versions, distcc tried to handle this by catching SIGCHLD when the child terminated, and aborting the operation, but I am not sure that the method is completely reliable. * Use return codes more consistently * Change log levels slightly to try to make sure nothing is emitted for successful compilation or even only compiler errors. * Detached daemon now ignores hangup signal. * Follow Unix convention of returning 128+SIGNAL if the compiler exits with a signal. (Martin Pool) * Write server error messages to a log file and send them back to the client on completion. 2002-11-01 17:25 Martin Pool * src/daemon.c: Doc 2002-10-31 13:40 Martin Pool * NEWS: More news 2002-10-31 13:28 Martin Pool * Makefile.in: Add TARGET_ROOT Makefile variable for installation, when building binary packages. 2002-10-31 13:15 Martin Pool * NEWS, src/daemon.c, src/exec.c, src/serve.c: Log messages on the server of severity "warning" or higher are captured and sent back to the client. Do not use atexit() to clean up temporary files, because this can cause havoc if it's ever called from a child process that forked but failed to exec. 2002-10-31 13:11 Martin Pool * src/tempfile.c: Show trace message when temporary files are deleted 2002-10-31 13:11 Martin Pool * src/: trace.c, trace.h, distcc.c: Change the logger callback system so that multiple loggers may be attached at any time. 2002-10-31 12:35 Martin Pool * src/exec.c: Add trace message for EINTR failure of wait4, because we don't really expect it to happen. Doc. 2002-10-31 12:34 Martin Pool * src/distcc.h: Define true and false for clarity 2002-10-31 12:33 Martin Pool * Makefile.in: Include autogen.sh in dist 2002-10-31 12:32 Martin Pool * configure.ac, src/distcc.c: Doc 2002-10-31 12:32 Martin Pool * news.emacs: No tabs please 2002-10-21 20:33 Martin Pool * analog/distcc.analog: Exclude distcc.samba.org from referrer calculations 2002-10-18 16:45 Martin Pool * DEPENDENCIES: Add URL for popt 2002-10-18 11:58 Martin Pool * NEWS: Note Makefile fixes 2002-10-18 11:57 Martin Pool * configure, configure.ac: Don't use -MD because there seems not to be a portable way to include the results in the Makefile 2002-10-18 11:55 Martin Pool * Makefile.in: Check that programs have been built before trying to install them 2002-10-18 11:53 Martin Pool * Makefile.in: Put back pkgdoc_DOCS, which somehow got lost Distribute pkgdocs as well 2002-10-18 11:46 Martin Pool * aclocal.m4, configure: Run autoconf 2002-10-18 11:45 Martin Pool * popt/: findme.c, findme.h, popt.c, popt.h, poptconfig.c, popthelp.c, poptint.h, poptparse.c, system.h: Import popt-1.7 2002-10-18 11:41 Martin Pool * README.popt: Start adding included popt 2002-10-18 11:38 Martin Pool * README.packaging, Makefile.in: Add note to packagers 2002-10-18 11:29 Martin Pool * Makefile.in, configure.ac: Remove reference to src/Makefile.in 2002-10-18 11:29 Martin Pool * NEWS, src/Makefile.in: Get rid of Makefile recursion; build all source from the toplevel Makefile 2002-10-18 11:22 Martin Pool * Makefile.in, .cvsignore: Get rid of Makefile recursion; build all source from the toplevel Makefile Binaries are now deposited into the top-level directory Drop obsolete pyunit rules 2002-10-18 10:36 Martin Pool * src/distcc.c: Test that the .i file exists before trying to transmit it to the server. Doc. 2002-10-17 18:33 Martin Pool * src/arg.c: Better message for object or output files 2002-10-17 18:32 Martin Pool * NEWS, test/testdistcc.py: Add test case for invocations like "distcc -c test1.c test2.c". 2002-10-17 18:22 Martin Pool * test/testdistcc.py: Doc 2002-10-17 18:21 Martin Pool * NEWS, test/testdistcc.py: Add test case for preprocessing non-C text, as is done by (for example) xrdb. Remove done TODOs 2002-10-17 18:07 Martin Pool * test/testdistcc.py: Add test case for #error directive 2002-10-17 13:40 Martin Pool * NEWS, linuxdoc/distcc.sgml: More Gentoo notes from Ernesto 2002-10-17 13:29 Martin Pool * linuxdoc/distcc.sgml, NEWS: Add Gentoo documentation from Dean Bailey 2002-10-16 11:00 Martin Pool * Makefile.in: Don't use "make -C" because some non-GNU makes don't support -C. Instead, explicitly cd, and do it in a way that better allows parallelism. 2002-10-11 11:45 Martin Pool * NEWS, test/testdistcc.py: Split out tests for implied compiler name into their own class 2002-10-11 11:40 Martin Pool * doc/lock-deadlock.txt: Doc deadlock observed in 0.13cvs 2002-10-10 12:56 Martin Pool * Makefile.in: Include where.h 2002-10-10 12:56 Martin Pool * src/Makefile.in: Cope when there are no .d files 2002-10-10 12:52 Martin Pool * Makefile.in: Clean up the dist targets; include new patches 2002-10-10 12:33 Martin Pool * packaging/SuSE/init.d/distcc, NEWS: SuSE init.d script from Brandon Forehand 2002-10-10 11:47 Martin Pool * patches/: colorgcc, distcc-hostlist.diff: Patches from Charles Samuels to store hosts in a file, and to run distcc through colorcc. 2002-10-10 10:54 Martin Pool * src/distcc.c: Add FIXME 2002-10-10 00:33 Martin Pool * src/: distcc.c, distcc.h, exec.c, exec.h, lock.h, serve.c, where.c, where.h: In lock debug messages, show whether we're running the compiler or the preprocessor. 2002-10-07 23:20 Martin Pool * NEWS: Doc 2002-10-07 23:13 Martin Pool * src/where.c: Add trace 2002-10-07 23:03 Martin Pool * src/lock.c: Fix parameters for fcntl locks 2002-10-07 23:02 Martin Pool * src/where.c: Add trace Use pid+ppid as a seed for randomly choosing a host when we can't find a free one. 2002-10-07 22:54 Martin Pool * src/: Makefile.in, distcc.c, distcc.h, hosts.h, lock.c, lock.h, where.c: Add code to wait for a blocking lock if no host is immediately free. 2002-10-07 22:10 Martin Pool * NEWS, src/dparent.c: When the parent is terminated, don't kill its process group. Allow children to finish in their own time. 2002-10-07 22:08 Martin Pool * src/Makefile.in: Include generated dependencies 2002-10-07 18:17 Martin Pool * test/testdistcc.py: NoDetachDaemon_Case: Fix bug in arguments for starting --no-detach daemon Correctly wait for daemon after signalling Fix log message 2002-10-07 15:07 Martin Pool * test/testdistcc.py: Move code for explaining failures into test case Move setUp/runTest/tearDown structure into framework runCmdNoWait(): take a list Add test case for --no-detach (broken) 2002-10-07 14:37 Martin Pool * NEWS: Nicer handling of ^C while running tests: print "INTERRUPT" and terminate the whole test 2002-10-07 14:36 Martin Pool * test/testdistcc.py: New runCmdNoWait function needs argument as string, not list 2002-10-07 14:28 Martin Pool * test/testdistcc.py: When killing daemon, ping every 200ms to try to notice faster that it's finished. Clean up some function names. Add unused DetachDaemon_Case 2002-10-07 13:57 Martin Pool * NEWS, src/dopt.c, src/dparent.c, src/opt.h: Add --no-detach option 2002-10-07 13:52 Martin Pool * NEWS, src/h_hosts.c, src/hosts.c, src/hosts.h, src/lock.c, src/where.c, test/testdistcc.py: Add per-host limit on number of compile slots to dcc_hostdef structure. Not used yet, and always set to 4. 2002-10-07 13:06 Martin Pool * NEWS, OLDNEWS, configure, configure.ac: Advance version to 0.13cvs 2002-10-07 12:39 Martin Pool * NEWS, aclocal.m4, configure, configure.ac: Bump version to 0.12 2002-10-07 12:34 Martin Pool * src/where.c: Doc 2002-10-07 12:29 Martin Pool * linuxdoc/distcc.sgml: Bump to version 0.12 2002-10-07 12:16 Martin Pool * linuxdoc/distcc.sgml: Note on adaptive scheduling 2002-10-07 11:35 Martin Pool * NEWS, src/clinet.c, src/clinet.h, src/distcc.c, src/exec.c, src/exec.h, src/hosts.c, src/hosts.h, src/lock.c, src/where.c: Roll back multi-A-record patch: seems to break the test suite, and on further consideration I think just SRV records might be cleaner. 2002-10-07 11:19 Martin Pool * test/testdistcc.py: Doc 2002-10-07 11:15 Martin Pool * src/hosts.c: Doc about handling host list. 2002-10-07 11:04 Martin Pool * linuxdoc/distcc.sgml: Add note about performance test suite. 2002-10-06 21:37 Martin Pool * aclocal.m4, configure, configure.ac: Bump version to 0.12cvs 2002-10-04 11:53 Martin Pool * NEWS: foo 2002-10-02 15:03 Martin Pool * src/arg.c: Add fixme 2002-10-02 14:55 Martin Pool * src/distcc.c: Add fixme 2002-10-02 13:03 Martin Pool * linuxdoc/distcc.sgml: Note about starting the daemon 2002-10-02 12:47 Martin Pool * doc/irc/: slashnet-distcc-20020919.txt, slashnet-distcc-20021002.txt: Check in IRC logs 2002-09-30 23:06 Martin Pool * src/h_hosts.c: Fix extra headers to allow for host definitions that now include an IP address. 2002-09-30 23:01 Martin Pool * NEWS, configure, src/clinet.c, src/clinet.h, src/distcc.c, src/exec.c, src/exec.h, src/hosts.c, src/hosts.h, src/lock.c, src/where.c: Handle DNS A records that give multiple IP addresses for a host by distributing work across all the addresses. This should allow you to create "linux.build.squick.net" that resolves to all the relevant machines. Patch from Andreas Granig, but seems to break some tests. 2002-09-30 16:06 Martin Pool * NEWS, src/serve.c: wait4() on Solaris can't handle a pid of -1, which means "any child" on Linux and BSD. Use pid of 0 instead to collect any children from the same process group. (Kevin Bailey) 2002-09-30 15:44 Martin Pool * NEWS, src/arg.c, test/testdistcc.py: Add tests for "gcc -S -o - foo.c" 2002-09-30 14:04 Martin Pool * linuxdoc/distcc.sgml: Update version to 0.11 2002-09-30 14:00 Martin Pool * linuxdoc/distcc.sgml: Remove done TODO 2002-09-30 13:46 Martin Pool * Makefile.in: Add roadmap 2002-09-27 14:50 Martin Pool * NEWS, src/arg.c: Handle "gcc -S foo.c -o -", which ought to write assembly to stdout. 2002-09-27 14:20 Martin Pool * src/where.c: Add fixme 2002-09-27 14:03 Martin Pool * Makefile.in: Add results page 2002-09-27 13:55 Martin Pool * survey.txt: Add qn about distcc version 2002-09-26 16:19 Martin Pool * NEWS, OLDNEWS: Roll over NEWS 2002-09-25 16:36 Martin Pool * src/implicit.c: Doc 2002-09-25 11:54 Martin Pool * NEWS, configure, configure.ac: Bump version to 0.11 2002-09-25 11:43 Martin Pool * Makefile.in, patches/README.patches, patches/granig_distcc_multi-A-record.diff: Add patches/README, and Andrea Granig's multi-A-record patch 2002-09-25 11:39 Martin Pool * Makefile.in: Include patches in distributed tarball 2002-09-25 11:37 Martin Pool * linuxdoc/distcc.sgml: GNU Info can't handle having two sections with the same heading 2002-09-24 18:18 Martin Pool * NEWS, src/strip.c: Fix (non-exploitable) buffer overrun bug. 2002-09-23 22:47 Martin Pool * NEWS: Update news 2002-09-23 22:31 Martin Pool * src/strip.c: List -MD, etc, separately, because we don't know how other -M options will be parsed in the future. 2002-09-23 22:29 Martin Pool * src/strip.c: Strip -MF -MT -MQ options that are followed by a filename 2002-09-23 22:24 Martin Pool * src/arg.c: Add support for gcc-3.2 new -M options (-MG, etc) 2002-09-23 15:25 Martin Pool * linuxdoc/distcc.sgml: Update todo list. Add section discussing ccache and distcc 2002-09-23 15:17 Martin Pool * patches/joerg-proof-build-01.diff: Patch from Joerg to do "proof" by compiling a file on all machines and checking that they're the same. 2002-09-23 14:56 Martin Pool * NEWS, src/daemon.c: Do not object to running as group 0, because on BSD this is "wheel" and many non-privileged users are in it. 2002-09-23 12:46 Martin Pool * doc/scheduling.txt: More notes 2002-09-20 12:37 Martin Pool * src/arg.c: Doc 2002-09-20 11:39 Martin Pool * NEWS, src/strip.c, test/testdistcc.py: Strip more local-only options Add more tests for argument stripping dcc_strip_local_args: trace result on completion 2002-09-20 10:30 Martin Pool * test/testdistcc.py: Doc 2002-09-20 10:14 Martin Pool * src/arg.c: Doc. 2002-09-19 00:33 Martin Pool * src/bulk.c: Mode on received files should be 0666&~umask 2002-09-19 00:06 Martin Pool * src/serve.c: Doc 2002-09-18 22:58 Martin Pool * src/serve.c: Doc 2002-09-18 21:36 Martin Pool * NEWS, src/bulk.c, src/daemon.c, test/testdistcc.py: Make permissions on output files obey umask, etc. Add test case for this. Add option to test case driver to run particular specified tests. 2002-09-18 16:57 Martin Pool * src/distcc.c, src/h_scanargs.c, src/implicit.c, src/implicit.h, test/testdistcc.py: Rename dcc_add_implicit to dcc_find_compiler Remove "distcc hello.o -o hello" case -- too hard at the moment. 2002-09-18 16:47 Martin Pool * src/: distcc.c, h_scanargs.c, implicit.c, implicit.h: Reduce too-long function name 2002-09-18 16:42 Martin Pool * src/implicit.c: Doc. 2002-09-18 16:39 Martin Pool * test/testdistcc.py: Add implicit linker test: "distcc testtmp.o -o testtmp" 2002-09-18 16:36 Martin Pool * test/testdistcc.py: Fix tests for -MD that were giving a false pass Add basic tests for implict compiler names. 2002-09-18 16:33 Martin Pool * NEWS, src/Makefile.in, src/h_scanargs.c, test/testdistcc.py: Add more test cases for implicit compiler name handling. Extend h_scanargs to exercise this. 2002-09-18 16:32 Martin Pool * src/arg.c: Fix doc. 2002-09-18 13:29 Martin Pool * NEWS: Release name 2002-09-18 10:45 Martin Pool * doc/results.txt: Add results on building inside VMWare 2002-09-17 18:49 Martin Pool * src/io.c: Doc. 2002-09-17 13:59 Martin Pool * src/srvnet.c: resolv.h might need sys/types.h on BSD? 2002-09-17 13:58 Martin Pool * src/implicit.c: Might need sys/types.h on BSD? 2002-09-16 18:14 Martin Pool * src/clinet.c: Fix docs 2002-09-16 11:02 Martin Pool * Makefile.in: Upload "tested" page 2002-09-16 11:01 Martin Pool * README: Update readme text 2002-09-14 19:02 Martin Pool * src/srvnet.c: Cope without hstrerror(). Thanks to Richard Zidlicky 2002-09-14 18:59 Martin Pool * configure, configure.ac, src/config.h.in: Check for presence of hstrerror function. Richard Zidlicky reports that it is missing in libc5 2002-09-14 18:54 Martin Pool * src/srvnet.c: Cope without socklen_t. Thanks to Richard Zidlicky 2002-09-14 18:53 Martin Pool * configure, configure.ac, src/config.h.in: Check for socklen_t 2002-09-14 18:46 Martin Pool * src/clinet.c, NEWS: Remove unnecessary sa_family_t cast. (Richard Zidlicky) 2002-09-14 13:35 Martin Pool * NEWS: Doc 2002-09-14 13:20 Martin Pool * NEWS, configure, configure.ac, src/config.h.in: More helpful message explaining that popt is needed if it is missing at build time. 2002-09-14 10:58 Martin Pool * configure.ac: Doc 2002-09-14 10:52 Martin Pool * src/dparent.c: Don't set cloexec() on the accept fd -- this seems to make it close after the first compiler runs. 2002-09-14 10:51 Martin Pool * NEWS, test/testdistcc.py: Create and use a separate TMPDIR for each test case. Also, rename subdirectories of testtmp 2002-09-14 10:46 Martin Pool * src/serve.c: Doc. 2002-09-14 10:38 Martin Pool * src/serve.c: Doc. 2002-09-14 10:11 Martin Pool * src/: dparent.c, exec.c: Don't close all fds when starting the compiler, because this gets a bit confusing with logs and lock files. However, do set CLOEXEC on the network fds, because the compiler should never be writing to them. 2002-09-14 09:52 Martin Pool * src/lock.c, NEWS: Fix leakage of fds when trying to get a lock. 2002-09-14 09:51 Martin Pool * src/util.c: Doc. 2002-09-14 09:50 Martin Pool * src/exec.c: Move lock prototypes to lock.h 2002-09-14 09:48 Martin Pool * src/: lock.h, distcc.h: Rearrange prototypes 2002-09-14 09:47 Martin Pool * Makefile.in, src/Makefile.in, src/exec.c, src/hosts.c, src/lock.c, src/lock.h, src/where.c: Split locking code out into a separate file so that it can be used by the server as well 2002-09-14 09:46 Martin Pool * test/testdistcc.py: Run daemon with --verbose 2002-09-14 09:33 Martin Pool * src/exec.c: dcc_execvp doesn't return 2002-09-14 09:32 Martin Pool * NEWS: Whenever a command by either the client or the server, it counts towards the load on that machine. This covers undistributed commands, cpp, and compilation. 2002-09-14 09:32 Martin Pool * src/distcc.c: dcc_compile_local: Don't need to take a lock as a special case; this is always done now 2002-09-14 09:30 Martin Pool * src/exec.c: dcc_inside_child: Take a lock on localhost for all executed commands 2002-09-14 09:08 Martin Pool * test/testdistcc.py: Doc 2002-09-14 08:42 Martin Pool * src/serve.c: Doc 2002-09-14 08:41 Martin Pool * src/exec.c, NEWS: dcc_inside_child: new function to handle setup and execution of children. Now checks return codes, and makes sure (very important!) that we can never return above the fork() call. 2002-09-14 08:33 Martin Pool * src/exec.c: dcc_redirect_fds: If any redirection fails, return that error. 2002-09-14 08:32 Martin Pool * src/util.c: Needs exitcode.h 2002-09-14 08:31 Martin Pool * src/util.c: dcc_redirect_fd: Return EXIT_IO_ERROR not -1 for error 2002-09-14 08:30 Martin Pool * src/util.c: dcc_redirect_fd: Remove calls to rs_fatal() in favour of returning an error. 2002-09-14 08:28 Martin Pool * src/tempfile.c: Doc 2002-09-14 08:26 Martin Pool * OLDNEWS, NEWS: Roll over NEWS 2002-09-14 08:25 Martin Pool * src/io.c: Failure to write should be an error, but not fatal. We might want to do something to make sure the process unwinds properly. 2002-09-14 08:23 Martin Pool * src/serve.c: Doc 2002-09-13 17:52 Martin Pool * linuxdoc/distcc.sgml: Update libtool situation. 2002-09-13 15:40 Martin Pool * doc/ssh-notes.txt: Back-of-envelope calculations on using SSH. 2002-09-13 13:08 Martin Pool * src/: arg.c: Doc. 2002-09-13 13:02 Martin Pool * src/arg.c: Doc. 2002-09-13 12:58 Martin Pool * src/serve.c: Doc. 2002-09-13 12:55 Martin Pool * src/serve.c: Remove done todo 2002-09-13 12:29 Martin Pool * Makefile.in: Remove done TODO 2002-09-13 12:28 Martin Pool * Makefile.in: Include new header file 2002-09-13 12:27 Martin Pool * configure, configure.ac: Bump version to 0.10.1 2002-09-13 12:24 Martin Pool * src/serve.c: Define W_EXITCODE with standard Unix meaning if it is missing. 2002-09-13 12:22 Martin Pool * src/: distcc.c, distcc.h, exec.c, exec.h, serve.c: Split headers, also fix fact that pid_t is in sys/types.h. 2002-09-13 12:20 Martin Pool * configure, configure.ac: Bump version to 0.10.1cvs 2002-09-12 21:38 Martin Pool * linuxdoc/distcc.sgml, src/distcc.c: Update for new syntax, 'distcc -c hello.c' 2002-09-12 21:28 Martin Pool * configure, configure.ac: Bump version to 0.10. 2002-09-12 21:20 Martin Pool * NEWS: Add release name. 2002-09-12 21:00 Martin Pool * NEWS: Strip emacs stuff. 2002-09-12 20:43 Martin Pool * NEWS, src/filename.c, test/testdistcc.py: It turns out that .s and .S files in fact cannot be assembled remotely, because they might use the gas '.include' pseudo op, which is resolved by the assembler and would end up reading something from the volunteer's disk. Thanks to Richard Zidlicky for pointing this out. 2002-09-12 20:15 Martin Pool * test/testdistcc.py: Doc. 2002-09-12 14:30 Martin Pool * src/: arg.c: Note about difficulties of included files in .s and .S. 2002-09-12 12:14 Martin Pool * test/testdistcc.py: Update regexp to handle new "cannot distribute" message format. 2002-09-12 11:20 Martin Pool * src/strip.c: Remove dumb overoptimization that mangled command lines 2002-09-12 11:17 Martin Pool * src/strip.c, NEWS: Strip -M* from remote command lines as well. 2002-09-12 11:13 Martin Pool * configure.ac: If using gcc, use -MMD for dependency files. 2002-09-12 11:03 Martin Pool * src/distcc.c, NEWS: If distribution fails, show the name of the server that we were trying to use. 2002-09-12 10:58 Martin Pool * src/implicit.c: Document design tradeoffs about implicit compiler names. 2002-09-12 10:34 Martin Pool * src/: distcc.c, distcc.h, hosts.c, implicit.c, implicit.h, where.c: Allow distcc to be directly used with the same syntax as a compiler: "distcc -c hello.c". At the moment, always calls "cc". 2002-09-11 17:19 Martin Pool * Makefile.in, NEWS, src/Makefile.in, src/arg.c, src/distcc.c, test/testdistcc.py: Allow distcc to be directly used with the same syntax as a compiler: "distcc -c hello.c". At the moment, always calls "cc". 2002-09-11 17:02 Martin Pool * src/: distcc.c, arg.c: Remove done todos. 2002-09-11 16:44 Martin Pool * NEWS, src/distcc.c, src/h_strip.c, src/strip.c, src/strip.h: Also strip -L arguments before passing across the network. There's no good reason why they should be on compilation lines, but it does happen in GNOME. 2002-09-11 16:26 Martin Pool * src/distcc.c: Strip -D and -I options before passing the command line across the network, for clarity (and perhaps a tiny performance improvement.) 2002-09-11 16:22 Martin Pool * NEWS: Strip -D and -I options before passing the command line across the network, for clarity (and perhaps a tiny performance improvement.) 2002-09-11 16:20 Martin Pool * NEWS, test/testdistcc.py: Add test case that uses -D on the compiler command line 2002-09-11 16:00 Martin Pool * test/testdistcc.py: Add test cases for scanning -Mfoo 2002-09-11 15:56 Martin Pool * test/testdistcc.py: Add test case for arg stripping 2002-09-11 15:37 Martin Pool * Makefile.in, src/.cvsignore, src/Makefile.in, src/h_strip.c, src/strip.c, src/strip.h, src/util.h: Add code to strip -D and -I from command lines before passing them, and test harness for same. 2002-09-11 13:08 Martin Pool * src/distcc.c: Doc 2002-09-11 12:43 Martin Pool * src/distcc.c: Doc from tpot 2002-09-09 22:44 Martin Pool * test/testdistcc.py, NEWS: Add a test for running 100 compilations simultaneously. 2002-09-09 18:56 Martin Pool * src/serve.c: Doc. 2002-09-09 18:31 Martin Pool * src/dopt.c: Doc. 2002-09-09 16:13 Martin Pool * src/bulk.c: Log info message giving length after receiving files. 2002-09-09 16:09 Martin Pool * src/arg.c: Fix docs. 2002-09-09 13:19 Martin Pool * NEWS, src/arg.c: Allow -MD and -MMD to be distributed, since the compiler will produce a little file locally. 2002-09-09 12:58 Martin Pool * test/testdistcc.py: Add todo 2002-09-09 11:23 Martin Pool * src/distcc.c, NEWS: Try to make sure to uncork client socket before closing if cpp fails, to work around Linux 2.2 bug that causes the socket to jam in FIN_WAIT1. 2002-09-09 10:34 Martin Pool * src/arg.c: Doc 2002-09-08 18:13 Martin Pool * NEWS, test/testdistcc.py: Test many simple compilations, in case there is an infrequent error. 2002-09-08 17:17 Martin Pool * test/testdistcc.py: Actually run CppError_Case 2002-09-08 17:15 Martin Pool * src/exec.c: Remove old doc. dcc_collect_child: Show pid returned from wait4, not input pid. Much better if called with -1. 2002-09-08 17:12 Martin Pool * src/serve.c: Factor out code for trapping child exit into new routine. 2002-09-08 17:08 Martin Pool * NEWS: update news 2002-09-08 17:08 Martin Pool * src/util.h: dcc_remove_if_exists: new function 2002-09-08 17:07 Martin Pool * src/serve.c: Remove pid variable which was causing trouble by not being initialized before the child exited. Instead, just wait(-1) to collect whatever child was started. 2002-09-08 17:03 Martin Pool * src/exec.c: When redirecting an fd in a new process, remove the file if it already exists. 2002-09-08 16:59 Martin Pool * src/tempfile.c: dcc_remove_if_exists: new common function 2002-09-08 16:56 Martin Pool * src/: util.h, exec.c: dcc_redirect_fd: Make name consistent. 2002-09-08 16:56 Martin Pool * src/util.c: dcc_redirect_fd: Make name consistent. Better error messages. 2002-09-08 15:54 Martin Pool * NEWS, src/distcc.c: If .o file is 0 bytes or not created on the server, do not create it on the client either. 2002-09-08 15:53 Martin Pool * NEWS, src/serve.c: Attempt to fix a race where the compiler process could exit without opening its input before we started writing to the FIFO. In that case, the daemon would hang forever waiting for the compiler to arrive. In the new code, SIGCHLD causes a longjmp to break out of trying to feed the compiler. 2002-09-08 15:25 Martin Pool * src/serve.c: Doc. 2002-09-08 15:01 Martin Pool * NEWS, src/serve.c: If the volunteer compiler exits without reading all of its input, return the compiler's own exit code across the network, rather than EXIT_DISTCC_FAILED. 2002-09-08 14:54 Martin Pool * src/serve.c: remove done todo 2002-09-08 14:48 Martin Pool * NEWS, test/testdistcc.py: Test compiler that succeeds without reading input. 2002-09-08 14:29 Martin Pool * NEWS, test/testdistcc.py: Test handling of a file that causes a preprocessor error. 2002-09-08 14:19 Martin Pool * Makefile.in: Don't upload Latte source. 2002-09-06 14:39 Martin Pool * src/distcc.c: Add fixmes. 2002-09-05 17:56 Martin Pool * src/zip.c: Doc. 2002-09-05 11:05 Martin Pool * test/testdistcc.py: todo 2002-09-05 10:07 Martin Pool * src/exec.c: Doc waitstatus requirements. 2002-09-04 16:14 Martin Pool * NEWS: Modified patch from Alexandre Oliva to handle "distcc -c -S testtmp.c". 2002-09-04 16:11 Martin Pool * test/testdistcc.py: Test case for "distcc -c -S testtmp.c", reported by Alexandre Oliva 2002-09-04 16:08 Martin Pool * src/arg.c: Modified patch from Alexandre Oliva to handle "distcc -c -S testtmp.c". 2002-09-04 15:53 Martin Pool * test/testdistcc.py: Test case for "distcc -c -S testtmp.c", reported by Alexandre Oliva 2002-09-04 13:48 Martin Pool * src/serve.c: Doc. 2002-09-04 13:46 Martin Pool * linuxdoc/distcc.sgml: Notes on getloadavg() 2002-09-04 12:59 Martin Pool * doc/lzo-notes.txt: Notes on LZO compression 2002-09-04 12:53 Martin Pool * src/srvnet.c: Use additional headers possibly required on Solaris. 2002-09-04 12:52 Martin Pool * src/config.h.in: Check for -lresolv 2002-09-04 12:51 Martin Pool * NEWS: Solaris portability fixes 2002-09-04 12:49 Martin Pool * configure: Look for -lresolv, needed on Solaris. http://docs.sun.com/?q=hstrerror&p=/doc/816-3322/6m9k32d1v&a=view Suggestion from Dimitri PAPADOPOULOS-ORFANOS. 2002-09-04 12:47 Martin Pool * analog/.cvsignore: Ignore downloaded logs 2002-09-04 12:40 Martin Pool * Makefile.in, src/Makefile.in: Solaris "install -d" can only create a single directory at a time. Suggestion from Dimitri PAPADOPOULOS-ORFANOS. 2002-09-04 12:38 Martin Pool * configure.ac: Look for -lresolv, needed on Solaris. http://docs.sun.com/?q=hstrerror&p=/doc/816-3322/6m9k32d1v&a=view Suggestion from Dimitri PAPADOPOULOS-ORFANOS. 2002-09-04 12:14 Martin Pool * src/distcc.c: Patch from Dimitri PAPADOPOULOS-ORFANOS to fix signedness warning. 2002-09-04 10:06 Martin Pool * linuxdoc/distcc.sgml: Note that server log messages stay on the server. 2002-09-03 18:13 Martin Pool * NEWS, OLDNEWS: Roll over NEWS 2002-09-03 18:12 Martin Pool * man/distccd.1: troff fix 2002-09-03 18:12 Martin Pool * man/distcc.1: Tiny troff fix 2002-09-03 18:09 Martin Pool * configure.ac: Set version to 0.10cvs 2002-09-03 18:02 Martin Pool * src/arg.c: Doc. 2002-09-03 18:00 Martin Pool * analog/distcc.analog: Turn on weekly report. Adjust floors. 2002-09-03 17:49 Martin Pool * Makefile.in: analog-download: Get archived log files 2002-09-03 15:45 Martin Pool * NEWS, configure, configure.ac: Bump version to 0.9 2002-09-03 14:03 Martin Pool * doc/results.txt: More results. 2002-09-03 14:02 Martin Pool * Makefile.in: Fix linuxdoc targets so that .ps and .info files don't get rebuilt if the .gz files are up-to-date. 2002-09-03 13:49 Martin Pool * Makefile.in: Doc. 2002-09-03 13:49 Martin Pool * Makefile.in: Change .gz rule to compress "in-place" 2002-09-03 13:48 Martin Pool * Makefile.in: Add new header files to list of things to distribute! 2002-09-03 13:40 Martin Pool * news.emacs: emacs stub to set up NEWS file. 2002-09-03 10:55 Martin Pool * linuxdoc/distcc.sgml: Split TODOs about load balancing out into their own section. Add nice suggestion from Oscar Esteban about allowing some jobs to be remotely queued. 2002-09-02 10:33 Martin Pool * linuxdoc/distcc.sgml: Add RFC for DNS SRV. 2002-09-02 10:32 Martin Pool * linuxdoc/distcc.sgml: More todo notes. 2002-09-02 09:21 Martin Pool * Makefile.in: Apache logs have moved on new samba.org machine 2002-09-02 09:17 Martin Pool * Makefile.in: Add analog-all target 2002-09-02 07:38 Martin Pool * src/distcc.c: Doc. 2002-09-02 07:16 Martin Pool * src/distcc.c: dcc_retrieve_results: If the remote compiler exited non-zero, but the transfer was successful, return 0, indicating that there is no point trying to re-run the job locally. 2002-09-02 07:12 Martin Pool * src/serve.c: If something went wrong running the compiler, then make sure the overall status is failure. However, only overwrite the status code if it was not already !0. 2002-09-02 07:07 Martin Pool * test/testdistcc.py: Set up a distcc client log file for all tests. 2002-09-02 07:02 Martin Pool * test/testdistcc.py: Add test case that runs /bin/false to simulate a compiler that fails without reading its input. 2002-09-01 15:33 Martin Pool * NEWS: Doc recent changes 2002-09-01 15:30 Martin Pool * src/bulk.c: Better message for the case where the compile command exits without opening the fifo. 2002-09-01 15:27 Martin Pool * src/serve.c: Fix message 2002-09-01 15:26 Martin Pool * src/serve.c: If compilation failed, then still collect the compiler child, and send back a reply, with the waitstatus forced to be failure. 2002-09-01 15:15 Martin Pool * src/distcc.c, NEWS: dcc_compile_remote: If transmission to the server fails, close the socket sooner rather than later so as not to make the server process wait around unnecessarily. 2002-09-01 15:12 Martin Pool * src/distcc.c: dcc_compile_remote: Split into smaller functions. 2002-09-01 15:02 Martin Pool * src/bulk.c: Doc. 2002-09-01 14:28 Martin Pool * NEWS: Add common routine for setting SIGPIPE handling. 2002-09-01 14:27 Martin Pool * src/serve.c: Split server-side compile code into slightly smaller functions If a network error is detected while feeding data to the compiler, then it is sent a SIGHUP. 2002-09-01 14:08 Martin Pool * NEWS, src/exec.c: Set SIGPIPE handler back to default before starting compiler tasks. 2002-09-01 14:06 Martin Pool * src/: clinet.c, serve.c, util.c, util.h: Add common routine for setting SIGPIPE handling. 2002-09-01 14:05 Martin Pool * test/testdistcc.py: Send distccd log to a file while testing -- easier for postmortems. 2002-09-01 13:56 Martin Pool * NEWS, src/dparent.c: Do not try to collect daemon children if --no-fork was specified. Otherwise that routine collects compilers, and gives crazy messages like "-2 children". 2002-09-01 13:43 Martin Pool * src/serve.c: Doc. 2002-09-01 09:18 Martin Pool * src/serve.c: Doc. 2002-09-01 09:09 Martin Pool * src/serve.c: Doc. 2002-09-01 09:07 Martin Pool * src/distcc.c: dcc_compile_remote: Better log message 2002-09-01 09:06 Martin Pool * src/serve.c: dcc_accept_job: Better log message 2002-09-01 09:05 Martin Pool * src/distcc.c: Fix silly parameter order bug. 2002-09-01 08:55 Martin Pool * src/dparent.c: Get rid of cloexec, just close fds by hand. 2002-09-01 08:52 Martin Pool * src/serve.c: Typo 2002-09-01 08:50 Martin Pool * src/exec.c, NEWS: Close extra file descriptors before starting the compiler. 2002-09-01 08:46 Martin Pool * src/dparent.c: Set close-on-exec flags on listen and accepted fds. 2002-09-01 08:43 Martin Pool * src/: util.c, util.h: set_cloexec_flag: new function 2002-09-01 08:39 Martin Pool * src/serve.c: Doc 2002-09-01 08:38 Martin Pool * src/: distcc.c, serve.c: dcc_accept_job: * Use new dcc_mkfifo routine to make sure the fifo is created properly. * Use new dcc_r_file_body, dcc_r_file and dcc_r_fifo routines to make sure each type of temporary file is opened in the right way. 2002-09-01 08:36 Martin Pool * src/daemon.c: tempfile.h: new header 2002-09-01 08:34 Martin Pool * NEWS: Doc mkfifo changes and BigAssFile_Case 2002-09-01 08:31 Martin Pool * src/tempfile.c: dcc_mkfifo: * New routine. * We now unlink before trying to create a fifo, to make sure that if somehow that name is already in use by a file or fifo we won't get confused. 2002-09-01 08:29 Martin Pool * src/: rpc.h, bulk.h: bulk.h: new header 2002-09-01 08:28 Martin Pool * src/io.c: needs exitcode.h 2002-09-01 08:27 Martin Pool * src/: bulk.c, dparent.c, where.c: tempfile.h: new header 2002-09-01 07:52 Martin Pool * src/: tempfile.h, distcc.h: Split out tempfile.c routines into their own header 2002-09-01 07:49 Martin Pool * src/bulk.c: Doc. dcc_r_file: * Unlink the name before starting to receive the file. This may prevent bugs where the name already existed as a fifo. The old code would have opened the fifo rather than replacing it, and therefore would hang. Afterwards, create with O_EXCL. * Check that the file is successfully closed. (Might catch ENOSPC or similar.) dcc_r_fd: Fix return code to be the result of transferring the contents of the file. 2002-09-01 07:40 Martin Pool * src/io.c: dcc_close: make return code consistent (EXIT_IO_ERROR, not errno) 2002-09-01 07:39 Martin Pool * src/exitcode.h: Add EXIT_IO_ERROR 2002-09-01 07:37 Martin Pool * src/io.c: dcc_close: log file descriptor correctly. 2002-08-31 14:50 Martin Pool * src/bulk.c: Doc 2002-08-31 14:45 Martin Pool * test/testdistcc.py, src/clinet.c: Doc 2002-08-31 14:43 Martin Pool * src/clinet.c: Doc. Make variables consistent. 2002-08-31 14:31 Martin Pool * src/distcc.c: Doc. 2002-08-31 14:23 Martin Pool * src/: bulk.c, serve.c: Doc. 2002-08-31 14:13 Martin Pool * src/: bulk.c, io.c, io.h, rpc.c, rpc.h, serve.c: dcc_r_token_int: Add common routine for reading token and parameter value. 2002-08-31 14:01 Martin Pool * src/rpc.c: Doc. 2002-08-31 13:58 Martin Pool * src/: io.c, io.h: dcc_write_token: remove dead function 2002-08-31 13:56 Martin Pool * src/io.c: Cleanup sendfile code somewhat. 2002-08-31 13:48 Martin Pool * NEWS, linuxdoc/distcc.sgml, src/distcc.c, src/io.c, src/tempfile.c, src/util.c, src/util.h: dcc_getenv_bool: Add parameter giving default value so that things can default to either on or off. Add new environment variable for client and server, DISTCC_TCP_CORK. Defaults to on, intended mostly for performance comparison or debugging. 2002-08-31 13:44 Martin Pool * src/rpc.c: Fix prototype Use dcc_x_token_int in one case I missed before 2002-08-31 12:41 Martin Pool * NEWS, src/bulk.c, src/distcc.c, src/rpc.c, src/rpc.h: Write token/parameters using a single write() call. May be very slightly more efficient in CPU and perhaps packets. 2002-08-31 12:13 Martin Pool * src/io.c: Doc. 2002-08-30 10:53 Martin Pool * src/dparent.c: Doc. 2002-08-30 10:51 Martin Pool * src/serve.c: Put cork in correct hole. 2002-08-29 11:43 Martin Pool * src/trace.c: Doc. 2002-08-29 11:18 Martin Pool * NEWS, src/io.c: Handle the case of sendfile() transmitting only part of the supplied data, similarly to a short write on a socket. This doesn't often happen, but can occur if a ptrace debugger attaches while sendfile is running. 2002-08-29 10:35 Martin Pool * NEWS, src/distcc.c: Message for completion of local cpp now gives the correct hostname. 2002-08-29 10:21 Martin Pool * src/Makefile.in: Include $CFLAGS when linking so that profiling works 2002-08-29 10:17 Martin Pool * NEWS: Display test names while they're running so that long tests are easier to follow. 2002-08-29 10:06 Martin Pool * NEWS: Doc 2002-08-29 10:05 Martin Pool * test/testdistcc.py: When trying to kill the daemon, keep pinging it to make sure it actually died. This prevents the cases sometimes tripping over each other. Fix damage to assembly cases from previous commit Doc Remove some dead code 2002-08-29 09:49 Martin Pool * src/dparent.c: Create the pid file from the parent process, so that we can be sure that it exists before the parent exits. 2002-08-29 09:24 Martin Pool * src/dparent.c: Turn on signal handlers in parent. Why were they off? 2002-08-29 08:50 Martin Pool * test/testdistcc.py: Add missing newline 2002-08-29 08:50 Martin Pool * test/testdistcc.py: Add test for compilation of a large file (200,000 lines) 2002-08-29 08:13 Martin Pool * src/serve.c: Uncork sock before exiting. 2002-08-29 06:50 Martin Pool * src/bulk.c: quote 2002-08-28 11:33 Martin Pool * test/testdistcc.py: Doc. 2002-08-28 10:35 Martin Pool * NEWS, src/tempfile.c: Properly support platforms with 32-bit pids, such as Cygwin. Patch from Aaron Lehmann. 2002-08-28 10:18 Martin Pool * src/Makefile.in: Remove 'check' target because it must be run from the parent 2002-08-26 09:37 Martin Pool * linuxdoc/distcc.sgml: Notes about Cygwin and LNX-BBC volunteers into TODO list. 2002-08-26 08:52 Martin Pool * NEWS, configure, configure.ac: On FreeBSD, the sa_family_t type is defined in (Patch from Dennis Taylor) 2002-08-26 08:48 Martin Pool * aclocal.m4, configure, configure.ac, NEWS: Bump version to 0.9cvs 2002-08-26 08:43 Martin Pool * NEWS, OLDNEWS: roll over news 2002-08-15 18:51 Martin Pool * configure: autoconf 2002-08-15 18:41 Martin Pool * configure.ac: Set version 2002-08-15 14:39 Martin Pool * NEWS: Ready for release. 2002-08-15 12:56 Martin Pool * src/distcc.c: Tweak message 2002-08-15 12:45 Martin Pool * test/testdistcc.py: Add assertReMatch utility function When testing invalid server names, look in the log for the warning message. 2002-08-15 12:24 Martin Pool * src/distcc.c: Only emit the "running locally" notice when the job ought to be distributed but is not. So having the host set to be local, or non-distributable arguments just silently works. 2002-08-15 12:10 Martin Pool * src/tempfile.c: Add headers, remove dead variable 2002-08-15 12:03 Martin Pool * src/filename.c: Doc 2002-08-15 11:59 Martin Pool * src/serve.c: dcc_accept_job: patch from Chris Halls to make us more robust against files where we can't work out the preprocessor extension. 2002-08-15 11:57 Martin Pool * NEWS, src/filename.c: Correctly handle compilation of C++ code under ccache, by properly recognizing the .ii extension. Same patch from both Stephen White and Chris Halls. 2002-08-15 11:17 Martin Pool * configure: Run autoconf 2002-08-12 06:36 Martin Pool * configure.ac: Fix quoting. 2002-08-10 15:28 Martin Pool * src/where.c: Doc. Don't truncate lock files, open them with open(). 2002-08-10 15:26 Martin Pool * src/bulk.c: Doc. 2002-08-10 15:19 Martin Pool * src/: distcc.c, exec.c: Doc. 2002-08-10 15:13 Martin Pool * linuxdoc/distcc.sgml: Explain that we don't keep trying if we fail to connect. 2002-08-10 15:11 Martin Pool * src/distcc.c: Doc. 2002-08-10 15:08 Martin Pool * NEWS, src/distcc.c, test/testdistcc.py: If anything goes wrong with remote compilation other than the remote compiler returning an error, then run it locally instead. 2002-08-10 15:07 Martin Pool * src/tempfile.c: dcc_getenv_bool(): new function to make behaviour of DISTCC_VERBOSE etc consistent. 2002-08-10 15:05 Martin Pool * src/: arg.c, dparent.c: Adjust error severity levels. 2002-08-10 15:04 Martin Pool * src/trace.c: rs_format_msg: put the function name before the severity rather than after. I hate to change message formats but this seems more readable. 2002-08-10 15:01 Martin Pool * src/: util.c, util.h: dcc_getenv_bool(): new function to make behaviour of DISTCC_VERBOSE etc consistent. 2002-08-10 14:59 Martin Pool * src/trace.c: Make notice messages have a "Notice: " prefix. 2002-08-10 14:50 Martin Pool * src/clinet.c: Doc 2002-08-10 14:39 Martin Pool * test/testdistcc.py: Put all scratch directories under 'testtmp' to keep things tidy. 2002-08-10 14:19 Martin Pool * configure: Run autoconf 2002-08-09 18:10 Martin Pool * linuxdoc/distcc.sgml: Clearer text about env vars. 2002-08-09 18:08 Martin Pool * linuxdoc/distcc.sgml: Add doc for DISTCC_SAVE_TEMPS 2002-08-09 18:02 Martin Pool * survey.txt: Better text. 2002-08-09 17:59 Martin Pool * survey.txt: Better text. 2002-08-09 17:56 Martin Pool * Makefile.in: Upload survey. 2002-08-09 17:55 Martin Pool * Makefile.in: Install survey.txt into docs 2002-08-09 17:53 Martin Pool * configure, configure.ac, survey.txt, src/survey.txt: Running configure now shows a click-wrapish version of the GPL, plus information on installation directories, and a request to complete the survey. 2002-08-09 17:42 Martin Pool * README: Add survey 2002-08-09 17:33 Martin Pool * src/survey.txt: Add survey 2002-08-09 16:43 Martin Pool * NEWS: Add documentation for --no-fifo and --log-stderr. 2002-08-09 16:29 Martin Pool * linuxdoc/distcc.sgml: Add documentation for --no-fifo and --log-stderr. 2002-08-09 16:15 Martin Pool * NEWS: Show host specification syntax in --help 2002-08-09 16:13 Martin Pool * src/distcc.c: Better --help message 2002-08-09 16:11 Martin Pool * src/distcc.c: Show host specification syntax in --help 2002-08-09 16:02 Martin Pool * NEWS, OLDNEWS: Roll over NEWS 2002-08-09 16:01 Martin Pool * linuxdoc/distcc.sgml: Document that $DISTCC_HOSTS can now specify ports. 2002-08-08 12:27 Martin Pool * contrib/dmake: Example script contributed by Luke Gorrie 2002-08-05 23:33 Martin Pool * Makefile.in: There's always one. 2002-08-05 23:25 Martin Pool * Makefile.in: Add rules to build NEWS and signature files, and to upload everything to the ftp site. 2002-08-05 23:19 Martin Pool * configure, configure.ac: Bump version to 0.7; run autoconf. 2002-08-05 23:19 Martin Pool * README: Note that it probably works on Cygwin now. 2002-08-05 23:07 Martin Pool * DEPENDENCIES: Add --with-extra-includes and --with-extra-libs configure options, as in CVS. This helps people on platforms such as Solaris and BSD where some things install into /usr/local, but that is not on the default path. 2002-08-05 23:01 Martin Pool * configure.ac, src/Makefile.in: Add --with-extra-includes and --with-extra-libs configure options, as in CVS. This helps people on platforms such as Solaris and BSD where some things install into /usr/local, but that is not on the default path. 2002-08-05 19:47 Martin Pool * Makefile.in: Another attempt at packaging and installing the manual, but coping on machines without linuxdoc. 2002-08-05 19:46 Martin Pool * src/serve.c: Doc. 2002-08-05 19:39 Martin Pool * Makefile.in: Make 'all' the default target again. 2002-08-05 19:28 Martin Pool * Makefile.in: Fix packaging of Linuxdoc html. 2002-08-05 19:22 Martin Pool * NEWS: Set version for release. 2002-08-05 15:44 Martin Pool * Makefile.in: Make all latte HTML files depend on style.latte 2002-08-05 15:15 Martin Pool * linuxdoc/distcc.sgml: Add todo 2002-08-03 23:31 Martin Pool * NEWS: Doc 2002-08-03 23:29 Martin Pool * NEWS: Add release name 2002-08-03 23:28 Martin Pool * NEWS: Note that documentation is shipped. 2002-08-03 18:21 Martin Pool * linuxdoc/distcc.sgml: We could strip -D and -I from command lines. 2002-08-02 15:00 Martin Pool * test/testdistcc.py: Remove debugging stub 2002-08-02 14:58 Martin Pool * src/exec.c: Remove old message 2002-08-02 14:56 Martin Pool * test/testdistcc.py: Don't try to link file which is expected not to compile. 2002-08-02 14:43 Martin Pool * test/testdistcc.py: Run daemon on port 42000 for testing. Check that compiling an invalid file produces no output file. Use absolute path for pid file so that it's not confused by changing directories. 2002-08-02 14:28 Martin Pool * NEWS: host:port syntax now supported. 2002-08-02 14:23 Martin Pool * src/: distcc.c, distcc.h, dparent.c, exec.c, hosts.c, hosts.h, serve.c, where.c: Move towards using passing around dcc_hostdef structures, rather than just hostnames, so that we can start supporting nonstandard ports and eventually ssh. 2002-08-02 14:20 Martin Pool * src/filename.c: Use strrchr() rather than rindex(): they ought to be identical, but Valgrind seems to dislike rindex() 2002-08-02 14:19 Martin Pool * src/arg.c: Doc 2002-08-02 11:59 Martin Pool * NEWS: --log-stderr 2002-08-02 11:56 Martin Pool * src/: daemon.c, dopt.c, opt.h: Add --log-stderr option, intended mainly for testing/debugging 2002-08-02 11:39 Martin Pool * .cvsignore: Ignore *.tmp 2002-08-02 11:36 Martin Pool * test/testdistcc.py: Run all test cases within their own scratch directory. 2002-08-01 23:58 Martin Pool * src/serve.c: Add the ability to use either a fifo or a regular temporary file for input to the compiler, controlled by --no-fifo or failure to create the fifo. 2002-08-01 23:39 Martin Pool * src/: daemon.c, dparent.c, serve.c: dcc_accept_job: return standard exit code 2002-08-01 23:34 Martin Pool * src/: daemon.c, dparent.c, io.c, io.h: Explicitly close the socket before exiting, so that we have a better chance of catching network transmission errors. 2002-08-01 23:20 Martin Pool * NEWS, src/dopt.c, src/opt.h: Add --no-fifo option. Doesn't do anything yet. 2002-08-01 23:19 Martin Pool * Makefile.in: Fix cvsplot target. 2002-08-01 23:17 Martin Pool * NEWS: Doc 2002-08-01 23:12 Martin Pool * contrib/distcc.sh: This file, contributed by Dimitri PAPADOPOULOS-ORFANOS may be installed as "cc" somewhere on your $PATH ahead of the real gcc. That allows you to just use regular Makefiles without modifying them to change hardcoded calls to cc. This script will be a bit slow because of the overhead of running things through a shell. In a future release, this function should be supported directly by distcc, which should be a bit faster. 2002-08-01 23:02 Martin Pool * src/dparent.c: Define WAIT_ANY if it is missing, as seems to be the case on Cygwin. 2002-08-01 22:11 Martin Pool * src/exec.c: Doc. 2002-08-01 22:07 Martin Pool * src/serve.c: Cygwin needs not 2002-08-01 21:44 Martin Pool * src/exec.c: Cope without WCOREDUMP, which is missing on Cygwin. 2002-08-01 21:34 Martin Pool * NEWS, configure, configure.ac, src/config.h.in, src/distcc.h: If sa_family_t is missing, try just defining it as int. Might help Cygwin. 2002-08-01 21:16 Martin Pool * src/where.c: Try using fcntl locks in addition to lockf and flock. Perhaps this will fix Cygwin. Thanks to Marco Alanen. 2002-08-01 17:41 Martin Pool * src/: daemon.c, dopt.c, opt.h: Make errors from command-line options go to stderr. 2002-08-01 17:14 Martin Pool * Makefile.in: Always build check programs before running checks, even with -j. Specify complete PATH to binaries when running tests, so that they can change into subdirectories. 2002-07-25 17:14 Martin Pool * Makefile.in: Remove file that's no longer in CVS from distro. 2002-07-25 17:11 Martin Pool * doc/results.txt: Add results file; not much here yet. 2002-07-25 16:58 Martin Pool * Makefile.in: Add a somewhat-hacky "make dist" target to build a tarball. Compared to just "cvs export", this means we get to include built versions of the documents, which is nice for people who can't easily get the Linuxdoc SGML tools to work. It does make the binary bigger because there are so many formats, though. Also, we omit things that end users might not want, such as the Latte web site source. People can get it from CVS (or rsync) if they care. 2002-07-25 16:08 Martin Pool * configure, configure.ac: Bump version 2002-07-24 19:03 Martin Pool * test/testdistcc.py: Clear the environment before running the child -- this avoids any problems with the developer's environment. 2002-07-24 19:02 Martin Pool * src/dparent.c: Change the semantics for detaching a little bit: we now do it once the socket is listening. This is rather more useful for the test suite, because the suite now knows for sure that when the parent exits, it can go ahead and try to connect. 2002-07-24 18:58 Martin Pool * DEPENDENCIES, Makefile.in: Test case now requires python 2.2 for proper unsetenv() semantics 2002-07-24 18:50 Martin Pool * NEWS: foo 2002-07-24 18:49 Martin Pool * src/tempfile.c: Avoid using asprintf() because it's missing on Solaris 2002-07-24 18:49 Martin Pool * src/where.c: dcc_make_lock_filename: new function Avoid using asprintf() because it's missing on Solaris 2002-07-24 18:48 Martin Pool * src/exitcode.h: Doc 2002-07-24 17:57 Martin Pool * src/dparent.c: remove pid file if daemon exits on signal 2002-07-24 17:55 Martin Pool * src/dparent.c, NEWS: Log pid even if running with --no-fork. Remove pid file on exit. 2002-07-24 14:39 Martin Pool * Makefile.in, configure, configure.ac, patches/distc, patches/distc++: Suggestion from Dimitri PAPADOPOULOS-ORFANOS: should check for -lnsl and -lsocket on Solaris. 2002-07-24 14:38 Martin Pool * OLDNEWS, NEWS: Roll over news 2002-07-23 11:36 Martin Pool * Makefile.in: Add the start of an FAQ, and the AOSS4 slides. 2002-07-22 16:45 Martin Pool * Makefile.in: Doc. 2002-07-12 11:46 Martin Pool * configure: Rerun autoconf 2002-07-12 11:44 Martin Pool * Makefile.in: "make install" doesn't imply install-linuxdoc 2002-07-12 11:38 Martin Pool * Makefile.in: "make install" doesn't imply install-linuxdoc 2002-07-12 11:34 Martin Pool * test/testdistcc.py: Start adding to the test framework a way for test cases to provide their own explanation of why they failed. In particular, for ones that run shell commands, dump out all the commands that were run, and their output. 2002-07-12 11:33 Martin Pool * src/distcc.c: Give a proper error message for "distcc --fubar", even when we would have chosen to run the command locally. 2002-07-12 11:32 Martin Pool * src/daemon.c: If stdin is neither a socket nor a tty assume --daemon mode. This is more compatible with previous usage. 2002-07-12 11:19 Martin Pool * src/arg.c: Correct message for "distcc --bad-option" 2002-07-12 10:51 Martin Pool * configure.ac: Set version for release. 2002-07-12 10:45 Martin Pool * NEWS: Update news for release. 2002-07-12 10:39 Martin Pool * DEPENDENCIES: Clarify requirements for libpopt 2002-07-12 10:37 Martin Pool * Makefile.in: Install info files into the right directory 2002-07-10 15:37 Martin Pool * src/arg.c: dcc_set_action_opt: Need to also understand how to transform "gcc -S hello.c" to "gcc -o hello.i -E hello.c" for the client. 2002-07-10 15:11 Martin Pool * NEWS, src/arg.c, src/distcc.h, src/filename.c: distcc will now distribute jobs which use -s to compile but not assemble. Previously they were always run locally, but there's no strong reason why they must be. Unfortunately you need to upgrade both the client and server for this to work, because old servers will refuse to run gcc with -s. 2002-07-10 14:07 Martin Pool * NEWS, src/tempfile.c: dcc_cleanup_tempfiles: If $DISTCC_SAVE_TEMPS is set to "1", then files are not actually deleted -- good for debugging. 2002-07-09 14:38 Martin Pool * Makefile.in: Add page with current problems 2002-07-09 12:06 Martin Pool * Makefile.in: Add target to run Linbot to check for broken links. 2002-07-08 17:20 Martin Pool * configure: autogen 2002-07-08 17:18 Martin Pool * src/: daemon.c, distcc.h: Fix prototypes 2002-07-08 17:17 Martin Pool * src/dopt.c: distccd_show_usage: Document new options 2002-07-08 17:16 Martin Pool * NEWS: dcc_scan_args: -M causes the preprocessor to produce a list of make-style dependencies on header files, either to stdout or to a local file. It implies -E, so only the preprocessor is run, not the compiler. There would be no point trying to distribute it even if we could. 2002-07-08 17:13 Martin Pool * src/daemon.c, linuxdoc/distcc.sgml: Change --inetd and --daemon defaults: - if both are specified, die - if either is specified, do that - if stdin is a socket or tty assume inetd or daemon respectively - otherwise, complain 2002-07-08 17:03 Martin Pool * linuxdoc/distcc.sgml: Document more distccd command-line options 2002-07-08 17:00 Martin Pool * man/distcc.1: Syntax fix 2002-07-08 16:57 Martin Pool * DEPENDENCIES: Clarify dependencies 2002-07-08 16:54 Martin Pool * linuxdoc/distcc.sgml: Clarify that distcc returns the same value as the compiler. 2002-07-08 16:53 Martin Pool * linuxdoc/distcc.sgml: Clarify description how to get environment variables set properly. 2002-07-08 16:50 Martin Pool * linuxdoc/distcc.sgml: Clarify description of jobs which are distributed or local, give an example of a typical command that can be distributed. 2002-07-08 16:46 Martin Pool * src/arg.c: dcc_scan_args: -M causes the preprocessor to produce a list of make-style dependencies on header files, either to stdout or to a local file. It implies -E, so only the preprocessor is run, not the compiler. There would be no point trying to distribute it even if we could. 2002-07-08 16:33 Martin Pool * Makefile.in: Doc. 2002-07-07 22:23 Martin Pool * NEWS: Works on FreeBSD? 2002-07-07 22:12 Martin Pool * src/Makefile.in: Have to respect $LDFLAGS so we can build on BSD. Thanks Lauri! 2002-07-07 22:11 Martin Pool * test/testdistcc.py: SyntaxError_Case: Be less fussy about the exact compiler error message 2002-07-07 21:58 Martin Pool * configure.ac: Doc. 2002-07-07 21:52 Martin Pool * test/testdistcc.py: --version output has changed to include build date and to just say "protocol 1" 2002-07-07 21:46 Martin Pool * src/arg.c: Temporary fix for "distcc -c hello.c" 2002-07-07 21:43 Martin Pool * NEWS: Note about valgrind fix 2002-07-07 21:02 Martin Pool * Makefile.in: We don't build the web pages or manual by default, because many people will not have the tools to do it. Just use all-web or all-linuxdoc if you want them. 2002-07-07 21:01 Martin Pool * DEPENDENCIES, README: Put the documentation of dependencies in a separate file where it can be more easily found by people doing ports. 2002-07-07 20:08 Martin Pool * src/arg.c: dcc_argv_tostr: If out of memory, give an error and exit, rather than aborting. Apparently Valgrind doesn't like using strchr(s, 0) to find the terminating nul. I wonder why? 2002-07-07 19:51 Martin Pool * src/distcc.h: Add missing prototype 2002-07-07 19:40 Martin Pool * src/: .cvsignore, h_argvtostr.c: Start new test case h_argvtostr 2002-07-07 19:38 Martin Pool * src/: Makefile.in, arg.c, filename.c, distcc.h: Split filename manipulation code out into new file filename.c 2002-07-07 19:36 Martin Pool * src/distcc.c: Get ready to handle command lines with implied compiler. 2002-07-06 18:24 Martin Pool * src/arg.c: Doc about the idea of handling "distcc -c hello.c" 2002-07-06 18:11 Martin Pool * src/distcc.c: Remove old docs. 2002-07-06 18:07 Martin Pool * linuxdoc/distcc.sgml: Document --ping option. 2002-07-06 18:00 Martin Pool * linuxdoc/distcc.sgml: The log now shows execution time; remove this from the todo list. 2002-07-06 16:49 Martin Pool * src/: clinet.c, clinet.h, distcc.c, distcc.h: dcc_open_socket_out: use the standard error return mechanism 2002-07-06 16:44 Martin Pool * src/: daemon.c, dparent.c: Include build date/time in daemon startup message 2002-07-06 16:41 Martin Pool * src/help.c: dcc_show_version: Include build date/time 2002-07-06 16:32 Martin Pool * src/clinet.c: dcc_open_socket_out: Return EXIT_CONNECT_FAILED if it did (or indeed for all client socket-opening errors at the moment.) 2002-07-06 16:24 Martin Pool * linuxdoc/distcc.sgml: Notes about distcc with autoconf.Doc. 2002-07-06 16:18 Martin Pool * src/: distcc.c, distcc.h, exec.c, serve.c, util.c, util.h: myhostname: rename to dcc_gethostname for consistency dcc_spawn_child, dcc_redirect_fds: add another parameter specifying redirection for stdin, so that the same routine can be used on the client (with regular stdin) or on the server (with /dev/null) dcc_compile_local: Run the compiler as a child process, not over the top of us. distcc/main: Log exit code. 2002-07-06 16:02 Martin Pool * src/distcc.c: Rename dcc_run_remote and dcc_build_locally to dcc_compile_* to be consistent. 2002-07-06 15:57 Martin Pool * src/exec.c: Doc. 2002-07-06 15:56 Martin Pool * NEWS: dcc_exit: Show self and children's CPU time usage when exiting. 2002-07-06 15:54 Martin Pool * linuxdoc/distcc.sgml, src/where.c: dcc_pick_buildhost: If the host specification is invalid or missing, fall back to building locally with a warning. 2002-07-06 15:51 Martin Pool * src/where.c: dcc_pick_buildhost: bug fix: if we fail to parse the host specification, then return the right error. 2002-07-06 15:50 Martin Pool * linuxdoc/distcc.sgml: More detail on handling of invalid hostspecs. 2002-07-06 15:46 Martin Pool * src/util.c: dcc_exit: Show self and children's CPU time usage when exiting. 2002-07-05 17:12 Martin Pool * linuxdoc/distcc.sgml: Note about libtool. 2002-07-05 16:48 Martin Pool * linuxdoc/distcc.sgml: Add note about Makefiles which don't use $(CC). 2002-07-05 12:48 Martin Pool * NEWS, src/daemon.c, src/dopt.c, src/opt.h: Add --daemon and --inetd options, so that you can properly start a remote daemon with a single-line ssh command. 2002-07-05 12:32 Martin Pool * src/dparent.c: Need sys/ioctl.h 2002-07-05 11:31 Martin Pool * configure, configure.ac: Put docs in $prefix/share/doc 2002-07-05 11:21 Martin Pool * Makefile.in: Add "make showpaths" target to show where "make install" will put things. 2002-07-04 23:42 Martin Pool * NEWS: Show CPU usage of compiler, cpp, etc 2002-07-04 23:39 Martin Pool * .cvsignore, src/daemon.c, src/distcc.c, src/distcc.h, src/exec.c, src/serve.c: Show CPU usage of compiler, cpp, etc 2002-07-04 23:38 Martin Pool * Makefile.in: Fix "make install" 2002-07-04 23:23 Martin Pool * Makefile.in: Shush linuxdoc 2002-07-04 23:10 Martin Pool * src/exec.c: Doc. 2002-07-04 23:06 Martin Pool * src/exec.c: Better trace message. 2002-07-04 23:06 Martin Pool * src/dparent.c: Doc. 2002-07-04 23:05 Martin Pool * src/exec.c: Fix inverted test on waitpid() result. Doc. 2002-07-04 23:01 Martin Pool * src/serve.c: Doc (passing server errors back to client) 2002-07-04 22:56 Martin Pool * linuxdoc/distcc.sgml: Note about tcpwrappers. Note that you can now set the server port number. 2002-07-04 22:46 Martin Pool * src/daemon.c: Doc. 2002-07-04 22:15 Martin Pool * Makefile.in: distclean removes config.log Better maintainer-clean rules 2002-07-04 22:12 Martin Pool * test/testdistcc.py: Doc. 2002-07-04 22:03 Martin Pool * Makefile.in, linuxdoc/.cvsignore, man/.cvsignore: More Makefile fiddling - make "all" the default rule again - add "upload-linuxdoc" - try make SGML stuff build properly 2002-07-04 21:48 Martin Pool * Makefile.in, configure, configure.ac, linuxdoc/Makefile.in: Move linuxdoc stuff into top-level Makefile too 2002-07-04 21:31 Martin Pool * Makefile.in, configure, configure.ac, man/Makefile.in: Move man/ makefile into top level 2002-07-03 23:11 Martin Pool * Makefile.in: New design of the web site, now using Latte. 2002-07-03 20:31 Martin Pool * Makefile.in, analog/Makefile, analog/distcc.analog: Fiddle analog Make rules; use jdresolve to do DNS resolution. 2002-07-03 19:58 Martin Pool * analog/.cvsignore: Ignore more stuff 2002-07-03 16:57 Martin Pool * Makefile.in: Further Makefile fudging 2002-07-03 16:54 Martin Pool * analog/.cvsignore: Ignore built files. 2002-07-03 16:47 Martin Pool * Makefile.in: Move web/latte rules into top-level Makefile. Add more maintainer-clean rules 2002-07-02 17:14 Martin Pool * linuxdoc/distcc.sgml: We now have proper C++ support, so s/C/C or C++/ where appropriate. 2002-07-02 17:11 Martin Pool * man/: distcc.1, distccd.1: Update manpages, and remove information that is redundant with the SGML manual. I think between them, the big manual and --help are more useful than man pages, and they're certainly easier to maintain. 2002-07-02 12:05 Martin Pool * linuxdoc/distcc.sgml: Add bug. 2002-07-01 19:39 Martin Pool * linuxdoc/distcc.sgml: Clearer explanation of multiprocessor scheduling. 2002-07-01 19:36 Martin Pool * linuxdoc/distcc.sgml: Add CVS revision. 2002-07-01 19:35 Martin Pool * linuxdoc/distcc.sgml: Add new error codes 105, 106 2002-07-01 19:32 Martin Pool * linuxdoc/distcc.sgml: Make titles consistent 2002-07-01 19:31 Martin Pool * linuxdoc/distcc.sgml: Remove redundant SMP section 2002-07-01 19:27 Martin Pool * linuxdoc/distcc.sgml: "Leaky buckets" explanation of scheduling algorithm. 2002-07-01 09:38 Martin Pool * src/serve.c: Doc 2002-07-01 09:34 Martin Pool * src/dopt.c: Fix small syntax error 2002-07-01 09:34 Martin Pool * src/dopt.c: Add --verbose option for daemon 2002-07-01 09:23 Martin Pool * NEWS: emacs-fu 2002-07-01 09:22 Martin Pool * NEWS: Reformat 2002-07-01 09:15 Martin Pool * NEWS, src/daemon.c, src/distcc.h, src/dparent.c, src/serve.c: Move check for !getuid() up to a higher level so that the daemon refuses to start at all. 2002-07-01 09:08 Martin Pool * linuxdoc/distcc.sgml: Improved quick-start guide. 2002-06-30 22:01 Martin Pool * linuxdoc/: distcc.sgml: Better URL link. 2002-06-30 21:59 Martin Pool * linuxdoc/distcc.sgml: Add link to ccache. 2002-06-30 21:59 Martin Pool * linuxdoc/distcc.sgml: Clarify bug about compilers which touch local files. 2002-06-30 21:58 Martin Pool * linuxdoc/distcc.sgml: Clarify large-file message. 2002-06-30 21:55 Martin Pool * linuxdoc/distcc.sgml: Substantially improved section on cross-compilation; give more details on how to use -b. 2002-06-30 17:32 Martin Pool * analog/distcc.analog: Show more referers 2002-06-30 17:32 Martin Pool * test/testdistcc.py: Fix regexp for new error message. 2002-06-30 17:31 Martin Pool * src/: .cvsignore, Makefile.in, hosts.c, where.c: Change to new hostspec parser 2002-06-30 00:34 Martin Pool * test/testdistcc.py: All tests now moved across to new framework 2002-06-30 00:26 Martin Pool * test/testdistcc.py: Go back to purely object-based definitions of test cases 2002-06-30 00:02 Martin Pool * test/testdistcc.py: Fiddle with comfychair interface 2002-06-30 00:00 Martin Pool * src/: trace.c, trace.h: Rename rs_trace_stderr to rs_trace_to_file, a more correct name. 2002-06-29 23:59 Martin Pool * src/dopt.c: Add --log-file option 2002-06-29 23:58 Martin Pool * src/: dparent.c, distcc.h: Make dcc_become_daemon private 2002-06-29 23:57 Martin Pool * analog/Makefile: Fix Makefile 2002-06-29 23:28 Martin Pool * test/testdistcc.py: Make comfychair more OO. 2002-06-29 23:14 Martin Pool * src/serve.c: Refuse to run daemon as root. 2002-06-29 23:13 Martin Pool * src/hosts.c: Doc. 2002-06-29 23:00 Martin Pool * doc/scheduling.txt: Notes on scheduling 2002-06-29 16:39 Martin Pool * src/OLDNEWS: Moved 2002-06-29 01:49 Martin Pool * test/testdistcc.py: Add more host parser cases. 2002-06-29 01:44 Martin Pool * src/hosts.c: Correctly handle ssh tokens with command specified. 2002-06-29 01:42 Martin Pool * src/h_hosts.c, src/hosts.c, src/hosts.h, test/testdistcc.py: Add special host type for local compilation. 2002-06-29 01:38 Martin Pool * test/testdistcc.py: Better hosts parser test 2002-06-29 01:37 Martin Pool * src/hosts.c: Fix parser bug in tcp with specified port. 2002-06-29 01:32 Martin Pool * test/testdistcc.py: Doc. 2002-06-29 01:25 Martin Pool * test/testdistcc.py: Add test case for host specification parser. 2002-06-29 01:24 Martin Pool * src/hosts.c: Hosts parser that works better with missing components. 2002-06-29 00:53 Martin Pool * test/testdistcc.py: Move more tests from pyunit to comfychair. It's definitely more comfortable! 2002-06-29 00:39 Martin Pool * test/testdistcc.py: Move more tests from pyunit to comfychair. It's definitely more comfortable! 2002-06-28 23:23 Martin Pool * src/srvnet.c: Also show numeric client address in connection message 2002-06-28 23:19 Martin Pool * linuxdoc/Makefile.in: Fix Makefile a bit more 2002-06-28 23:15 Martin Pool * linuxdoc/Makefile.in: Fix Makefile 2002-06-28 23:14 Martin Pool * linuxdoc/distcc.sgml: Bump version. Note about IPv6 2002-06-28 23:03 Martin Pool * src/dparent.c: Doc. 2002-06-28 23:01 Martin Pool * src/dparent.c: When in no-fork mode, clean up files after each job 2002-06-28 22:59 Martin Pool * src/Makefile.in: Drop sbin install target. 2002-06-28 22:49 Martin Pool * src/tempfile.c: Doc. 2002-06-28 22:14 Martin Pool * src/: dopt.c, dparent.c, opt.h: Add --no-fork option to daemon to help with some debugging stuff. 2002-06-28 21:51 Martin Pool * man/distcc.1: Add newline 2002-06-28 21:50 Martin Pool * man/distccd.1: Make a slightly more useful distccd manpage 2002-06-28 21:41 Martin Pool * analog/Makefile: Create report/ subdir if it doesn't exist. 2002-06-28 21:40 Martin Pool * linuxdoc/Makefile.in: Create html/ subdir if it doesn't exist. 2002-06-28 18:35 Martin Pool * README: Make it clear that we do C++ too! Try to explain relationship to gcc. 2002-06-28 18:20 Martin Pool * test/testdistcc.py: test_option_version: Handle host triples like i386-unknown-freebsd4.4 (Claes Wallin) 2002-06-28 16:57 Martin Pool * src/dparent.c: Doc. 2002-06-28 16:53 Martin Pool * src/: dparent.c, exec.c: The two routines that call waitpid() must handle EINTR, in case a signal arrives while waiting. (Perhaps on BSD if a child exits, you will break out with SIGCHLD and then need to wait again? Not sure.) 2002-06-28 16:49 Martin Pool * Makefile.in: Add target to run old (currently broken) pyunit tests 2002-06-28 16:47 Martin Pool * src/distcc.h: Add prototypes for hosts.c 2002-06-28 16:33 Martin Pool * src/serve.c: Doc. 2002-06-28 16:19 Martin Pool * src/: io.c: Better message. 2002-06-28 16:13 Martin Pool * src/Makefile.in: distccd ought to be in bin/; add rationale. 2002-06-28 16:04 Martin Pool * NEWS, src/io.c: If the system supports sendfile, but the particular filesystem we're on (e.g. tmpfs) doesn't, then fall back to using read/write. 2002-06-28 16:02 Martin Pool * src/Makefile.in: Makefile must properly inherit configured variables 2002-06-28 16:01 Martin Pool * man/Makefile.in: Remove old Makefile target to do with pre-processed manpages 2002-06-28 16:00 Martin Pool * configure: foo 2002-06-28 15:59 Martin Pool * man/Makefile.in: distccd can be run by ordinary users, so arguably belongs in section 1. 2002-06-28 13:20 Martin Pool * NEWS: Foo 2002-06-28 13:18 Martin Pool * README: Update README. 2002-06-28 13:12 Martin Pool * src/Makefile.in: Make directories before installing into them. 2002-06-28 13:08 Martin Pool * OLDNEWS: Merge news from 0.5 and make format consistent. 2002-06-28 13:07 Martin Pool * Makefile.in: Also install top-level documentation (e.g. README) 2002-06-28 13:05 Martin Pool * configure.ac, linuxdoc/Makefile.in, man/Makefile.in, src/Makefile.in: More work on 'make install' 2002-06-28 12:49 Martin Pool * configure.ac, analog/distcc.analog, man/Makefile.in: More automake removal, mostly for man/ 2002-06-28 12:48 Martin Pool * Makefile.in: If any sub-make fails, the top-level one should fail too. 2002-06-28 12:06 Martin Pool * Makefile.in, configure, configure.ac, linuxdoc/.cvsignore, src/Makefile.in: More work on conversion away from automake 2002-06-28 11:56 Martin Pool * linuxdoc/Makefile.in: Cleanup. Only remove documents with maintainer-clean. 2002-06-28 11:50 Martin Pool * linuxdoc/Makefile.in: Remove automake cruft. 2002-06-28 11:42 Martin Pool * src/io.c: Merge fixup 2002-06-28 11:41 Martin Pool * patches/ChangeLog: kill changelogs 2002-06-28 11:40 Martin Pool * missing: remove automake cruft 2002-06-28 11:38 Martin Pool * .cvsignore, linuxdoc/distcc.sgml, src/arg.c, src/distcc.c, src/distcc.h, src/exec.c, src/h_scanargs.c, src/io.c, src/serve.c: Merge changes from freeze_0_5 branch: - avoid argv[] overrun bug - more trace messages - some refactoring/cleanups - FreeBSD sendfile portability fix - better exit codes 2002-06-28 11:23 Martin Pool * analog/: Makefile, distcc.analog: Add analog config. 2002-06-27 22:45 Martin Pool * test/testdistcc.py: Also test hostspec parser. 2002-06-27 22:43 Martin Pool * src/hosts.c: Better messages for EXIT_BAD_HOSTSPEC 2002-06-27 22:41 Martin Pool * src/hosts.c: dcc_parse_hosts() needs to return EXIT_BAD_HOSTSPEC if no hosts are defined. 2002-06-27 22:29 Martin Pool * test/testdistcc.py: Port more tests from PyUnit. 2002-06-27 22:27 Martin Pool * Makefile.in: Run tests against just-built executables. 2002-06-27 22:12 Martin Pool * test/testdistcc.py: Add a slightly nontrivial test that we can call --version on distcc and distccd. 2002-06-27 21:59 Martin Pool * Makefile.in: Don't run pyunit by default any more. 2002-06-27 21:58 Martin Pool * Makefile.in: Call comfy chair and pyunit tests 2002-06-27 21:57 Martin Pool * test/testdistcc.py: Start of conversion of Python tests to use comfy chair 2002-06-27 21:45 Martin Pool * Makefile.in, aclocal.m4: Start getting 'make check' working without automake. 2002-06-27 21:45 Martin Pool * src/Makefile.in: Add non-automake rules to build test harnesses. 2002-06-27 21:34 Martin Pool * src/exitcode.h: Cleanup. 2002-06-27 21:33 Martin Pool * src/: daemon.c, dparent.c: Fixes for removal of automake. 2002-06-27 21:29 Martin Pool * src/distcc.h: Add a new host specification string parser (not called yet except from test case.) 2002-06-27 21:28 Martin Pool * src/io.c: Reindent. Emit trace messages when (un)corking sockets. 2002-06-27 21:25 Martin Pool * src/trace.h: Change rs_log_critical to rs_log_crit to be consistent. 2002-06-27 21:24 Martin Pool * src/srvnet.c: Doc 2002-06-27 21:24 Martin Pool * src/: hosts.c, where.c: Add a new host specification string parser (not called yet except from test case.) 2002-06-27 21:24 Martin Pool * src/h_hosts.c: Print out the results of parsing the host specification. Pass exit code from scanner out. 2002-06-27 21:23 Martin Pool * src/exitcode.h: Add additional exit codes: compiler crashed, out of memory, bad hostspec. Doc. 2002-06-27 21:20 Martin Pool * src/dparent.c: Log an info message when standalone daemon starts, including version. 2002-06-27 21:20 Martin Pool * src/daemon.c: Log an info message when inetd daemon starts. 2002-06-27 20:36 Martin Pool * configure, configure.ac: Bump version to 0.5 2002-06-27 20:32 Martin Pool * NEWS: Add date, etc. 2002-06-27 20:28 Martin Pool * NEWS: Update NEWS 2002-06-27 20:25 Martin Pool * src/io.c: Doc. 2002-06-27 14:34 Martin Pool * configure, configure.ac: Bump version. 2002-06-27 13:46 Martin Pool * src/io.c: Try to handle FreeBSD's different API for sendfile() by introducing a sys_sendfile() portability wrapper. 2002-06-27 13:23 Martin Pool * Makefile.am, Makefile.in, NEWS, aclocal.m4, autogen.sh, configure, configure.ac, linuxdoc/Makefile.am, man/Makefile.am, src/Makefile.am, src/Makefile.in, src/config.h.in, src/help.c: Get rid of automake, just use plain autoconf 2.53. What a mess! Building the basic executables should still work; test cases etc is probably broken at the moment. 2002-06-27 10:39 Martin Pool * ChangeLog, Makefile.in, aclocal.m4, contrib/ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, linuxdoc/Makefile.in, man/ChangeLog, man/Makefile.in, src/ChangeLog, src/Makefile.in: Run autogen Remove dumb ChangeLogs 2002-06-26 21:59 Martin Pool * Makefile.in, aclocal.m4, configure, depcomp, missing, linuxdoc/Makefile.in, man/Makefile.in, src/Makefile.in: Upgrade automake to 1.5. 2002-06-26 21:59 Martin Pool * NEWS: Set version. 2002-06-26 21:58 Martin Pool * autogen.sh, .cvsignore: ChangeLogs no longer stored in CVS. 2002-06-26 21:56 Martin Pool * src/dparent.c: Handle EINTR from waitpid(), which is expected on FreeBSD. 2002-06-26 14:49 Martin Pool * linuxdoc/distcc.sgml: Document EXIT_COMPILER_CRASHED. 2002-06-26 14:44 Martin Pool * src/distcc.c: Doc. Clearer message for remote compiler failure. 2002-06-26 14:35 Martin Pool * ChangeLog, contrib/ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, man/ChangeLog, patches/ChangeLog, src/ChangeLog: Remove ChangeLogs -- I'm not convinced that keeping them in CVS makes much sense. If you want them, autogenerate them. 2002-06-26 14:21 Martin Pool * configure, configure.ac: Set version to 0.5rc1 2002-06-26 14:19 Martin Pool * NEWS, src/arg.c, src/distcc.c, src/distcc.h, src/exec.c, src/exitcode.h, src/h_hosts.c, src/h_scanargs.c, src/serve.c: Fix bug in h_hosts that caused us to write off the end of the real argv[], rather than a copy. Thanks to Julian Seward. Use more specific return codes when the remote compiler fails: EXIT_COMPILER_CRASHED for a signal, or the return code from the compiler if it exited non-0. Refactor client main() to be a bit clearer. 2002-06-22 14:44 Martin Pool * src/: t_exten, t_issource, t_version: Remove unused sh-based tests. 2002-06-22 03:58 Martin Pool * Makefile.in, NEWS, aclocal.m4, configure, configure.ac, linuxdoc/Makefile.in, man/Makefile.in, src/Makefile.in: Bump version to 0.5. 2002-06-22 03:56 Martin Pool * src/trace.h: Doc. 2002-06-21 19:48 Martin Pool * src/: distcc.h, h_hosts.c, hosts.c, where.c: Make everything build again :) 2002-06-21 19:46 Martin Pool * src/hosts.c: Doc. 2002-06-21 19:34 Martin Pool * src/hosts.c: dcc_parse_hosts_env: Better parser that splits things into words and recognizes the two types of host definition. Doesn't do the whole job yet though. 2002-06-21 19:33 Martin Pool * src/h_hosts.c: h_hosts: Actually print out the results of the test. Exit 1 if something went wrong or is inconsistent. 2002-06-21 19:15 Martin Pool * src/: .cvsignore, Makefile.am, Makefile.in, distcc.h, h_hosts.c, hosts.c, hosts.h, where.c: Start splitting out new host parser. Doesn't do anything yet. 2002-06-18 08:50 Martin Pool * linuxdoc/Makefile.in: Keep Makefile.in to allow building without automake. 2002-06-13 15:42 Martin Pool * src/: trace.c, trace.h: Cope without varargs macros. All trace routines are redirected to plain functions. 2002-06-13 15:41 Martin Pool * Makefile.in, configure, src/config.h.in: Run autoconf 2002-06-13 15:22 Martin Pool * src/: h_exten.c, h_issource.c, h_scanargs.c: - cope without varargs macros or __attribute__ 2002-06-13 15:14 Martin Pool * NEWS, configure.ac, src/arg.c, src/bulk.c, src/distcc.c, src/distcc.h, src/dopt.c, src/dparent.c, src/exec.c, src/io.c, src/rpc.c, src/tempfile.c, src/trace.c, src/trace.h, src/util.c, src/util.h, src/where.c: Modified patch from Petter Reinholdtsen to try to build on Solaris with Forte cc. Specifically: - cope without varargs macros or __attribute__ - use lockf rather than flock if missing - fix bashism - put config.h in all files 2002-06-13 15:02 Martin Pool * Makefile.in, man/Makefile.in: run automake 2002-06-13 15:01 Martin Pool * README: Remove old performance numbers Add supported platforms 2002-06-13 15:00 Martin Pool * patches/freebsd-mknod.diff: committed 2002-06-13 14:58 Martin Pool * NEWS, src/serve.c: FreeBSD mknod/mkfifo fix. (Claes Wallin) 2002-06-13 14:54 Martin Pool * src/dopt.c: Doc. 2002-06-12 02:44 Martin Pool * NEWS, man/Makefile.am: Makefile.am patch from Petter Reinholdtsen to correctly install and distribute manpages. (They need to be updated to include just quick reference information and to point to the sgml manual.) 2002-06-12 02:15 Martin Pool * packaging/: README.rpm, distcc.spec: RPM spec file from Ben Elliston. 2002-06-12 01:53 Martin Pool * NEWS, OLDNEWS: Roll over NEWS 2002-06-12 01:52 Martin Pool * src/: bulk.c, distcc.h: Refactor bulk file transfer code in preparation for gzip compressiong. 2002-06-12 01:51 Martin Pool * src/io.c: Doc. 2002-06-12 01:47 Martin Pool * src/zip.c: Skeleton of zip compression. Not used yet. 2002-06-12 01:39 Martin Pool * man/: .cvsignore, Makefile.in: Keep files generated by automake, but not by configure. 2002-06-12 01:39 Martin Pool * patches/freebsd-mknod.diff: Patch from Claes Wallin for FreeBSD. 2002-06-12 01:37 Martin Pool * man/.cvsignore: Ignore autoconf generated files. 2002-06-12 01:36 Martin Pool * linuxdoc/.cvsignore: Ignore generated files. 2002-06-09 02:58 Martin Pool * linuxdoc/distcc.sgml: Bump version to 0.4 2002-06-09 02:53 Martin Pool * ChangeLog, contrib/ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, man/ChangeLog, patches/ChangeLog, src/ChangeLog: update ChangeLogs 2002-06-09 02:51 Martin Pool * configure, linuxdoc/Makefile, linuxdoc/Makefile.am, man/Makefile, man/Makefile.am, src/Makefile.in: Shuffle Makefiles 2002-06-09 02:50 Martin Pool * NEWS: Update news 2002-06-09 02:40 Martin Pool * src/Makefile.am: Add missing file 2002-06-09 02:38 Martin Pool * configure.ac: Bump version to 0.4 Get rid of old test scripts Add new Makefiles 2002-06-09 02:34 Martin Pool * NEWS: Doc. 2002-06-09 02:32 Martin Pool * src/dopt.c: Hide --tasks from help since it does nothing. 2002-06-09 02:09 Martin Pool * linuxdoc/distcc.sgml: Add section on SMP. 2002-06-09 02:02 Martin Pool * src/dparent.c: Doc. 2002-06-09 01:58 Martin Pool * ChangeLog, contrib/ChangeLog, linuxdoc/ChangeLog, patches/ChangeLog, src/ChangeLog: update changelog 2002-06-09 01:50 Martin Pool * src/dparent.c: Factor out code to collect children. Keep track of how many are running. 2002-06-09 01:44 Martin Pool * src/: daemon.c, dparent.c: Change server to a more traditional Unix model of forking after accepting -- possibly less efficient, but I was having trouble managing an orderly shutdown of all children and this is simpler. 2002-06-09 01:43 Martin Pool * src/Makefile.in: Run autoconf 2002-06-09 01:42 Martin Pool * NEWS: Doc 2002-06-09 00:23 Martin Pool * NEWS: .S and .s probably works now. 2002-06-09 00:21 Martin Pool * src/: arg.c, distcc.h, serve.c: Correctly infer preprocessed filename from source filename. So for example if we're processing a .S file, then we need to call the tmpfile .s so that the compiler driver understands that it should just run the assembler. 2002-06-09 00:08 Martin Pool * linuxdoc/distcc.sgml: Note that network errors will not be detected. 2002-06-09 00:05 Martin Pool * src/dopt.c: Doc. 2002-06-09 00:03 Martin Pool * src/arg.c: Server should log input and output filename too. 2002-06-08 23:54 Martin Pool * src/: arg.c: Log input and output filename. 2002-06-08 23:45 Martin Pool * src/dparent.c: Daemon parent tries to close listen_fd after forking children, because it's no longer required. 2002-06-08 23:43 Martin Pool * src/: Makefile.am, daemon.c, distcc.h, dparent.c: Split daemon-standalone-parent code into a separate file. 2002-06-08 23:35 Martin Pool * src/daemon.c: Lots of doc updates. 2002-06-08 23:30 Martin Pool * src/daemon.c: Update docs. 2002-06-08 23:24 Martin Pool * NEWS: Note --pid-file. 2002-06-08 23:10 Martin Pool * src/daemon.c: Add log message for stdin being a socket 2002-06-08 23:09 Martin Pool * src/srvnet.c: open_socket_in: check that port number is reasonable 2002-06-08 22:54 Martin Pool * linuxdoc/: .cvsignore, Makefile: Fix Plucker filename 2002-06-08 22:49 Martin Pool * linuxdoc/.cvsignore: Add Plucker-ized manual 2002-06-08 22:48 Martin Pool * linuxdoc/Makefile: Better name for Plucker file. 2002-06-08 22:40 Martin Pool * src/daemon.c: Consistently call dcc_exit(). Notice immediately when one of our children dies, and reap all of them. When all children die or the parent is signalled, the parent should kill the process group and itself. 2002-06-08 22:31 Martin Pool * src/util.h: Fix function attributes. 2002-06-08 22:16 Martin Pool * src/distcc.h: Clean up prototypes. 2002-06-08 22:11 Martin Pool * src/daemon.c: Clean up exit codes. If fork() fails, log an error, but keep trying. Try to listen on socket before going into background, so that failure is visible to the calling script. 2002-06-08 22:00 Martin Pool * src/distcc.c: Detect invocations like "distcc -c" 2002-06-08 22:00 Martin Pool * src/exitcode.h, linuxdoc/distcc.sgml: Renumber exit codes so that 100 is a generic distcc failure. 2002-06-08 21:44 Martin Pool * src/dopt.c: Fix help message for --pid-file 2002-06-08 21:43 Martin Pool * src/: daemon.c, dopt.c, opt.h: Add --pid-file option to save daemon's pid. 2002-06-08 21:42 Martin Pool * Makefile.in: Update autoconf stuff 2002-06-08 14:24 Martin Pool * linuxdoc/Makefile: Don't build Linuxdoc by default because many machines won't have the tools. 2002-06-08 13:49 Martin Pool * src/dopt.c: Fix overzealous memory mistake. 2002-06-07 16:17 Martin Pool * ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, man/ChangeLog, src/ChangeLog: auto-update ChangeLog 2002-06-07 11:09 Martin Pool * man/: .cvsignore, Makefile, distcc.1, distccd.1: Correction from Juan F. Codagnone for Makefile -- should call groff, not man, to transform manpages Also, add a little stub distccd page. Both need to be updated to show just the basic information and refer to the manual for more info. 2002-06-06 18:21 Martin Pool * linuxdoc/distcc.sgml: Improve cross-compile section. 2002-06-06 17:52 Martin Pool * linuxdoc/distcc.sgml: Update doc: test suite has now been written. 2002-06-06 00:22 Martin Pool * Makefile.in, NEWS, configure, configure.ac, src/config.h.in, src/daemon.c, src/distcc.h, src/dopt.c, src/exitcode.h, src/opt.h: Improvements to demon: - make daemon put itself into background when running alone - daemon preforks children according to --tasks option, notes if they die, and kills them when terminated - --port option to set listening port (currently not useful, since you can't set port on client) 2002-06-05 19:00 Martin Pool * src/dopt.c: Fix mostly-harmless leaks of poptContext. Detected by valgrind -- how cool! 2002-06-05 18:53 Martin Pool * NEWS, src/tempfile.c: Add support for TMPDIR. Not tested. 2002-06-05 17:22 Martin Pool * src/: bulk.c, daemon.c, distcc.c, exec.c, where.c: Doc. 2002-06-02 15:02 Martin Pool * NEWS: Test cvs 2002-06-02 14:28 Martin Pool * linuxdoc/Makefile, man/Makefile: Fix recursive make targets 2002-06-02 14:18 Martin Pool * linuxdoc/Makefile, man/Makefile: Fix recursive make targets 2002-06-02 14:10 Martin Pool * Makefile.in, linuxdoc/Makefile: automake 2002-06-02 14:09 Martin Pool * src/: Makefile.in, daemon.c, exitcode.h: Start using consistent return codes across all programs. 2002-06-02 14:07 Martin Pool * contrib/make-j: make-j script from Alexandre Oliva for use with distcc Tests which machines are up, and runs Make with concurrency set appropriately. 2002-06-02 13:59 Martin Pool * src/: .cvsignore, Makefile.am, Makefile.in, arg.c, clinet.c, daemon.c, distcc.c, exitcode.h, h_scanargs.c, help.c, serve.c, srvnet.c, trace.c, trace.h, util.c, util.h, where.c: Many changes: Start using consistent return codes across all programs. Add h_scanargs to allow pyunit to test argument analysis. If -fprofile-args, -ftest-coverage or -x is seen in arguments, run locally. Handle "gcc -c -c hello.c" Better help message. Start handling .s files (doesn't work yet) Fix insertion of program/pid into trace msgs. 2002-06-02 13:56 Martin Pool * configure, configure.ac: FreeBSD installs its version of libpopt into /usr/local/, but does not put that on the default library and header path. We used to add that path if building on *bsd*, but bje points out that will break cross-compilation, and it's kind of ugly anyhow. 2002-06-02 13:55 Martin Pool * autogen.sh: Don't configure from autogen.sh 2002-06-02 13:54 Martin Pool * Makefile.am, Makefile.in: Also descend into linuxdoc, pyunit and man directories. 2002-06-02 13:51 Martin Pool * linuxdoc/distcc.sgml: More documentation, especially about bugs. 2002-06-02 13:50 Martin Pool * NEWS, OLDNEWS: Roll over news. 2002-05-31 16:36 Martin Pool * configure, configure.ac: Apparently FreeBSD needs sys/types.h before netinet/in.h. From Frerich Raabe. 2002-05-31 16:20 Martin Pool * linuxdoc/distcc.sgml: Add distcc link. 2002-05-31 16:10 Martin Pool * linuxdoc/Makefile: Move to distcc.samba.org. 2002-05-31 16:09 Martin Pool * linuxdoc/distcc.sgml: Manual is now current for 0.3 2002-05-31 16:08 Martin Pool * linuxdoc/footer.html: Fix distcc homepage link. 2002-05-30 08:31 Martin Pool * configure.ac: Documentation from ben 2002-05-29 14:35 Martin Pool * linuxdoc/distcc.sgml: More notes from recent discussions. 2002-05-29 14:21 Martin Pool * src/arg.c: Doc. 2002-05-28 23:11 Martin Pool * ChangeLog, Makefile.am, Makefile.in, linuxdoc/ChangeLog, src/ChangeLog: Commit Makefile rule 2002-05-28 23:09 Martin Pool * Makefile.am: Need to distribute ChangeLogs across directories 2002-05-28 23:04 Martin Pool * ChangeLog: Update ChangeLog from CVS 2002-05-28 23:00 Martin Pool * Makefile.in, aclocal.m4, src/Makefile.in: autoconf 2002-05-28 22:58 Martin Pool * Makefile.in, src/Makefile.in: update autoconf 2002-05-28 22:58 Martin Pool * src/NEWS: Moved to parent directory 2002-05-28 22:56 Martin Pool * NEWS: Go ahead and release. 2002-05-28 22:38 Martin Pool * aclocal.m4, configure, configure.ac, src/Makefile.am: Bump version to 0.3. Try to get "make dist" working. 2002-05-28 19:50 Martin Pool * Makefile.in, configure, src/Makefile.in: rerun autoconf 2002-05-28 19:32 Martin Pool * configure.ac: Suggestion from Frerich to fix check for *bsd*. 2002-05-28 15:38 Martin Pool * src/.cvsignore: Ignore temp file. 2002-05-28 15:29 Martin Pool * aclocal.m4, configure.ac, src/Makefile.am, src/Makefile.in, src/t_version: Add another trivial test suggested by bje 2002-05-28 15:18 Martin Pool * Makefile.in, configure, configure.ac, src/config.h.in, src/help.c: Export gnu host triple in --version 2002-05-28 15:07 Martin Pool * Makefile.in, aclocal.m4, config.guess, config.sub, configure, configure.ac, src/Makefile.in: Detect BSD, and add /usr/local/ to the CFLAGS and LDFLAGS. 2002-05-28 14:31 Martin Pool * aclocal.m4: Silly autoconf 2002-05-28 14:24 Martin Pool * patches/: distc, distc++: Single files that call 'distcc gcc' -- possibly needed for Makefiles that assume the compiler is a single word. (Does this include libtool?) 2002-05-28 14:18 Martin Pool * src/: .cvsignore, Makefile.in, config.h.in: Check in extra autoconf-generated files. 2002-05-28 14:17 Martin Pool * src/timebuild: Very primitive script for timing tests. 2002-05-28 13:52 Martin Pool * src/: h_exten.c, h_issource.c: Additional fixes for rs_program_name. 2002-05-28 13:48 Martin Pool * Makefile.in, configure, configure.ac, src/serve.c: BSD needs sys/signal.h. 2002-05-28 12:43 Martin Pool * .cvsignore, COPYING.FDL, Makefile.am, Makefile.in, aclocal.m4, configure, install-sh, missing, mkinstalldirs: Keep a copy of autotools files in CVS, to help people on machines with different versions. Bah, humbug! 2002-05-28 12:37 Martin Pool * ChangeLog, doc/ChangeLog, linuxdoc/ChangeLog, man/ChangeLog: Regenerate ChangeLogs 2002-05-28 12:28 Martin Pool * src/: ChangeLog, daemon.c, distcc.c, trace.c, trace.h: Clean up rs_program_name shmozlle 2002-05-27 00:58 Martin Pool * src/srvnet.c: Doc 2002-05-27 00:14 Martin Pool * configure.ac: Doc 2002-05-26 01:44 Martin Pool * .cvsignore, src/.cvsignore: Ignore extra garbage 2002-05-26 01:38 Martin Pool * configure.ac: Need to also look in sys/types.h for in_port_t on BSD. 2002-05-26 01:35 Martin Pool * src/arg.c: Good fix from Ian Reinhart Geiser for silly mistake in dcc_set_file_extension that I think would show up in "gcc -c hello.c". 2002-05-26 01:27 Martin Pool * NEWS, src/serve.c: Ignore SIGPIPE in daemon as well as client. Thanks to Ben Elliston. 2002-05-26 01:21 Martin Pool * configure.ac, src/clinet.c, NEWS: Try to cope without in_port_t. Thanks to Luke Gorrie. 2002-05-26 01:11 Martin Pool * src/: daemon.c, distcc.c, h_exten.c, h_issource.c, trace.c: Cope without program_invocation_short_name, as some GNU libc/cc combinations don't seem to have it (???) 2002-05-26 00:54 Martin Pool * src/trace.c: Replace calls to strnlen with strlen, because it will always be short enough and FreeBSD doesn't have strnlen 2002-05-26 00:49 Martin Pool * configure.ac, src/help.c: Ignore strange new automake variables, just use PACKAGE and VERSION 2002-05-26 00:47 Martin Pool * NEWS: Fix Ian's name. 2002-05-26 00:46 Martin Pool * NEWS: M-/ strikes again :-) 2002-05-26 00:42 Martin Pool * src/io.c: If there are no corks on this computer, don't try to use them. 2002-05-26 00:32 Martin Pool * configure.ac, src/arg.c, src/bulk.c, src/clinet.c, src/daemon.c, src/distcc.c, src/exec.c, src/h_exten.c, src/h_issource.c, src/io.c, src/rpc.c, src/serve.c, src/srvnet.c, src/tempfile.c, src/util.c, src/where.c, NEWS: Test for sys/sendfile.h and sendfile(), and if we don't have them use plain read/write instead. Remove unnecessary dependencies on sys/sendfile.h 2002-05-26 00:23 Martin Pool * autogen.sh: Don't say "make all", because on some platforms you might really need gmake. 2002-05-26 00:08 Martin Pool * autogen.sh: Need to also run aclocal to install automake stuff. Also need to run autoheader early on in the process, because automake depends on finding config.h.in. 2002-05-26 00:04 Martin Pool * NEWS: Note help with automake 2002-05-26 00:01 Martin Pool * autogen.sh: Handle ChangeLog 2002-05-25 23:57 Martin Pool * src/.cvsignore: More test cases 2002-05-25 23:55 Martin Pool * src/Makefile.am: Get rid of editing mistake. _SOURCES is a magic name for automake, so don't use it for common source. Thanks to Frerich Raabe. 2002-05-25 23:50 Martin Pool * autogen.sh: Add a script to do everything necessary to build from CVS. This is needed because automake requires a spliff to get out of bed, and the generated files are shipped in tarballs but not stored in CVS. 2002-05-25 23:47 Martin Pool * configure.ac: Fix shell syntax: square brackets can't be used in configure.ac because they clash with m4. 2002-05-25 19:23 Martin Pool * src/: Makefile.am, h_issource.c, t_issource: Add another test 2002-05-25 19:23 Martin Pool * configure.ac: chmod test files 2002-05-25 18:57 Martin Pool * src/: arg.c, distcc.c, distcc.h: Recognize the .ii extension that ccache uses for preprocessed C++ code. (Ian Reinhart Geiser) 2002-05-25 18:55 Martin Pool * NEWS: * Convert to using GNU automake and autoconf, so that distcc can better handle portability, distribution and testing. (Martin Pool) * Start adding some "make check" tests. (Martin Pool) 2002-05-25 18:51 Martin Pool * src/arg.c: Recognize the .ii extension that ccache uses for preprocessed C++ code. 2002-05-25 18:50 Martin Pool * src/: .cvsignore, Makefile.am, arg.c, distcc.h, h_exten.c, t_exten: Add a test harness and script to test the simplest function we have -- finding the extension of a filename. 2002-05-25 18:34 Martin Pool * src/GNUmakefile: This Makefile is no longer needed because we have automake. 2002-05-25 18:33 Martin Pool * .cvsignore, src/.cvsignore: Ignore automake-generated files 2002-05-25 16:02 Martin Pool * configure.ac, src/Makefile.am, src/help.c, src/trace.c: More automake integration fixes. Builds properly now. 2002-05-25 15:47 Martin Pool * .cvsignore, AUTHORS, COPYING, INSTALL, Makefile, Makefile.am, NEWS, OLDNEWS, configure.ac, src/.cvsignore, src/Makefile.am: Convert to automake. Don't know if it works yet. 2002-05-24 16:45 Martin Pool * linuxdoc/distcc.sgml: Add GNU FDL stuff. 2002-05-24 15:17 Martin Pool * src/: distcc.c, distcc.h, exec.c, NEWS: Only fiddle with the compiler's stdin/out/err when running on the server, not on the client. This should make cpp from stdin work. (Reported by Ian Reinhart Geiser from KDE.) 2002-05-24 15:15 Martin Pool * src/distcc.c: Doc. 2002-05-24 15:11 Martin Pool * src/: distcc.h, exec.c: Split out code to redirect stdin/out/err, because we don't want to do this locally. 2002-05-24 13:49 Martin Pool * Makefile: Add always_ChangeLog target 2002-05-24 13:47 Martin Pool * src/serve.c: Use a FIFO to feed preprocessed source from the daemon into the compiler, so that compilation can be overlapped with network transit. 2002-05-24 13:22 Martin Pool * src/NEWS: Support C++ compilation by correctly detecting prefixes. 2002-05-24 13:22 Martin Pool * src/arg.c: Better error messages for when we encounter an argument that is not a source file name. 2002-05-24 13:19 Martin Pool * src/arg.c: Fix little syntax error. 2002-05-24 13:18 Martin Pool * src/arg.c: Change code to recognize source files so that it will detect all the C++ variants. Based on a patch from ian reinhart geiser. Factor source file recognition into its own function. 2002-05-24 13:03 Martin Pool * src/arg.c: Refactor code to set file extension, so that we can handle things like "foo.cpp" where the source extension is longer than ".o". Based on a patch from ian reinhart geiser, but more defensive. 2002-05-23 16:19 Martin Pool * linuxdoc/distcc.sgml: Fix SGML. 2002-05-23 16:17 Martin Pool * linuxdoc/distcc.sgml: Texinfo can't handle having two headings with the same name. 2002-05-23 16:12 Martin Pool * linuxdoc/distcc.sgml: Add explanation of special meaning of "localhost" in DISTCC_HOSTS. Move results around. 2002-05-21 18:17 Martin Pool * src/: NEWS, OLDNEWS: Roll over NEWS 2002-05-21 18:10 Martin Pool * src/GNUmakefile: Set version to 0.2.99 2002-05-21 17:20 Martin Pool * src/serve.c: Doc. 2002-05-20 16:00 Martin Pool * linuxdoc/distcc.sgml: Fix SGML 2002-05-20 15:57 Martin Pool * linuxdoc/distcc.sgml: Add section about libtool. Add results for building glib-1.2. 2002-05-20 14:38 Martin Pool * src/GNUmakefile: linuxdoc/ subdir is no longer here. 2002-05-20 14:30 Martin Pool * linuxdoc/distcc.sgml: Cleaner CVS stuff. 2002-05-20 14:26 Martin Pool * linuxdoc/distcc.sgml: Cleaner CVS stuff. 2002-05-20 14:25 Martin Pool * linuxdoc/distcc.sgml: Better explanation of issues around SSH. 2002-05-20 14:06 Martin Pool * src/trace.c: Doc. 2002-05-20 14:02 Martin Pool * linuxdoc/distcc.sgml: Clarify handling of compiler error messages. 2002-05-20 13:54 Martin Pool * linuxdoc/.cvsignore: Better exclude specification 2002-05-20 13:54 Martin Pool * linuxdoc/: Makefile, footer.html: Add HTML footer 2002-05-20 13:46 Martin Pool * Makefile, cvs2cl.ufile: Add top-level makefile 2002-05-20 13:35 Martin Pool * src/NEWS: News for something that happened last week! 2002-05-20 13:23 Martin Pool * src/HACKING: Cleanup 2002-05-20 13:21 Martin Pool * linuxdoc/distcc.sgml: Add results. 2002-05-19 18:09 Martin Pool * linuxdoc/: .cvsignore, Makefile, distcc.sgml: Move directory 2002-05-17 15:45 Martin Pool * src/GNUmakefile: Set version to 0.2 2002-05-17 14:10 Martin Pool * src/help.c: Add email address 2002-05-17 14:09 Martin Pool * src/: GNUmakefile, distcc.c, distcc.h, dopt.c, help.c: Improve --help messages, and make all programs response to --version properly. 2002-05-17 13:45 Martin Pool * src/daemon.c: Doc. 2002-05-16 17:56 Martin Pool * src/arg.c: If -o is not specified, gcc dumps the object file in the current directory, not the source directory. Make our behaviour the same. 2002-05-16 17:27 Martin Pool * src/: arg.c, distcc.c, distcc.h: Try to handle cases like "gcc -c hello.c" by appending "-o hello.o" to the end. This doesn't work yet for files not in the current directory. 2002-05-16 15:53 Martin Pool * .cvsignore, src/GNUmakefile: Add a nice simple user manual 2002-05-16 13:48 Martin Pool * src/HACKING: Note about cpp performance. 2002-05-15 23:13 Martin Pool * src/HACKING: Doc. 2002-05-15 18:19 Martin Pool * src/: HACKING, tempfile.c, where.c: Doc. 2002-05-15 17:45 Martin Pool * src/where.c: Better trace msg 2002-05-15 17:44 Martin Pool * man/.cvsignore: Ignore generated 2002-05-15 17:44 Martin Pool * doc/distcc-irc.txt: Rough notes from irc 2002-05-15 17:38 Martin Pool * src/: distcc.h, tempfile.c, where.c: Use simple file locks to spread work across hosts 2002-05-15 17:23 Martin Pool * src/where.c: Split out code for parsing list of hosts, and actually picking a host to use. Doc about locking method for distributing work. 2002-05-15 16:15 Martin Pool * src/: GNUmakefile, bulk.c, distcc.c, distcc.h, rpc.h, serve.c, where.c: Back out of the compression changes; they seem like a premature optimization 2002-05-15 16:07 Martin Pool * src/HACKING: Scratch numbers on compression 2002-05-15 15:57 Martin Pool * src/serve.c: Use correct proto version 2002-05-15 15:54 Martin Pool * src/: bulk.c, distcc.c, io.h, rpc.h, serve.c: zlevel is passed everywhere but ignored 2002-05-15 15:51 Martin Pool * src/: GNUmakefile, distcc.c, serve.c: Server accepts GZIP token 2002-05-15 15:45 Martin Pool * src/HACKING: Note about server-side error handling 2002-05-15 15:42 Martin Pool * src/: distcc.c, distcc.h: Bump proto version to 2; send GZIP token in header to request compression 2002-05-15 15:35 Martin Pool * src/: distcc.c, distcc.h, where.c: Parse zlevel out of _HOSTS 2002-05-15 15:27 Martin Pool * src/: bulk.c, io.c, io.h: Factor out common methods of bulk transfer 2002-05-15 15:26 Martin Pool * src/GNUmakefile: Bump version 2002-05-15 15:20 Martin Pool * man/distcc.1: Note about mtimes 2002-05-15 15:13 Martin Pool * src/bulk.c: Doc 2002-05-15 15:10 Martin Pool * src/GNUmakefile: Set version to 1.0 2002-05-15 15:09 Martin Pool * .cvsignore, man/distcc.1, src/HACKING, src/distcc.c, src/trace.c, src/trace.h: Allow log messages from distcc to be separated from stderr 2002-05-15 15:01 Martin Pool * src/: GNUmakefile, bulk.c, rpc.c: Split out file transfer code 2002-05-15 14:56 Martin Pool * src/tempfile.c: Add quote 2002-05-15 14:56 Martin Pool * src/distcc.c: Handle --help 2002-05-15 14:56 Martin Pool * man/distcc.1: Add more links 2002-05-15 14:55 Martin Pool * man/Makefile: Add PDF target 2002-05-15 14:50 Martin Pool * src/distcc.c: Show environment variables in usage message for distcc 2002-05-13 13:30 Martin Pool * src/GNUmakefile: Add "install" target. 2002-05-13 13:27 Martin Pool * src/dopt.c: Fix dumb "break" mistake in option parsing. 2002-05-06 09:10 Martin Pool * src/dopt.c: Add --nice option 2002-05-05 19:23 Martin Pool * src/: GNUmakefile, daemon.c, distcc.h, dopt.c: Start adding daemon command-line handling 2002-05-05 19:22 Martin Pool * src/trace.c: Better formatting when not using the pid. 2002-05-05 19:21 Martin Pool * README: Note library dependencies 2002-05-02 15:17 Martin Pool * man/distcc.1: More stuff. 2002-05-02 14:25 Martin Pool * man/distcc.1: More manpage updates. 2002-05-02 13:26 Martin Pool * man/: Makefile, distcc.1: Add the start of a man page. 2002-05-01 12:42 Martin Pool * src/io.c: "i've always wanted to use sendfile(), but never had a reason until now" 2002-05-01 12:31 Martin Pool * README: Add author name. 2002-04-30 20:48 Martin Pool * README, src/README: Rearrange 2002-04-30 18:15 Martin Pool * src/: exec.c: Doc. 2002-04-30 18:06 Martin Pool * src/serve.c: Make file sizes correct even if compilation fails. 2002-04-30 18:05 Martin Pool * src/: distcc.h, serve.c, srvnet.c: daemon logs client names 2002-04-30 18:04 Martin Pool * src/exec.c: Doc 2002-04-30 17:50 Martin Pool * src/trace.c: you're never going to want program or pid in a syslog message, because it's redundant. 2002-04-30 17:48 Martin Pool * src/: serve.c, exec.c: Log job completion 2002-04-30 17:45 Martin Pool * src/daemon.c: Log opening of port 2002-04-30 17:38 Martin Pool * src/exec.c: If compiler finished OK, that's an INFO level message 2002-04-30 17:34 Martin Pool * src/: distcc.c, rpc.c, rpc.h, serve.c: Record size of files transferred 2002-04-30 17:31 Martin Pool * src/: daemon.c, trace.c, trace.h: More flexible trace formatting 2002-04-30 17:22 Martin Pool * src/trace.c: Fix stderr logging. 2002-04-30 17:19 Martin Pool * src/: daemon.c, trace.c, trace.h: distccd logs to syslog/daemon. 2002-04-30 17:13 Martin Pool * src/: trace.c, trace.h: Big rework of trace system so that the trace implementation gets to format the string, possibly using a helper function. 2002-04-30 16:35 Martin Pool * src/srvnet.c: Delete dead code 2002-04-30 15:46 Martin Pool * src/io.c: Don't ever just exit 2002-04-30 15:45 Martin Pool * src/daemon.c: Don't abort if accept() fails. 2002-04-30 15:29 Martin Pool * src/tempfile.c: Make cleanup code reusable. 2002-04-30 15:28 Martin Pool * src/srvnet.c: Need to listen() on socket before accept() 2002-04-30 15:20 Martin Pool * src/distcc.c: Fix silly pointer bug 2002-04-30 15:17 Martin Pool * src/: GNUmakefile, daemon.c, srvnet.c, util.h: Really simple standalone mode. 2002-04-30 14:43 Martin Pool * src/: GNUmakefile, daemon.c, distcc.h, serve.c: Split out daemon stuff in preparation for listening on our own socket. 2002-04-30 14:41 Martin Pool * src/io.c: Cast from gcc warning 2002-04-30 14:41 Martin Pool * src/distcc.c: Trace 2002-04-30 14:22 Martin Pool * src/: README, distcc.c: Add DISTCC_VERBOSE env var 2002-04-30 14:09 Martin Pool * src/rpc.c: Add necessary cast, thanks to gcc. 2002-04-30 14:09 Martin Pool * src/HACKING: Doc. 2002-04-30 14:04 Martin Pool * src/rpc.c: If we fail to receive a file, delete the destination rather than leaving it truncated. 2002-04-30 14:03 Martin Pool * src/: daemon.c, distcc.c: Don't send the .o file unless compilation succeeded. 2002-04-30 13:54 Martin Pool * src/distcc.c: If no build hosts are set, just run here. 2002-04-30 13:53 Martin Pool * src/GNUmakefile: Add targets to run cflow. 2002-04-30 13:50 Martin Pool * src/distcc.c: Doc. 2002-04-30 13:02 Martin Pool * src/distcc.c: Do clean up temporary files. 2002-04-30 13:00 Martin Pool * src/distcc.c: Better help message. 2002-04-30 12:58 Martin Pool * src/GNUmakefile: Turn on more warnings 2002-04-30 12:54 Martin Pool * src/where.c: Fix gcc warning. 2002-04-29 20:08 Martin Pool * src/clinet.c: Note from Huxley 2002-04-29 15:28 Martin Pool * src/where.c: Doc. 2002-04-29 15:23 Martin Pool * src/daemon.c: Doc. 2002-04-29 15:20 Martin Pool * src/: clinet.c, distcc.c: Doc. 2002-04-29 15:17 Martin Pool * src/clinet.c: Handle EPIPE as a regular error 2002-04-29 14:52 Martin Pool * src/daemon.c: Clean up temp files if build is successful 2002-04-29 14:50 Martin Pool * src/daemon.c: Docs about better performance. 2002-04-29 14:45 Martin Pool * src/where.c: Docs about better methods of choosing compile hosts. 2002-04-28 23:46 Martin Pool * src/: arg.c, clinet.c, daemon.c, io.c, where.c: Clean up 2002-04-28 23:43 Martin Pool * src/README: Notes on building the kernel 2002-04-28 23:05 Martin Pool * src/GNUmakefile: Change version to 0.1cvs 2002-04-28 22:50 Martin Pool * src/exec.c: Better messages 2002-04-28 22:50 Martin Pool * src/arg.c: Better quoting for commands 2002-04-28 22:45 Martin Pool * src/: README, distcc.c, distcc.h, exec.c: Make the magic name localhost Better execution messages 2002-04-28 22:32 Martin Pool * src/: README, distcc.c: Make the magic name LOCALHOST, not LOCAL 2002-04-28 22:30 Martin Pool * src/where.c: Randomize by pid/ppid, rather than time(), because it is likely that multiple copies might be forked within a second by make -j. 2002-04-28 22:29 Martin Pool * src/io.c: Fix headers 2002-04-28 20:54 Martin Pool * src/README: Add title. 2002-04-28 20:41 Martin Pool * src/: clinet.c, daemon.c, distcc.h, io.c, io.h: Also cork response from the server 2002-04-28 20:41 Martin Pool * src/trace.c: Larger log buffer for chunky gcc lines 2002-04-28 20:37 Martin Pool * src/distcc.c: Cork and uncork socket around request. 2002-04-28 20:36 Martin Pool * src/distcc.c: Cope properly when not running cpp. 2002-04-28 20:35 Martin Pool * src/: clinet.c, distcc.h: Add code to cork a socket 2002-04-28 20:26 Martin Pool * src/: exec.c, rpc.c: Better trace 2002-04-28 20:15 Martin Pool * src/: daemon.c, distcc.c: Fiddle debug and tempfile stuff to better support debugging. 2002-04-28 20:13 Martin Pool * src/README: Some initial numbers on performance building rsync. 2002-04-28 19:38 Martin Pool * src/clinet.c: Fix messages 2002-04-28 19:31 Martin Pool * src/io.c: Quieten trace 2002-04-28 19:27 Martin Pool * src/: distcc.c, distcc.h, exec.c, util.c, util.h: Show program and hostname in completion message. 2002-04-28 19:19 Martin Pool * src/io.c: Fix nasty bug that caused us to read much more than we wanted. 2002-04-28 19:16 Martin Pool * src/rpc.c: More trace 2002-04-28 19:16 Martin Pool * src/daemon.c: Fix tempfile names. 2002-04-28 19:07 Martin Pool * src/distcc.c: Better messages. 2002-04-28 19:04 Martin Pool * src/where.c: Typo. 2002-04-28 19:03 Martin Pool * src/tempfile.c: Better error message. 2002-04-28 19:02 Martin Pool * src/: clinet.c, distcc.c, distcc.h: Actually try to use a random remote host. 2002-04-28 18:58 Martin Pool * src/where.c: Add routine to pick a random build host 2002-04-28 18:58 Martin Pool * src/trace.h: Add rs_log_warning 2002-04-28 18:57 Martin Pool * src/io.c: Quieten warning 2002-04-28 18:55 Martin Pool * src/README: Doc 2002-04-28 17:02 Martin Pool * src/rpc.c: dcc_x_file: If a file does not exist, send it as empty rather than aborting. 2002-04-28 17:00 Martin Pool * src/distcc.c: If the remote compiler fails, we don't need to try again locally. (Actually, we might want to, but don't worry about that for now.) 2002-04-28 16:55 Martin Pool * src/: distcc.c, rpc.c, rpc.h: Receive and display remote stdout/stderr. 2002-04-28 16:52 Martin Pool * src/daemon.c: Capture and send compiler's stdout/stderr. 2002-04-28 16:47 Martin Pool * src/: daemon.c, distcc.c, distcc.h, exec.c, util.c, util.h: Get ready for catching compiler stdout/stderr. 2002-04-28 15:20 Martin Pool * src/distcc.c: Show proto ver in version info. 2002-04-28 15:19 Martin Pool * src/: clinet.c, distcc.c, daemon.c: Doc. 2002-04-28 15:15 Martin Pool * src/: GNUmakefile, where.c: Add where.c 2002-04-28 15:14 Martin Pool * src/: README, distcc.c, distcc.h, exec.c: Run cpp in background while trying to connect. 2002-04-28 15:13 Martin Pool * src/GNUmakefile: Should use CFLAGS to link too 2002-04-28 13:22 Martin Pool * src/distcc.c: Better message when compiler fails. 2002-04-28 13:19 Martin Pool * src/: distcc.c, distcc.h, exec.c: Get ready for async subcommands 2002-04-28 13:14 Martin Pool * src/arg.c: Better message 2002-04-28 13:12 Martin Pool * src/: GNUmakefile, arg.c, clinet.c, daemon.c, distcc.c, distcc.h, io.h, tempfile.c, util.c: More splint-based checks 2002-04-28 12:37 Martin Pool * src/tempfile.c: Check permissions on temporary dir 2002-04-28 12:33 Martin Pool * src/tempfile.c: Automatically set up temp dir when needed Fix temp dir permissions 2002-04-28 12:32 Martin Pool * src/GNUmakefile: Turn off dynamic dependencies for the moment 2002-04-28 12:29 Martin Pool * src/: GNUmakefile, arg.c, clinet.c, daemon.c, distcc.c, io.c, io.h, rpc.c, trace.c, trace.h, util.c: Splint codeups 2002-04-28 12:16 Martin Pool * src/trace.h: Remove broken non-gcc stuff 2002-04-28 12:15 Martin Pool * src/GNUmakefile: Add SPLINT target 2002-04-28 12:08 Martin Pool * src/: distcc.h, tempfile.c: Add routine to cleanup temporary files. 2002-04-28 12:03 Martin Pool * src/: daemon.c, distcc.c, distcc.h, io.c, tempfile.c: Better (secure?) temporary name routine. 2002-04-28 12:03 Martin Pool * src/arg.c: Doc 2002-04-25 20:03 Martin Pool * src/distcc.c: Doc. 2002-04-25 20:00 Martin Pool * src/io.c: Use a larger copy buffer. 2002-04-25 19:59 Martin Pool * src/distcc.c: Be quiet by default 2002-04-25 19:32 Martin Pool * src/: arg.c, daemon.c: Fix filename substitution code. 2002-04-25 19:26 Martin Pool * src/arg.c: Fix message 2002-04-25 19:24 Martin Pool * src/: daemon.c, exec.c, io.c, io.h: Split out code for reading length-preceded strings. 2002-04-25 19:11 Martin Pool * src/daemon.c: Properly nul-terminate argv strings 2002-04-25 19:07 Martin Pool * src/distcc.h: Fix header 2002-04-25 19:05 Martin Pool * src/: daemon.c, distcc.h: Drop job structure altogether. The server no longer needs to use the client's argument parsing system. 2002-04-25 19:00 Martin Pool * src/: arg.c, distcc.h: Drop dead code 2002-04-25 18:57 Martin Pool * src/rpc.c: Better log 2002-04-25 18:56 Martin Pool * src/: io.h, rpc.c: Rename to dcc_r_token 2002-04-25 18:54 Martin Pool * src/io.c: IO errors need not cause us to abort. 2002-04-25 18:52 Martin Pool * src/daemon.c: Generate our slightly more proper temporary names. 2002-04-25 18:51 Martin Pool * src/trace.h: Add rs_log_critical convenience. 2002-04-25 18:48 Martin Pool * src/io.c: dcc_expect_token: check expected token is sane, and if read fails then say what we were hoping for 2002-04-25 18:44 Martin Pool * src/trace.c: Show pid in log messages. 2002-04-25 18:43 Martin Pool * src/: arg.c, distcc.h: Add dcc_set_input 2002-04-25 18:37 Martin Pool * src/: arg.c, daemon.c, distcc.c, distcc.h, rpc.c, rpc.h: Clean argc, argv, wait status stuff out of job structure. 2002-04-25 18:28 Martin Pool * src/arg.c: Better log messages from arg scanner 2002-04-25 18:18 Martin Pool * src/distcc.c: Actually go ahead and run cpp if necessary. 2002-04-25 18:07 Martin Pool * src/exec.c: Doc. 2002-04-25 18:06 Martin Pool * src/: daemon.c, distcc.h, exec.c: Cleanup dcc_run_child 2002-04-25 18:01 Martin Pool * src/: arg.c, distcc.h, exec.c: Show whole command being executed. 2002-04-25 17:50 Martin Pool * src/distcc.c: log message 2002-04-25 17:42 Martin Pool * src/GNUmakefile: Sketchy routines to build temporary filenames 2002-04-25 17:38 Martin Pool * src/tempfile.c: Sketchy routines to build temporary filenames 2002-04-25 17:38 Martin Pool * src/distcc.c: Get closer to running cpp locally 2002-04-25 17:37 Martin Pool * src/: arg.c, distcc.h: Add more argv[] utilities 2002-04-25 17:09 Martin Pool * src/arg.c: Fix harmless glitch. Better message. 2002-04-25 17:07 Martin Pool * src/util.c: Fix inverted sense in str_startswith 2002-04-25 16:59 Martin Pool * src/: arg.c, daemon.c, distcc.c, distcc.h, exec.c: Prepare to run preprocessor on client 2002-04-25 15:46 Martin Pool * src/arg.c: Better handle the case of being passed a non-preprocessed file. 2002-04-25 14:12 Martin Pool * src/arg.c: Fix headers. 2002-04-25 14:12 Martin Pool * src/: util.c, util.h: Add str_startswith 2002-04-25 14:08 Martin Pool * src/: distcc.c, distcc.h: Start adding support for running cpp ourselves before going across the network. 2002-04-25 14:07 Martin Pool * src/daemon.c: Error out if we somehow get a request to run cpp on the server. 2002-04-25 14:04 Martin Pool * src/arg.c: Parse out -o options; also work out whether we ought to call cpp. 2002-04-25 13:34 Martin Pool * src/: arg.c, daemon.c, distcc.c, distcc.h: Start refactoring argument scanner. 2002-04-25 13:15 Martin Pool * src/rpc.c: Must truncate temp file as we start receiving. 2002-04-25 12:00 Martin Pool * src/GNUmakefile: Doc. 2002-04-25 11:59 Martin Pool * src/: GNUmakefile, Makefile: The dependency stuff in the makefile current requires GNU Make, so change the filename to reflect that. 2002-04-25 01:33 Martin Pool * src/: daemon.c, distcc.c, io.c, rpc.c, rpc.h: client now receives DOTO file from the server and stores it in the destination 2002-04-25 01:23 Martin Pool * src/: daemon.c, distcc.c, io.c, io.h, rpc.c, rpc.h: Send back compiler wait-status and .o file 2002-04-25 01:11 Martin Pool * src/: daemon.c, distcc.c, rpc.c, rpc.h: Client now waits for the start of the response from the server 2002-04-25 01:11 Martin Pool * src/Makefile: Add rpc.c Make clean cleans .d files 2002-04-25 00:27 Martin Pool * src/: distcc.h, exec.c: Examine and remember the cc exit code. 2002-04-25 00:18 Martin Pool * src/: daemon.c, distcc.c, distcc.h, exec.c, io.h: Server now starts sending a response back. 2002-04-25 00:04 Martin Pool * src/: arg.c, daemon.c, distcc.c, distcc.h: Improve server-side argument argument parsing 2002-04-24 23:52 Martin Pool * src/arg.c: Better debug for server-side substitution 2002-04-24 23:44 Martin Pool * src/util.c: fix file-style 2002-04-24 23:44 Martin Pool * src/distcc.c: message when sending is complete 2002-04-24 23:43 Martin Pool * src/: daemon.c, util.h: redirect stderr to prevent fouling socket 2002-04-24 23:30 Martin Pool * src/distcc.c: Clean up; add error checks. 2002-04-24 23:30 Martin Pool * src/clinet.c: Clean up imported code, and in particular log messages 2002-04-24 23:29 Martin Pool * src/arg.c: Fix comment 2002-04-24 23:29 Martin Pool * src/Makefile: Store version in Makefile 2002-04-24 23:17 Martin Pool * src/clinet.c: Copy in network code from rsync. Currently hardcoded to localhost:4200. 2002-04-24 18:05 Martin Pool * src/: .cvsignore, Makefile, clinet.c, distcc.c, distcc.h: Start changes to connect across the network rather than dumping to a file. 2002-04-24 16:29 Martin Pool * src/distcc.c: Doc 2002-04-24 16:13 Martin Pool * src/: Makefile, arg.c, daemon.c, distcc.c, distcc.h, exec.c, io.c: daemon will now actually compile programs 2002-04-24 00:51 Martin Pool * src/: daemon.c, distcc.c, distcc.h, exec.c, io.c, io.h: Make the server receive the .i file into a temporary file. 2002-04-24 00:50 Martin Pool * src/Makefile: Fix 'make clean' 2002-04-24 00:49 Martin Pool * src/.cvsignore: Ignore any .i files that might be around 2002-04-24 00:21 Martin Pool * src/: Makefile, distcc.c, distcc.h, exec.c: Split out code to run the compiler 2002-04-24 00:10 Martin Pool * src/: README, daemon.c, distcc.c, distcc.h, io.c, io.h, trace.h: Server now reads argv from network. 2002-04-23 17:37 Martin Pool * src/: daemon.c, distcc.c, distcc.h, io.c: Start adding code to let the daemon read requests. 2002-04-23 16:39 Martin Pool * src/io.c: Split out more common code. Send the bulk of the file. Add a no-op distccd. 2002-04-23 16:33 Martin Pool * src/: .cvsignore, Makefile, daemon.c, distcc.c, distcc.h: Split out more common code. Send the bulk of the file. Add a no-op distccd. 2002-04-23 14:55 Martin Pool * src/: .cvsignore, Makefile, distcc.c, distcc.h, trace.c, util.c: Split utilities into their own file 2002-04-23 14:44 Martin Pool * src/distcc.c: Add framework for sending requests to server, but just send them to a tmpfile instead. 2002-04-23 14:24 Martin Pool * src/distcc.c: Put arguments into a jobinfo_t struct. 2002-04-23 14:14 Martin Pool * src/distcc.c: Try to detect .i and .o files 2002-04-23 13:47 Martin Pool * src/distcc.c: Handle empty command line. 2002-04-23 13:25 Martin Pool * src/.cvsignore: Ignore built files 2002-04-23 13:24 Martin Pool * src/: trace.c, trace.h: Copy trace routines from librsync 2002-04-23 13:22 Martin Pool * src/: distcc.c, .cvsignore, HACKING, Makefile: Copy very simple code into public samba cvs distcc-3.1/source/install-sh0000750000175000017500000001273611115326647015160 0ustar wolffwolff#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 distcc-3.1/source/README0000640000175000017500000000504011115326647014023 0ustar wolffwolff distcc -- a free distributed C/C++ compiler system http://code.google.com/p/distcc/ by Martin Pool "pump" functionality added by Fergus Henderson, Nils Klarlund, Manos Renieris, and Craig Silverstein (Google Inc.) distcc is a program to distribute compilation of C or C++ code across several machines on a network. distcc should always generate the same results as a local compile, is simple to install and use, and is often two or more times faster than a local compile. Unlike other distributed build systems, distcc does not require all machines to share a filesystem, have synchronized clocks, or to have the same libraries or header files installed. Machines can be running different operating systems, as long as they have compatible binary formats or cross-compilers. By default, distcc sends the complete preprocessed source code across the network for each job, so all it requires of the volunteer machines is that they be running the distccd daemon, and that they have an appropriate compiler installed. The distcc "pump" functionality, added in distcc 3.0, improves on distcc by distributing not only compilation but also preprocessing to distcc servers. This requires that the server and client have the same system headers (the client takes responsibility for transmitting application-specific headers). Given that, distcc in pump mode yields the same results that distcc would in non-pump mode, but faster, since the preprocessor no longer runs locally. For more details on the pump functionality, see README.pump. distcc is not itself a compiler, but rather a front-end to the GNU C/C++ compiler (gcc), or another compiler of your choice. All the regular gcc options and features work as normal. distcc is designed to be used with GNU make's parallel-build feature (-j). Shipping files across the network takes time, but few cycles on the client machine. Any files that can be built remotely are essentially "for free" in terms of client CPU. This is even more true in "pump" mode, where the client does not even have to take time to preprocess the source files. distcc has been successfully used in environments with hundreds of distcc servers, supporting dozens of simultaneous compiles. distcc is now reasonably stable and can successfully compile the Linux kernel, rsync, KDE, GNOME (via GARNOME), Samba and Ethereal. distcc is nearly linearly scalable for small numbers of machines: for a typical case, three machines are 2.6 times faster than one. distcc is distributed under the GNU General Public Licence v2. distcc-3.1/source/lzo/0000750000175000017500000000000011115327755013750 5ustar wolffwolffdistcc-3.1/source/lzo/lzoconf.h0000640000175000017500000003540611115326642015576 0ustar wolffwolff/* 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 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 #endif #include #ifdef __cplusplus extern "C" { #endif /*********************************************************************** // LZO requires a conforming ************************************************************************/ #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 # 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 */ distcc-3.1/source/lzo/minilzo.h0000640000175000017500000000607111115326642015601 0ustar wolffwolff/* 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 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 */ distcc-3.1/source/lzo/minilzo.c0000640000175000017500000020525611115326642015602 0ustar wolffwolff/* 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 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 #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 #endif #include #ifndef __LZO_CONF_H #define __LZO_CONF_H #if !defined(__LZO_IN_MINILZO) # ifndef __LZOCONF_H # include # endif #endif #if defined(__BOUNDS_CHECKING_ON) # include #else # define BOUNDS_CHECKING_OFF_DURING(stmt) stmt # define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) #endif #if !defined(LZO_HAVE_CONFIG_H) # include # include # if !defined(NO_STDLIB_H) # include # endif # define HAVE_MEMCMP # define HAVE_MEMCPY # define HAVE_MEMMOVE # define HAVE_MEMSET #else # include # if defined(HAVE_STDDEF_H) # include # endif # if defined(STDC_HEADERS) # include # include # 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 # endif #endif #include #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 # if 1 && defined(__WATCOMC__) # include __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" "\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 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 #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 *****/ distcc-3.1/source/lzo/.stamp-conf.in0000640000175000017500000000007111115326642016416 0ustar wolffwolff## Force lzo directory to be created in build directory. distcc-3.1/source/packaging/0000750000175000017500000000000011115327757015072 5ustar wolffwolffdistcc-3.1/source/packaging/rpm.sh0000750000175000017500000000526611115326637016234 0ustar wolffwolff#!/bin/sh -e # Run this from the 'packaging' directory, just under rootdir # We can only build rpm packages, if the rpm build tools are installed if [ \! -x /usr/bin/rpmbuild ] then echo "Cannot find /usr/bin/rpmbuild. Not building an rpm." 1>&2 exit 0 fi # Check if we have a bad kernel + RPM combination; that is, a kernel # that does not support vdso, and a find-requires script that doesn't # notice that and special-case linux-gate as a result. # Background: # Versions of RPM prior to 4.4.1 incorrectly add a dependency on # 'linux-gate.so.1', which is a virtual dso in 2.6+ Linux # kernels. Since this is not a real lib provided by any package, the # resulting RPMs won't install due to failed dependency checks. # For the curious, more linux-gate details are documented at: # http://www.trilithium.com/johan/2005/08/linux-gate/ if ! cat /proc/self/maps | grep -q vdso; then if ! grep -q 'linux-gate' /usr/lib/rpm/find-requires; then echo 'ERROR: Your combination of RPM and kernel is buggy.' echo 'Upgrade to RPM 4.4.1-5 or later, or patch /usr/lib/rpm/find-requires' echo 'to special-case the "linux-gate" dependency.' echo 'see also http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=338515' exit 1 fi fi # Check the commandline flags PACKAGE="$1" VERSION="$2" fullname="${PACKAGE}-${VERSION}" archive=../$fullname.tar.gz if [ -z "$1" -o -z "$2" ] then echo "Usage: $0 " 1>&2 exit 0 fi # Double-check we're in the packages directory, just under rootdir if [ \! -r ../Makefile -a \! -r ../INSTALL ] then echo "Must run $0 in the 'packaging' directory, under the root directory." 1>&2 echo "Also, you must run \"make dist\" before running this script." 1>&2 exit 0 fi if [ \! -r "$archive" ] then echo "Cannot find $archive. Run \"make dist\" first." 1>&2 exit 0 fi # Create the directory where the input lives, and where the output should live RPM_SOURCE_DIR="/tmp/rpmsource-$fullname" RPM_BUILD_DIR="/tmp/rpmbuild-$fullname" trap 'rm -rf $RPM_SOURCE_DIR $RPM_BUILD_DIR; exit $?' EXIT SIGHUP SIGINT SIGTERM rm -rf "$RPM_SOURCE_DIR" "$RPM_BUILD_DIR" mkdir "$RPM_SOURCE_DIR" mkdir "$RPM_BUILD_DIR" cp "$archive" "$RPM_SOURCE_DIR" rpmbuild -bb RedHat/rpm.spec \ --define "NAME $PACKAGE" \ --define "VERSION $VERSION" \ --define "_sourcedir $RPM_SOURCE_DIR" \ --define "_builddir $RPM_BUILD_DIR" \ --define "_rpmdir $RPM_SOURCE_DIR" # Clean out any existing rpms from a previous build. rm -f "$PACKAGE"*[-._]"$VERSION"[-._]*.rpm # We want to get not only the main package but devel etc, hence the middle * mv "$RPM_SOURCE_DIR"/*/"$PACKAGE"-*"$VERSION"*.rpm . echo echo "The rpm package file(s) are located in $PWD:" ls *.rpm distcc-3.1/source/packaging/RedHat/0000750000175000017500000000000011115327757016241 5ustar wolffwolffdistcc-3.1/source/packaging/RedHat/rpm.spec0000640000175000017500000002274711115326637017724 0ustar wolffwolff%define RELEASE 1 %define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE} %define _prefix /usr %define _bindir %{_prefix}/bin %define _datadir %{_prefix}/share #%define _docdir %{_datadir}/doc/%{name}-%{version} %define _docdir %{_datadir}/doc/%{name} %define _libdir %{_prefix}/lib %define _mandir %{_datadir}/man %define _sysconfdir /etc Name: %NAME Summary: Client side program for distributed C/C++ compilations. Version: %VERSION Release: %rel Group: Development/Languages Url: https://code.google.com/p/distcc License: GPL Packager: Google Inc. Source: http://%{NAME}.googlecode.com/files/%{NAME}-%{VERSION}.tar.gz Distribution: Redhat 7 and above. BuildRoot: %{_tmppath}/%{name}-buildroot Prefix: %_prefix Provides: distcc Obsoletes: crosstool-distcc distcc-include-server %description distcc is a program to distribute compilation of C or C++ code across several machines on a network. distcc should always generate the same results as a local compile, is simple to install and use, and is often two or more times faster than a local compile. %prep %setup %build # Work around broken sendfile in 32 bit apps on some x86_64 systems ac_cv_func_sendfile=no ac_cv_header_sys_sendfile_h=no ./configure \ --prefix=%{_prefix} \ --bindir=%{_bindir} \ --sysconfdir=%{_sysconfdir} \ --datadir=%{_datadir} \ --with-docdir=%{_docdir} \ --mandir=%{_mandir} \ --enable-rfc2553 --with-included-popt # Get the list of files installed by the python install process # by asking make to tell setup.py to put it in python_install_record make RPM_OPT_FLAGS="$RPM_OPT_FLAGS" \ PYTHON_INSTALL_RECORD=python_install_record %install rm -rf $RPM_BUILD_ROOT make DESTDIR=${RPM_BUILD_ROOT} PYTHON_INSTALL_RECORD=python_install_record install # The remaining configuration files are installed here rather than by # 'make install' because their nature and their locations are too # system-specific. mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d install -m 644 packaging/RedHat/logrotate.d/distcc $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/distcc mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d install -m 644 packaging/RedHat/xinetd.d/distcc $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d/distcc mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/init.d install -m 755 packaging/RedHat/init.d/distcc $RPM_BUILD_ROOT%{_sysconfdir}/init.d/distcc # TODO(fergus): move the next five lines to 'make install'? mkdir -p $RPM_BUILD_ROOT/%{_libdir}/distcc ln -s %{_bindir}/distcc $RPM_BUILD_ROOT/%{_libdir}/distcc/cc ln -s %{_bindir}/distcc $RPM_BUILD_ROOT/%{_libdir}/distcc/c++ ln -s %{_bindir}/distcc $RPM_BUILD_ROOT/%{_libdir}/distcc/gcc ln -s %{_bindir}/distcc $RPM_BUILD_ROOT/%{_libdir}/distcc/g++ %clean rm -rf $RPM_BUILD_ROOT %files -f python_install_record %defattr(-, root, root, 0755) %{_bindir}/distcc %{_bindir}/distccmon-text %{_bindir}/lsdistcc %{_libdir}/distcc %{_bindir}/pump %dir %{_sysconfdir}/distcc %config %{_sysconfdir}/distcc/hosts %doc %{_mandir}/man1/distcc.1.gz %doc %{_mandir}/man1/distccmon-text.1.gz %doc %{_mandir}/man1/pump.1.gz %doc %{_mandir}/man1/include_server.1.gz %doc %{_docdir} %package server Summary: Server side program for distributed C/C++ compilations. Group: Development/Languages Provides: distccd Obsoletes: crosstool-distcc-server %description server distcc is a program to distribute compilation of C or C++ code across several machines on a network. distcc should always generate the same results as a local compile, is simple to install and use, and is often two or more times faster than a local compile. %files server %defattr(-, root, root, 0755) %{_bindir}/distccd %dir %{_sysconfdir}/logrotate.d %config %{_sysconfdir}/logrotate.d/distcc # Don't list init.d dir because on Red Hat it's a symlink owned by # chkconfig, so it causes a conflict on install. #%dir %{_sysconfdir}/init.d %config %{_sysconfdir}/init.d/distcc %dir %{_sysconfdir}/xinetd.d/ %config %{_sysconfdir}/xinetd.d/distcc %dir %{_sysconfdir}/distcc %config %{_sysconfdir}/distcc/clients.allow %config %{_sysconfdir}/distcc/commands.allow.sh %dir %{_sysconfdir}/default %config %{_sysconfdir}/default/distcc %doc %{_mandir}/man1/distccd.1.gz %pre server %post server DISTCC_USER=distcc if [ -s /etc/redhat-release ]; then # sadly, can't useradd -s /sbin/nologin on rh71, since # then starting the service as user distcc fails, # since it uses su - without overriding the shell :-( # See https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=26894 /sbin/service distcc stop &>/dev/null || : if fgrep 'nice initlog $INITLOG_ARGS -c "su - $user' /etc/init.d/functions | fgrep -v '.-s ' > /dev/null 2>&1 ; then # Kludge: for Red Hat 6.2, don't use -s /sbin/nologin /usr/sbin/useradd -d /var/run/distcc -m -r $DISTCC_USER &>/dev/null || : else # but do for everyone else /usr/sbin/useradd -d /var/run/distcc -m -r -s /sbin/nologin $DISTCC_USER &>/dev/null || : fi else echo Creating $DISTCC_USER user... if ! id $DISTCC_USER > /dev/null 2>&1 ; then if ! id -g $DISTCC_USER > /dev/null 2>&1 ; then addgroup --system --gid 11 $DISTCC_USER fi adduser --quiet --system --gid 11 \ --home / --no-create-home --uid 15 $DISTCC_USER fi fi DISTCC_LOGFILE=/var/log/distccd.log if [ ! -s $DISTCC_LOGFILE ]; then touch $DISTCC_LOGFILE chown ${DISTCC_USER}:adm $DISTCC_LOGFILE chmod 640 $DISTCC_LOGFILE fi if ! grep -q "3632/tcp" /etc/services; then echo -e "distcc\t\t3632/tcp\t\t\t# Distcc Distributed Compiler" >> /etc/services fi if ! grep -q "^distcc:" /etc/hosts.allow; then echo -e "distcc:\t127.0.0.1" >> /etc/hosts.allow fi # Update runlevel settings and start daemon. if [ -s /etc/redhat-release ]; then /sbin/chkconfig --add distcc /etc/init.d/distcc start || exit 0 else if [ -x "/etc/init.d/distcc" ]; then update-rc.d -f distcc remove >/dev/null update-rc.d distcc defaults 95 05 >/dev/null if [ -x /usr/sbin/invoke-rc.d ]; then start_command="invoke-rc.d distcc start" else start_command="/etc/init.d/distcc start" fi $start_command || { echo "To enable distcc's TCP mode, you should edit these files" echo " %{_sysconfdir}/distcc/clients.allow" echo " %{_sysconfdir}/distcc/commands.allow.sh" echo "and then run (as root)" echo " $start_command" echo "For more info, including alternatives to TCP mode, see" echo "%{_docdir}/INSTALL and %{_docdir}/examples/README." } fi fi %preun server # Remove hosts.allow entry. if grep -q "^distcc:" /etc/hosts.allow; then sed -e "/^distcc/d" /etc/hosts.allow > /etc/hosts.allow.new mv /etc/hosts.allow.new /etc/hosts.allow fi # Stop daemon and clear runlevel settings. if [ -s /etc/redhat-release ]; then if [ $1 -eq 0 ]; then /sbin/service distcc stop &>/dev/null || : fi # chkconfig --del must run before deleting init script. /sbin/chkconfig --del distcc else if [ -x "/etc/init.d/distcc" ]; then if [ -x /usr/sbin/invoke-rc.d ] ; then invoke-rc.d distcc stop || exit 0 else /etc/init.d/distcc stop || exit 0 fi fi fi %postun server # TODO(mtm) Should Red Hat also remove user/group? if [ -s /etc/debian_version ]; then case "$1" in purge) deluser --quiet --system distcc delgroup --quiet --system distcc ;; remove) ;; upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) ;; *) echo "postrm called with unknown argument \`$1'" >&2 exit 1 ;; esac if [ "$1" = "purge" ] ; then # update-rc.d must run after deleting init script. update-rc.d distcc remove >/dev/null || exit 0 fi fi %changelog * Sat Mar 12 2008 Craig Silverstein 3.0-1 - Updated to 3.0 - Added include-server files - useradd is run in post- rather than pre-install - distcc server is automatically started - Remove source package generation - Man pages are now unzipped - Deb packages now also built, using alien * Sat May 31 2003 Terry Griffin 2.5-2 - Updated to 2.5 * Sat May 24 2003 Terry Griffin 2.4.2-2 - Updated to 2.4.2 * Sat May 17 2003 Terry Griffin 2.3-2 - Updated to 2.3 * Sun May 04 2003 Terry Griffin 2.1-2 - Updated to 2.1 - Added symbolic links for masquerade mode * Fri Mar 28 2003 Terry Griffin 2.0.1-2 - Updated to 2.0.1 - Removed info file from document list. * Tue Feb 25 2003 Terry Griffin 1.2.1-2 - Updated to 1.2.1 * Mon Jan 27 2003 Terry Griffin 1.1-2 - Updated to 1.1 - Minor improvements to the RPM spec file * Mon Dec 16 2002 Terry Griffin 0.15-2 - Changed server user back to 'nobody' * Fri Dec 13 2002 Terry Griffin 0.15-2 - Updated to 0.15 - Changed port number in server configs to 3632 * Sat Nov 23 2002 Terry Griffin 0.14-2 - Updated to 0.14 - Major rework of the RPM spec file - Added Red Hat server config files for both xinetd and SysV init. - Change server user to daemon. * Sat Nov 09 2002 Terry Griffin 0.12-1 - Updated to 0.12 * Thu Oct 10 2002 Terry Griffin 0.11-3 - First binary packages for Red Hat 8.x - Fixed xinetd config file for location of distccd. * Mon Sep 30 2002 Terry Griffin 0.11-2 - Moved distccd back to /usr/bin from /usr/sbin. * Sat Sep 28 2002 Terry Griffin 0.11-1 - Initial build (Red Hat 7.x) - Client and server in separate binary packages - Added xinetd config file - Moved distccd to /usr/sbin - Added version number suffix to the documentation directory distcc-3.1/source/packaging/RedHat/init.d/0000750000175000017500000000000011115327757017426 5ustar wolffwolffdistcc-3.1/source/packaging/RedHat/init.d/distcc0000640000175000017500000001232711115326637020624 0ustar wolffwolff#!/bin/bash # # /etc/rc.d/init.d/distcc # # Starts the distccd daemon # # WARNING: Don't enable on untrusted networks # # NOTE: Allows access from all networks listed in clients.allow # clients.allow is searched for in directories # /etc/distcc/`dnsdomainname`/clients.allow # /etc/distcc/clients.allow # Format of clients.allow is # addr/size # addr/size # addr/size # etc. e.g. # 196.168.0.0/16 # 127.0.0.0/8 # # chkconfig: - 80 20 # description: Start the distcc daemon # processname: distccd # # # Determine which kind of configuration we're using # system=unknown if [ -f /etc/debian_version ]; then system=debian elif [ -f /etc/redhat-release ]; then system=redhat else echo "$0: Unknown system, please port and contact distcc-admin@google.com" 1>&2 exit 1 fi OPTIONS="--daemon --stats --job-lifetime=1200" USER=distcc PROG="distccd" PIDFILE=/var/run/$PROG.pid EXEC="/usr/bin/distccd" if [ -f /etc/sitename.install ]; then # Debian? DOMAIN=`cat /etc/sitename.install` if [ -d /etc/site/current/distcc ]; then CONFIGDIR=/etc/site/current/distcc else CONFIGDIR=/etc/distcc fi NORESTART=$CONFIGDIR/no-restart else # RedHat? DOMAIN=`/bin/dnsdomainname` CONFIGDIR=/etc/distcc NORESTART=$CONFIGDIR/no-restart fi if [ $system = redhat ]; then . /etc/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ ${NETWORKING} = "no" ] && exit 0 fi if [ $system = debian ]; then . /lib/lsb/init-functions . /etc/default/distcc thisscript="$0" if [ ! -f "$thisscript" ]; then echo "$0: Cannot find myself" 1>&2 exit 1 fi if [ "$STARTDISTCC" != "true" ] ; then echo "STARTDISTCC is set to false in /etc/default/distcc" echo "$something is not starting" exit 0 fi touch $PIDFILE chown $USER $PIDFILE fi # Tell distccd to store temp files in /var/tmp/distcc to avoid filling up / # The sysadmin may want to make /var/tmp/distcc be a symlink to a # directory on a larger partition (hence the /. on the chown) TMPDIR=/var/tmp/distcc export TMPDIR mkdir -p $TMPDIR chown $USER $TMPDIR/. rm -rf $TMPDIR/* || : chmod 700 $TMPDIR RETVAL=0 [ -x /usr/bin/distccd ] || exit 0 ALLOWFILE="" if test -f $CONFIGDIR/$DOMAIN/clients.allow; then ALLOWFILE=$CONFIGDIR/$DOMAIN/clients.allow elif test -f $CONFIGDIR/clients.allow; then ALLOWFILE=$CONFIGDIR/clients.allow else echo "$0: no clients allowed" exit 1 fi if test "$ALLOWFILE"x != x; then ALLOW_OPTIONS=$(sed -e 's/#.*$//' -e '/^[ ]*$/d' -e 's/^/--allow=/' < $ALLOWFILE) OPTIONS="$OPTIONS $ALLOW_OPTIONS" fi COMMANDFILE="" if test -f $CONFIGDIR/$DOMAIN/commands.allow.sh; then COMMANDFILE=$CONFIGDIR/$DOMAIN/commands.allow.sh elif test -f $CONFIGDIR/commands.allow.sh; then COMMANDFILE=$CONFIGDIR/commands.allow.sh fi mkdir -p /var/state/distcc CMDLIST=/var/state/distcc/commands.allow rh_start() { echo -n "Starting $PROG" if [ -f $NORESTART ] then echo "failed -- $NORESTART present" return 1 fi env="TMPDIR=$TMPDIR" if [ -n "$COMMANDFILE" ]; then : > $CMDLIST . $COMMANDFILE if [ "$DISTCC_CMDLIST" ]; then env="$env DISTCC_CMDLIST=$DISTCC_CMDLIST" fi if [ "$DISTCC_CMDLIST_NUMWORDS" ]; then env="$env DISTCC_CMDLIST_NUMWORDS=$DISTCC_CMDLIST_NUMWORDS" fi fi daemon --user $USER $env $PROG $OPTIONS RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$PROG return $RETVAL } rh_stop() { echo -n "Shutting down $PROG" killproc $PROG RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$PROG return $RETVAL } redhat() { case "$1" in start) rh_start ;; stop) rh_stop ;; status) status $PROG RETVAL=$? ;; restart|reload) rh_stop rh_start RETVAL=$? ;; condrestart) if [ -f /var/lock/subsys/$PROG ]; then rh_stop rh_start RETVAL=$? fi ;; *) echo $"Usage $0 {start|stop|restart|condrestart|status}" exit 1 esac } deb_start() { log_begin_msg "Starting $PROG..." if [ -f $NORESTART ] then log_end_msg 1 echo "distcc start failed -- $NORESTART present" return 1 fi if [ -n "$COMMANDFILE" ]; then : > $CMDLIST . $COMMANDFILE export DISTCC_CMDLIST export DISTCC_CMDLIST_NUMWORDS fi export TMPDIR=$TMPDIR start-stop-daemon --start --name distccd --pidfile $PIDFILE -m --chuid $USER --exec $EXEC -- $OPTIONS RETVAL=$? log_end_msg $RETVAL return $RETVAL } deb_stop() { log_begin_msg "Shutting down $PROG..." start-stop-daemon --stop --name distccd --retry 30 RETVAL=$? [ $RETVAL -eq 0 ] || log_success_msg "$PROG not running?" log_end_msg $RETVAL [ $RETVAL -eq 0 ] && rm -f $PIDFILE return $RETVAL } debian() { case "$1" in start) deb_start ;; stop) deb_stop ;; restart|reload) deb_stop deb_start RETVAL=$? ;; condrestart) if [ -f /var/lock/subsys/$PROG ]; then deb_stop deb_start RETVAL=$? fi ;; *) echo $"Usage $0 {start|stop|restart|condrestart}" exit 1 esac } # See how we were called. RETVAL=0 if [ $system = debian ]; then debian "$@" elif [ $system = redhat ]; then redhat "$@" fi exit $RETVAL distcc-3.1/source/packaging/RedHat/default/0000750000175000017500000000000011115327757017665 5ustar wolffwolffdistcc-3.1/source/packaging/RedHat/default/distcc0000640000175000017500000000002111115326637021047 0ustar wolffwolffSTARTDISTCC=true distcc-3.1/source/packaging/RedHat/conf/0000750000175000017500000000000011115327757017166 5ustar wolffwolffdistcc-3.1/source/packaging/RedHat/conf/commands.allow.sh0000640000175000017500000000334311115326637022440 0ustar wolffwolff#!/bin/sh # --- /etc/site/current/distcc/commands.allow.sh ---------------------- # # This file is a shell script that gets sourced by /etc/init.d/distcc. # It's purpose is to optionally set the following environment # variables, which affect the behaviour of distccd: # # DISTCC_CMDLIST # If the environment variable DISTCC_CMDLIST is set, distccd will # load a list of supported commands from the file named by # DISTCC_CMDLIST, and will refuse to serve any command whose last # DISTCC_CMDLIST_MATCHWORDS last words do not match those of a # command in that list. See the comments in src/serve.c. # # DISTCC_CMDLIST_NUMWORDS # The number of words, from the end of the command, to match. The # default is 1. # # The interface to this script is as follows. # Input variables: # CMDLIST: this variable will hold the full path of the commands.allow file. # Side effects: # This script should write into the commands.allow file specified by # $CMDLIST. It should write the list of allowable commands, one per line. # Output variables: # DISTCC_CMDLIST and DISTCC_CMDLIST_NUMWORDS. See above. #-----------------------------------------------------------------------------# # Here are the parts that you may want to modify. numwords=1 allowed_compilers=" /usr/bin/cc /usr/bin/c++ /usr/bin/c89 /usr/bin/c99 /usr/bin/gcc /usr/bin/g++ /usr/bin/*gcc-* /usr/bin/*g++-* " # You shouldn't need to alter anything below here. [ "$CMDLIST" ] || { echo "$0: don't run this script directly!" >&2 echo "Run /etc/init.d/distcc (or equivalent) instead." >&2 exit 1 } echo $allowed_compilers | tr ' ' '\n' > $CMDLIST DISTCC_CMDLIST=$CMDLIST DISTCC_CMDLIST_NUMWORDS=$numwords distcc-3.1/source/packaging/RedHat/conf/hosts0000640000175000017500000000031311115326637020243 0ustar wolffwolff# --- /etc/distcc/hosts ----------------------- # See the "Hosts Specification" section of # "man distcc" for the format of this file. # # By default, just test that it works in loopback mode. 127.0.0.1 distcc-3.1/source/packaging/RedHat/conf/clients.allow0000640000175000017500000000254111115326637021666 0ustar wolffwolff# Comments start with "#" and go to end of line. Non-comment lines should # contain entries suitable for passing to the --allow option of distccd, e.g. # 192.168.1.100 # 192.168.2.0/8 # # From the distccd man page: # -a, --allow IPADDR[/MASK] # Instructs distccd to accept connections from the IP address # IPADDR. A CIDR mask length can be supplied optionally after a # trailing slash, e.g. 192.168.0.0/24, in which case addresses # that match in the most significant MASK bits will be allowed. # If no --allow options are specified, no clients are allowed! # Unauthorized connections are rejected by closing the TCP connec- # tion immediately. A warning is logged on the server but nothing # is sent to the client. # # You should only allow trusted hosts to connect to distccd in TCP mode. # You should assume that any user on the trusted hosts can (with some # effort) run arbitrary commands as the distcc user on the distccd host. # If this is not acceptible, then you should leave this config file empty # (apart from comments) and thus only allow SSH mode rather than TCP mode. # However, be aware that SSH mode has poorer performance than TCP mode. # Add your trusted hosts here, e.g. start by uncommented the line below. # 127.0.0.1 distcc-3.1/source/packaging/RedHat/xinetd.d/0000750000175000017500000000000011115327757017756 5ustar wolffwolffdistcc-3.1/source/packaging/RedHat/xinetd.d/distcc0000640000175000017500000000051511115326637021150 0ustar wolffwolff# default: on # description: distccd serves C/C++ compilation requests from distcc clients. # WARNING: This service should ONLY be used on trusted networks. service distcc { socket_type = stream protocol = tcp port = 3632 wait = no user = nobody server = /usr/bin/distccd server_args = --inetd disable = yes } distcc-3.1/source/packaging/RedHat/logrotate.d/0000750000175000017500000000000011115327757020463 5ustar wolffwolffdistcc-3.1/source/packaging/RedHat/logrotate.d/distcc0000640000175000017500000000046311115326636021656 0ustar wolffwolff# logrotate.d example configuration for distcc, contributed by Dag # Wieers. # The "copytruncate" option means distcc can keep appending to the # same filehandle. You would otherwise need to shut down and restart # distccd. /var/log/distccd.log { missingok copytruncate notifempty } distcc-3.1/source/packaging/googlecode_upload.py0000750000175000017500000003571511115326637021131 0ustar wolffwolff#!/usr/bin/env python # # Copyright 2006, 2007 Google Inc. All Rights Reserved. # Author: danderson@google.com (David Anderson) # # Modifications for distcc Copyright 2008 Google Inc. # Author: Craig Silverstein. # # Script for uploading files to a Google Code project. # # This is intended to be both a useful script for people who want to # streamline project uploads and a reference implementation for # uploading files to Google Code projects. # # To upload a file to Google Code, you need to provide a path to the # file on your local machine, a small summary of what the file is, a # project name, and a valid account that is a member or owner of that # project. You can optionally provide a list of labels that apply to # the file. The file will be uploaded under the same name that it has # in your local filesystem (that is, the "basename" or last path # component). Run the script with '--help' to get the exact syntax # and available options. # # Note that the upload script requests that you enter your # googlecode.com password. This is NOT your Gmail account password! # This is the password you use on googlecode.com for committing to # Subversion and uploading files. You can find your password by going # to http://code.google.com/hosting/settings when logged in with your # Gmail account. If you have already committed to your project's # Subversion repository, the script will automatically retrieve your # credentials from there (unless disabled, see the output of '--help' # for details). # # If you are looking at this script as a reference for implementing # your own Google Code file uploader, then you should take a look at # the upload() function, which is the meat of the uploader. You # basically need to build a multipart/form-data POST request with the # right fields and send it to https://PROJECT.googlecode.com/files . # Authenticate the request using HTTP Basic authentication, as is # shown below. # # Licensed under the terms of the Apache Software License 2.0: # http://www.apache.org/licenses/LICENSE-2.0 # # Questions, comments, feature requests and patches are most welcome. # Please direct all of these to the Google Code users group: # http://groups.google.com/group/google-code-hosting """Google Code file uploader script. """ __author__ = 'danderson@google.com (David Anderson)' import httplib import os.path import optparse import getpass import base64 import sys import re def extract_version(project, file_paths): """Given a list of filenames belonging to a given Google Code project, derive from that the version number. Do this by looking for a .tar.gz, .tgz. .tar.bz2, or .zip file, and assume those are named -.. Verify by making sure and are substrings in all given files. Returns version, or empty string if couldn't figure it out. """ for file_path in file_paths: m = re.match(r'%s-([0-9]+\.[0-9]+.*)\.(tar\.gz|tgz|tar\.bz2|zip)' % project, os.path.basename(file_path), re.I) if m: version = m.group(1) break else: # for ended without finding anything return '' # Now verify the project and version are everywhere for file_path in file_paths: if file_path.find(version) == -1: return '' return version def derive_summary_and_labels(file_path, package, version): """Derive a summary associated with a file given some file information. Returns (summary, list_of_labels). Raises ValueError if there was a problem figuring out the summary. Given a filename like google_perftools-0.94.rpm, this function would derive * summary = "RPM for google_perftools 0.94" * labels = ["Type-Package", "OpSys-Linux"] """ if file_path.find('distcc-server') != -1: project = 'Distcc server (distccd)' elif file_path.find('distcc') != -1: if file_path.find('.tar') != -1: # The source distribution has both client and server project = 'Distcc (both client and server)' else: project = 'Distcc client (distcc)' else: raise ValueError("Unknown project name for '%s'" % file_path) if (file_path.endswith('.tar.gz') or file_path.endswith('.tgz') or file_path.endswith('.tar.bz2')): return ('Tarball for %s %s' % (project, version), ('Type-Source', 'OpSys-All')) if file_path.endswith('.zip'): return ('Zip file for %s %s' % (project, version), ('Type-Source', 'OpSys-Windows')) if file_path.endswith('.deb') and file_path.find('-dev_') != -1: return ('Development deb for %s %s' % (project, version), ('Type-Package', 'OpSys-Linux')) if file_path.endswith('.deb'): return ('Deb for %s %s' % (project, version), ('Type-Package', 'OpSys-Linux')) if file_path.endswith('.src.rpm') and file_path.find('-devel-') != -1: return ('Source-code RPM for %s %s' % (project, version), ('Type-Package', 'OpSys-Linux')) if file_path.endswith('.rpm') and file_path.find('-devel-') != -1: return ('Development RPM for %s %s' % (project, version), ('Type-Package', 'OpSys-Linux')) if file_path.endswith('.rpm'): return ('RPM for %s %s' % (project, version), ('Type-Package', 'OpSys-Linux')) raise ValueError("Unknown file extension for '%s'" % file_path) def get_svn_config_dir(): """Return user's Subversion configuration directory.""" try: from win32com.shell.shell import SHGetFolderPath import win32com.shell.shellcon except ImportError: # If we can't import the win32api, just use ~; this is right on unix, and # returns not entirely unreasonable results on Windows. return os.path.expanduser('~/.subversion') # We're on Windows with win32api; use APPDATA. return os.path.join(SHGetFolderPath(0, win32com.shell.shellcon.CSIDL_APPDATA, 0, 0).encode('utf-8'), 'Subversion') def get_svn_auth(project_name, config_dir): """Return (username, password) for project_name in config_dir.""" # Default to returning nothing. result = (None, None) try: from svn.core import SVN_AUTH_CRED_SIMPLE, svn_config_read_auth_data from svn.core import SubversionException except ImportError: return result realm = (' Google Code Subversion Repository' % project_name) # auth may be none even if no exception is raised, e.g. if config_dir does # not exist, or exists but has no entry for realm. try: auth = svn_config_read_auth_data(SVN_AUTH_CRED_SIMPLE, realm, config_dir) except SubversionException: auth = None if auth is not None: try: result = (auth['username'], auth['password']) except KeyError: # Missing the keys, so return nothing. pass return result def upload(file, project_name, user_name, password, summary, labels=None): """Upload a file to a Google Code project's file server. Args: file: The local path to the file. project_name: The name of your project on Google Code. user_name: Your Google account name. password: The googlecode.com password for your account. Note that this is NOT your global Google Account password! summary: A small description for the file. labels: an optional list of label strings with which to tag the file. Returns: a tuple: http_status: 201 if the upload succeeded, something else if an error occured. http_reason: The human-readable string associated with http_status file_url: If the upload succeeded, the URL of the file on Google Code, None otherwise. """ # The login is the user part of user@gmail.com. If the login provided # is in the full user@domain form, strip it down. if '@' in user_name: user_name = user_name[:user_name.index('@')] form_fields = [('summary', summary)] if labels is not None: form_fields.extend([('label', l.strip()) for l in labels]) content_type, body = encode_upload_request(form_fields, file) upload_host = '%s.googlecode.com' % project_name upload_uri = '/files' auth_token = base64.b64encode('%s:%s'% (user_name, password)) headers = { 'Authorization': 'Basic %s' % auth_token, 'User-Agent': 'Googlecode.com uploader v0.9.4', 'Content-Type': content_type, } server = httplib.HTTPSConnection(upload_host) server.request('POST', upload_uri, body, headers) resp = server.getresponse() server.close() if resp.status == 201: location = resp.getheader('Location', None) else: location = None return resp.status, resp.reason, location def encode_upload_request(fields, file_path): """Encode the given fields and file into a multipart form body. fields is a sequence of (name, value) pairs. file is the path of the file to upload. The file will be uploaded to Google Code with the same file name. Returns: (content_type, body) ready for httplib.HTTP instance """ BOUNDARY = '----------Googlecode_boundary_reindeer_flotilla' CRLF = '\r\n' body = [] # Add the metadata about the upload first for key, value in fields: body.extend( ['--' + BOUNDARY, 'Content-Disposition: form-data; name="%s"' % key, '', value, ]) # Now add the file itself file_name = os.path.basename(file_path) f = open(file_path, 'rb') file_content = f.read() f.close() body.extend( ['--' + BOUNDARY, 'Content-Disposition: form-data; name="filename"; filename="%s"' % file_name, # The upload server determines the mime-type, no need to set it. 'Content-Type: application/octet-stream', '', file_content, ]) # Finalize the form body body.extend(['--' + BOUNDARY + '--', '']) return 'multipart/form-data; boundary=%s' % BOUNDARY, CRLF.join(body) def upload_find_auth(file_path, project_name, summary, labels=None, config_dir=None, user_name=None, tries=3): """Find credentials and upload a file to a Google Code project's file server. file_path, project_name, summary, and labels are passed as-is to upload. If config_dir is None, try get_svn_config_dir(); if it is 'none', skip trying the Subversion configuration entirely. If user_name is not None, use it for the first attempt; prompt for subsequent attempts. Args: file_path: The local path to the file. project_name: The name of your project on Google Code. summary: A small description for the file. labels: an optional list of label strings with which to tag the file. config_dir: Path to Subversion configuration directory, 'none', or None. user_name: Your Google account name. tries: How many attempts to make. """ if config_dir != 'none': # Try to load username/password from svn config for first try. if config_dir is None: config_dir = get_svn_config_dir() (svn_username, password) = get_svn_auth(project_name, config_dir) if user_name is None: # If username was not supplied by caller, use svn config. user_name = svn_username else: # Just initialize password for the first try. password = None while tries > 0: if user_name is None: # Read username if not specified or loaded from svn config, or on # subsequent tries. sys.stdout.write('Please enter your googlecode.com username: ') sys.stdout.flush() user_name = sys.stdin.readline().rstrip() if password is None: # Read password if not loaded from svn config, or on subsequent tries. print 'Please enter your googlecode.com password.' print '** Note that this is NOT your Gmail account password! **' print 'It is the password you use to access Subversion repositories.' prompt = 'Password (listed at http://code.google.com/hosting/settings): ' password = getpass.getpass(prompt) status, reason, url = upload(file_path, project_name, user_name, password, summary, labels) # Returns 403 Forbidden instead of 401 Unauthorized for bad # credentials as of 2007-07-17. if status in [httplib.FORBIDDEN, httplib.UNAUTHORIZED]: # Rest for another try. user_name = password = None tries = tries - 1 else: # We're done. break return status, reason, url def main(): parser = optparse.OptionParser(usage='googlecode-upload.py -s SUMMARY ' '-p PROJECT [options] FILE [FILE] ...') parser.add_option('--config-dir', dest='config_dir', metavar='DIR', help='read svn auth data from DIR' ' ("none" means not to use svn auth data)') parser.add_option('-s', '--summary', dest='summary', help='Short description of the file' ' (if not set, description will derive from filename)') parser.add_option('-u', '--user', dest='user', help='Your Google Code username' ' (if not set, the program will prompt you)') parser.add_option('-l', '--labels', dest='labels', help='An optional list of labels to attach to the file' ' (if not set, labels will derive from filename)') options, args = parser.parse_args() if not args: parser.error('File(s) to upload not provided.') project = 'distcc' # We hard-code that. :-) if options.labels: user_labels = options.labels.split(',') else: user_labels = None default_user = os.environ.get('USER', 'unknown') if options.user: user = options.user else: print 'Enter username ( takes the default of "%s"):' % default_user, user = raw_input() or default_user prompt = 'Password (listed at http://code.google.com/hosting/settings): ' password = getpass.getpass(prompt) version = extract_version(project, args) successes = 0 failures = 0 for file_path in args: # If the user did not specify the summary or labels, derive these # from the filename. try: (derived_summary, derived_labels) = \ derive_summary_and_labels(file_path, project, version) except ValueError, why: print "%s" % why failures += 1 continue summary = options.summary or derived_summary labels = user_labels or derived_labels # The find_auth functionality is currently broken; see # http://code.google.com/p/support/issues/detail?id=558 # This is why we asked for the password/username above. ## status, reason, url = upload_find_auth(file_path, options.project, ## options.summary, labels, ## options.config_dir, options.user) status, reason, url = upload(file_path, project, user, password, summary, labels) if url: print '%s was uploaded successfully.' % file_path print 'URL: %s' % url print successes += 1 else: print 'An error occurred. %s was not uploaded.' % file_path print 'Google Code upload server said: %s (%s)' % (reason, status) print failures += 1 print "Upload status: %d successes, %d failures." % (successes, failures) return failures if __name__ == '__main__': sys.exit(main()) distcc-3.1/source/packaging/deb.sh0000750000175000017500000000077211115326637016165 0ustar wolffwolff#!/bin/sh -e # This takes a package name and version, # and a list of rpms to convert to .deb files. # It puts them all under a debian-* directory under the current directory. # # Run this from the 'packaging' directory, just under rootdir PACKAGE="$1"; VERSION="$2"; shift; shift; # Clean out any old .deb files from a previous build. rm -f "$PACKAGE"*[-._]"$VERSION".deb for file in "$@"; do fakeroot alien -c -k -v "$file" done echo echo "The Debian package files are located in $PWD:" ls *.deb