GNU bug report logs - #9578
make uninstall fails after make install-data in empty prefix.

Previous Next

Package: automake;

Reported by: Nick Bowler <nbowler <at> elliptictech.com>

Date: Thu, 22 Sep 2011 18:47:01 UTC

Severity: normal

Tags: patch

Done: Stefano Lattarini <stefano.lattarini <at> gmail.com>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 9578 in the body.
You can then email your comments to 9578 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-automake <at> gnu.org:
bug#9578; Package automake. (Thu, 22 Sep 2011 18:47:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Nick Bowler <nbowler <at> elliptictech.com>:
New bug report received and forwarded. Copy sent to bug-automake <at> gnu.org. (Thu, 22 Sep 2011 18:47:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Nick Bowler <nbowler <at> elliptictech.com>
To: bug-automake <at> gnu.org
Subject: make uninstall fails after make install-data in empty prefix.
Date: Thu, 22 Sep 2011 14:42:59 -0400
Hello,

I noticed a problem testing the uninstall target of my
automake-generated Makefiles.  If the install prefix does not exist
before installation, automake will create the necessary directories.
But if you run a plain "make install-data" (without make install-exec),
the directories for executables are (unsurprisingly) not created.  The
problem is that "make uninstall" fails in this case:

  % ./configure --prefix=/tmp/does_not_exist
  % make install-data
  % make uninstall
   ( cd '/tmp/does_not_exist/bin' && rm -f foo )
  /bin/sh: line 6: cd: /tmp/does_not_exist/bin: No such file or directory
  make: *** [uninstall-binPROGRAMS] Error 1

and the installed data files are not deleted.  For reference, here's the
generated uninstall-binPROGRAMS target:

  uninstall-binPROGRAMS:
  	@$(NORMAL_UNINSTALL)
  	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
  	files=`for p in $$list; do echo "$$p"; done | \
  	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
  	      -e 's/$$/$(EXEEXT)/' `; \
  	test -n "$$list" || exit 0; \
  	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
  	cd "$(DESTDIR)$(bindir)" && rm -f $$files

Manually adding a - before the second command corrects the issue and the
data is successfully uninstalled.

A similar problem occurs with "make install-exec" followed by "make
uninstall", although this is somewhat less severe because GNU make will
successfully uninstall the executables before failing when it gets to
the data.  I'm using autoconf-2.68 and automake-1.11.1; the problem also
occurs with latest git automake at the time of writing.  The above was
reproduced with the following:

% cat >Makefile.am <<'EOF'
bin_PROGRAMS = foo
data_DATA = bar
EOF

% cat >configure.ac <<'EOF'
AC_INIT([test], [1.0])

AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CC

AC_CONFIG_FILES([Makefile])
AC_OUTPUT
EOF

% cat >foo.c <<'EOF'
int main(void) { return 0; }
EOF

% cat >bar <<'EOF'
baz
EOF

Cheers,
-- 
Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/)




Information forwarded to bug-automake <at> gnu.org:
bug#9578; Package automake. (Sat, 24 Sep 2011 13:33:01 GMT) Full text and rfc822 format available.

Message #8 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Stefano Lattarini <stefano.lattarini <at> gmail.com>
To: bug-automake <at> gnu.org
Cc: 9578 <at> debbugs.gnu.org, Nick Bowler <nbowler <at> elliptictech.com>,
	automake-patches <at> gnu.org
Subject: Re: bug#9578: make uninstall fails after make install-data in empty
	prefix.
Date: Sat, 24 Sep 2011 15:31:22 +0200
[Message part 1 (text/plain, inline)]
On Thursday 22 September 2011, Nick Bowler wrote:
> Hello,
>
Hi Nick, thanks for the report.

> I noticed a problem testing the uninstall target of my
> automake-generated Makefiles.  If the install prefix does not exist
> before installation, automake will create the necessary directories.
> But if you run a plain "make install-data" (without make install-exec),
> the directories for executables are (unsurprisingly) not created.  The
> problem is that "make uninstall" fails in this case:
>
I'm not yet sure whether this should be considered a bug or a feature...
I'm inclined to agree with you that it's more of a bug though, so I'll
push the attached patch to maint in a few days if nobody objects.  This
change is not completely obvious, so any review would be appreciated.

Notice that the test coverage added by the patch is far from perfect, but
I'd rather improve it in the `testsuite-work' branch only, so that I'll
be able to use TAP and won't be forced to write 10 or so new "sister
tests" instead.

Thanks,
   Stefano
[0001-uninstall-make-uninstall-before-make-install-works.patch (text/x-patch, inline)]
From 21011463ca951d397be0ea89e58b278ca8f40c2f Mon Sep 17 00:00:00 2001
Message-Id: <21011463ca951d397be0ea89e58b278ca8f40c2f.1316870869.git.stefano.lattarini <at> gmail.com>
From: Stefano Lattarini <stefano.lattarini <at> gmail.com>
Date: Fri, 23 Sep 2011 22:50:14 +0200
Subject: [PATCH] uninstall: "make uninstall" before "make install" works

This change fixes automake bug#9578.

* lib/am/inst-vars.am (am__uninstall_files_from_dir): New internal
macro, that defines a shell code fragment to uninstall files from
a given directory.
* lib/am/data.am (uninstall-%DIR%%PRIMARY%): Use it, to reduce code
duplication and improve consistency and correctness.
* lib/am/libs.am (uninstall-%DIR%LIBRARIES): Likewise.
* lib/am/lisp.am (uninstall-%DIR%LISP): Likewise.
* lib/am/mans.am (uninstall-man%SECTION%): Likewise.
* lib/am/python.am (uninstall-%DIR%LIBRARIES): Likewise.
* lib/am/scripts.am (uninstall-%DIR%SCRIPTS): Likewise.
* tests/uninstall-pr9578.test: New test.
* tests/uninstall-fail.test: New test.
* tests/Makefile.am (TESTS): Add them.
* NEWS, THANKS: Update.

Report by Nick Bowler.
---
 ChangeLog                      |   20 ++++++++++++
 Makefile.in                    |   10 ++++--
 NEWS                           |    4 ++
 THANKS                         |    1 +
 doc/Makefile.in                |   14 +++++----
 lib/Automake/Makefile.in       |   14 +++++----
 lib/Automake/tests/Makefile.in |    6 ++++
 lib/Makefile.in                |   14 +++++----
 lib/am/Makefile.in             |   10 ++++--
 lib/am/data.am                 |    4 +--
 lib/am/inst-vars.am            |   18 +++++++++++
 lib/am/libs.am                 |    4 +--
 lib/am/lisp.am                 |    8 +----
 lib/am/mans.am                 |    8 +----
 lib/am/python.am               |   15 ++++-----
 lib/am/scripts.am              |    4 +--
 m4/Makefile.in                 |   14 +++++----
 tests/Makefile.am              |    2 +
 tests/Makefile.in              |    8 +++++
 tests/uninstall-fail.test      |   64 +++++++++++++++++++++++++++++++++++++++
 tests/uninstall-pr9578.test    |   65 ++++++++++++++++++++++++++++++++++++++++
 21 files changed, 248 insertions(+), 59 deletions(-)
 create mode 100755 tests/uninstall-fail.test
 create mode 100755 tests/uninstall-pr9578.test

diff --git a/ChangeLog b/ChangeLog
index 47aee92..4347a89 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2011-09-24  Stefano Lattarini  <stefano.lattarini <at> gmail.com>
+
+	uninstall: "make uninstall" before "make install" works
+	This change fixes automake bug#9578.
+	* lib/am/inst-vars.am (am__uninstall_files_from_dir): New internal
+	macro, that defines a shell code fragment to uninstall files from
+	a given directory.
+	* lib/am/data.am (uninstall-%DIR%%PRIMARY%): Use it, to reduce code
+	duplication and improve consistency and correctness.
+	* lib/am/libs.am (uninstall-%DIR%LIBRARIES): Likewise.
+	* lib/am/lisp.am (uninstall-%DIR%LISP): Likewise.
+	* lib/am/mans.am (uninstall-man%SECTION%): Likewise.
+	* lib/am/python.am (uninstall-%DIR%LIBRARIES): Likewise.
+	* lib/am/scripts.am (uninstall-%DIR%SCRIPTS): Likewise.
+	* tests/uninstall-pr9578.test: New test.
+	* tests/uninstall-fail.test: New test.
+	* tests/Makefile.am (TESTS): Add them.
+	* NEWS, THANKS: Update.
+	Report by Nick Bowler.
+
 2011-09-22  Stefano Lattarini  <stefano.lattarini <at> gmail.com>
 
 	tests: fix tests on aclocal search path precedences
diff --git a/Makefile.in b/Makefile.in
index 35a9cbd..a8c3244 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -91,6 +91,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
 am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         cd "$$dir" && rm -f $$files; }; \
+  }
 am__installdirs = "$(DESTDIR)$(bindir)"
 SCRIPTS = $(bin_SCRIPTS)
 SOURCES =
@@ -447,9 +453,7 @@ uninstall-binSCRIPTS:
 	@list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
 	files=`for p in $$list; do echo "$$p"; done | \
 	       sed -e 's,.*/,,;$(transform)'`; \
-	test -n "$$list" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(bindir)" && rm -f $$files
+	dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir)
 
 # This directory's subdirectories are mostly independent; you can cd
 # into them and run `make' without going through this Makefile.
diff --git a/NEWS b/NEWS
index b696977..54838d0 100644
--- a/NEWS
+++ b/NEWS
@@ -61,6 +61,10 @@ Bugs fixed in 1.11.0a:
 
 * Long standing bugs:
 
+  - A "make uninstall" issued before a "make install", or after a mere
+    "make install-data" or a mere "make install-exec" does not spuriously
+    fail anymore.
+
   - Automake now warns about more primary/directory invalid combinations,
     such as "doc_LIBRARIES" or "pkglib_PROGRAMS".
 
diff --git a/THANKS b/THANKS
index f83e1fc..b840088 100644
--- a/THANKS
+++ b/THANKS
@@ -244,6 +244,7 @@ Motoyuki Kasahara	m-kasahr <at> sra.co.jp
 Nathanael Nerode	neroden <at> twcny.rr.com
 Nelson H. F. Beebe	beebe <at> math.utah.edu
 Nicholas Wourms		nwourms <at> netscape.net
+Nick Bowler		nbowler <at> elliptictech.com
 Nicolas Joly		njoly <at> pasteur.fr
 Nicolas Thiery		nthiery <at> Icare.mines.edu
 NightStrike		nightstrike <at> gmail.com
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 3034dcb..23630ab 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -105,6 +105,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
 am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         cd "$$dir" && rm -f $$files; }; \
+  }
 man1dir = $(mandir)/man1
 NROFF = nroff
 MANS = $(dist_man1_MANS)
@@ -478,9 +484,7 @@ uninstall-man1:
 	files=`{ for i in $$list; do echo "$$i"; done; \
 	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
 	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
-	test -z "$$files" || { \
-	  echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \
-	  cd "$(DESTDIR)$(man1dir)" && rm -f $$files; }
+	dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
 install-dist_docDATA: $(dist_doc_DATA)
 	@$(NORMAL_INSTALL)
 	test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)"
@@ -498,9 +502,7 @@ uninstall-dist_docDATA:
 	@$(NORMAL_UNINSTALL)
 	@list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
 	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-	test -n "$$files" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(docdir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(docdir)" && rm -f $$files
+	dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir)
 
 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
 	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
diff --git a/lib/Automake/Makefile.in b/lib/Automake/Makefile.in
index baccf7d..e23e0ae 100644
--- a/lib/Automake/Makefile.in
+++ b/lib/Automake/Makefile.in
@@ -96,6 +96,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
 am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         cd "$$dir" && rm -f $$files; }; \
+  }
 am__installdirs = "$(DESTDIR)$(perllibdir)" "$(DESTDIR)$(perllibdir)"
 DATA = $(dist_perllib_DATA) $(nodist_perllib_DATA)
 RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
@@ -316,9 +322,7 @@ uninstall-dist_perllibDATA:
 	@$(NORMAL_UNINSTALL)
 	@list='$(dist_perllib_DATA)'; test -n "$(perllibdir)" || list=; \
 	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-	test -n "$$files" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(perllibdir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(perllibdir)" && rm -f $$files
+	dir='$(DESTDIR)$(perllibdir)'; $(am__uninstall_files_from_dir)
 install-nodist_perllibDATA: $(nodist_perllib_DATA)
 	@$(NORMAL_INSTALL)
 	test -z "$(perllibdir)" || $(MKDIR_P) "$(DESTDIR)$(perllibdir)"
@@ -336,9 +340,7 @@ uninstall-nodist_perllibDATA:
 	@$(NORMAL_UNINSTALL)
 	@list='$(nodist_perllib_DATA)'; test -n "$(perllibdir)" || list=; \
 	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-	test -n "$$files" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(perllibdir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(perllibdir)" && rm -f $$files
+	dir='$(DESTDIR)$(perllibdir)'; $(am__uninstall_files_from_dir)
 
 # This directory's subdirectories are mostly independent; you can cd
 # into them and run `make' without going through this Makefile.
diff --git a/lib/Automake/tests/Makefile.in b/lib/Automake/tests/Makefile.in
index 17a2002..14a8122 100644
--- a/lib/Automake/tests/Makefile.in
+++ b/lib/Automake/tests/Makefile.in
@@ -101,6 +101,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
 am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         cd "$$dir" && rm -f $$files; }; \
+  }
 # Restructured Text title and section.
 am__rst_title = sed 's/.*/   &   /;h;s/./=/g;p;x;p;g;p;s/.*//'
 am__rst_section = sed 'p;s/./=/g;p;g'
diff --git a/lib/Makefile.in b/lib/Makefile.in
index bc2a6c0..9caa64a 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -98,6 +98,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
 am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         cd "$$dir" && rm -f $$files; }; \
+  }
 am__installdirs = "$(DESTDIR)$(pkgvdatadir)" "$(DESTDIR)$(scriptdir)"
 DATA = $(dist_pkgvdata_DATA) $(dist_script_DATA)
 RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
@@ -287,9 +293,7 @@ uninstall-dist_pkgvdataDATA:
 	@$(NORMAL_UNINSTALL)
 	@list='$(dist_pkgvdata_DATA)'; test -n "$(pkgvdatadir)" || list=; \
 	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-	test -n "$$files" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(pkgvdatadir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(pkgvdatadir)" && rm -f $$files
+	dir='$(DESTDIR)$(pkgvdatadir)'; $(am__uninstall_files_from_dir)
 install-dist_scriptDATA: $(dist_script_DATA)
 	@$(NORMAL_INSTALL)
 	test -z "$(scriptdir)" || $(MKDIR_P) "$(DESTDIR)$(scriptdir)"
@@ -307,9 +311,7 @@ uninstall-dist_scriptDATA:
 	@$(NORMAL_UNINSTALL)
 	@list='$(dist_script_DATA)'; test -n "$(scriptdir)" || list=; \
 	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-	test -n "$$files" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(scriptdir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(scriptdir)" && rm -f $$files
+	dir='$(DESTDIR)$(scriptdir)'; $(am__uninstall_files_from_dir)
 
 # This directory's subdirectories are mostly independent; you can cd
 # into them and run `make' without going through this Makefile.
diff --git a/lib/am/Makefile.in b/lib/am/Makefile.in
index 649c1bf..194f1cb 100644
--- a/lib/am/Makefile.in
+++ b/lib/am/Makefile.in
@@ -89,6 +89,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
 am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         cd "$$dir" && rm -f $$files; }; \
+  }
 am__installdirs = "$(DESTDIR)$(amdir)"
 DATA = $(dist_am_DATA)
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -279,9 +285,7 @@ uninstall-dist_amDATA:
 	@$(NORMAL_UNINSTALL)
 	@list='$(dist_am_DATA)'; test -n "$(amdir)" || list=; \
 	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-	test -n "$$files" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(amdir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(amdir)" && rm -f $$files
+	dir='$(DESTDIR)$(amdir)'; $(am__uninstall_files_from_dir)
 tags: TAGS
 TAGS:
 
diff --git a/lib/am/data.am b/lib/am/data.am
index 36af717..1817447 100644
--- a/lib/am/data.am
+++ b/lib/am/data.am
@@ -73,9 +73,7 @@ uninstall-%DIR%%PRIMARY%:
 	@list='$(%DIR%_%PRIMARY%)'; test -n "$(%NDIR%dir)" || list=; \
 ?BASE?	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
 ?!BASE?	$(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
-	test -n "$$files" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(%NDIR%dir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(%NDIR%dir)" && rm -f $$files
+	dir='$(DESTDIR)$(%NDIR%dir)'; $(am__uninstall_files_from_dir)
 endif %?INSTALL%
 
 
diff --git a/lib/am/inst-vars.am b/lib/am/inst-vars.am
index a49cfe9..477513f 100644
--- a/lib/am/inst-vars.am
+++ b/lib/am/inst-vars.am
@@ -15,6 +15,7 @@
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 if %?FIRST%
+
 ## These variables help stripping any $(VPATH) that some
 ## Make implementations prepend before VPATH-found files.
 ## The issue is discussed at length in distdir.am.
@@ -52,4 +53,21 @@ am__nobase_list = $(am__nobase_strip_setup); \
 am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+
+## A shell code fragment to uninstall files from a given directory.
+## It expects the $dir and $files shell variables to be defined respectively
+## to the directory where the files to be removed are, and to the list of
+## such files.
+am__uninstall_files_from_dir = { \
+## Some rm implementations complain if `rm -f' is used without arguments.
+  test -z "$$files" \
+## At least Solaris /bin/sh still lacks `test -e', so we use the multiple
+## tests below instead.  We expect $dir to be either non-existent or a
+## directory, so the failure we'll experience if it is a regular file
+## is indeed desired and welcome (better to fail loudly thasn silently).
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         cd "$$dir" && rm -f $$files; }; \
+  }
+
 endif %?FIRST%
diff --git a/lib/am/libs.am b/lib/am/libs.am
index eec62a1..29f630b 100644
--- a/lib/am/libs.am
+++ b/lib/am/libs.am
@@ -87,9 +87,7 @@ uninstall-%DIR%LIBRARIES:
 	@list='$(%DIR%_LIBRARIES)'; test -n "$(%NDIR%dir)" || list=; \
 ?BASE?	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
 ?!BASE?	$(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
-	test -n "$$files" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(%NDIR%dir)' && rm -f "$$files" )"; \
-	cd "$(DESTDIR)$(%NDIR%dir)" && rm -f $$files
+	dir='$(DESTDIR)$(%NDIR%dir)'; $(am__uninstall_files_from_dir)
 endif %?INSTALL%
 
 
diff --git a/lib/am/lisp.am b/lib/am/lisp.am
index ab45b30..6ffcdbf 100644
--- a/lib/am/lisp.am
+++ b/lib/am/lisp.am
@@ -128,12 +128,8 @@ uninstall-%DIR%LISP:
 	list='$(%DIR%_LISP)'; \
 ?BASE?	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
 ?!BASE?	$(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
-	test -n "$$files" || exit 0; \
-	filesc=`echo "$$files" | sed 's|$$|c|'`; \
-	echo " ( cd '$(DESTDIR)$(%NDIR%dir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(%NDIR%dir)" && rm -f $$files || exit $$?; \
-	echo " ( cd '$(DESTDIR)$(%NDIR%dir)' && rm -f" $$filesc ")"; \
-	cd "$(DESTDIR)$(%NDIR%dir)" && rm -f $$filesc
+	files="$$files "`echo "$$files" | sed 's|$$|c|'`; \
+	dir='$(DESTDIR)$(%NDIR%dir)'; $(am__uninstall_files_from_dir)
 endif %?INSTALL%
 
 
diff --git a/lib/am/mans.am b/lib/am/mans.am
index 66a6c7e..b41a94d 100644
--- a/lib/am/mans.am
+++ b/lib/am/mans.am
@@ -119,9 +119,7 @@ if %?NOTRANS_MANS%
 ?HAVE_NOTRANS?	  sed -n '/\.%SECTION%[a-z]*$$/p'; \
 ## Extract basename of manpage, change the extension if needed.
 	} | sed 's,.*/,,;s,\.[^%SECTION%][0-9a-z]*$$,.%SECTION%,'`; \
-	test -z "$$files" || { \
-	  echo " ( cd '$(DESTDIR)$(man%SECTION%dir)' && rm -f" $$files ")"; \
-	  cd "$(DESTDIR)$(man%SECTION%dir)" && rm -f $$files; }
+	dir='$(DESTDIR)$(man%SECTION%dir)'; $(am__uninstall_files_from_dir)
 endif %?NOTRANS_MANS%
 if %?TRANS_MANS%
 ## Handle MANS without notrans_ prefix
@@ -136,7 +134,5 @@ if %?TRANS_MANS%
 ## transform, and change the extension if needed.
 	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^%SECTION%][0-9a-z]*$$,%SECTION%,;x' \
 	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
-	test -z "$$files" || { \
-	  echo " ( cd '$(DESTDIR)$(man%SECTION%dir)' && rm -f" $$files ")"; \
-	  cd "$(DESTDIR)$(man%SECTION%dir)" && rm -f $$files; }
+	dir='$(DESTDIR)$(man%SECTION%dir)'; $(am__uninstall_files_from_dir)
 endif %?TRANS_MANS%
diff --git a/lib/am/python.am b/lib/am/python.am
index 40aaa62..427c95d 100644
--- a/lib/am/python.am
+++ b/lib/am/python.am
@@ -94,16 +94,15 @@ uninstall-%DIR%PYTHON:
 ?BASE?	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
 ?!BASE?	$(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
 	test -n "$$files" || exit 0; \
+	dir='$(DESTDIR)$(%NDIR%dir)'; \
+## Also remove the .pyc and .pyo byte compiled versions.
 	filesc=`echo "$$files" | sed 's|$$|c|'`; \
 	fileso=`echo "$$files" | sed 's|$$|o|'`; \
-	echo " ( cd '$(DESTDIR)$(%NDIR%dir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(%NDIR%dir)" && rm -f $$files || exit $$?; \
-## This is to remove the .pyc and .pyo byte compiled versions (a bit
-## of a hack).
-	echo " ( cd '$(DESTDIR)$(%NDIR%dir)' && rm -f" $$filesc ")"; \
-	cd "$(DESTDIR)$(%NDIR%dir)" && rm -f $$filesc || exit $$?; \
-	echo " ( cd '$(DESTDIR)$(%NDIR%dir)' && rm -f" $$fileso ")"; \
-	cd "$(DESTDIR)$(%NDIR%dir)" && rm -f $$fileso
+	st=0; \
+	for files in "$$files" "$$filesc" "$$fileso"; do \
+	  $(am__uninstall_files_from_dir) || st=$$?; \
+	done; \
+	exit $$st
 endif %?INSTALL%
 
 
diff --git a/lib/am/scripts.am b/lib/am/scripts.am
index 790cb64..346f0d3 100644
--- a/lib/am/scripts.am
+++ b/lib/am/scripts.am
@@ -83,9 +83,7 @@ uninstall-%DIR%SCRIPTS:
 ?!BASE?	$(am__nobase_strip_setup); \
 ?!BASE?	files=`$(am__nobase_strip) \
 ?!BASE?	       -e 'h;s,.*/,,;$(transform);x;s|[^/]*$$||;G;s,\n,,'`; \
-	test -n "$$list" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(%NDIR%dir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(%NDIR%dir)" && rm -f $$files
+	dir='$(DESTDIR)$(%NDIR%dir)'; $(am__uninstall_files_from_dir)
 endif %?INSTALL%
 
 
diff --git a/m4/Makefile.in b/m4/Makefile.in
index 2e7e547..9fb6989 100644
--- a/m4/Makefile.in
+++ b/m4/Makefile.in
@@ -89,6 +89,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
 am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         cd "$$dir" && rm -f $$files; }; \
+  }
 am__installdirs = "$(DESTDIR)$(automake_acdir)" \
 	"$(DESTDIR)$(system_acdir)"
 DATA = $(dist_automake_ac_DATA) $(dist_system_ac_DATA)
@@ -281,9 +287,7 @@ uninstall-dist_automake_acDATA:
 	@$(NORMAL_UNINSTALL)
 	@list='$(dist_automake_ac_DATA)'; test -n "$(automake_acdir)" || list=; \
 	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-	test -n "$$files" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(automake_acdir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(automake_acdir)" && rm -f $$files
+	dir='$(DESTDIR)$(automake_acdir)'; $(am__uninstall_files_from_dir)
 install-dist_system_acDATA: $(dist_system_ac_DATA)
 	@$(NORMAL_INSTALL)
 	test -z "$(system_acdir)" || $(MKDIR_P) "$(DESTDIR)$(system_acdir)"
@@ -301,9 +305,7 @@ uninstall-dist_system_acDATA:
 	@$(NORMAL_UNINSTALL)
 	@list='$(dist_system_ac_DATA)'; test -n "$(system_acdir)" || list=; \
 	files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-	test -n "$$files" || exit 0; \
-	echo " ( cd '$(DESTDIR)$(system_acdir)' && rm -f" $$files ")"; \
-	cd "$(DESTDIR)$(system_acdir)" && rm -f $$files
+	dir='$(DESTDIR)$(system_acdir)'; $(am__uninstall_files_from_dir)
 tags: TAGS
 TAGS:
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1d258c9..221f08a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -852,6 +852,8 @@ txinfo32.test \
 txinfo33.test \
 transform.test \
 transform2.test \
+uninstall-pr9578.test \
+uninstall-fail.test \
 unused.test \
 upc.test \
 upc2.test \
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 7e9bc20..591cfc6 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -104,6 +104,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
 am__base_list = \
   sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
   sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         cd "$$dir" && rm -f $$files; }; \
+  }
 # Restructured Text title and section.
 am__rst_title = sed 's/.*/   &   /;h;s/./=/g;p;x;p;g;p;s/.*//'
 am__rst_section = sed 'p;s/./=/g;p;g'
@@ -1130,6 +1136,8 @@ txinfo32.test \
 txinfo33.test \
 transform.test \
 transform2.test \
+uninstall-pr9578.test \
+uninstall-fail.test \
 unused.test \
 upc.test \
 upc2.test \
diff --git a/tests/uninstall-fail.test b/tests/uninstall-fail.test
new file mode 100755
index 0000000..6ba0eba
--- /dev/null
+++ b/tests/uninstall-fail.test
@@ -0,0 +1,64 @@
+#! /bin/sh
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# "make uninstall" complains and errors out on failures.
+
+# FIXME: this test only dealt with DATA primary; maybe we need sister
+# tests for other primaries too?  E.g., SCRIPTS, PROGRAMS, LISP, PYTHON,
+# etc...
+
+. ./defs || Exit 1
+
+set -e
+
+cat >> configure.in << 'END'
+AC_OUTPUT
+END
+
+cat > Makefile.am << 'END'
+data_DATA = foobar.txt
+END
+
+: > foobar.txt
+
+$ACLOCAL
+$AUTOMAKE
+$AUTOCONF
+
+inst=__inst-dir__
+
+./configure --prefix="`pwd`/$inst"
+
+mkdir $inst $inst/share
+: > $inst/share/foobar.txt
+
+chmod a-w $inst/share
+touch $inst/share/t && skip_ "cannot make directories unwritable"
+rm -f $inst/share/t
+
+$MAKE uninstall >output 2>&1 && { cat output; Exit 1; }
+cat output
+grep "rm: .*foobar\.txt" output
+
+chmod a-rwx $inst/share
+(cd $inst/share) && skip_ "cannot make directories fully unreadable"
+
+$MAKE uninstall >output 2>&1 && { cat output; Exit 1; }
+cat output
+grep "cd: .*$inst/share" output
+
+
+:
diff --git a/tests/uninstall-pr9578.test b/tests/uninstall-pr9578.test
new file mode 100755
index 0000000..3f67203
--- /dev/null
+++ b/tests/uninstall-pr9578.test
@@ -0,0 +1,65 @@
+#! /bin/sh
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Check against automake bug#9578: "make uninstall" issued before
+# "make install" or after a mere "make install-data" or a mere
+# "make install-exec" failed spuriously.
+
+. ./defs || Exit 1
+
+set -e
+
+cat >> configure.in << 'END'
+AC_OUTPUT
+END
+
+: > foo
+: > bar
+
+cat > Makefile.am << 'END'
+bin_SCRIPTS = foo
+data_DATA = bar
+END
+
+$ACLOCAL
+$AUTOMAKE
+$AUTOCONF
+
+./configure --prefix="`pwd`/inst"
+
+$MAKE uninstall
+test ! -d inst
+
+rm -rf inst
+
+$MAKE install-exec
+test -f inst/bin/foo || Exit 99 # Sanity check.
+$MAKE uninstall
+test ! -f inst/bin/foo
+
+$MAKE install-data
+test -f inst/share/bar || Exit 99 # Sanity check.
+$MAKE uninstall
+test ! -f inst/share/bar
+
+rm -rf inst
+
+$MAKE install-exec
+test -f inst/bin/foo || Exit 99 # Sanity check.
+$MAKE uninstall
+test ! -f inst/bin/foo
+
+:
-- 
1.7.2.3


Information forwarded to bug-automake <at> gnu.org:
bug#9578; Package automake. (Sat, 24 Sep 2011 13:33:02 GMT) Full text and rfc822 format available.

Added tag(s) patch. Request was from Stefano Lattarini <stefano.lattarini <at> gmail.com> to control <at> debbugs.gnu.org. (Sat, 24 Sep 2011 14:16:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-automake <at> gnu.org:
bug#9578; Package automake. (Mon, 26 Sep 2011 19:57:02 GMT) Full text and rfc822 format available.

Message #16 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Stefano Lattarini <stefano.lattarini <at> gmail.com>
To: bug-automake <at> gnu.org
Cc: Nick Bowler <nbowler <at> elliptictech.com>, 9578-done <at> debbugs.gnu.org,
	automake-patches <at> gnu.org
Subject: Re: bug#9578: make uninstall fails after make install-data in empty
	prefix.
Date: Mon, 26 Sep 2011 21:55:30 +0200
On Saturday 24 September 2011, Stefano Lattarini wrote:
> On Thursday 22 September 2011, Nick Bowler wrote:
> > Hello,
> >
> Hi Nick, thanks for the report.
> 
> > I noticed a problem testing the uninstall target of my
> > automake-generated Makefiles.  If the install prefix does not exist
> > before installation, automake will create the necessary directories.
> > But if you run a plain "make install-data" (without make install-exec),
> > the directories for executables are (unsurprisingly) not created.  The
> > problem is that "make uninstall" fails in this case:
> >
> I'm not yet sure whether this should be considered a bug or a feature...
> I'm inclined to agree with you that it's more of a bug though, so I'll
> push the attached patch to maint in a few days if nobody objects.  This
> change is not completely obvious, so any review would be appreciated.
> 
> Notice that the test coverage added by the patch is far from perfect, but
> I'd rather improve it in the `testsuite-work' branch only, so that I'll
> be able to use TAP and won't be forced to write 10 or so new "sister
> tests" instead.
>
> Thanks,
>    Stefano
> 

I've squashed in the following, and pushed.  I'm thus closing the bug
report.

Regards,
  Stefano

-*-*-*-

diff --git a/tests/uninstall-fail.test b/tests/uninstall-fail.test
index 6ba0eba..a3e7a7a 100755
--- a/tests/uninstall-fail.test
+++ b/tests/uninstall-fail.test
@@ -16,7 +16,7 @@
 
 # "make uninstall" complains and errors out on failures.
 
-# FIXME: this test only dealt with DATA primary; maybe we need sister
+# FIXME: this test only deal with DATA primary; maybe we need sister
 # tests for other primaries too?  E.g., SCRIPTS, PROGRAMS, LISP, PYTHON,
 # etc...
 
diff --git a/tests/uninstall-pr9578.test b/tests/uninstall-pr9578.test
index 3f67203..9aea52d 100755
--- a/tests/uninstall-pr9578.test
+++ b/tests/uninstall-pr9578.test
@@ -17,6 +17,10 @@
 # Check against automake bug#9578: "make uninstall" issued before
 # "make install" or after a mere "make install-data" or a mere
 # "make install-exec" failed spuriously.
+#
+# FIXME: this test only deal with DATA and script primaries; maybe we
+# need sister tests for other primaries too?  E.g., PROGRAMS, LISP,
+# PYTHON, etc...
 
 . ./defs || Exit 1




Reply sent to Stefano Lattarini <stefano.lattarini <at> gmail.com>:
You have taken responsibility. (Mon, 26 Sep 2011 19:57:02 GMT) Full text and rfc822 format available.

Notification sent to Nick Bowler <nbowler <at> elliptictech.com>:
bug acknowledged by developer. (Mon, 26 Sep 2011 19:57:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-automake <at> gnu.org:
bug#9578; Package automake. (Wed, 28 Sep 2011 11:26:02 GMT) Full text and rfc822 format available.

Message #24 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Stefano Lattarini <stefano.lattarini <at> gmail.com>
To: bug-automake <at> gnu.org
Cc: 9578 <at> debbugs.gnu.org, Nick Bowler <nbowler <at> elliptictech.com>,
	automake-patches <at> gnu.org
Subject: Re: bug#9578: make uninstall fails after make install-data in empty
	prefix.
Date: Wed, 28 Sep 2011 13:24:13 +0200
[Message part 1 (text/plain, inline)]
On Monday 26 September 2011, Stefano Lattarini wrote:
> On Saturday 24 September 2011, Stefano Lattarini wrote:
> > On Thursday 22 September 2011, Nick Bowler wrote:
> > > Hello,
> > >
> > Hi Nick, thanks for the report.
> > 
> > > I noticed a problem testing the uninstall target of my
> > > automake-generated Makefiles.  If the install prefix does not exist
> > > before installation, automake will create the necessary directories.
> > > But if you run a plain "make install-data" (without make install-exec),
> > > the directories for executables are (unsurprisingly) not created.  The
> > > problem is that "make uninstall" fails in this case:
> > >
> > I'm not yet sure whether this should be considered a bug or a feature...
> > I'm inclined to agree with you that it's more of a bug though, so I'll
> > push the attached patch to maint in a few days if nobody objects.  This
> > change is not completely obvious, so any review would be appreciated.
> > 
> > Notice that the test coverage added by the patch is far from perfect, but
> > I'd rather improve it in the `testsuite-work' branch only, so that I'll
> > be able to use TAP and won't be forced to write 10 or so new "sister
> > tests" instead.
> >
> > Thanks,
> >    Stefano
> > 
> 
Oops, the patch as I've pushed it was causing "make maintainer-check" to
fail.  I've pushed the attached follow-up to fix this.

Sorry for the noise,
  Stefano
[0001-maintcheck-fix-usage-of-cd-instead-of-am__cd.patch (text/x-patch, inline)]
From a2803e6a0d65e5124dd12d89acab61ac8fc11a53 Mon Sep 17 00:00:00 2001
Message-Id: <a2803e6a0d65e5124dd12d89acab61ac8fc11a53.1317208837.git.stefano.lattarini <at> gmail.com>
From: Stefano Lattarini <stefano.lattarini <at> gmail.com>
Date: Wed, 28 Sep 2011 13:17:13 +0200
Subject: [PATCH] maintcheck: fix usage of `cd' instead of `$(am__cd)'

* lib/am/inst-vars.am (am__uninstall_files_from_dir): Use
`$(am__cd)', not plain `cd'.
---
 ChangeLog           |    6 ++++++
 lib/am/inst-vars.am |    2 +-
 2 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4347a89..c3b041d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2011-09-28  Stefano Lattarini  <stefano.lattarini <at> gmail.com>
+
+	maintcheck: fix usage of `cd' instead of `$(am__cd)'
+	* lib/am/inst-vars.am (am__uninstall_files_from_dir): Use
+	`$(am__cd)', not plain `cd'.
+
 2011-09-24  Stefano Lattarini  <stefano.lattarini <at> gmail.com>
 
 	uninstall: "make uninstall" before "make install" works
diff --git a/lib/am/inst-vars.am b/lib/am/inst-vars.am
index 477513f..a807f79 100644
--- a/lib/am/inst-vars.am
+++ b/lib/am/inst-vars.am
@@ -67,7 +67,7 @@ am__uninstall_files_from_dir = { \
 ## is indeed desired and welcome (better to fail loudly thasn silently).
     || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
     || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-         cd "$$dir" && rm -f $$files; }; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
   }
 
 endif %?FIRST%
-- 
1.7.2.3


Information forwarded to bug-automake <at> gnu.org:
bug#9578; Package automake. (Wed, 28 Sep 2011 11:26:02 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Thu, 27 Oct 2011 11:24:04 GMT) Full text and rfc822 format available.

This bug report was last modified 13 years and 241 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.