aboutsummaryrefslogtreecommitdiff
path: root/buildtools
diff options
context:
space:
mode:
Diffstat (limited to 'buildtools')
-rw-r--r--buildtools/build-freebsd-ca-port.py257
-rw-r--r--buildtools/build-freebsd-port.py185
-rw-r--r--buildtools/build-freebsd-rp-port.py351
-rw-r--r--buildtools/debian-package-skeleton.py841
-rw-r--r--buildtools/hack-debian-changelog.py110
-rw-r--r--buildtools/make-rcynic-script.py12
-rw-r--r--buildtools/wrap-tree.py61
7 files changed, 1629 insertions, 188 deletions
diff --git a/buildtools/build-freebsd-ca-port.py b/buildtools/build-freebsd-ca-port.py
new file mode 100644
index 00000000..ad4865e0
--- /dev/null
+++ b/buildtools/build-freebsd-ca-port.py
@@ -0,0 +1,257 @@
+"""
+Construct a FreeBSD port template given the URL of a source tarball.
+
+$Id$
+
+Copyright (C) 2012-2013 Internet Systems Consortium ("ISC")
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+"""
+
+import sys
+import os
+import subprocess
+import urlparse
+import errno
+import glob
+
+try:
+ url = sys.argv[1]
+except IndexError:
+ sys.exit("Usage: %s URL-of-source-tarball" % sys.argv[0])
+
+def stripext(fn, *exts):
+ fn1, fn2 = os.path.splitext(fn)
+ return fn1 if fn2 in exts else fn
+
+def mkdir_maybe(d):
+ try:
+ print "Creating", d
+ os.makedirs(d)
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ raise
+
+name = os.path.basename(urlparse.urlparse(url).path)
+name = stripext(name, ".gz", ".bz2", ".xz")
+name = stripext(name, ".tar", ".tgz", ".tbz", ".txz")
+
+# Up until this point this is fairly generic, but we reach the point
+# of diminishing returns when we have to parse the port name and
+# version number out of the filename. This will need to be changed
+# when we start doing this with something other than snapshot
+# tarballs.
+
+try:
+ base, branch, vers = name.split("-")
+except:
+ base, branch, vers = None
+
+if base not in ("rpkitools", "rpki"):
+ base = None
+
+if branch != "trunk" and (branch[:2] != "tk" or not branch[2:].isdigit()):
+ branch = None
+
+if not vers.isdigit() and (base != "rpki" or vers[0] != "r" or not vers[1:].isdigit()):
+ vers = None
+else:
+ vers = vers[1:]
+
+if None in (base, branch, vers):
+ sys.exit("Unexpected tarball URL name format")
+
+base += "-ca"
+
+mkdir_maybe(base)
+
+with open(os.path.join(base, "Makefile"), "w") as f:
+ print "Writing", f.name
+
+ f.write('''\
+PORTNAME= %(portname)s
+PORTVERSION= 0.%(snapshot)s
+CATEGORIES= net
+MASTER_SITES= %(master_sites)s
+DISTFILES= %(distfiles)s
+WRKSRC= ${WRKDIR}/%(tarname)s
+MAINTAINER= sra@hactrn.net
+COMMENT= rpki.net RPKI CA tools
+
+GNU_CONFIGURE= yes
+USE_PYTHON= 2.7+
+USE_GNOME= libxml2 libxslt
+USE_MYSQL= server
+USE_APACHE_RUN= 22+
+
+USE_RC_SUBR= rpki-ca
+
+# For OpenSSL, not needed otherwise
+USE_PERL5_BUILD=yes
+
+# For building OpenSSL, not needed otherwise
+BUILD_DEPENDS+= makedepend>0:${PORTSDIR}/devel/makedepend
+
+# Needed at build to keep ./configure from complaining.
+BUILD_DEPENDS+= rsync>0:${PORTSDIR}/net/rsync
+
+RPKID_DEPENDS= ${PYTHON_PKGNAMEPREFIX}lxml>0:${PORTSDIR}/devel/py-lxml \\
+ ${PYTHON_PKGNAMEPREFIX}MySQLdb>0:${PORTSDIR}/databases/py-MySQLdb \\
+ ${PYTHON_PKGNAMEPREFIX}django>=1.3:${PORTSDIR}/www/py-django \\
+ ${PYTHON_PKGNAMEPREFIX}vobject>0:${PORTSDIR}/deskutils/py-vobject \\
+ ${PYTHON_PKGNAMEPREFIX}yaml>0:${PORTSDIR}/devel/py-yaml \\
+ ${PYTHON_PKGNAMEPREFIX}south>=0.7.6:${PORTSDIR}/databases/py-south
+
+BUILD_DEPENDS+= ${RPKID_DEPENDS}
+RUN_DEPENDS+= ${RPKID_DEPENDS}
+
+RUN_DEPENDS+= ${APACHE_PKGNAMEPREFIX}mod_wsgi>3:${PORTSDIR}/www/mod_wsgi3
+
+# Try to use system OpenSSL if we can.
+CONFIGURE_ENV= CFLAGS="-I${LOCALBASE}/include" LDFLAGS="-L${LOCALBASE}/lib"
+
+CONFIGURE_ARGS= --disable-target-installation --disable-rp-tools
+
+.include <bsd.port.mk>
+''' % { "portname" : base,
+ "snapshot" : vers,
+ "tarname" : name,
+ "master_sites" : os.path.dirname(url) + "/",
+ "distfiles" : os.path.basename(url) })
+
+with open(os.path.join(base, "pkg-descr"), "w") as f:
+ print "Writing", f.name
+
+ f.write('''\
+This is a port of the rpki.net RPKI toolkit CA tools.
+
+WWW: http://rpki.net/
+''')
+
+mkdir_maybe(os.path.join(base, "files"))
+
+with open(os.path.join(base, "files", "rpki-ca.in"), "w") as f:
+ print "Writing", f.name
+
+ f.write('''\
+#!/bin/sh
+
+# PROVIDE: rpki-ca
+# REQUIRE: LOGIN mysql
+# KEYWORD: shutdown
+#
+# Add the following line to /etc/rc.conf[.local] to enable whatever
+# RPKI CA services you have configured in rpki.conf
+#
+# rpkica_enable="YES"
+
+. /etc/rc.subr
+
+name="rpkica"
+rcvar=rpkica_enable
+
+start_cmd="rpkica_start"
+stop_cmd="rpkica_stop"
+
+load_rc_config $name
+
+: ${rpkica_enable="NO"}
+
+: ${rpkica_pid_dir="/var/run/rpki"}
+
+rpkica_start()
+{
+ /usr/bin/install -m 755 -d $rpkica_pid_dir
+ /usr/local/sbin/rpki-start-servers
+ return 0
+}
+
+rpkica_stop()
+{
+ for i in rpkid pubd irdbd rootd
+ do
+ if /bin/test -f $rpkica_pid_dir/$i.pid
+ then
+ /bin/kill `/bin/cat $rpkica_pid_dir/$i.pid`
+ fi
+ done
+ return 0
+}
+
+run_rc_command "$1"
+''')
+
+
+#with open(os.path.join(base, "pkg-plist"), "w") as f:
+# print "Writing empty", f.name
+
+print "Generating checksum"
+
+subprocess.check_call(("make", "makesum", "DISTDIR=" + os.getcwd()), cwd = base)
+
+# We will need a pkg-install and perhaps a pkg-deinstall, but I don't
+# know what they look like (yet).
+
+print "Building"
+
+# "USE_GNOME=" gets rid of annoying whining due to empty or
+# non-existent pkg-plist. The (direct) Gnome dependency doesn't
+# matter while constructing the port skeleton, so it's simplest just
+# to disable it for this one command.
+
+subprocess.check_call(("make", "DISTDIR=" + os.getcwd(), "USE_GNOME="), cwd = base)
+
+print "Installing to temporary tree"
+
+tempdir = os.path.join(base, "work", "temp-install", "")
+
+subprocess.check_call(("make", "install", "DESTDIR=" + os.path.abspath(tempdir)),
+ cwd = os.path.join(base, "work", name))
+
+print "Generating pkg-plist"
+
+with open(os.path.join(base, "pkg-plist"), "w") as f:
+
+ dont_remove = ("usr", "etc", "bin", "var", "lib", "sbin", "share", "lib/python2.7", "lib/python2.7/site-packages")
+
+ usr_local = None
+
+ for dirpath, dirnames, filenames in os.walk(tempdir, topdown = False):
+ dn = dirpath[len(tempdir):]
+
+ if dn.startswith("usr/local"):
+ if not usr_local and usr_local is not None:
+ f.write("@cwd\n")
+ usr_local = True
+ dn = dn[len("usr/local/"):]
+ else:
+ if usr_local:
+ f.write("@cwd /\n")
+ usr_local = False
+
+ if not dirnames and not filenames:
+ f.write("@exec mkdir -p %%D/%s\n" % dn)
+
+ for fn in filenames:
+ if fn == "rpki.conf.sample":
+ f.write("@unexec if cmp -s %%D/%s/rpki.conf.sample %%D/%s/rpki.conf; then rm -f %%D/%s/rpki.conf; fi\n" % (dn, dn, dn))
+ f.write(os.path.join(dn, fn) + "\n")
+ if fn == "rpki.conf.sample":
+ f.write("@exec if [ ! -f %%D/%s/rpki.conf ] ; then cp -p %%D/%s/rpki.conf.sample %%D/%s/rpki.conf; fi\n" % (dn, dn, dn))
+
+ if dn and dn not in dont_remove:
+ f.write("@dirrm %s\n" % dn)
+
+print "Cleaning up"
+
+subprocess.check_call(("make", "clean"), cwd = base)
diff --git a/buildtools/build-freebsd-port.py b/buildtools/build-freebsd-port.py
deleted file mode 100644
index 033bcc9b..00000000
--- a/buildtools/build-freebsd-port.py
+++ /dev/null
@@ -1,185 +0,0 @@
-"""
-Construct a FreeBSD port template given the URL of a source tarball.
-
-$Id$
-
-Copyright (C) 2012 Internet Systems Consortium ("ISC")
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-"""
-
-import sys
-import os
-import subprocess
-import urlparse
-import errno
-import glob
-
-try:
- url = sys.argv[1]
-except IndexError:
- sys.exit("Usage: %s URL-of-source-tarball" % sys.argv[0])
-
-def stripext(fn, *exts):
- fn1, fn2 = os.path.splitext(fn)
- return fn1 if fn2 in exts else fn
-
-def mkdir_maybe(*args):
- try:
- print "Creating", args[0]
- os.makedirs(*args)
- except OSError, e:
- if e.errno != errno.EEXIST:
- raise
-
-name = os.path.basename(urlparse.urlparse(url).path)
-name = stripext(name, ".gz", ".bz2", ".xz")
-name = stripext(name, ".tar", ".tgz", ".tbz", ".txz")
-
-# Up until this point this is fairly generic, but we reach the point
-# of diminishing returns when we have to parse the port name and
-# version number out of the filename. This will need to be changed
-# when we start doing this with something other than snapshot
-# tarballs.
-
-try:
- base, trunk, vers = name.split("-")
-except:
- base, trunk, vers = None
-
-if trunk != "trunk" or not vers.isdigit():
- sys.exit("Unexpected tarball URL name format")
-
-mkdir_maybe(base)
-
-fn = os.path.join(base, "Makefile")
-
-print "Writing", fn
-
-with open(fn, "w") as f:
- f.write('''\
-PORTNAME= %(portname)s
-PORTVERSION= 0.%(snapshot)s
-CATEGORIES= net
-MASTER_SITES= %(master_sites)s
-DISTFILES= %(distfiles)s
-WRKSRC= ${WRKDIR}/%(tarname)s
-
-MAINTAINER= sra@hactrn.net
-COMMENT= rpki.net RPKI tools package
-
-GNU_CONFIGURE= yes
-USE_PYTHON= 2.7+
-USE_MYSQL= server
-USE_APACHE_RUN= 22+
-USE_GNOME= libxml2 libxslt
-
-# For OpenSSL, not needed otherwise
-USE_PERL5_BUILD=yes
-
-# Split between dependency targets is somewhat arbitrary here, much of what is
-# listed as BUILD_DEPENDS might be better as RUN_DEPENDS.
-
-BUILD_DEPENDS+= ${PYTHON_PKGNAMEPREFIX}lxml>0:${PORTSDIR}/devel/py-lxml \\
- ${PYTHON_PKGNAMEPREFIX}MySQLdb>0:${PORTSDIR}/databases/py-MySQLdb \\
- ${PYTHON_PKGNAMEPREFIX}django>=1.3:${PORTSDIR}/www/py-django \\
- ${PYTHON_PKGNAMEPREFIX}vobject>0:${PORTSDIR}/deskutils/py-vobject \\
- ${PYTHON_PKGNAMEPREFIX}yaml>0:${PORTSDIR}/devel/py-yaml \\
- ${PYTHON_PKGNAMEPREFIX}south>=0.7.6:${PORTSDIR}/databases/py-south \\
- makedepend>0:${PORTSDIR}/devel/makedepend
-
-RUN_DEPENDS+= rrdtool>0:${PORTSDIR}/databases/rrdtool \\
- ${APACHE_PKGNAMEPREFIX}mod_wsgi>3:${PORTSDIR}/www/mod_wsgi3
-
-.include <bsd.port.mk>
-''' % { "portname" : base,
- "snapshot" : vers,
- "tarname" : name,
- "master_sites" : os.path.dirname(url) + "/",
- "distfiles" : os.path.basename(url) })
-
-fn = os.path.join(base, "pkg-descr")
-
-print "Writing", fn
-
-with open(fn, "w") as f:
- f.write('''\
-This is a port of the rpki.net RPKI toolkit.
-
-WWW: http://rpki.net/
-''')
-
-print "Generating checksum"
-
-subprocess.check_call(("make", "makesum", "DISTDIR=" + os.getcwd()), cwd = base)
-
-fn = os.path.join(base, "pkg-plist")
-print "Creating empty", fn
-open(fn, "w").close()
-
-print "Running make configure"
-
-# The "USE_GNOME=" setting is to silence a mess of grep errors we'd get otherwise.
-# Not sure what this is about, seems to trigger on empty pkg-plist, so just disable
-# this while generating pkg-plist so we can leave proper USE_GNOME setting in Makefile.
-
-subprocess.check_call(("make", "configure", "DISTDIR=" + os.getcwd(),
- "USE_GNOME=", "NO_DEPENDS=yes"),
- cwd = base)
-
-print "Running make installation-manifest"
-
-subprocess.check_call(("make", "installation-manifest"),
- cwd = os.path.join(base, "work", name))
-
-files = []
-dirs = []
-
-dirmap = {
- "%%BINDIR%%" : "bin",
- "%%DATAROOTDIR%%" : "share",
- "%%PYTHON_SITELIBDIR%%" : "%%PYTHON_SITELIBDIR%%",
- "%%RCDIR%%" : "etc/rc.d",
- "%%RCYNICJAILDIR%%" : "/var/rcynic",
- "%%SBINDIR%%" : "sbin",
- "%%SYSCONFDIR%%" : "etc" }
-
-fn = os.path.join(base, "work", name, "installation-manifest")
-
-print "Parsing", fn
-
-with open(fn, "r") as f:
- for line in f:
- kind, fn = line.rstrip("/").split()
- dir, sep, tail = fn.partition("/")
- if dir in dirmap:
- fn = dirmap[dir] + sep + tail
- else:
- print "Warning: No mapping for %r in %r, blundering onwards" % (dir, fn)
- if kind == "F":
- files.append(fn)
- elif kind == "D":
- dirs.append(fn)
- else:
- sys.exit("Don't know what to do with %r" % line)
-
-files.sort()
-dirs.sort(reverse = True)
-
-fn = os.path.join(base, "pkg-plist")
-print "Writing", fn
-with open(fn, "w") as f:
- for fn in files:
- f.write("%s\n" % fn)
- for fn in dirs:
- f.write("@dirrm %s\n" % fn)
diff --git a/buildtools/build-freebsd-rp-port.py b/buildtools/build-freebsd-rp-port.py
new file mode 100644
index 00000000..2b37c5a5
--- /dev/null
+++ b/buildtools/build-freebsd-rp-port.py
@@ -0,0 +1,351 @@
+"""
+Construct a FreeBSD port template given the URL of a source tarball.
+
+$Id$
+
+Copyright (C) 2012-2013 Internet Systems Consortium ("ISC")
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+"""
+
+import sys
+import os
+import subprocess
+import urlparse
+import errno
+import glob
+
+try:
+ url = sys.argv[1]
+except IndexError:
+ sys.exit("Usage: %s URL-of-source-tarball" % sys.argv[0])
+
+def stripext(fn, *exts):
+ fn1, fn2 = os.path.splitext(fn)
+ return fn1 if fn2 in exts else fn
+
+def mkdir_maybe(d):
+ try:
+ print "Creating", d
+ os.makedirs(d)
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ raise
+
+name = os.path.basename(urlparse.urlparse(url).path)
+name = stripext(name, ".gz", ".bz2", ".xz")
+name = stripext(name, ".tar", ".tgz", ".tbz", ".txz")
+
+# Up until this point this is fairly generic, but we reach the point
+# of diminishing returns when we have to parse the port name and
+# version number out of the filename. This will need to be changed
+# when we start doing this with something other than snapshot
+# tarballs.
+
+try:
+ base, branch, vers = name.split("-")
+except:
+ base, branch, vers = None
+
+if base not in ("rpkitools", "rpki"):
+ base = None
+
+if branch != "trunk" and (branch[:2] != "tk" or not branch[2:].isdigit()):
+ branch = None
+
+if not vers.isdigit() and (base != "rpki" or vers[0] != "r" or not vers[1:].isdigit()):
+ vers = None
+else:
+ vers = vers[1:]
+
+if None in (base, branch, vers):
+ sys.exit("Unexpected tarball URL name format")
+
+base += "-rp"
+
+mkdir_maybe(base)
+
+with open(os.path.join(base, "Makefile"), "w") as f:
+ print "Writing", f.name
+
+ f.write('''\
+PORTNAME= %(portname)s
+PORTVERSION= 0.%(snapshot)s
+CATEGORIES= net
+MASTER_SITES= %(master_sites)s
+DISTFILES= %(distfiles)s
+WRKSRC= ${WRKDIR}/%(tarname)s
+MAINTAINER= sra@hactrn.net
+COMMENT= rpki.net RPKI relying party tools
+
+GNU_CONFIGURE= yes
+USE_PYTHON= 2.7+
+USE_GNOME= libxml2 libxslt
+
+# For OpenSSL, not needed otherwise
+USE_PERL5_BUILD=yes
+
+# For building OpenSSL, not needed otherwise
+BUILD_DEPENDS+= makedepend>0:${PORTSDIR}/devel/makedepend
+
+# Needed at build to keep ./configure from complaining;
+# needed at runtime for rcynic to do anything useful.
+BUILD_DEPENDS+= rsync>0:${PORTSDIR}/net/rsync
+RUN_DEPENDS+= rsync>0:${PORTSDIR}/net/rsync
+
+# For rcynic-html
+RUN_DEPENDS+= rrdtool>0:${PORTSDIR}/databases/rrdtool
+
+# Just want relying party tools, try to use system OpenSSL if we can.
+
+CONFIGURE_ARGS= --disable-ca-tools
+CONFIGURE_ENV= CFLAGS="-I${LOCALBASE}/include" LDFLAGS="-L${LOCALBASE}/lib"
+
+# rcynic's Makefile constructs an rcynic.conf for us if it doesn't
+# find one already installed. This turns out to be exactly what
+# FreeBSD's rules want us to install as rcynic.conf.sample, so we
+# shuffle things around a bit just before and just after installation
+# to make this all come out right.
+#
+# If I ever teach rcynic to construct a .conf.sample file per the
+# FreeBSD way of doing things, this will need to change to match.
+
+pre-install:
+ PKG_PREFIX=${PREFIX} ${SH} ${PKGINSTALL} ${PKGNAME} PRE-INSTALL
+ @if [ -f ${PREFIX}/etc/rcynic.conf ]; then \
+ ${MV} -f ${PREFIX}/etc/rcynic.conf ${PREFIX}/etc/rcynic.conf.real ; \
+ fi
+
+post-install:
+ PKG_PREFIX=${PREFIX} ${SH} ${PKGINSTALL} ${PKGNAME} POST-INSTALL
+ @if [ -f ${PREFIX}/etc/rcynic.conf.real ]; then \
+ ${MV} -f ${PREFIX}/etc/rcynic.conf ${PREFIX}/etc/rcynic.conf.sample ; \
+ ${MV} -f ${PREFIX}/etc/rcynic.conf.real ${PREFIX}/etc/rcynic.conf ; \
+ else \
+ ${CP} -p ${PREFIX}/etc/rcynic.conf ${PREFIX}/etc/rcynic.conf.sample ; \
+ fi
+
+.include <bsd.port.mk>
+''' % { "portname" : base,
+ "snapshot" : vers,
+ "tarname" : name,
+ "master_sites" : os.path.dirname(url) + "/",
+ "distfiles" : os.path.basename(url) })
+
+with open(os.path.join(base, "pkg-descr"), "w") as f:
+ print "Writing", f.name
+
+ f.write('''\
+This is a port of the rpki.net RPKI toolkit relying party tools.
+
+WWW: http://rpki.net/
+''')
+
+with open(os.path.join(base, "pkg-plist"), "w") as f:
+
+ print "Writing empty", f.name
+
+print "Generating checksum"
+
+subprocess.check_call(("make", "makesum", "DISTDIR=" + os.getcwd()), cwd = base)
+
+print "Extracting list of trust anchors"
+
+trust_anchors = [os.path.basename(fn)
+ for fn in subprocess.check_output(("tar", "tf", os.path.basename(url))).splitlines()
+ if "/rcynic/sample-trust-anchors/" in fn and fn.endswith(".tal")]
+
+with open(os.path.join(base, "pkg-plist"), "w") as f:
+
+ print "Writing", f.name
+
+ f.write('''\
+bin/find_roa
+bin/hashdir
+bin/print_roa
+bin/print_rpki_manifest
+bin/rcynic
+bin/rcynic-cron
+bin/rcynic-html
+bin/rcynic-svn
+bin/rcynic-text
+bin/rtr-origin
+bin/scan_roas
+bin/validation_status
+@unexec if cmp -s %D/etc/rcynic.conf.sample %D/etc/rcynic.conf; then rm -f %D/etc/rcynic.conf; fi
+etc/rcynic.conf.sample
+@exec if [ ! -f %D/etc/rcynic.conf ] ; then cp -p %D/%F %D/etc/rcynic.conf; fi
+''')
+
+ for trust_anchor in sorted(trust_anchors):
+ f.write("etc/rpki/trust-anchors/%s\n" % trust_anchor)
+
+ f.write('''\
+@dirrm etc/rpki/trust-anchors
+@dirrmtry etc/rpki
+@dirrm www/apache22/data/rcynic
+@cwd /
+@exec install -d -o root -g wheel %D/var/rcynic
+@exec install -d -o rcynic -g rcynic %D/var/rcynic/data
+@dirrm var/rcynic/data
+@exec install -d -o rcynic -g rcynic %D/var/rcynic/rpki-rtr
+@dirrm var/rcynic/rpki-rtr/sockets
+@dirrm var/rcynic/rpki-rtr
+@dirrm var/rcynic
+''')
+
+# 90% of this is $top/rcynic/installation-scripts/freebsd/install.sh.
+# Somehow or another this duplication needs to go away, but priority
+# for today is a working package.
+
+with open(os.path.join(base, "pkg-install"), "w") as f:
+
+ print "Writing", f.name
+
+ f.write('''\
+#!/bin/sh -
+
+case $2 in
+
+PRE-INSTALL)
+ if /usr/sbin/pw groupshow "rcynic" 2>/dev/null; then
+ echo "You already have a group \\"rcynic\\", so I will use it."
+ elif /usr/sbin/pw groupadd rcynic; then
+ echo "Added group \\"rcynic\\"."
+ else
+ echo "Adding group \\"rcynic\\" failed..."
+ echo "Please create it, then try again."
+ exit 1
+ fi
+ if /usr/sbin/pw usershow "rcynic" 2>/dev/null; then
+ echo "You already have a user \\"rcynic\\", so I will use it."
+ elif /usr/sbin/pw useradd rcynic -g rcynic -h - -d /nonexistant -s /usr/sbin/nologin -c "RPKI validation system"; then
+ echo "Added user \\"rcynic\\"."
+ else
+ echo "Adding user \\"rcynic\\" failed..."
+ echo "Please create it, then try again."
+ exit 1
+ fi
+ ;;
+
+POST-INSTALL)
+ htmldir=/usr/local/www/apache22/data/rcynic
+ if ! test -d $htmldir ; then
+ echo "Creating $htmldir"
+ install -o rcynic -g rcynic -d $htmldir
+ fi
+ sockdir=/var/rcynic/rpki-rtr/sockets
+ if ! test -d $sockdir ; then
+ echo "Creating $sockdir"
+ install -o nobody -g rcynic -d $sockdir
+ fi
+ echo "Setting up rcynic's crontab to run rcynic-cron script"
+ /usr/bin/crontab -l -u rcynic 2>/dev/null |
+ /usr/bin/awk -v t=`hexdump -n 2 -e '"%u\\n"' /dev/random` '
+ BEGIN {
+ cmd = "exec /usr/local/bin/rcynic-cron";
+ }
+ $0 !~ cmd {
+ print;
+ }
+ END {
+ printf "%u * * * *\\t%s\\n", t % 60, cmd;
+ }' |
+ /usr/bin/crontab -u rcynic -
+ echo "Setting up rpki-rtr listener under inetd"
+ if /usr/bin/egrep -q '^rpki-rtr' /etc/services ; then
+ echo "You already have a /etc/services entry for rpki-rtr, so I will use it."
+ elif echo >>/etc/services "rpki-rtr 43779/tcp #RFC 6810" ; then
+ echo "Added rpki-rtr to /etc/services."
+ else
+ echo "Adding rpki-rtr to /etc/services failed, please fix this, then try again."
+ exit 1
+ fi
+ if /usr/bin/egrep -q "rpki-rtr[ ]+stream[ ]+tcp[ ]" /etc/inetd.conf; then
+ echo "You already have an inetd.conf entry for rpki-rtr on TCPv4, so I will use it."
+ elif echo >>/etc/inetd.conf "rpki-rtr stream tcp nowait nobody /usr/local/bin/rtr-origin rtr-origin --server /var/rcynic/rpki-rtr"; then
+ echo "Added rpki-rtr for TCPv4 to /etc/inetd.conf."
+ else
+ echo "Adding rpki-rtr for TCPv4 to /etc/inetd.conf failed, please fix this, then try again."
+ exit 1
+ fi
+ if /usr/bin/egrep -q "rpki-rtr[ ]+stream[ ]+tcp6[ ]" /etc/inetd.conf; then
+ echo "You already have an inetd.conf entry for rpki-rtr on TCPv6, so I will use it."
+ elif echo >>/etc/inetd.conf "rpki-rtr stream tcp6 nowait nobody /usr/local/bin/rtr-origin rtr-origin --server /var/rcynic/rpki-rtr"; then
+ echo "Added rpki-rtr for TCPv6 to /etc/inetd.conf."
+ else
+ echo "Adding rpki-rtr for TCPv6 to /etc/inetd.conf failed, please fix this, then try again."
+ exit 1
+ fi
+ ;;
+
+*)
+ echo "No clue what this script is meant to do when invoked with arguments \\"$*\\". Punting."
+ exit 1
+ ;;
+
+esac
+''')
+
+with open(os.path.join(base, "pkg-deinstall"), "w") as f:
+
+ print "Writing", f.name
+
+ f.write('''\
+#!/bin/sh -
+
+case $2 in
+
+DEINSTALL)
+ echo "Whacking rcynic's crontab"
+ /usr/bin/crontab -l -u rcynic 2>/dev/null |
+ /usr/bin/awk '
+ $0 !~ "exec /usr/local/bin/rcynic-cron" {
+ line[++n] = $0;
+ }
+ END {
+ if (n)
+ for (i = 1; i <= n; i++)
+ print line[i] | "/usr/bin/crontab -u rcynic -";
+ else
+ system("/usr/bin/crontab -u rcynic -r");
+ }'
+ ;;
+
+POST-DEINSTALL)
+ ;;
+
+*)
+ echo "No clue what this script is meant to do when invoked with arguments \\"$*\\". Punting."
+ exit 1
+ ;;
+
+esac
+''')
+
+with open(os.path.join(base, "pkg-message"), "w") as f:
+
+ print "Writing", f.name
+
+ f.write('''\
+You may want to customize /usr/local/etc/rcynic.conf. If you did not
+install your own trust anchors, a default set of SAMPLE trust anchors
+may have been installed for you, but you, the relying party, are the
+only one who can decide whether you trust those anchors. rcynic will
+not do anything useful without good trust anchors.
+
+rcynic-cron has been configured to run hourly, at a randomly selected
+minute, to spread load on the global RPKI repository servers. Please
+do NOT adjust this to run on the hour. In particular please do NOT
+adjust this to run at midnight UTC.
+''')
diff --git a/buildtools/debian-package-skeleton.py b/buildtools/debian-package-skeleton.py
new file mode 100644
index 00000000..e169fd2c
--- /dev/null
+++ b/buildtools/debian-package-skeleton.py
@@ -0,0 +1,841 @@
+# Generated by wrap-tree.py. Needs hacking for things like
+# maintaining the debian/changelog file, but at least this gets all
+# the debian/ubuntu stuff to date into the repository.
+
+import os
+
+os.makedirs('debian')
+
+with open('debian/changelog', "wb") as f:
+ f.write('''\
+rpki (0.5059) UNRELEASED; urgency=low
+ * Not using MANIFEST.in.
+ -- sra <sra@rpki.net> Sun, 24 Feb 2013 03:24:07 -0000
+
+rpki (0.5060) UNRELEASED; urgency=low
+ * First build, then install, doh.
+ -- sra <sra@rpki.net> Sun, 24 Feb 2013 03:33:30 -0000
+
+rpki (0.5059) UNRELEASED; urgency=low
+ * Not using MANIFEST.in.
+ -- sra <sra@rpki.net> Sun, 24 Feb 2013 03:24:07 -0000
+
+rpki (0.5058) UNRELEASED; urgency=low
+ * inetd/xinetd listener for rpki-rtr on source code installation,
+ also needed for Ubuntu package.
+ -- sra <sra@rpki.net> Sun, 24 Feb 2013 03:22:00 -0000
+
+rpki (0.5057) UNRELEASED; urgency=low
+ * Add dependency on xinetd.
+ -- sra <sra@rpki.net> Sat, 23 Feb 2013 13:25:46 -0000
+
+rpki (0.5056) UNRELEASED; urgency=low
+ * More post-installation: add rpki-rtr listener to /etc/services and
+ /etc/inetd.conf, create a few missing directories.
+ -- sra <sra@rpki.net> Sat, 23 Feb 2013 12:22:10 -0000
+
+rpki (0.5054) UNRELEASED; urgency=low
+ * Hack to use pip to install recent versions of Django and South.
+ Probably should be replaced by our own APT repository at some
+ point, but this seems to work.
+ -- sra <sra@rpki.net> Fri, 22 Feb 2013 03:48:54 -0000
+
+rpki (0.5051) UNRELEASED; urgency=low
+ * Pull from trunk.
+ -- sra <sra@rpki.net> Thu, 21 Feb 2013 01:17:22 -0000
+
+rpki (0.5047) UNRELEASED; urgency=low
+ * Pull from trunk.
+ -- sra <sra@rpki.net> Wed, 20 Feb 2013 08:31:58 -0000
+
+rpki (0.5045) UNRELEASED; urgency=low
+ * Pull from trunk.
+ -- sra <sra@rpki.net> Wed, 20 Feb 2013 01:31:40 -0000
+
+rpki (0.5042) UNRELEASED; urgency=low
+ * Get rid of silly "r" prefix on version number for FreeBSD
+ packages, among other reasons so that we can have the same version
+ numbers on FreeBSD and Ubuntu, doh.
+ -- sra <sra@rpki.net> Tue, 19 Feb 2013 02:20:28 -0000
+
+rpki (0.5041) UNRELEASED; urgency=low
+ * Install generated debian/changelog, now that we generate ones that
+ debuild accepts.
+ -- sra <sra@rpki.net> Mon, 18 Feb 2013 07:17:57 -0000
+
+rpki (0.5040) UNRELEASED; urgency=low
+ * debuild et al are picky about format of email addresses.
+
+ For some reason debuild now cares about "make test" failing (which
+ it always has on package builds, because of MySQL setup
+ requirements, but debuild used to ignore that), so tweak rules to
+ skip the test suite.
+ -- sra <sra@rpki.net> Mon, 18 Feb 2013 06:58:51 -0000
+
+rpki (0.5039) UNRELEASED; urgency=low
+ * Script to automate debian/changelogs.
+ -- sra <sra@rpki.net> Mon, 18 Feb 2013 05:46:00 -0000
+
+rpki (0.5038) UNRELEASED; urgency=low
+ * Add rc.d script.
+ -- sra <sra@rpki.net> Sun, 17 Feb 2013 10:05:49 -0000
+
+rpki (0.5037) UNRELEASED; urgency=low
+ * Debug pkg-plist generation.
+ -- sra <sra@rpki.net> Mon, 11 Feb 2013 05:27:59 -0000
+
+rpki (0.5036) UNRELEASED; urgency=low
+ * pkg-plist generation hacks.
+ -- sra <sra@rpki.net> Mon, 11 Feb 2013 03:04:05 -0000
+
+rpki (0.5035) UNRELEASED; urgency=low
+ * Pull from trunk.
+ -- sra <sra@rpki.net> Mon, 11 Feb 2013 02:25:18 -0000
+
+rpki (0.5034) UNRELEASED; urgency=low
+ * Add --disable-rp-tools, for package building.
+ -- sra <sra@rpki.net> Mon, 11 Feb 2013 02:18:42 -0000
+
+rpki (0.5030) UNRELEASED; urgency=low
+ * Pull from trunk.
+ -- sra <sra@rpki.net> Tue, 05 Feb 2013 21:04:06 -0000
+
+rpki (0.5028) UNRELEASED; urgency=low
+ * Run daemons as root for now, come back to permission issues when
+ everything else works as expected.
+ -- sra <sra@rpki.net> Tue, 05 Feb 2013 04:41:02 -0000
+
+rpki (0.5027) UNRELEASED; urgency=low
+ * Clean up debian/ directory, enable upstart.
+ -- sra <sra@rpki.net> Tue, 05 Feb 2013 00:12:49 -0000
+
+rpki (0.5026) UNRELEASED; urgency=low
+ * Install sample rpki.conf, since we don't (yet?) have a good way to
+ generate one automatically during installation. Installation
+ dialog is probably not the right way to go, some kind of setup
+ wizard script for the user to run after installation is probably a
+ better bet.
+ -- sra <sra@rpki.net> Mon, 04 Feb 2013 23:09:34 -0000
+
+rpki (0.5025) UNRELEASED; urgency=low
+ * Tweak directory ownerships on Debian install, and add a few more
+ bits to rpki-ca.upstart while we're at it.
+ -- sra <sra@rpki.net> Mon, 04 Feb 2013 05:36:12 -0000
+
+rpki (0.5024) UNRELEASED; urgency=low
+ * Allow naming tree(s) on command line.
+ -- sra <sra@rpki.net> Mon, 04 Feb 2013 05:31:03 -0000
+
+rpki (0.5023) UNRELEASED; urgency=low
+ * Wrapped debian skeleton.
+ -- sra <sra@rpki.net> Sun, 03 Feb 2013 22:27:01 -0000
+
+rpki (0.5022) UNRELEASED; urgency=low
+ * Helper for generating package skeletons.
+ -- sra <sra@rpki.net> Sun, 03 Feb 2013 22:15:47 -0000
+
+rpki (0.5021) UNRELEASED; urgency=low
+ * Checkpoint.
+ -- sra <sra@rpki.net> Sun, 03 Feb 2013 17:02:21 -0000
+
+rpki (0.5020) UNRELEASED; urgency=low
+ * Change default location of rcynic-html output on FreeBSD to track
+ the current FreeBSD Apache default, silly though that location may
+ be. Thanks, Jay!
+ -- sra <sra@rpki.net> Sun, 03 Feb 2013 16:41:33 -0000
+
+rpki (0.5019) UNRELEASED; urgency=low
+ * Don't try to run rcynic-html if parent output directory doesn't
+ exist.
+ -- sra <sra@rpki.net> Sun, 03 Feb 2013 16:36:45 -0000
+
+rpki (0.5018) UNRELEASED; urgency=low
+ * Doh, don't put in generated rcynic.conf.
+ -- sra <sra@rpki.net> Sun, 03 Feb 2013 16:25:18 -0000
+
+rpki (0.5017) UNRELEASED; urgency=low
+ * Cleanup
+ -- sra <sra@rpki.net> Sun, 03 Feb 2013 05:38:42 -0000
+
+rpki (0.5016) UNRELEASED; urgency=low
+ * Seems /var/run is a temporary filesystem on some platforms.
+ -- sra <sra@rpki.net> Sun, 03 Feb 2013 02:07:39 -0000
+
+rpki (0.5015) UNRELEASED; urgency=low
+ * Typo in pkg-deinstall.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 19:46:33 -0000
+
+rpki (0.5014) UNRELEASED; urgency=low
+ * Exit without whining when another process holds the lock.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 19:08:34 -0000
+
+rpki (0.5013) UNRELEASED; urgency=low
+ * Wire installed location of scan_roas into installed rtr-origin, so
+ that we can stop fighting with FreeBSD's odd habit of installing
+ packaged software in /usr/local/bin while excluding /usr/local/bin
+ from the default $PATH in system cron jobs and shell scripts.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 19:02:11 -0000
+
+rpki (0.5012) UNRELEASED; urgency=low
+ * Need rsync as both build and runtime dependency.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 08:34:30 -0000
+
+rpki (0.5011) UNRELEASED; urgency=low
+ * OK, now I know why nobody ever uses "install -C".
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 08:19:35 -0000
+
+rpki (0.5010) UNRELEASED; urgency=low
+ * rcynic requires rsync, doh.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 07:56:31 -0000
+
+rpki (0.5009) UNRELEASED; urgency=low
+ * Fun with DESTDIR.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 07:22:08 -0000
+
+rpki (0.5008) UNRELEASED; urgency=low
+ * Beat FreeBSD packaging stuff with a club. Might be working now.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 06:58:53 -0000
+
+rpki (0.5007) UNRELEASED; urgency=low
+ * Whoops, ac_* variables are lowercase this week.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 06:58:27 -0000
+
+rpki (0.5006) UNRELEASED; urgency=low
+ * Doh, write TAL configuration to correct file.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 05:37:46 -0000
+
+rpki (0.5005) UNRELEASED; urgency=low
+ * etc/rc.d/rcynic is only for jails, so it's not in the port
+ anymore.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 05:29:03 -0000
+
+rpki (0.5004) UNRELEASED; urgency=low
+ * Whack FreeBSD port skeleton to track recent changes.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 05:00:27 -0000
+
+rpki (0.5003) UNRELEASED; urgency=low
+ * First round of fixes to installation targets.
+ -- sra <sra@rpki.net> Sat, 02 Feb 2013 04:15:51 -0000
+
+rpki (0.5002) UNRELEASED; urgency=low
+ * Finally ready to start testing new rcynic install code.
+ -- sra <sra@rpki.net> Fri, 01 Feb 2013 21:50:18 -0000
+
+rpki (0.5001) UNRELEASED; urgency=low
+ * Checkpoint
+ -- sra <sra@rpki.net> Fri, 01 Feb 2013 18:38:48 -0000
+
+rpki (0.5000) UNRELEASED; urgency=low
+ * Cleanup.
+ -- sra <sra@rpki.net> Fri, 01 Feb 2013 13:22:19 -0000
+
+rpki (0.4999) UNRELEASED; urgency=low
+ * chown() lock file to rcynic user when creating it as root.
+ -- sra <sra@rpki.net> Fri, 01 Feb 2013 05:08:08 -0000
+
+rpki (0.4998) UNRELEASED; urgency=low
+ * Add rcynic-cron.
+ -- sra <sra@rpki.net> Fri, 01 Feb 2013 03:17:34 -0000
+
+rpki (0.4997) UNRELEASED; urgency=low
+ * Merge from trunk.
+ -- sra <sra@rpki.net> Thu, 31 Jan 2013 22:10:02 -0000
+
+rpki (0.4995) UNRELEASED; urgency=low
+ * Checkpoint
+ -- sra <sra@rpki.net> Thu, 31 Jan 2013 21:56:29 -0000
+
+rpki (0.4989) UNRELEASED; urgency=low
+ * Pull from trunk.
+ -- sra <sra@rpki.net> Thu, 31 Jan 2013 05:04:39 -0000
+
+rpki (0.4988) UNRELEASED; urgency=low
+ * Checkpoint
+ -- sra <sra@rpki.net> Thu, 31 Jan 2013 05:03:04 -0000
+
+rpki (0.4980) UNRELEASED; urgency=low
+ * Pull from trunk.
+ -- sra <sra@rpki.net> Fri, 25 Jan 2013 07:41:00 -0000
+
+rpki (0.4978) UNRELEASED; urgency=low
+ * Pull from trunk.
+ -- sra <sra@rpki.net> Fri, 25 Jan 2013 05:09:38 -0000
+
+rpki (0.4976) UNRELEASED; urgency=low
+
+ * Test update to changelog.
+
+ -- Rob Austein <sra@hactrn.net> Tue, 22 Jan 2013 02:50:01 -0500
+
+rpki (0.4968) UNRELEASED; urgency=low
+
+ * Initial Release.
+
+ -- Rob Austein <sra@hactrn.net> Tue, 15 Jan 2013 13:29:54 -0500
+''')
+
+with open('debian/compat', "wb") as f:
+ f.write('''\
+8
+''')
+
+with open('debian/control', "wb") as f:
+ f.write('''\
+# Dependencies on python-pip are a temporary hack, so that we can
+# install recent versions of django and south during Singapore
+# hackathon without messing about with setting up our own apt
+# repository. In the longer run, the dependencies on python-pip
+# should go away, and we should dependencies on python-django and
+# python-south with the right version numbers.
+#
+# Also see the pip install stuff in rpki-ca.postinst, which is part of
+# the same kludge.
+
+Source: rpki
+Priority: extra
+Maintainer: Rob Austein <sra@hactrn.net>
+Build-Depends: debhelper (>= 8.0.0), autotools-dev, xsltproc, python (>= 2.7), python-all-dev, python-setuptools, python-lxml, libxml2-utils, mysql-client, mysql-server, python-mysqldb, python-vobject, python-yaml
+Standards-Version: 3.9.3
+Homepage: http://trac.rpki.net/
+Vcs-Svn: http://subvert-rpki.hactrn.net/
+Vcs-Browser: http://trac.rpki.net/browser
+
+Package: rpki-rp
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, python (>= 2.7), rrdtool, rsync, xinetd
+Description: rpki.net relying party tools
+ "Relying party" validation tools from the rpki.net toolkit.
+ See the online documentation at http://rpki.net/.
+
+Package: rpki-ca
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, xsltproc, python (>= 2.7), python-pip, python-lxml, libxml2-utils, mysql-client, mysql-server, python-mysqldb, python-vobject, python-yaml
+Description: rpki.net certification authority tools
+ "Certification authority" tools for issuing RPKI certificates and
+ related objects using the rpki.net toolkit.
+ See the online documentation at http://rpki.net/.
+''')
+
+with open('debian/copyright', "wb") as f:
+ f.write('''\
+Format: http://dep.debian.net/deps/dep5
+Upstream-Name: rpki
+Source: http://rpki.net/
+
+
+Files: *
+Copyright: 2006-2008 American Registry for Internet Numbers
+ 2009-2013 Internet Systems Consortium
+ 2010-2013 SPARTA, Inc.
+License: ISC
+
+
+Files: openssl/openssl-*.tar.gz
+Copyright: 1998-2012 The OpenSSL Project
+ 1995-1998 Eric A. Young, Tim J. Hudson
+License: OpenSSL and SSLeay
+
+
+License: ISC
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ PERFORMANCE OF THIS SOFTWARE.
+
+
+License: OpenSSL
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ .
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ .
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ .
+ 3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+ "This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ .
+ 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ endorse or promote products derived from this software without
+ prior written permission. For written permission, please contact
+ licensing@OpenSSL.org.
+ .
+ 5. Products derived from this software may not be called "OpenSSL"
+ nor may "OpenSSL" appear in their names without prior written
+ permission of the OpenSSL Project.
+ .
+ 6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ .
+ THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ OF THE POSSIBILITY OF SUCH DAMAGE.
+ .
+ This product includes cryptographic software written by Eric Young
+ (eay@cryptsoft.com). This product includes software written by Tim
+ Hudson (tjh@cryptsoft.com).
+
+
+License: SSLeay
+ This library is free for commercial and non-commercial use as long as
+ the following conditions are aheared to. The following conditions
+ apply to all code found in this distribution, be it the RC4, RSA,
+ lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ included with this distribution is covered by the same copyright terms
+ except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ .
+ Copyright remains Eric Young's, and as such any Copyright notices in
+ the code are not to be removed.
+ If this package is used in a product, Eric Young should be given attribution
+ as the author of the parts of the library used.
+ This can be in the form of a textual message at program startup or
+ in documentation (online or textual) provided with the package.
+ .
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ "This product includes cryptographic software written by
+ Eric Young (eay@cryptsoft.com)"
+ The word 'cryptographic' can be left out if the rouines from the library
+ being used are not cryptographic related :-).
+ 4. If you include any Windows specific code (or a derivative thereof) from
+ the apps directory (application code) you must include an acknowledgement:
+ "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ .
+ THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+ .
+ The licence and distribution terms for any publically available version or
+ derivative of this code cannot be changed. i.e. this code cannot simply be
+ copied and put under another distribution licence
+ [including the GNU Public Licence.]
+''')
+
+with open('debian/rpki-ca.install', "wb") as f:
+ f.write('''\
+etc/rpki.conf.sample
+etc/rpki/apache.conf
+etc/rpki/settings.py
+usr/lib
+usr/sbin
+usr/share
+''')
+
+with open('debian/rpki-ca.lintian-overrides', "wb") as f:
+ f.write('''\
+# The RPKI code requires a copy of the OpenSSL library with both the
+# CMS code and RFC 3779 code enabled. All recent versions of OpenSSL
+# include this code, but it's not enabled on all platforms. On Ubuntu
+# 12.04 LTS, the RFC 3779 code is disabled. So we take the least bad
+# of our several bad options, and carefully link against a private
+# copy of the OpenSSL crypto library built with the options we need,
+# with all the voodoo necessary to avoid conflicts with, eg, the
+# OpenSSL shared libraries that are already linked into Python.
+#
+# It would be totally awesome if the OpenSSL package maintainers were
+# to enable the RFC 3779 code for us, but I'm not holding my breath.
+#
+# In the meantime, we need to tell lintian to allow this nasty hack.
+
+rpki-ca: embedded-library
+''')
+
+with open('debian/rpki-ca.postinst', "wb") as f:
+ f.write('''\
+#!/bin/sh
+# postinst script for rpki-ca
+#
+# see: dh_installdeb(1)
+
+set -e
+
+setup_rpkid_user() {
+ if ! getent passwd rpkid >/dev/null
+ then
+ useradd -g rpkid -M -N -d /nonexistent -s /sbin/nologin -c "RPKI certification authority engine(s)" rpkid
+ fi
+}
+
+setup_rpkid_group() {
+ if ! getent group rpkid >/dev/null
+ then
+ groupadd rpkid
+ fi
+}
+
+# This is kind of sick, but the versions of Django and and South that
+# ship with Ubuntu 12.04 LTS are too old, so we need to install from
+# PyPi if we can. If the user has already done that, great, otherwise
+# we try to do it here. Clearly this is not what we want in the long
+# run, but neither rae the OpenSSL library hacks.
+#
+# Basic approach here is copied from what we do in configure.ac.
+
+maybe_install_django() {
+ if python -c 'import sys, django; sys.exit(0 if django.VERSION < (1, 3, 7) else 1)' 2>/dev/null
+ then
+ echo 1>&2 "Unusable version of Django installed, please uninstall it then try again"
+ exit 1
+ fi
+
+ if ! python -c 'import django' 2>/dev/null &&
+ ! pip install django==1.3.7
+ then
+ echo 1>&2 "Unable to install usable version of Django, sorry"
+ exit 1
+ fi
+}
+
+maybe_install_south() {
+ if python -c 'import sys, south; sys.exit(0 if map(int,south.__version__.split(".")) < [0, 7, 6] else 1)' 2>/dev/null
+ then
+ echo 1>&2 "Unusable version of South installed, please uninstall it then try again"
+ exit 1
+ fi
+
+ if ! python -c 'import south' 2>/dev/null &&
+ ! pip install South==0.7.6
+ then
+ echo 1>&2 "Unable to install usable version of Django, sorry"
+ exit 1
+ fi
+}
+
+# summary of how this script can be called:
+# * <postinst> `configure' <most-recently-configured-version>
+# * <old-postinst> `abort-upgrade' <new version>
+# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+# <new-version>
+# * <postinst> `abort-remove'
+# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+# <failed-install-package> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ setup_rpkid_group
+ setup_rpkid_user
+ maybe_install_django
+ maybe_install_south
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \\`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+''')
+
+with open('debian/rpki-ca.upstart', "wb") as f:
+ f.write('''\
+# RPKI CA Service
+
+description "RPKI CA Servers"
+author "Rob Austein <sra@hactrn.net>"
+
+# This is almost certainly wrong. Suggestions on how to improve this
+# welcome, but please first read the Python code to understand what it
+# is doing.
+
+# Our only real dependencies are on mysqld and our config file.
+
+start on started mysql
+stop on stopping mysql
+
+pre-start script
+ if test -f /etc/rpki.conf &&
+ test -f /usr/share/rpki/ca.cer &&
+ test -f /usr/share/rpki/irbe.cer &&
+ test -f /usr/share/rpki/irdbd.cer &&
+ test -f /usr/share/rpki/rpkid.cer &&
+ test -f /usr/share/rpki/rpkid.key
+ then
+ install -m 755 -o rpkid -g rpkid -d /var/run/rpki
+
+ # This should be running as user rpkid, but I haven't got all
+ # the pesky details worked out yet. Most testing to date has
+ # either been all under a single non-root user or everything
+ # as root, so, eg, running "rpkic initialize" as root will not
+ # leave things in a sane state for rpkid running as user
+ # rpkid.
+ #
+ # In the interest of debugging the rest of this before trying
+ # to break new ground, run daemons as root for the moment,
+ # with the intention of coming back to fix this later.
+ #
+ #sudo -u rpkid /usr/sbin/rpki-start-servers
+ /usr/sbin/rpki-start-servers
+
+ else
+ stop
+ exit 0
+ fi
+end script
+
+post-stop script
+ for i in rpkid pubd irdbd rootd
+ do
+ if test -f /var/run/rpki/$i.pid
+ then
+ kill `cat /var/run/rpki/$i.pid`
+ fi
+ done
+end script
+''')
+
+with open('debian/rpki-rp.install', "wb") as f:
+ f.write('''\
+etc/rcynic.conf
+etc/rpki/trust-anchors
+etc/xinetd.d/rpki-rtr
+usr/bin
+var/rcynic
+''')
+
+with open('debian/rpki-rp.lintian-overrides', "wb") as f:
+ f.write('''\
+# The RPKI code requires a copy of the OpenSSL library with both the
+# CMS code and RFC 3779 code enabled. All recent versions of OpenSSL
+# include this code, but it's not enabled on all platforms. On Ubuntu
+# 12.04 LTS, the RFC 3779 code is disabled. So we take the least bad
+# of our several bad options, and carefully link against a private
+# copy of the OpenSSL crypto library built with the options we need,
+# with all the voodoo necessary to avoid conflicts with, eg, the
+# OpenSSL shared libraries that are already linked into Python.
+#
+# It would be totally awesome if the OpenSSL package maintainers were
+# to enable the RFC 3779 code for us, but I'm not holding my breath.
+#
+# In the meantime, we need to tell lintian to allow this nasty hack.
+
+rpki-rp: embedded-library
+
+# /var/rcynic is where we have been keeping this for years. We could change
+# but all the documentation says /var/rcynic. Maybe some day we will
+# figure out a politically correct place to put this, for now stick
+# with what the documentation leads the user to expect.
+
+rpki-rp: non-standard-dir-in-var
+''')
+
+with open('debian/rpki-rp.postinst', "wb") as f:
+ f.write('''\
+#!/bin/sh
+# postinst script for rpki-rp
+#
+# see: dh_installdeb(1)
+
+set -e
+
+setup_rcynic_ownership() {
+ install -o rcynic -g rcynic -d /var/rcynic/data /var/rcynic/rpki-rtr /var/rcynic/rpki-rtr
+ if test -d /var/www
+ then
+ install -o rcynic -g rcynic -d /var/www/rcynic
+ fi
+}
+
+setup_rcynic_user() {
+ if ! getent passwd rcynic >/dev/null
+ then
+ useradd -g rcynic -M -N -d /var/rcynic -s /sbin/nologin -c "RPKI validation system" rcynic
+ fi
+}
+
+setup_rcynic_group() {
+ if ! getent group rcynic >/dev/null
+ then
+ groupadd rcynic
+ fi
+}
+
+# We want to pick a *random* minute for rcynic to run, to spread load
+# on repositories, which is why we don't just use a package crontab.
+
+setup_rcynic_cron() {
+ crontab -l -u rcynic 2>/dev/null |
+ awk -v t=`hexdump -n 2 -e '"%u\\n"' /dev/urandom` '
+ BEGIN { cmd = "exec /usr/bin/rcynic-cron" }
+ $0 !~ cmd { print }
+ END { printf "%u * * * *\\t%s\\n", t % 60, cmd }
+ ' |
+ crontab -u rcynic -
+}
+
+setup_rpki_rtr_listener() {
+ killall -HUP xinetd
+}
+
+# summary of how this script can be called:
+# * <postinst> `configure' <most-recently-configured-version>
+# * <old-postinst> `abort-upgrade' <new version>
+# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+# <new-version>
+# * <postinst> `abort-remove'
+# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+# <failed-install-package> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ setup_rcynic_group
+ setup_rcynic_user
+ setup_rcynic_ownership
+ setup_rcynic_cron
+ setup_rpki_rtr_listener
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \\`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+''')
+
+with open('debian/rpki-rp.prerm', "wb") as f:
+ f.write('''\
+#!/bin/sh
+# prerm script for rpki-rp
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <prerm> `remove'
+# * <old-prerm> `upgrade' <new-version>
+# * <new-prerm> `failed-upgrade' <old-version>
+# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+# * <deconfigured's-prerm> `deconfigure' `in-favour'
+# <package-being-installed> <version> `removing'
+# <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ remove)
+
+ crontab -l -u rcynic 2>/dev/null | awk '
+ $0 !~ "exec /usr/bin/rcynic-cron" {
+ line[++n] = $0;
+ }
+ END {
+ if (n)
+ for (i = 1; i <= n; i++)
+ print line[i] | "crontab -u rcynic -";
+ else
+ system("crontab -u rcynic -r");
+ }'
+ ;;
+
+ upgrade|deconfigure)
+ ;;
+
+ failed-upgrade)
+ ;;
+
+ *)
+ echo "prerm called with unknown argument \\`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+''')
+
+with open('debian/rules', "wb") as f:
+ f.write('''\
+#!/usr/bin/make -f
+# -*- makefile -*-
+
+# Uncomment this to turn on verbose mode.
+export DH_VERBOSE=1
+
+%:
+ dh $@ --with python2
+
+override_dh_auto_configure:
+ dh_auto_configure -- --disable-target-installation
+
+override_dh_auto_test:
+ @true
+''')
+
+os.makedirs('debian/source')
+
+with open('debian/source/format', "wb") as f:
+ f.write('''\
+3.0 (native)
+''')
diff --git a/buildtools/hack-debian-changelog.py b/buildtools/hack-debian-changelog.py
new file mode 100644
index 00000000..01d66fd3
--- /dev/null
+++ b/buildtools/hack-debian-changelog.py
@@ -0,0 +1,110 @@
+# $Id$
+#
+# Nasty hack to generate debian/changelog entries from subversion.
+# This is useful to the extent that it allows us to generate new
+# packages automatically with version numbers corresponding to
+# subversion revisions; the human-readable part of the changelog may
+# or may not be all that useful
+#
+#
+# Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+
+import debian.changelog
+import email.utils
+import subprocess
+import textwrap
+import time
+import calendar
+import errno
+import os
+
+try:
+ from lxml.etree import XML
+except ImportError:
+ from xml.etree.ElementTree import XML
+
+fn = "debian/changelog"
+
+ignore_trivial_changes = False
+
+trivial_changes = ("Pull from trunk.", "Merge from trunk.", "Checkpoint.", "Cleanup.")
+
+# Fill this in (somehow) with real email addresses if and when we
+# care. Right now we only care to the extent that failing to comply
+# with the required syntax breaks package builds.
+
+author_map = {}
+
+author_default_format = "%s <%s@rpki.net>"
+
+# Main
+
+changelog = debian.changelog.Changelog()
+
+try:
+ with open(fn) as f:
+ changelog.parse_changelog(f)
+ latest = int(str(changelog.version).split(".")[1])
+ print "Parsed", fn, "latest change", latest
+except IOError, e:
+ if e.errno == errno.ENOENT:
+ print fn, "not found, starting new changelog"
+ latest = 0
+ else:
+ raise
+
+print "Pulling change list from subversion"
+
+svn = XML(subprocess.check_output(("svn", "log", "--xml", "--revision", "%s:COMMITTED" % (latest + 1))))
+
+first_wrapper = textwrap.TextWrapper(initial_indent = " * ", subsequent_indent = " ")
+rest_wrapper = textwrap.TextWrapper(initial_indent = " ", subsequent_indent = " ")
+
+changed = 0
+
+print "Generating new change entries"
+
+for elt in svn.findall("logentry"):
+ msg = elt.findtext("msg")
+ author = elt.findtext("author")
+
+ if ignore_trivial_changes and (msg in trivial_changes or msg + "." in trivial_changes):
+ continue
+
+ author = author_map.get(author, author_default_format % (author, author))
+
+ changelog.new_block(
+ package = changelog.package,
+ version = "0." + elt.get("revision"),
+ distributions = changelog.distributions,
+ urgency = changelog.urgency,
+ author = author,
+ date = email.utils.formatdate(calendar.timegm(time.strptime(elt.findtext("date"),
+ "%Y-%m-%dT%H:%M:%S.%fZ"))))
+ changelog.add_change("\n\n".join((rest_wrapper if i else first_wrapper).fill(s)
+ for i, s in enumerate(msg.split("\n\n"))))
+
+ changed += 1
+
+if changed:
+ print changed, "new entries"
+ with open(fn + ".new", "w") as f:
+ print "Writing", f.name
+ changelog.write_to_open_file(f)
+ print "Renaming %s.new to %s" % (fn, fn)
+ os.rename(fn + ".new", fn)
+else:
+ print "No changes"
diff --git a/buildtools/make-rcynic-script.py b/buildtools/make-rcynic-script.py
index 1bdd7960..472faa98 100644
--- a/buildtools/make-rcynic-script.py
+++ b/buildtools/make-rcynic-script.py
@@ -1,7 +1,7 @@
"""
$Id$
-Copyright (C) 2011-2012 Internet Systems Consortium ("ISC")
+Copyright (C) 2011-2013 Internet Systems Consortium ("ISC")
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -23,10 +23,16 @@ sys.stdout.write('''\
#!%(AC_PYTHON_INTERPRETER)s
# Automatically constructed script header
-ac_rrdtool_binary = "%(AC_RRDTOOL_BINARY)s"
+''' % os.environ)
+
+for k, v in os.environ.iteritems():
+ if k.startswith("AC_") and k != "AC_PYTHON_INTERPRETER":
+ sys.stdout.write("%s = '''%s'''\n" % (k.lower(), v))
+
+sys.stdout.write('''\
# Original script starts here
-''' % os.environ)
+''')
sys.stdout.write(sys.stdin.read())
diff --git a/buildtools/wrap-tree.py b/buildtools/wrap-tree.py
new file mode 100644
index 00000000..2123b79b
--- /dev/null
+++ b/buildtools/wrap-tree.py
@@ -0,0 +1,61 @@
+"""
+Package a directory tree inside a Python script. This is mostly
+useful when generating templates for small trees of files one wants to
+generate automatically with some customizations (eg, the skeleton for
+some the packaging files needed by some platform or another).
+
+$Id$
+
+Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+"""
+
+import os
+import sys
+
+result = {}
+
+for root in sys.argv[1:] or ["."]:
+ if root != ".":
+ result[root] = None
+ for dirpath, dirs, files in os.walk(root):
+ for dn in dirs:
+ dn = os.path.relpath(os.path.join(dirpath, dn))
+ result[dn] = None
+ for fn in files:
+ fn = os.path.relpath(os.path.join(dirpath, fn))
+ with open(fn, "r") as f:
+ result[fn] = f.read()
+
+sys.stdout.write("# Automatically generated. Hack if you like, but beware of overwriting.\n\nimport os\n")
+
+for k in sorted(result):
+ v = result[k]
+ if v is None:
+ sys.stdout.write("\nos.makedirs(%r)\n" % k)
+ else:
+ sys.stdout.write("\nwith open(%r, \"wb\") as f:\n" % k)
+ lines = v.splitlines()
+ if v.endswith("\n"):
+ lines.append("")
+ sys.stdout.write(" f.write('''\\\n")
+ while lines:
+ words = lines.pop(0).replace("\\", "\\\\").split("'''")
+ sys.stdout.write(words[0])
+ for word in words[1:]:
+ sys.stdout.write("''' + \"'''\" + '''")
+ sys.stdout.write(word)
+ if not lines:
+ sys.stdout.write("''')")
+ sys.stdout.write("\n")