utilities and has no Gtk dependence.
- For the graphical utilities, Gtk+-1.2 and Gtk+-2.0 should both be
- supported.
-
- - Both Unix Makefiles have an `install' target. Note that by default
- it tries to install `man' pages, which you may need to have built
- using Halibut first -- see below.
+ supported. In the absence of either, the configure script will
+ automatically construct a Makefile which builds only the
+ command-line utilities.
+
+ - pterm would like to be setuid or setgid, as appropriate, to permit
+ it to write records of user logins to /var/run/utmp and
+ /var/log/wtmp. (Of course it will not use this privilege for
+ anything else, and in particular it will drop all privileges before
+ starting up complex subsystems like GTK.) By default the makefile
+ will not attempt to add privileges to the pterm executable at 'make
+ install' time, but you can ask it to do so by running configure
+ with the option '--enable-setuid=USER' or '--enable-setgid=GROUP'.
+
+ - The Unix Makefiles have an `install' target. Note that by default
+ it tries to install `man' pages; if you have fetched the source via
+ Subversion then you will need to have built these using Halibut
+ first - see below.
All of the Makefiles are generated automatically from the file
-`Recipe' by the Perl script `mkfiles.pl'. Additions and corrections
-to Recipe and the mkfiles.pl are much more useful than additions and
-corrections to the alternative Makefiles themselves.
+`Recipe' by the Perl script `mkfiles.pl' (except for the Unix one,
+which is generated by the `configure' script; mkfiles.pl only
+generates the input to automake). Additions and corrections to Recipe,
+mkfiles.pl and/or configure.ac are much more useful than additions and
+corrections to the actual Makefiles, Makefile.am or Makefile.in.
The Unix `configure' script and its various requirements are generated
by the shell script `mkauto.sh', which requires GNU Autoconf, GNU
Automake, and Gtk; if you've got the source from Subversion rather
than using one of our source snapshots, you'll need to run this
-yourself.
+yourself. The input file to Automake is generated by mkfiles.pl along
+with all the rest of the makefiles, so you will need to run mkfiles.pl
+and then mkauto.sh.
Documentation (in various formats including Windows Help and Unix
`man' pages) is built from the Halibut (`.but') files in the `doc'
!makefile lcc windows/Makefile.lcc
!makefile gtk unix/Makefile.gtk
!makefile unix unix/Makefile.ux
-!makefile ac unix/Makefile.in
+!makefile am unix/Makefile.am
!makefile osx macosx/Makefile
!makefile devcppproj windows/DEVCPP
# Source directories.
fi
!end
!specialobj gtk version
+# In the automake build, we have to do the whole job by supplying
+# extra CFLAGS, so we have to put the if statement inside one big
+# backtick expression. We also force rebuilding via a -D option that
+# makes version.o include empty.h, which we construct ourselves and
+# touch whenever any source file is updated.
+!cflags am version $(VER) -DINCLUDE_EMPTY_H `if test -z "$(VER)" && (cd $(srcdir)/..; md5sum -c manifest >/dev/null 2>&1); then cat $(srcdir)/../version.def; else echo "$(VER)"; fi`
+!begin am
+BUILT_SOURCES = empty.h
+CLEANFILES = empty.h
+empty.h: $(allsources)
+ echo '/* nothing to see here */' >$@
+
+!end
# Add VER to Windows resource targets, and force them to be rebuilt every
# time, on the assumption that they will contain version information.
CFLAGS += -DMACOSX
!end
+# List the man pages for the automake makefile.
+!begin am
+man1_MANS = ../doc/plink.1 ../doc/pscp.1 ../doc/psftp.1 ../doc/pterm.1 \
+ ../doc/putty.1 ../doc/puttygen.1 ../doc/puttytel.1
+!end
+
+# In automake, chgrp/chmod pterm after installation, if configured to.
+!begin am
+if HAVE_SETID_CMD
+install-exec-local:
+ @SETID_CMD@ $(bindir)/pterm
+ chmod @SETID_MODE@ $(bindir)/pterm
+endif
+!end
+
# Random symbols.
!begin cygwin vars
# _WIN32_IE is required to expose identifiers that only make sense on
# well as from outside.
test -f unix.h && cd ..
-# Persuade automake to give us a copy of its install-sh. This is a
-# pain because I don't actually want to have to _use_ automake.
-# Instead, I construct a trivial unrelated automake project in a
-# temporary subdirectory, run automake so that it'll copy
-# install-sh into that directory, then copy it back out again.
-# Hideous, but it should work.
-
-mkdir automake-grievous-hack
-cat > automake-grievous-hack/hello.c << EOF
-#include <stdio.h>
-int main(int argc, char **argv)
-{
- printf("hello, world\n");
- return 0;
-}
-EOF
-cat > automake-grievous-hack/Makefile.am << EOF
-bin_PROGRAMS = hello
-hello_SOURCES = hello.c
-EOF
-cat > automake-grievous-hack/configure.ac << EOF
-AC_INIT
-AM_INIT_AUTOMAKE(hello, 1.0)
-AC_CONFIG_FILES([Makefile])
-AC_PROG_CC
-AC_OUTPUT
-EOF
-echo Some news > automake-grievous-hack/NEWS
-echo Some text > automake-grievous-hack/README
-echo Some people > automake-grievous-hack/AUTHORS
-echo Some changes > automake-grievous-hack/ChangeLog
-rm -f install-sh # this won't work if we accidentally have one _here_
-(cd automake-grievous-hack && autoreconf -i && \
- cp install-sh ../unix/install-sh)
-rm -rf automake-grievous-hack
-
-# That was the hard bit. Now run autoconf on our real configure.in.
-(cd unix && autoreconf && rm -rf aclocal.m4 autom4te.cache)
+# Run autoconf on our real configure.in.
+(cd unix && autoreconf -i && rm -rf autom4te.cache)
if ($_[0] eq "!srcdir") { push @srcdirs, $_[1]; next; }
if ($_[0] eq "!makefile" and &mfval($_[1])) { $makefiles{$_[1]}=$_[2]; next;}
if ($_[0] eq "!specialobj" and &mfval($_[1])) { $specialobj{$_[1]}->{$_[2]} = 1; next;}
+ if ($_[0] eq "!cflags" and &mfval($_[1])) {
+ ($rest = $_) =~ s/^\s*\S+\s+\S+\s+\S+\s*//; # find rest of input line
+ $rest = 1 if $rest eq "";
+ $cflags{$_[1]}->{$_[2]} = $rest;
+ next;
+ }
if ($_[0] eq "!forceobj") { $forceobj{$_[1]} = 1; next; }
if ($_[0] eq "!begin") {
if (&mfval($_[1])) {
# file name into a listref containing further source file names.
%further = ();
+%allsourcefiles = (); # this is wanted by some makefiles
while (scalar @scanlist > 0) {
$file = shift @scanlist;
next if defined $further{$file}; # skip if we've already done it
$further{$file} = [];
$dirfile = &findfile($file);
+ $allsourcefiles{$dirfile} = 1;
open IN, "$dirfile" or die "unable to open source file $file\n";
while (<IN>) {
chomp;
# prints a warning and returns false;
if (grep { $type eq $_ }
("vc","vcproj","cygwin","borland","lcc","devcppproj","gtk","unix",
- "ac","osx",)) {
+ "am","osx",)) {
return 1;
}
warn "$.:unknown makefile type '$type'\n";
select STDOUT; close OUT;
}
-if (defined $makefiles{'ac'}) {
- $dirpfx = &dirpfx($makefiles{'ac'}, "/");
+if (defined $makefiles{'am'}) {
+ $dirpfx = "\$(srcdir)/" . &dirpfx($makefiles{'am'}, "/");
- ##-- Unix/autoconf makefile
- open OUT, ">$makefiles{'ac'}"; select OUT;
+ ##-- Unix/autoconf Makefile.am
+ open OUT, ">$makefiles{'am'}"; select OUT;
print
- "# Makefile.in for $project_name under Unix with Autoconf.\n".
+ "# Makefile.am for $project_name under Unix with Autoconf/Automake.\n".
"#\n# This file was created by `mkfiles.pl' from the `Recipe' file.\n".
- "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n";
- # gcc command line option is -D not /D
- ($_ = $help) =~ s/([=" ])\/D/$1-D/gs;
- print $_;
- print
- "\n".
- "CC = \@CC\@\n".
- "\n".
- &splitline("CFLAGS = \@CFLAGS\@ \@PUTTYCFLAGS\@ \@CPPFLAGS\@ " .
- "\@DEFS\@ \@GTK_CFLAGS\@ " .
- (join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
- "XLDFLAGS = \@LDFLAGS\@ \@LIBS\@ \@GTK_LIBS\@\n".
- "ULDFLAGS = \@LDFLAGS\@ \@LIBS\@\n".
- "INSTALL=\@INSTALL\@\n".
- "INSTALL_PROGRAM=\$(INSTALL)\n".
- "INSTALL_DATA=\$(INSTALL)\n".
- "prefix=\@prefix\@\n".
- "exec_prefix=\@exec_prefix\@\n".
- "bindir=\@bindir\@\n".
- "datarootdir=\@datarootdir\@\n".
- "mandir=\@mandir\@\n".
- "man1dir=\$(mandir)/man1\n".
- "\n".
- &def($makefile_extra{'gtk'}->{'vars'}) .
- "\n".
- ".SUFFIXES:\n".
- "\n".
- "\n".
- "all: \@all_targets\@\n".
- &splitline("all-cli:" . join "", map { " $_" } &progrealnames("U"))."\n".
- &splitline("all-gtk:" . join "", map { " $_" } &progrealnames("X"))."\n";
- print "\n";
- foreach $p (&prognames("X:U")) {
+ "# DO NOT EDIT THIS FILE DIRECTLY; edit Recipe or mkfiles.pl instead.\n\n";
+
+ # Complete list of source and header files. Not used by the
+ # auto-generated parts of this makefile, but Recipe might like to
+ # have it available as a variable so that mandatory-rebuild things
+ # (version.o) can conveniently be made to depend on it.
+ @sources = ("allsources", "=",
+ map {"${dirpfx}$_"} sort keys %allsourcefiles);
+ print &splitline(join " ", @sources), "\n\n";
+
+ @cliprogs = ("bin_PROGRAMS", "=");
+ foreach $p (&prognames("U")) {
($prog, $type) = split ",", $p;
- $objstr = &objects($p, "X.o", undef, undef);
- print &splitline($prog . ": " . $objstr), "\n";
- $libstr = &objects($p, undef, undef, "-lX");
- print &splitline("\t\$(CC) -o \$@ " .
- $objstr . " \$(${type}LDFLAGS) $libstr", 69), "\n\n";
+ push @cliprogs, $prog;
}
- foreach $d (&deps("X.o", undef, $dirpfx, "/", "gtk")) {
- if ($forceobj{$d->{obj_orig}}) {
- printf("%s: FORCE\n", $d->{obj});
- } else {
- print &splitline(sprintf("%s: %s", $d->{obj},
- join " ", @{$d->{deps}})), "\n";
+ @allprogs = @cliprogs;
+ foreach $p (&prognames("X")) {
+ ($prog, $type) = split ",", $p;
+ push @allprogs, $prog;
+ }
+ print "if HAVE_GTK\n";
+ print &splitline(join " ", @allprogs), "\n";
+ print "else\n";
+ print &splitline(join " ", @cliprogs), "\n";
+ print "endif\n\n";
+
+ %objtosrc = ();
+ foreach $d (&deps("X", undef, $dirpfx, "/", "am")) {
+ $objtosrc{$d->{obj}} = $d->{deps}->[0];
+ }
+
+ @amcflags = ("\$(COMPAT)", "\$(XFLAGS)", map {"-I$dirpfx$_"} @srcdirs);
+ print "if HAVE_GTK\n";
+ print &splitline(join " ", "AM_CFLAGS", "=",
+ "\$(GTK_CFLAGS)", @amcflags), "\n";
+ print "else\n";
+ print &splitline(join " ", "AM_CFLAGS", "=", @amcflags), "\n";
+ print "endif\n\n";
+
+ %amspeciallibs = ();
+ foreach $obj (sort { $a cmp $b } keys %{$cflags{'am'}}) {
+ print "lib${obj}_a_SOURCES = ", $objtosrc{$obj}, "\n";
+ print &splitline(join " ", "lib${obj}_a_CFLAGS", "=", @amcflags,
+ $cflags{'am'}->{$obj}), "\n";
+ $amspeciallibs{$obj} = "lib${obj}.a";
+ }
+ print &splitline(join " ", "noinst_LIBRARIES", "=",
+ sort { $a cmp $b } values %amspeciallibs), "\n\n";
+
+ foreach $p (&prognames("X:U")) {
+ ($prog, $type) = split ",", $p;
+ print "if HAVE_GTK\n" if $type eq "X";
+ @progsources = ("${prog}_SOURCES", "=");
+ %sourcefiles = ();
+ @ldadd = ();
+ $objstr = &objects($p, "X", undef, undef);
+ foreach $obj (split / /,$objstr) {
+ if ($amspeciallibs{$obj}) {
+ push @ldadd, $amspeciallibs{$obj};
+ } else {
+ $sourcefiles{$objtosrc{$obj}} = 1;
+ }
}
- print &splitline("\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c $d->{deps}->[0]\n");
+ push @progsources, sort { $a cmp $b } keys %sourcefiles;
+ print &splitline(join " ", @progsources), "\n";
+ if ($type eq "X") {
+ push @ldadd, "\$(GTK_LIBS)";
+ }
+ if (@ldadd) {
+ print &splitline(join " ", "${prog}_LDADD", "=", @ldadd), "\n";
+ }
+ print "endif\n" if $type eq "X";
+ print "\n";
}
- print "\n";
- print $makefile_extra{'gtk'}->{'end'};
- print "\nclean:\n".
- "\trm -f *.o". (join "", map { " $_" } &progrealnames("X:U")) . "\n";
- print "\ndistclean: clean\n".
- "\t". &splitline("rm -f config.status config.cache config.log ".
- "configure.lineno config.status.lineno Makefile") . "\n";
- print "\nFORCE:\n";
+ print $makefile_extra{'am'}->{'end'};
select STDOUT; close OUT;
}
case "$1" in
????-??-??)
case "$1" in *[!-0-9]*) echo "Malformed snapshot ID '$1'" >&2;exit 1;;esac
- arcsuffix="-`cat LATEST.VER`-$1"
+ autoconfver="`cat LATEST.VER`-$1"
+ arcsuffix="-$autoconfver"
ver="-DSNAPSHOT=$1"
docver=
;;
r*)
- arcsuffix="-$1"
+ autoconfver="$1"
+ arcsuffix="-$autoconfver"
ver="-DSVN_REV=${1#r}"
docver=
;;
'')
+ autoconfver="X.XX" # got to put something in here!
arcsuffix=
ver=
docver=
;;
*)
case "$1" in *[!.0-9a-z]*) echo "Malformed release ID '$1'">&2;exit 1;;esac
- arcsuffix="-$1"
+ autoconfver="$1"
+ arcsuffix="-$autoconfver"
ver="-DRELEASE=$1"
docver="VERSION=\"PuTTY release $1\""
;;
perl mkfiles.pl
(cd doc && make -s ${docver:+"$docver"})
-sh mkauto.sh 2>/dev/null
relver=`cat LATEST.VER`
arcname="putty$arcsuffix"
-name CVS -prune -o \
-name .cvsignore -prune -o \
-name .svn -prune -o \
+ -name configure.ac -prune -o \
-name '*.zip' -prune -o \
-name '*.tar.gz' -prune -o \
-type f -exec ln -s $PWD/{} uxarc/$arcname/{} \;
md5sum `find . -name '*.[ch]' -print` > manifest;
echo "$ver" > version.def)
fi
+sed "s/^AC_INIT(putty,.*/AC_INIT(putty, $autoconfver)/" unix/configure.ac > uxarc/$arcname/unix/configure.ac
+(cd uxarc/$arcname && sh mkauto.sh) 2>errors || { cat errors >&2; exit 1; }
+
tar -C uxarc -chzof $arcname.tar.gz $arcname
rm -rf uxarc
# * Automake (for aclocal)
# If you've got them, running "autoreconf" should work.
-AC_INIT
+# Version number is substituted by Buildscr for releases, snapshots
+# and custom builds out of svn; X.XX shows up in ad-hoc developer
+# builds, which shouldn't matter
+AC_INIT(putty, X.XX)
AC_CONFIG_FILES([Makefile])
AC_CONFIG_HEADERS([uxconfig.h:uxconfig.in])
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_INSTALL
-AC_PROG_CC
-if test "X$GCC" = Xyes; then
- PUTTYCFLAGS="-Wall -Werror"
-else
- PUTTYCFLAGS=""
-fi
-AC_SUBST(PUTTYCFLAGS)
+AC_PROG_RANLIB
+
+# Mild abuse of the '--enable' option format to allow manual
+# specification of setuid or setgid setup in pterm.
+setidtype=none
+AC_ARG_ENABLE([setuid],
+ [AS_HELP_STRING([--enable-setuid=USER],
+ [make pterm setuid to a given user])],
+ [case "$enableval" in
+ no) setidtype=none;;
+ *) setidtype=setuid; setidval="$enableval";;
+ esac])
+AC_ARG_ENABLE([setgid],
+ [AS_HELP_STRING([--enable-setgid=GROUP],
+ [make pterm setgid to a given group])],
+ [case "$enableval" in
+ no) setidtype=none;;
+ *) setidtype=setgid; setidval="$enableval";;
+ esac])
+AM_CONDITIONAL(HAVE_SETID_CMD, [test "$setidtype" != "none"])
+AS_IF([test "x$setidtype" = "xsetuid"],
+ [SETID_CMD="chown $setidval"; SETID_MODE="4755"])
+AS_IF([test "x$setidtype" = "xsetgid"],
+ [SETID_CMD="chgrp $setidval"; SETID_MODE="2755"])
+AC_SUBST(SETID_CMD)
+AC_SUBST(SETID_MODE)
AC_ARG_WITH([gssapi],
[AS_HELP_STRING([--without-gssapi],
#include <sys/types.h>
#include <utmp.h>])
-# Look for both GTK 1 and GTK 2.
+# Look for both GTK 1 and GTK 2. If we can't find either, have the
+# makefile only build the CLI programs.
gtk=none
;;
esac
-if test "$gtk" = "none"; then
- all_targets="all-cli"
-else
- all_targets="all-cli all-gtk"
-fi
+AM_CONDITIONAL(HAVE_GTK, [test "$gtk" != "none"])
if test "$gtk" = "2"; then
ac_save_CFLAGS="$CFLAGS"
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
-AC_SUBST([all_targets])
AC_SEARCH_LIBS([socket], [xnet])
AC_OUTPUT
+if test "$gtk" = "none"; then cat <<EOF
+
+'configure' was unable to find either the GTK 1 or GTK 2 libraries on
+your system. Therefore, PuTTY itself and the other GUI utilities will
+not be built by the generated Makefile: only the command-line tools
+such as puttygen, plink and psftp will be built.
+
+EOF
+fi
+
AH_BOTTOM([
/* Convert autoconf definitions to ones that PuTTY wants. */
#define STR1(x) #x
#define STR(x) STR1(x)
+#ifdef INCLUDE_EMPTY_H
+/*
+ * Horrible hack to force version.o to be rebuilt unconditionally in
+ * the automake world: empty.h is an empty header file, created by the
+ * makefile and forcibly updated every time make is run. Including it
+ * here causes automake to track it as a dependency, which will cause
+ * version.o to be rebuilt too.
+ *
+ * The space between # and include causes mkfiles.pl's dependency
+ * scanner (for all other makefile types) to ignore this include,
+ * which is correct because only the automake makefile passes
+ * -DINCLUDE_EMPTY_H to enable it.
+ */
+# include "empty.h"
+#endif
+
#if defined SNAPSHOT
#if defined SVN_REV