]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
add apkg-powered upstream packaging for deb, rpm
authorJakub Ružička <jakub.ruzicka@nic.cz>
Tue, 6 Apr 2021 16:13:16 +0000 (18:13 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 19 May 2021 15:22:11 +0000 (17:22 +0200)
Files in a single new distro/ dir allow apkg to build BIRD packages for
various distros directly from upstream sources as well as from upstream
archives.

Please see distro/README.md for more detail as well as apkg docs:

https://apkg.rtfd.io

I've used these files to build bird-2.0.8 on all currently supported
releases of following distros:

* Debian
* Ubuntu
* Fedora
* CentOS
* openSUSE

Please note that latest apkg with accumulated fixes for bird is needed:
https://gitlab.nic.cz/packaging/apkg/-/merge_requests/35

30 files changed:
.gitignore
distro/README.md [new file with mode: 0644]
distro/config/apkg.toml [new file with mode: 0644]
distro/pkg/deb/bird.xml [new file with mode: 0644]
distro/pkg/deb/bird2-doc.docs [new file with mode: 0644]
distro/pkg/deb/bird2.bird.init [new file with mode: 0644]
distro/pkg/deb/bird2.bird.service [new file with mode: 0644]
distro/pkg/deb/bird2.docs [new file with mode: 0644]
distro/pkg/deb/bird2.install [new file with mode: 0644]
distro/pkg/deb/bird2.lintian-overrides [new file with mode: 0644]
distro/pkg/deb/bird2.manpages [new file with mode: 0644]
distro/pkg/deb/bird2.postinst [new file with mode: 0644]
distro/pkg/deb/bird2.postrm [new file with mode: 0644]
distro/pkg/deb/changelog [new file with mode: 0644]
distro/pkg/deb/compat [new file with mode: 0644]
distro/pkg/deb/control [new file with mode: 0644]
distro/pkg/deb/copyright [new file with mode: 0644]
distro/pkg/deb/envvars [new file with mode: 0644]
distro/pkg/deb/gbp.conf [new file with mode: 0644]
distro/pkg/deb/patches/0001-Sync-the-linuxdoc-mangled-files-with-linuxdoc-tools_.patch [new file with mode: 0644]
distro/pkg/deb/patches/series [new file with mode: 0644]
distro/pkg/deb/prepare-environment [new file with mode: 0755]
distro/pkg/deb/rules [new file with mode: 0755]
distro/pkg/deb/source/format [new file with mode: 0644]
distro/pkg/deb/watch [new file with mode: 0644]
distro/pkg/rpm/bird.service [new file with mode: 0644]
distro/pkg/rpm/bird.spec [new file with mode: 0644]
distro/pkg/rpm/bird.tmpfilesd [new file with mode: 0644]
tools/make-dev-archive [new file with mode: 0755]
tools/make-obs [new file with mode: 0755]

index 4dd0a56887a40c18a6e39f59c89d9d1a18a2b81a..a50f1fceb2ab049f37e02da89cfa171472f4c55f 100644 (file)
@@ -1,5 +1,6 @@
 /autom4te.cache/
 /obj/
+/pkg/
 /Makefile
 /bird
 /birdc
@@ -12,3 +13,4 @@
 /sysdep/autoconf.h.in
 /sysdep/autoconf.h.in~
 /cscope.*
+*.tar.gz
diff --git a/distro/README.md b/distro/README.md
new file mode 100644 (file)
index 0000000..ac1a75b
--- /dev/null
@@ -0,0 +1,69 @@
+# BIRD upstream packaging sources
+
+This distro/ directory contains packaging sources initially copied from Debian
+and Fedora downstream repos.
+
+Files in this directory follow [apkg] conventions and apkg can be used to
+create BIRD packages for various distros directly from upstream sources as
+well as from upstream archives.
+
+[apkg]: https://apkg.rtfd.io
+
+
+## Create (source) package from current repo commit
+
+Following command should build source package for current distro directly
+from current repo state - run at top bird directory:
+
+    apkg srcpkg
+
+or build native packages directly:
+
+    apkg build
+
+or in case of disposable VM/container you can use faster direct host build
+
+    apkg build -Hi
+
+tools/make-dev-archive script is in charge of creating archive from source.
+
+
+## Create (source) package from upstream release
+
+Following commands can be used to clone upstream repo, download current upstream
+archive (tarball), and build Debian, Ubuntu, Fedora, CentOS, or OpenSUSE
+source package (depending on host system) using files in bird/distro:
+
+    git clone https://gitlab.nic.cz/labs/bird
+    cd bird
+    apkg get-archive
+    apkg srcpkg -a pkg/archives/upstream/bird-2.0.8.tar.gz
+
+To create native packages instead use `build`:
+
+    apkg build -a pkg/archives/upstream/bird-2.0.8.tar.gz
+
+Or to build packages directly in case of a disposable VM/container (faster, modifies system):
+
+    apkg build -Hi -a pkg/archives/upstream/bird-2.0.8.tar.gz
+
+
+## Build packages in openSUSE Build Service (OBS)
+
+tools/make-obs script can be used on Debian-based system to create OBS
+source package in pkg/obs directory ready to be uploaded:
+
+    cd bird
+    apkg get-archive
+    ./tools/make-obs
+    # result in pkg/obs
+
+You can also supply (upstream) archive to build from:
+
+    # or to use specified archive
+    ./tools/make-obs pkg/archives/upstream/bird-2.0.8.tar.gz
+
+
+## More Info
+
+Please see [apkg docs][apkg].
diff --git a/distro/config/apkg.toml b/distro/config/apkg.toml
new file mode 100644 (file)
index 0000000..c70306d
--- /dev/null
@@ -0,0 +1,8 @@
+[project]
+name = "bird"
+# needed for make-archive
+make_archive_script = "tools/make-dev-archive"
+
+[upstream]
+# needed for get-archive
+archive_url = "https://bird.network.cz/download/bird-{{ version }}.tar.gz"
diff --git a/distro/pkg/deb/bird.xml b/distro/pkg/deb/bird.xml
new file mode 100644 (file)
index 0000000..4ba3868
--- /dev/null
@@ -0,0 +1,286 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+
+<!--
+
+`xsltproc -''-nonet \
+          -''-param man.charmap.use.subset "0" \
+          -''-param make.year.ranges "1" \
+          -''-param make.single.year.ranges "1" \
+          /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl \
+          manpage.xml'
+
+A manual page <package>.<section> will be generated. You may view the
+manual page with: nroff -man <package>.<section> | less'. A typical entry
+in a Makefile or Makefile.am is:
+
+DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl
+XP     = xsltproc -''-nonet -''-param man.charmap.use.subset "0"
+
+manpage.1: manpage.xml
+        $(XP) $(DB2MAN) $<
+
+The xsltproc binary is found in the xsltproc package. The XSL files are in
+docbook-xsl. A description of the parameters you can use can be found in the
+docbook-xsl-doc-* packages. Please remember that if you create the nroff
+version in one of the debian/rules file targets (such as build), you will need
+to include xsltproc and docbook-xsl in your Build-Depends control field.
+Alternatively use the xmlto command/package. That will also automatically
+pull in xsltproc and docbook-xsl.
+
+Notes for using docbook2x: docbook2x-man does not automatically create the
+AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as
+<refsect1> ... </refsect1>.
+
+To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections
+read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be
+found in the docbook-xsl-doc-html package.
+
+Validation can be done using: `xmllint -''-noout -''-valid manpage.xml`
+
+General documentation about man-pages and man-page-formatting:
+man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
+
+-->
+
+  <!ENTITY dhfirstname "Giovanni">
+  <!ENTITY dhsurname   "Mascellani">
+  <!ENTITY dhusername  "&dhfirstname; &dhsurname;">
+  <!ENTITY dhemail     "mascellani@poisson.phc.unipi.it">
+  <!ENTITY dhsection   "8">
+  <!ENTITY dhtitle     "BIRD User Manual">
+]>
+
+<refentry>
+  <refentryinfo>
+    <title>&dhtitle;</title>
+    <productname>bird</productname>
+    <authorgroup>
+      <author>
+       <firstname>&dhfirstname;</firstname>
+        <surname>&dhsurname;</surname>
+        <contrib>Wrote this manpage for the Debian system.</contrib>
+        <address>
+          <email>&dhemail;</email>
+        </address>
+      </author>
+    </authorgroup>
+    <copyright>
+      <year>2010</year>
+      <holder>&dhusername;</holder>
+    </copyright>
+    <legalnotice>
+      <para>This manual page was written for the Debian system
+        (and may be used by others).</para>
+      <para>Permission is granted to copy, distribute and/or modify this
+        document under the terms of the GNU General Public License,
+        Version 2 or (at your option) any later version published by
+        the Free Software Foundation.</para>
+      <para>On Debian systems, the complete text of the GNU General Public
+        License can be found in
+        <filename>/usr/share/common-licenses/GPL</filename>.</para>
+    </legalnotice>
+
+  </refentryinfo>
+  <refmeta>
+    <refentrytitle>bird</refentrytitle>
+    <manvolnum>&dhsection;</manvolnum>
+  </refmeta>
+  <refnamediv>
+    <refname>bird</refname>
+    <refpurpose>BIRD Internet Routing Daemon</refpurpose>
+  </refnamediv>
+  <refnamediv>
+    <refname>birdc</refname>
+    <refpurpose>BIRD Internet Routing Daemon remote control</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>bird</command>
+      <arg choice="opt"><option>-c <replaceable>config-file</replaceable></option></arg>
+      <arg choice="opt"><option>-d</option></arg>
+      <arg choice="opt"><option>-D <replaceable>debug-file</replaceable></option></arg>
+      <arg choice="opt"><option>-f</option></arg>
+      <arg choice="opt"><option>-g <replaceable>group</replaceable></option></arg>
+      <arg choice="opt"><option>-l</option></arg>
+      <arg choice="opt"><option>-p</option></arg>
+      <arg choice="opt"><option>-P <replaceable>pid-file</replaceable></option></arg>
+      <arg choice="opt"><option>-R</option></arg>
+      <arg choice="opt"><option>-s <replaceable>control-socket</replaceable></option></arg>
+      <arg choice="opt"><option>-u <replaceable>user</replaceable></option></arg>
+    </cmdsynopsis>
+    <cmdsynopsis>
+      <command>birdc</command>
+      <arg choice="opt"><option>-l</option></arg>
+      <arg choice="opt"><option>-r</option></arg>
+      <arg choice="opt"><option>-s <replaceable>control-socket</replaceable></option></arg>
+      <arg choice="opt"><option>-v</option></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1 id="description">
+    <title>DESCRIPTION</title>
+    <para><command>bird</command> is an Internet Routing Daemon. That is,
+      it sends and receives messages using different protocols in order to
+      discover and exchange routing information with other routing daemons
+      present on the same network. It is able to talk the most widely
+      known routing protocols (such as BGPv4, RIPv2, OSPFv2 and OSPFv3),
+      both on IPv4 and IPv6 and it features a very powerful language for
+      route filtering.</para>
+    <para><command>birdc</command> is a remote control for <command>bird</command>.
+      While <command>bird</command> is running, the system administrator can
+      connect to it using <command>birdc</command>, to inspect its internal
+      status and reconfigure it. The two processes use a Unix socket to
+      communicate. Once started, <command>bird</command> will give access
+      to an interactive shell: commands can be completed with TAB and help
+      can be requested by pressing the key `?'. More documentation on
+      the available commands can be foung on the website, see below.</para>
+  </refsect1>
+
+  <refsect1 id="options">
+    <title>OPTIONS</title>
+    <para>The <command>bird</command> accepts these options:</para>
+    <variablelist>
+      <varlistentry>
+        <term><option>-c <replaceable>config-file</replaceable></option></term>
+        <listitem>
+          <para>Use given configuration file instead of the default /etc/bird/bird.conf.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-d</option></term>
+        <listitem>
+          <para>Enable debug messages to stderr, and run bird in foreground.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-D <replaceable>debug-file</replaceable></option></term>
+        <listitem>
+          <para>Enable debug messages to given file.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-f</option></term>
+        <listitem>
+          <para>Run bird in foreground.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-g <replaceable>group</replaceable></option></term>
+        <listitem>
+          <para>Run bird with given group ID.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--help</option></term>
+        <listitem>
+          <para>Display command-line options to bird.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-l</option></term>
+        <listitem>
+          <para>Look for a configuration file and a communication socket in the
+            current working directory instead of in default system locations.
+            However, paths specified by options <option>-c</option>,
+            <option>-s</option> have higher priority.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-p</option></term>
+        <listitem>
+          <para>Just parse the config file and exit. Return value is zero if the
+            config file is valid, nonzero if there are some errors.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-P <replaceable>pid-file</replaceable></option></term>
+        <listitem>
+          <para>Create a PID file with given filename.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-R</option></term>
+        <listitem>
+          <para>Apply graceful restart recovery after start.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-s <replaceable>control-socket</replaceable></option></term>
+        <listitem>
+          <para>Use given filename for a socket for communications with the
+            client (remote control), default is /run/bird/bird.ctl.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-u <replaceable>user</replaceable></option></term>
+        <listitem>
+          <para>Drop privileges and run as given user instead of root. The bird
+            would keep CAP_NET_ADMIN and other network-related capabilities
+            necessary for its function.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--version</option></term>
+        <listitem>
+          <para>Display bird version.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>The <command>birdc</command> accepts these options:</para>
+    <variablelist>
+      <varlistentry>
+        <term><option>-l</option></term>
+        <listitem>
+          <para>Look for a communication socket in the current working directory.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-r</option></term>
+        <listitem>
+          <para>Run <command>birdc</command> in restricted mode: only the
+            `show ...' commands are allowed.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-s <replaceable>control-socket</replaceable></option></term>
+        <listitem>
+          <para>Use given filename for a socket for communications with the
+            server, default is /run/bird/bird.ctl.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-v</option></term>
+        <listitem>
+          <para>Numeric return codes are dumped along with messages, making
+            them easily parsable by a program. See the programmer's documentation
+            for information about their meanings.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1 id="files">
+    <title>FILES</title>
+    <variablelist>
+      <varlistentry>
+        <term><filename>/etc/bird/bird.conf</filename></term>
+        <listitem>
+          <para>The system-wide configuration file to control the
+            behaviour of <application>bird</application>. See
+            the website for more documentation.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1 id="see_also">
+    <title>SEE ALSO</title>
+    <para>More documentation con be found on the website:
+      https://bird.network.cz/.</para>
+  </refsect1>
+</refentry>
+
diff --git a/distro/pkg/deb/bird2-doc.docs b/distro/pkg/deb/bird2-doc.docs
new file mode 100644 (file)
index 0000000..4c0c646
--- /dev/null
@@ -0,0 +1,4 @@
+obj/doc/bird*.html
+obj/doc/bird.pdf
+obj/doc/prog*.html
+obj/doc/prog.pdf
diff --git a/distro/pkg/deb/bird2.bird.init b/distro/pkg/deb/bird2.bird.init
new file mode 100644 (file)
index 0000000..ac15e69
--- /dev/null
@@ -0,0 +1,136 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          bird
+# Required-Start:    $remote_fs $syslog
+# Required-Stop:     $remote_fs $syslog
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+### END INIT INFO
+
+# Author: Ondřej Surý <ondrej@sury.org>
+#
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC="BIRD Internet Routing Daemon"
+NAME=bird
+DAEMON=/usr/sbin/$NAME
+BIRD_ARGS=""
+SCRIPTNAME=/etc/init.d/$NAME
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# read the RUN variables
+. /etc/bird/envvars
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+# Create /run/bird with correct permissions
+/usr/lib/bird/prepare-environment
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+       # Return
+       #   0 if daemon has been started
+       #   1 if daemon was already running
+       #   2 if daemon could not be started
+       start-stop-daemon --start --quiet --name $NAME --exec $DAEMON --test > /dev/null \
+               || return 1
+       start-stop-daemon --start --quiet --name $NAME --exec $DAEMON -- \
+               -u $BIRD_RUN_USER -g $BIRD_RUN_GROUP $BIRD_ARGS \
+               || return 2
+       # Add code here, if necessary, that waits for the process to be ready
+       # to handle requests from services started subsequently which depend
+       # on this one.  As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+       # Return
+       #   0 if daemon has been stopped
+       #   1 if daemon was already stopped
+       #   2 if daemon could not be stopped
+       #   other if a failure occurred
+       start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --name $NAME --exec $DAEMON
+       RETVAL="$?"
+       [ "$RETVAL" = 2 ] && return 2
+       # Wait for children to finish too if this is a daemon that forks
+       # and if the daemon is only ever run from this initscript.
+       start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --name $NAME --exec $DAEMON
+       [ "$?" = 2 ] && return 2
+       return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+       #
+       # If the daemon can reload its configuration without
+       # restarting (for example, when it is sent a SIGHUP),
+       # then implement that here.
+       #
+       start-stop-daemon --stop --signal 1 --quiet --name $NAME --exec $DAEMON
+       return 0
+}
+
+case "$1" in
+  start)
+       log_daemon_msg "Starting $DESC" "$NAME"
+       do_start
+       case "$?" in
+               0|1) log_end_msg 0 ;;
+               2) log_end_msg 1 ;;
+       esac
+       ;;
+  stop)
+       log_daemon_msg "Stopping $DESC" "$NAME"
+       do_stop
+       case "$?" in
+               0|1) log_end_msg 0 ;;
+               2) log_end_msg 1 ;;
+       esac
+       ;;
+  reload|force-reload)
+       #
+       # If do_reload() is not implemented then leave this commented out
+       # and leave 'force-reload' as an alias for 'restart'.
+       #
+       log_daemon_msg "Reloading $DESC" "$NAME"
+       do_reload
+       log_end_msg $?
+       ;;
+  restart)
+       log_daemon_msg "Restarting $DESC" "$NAME"
+       do_stop
+       case "$?" in
+         0|1)
+               do_start
+               case "$?" in
+                       0) log_end_msg 0 ;;
+                       1) log_end_msg 1 ;; # Old process is still running
+                       *) log_end_msg 1 ;; # Failed to start
+               esac
+               ;;
+         *)
+               # Failed to stop
+               log_end_msg 1
+               ;;
+       esac
+       ;;
+  *)
+       echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+       exit 3
+       ;;
+esac
+
+:
diff --git a/distro/pkg/deb/bird2.bird.service b/distro/pkg/deb/bird2.bird.service
new file mode 100644 (file)
index 0000000..37e75fb
--- /dev/null
@@ -0,0 +1,14 @@
+[Unit]
+Description=BIRD Internet Routing Daemon
+After=network.target
+
+[Service]
+EnvironmentFile=/etc/bird/envvars
+ExecStartPre=/usr/lib/bird/prepare-environment
+ExecStartPre=/usr/sbin/bird -p
+ExecReload=/usr/sbin/birdc configure
+ExecStart=/usr/sbin/bird -f -u $BIRD_RUN_USER -g $BIRD_RUN_GROUP $BIRD_ARGS
+Restart=on-abort
+
+[Install]
+WantedBy=multi-user.target
diff --git a/distro/pkg/deb/bird2.docs b/distro/pkg/deb/bird2.docs
new file mode 100644 (file)
index 0000000..50bd824
--- /dev/null
@@ -0,0 +1,2 @@
+NEWS
+README
diff --git a/distro/pkg/deb/bird2.install b/distro/pkg/deb/bird2.install
new file mode 100644 (file)
index 0000000..d0fad47
--- /dev/null
@@ -0,0 +1,6 @@
+etc/bird/bird.conf /usr/share/bird2/
+debian/envvars /etc/bird/
+debian/prepare-environment /usr/lib/bird/
+usr/sbin/bird
+usr/sbin/birdc
+usr/sbin/birdcl
diff --git a/distro/pkg/deb/bird2.lintian-overrides b/distro/pkg/deb/bird2.lintian-overrides
new file mode 100644 (file)
index 0000000..e64c0ef
--- /dev/null
@@ -0,0 +1 @@
+bird2: binary-without-manpage usr/sbin/birdcl
diff --git a/distro/pkg/deb/bird2.manpages b/distro/pkg/deb/bird2.manpages
new file mode 100644 (file)
index 0000000..94898ea
--- /dev/null
@@ -0,0 +1,2 @@
+bird.8
+birdc.8
diff --git a/distro/pkg/deb/bird2.postinst b/distro/pkg/deb/bird2.postinst
new file mode 100644 (file)
index 0000000..8f85b15
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+set -e
+
+if [ "$1" = "configure" ]; then
+
+    if ! getent passwd bird > /dev/null; then
+       adduser --quiet --system --group --no-create-home --home /run/bird bird
+    fi
+
+    dpkg-statoverride --list /etc/bird > /dev/null || dpkg-statoverride --update --add bird bird 0750 /etc/bird
+
+    ucf /usr/share/bird2/bird.conf /etc/bird/bird.conf
+    ucfr -f bird2 /etc/bird/bird.conf
+    dpkg-statoverride --list /etc/bird/bird.conf > /dev/null || dpkg-statoverride --update --add bird bird 0640 /etc/bird/bird.conf
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/distro/pkg/deb/bird2.postrm b/distro/pkg/deb/bird2.postrm
new file mode 100644 (file)
index 0000000..ab03e6e
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+set -e
+
+if test "$1" = "purge"; then
+
+    # Check if there is no collision of ownership of /etc/bird/bird.conf
+    if ! command -v ucf ucfr >/dev/null || ucfr bird2 /etc/bird/bird.conf 2>/dev/null; then
+       dpkg-statoverride --remove /etc/bird >/dev/null 2>/dev/null || true
+       dpkg-statoverride --remove /etc/bird/bird.conf >/dev/null 2>/dev/null || true
+
+       for ext in '~' '%' .bak .ucf-new .ucf-old .ucf-dist;  do
+           rm -f /etc/bird/bird.conf$ext
+       done
+       rm -f /etc/bird/bird.conf
+       if command -v ucf ucfr >/dev/null; then
+           ucf --purge /etc/bird/bird.conf
+           ucfr --purge bird2 /etc/bird/bird.conf
+       fi
+
+       deluser --quiet bird > /dev/null || true
+    fi
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/distro/pkg/deb/changelog b/distro/pkg/deb/changelog
new file mode 100644 (file)
index 0000000..d371bc0
--- /dev/null
@@ -0,0 +1,5 @@
+bird2 ({{ version }}-cznic.{{ release }}) unstable; urgency=medium
+
+  * upstream package
+
+ -- Jakub Ružička <jakub.ruzicka@nic.cz>  Mon, 29 Mar 2021 14:15:50 +0000
diff --git a/distro/pkg/deb/compat b/distro/pkg/deb/compat
new file mode 100644 (file)
index 0000000..ec63514
--- /dev/null
@@ -0,0 +1 @@
+9
diff --git a/distro/pkg/deb/control b/distro/pkg/deb/control
new file mode 100644 (file)
index 0000000..4935c69
--- /dev/null
@@ -0,0 +1,55 @@
+Source: bird2
+Section: net
+Priority: optional
+Build-Depends: bison,
+               debhelper,
+               docbook-xsl,
+               flex,
+               libncurses5-dev,
+               libreadline-dev | libreadline6-dev | libreadline5-dev,
+               libssh-gcrypt-dev,
+               linuxdoc-tools-latex,
+               m4,
+               opensp,
+               quilt,
+               texlive-latex-extra,
+               xsltproc
+Maintainer: Jakub Ružička <jakub.ruzicka@nic.cz>
+Uploaders: Ondřej Surý <ondrej@debian.org>
+Standards-Version: 4.3.0
+Vcs-Browser: https://salsa.debian.org/debian/bird2
+Vcs-Git: https://salsa.debian.org/debian/bird2.git
+Homepage: https://bird.network.cz/
+
+Package: bird2
+Architecture: kfreebsd-any linux-any
+Pre-Depends: init-system-helpers (>= 1.56~),
+             ${misc:Pre-Depends}
+Depends: adduser,
+         lsb-base,
+         ucf,
+         ${misc:Depends},
+         ${shlibs:Depends}
+Conflicts: bird
+Suggests: bird2-doc
+Description: Internet Routing Daemon
+ BIRD is an Internet routing daemon with full support for all the major
+ routing protocols. It allows redistribution between protocols with a
+ powerful route filtering syntax and an easy-to-use configuration
+ interface.
+ .
+ BIRD supports IPv4 and IPv6 versions of OSPF, RIP, BGP and Babel routing
+ protocols. It also supports supplementary protocols like BFD, RPKI-Router
+ and IPv6 router advertisements.
+
+Package: bird2-doc
+Architecture: all
+Section: doc
+Depends: ${misc:Depends}
+Description: Internet Routing Daemon - documentation
+ BIRD is an Internet routing daemon with full support for all the major
+ routing protocols. It allows redistribution between protocols with a
+ powerful route filtering syntax and an easy-to-use configuration
+ interface.
+ .
+ This package provides the user and developer documentation.
diff --git a/distro/pkg/deb/copyright b/distro/pkg/deb/copyright
new file mode 100644 (file)
index 0000000..7d3c391
--- /dev/null
@@ -0,0 +1,99 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: bird
+Upstream-Contact: bird-users@network.cz
+Source: https://bird.network.cz
+
+Files: *
+Copyright: 1998-2008 Martin Mareš
+          1998-2019 Ondřej Filip
+          1998-2000 Pavel Machek
+          2008-2019 Ondřej Zajíček
+          2015-2019 Maria Matějka
+License: GPL-2+
+
+Files: lib/heap.h
+Copyright: 2001 Martin Mareš <mj@ucw.cz>
+          2005 Tomáš Valla <tom@ucw.cz>
+License: LGPL-2+
+
+Files: lib/md5.c
+Copyright: 1993 Colin Plumb
+License: public-domain
+
+Files: lib/printf.c
+Copyright: 1991-1992 Lars Wirzenius
+          1991-1992 Linus Torvalds
+          1998-2000 Martin Mareš
+License: GPL-2
+
+Files: lib/sha*
+Copyright: 1998-2009 Free Software Foundation, Inc.
+          2015-2016 Pavel Tvrdík
+          2015-2016 Ondřej Zajíček
+License: GPL-2+
+
+Files: proto/babel/*
+Copyright: 2015-2016 Toke Høiland-Jørgensen
+          2016-2018 Ondřej Zajíček
+License: GPL-2+
+
+Files: proto/rpki/*
+Copyright: 2015-2016 Pavel Tvrdík
+          2016-2018 Ondřej Zajíček
+License: GPL-2+
+
+Files: debian/*
+Copyright: 2010-2013 Ondřej Surý <ondrej@debian.org>
+License: GPL-2+
+
+License: GPL-2+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+  .
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  .
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+  .
+  On Debian systems, the complete text of the GNU General Public License
+  version 2 can be found in `/usr/share/common-licenses/GPL-2'.
+
+License: GPL-2
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ .
+ On Debian systems, the complete text of the GNU General Public License
+ version 2 can be found in `/usr/share/common-licenses/GPL-2'.
+
+License: LGPL-2+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+ .
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Library General Public License for more details.
+ .
+ On Debian systems, the complete text of the GNU Lesser General Public
+ License version 2 can be found in `/usr/share/common-licenses/LGPL-2'.
+
+License: public-domain
+  This code is in the public domain; do with it what you wish.
diff --git a/distro/pkg/deb/envvars b/distro/pkg/deb/envvars
new file mode 100644 (file)
index 0000000..9ca9baa
--- /dev/null
@@ -0,0 +1,3 @@
+BIRD_RUN_USER=bird
+BIRD_RUN_GROUP=bird
+#BIRD_ARGS=
diff --git a/distro/pkg/deb/gbp.conf b/distro/pkg/deb/gbp.conf
new file mode 100644 (file)
index 0000000..f04b9f6
--- /dev/null
@@ -0,0 +1,9 @@
+[DEFAULT]
+debian-branch = master
+debian-tag = debian/%(version)s
+upstream-branch = upstream
+upstream-tag = upstream/%(version)s
+pristine-tar = True
+
+[dch]
+meta = 1
diff --git a/distro/pkg/deb/patches/0001-Sync-the-linuxdoc-mangled-files-with-linuxdoc-tools_.patch b/distro/pkg/deb/patches/0001-Sync-the-linuxdoc-mangled-files-with-linuxdoc-tools_.patch
new file mode 100644 (file)
index 0000000..9ac9681
--- /dev/null
@@ -0,0 +1,1394 @@
+From: =?utf-8?b?T25kxZllaiBTdXLDvQ==?= <ondrej@debian.org>
+Date: Mon, 11 May 2020 10:27:06 +0200
+Subject: Sync the linuxdoc mangled files with linuxdoc-tools_0.9.73-2
+
+---
+ doc/LinuxDocTools.pm | 903 ++++++++++++++++++++++++++-------------------------
+ doc/sgml2html        |  77 +++--
+ doc/sgml2latex       |  77 +++--
+ doc/sgml2txt         |  77 +++--
+ 4 files changed, 611 insertions(+), 523 deletions(-)
+
+diff --git a/doc/LinuxDocTools.pm b/doc/LinuxDocTools.pm
+index d32f317..c035f62 100644
+--- a/doc/LinuxDocTools.pm
++++ b/doc/LinuxDocTools.pm
+@@ -1,21 +1,19 @@
+-#! /usr/bin/perl 
++#! /usr/bin/perl
+ #
+ #  LinuxDocTools.pm
+ #
+-#  $Id$
+-#
+-#  LinuxDoc-Tools driver core. This contains all the basic functionality
+-#  we need to control all other components.
+-#
+-#  © Copyright 1996, Cees de Groot.
+-#  © Copyright 2000, Taketoshi Sano
+-#
+-#  THIS VERSION HAS BEEN HACKED FOR BIRD BY MARTIN MARES
++#  LinuxDoc-Tools driver core. This contains all the basic
++#  functionality we need to control all other components.
+ #
++#  Copyright © 1996, Cees de Groot.
++#  Copyright © 2000, Taketoshi Sano
++#  Copyright © 2006-2020, Agustin Martin
++# -------------------------------------------------------------------
+ package LinuxDocTools;
+-require 5.004;
++require 5.006;
+ use strict;
++use LinuxDocTools::Data::Latin1ToSgml qw{ldt_latin1tosgml};
+ =head1 NAME
+@@ -33,8 +31,8 @@ LinuxDocTools - SGML conversion utilities for LinuxDoc DTD.
+ =head1 DESCRIPTION
+ The LinuxDocTools package encapsulates all the functionality offered by
+-LinuxDoc-Tools. It is used, of course, by LinuxDoc-Tools; 
+-but the encapsulation should provide for a simple interface for other users as well. 
++LinuxDoc-Tools. It is used, of course, by LinuxDoc-Tools;
++but the encapsulation should provide for a simple interface for other users as well.
+ =head1 FUNCTIONS
+@@ -42,21 +40,24 @@ but the encapsulation should provide for a simple interface for other users as w
+ =cut
+-use DirHandle;
+-use File::Basename;
+-use File::Find;
+ use File::Copy;
+-use FileHandle;
+-use IPC::Open2;
+-use Cwd;
++use File::Temp qw(tempdir);
++use File::Basename qw(fileparse);
+ use LinuxDocTools::Lang;
+-use LinuxDocTools::Utils qw(process_options usage cleanup trap_signals remove_tmpfiles create_temp);
++use LinuxDocTools::Utils qw(
++  cleanup
++  create_temp
++  ldt_log
++  remove_tmpfiles
++  trap_signals
++  usage
++  );
+ use LinuxDocTools::Vars;
+ sub BEGIN
+ {
+   #
+-  #  Make sure we're always looking here. Note that "use lib" adds 
++  #  Make sure we're always looking here. Note that "use lib" adds
+   #  on the front of the search path, so we first push dist, then
+   #  site, so that site is searched first.
+   #
+@@ -64,54 +65,127 @@ sub BEGIN
+   use lib "$main::DataDir/site";
+ }
++# -------------------------------------------------------------------
++sub ldt_searchfile {
++  # -----------------------------------------------------------------
++  # Look for a readable file in the locations. Return first math.
++  # -----------------------------------------------------------------
++  my $files = shift;
++  foreach my $file  ( @$files ){
++    return $file if -r $file;
++  }
++}
++
++# -------------------------------------------------------------------
++sub ldt_getdtd_v1 {
++  # -----------------------------------------------------------------
++  # Get the dtd
++  # -----------------------------------------------------------------
++  my $file         = shift;
++  my $error_header = "LinuxdocTools::ldt_getdtd_v1";
++  my $dtd;
++
++  open ( my $FILE, "< $file")
++    or die "$error_header: Could not open \"$file\" for reading. Aborting ...\n";
++
++  while ( <$FILE> ) {
++    tr/A-Z/a-z/;
++    # check for [<!doctype ... system] type definition
++    if ( /<!doctype\s*(\w*)\s*system/ ) {
++      $dtd = $1;
++      last;
++      # check for <!doctype ... PUBLIC ... DTD ...
++    } elsif ( /<!doctype\s*\w*\s*public\s*.*\/\/dtd\s*(\w*)/mi ) {
++      $dtd = $1;
++      last;
++      # check for <!doctype ...
++      #          PUBLIC  ... DTD ...
++      # (multi-line version)
++    } elsif ( /<!doctype\s*(\w*)/ ) {
++      $dtd = "precheck";
++      next;
++    } elsif ( /\s*public\s*.*\/\/dtd\s*(\w*)/ && $dtd eq "precheck" ) {
++      $dtd = $1;
++      last;
++    }
++  }
++  close $FILE;
++
++  return $dtd;
++}
++
++# -------------------------------------------------------------------
++sub ldt_getdtd_v2 {
++  # -----------------------------------------------------------------
++  # Second way of getting dtd, fron nsgmls output.
++  # -----------------------------------------------------------------
++  my $preaspout    = shift;
++  my $error_header = "LinuxdocTools::ldt_getdtd_v2";
++  my $dtd2;
++
++  open (my $TMP,"< $preaspout")
++    or die "%error_header: Could not open $preaspout for reading. Aborting ...\n";
++  while ( defined ($dtd2 = <$TMP>) && ! ( $dtd2 =~ /^\(/) ) { };
++  close $TMP;
++  $dtd2 =~ s/^\(//;
++  $dtd2 =~ tr/A-Z/a-z/;
++  chomp $dtd2;
++  return $dtd2;
++}
++
++# -------------------------------------------------------------------
++
+ =item LinuxDocTools::init
+ Takes care of initialization of package-global variables (which are actually
+ defined in L<LinuxDocTools::Vars>). The package-global variables are I<$global>,
+ a reference to a hash containing numerous settings, I<%Formats>, a hash
+ containing all the formats, and I<%FmtList>, a hash containing the currently
+-active formats for help texts. 
++active formats for help texts.
+ Apart from this, C<LinuxDocTools::init> also finds all distributed and site-local
+ formatting backends and C<require>s them.
+ =cut
+-sub init
+-{
++# -------------------------------------------------------------------
++sub init {
++# -------------------------------------------------------------------
+   trap_signals;
+-  #
+-  #  Register the ``global'' pseudoformat. Apart from the global settings,
+-  #  we also use $global to keep the global variable name space clean; 
+-  #  everything that we need to provide to other modules is stuffed
+-  #  into $global.
+-  #
+-  $global = {};
+-  $global->{NAME} = "global";
+-  $global->{HELP} = "";
+-  $global->{OPTIONS} = [
+-    { option => "backend", type => "l",
+-      'values' => [ "html", "info", "latex", 
+-                      "lyx", "rtf", "txt", "check" ],
+-       short => "B" },
+-    { option => "papersize", type => "l",
+-      'values' => [ "a4", "letter" ], short => "p" },
+-    { option => "language",  type => "l",
+-      'values' => [ @LinuxDocTools::Lang::Languages ], short => "l" },
+-    { option => "charset",   type => "l",
+-      'values' => [ "latin", "ascii", "nippon", "euc-kr" ], short => "c" },
+-    { option => "style",     type => "s", short => "S" },
+-    { option => "tabsize",   type => "i", short => "t" },
+-#    { option => "verbose",   type => "f", short => "v" },
+-    { option => "debug",     type => "f", short => "d" },
+-    { option => "define",    type => "s", short => "D" },
+-    { option => "include",   type => "s", short => "i" },
+-    { option => "pass",      type => "s", short => "P" }
+-  ];
++  # Register the ``global'' pseudoformat. Apart from the global settings, we
++  # also use $global to keep the global variable name space clean everything
++  # that we need to provide to other modules is stuffed into $global.
++  $global              = {};
++  $global->{NAME}      = "global";
++  $global->{HELP}      = "";
++  $global->{OPTIONS}   = [
++                        { option => "backend",
++                          type => "l",
++                          'values' => [ "html", "info", "latex", "lyx", "rtf", "txt", "check" ],
++                          short => "B" },
++                        { option => "papersize",
++                          type => "l",
++                          'values' => [ "a4", "letter" ],
++                          short => "p" },
++                        { option => "language",
++                          type => "l",
++                          'values' => [ @LinuxDocTools::Lang::Languages ],
++                          short => "l" },
++                        { option => "charset",   type => "l",
++                          'values' => [ "latin", "ascii", "nippon", "euc-kr" , "utf-8"],
++                          short => "c" },
++                        { option => "style",     type => "s", short => "S" },
++                        { option => "tabsize",   type => "i", short => "t" },
++                        # { option => "verbose",   type => "f", short => "v" },
++                        { option => "debug",     type => "f", short => "d" },
++                        { option => "define",    type => "s", short => "D" },
++                        { option => "include",   type => "s", short => "i" },
++                        { option => "pass",      type => "s", short => "P" }
++                        ];
+   $global->{backend}   = "linuxdoc";
+   $global->{papersize} = "a4";
+-  $global->{language}  = "en";
++  $global->{language}  = '';
+   $global->{charset}   = "ascii";
+   $global->{style}     = "";
+   $global->{tabsize}   = 8;
+@@ -119,11 +193,24 @@ sub init
+   $global->{define}    = "";
+   $global->{debug}     = 0;
+   $global->{include}   = "";
++  $global->{logfile}   = '';
+   $global->{pass}      = "";
+   $global->{InFiles}   = [];
++  $global->{fmtlist}   = "";            # List of loaded fmt files
+   $Formats{$global->{NAME}} = $global;        # All formats we know.
+   $FmtList{$global->{NAME}} = $global;  # List of formats for help msgs.
++  $global->{sgmlpre}   = "$main::AuxBinDir/sgmlpre";
++  my $error_header     = "LinuxdocTools::init";
++
++  if ( -e "/etc/papersize" ){
++    open (my $PAPERSIZE,"< /etc/papersize") ||
++      die "$error_header: Count not open \"/etc/papersize\" for reading\n";
++    chomp (my $paper = <$PAPERSIZE>);
++    $global->{papersize} = "letter" if ( $paper eq "letter");
++    close $PAPERSIZE;
++  }
++
+   # automatic language detection: disabled by default
+   # {
+   #    my $lang;
+@@ -137,42 +224,39 @@ sub init
+   #     }
+   # }
+-  #
+-  #  Used when the format is "global" (from sgmlcheck).
+-  #
++  # -------------------------------------------------------------------
+   $global->{preNSGMLS} = sub {
+-    $global->{NsgmlsOpts} .= " -s ";
++    # -----------------------------------------------------------------
++    #  Define a fallback preNSGMLS. Used when the format is "global"
++    #  (from sgmlcheck).
++    # -----------------------------------------------------------------
++    $global->{NsgmlsOpts}   .= " -s ";
+     $global->{NsgmlsPrePipe} = "cat $global->{file}";
+   };
+-  #
+-  #  Build up the list of formatters.
+-  #
+-  my $savdir = cwd;
+-  my %Locs;
+-  chdir "$main::DataDir/dist";
+-  my $dir = new DirHandle(".");
+-  die "Unable to read directory $main::DataDir/dist: $!" unless defined($dir);
+-  foreach my $fmt (grep(/^fmt_.*\.pl$/, $dir->read()))
+-  {
+-    $Locs{$fmt} = "dist";
+-  }
+-  $dir->close();
+-  chdir "$main::DataDir/site";
+-  $dir = new DirHandle(".");
+-  die "Unable to read directory $main::DataDir/site: $!" unless defined($dir);
+-  foreach my $fmt (grep(/^fmt_.*\.pl$/, $dir->read()))
+-  {
+-    $Locs{$fmt} = "site";
++  # We need to load all fmt files here, so the allowed options for all
++  # format are put into $global and a complete usage message is built,
++  # including options for all formats.
++  my %locations = ();
++  foreach my $path ("$main::DataDir/site",
++                  "$main::DataDir/dist",
++                  "$main::DataDir/fmt"){
++    foreach my $location (<$path/fmt_*.pl>){
++      my $fmt =  $location;
++      $fmt    =~ s/^.*_//;
++      $fmt    =~ s/\.pl$//;
++      $locations{$fmt} = $location unless defined $locations{$fmt};
++    }
+   }
+-  $dir->close();
+-  foreach my $fmt (keys %Locs)
+-  {
+-    require $fmt;
++
++  foreach my $fmt ( keys %locations ){
++    $global->{fmtlist}   .= "  Loading $locations{$fmt}\n";
++    require $locations{$fmt};
+   }
+-  chdir $savdir;
+ }
++# ------------------------------------------------------------------------
++
+ =item LinuxDocTools::process_options ($0, @ARGV)
+ This function contains all initialization that is bound to the current
+@@ -181,91 +265,113 @@ should be used (ld2txt activates the I<txt> backend) and parses the
+ options array. It returns an array of filenames it encountered during
+ option processing.
+-As a side effect, the environment variables I<SGMLDECL> and 
+-I<SGML_CATALOG_FILES> are modified.
++As a side effect, the environment variable I<SGML_CATALOG_FILES> is
++modified and, once I<$global->{format}> is known, I<SGMLDECL> is set.
+ =cut
+-sub process_options
+-{
+-  my $progname = shift;
+-  my @args = @_;
++# -------------------------------------------------------------------
++sub process_options {
++  # -----------------------------------------------------------------
++  my $progname  = shift;
++  my @tmpargs   = @_;
++  my @args      = ();
++  my $format    = '';
++  my $msgheader = "LinuxDocTools::process_options";
++
++  # Try getting the format. We need to do this here so process_options
++  # knows which is the format and which format options are allowed
++
++  # First, see if we have an explicit backend option by looping over command line.
++  # Do not shift in the while condition itself, 0 in options like '-s 0' will
++  # otherwise stop looping
++  while ( @tmpargs ){
++    $_ = shift @tmpargs;
++    if ( s/--backend=// ){
++      $format = $_;
++    } elsif ( $_ eq "-B" ){
++      $format = shift @tmpargs;
++    } else {
++      push @args, $_;
++    }
++  }
+-  #
+-  #  Deduce the format from the caller's file name
+-  #
+-  my ($format, $dummy1, $dummy2) = fileparse ($progname, "");
+-  $global->{myname} = $format;
+-  $format =~ s/sgml2*(.*)/$1/;
++  unless ( $format ){
++    my ($tmpfmt, $dummy1, $dummy2) = fileparse($progname, "");
++    if ( $tmpfmt =~ s/^sgml2// ) {       # Calling program through sgml2xx symlinks
++      $format = $tmpfmt;
++    } elsif ( $tmpfmt eq "sgmlcheck" ) { # Calling program through sgmlcheck symlink
++      $format = "global";
++    }
++  }
+-  #
+-  # check the option "--backend / -B"
+-  #
+-  if ($format eq "linuxdoc") {
+-      my @backends = @args;
+-      my $arg;
+-      while (@backends) {
+-         $arg = shift @backends;
+-         if ($arg eq "-B") {
+-                $arg = shift @backends;
+-                $format = $arg;
+-                last;
+-       }
+-         if ( $arg =~ s/--backend=(.*)/$1/ ) {
+-                $format = $arg;
+-                last;
+-         }
++  if ( $format ) {
++    if ( $format eq "check" ){
++      $format = "global";
++    } elsif ( $format eq "latex" ){
++      $format = "latex2e";
++    }
++    $FmtList{$format} = $Formats{$format} or
++      usage("$format: Unknown format");
++    $global->{format} = $format;
++  } else {
++    usage("");
++  }
++
++  # Parse all the options from @args, and return files.
++  my @files    = LinuxDocTools::Utils::process_options(@args);
++
++  # Check the number of given files
++  $#files > -1 || usage("No filenames given");
++
++  # Normalize language string
++  $global->{language} = Any2ISO($global->{language})
++    if ( defined $global->{language} );
++
++  # Fine tune japanese and korean charsets when not utf-8
++  if ($global->{charset} ne "utf-8") {
++    if ($global->{language} eq "ja" ){
++      $global->{charset} = "nippon";
++    } elsif ($global->{language} eq "ko"){
++      if ($global->{format} eq "groff") {
++      $global->{charset} = "latin1";
++      } else {
++      $global->{charset} = "euc-kr";
+       }
++    }
+   }
+-  $format = "global" if $format eq "check";
+-  usage ("") if $format eq "linuxdoc";
+-  $format = "latex2e" if $format eq "latex";
+-  $FmtList{$format} = $Formats{$format} or 
+-     usage ("$global->{myname}: unknown format");
+-  $global->{format} = $format;
++  # Setup the SGML environment.
++  my @sgmlcatalogs =
++    (# SGML iso-entities catalog location in Debian sgml-data package
++     "$main::isoentities_prefix/share/sgml/entities/sgml-iso-entities-8879.1986/catalog",
++     # SGML iso-entities catalog location in ArchLinux, Fedora and Gentoo
++     "$main::isoentities_prefix/share/sgml/sgml-iso-entities-8879.1986/catalog",
++     # SGML iso-entities catalog location when installed from linuxdoc-tools
++     "$main::isoentities_prefix/share/sgml/iso-entities-8879.1986/iso-entities.cat",
++     # dtd/catalog for SGML-Tools
++     "$main::DataDir/linuxdoc-tools.catalog",
++     # The super catalog
++     "/etc/sgml/catalog");
+-  #
+-  #  Parse all the options.
+-  #
+-  my @files = LinuxDocTools::Utils::process_options (@args);
+-  $global->{language} = Any2ISO ($global->{language});
+-  #
+-  # check the number of given files 
+-  $#files > -1 || usage ("no filenames given");
++  @sgmlcatalogs = ($ENV{SGML_CATALOG_FILES}, @sgmlcatalogs) if defined $ENV{SGML_CATALOG_FILES};
+-  #
+-  #  Setup the SGML environment.
+-  #  (Note that Debian package rewrite path to catalog of
+-  #   iso-entities using debian/rules so that it can use 
+-  #   entities from sgml-data pacakge.  debian/rules also
+-  #   removes iso-entites sub directory after doing make install.)
+-  #
+-  $ENV{SGML_CATALOG_FILES} .= (defined $ENV{SGML_CATALOG_FILES} ? ":" : "") .
+-     "$main::prefix/share/sgml/sgml-iso-entities-8879.1986/catalog:" .
+-     "$main::prefix/share/sgml/entities/sgml-iso-entities-8879.1986/catalog";
+-  $ENV{SGML_CATALOG_FILES} .= ":$main::DataDir/linuxdoc-tools.catalog";
+-  $ENV{SGML_CATALOG_FILES} .= ":$main::/etc/sgml.catalog";
+-  if (-f "$main::DataDir/dtd/$format.dcl")
+-    {
+-      $ENV{SGMLDECL} = "$main::DataDir/dtd/$format.dcl";
+-    }
+-  elsif (-f "$main::DataDir/dtd/$global->{style}.dcl")
+-    {
+-      $ENV{SGMLDECL} = "$main::DataDir/dtd/$global->{style}.dcl";
+-    }
+-  elsif (-f "$main::DataDir/dtd/sgml.dcl")
+-    {
+-      $ENV{SGMLDECL} = "$main::DataDir/dtd/sgml.dcl";
+-    }
++  $ENV{SGML_CATALOG_FILES} = join(':', @sgmlcatalogs);
+-  #
+-  #  OK. Give the list of files we distilled from the options
+-  #  back to the caller.
+-  #
++  # Set to one of these if readable, nil otherwise
++  $ENV{SGMLDECL} = ldt_searchfile(["$main::DataDir/dtd/$global->{format}.dcl",
++                                 "$main::DataDir/dtd/$global->{style}.dcl",
++                                 "$main::DataDir/dtd/sgml.dcl"]);
++
++  # Show the list of loaded fmt_*.pl files if debugging
++  print STDERR $global->{fmtlist} if $global->{debug};
++
++  # Return the list of files to be processed
+   return @files;
+ }
++# -------------------------------------------------------------------
++
+ =item LinuxDocTools::process_file
+ With all the configuration done, this routine will take a single filename
+@@ -294,330 +400,243 @@ etcetera. See the code for details.
+ =cut
+-sub process_file
+-{
+-  my $file = shift (@_);
+-  my $saved_umask = umask;
++# -------------------------------------------------------------------
++sub process_file {
++  # ----------------------------------------------------------------
++  my $file            = $global->{origfile} = shift (@_);
++  my $saved_umask     = umask;
++  my $error_header    = "LinuxdocTools::process_file";
++  my $fmtopts         = $Formats{$global->{format}};
+   print "Processing file $file\n";
+   umask 0077;
+-  my ($filename, $filepath, $filesuffix) = fileparse ($file, "\.sgml");
+-  my $tmpnam = $filepath . '/' . $filename;
+-  $file = $tmpnam . $filesuffix;
+-  -f $file || $file =~ /.*.sgml$/ || ($file .= '.sgml');
+-  -f $file || ($file = $tmpnam . '.SGML');
+-  -f $file || die "Cannot find $file\n";
++  my ($filename, $filepath, $filesuffix) = fileparse($file, "\.sgml");
+   $global->{filename} = $filename;
+-  $global->{file} = $file;
+   $global->{filepath} = $filepath;
++  $global->{file}     = ldt_searchfile(["$filepath/$filename.sgml",
++                                      "$filepath/$filename.SGML"])
++    or die "$error_header: Cannot find $file. Aborting ...\n";
++
++  my $dtd = ldt_getdtd_v1("$global->{file}");
++  print STDERR "DTD: " . $dtd . "\n" if $global->{debug};
++
++  # -- Prepare temporary directory
++  my $tmpdir    = $ENV{'TMPDIR'} || '/tmp';
++  $tmpdir       = tempdir("linuxdoc-tools.XXXXXXXXXX", DIR => "$tmpdir");
++
++  # -- Set common base name for temp files and temp file names
++  my $tmpbase   = $global->{tmpbase} = $tmpdir . '/sgmltmp.' . $filename;
++  my $precmdout = "$tmpbase.01.precmdout";
++  my $nsgmlsout = "$tmpbase.02.nsgmlsout";   # Was $tmpbase.1
++  my $preaspout = "$tmpbase.03.preaspout";   # Was $tmpbase.2
++  my $aspout    = "$tmpbase.04.aspout";      # Was $tmpbase.3
++
++  # -- Set $global->{logfile} and initialize logfile.
++  $global->{logfile} = "$tmpbase.$global->{format}.log";
++  open (my $LOGFILE, ">", "$global->{logfile}")
++    or die "$error_header: Could not open \"$global->{logfile}\" logfile for write.\n";
++  print $LOGFILE "--- Opening \"$global->{logfile}\" logfile ---\n";
++  close $LOGFILE;
++
++  # -- Write info about some global options
++  ldt_log "--- Begin: Info about global options";
++  foreach ( sort keys %$global ){
++    next if m/fmtlist|InFiles|OPTIONS/;
++    ldt_log "$_:  $global->{$_}";
++  }
++  ldt_log "--- End: Info about global options";
++  ldt_log "$global->{fmtlist}";
++
++  # -- Write info about some backend options
++  ldt_log "--- Begin: Info about backend options";
++  foreach ( sort keys %$fmtopts ){
++    next if m/fmtlist|InFiles|OPTIONS/;
++    ldt_log "$_:  $fmtopts->{$_}";
++  }
++  ldt_log "--- End: Info about backend options";
+-  my $tmp = new FileHandle "<$file";
+-  my $dtd;
+-  while ( <$tmp> )
+-    {
+-      tr/A-Z/a-z/;
+-      # check for [<!doctype ... system] type definition
+-      if ( /<!doctype\s*(\w*)\s*system/ )
+-        {
+-          $dtd = $1;
+-          last;
+-        }
+-      # check for <!doctype ... PUBLIC ... DTD ...
+-      if ( /<!doctype\s*\w*\s*public\s*.*\/\/dtd\s*(\w*)/mi )
+-        {
+-          $dtd = $1;
+-          last;
+-        }
+-      # check for <!doctype ...
+-      #          PUBLIC  ... DTD ...
+-      # (multi-line version)
+-      if ( /<!doctype\s*(\w*)/ )
+-        {
+-          $dtd = "precheck";
+-          next;
+-        }
+-      if ( /\s*public\s*.*\/\/dtd\s*(\w*)/ && $dtd eq "precheck" )
+-        {
+-          $dtd = $1;
+-          last;
+-        }
+-    }
+-  $tmp->close;
+-  if ( $global->{debug} )
+-    {
+-      print "DTD: " . $dtd . "\n";
++  # Set up the preprocessing command. Conditionals have to be
++  # handled here until they can be moved into the DTD, otherwise
++  # a validating SGML parser will choke on them.
++
++  # -- Check if output option for latex is pdf or not
++  if ($global->{format} eq "latex2e") {
++    if ($Formats{$global->{format}}{output} eq "pdf") {
++      $global->{define} .= " pdflatex=yes";
+     }
+-  $global->{dtd} = $dtd;
++  }
+-  # prepare temporary directory
+-  my $tmpdir = $ENV{'TMPDIR'} || '/tmp';
+-  $tmpdir = $tmpdir . '/' . 'linuxdoc-dir-' . $$;
+-  mkdir ($tmpdir, 0700) ||
+-   die " - temporary files can not be created, aborted - \n";
++  # -- Set the actual pre-processing command
++  my($precmd) = "| $global->{sgmlpre} output=$global->{format} $global->{define}";
++  ldt_log "  ${error_header}::precmd:\n    $precmd";
+-  my $tmpbase = $global->{tmpbase} = $tmpdir . '/sgmltmp.' . $filename;
++  # -- Make sure path of file to be processed is in SGML_SEARCH_PATH
+   $ENV{"SGML_SEARCH_PATH"} .= ":$filepath";
+-  #
+-  # Set up the preprocessing command.  Conditionals have to be
+-  # handled here until they can be moved into the DTD, otherwise
+-  # a validating SGML parser will choke on them.
+-  #
+-  # check if output option for latex is pdf or not
+-  if ($global->{format} eq "latex2e")
+-    {
+-      if ($Formats{$global->{format}}{output} eq "pdf")
+-        {
+-          $global->{define} .= " pdflatex=yes";
+-        }
+-    }
+-  #
++  # -- You can hack $NsgmlsOpts here, etcetera.
++  $global->{NsgmlsOpts}   .= "-D $main::prefix/share/sgml -D $main::DataDir";
++  $global->{NsgmlsOpts}   .= "-i$global->{include}" if ($global->{include});
++
++  # If a preNSGMLS function is defined in the fmt file, pipe its output to $FILE,
++  # otherwise just open $global->{file} as $IFILE
++  # -----------------------------------------------------------------
++  ldt_log "- PreNsgmls stage started.";
++  my $IFILE;
++  if ( defined $Formats{$global->{format}}{preNSGMLS} ) {
++    $global->{NsgmlsPrePipe} = &{$Formats{$global->{format}}{preNSGMLS}};
++    ldt_log  "  ${error_header}::NsgmlsPrePipe: $global->{NsgmlsPrePipe} |";
++    open ($IFILE,"$global->{NsgmlsPrePipe} |")
++      || die "$error_header: Could not open pipe from $global->{NsgmlsPrePipe}. Aborting ...\n";
++  } else {
++    ldt_log "  ${error_header}: No prepipe. Just opening \"$global->{file}\" for read";
++    open ($IFILE,"< $global->{file}")
++      || die "$error_header: Could not open $global->{file} for reading. Aborting ...\n";
++  }
+-  local $ENV{PATH} = "$ENV{PATH}:/usr/lib/linuxdoc-tools";
+-  my($precmd) = "|sgmlpre output=$global->{format} $global->{define}";
++  # -- Create a temp file with $precmd output
++  my $precmd_command    = "$precmd > $precmdout";
++  ldt_log "  ${error_header}::precmd_command:\n    $precmd_command";
+-  #
+-  #  You can hack $NsgmlsOpts here, etcetera.
+-  #
+-  $global->{NsgmlsOpts} .= "-D $main::prefix/share/sgml -D $main::DataDir";
+-  $global->{NsgmlsOpts} .= "-i$global->{include}" if ($global->{include});
+-  $global->{NsgmlsPrePipe} = "NOTHING";
+-  if ( defined $Formats{$global->{format}}{preNSGMLS} )
+-    {
+-      $global->{NsgmlsPrePipe} = &{$Formats{$global->{format}}{preNSGMLS}};
+-    }
++  open (my $PRECMDOUT, "$precmd_command")
++    or die "$error_header: Could not open pipe to $precmdout. Aborting ...\n";
+-  #
+-  #  Run the prepocessor and nsgmls.
+-  #
+-  my ($ifile, $writensgmls);
++  # -- Convert latin1 chars to sgml entities for html backend
++  if ( $global->{format} eq "html"
++       && $global->{charset} eq "latin"  ) {
++    ldt_log "  ${error_header}: Converting latin1 chars to sgml entities for html backend";
++    print $PRECMDOUT ldt_latin1tosgml($IFILE);
++  } else {
++    copy($IFILE,$PRECMDOUT);
++  }
+-  if ($global->{NsgmlsPrePipe} eq "NOTHING")
+-    {
+-      $ifile = new FileHandle $file;
+-    }
+-  else
+-    {
+-      $ifile = new FileHandle "$global->{NsgmlsPrePipe}|";
+-    }
++  close $IFILE;
++  close $PRECMDOUT;
++  ldt_log "- PreNsgmls stage finished.";
+-  create_temp("$tmpbase.1");
+-  $writensgmls = new FileHandle
+-      "$precmd|$main::progs->{NSGMLS} $global->{NsgmlsOpts} $ENV{SGMLDECL} >\"$tmpbase.1\"";
+-  if ($global->{charset} eq "latin")
+-    {
+-      while (<$ifile>) 
+-        {
+-        # Outline these commands later on - CdG
+-        #change latin1 characters to SGML
+-        #by Farzad Farid, adapted by Greg Hankins
+-        s/À/\&Agrave;/g;
+-        s/Á/\&Aacute;/g;
+-        s/Â/\&Acirc;/g;
+-        s/Ã/\&Atilde;/g;
+-        s/Ä/\&Auml;/g;
+-        s/Å/\&Aring;/g;
+-        s/Æ/\&AElig;/g;
+-        s/Ç/\&Ccedil;/g;
+-        s/È/\&Egrave;/g;
+-        s/É/\&Eacute;/g;
+-        s/Ê/\&Ecirc;/g;
+-        s/Ë/\&Euml;/g;
+-        s/Ì/\&Igrave;/g;
+-        s/Í/\&Iacute;/g;
+-        s/Î/\&Icirc;/g;
+-        s/Ï/\&Iuml;/g;
+-        s/Ñ/\&Ntilde;/g;
+-        s/Ò/\&Ograve;/g;
+-        s/Ó/\&Oacute;/g;
+-        s/Ô/\&Ocirc;/g;
+-        s/Õ/\&Otilde;/g;
+-        s/Ö/\&Ouml;/g;
+-        s/Ø/\&Oslash;/g;
+-        s/Ù/\&Ugrave;/g;
+-        s/Ú/\&Uacute;/g;
+-        s/Û/\&Ucirc;/g;
+-        s/Ü/\&Uuml;/g;
+-        s/Ý/\&Yacute;/g;
+-        s/Þ/\&THORN;/g;
+-        s/ß/\&szlig;/g;
+-        s/à/\&agrave;/g;
+-        s/á/\&aacute;/g;
+-        s/â/\&acirc;/g;
+-        s/ã/\&atilde;/g;
+-        s/ä/\&auml;/g;
+-        s/å/\&aring;/g;
+-        s/æ/\&aelig;/g;
+-        s/ç/\&ccedil;/g;
+-        s/è/\&egrave;/g;
+-        s/é/\&eacute;/g;
+-        s/ê/\&ecirc;/g;
+-        s/ë/\&euml;/g;
+-        s/ì/\&igrave;/g;
+-        s/í/\&iacute;/g;
+-        s/î/\&icirc;/g;
+-        s/ï/\&iuml;/g;
+-        s/µ/\&mu;/g;
+-        s/ð/\&eth;/g;
+-        s/ñ/\&ntilde;/g;
+-        s/ò/\&ograve;/g;
+-        s/ó/\&oacute;/g;
+-        s/ô/\&ocirc;/g;
+-        s/õ/\&otilde;/g;
+-        s/ö/\&ouml;/g;
+-        s/ø/\&oslash;/g;
+-        s/ù/\&ugrave;/g;
+-        s/ú/\&uacute;/g;
+-        s/û/\&ucirc;/g;
+-        s/ü/\&uuml;/g;
+-        s/ý/\&yacute;/g;
+-        s/þ/\&thorn;/g;
+-        s/ÿ/\&yuml;/g;
+-          print $writensgmls $_;
+-      }
+-    }
+-  else
+-    {
+-      while (<$ifile>)
+-        {
+-          print $writensgmls $_;
+-      }
+-    }
+-  $ifile->close;
+-  $writensgmls->close;
+-        
+-  #
+-  #  Special case: if format is global, we're just checking.
+-  #
+-  $global->{format} eq "global" && cleanup;
++  ldt_log "- Nsgmls stage started.";
+-  #
+-  #  If the output file is empty, something went wrong.
+-  #
+-  ! -e "$tmpbase.1" and die "can't create file - exiting";
+-  -z "$tmpbase.1" and die "SGML parsing error - exiting";
+-  if ( $global->{debug} )
+-    {
+-      print "Nsgmls stage finished.\n";
+-    }
++  # -- Pass apropriate envvars to nsgmls to better deal with utf-8
++  my $NSGMLS_envvars = ($global->{charset} eq "utf-8")
++    ? "SP_CHARSET_FIXED=yes SP_ENCODING=utf-8" : "";
++
++  # -- Process with nsgmls.
++  my $nsgmls_command = "$NSGMLS_envvars $main::progs->{NSGMLS} $global->{NsgmlsOpts} $ENV{SGMLDECL} $precmdout > $nsgmlsout";
++  ldt_log "  ${error_header}::nsgmls_command:\n    $nsgmls_command";
++  system($nsgmls_command) == 0
++    or die "${error_header}: Error: \"$nsgmls_command\" failed with exit status: ",$? >> 8,"\n";
++
++  #  -- Special case: if format is global, we're just checking.
++  cleanup if ( $global->{format} eq "global");
++
++  # -- If output file does not exists or is empty, something went wrong.
++  if ( ! -e "$nsgmlsout" ) {
++    die "$error_header: Can't create file $nsgmlsout. Aborting ...\n";
++  } elsif ( -z "$nsgmlsout" ){
++    die "$error_header: $nsgmlsout empty, SGML parsing error. Aborting ...\n";
++  }
++
++  print "- Nsgmls stage finished.\n" if $global->{debug};
++  ldt_log "- Nsgmls stage finished.";
+-  #
+   #  If a preASP stage is defined, let the format handle it.
+-  #  
+-  #  preASP ($inhandle, $outhandle);
+-  #
+-  my $inpreasp = new FileHandle "<$tmpbase.1";
+-  my $outpreasp = new FileHandle "$tmpbase.2",O_WRONLY|O_CREAT|O_EXCL,0600;
+-  if (defined $Formats{$global->{format}}{preASP})
+-    {
+-      &{$Formats{$global->{format}}{preASP}}($inpreasp, $outpreasp) == 0 or
+-       die "error pre-processing $global->{format}.\n";
+-    }  
+-  else
+-    {
+-      copy ($inpreasp, $outpreasp);
+-    }
+-  $inpreasp->close;
+-  $outpreasp->close;
+-  ! -e "$tmpbase.2" and die "can't create file - exiting";
++  #  --------------------------------------------------------
++  ldt_log "- PreASP stage started.";
++  open (my $PREASP_IN, "< $nsgmlsout")
++    or die "$error_header: Could not open $nsgmlsout for reading. Aborting ...\n";
++  open (my $PREASP_OUT, "> $preaspout")
++    or die "$error_header: Could not open $preaspout for writing. Aborting ...\n";
++
++  if (defined $Formats{$global->{format}}{preASP}) {
++    # Usage: preASP ($INHANDLE, $OUTHANDLE);
++    &{$Formats{$global->{format}}{preASP}}($PREASP_IN, $PREASP_OUT) == 0
++      or die "$error_header: Error pre-processing $global->{format}.\n";
++  } else {
++    copy ($PREASP_IN, $PREASP_OUT);
++  }
+-  if ( $global->{debug} )
+-    {
+-      print "PreASP stage finished.\n";
+-    }
++  close $PREASP_IN;
++  close $PREASP_OUT;
++
++  die "$error_header: Can't create $preaspout file. Aborting ...\n"
++    unless -e "$preaspout";
++
++  print "- PreASP stage finished.\n" if ( $global->{debug} );
++  ldt_log "- PreASP stage finished.";
++
++  # Run sgmlsasp, with an optional style if specified.
++  # -----------------------------------------------------------
++  ldt_log "- ASP stage started.";
++  my $dtd2 = ldt_getdtd_v2($preaspout)
++    or die "$error_header: Could not read dtd from $preaspout. Aborting ...\n";
++
++  ldt_log "  $error_header: dtd_v1: $dtd, dtd_v2: $dtd2, both must match, dtd_v2 prevails";
++  unless ( $dtd eq $dtd2 ){
++    print STDERR "Warning: Two different values for dtd, dtd1: $dtd, dtd2: $dtd2\n";
++    $dtd = $dtd2;
++  }
++
++  $global->{'dtd'} = $dtd;
+-  #
+-  #  Run sgmlsasp, with an optional style if specified.
+-  #
+   #  Search order:
+   #  - datadir/site/<dtd>/<format>
+   #  - datadir/dist/<dtd>/<format>
+-  #  So we need to fetch the doctype from the intermediate.
+-  #
+-  #  Note: this is a very simplistic check - but as far as I know,
+-  #  it is correct. Am I right?
+-  #
+-  my $tmp = new FileHandle "<$tmpbase.2";
+-  my $dtd;
+-  while ( ($dtd = <$tmp>) && ! ( $dtd =~ /^\(/) ) { };
+-  $tmp->close;
+-  $dtd =~ s/^\(//;
+-  $dtd =~ tr/A-Z/a-z/;
+-  chop $dtd;
+-  $global->{dtd} = $dtd;
+-
+-  my $style = "";
+-  if ($global->{style})
+-    {
+-      $style = "$main::DataDir/site/$dtd/$global->{format}/$global->{style}mapping";
+-      -r $style or
+-         $style = "$main::DataDir/dist/$dtd/$global->{format}/$global->{style}mapping";
+-    }
+-  my $mapping = "$main::DataDir/site/$dtd/$global->{format}/mapping";
+-  -r $mapping or $mapping = "$main::DataDir/dist/$dtd/$global->{format}/mapping";
+-  $global->{charset} = "nippon" if ($global->{language} eq "ja");
+-  #
+-  # we don't have Korean groff so charset should be latin1.
+-  #
+-  if ($global->{language} eq "ko")
+-    {
+-      if ($global->{format} eq "groff")
+-        {
+-          $global->{charset} = "latin1";
+-        }
+-      else
+-        {
+-          $global->{charset} = "euc-kr";
+-        }
+-    }
+-  
+-  if ($global->{format} eq "groff" or $global->{format} eq "latex2e")
+-    {
+-      if ($dtd eq "linuxdoctr")
+-        {
+-          $mapping = "$main::DataDir/dist/$dtd/$global->{format}/tr-mapping";
+-        }
+-    }
++  my $style = ($global->{style}) ?
++    ldt_searchfile(["$main::DataDir/site/$dtd/$global->{format}/$global->{style}mapping",
++                  "$main::DataDir/dist/$dtd/$global->{format}/$global->{style}mapping",
++                  "$main::DataDir/mappings/$global->{format}/$global->{style}mapping"])
++    :
++    '';
+-  create_temp("$tmpbase.3");
+-  system ("$main::progs->{SGMLSASP} $style $mapping <\"$tmpbase.2\" |
+-      expand -$global->{tabsize} >\"$tmpbase.3\"");
+-  ! -e "$tmpbase.3" and die "can't create file - exiting";
++  my $mapping = ldt_searchfile(["$main::DataDir/site/$dtd/$global->{format}/mapping",
++                              "$main::DataDir/dist/$dtd/$global->{format}/mapping",
++                              "$main::DataDir/mappings/$global->{format}/mapping"])
++    or die "$error_header: Could not find mapping file for $dtd/$global->{format}. Aborting ...\n";
++  $mapping = "$style $mapping" if $style;
+-  if ( $global->{debug} )
+-    {
+-      print "ASP stage finished.\n";
++  if ($global->{format} eq "groff"){
++    if ($dtd eq "linuxdoctr") {
++      $mapping = "$main::DataDir/mappings/$global->{format}/tr-mapping";
+     }
++  }
++
++  my $sgmlsasp_command = "$main::progs->{SGMLSASP} $mapping < $preaspout |
++      expand -t $global->{tabsize} > $aspout";
++  ldt_log "  ${error_header}::sgmlsasp_command:\n    $sgmlsasp_command";
++  system ($sgmlsasp_command) == 0
++    or die "$error_header: Error running $sgmlsasp_command. Aborting ...\n";
++
++  die "$error_header: Can't create $aspout file. Aborting ...\n"
++    unless -e "$aspout";
++
++  print "- ASP stage finished.\n" if ( $global->{debug} );
++  ldt_log "- ASP stage finished.";
+-  #
+   #  If a postASP stage is defined, let the format handle it.
+-  #  It should leave whatever it thinks is right based on $file.
+-  #
+-  #  postASP ($inhandle)
+-  #
++  # ----------------------------------------------------------------
++  ldt_log "- postASP stage started.";
+   umask $saved_umask;
+-  my $inpostasp = new FileHandle "<$tmpbase.3";
+-  if (defined $Formats{$global->{format}}{postASP})
+-    {
+-      &{$Formats{$global->{format}}{postASP}}($inpostasp) == 0 or
+-      die "error post-processing $global->{format}.\n";
+-    }
+-  $inpostasp->close;
+-
+-  if ( $global->{debug} )
+-    {
+-      print "postASP stage finished.\n";
+-    }
+-  #
+-  #  All done, remove the temporaries.
+-  #
+-  if( !$global->{debug} ) {
+-      remove_tmpfiles($tmpbase);
++  open (my $INPOSTASP, "< $aspout" )
++    or die "$error_header: Could not open $aspout for reading. Aborting ...\n";
++  if (defined $Formats{$global->{format}}{postASP}) {
++    # Usage: postASP ($INHANDLE)
++    # Should leave whatever it thinks is right based on $INHANDLE.
++    &{$Formats{$global->{format}}{postASP}}($INPOSTASP) == 0
++      or die "$error_header: Error post-processing $global->{format}. Aborting ...\n";
+   }
++  close $INPOSTASP;
++
++  print "- postASP stage finished.\n" if ( $global->{debug} );
++  ldt_log "- postASP stage finished.";
++
++  # -- Reset $global->{logfile} for next file
++  $global->{logfile} = '';
++
++  # -- All done, remove the temporaries.
++  remove_tmpfiles($tmpbase) unless ( $global->{debug} );
+ }
+ =pod
+@@ -629,7 +648,7 @@ sub process_file
+ Documentation for various sub-packages of LinuxDocTools.
+ =head1 AUTHOR
+-SGMLTools are written by Cees de Groot, C<E<lt>cg@cdegroot.comE<gt>>, 
++SGMLTools are written by Cees de Groot, C<E<lt>cg@cdegroot.comE<gt>>,
+ and various SGML-Tools contributors as listed in C<CONTRIBUTORS>.
+ Taketoshi Sano C<E<lt>sano@debian.org<gt>> rename to LinuxDocTools.
+diff --git a/doc/sgml2html b/doc/sgml2html
+index ea8e8c9..98a688c 100755
+--- a/doc/sgml2html
++++ b/doc/sgml2html
+@@ -1,53 +1,76 @@
+ #!/usr/bin/perl 
+ #
+-#   sgmltools.in
+-#
+-#   $Id$
+-#
+-#   SGML-Tools driver. Calls all other SGML-Tools components, contains
+-#   configuration information, etcetera.
++#   linuxdoc.in
+ #
++#   LinuxDoc-Tools driver. Calls all other LinuxDoc-Tools components,
++#   contains configuration information, etcetera.
++# -------------------------------------------------------------------
++
+ package main;
+-sub BEGIN 
+-{
++sub BEGIN {
+   require 5.004;
+ }
++
+ use strict;
+-use vars qw($prefix $DataDir $BinDir $progs);
++use vars qw($prefix
++          $isoentities_prefix
++          $DataDir
++          $AuxBinDir
++          $progs);
+ use FindBin;
+-$prefix = "/usr";
+-$DataDir = "$FindBin::Bin/sbase";
+-$BinDir = "/usr/bin";
++$prefix             = "/usr";
++$isoentities_prefix = "/usr";
++$DataDir            = "$FindBin::Bin/sbase";
++$AuxBinDir          = "/usr/lib/linuxdoc-tools";
+ use lib "/usr/share/linuxdoc-tools";
+-use lib "/usr/perl5";
+-use lib "/usr/lib/perl5";
+ use lib "/usr/share/perl5";
+-$progs = {
+-  "NSGMLS" => "/usr/bin/nsgmls",
+-  "SGMLSASP" => "/usr/bin/sgmlsasp",
+-  "GROFF" => "/usr/bin/groff",
++
++# ---------------------------------------------------------------------
++sub ldt_which {
++# ---------------------------------------------------------------------
++# ---------------------------------------------------------------------
++  die "ldt_which: No filename(s) array given. Aborting ...\n" unless scalar @_;
++
++  foreach my $file ( @_ ){
++    if ( $file =~ m/\// ) {
++      return $file if -x $file;
++    } else {
++      foreach my $path ( split(':',$ENV{'PATH'}) ){
++      $path =~ s/\/+$//;
++      return $file if -x "$path/$file";
++      }
++    }
++  }
++  die "No executable found in path for (", join(' ',@_) ,"). Aborting ...\n";
++}
++
++$progs   = {
++  "SGMLSASP"   => ldt_which("sgmlsasp"),
++  "NSGMLS"     => ldt_which("nsgmls","onsgmls"),
++  "GROFF"      => ldt_which("groff"),
+   "GROFFMACRO" => "-ms",
+-  "AWK" => "/usr/share/linuxdoc-tools/awkwhich"
++#  "NKF" => "@NKF@"
+ };
+-if (! -x $progs->{"NSGMLS"})
+-  { $progs->{"NSGMLS"} = "/usr/bin/onsgmls"; }
+-
+ $ENV{"SGML_CATALOG_FILES"} = "$DataDir/dtd/catalog" .
+   (defined $ENV{SGML_CATALOG_FILES} ? ":$ENV{SGML_CATALOG_FILES}" : "");
+ require "$FindBin::Bin/LinuxDocTools.pm";
+ &LinuxDocTools::init;
+-my @FileList = LinuxDocTools::process_options ("html", @ARGV);
+-for my $curfile (@FileList)
+-  {
+-    LinuxDocTools::process_file ($curfile);
+-  }
++my @FileList = LinuxDocTools::process_options ($0, @ARGV);
++
++foreach my $curfile (@FileList) {
++  &LinuxDocTools::process_file ($curfile);
++}
+ exit 0;
++
++# Local Variables:
++#  mode: perl
++# End:
+diff --git a/doc/sgml2latex b/doc/sgml2latex
+index 79c6df0..98a688c 100755
+--- a/doc/sgml2latex
++++ b/doc/sgml2latex
+@@ -1,53 +1,76 @@
+ #!/usr/bin/perl 
+ #
+-#   sgmltools.in
+-#
+-#   $Id$
+-#
+-#   SGML-Tools driver. Calls all other SGML-Tools components, contains
+-#   configuration information, etcetera.
++#   linuxdoc.in
+ #
++#   LinuxDoc-Tools driver. Calls all other LinuxDoc-Tools components,
++#   contains configuration information, etcetera.
++# -------------------------------------------------------------------
++
+ package main;
+-sub BEGIN 
+-{
++sub BEGIN {
+   require 5.004;
+ }
++
+ use strict;
+-use vars qw($prefix $DataDir $BinDir $progs);
++use vars qw($prefix
++          $isoentities_prefix
++          $DataDir
++          $AuxBinDir
++          $progs);
+ use FindBin;
+-$prefix = "/usr";
+-$DataDir = "$FindBin::Bin/sbase";
+-$BinDir = "/usr/bin";
++$prefix             = "/usr";
++$isoentities_prefix = "/usr";
++$DataDir            = "$FindBin::Bin/sbase";
++$AuxBinDir          = "/usr/lib/linuxdoc-tools";
+ use lib "/usr/share/linuxdoc-tools";
+-use lib "/usr/perl5";
+-use lib "/usr/lib/perl5";
+ use lib "/usr/share/perl5";
+-$progs = {
+-  "NSGMLS" => "/usr/bin/nsgmls",
+-  "SGMLSASP" => "/usr/bin/sgmlsasp",
+-  "GROFF" => "/usr/bin/groff",
++
++# ---------------------------------------------------------------------
++sub ldt_which {
++# ---------------------------------------------------------------------
++# ---------------------------------------------------------------------
++  die "ldt_which: No filename(s) array given. Aborting ...\n" unless scalar @_;
++
++  foreach my $file ( @_ ){
++    if ( $file =~ m/\// ) {
++      return $file if -x $file;
++    } else {
++      foreach my $path ( split(':',$ENV{'PATH'}) ){
++      $path =~ s/\/+$//;
++      return $file if -x "$path/$file";
++      }
++    }
++  }
++  die "No executable found in path for (", join(' ',@_) ,"). Aborting ...\n";
++}
++
++$progs   = {
++  "SGMLSASP"   => ldt_which("sgmlsasp"),
++  "NSGMLS"     => ldt_which("nsgmls","onsgmls"),
++  "GROFF"      => ldt_which("groff"),
+   "GROFFMACRO" => "-ms",
+-  "AWK" => "/usr/share/linuxdoc-tools/awkwhich"
++#  "NKF" => "@NKF@"
+ };
+-if (! -x $progs->{"NSGMLS"})
+-  { $progs->{"NSGMLS"} = "/usr/bin/onsgmls"; }
+-
+ $ENV{"SGML_CATALOG_FILES"} = "$DataDir/dtd/catalog" .
+   (defined $ENV{SGML_CATALOG_FILES} ? ":$ENV{SGML_CATALOG_FILES}" : "");
+ require "$FindBin::Bin/LinuxDocTools.pm";
+ &LinuxDocTools::init;
+-my @FileList = LinuxDocTools::process_options ("latex", @ARGV);
+-for my $curfile (@FileList)
+-  {
+-    LinuxDocTools::process_file ($curfile);
+-  }
++my @FileList = LinuxDocTools::process_options ($0, @ARGV);
++
++foreach my $curfile (@FileList) {
++  &LinuxDocTools::process_file ($curfile);
++}
+ exit 0;
++
++# Local Variables:
++#  mode: perl
++# End:
+diff --git a/doc/sgml2txt b/doc/sgml2txt
+index 013479f..98a688c 100755
+--- a/doc/sgml2txt
++++ b/doc/sgml2txt
+@@ -1,53 +1,76 @@
+ #!/usr/bin/perl 
+ #
+-#   sgmltools.in
+-#
+-#   $Id$
+-#
+-#   SGML-Tools driver. Calls all other SGML-Tools components, contains
+-#   configuration information, etcetera.
++#   linuxdoc.in
+ #
++#   LinuxDoc-Tools driver. Calls all other LinuxDoc-Tools components,
++#   contains configuration information, etcetera.
++# -------------------------------------------------------------------
++
+ package main;
+-sub BEGIN 
+-{
++sub BEGIN {
+   require 5.004;
+ }
++
+ use strict;
+-use vars qw($prefix $DataDir $BinDir $progs);
++use vars qw($prefix
++          $isoentities_prefix
++          $DataDir
++          $AuxBinDir
++          $progs);
+ use FindBin;
+-$prefix = "/usr";
+-$DataDir = "$FindBin::Bin/sbase";
+-$BinDir = "/usr/bin";
++$prefix             = "/usr";
++$isoentities_prefix = "/usr";
++$DataDir            = "$FindBin::Bin/sbase";
++$AuxBinDir          = "/usr/lib/linuxdoc-tools";
+ use lib "/usr/share/linuxdoc-tools";
+-use lib "/usr/perl5";
+-use lib "/usr/lib/perl5";
+ use lib "/usr/share/perl5";
+-$progs = {
+-  "NSGMLS" => "/usr/bin/nsgmls",
+-  "SGMLSASP" => "/usr/bin/sgmlsasp",
+-  "GROFF" => "/usr/bin/groff",
++
++# ---------------------------------------------------------------------
++sub ldt_which {
++# ---------------------------------------------------------------------
++# ---------------------------------------------------------------------
++  die "ldt_which: No filename(s) array given. Aborting ...\n" unless scalar @_;
++
++  foreach my $file ( @_ ){
++    if ( $file =~ m/\// ) {
++      return $file if -x $file;
++    } else {
++      foreach my $path ( split(':',$ENV{'PATH'}) ){
++      $path =~ s/\/+$//;
++      return $file if -x "$path/$file";
++      }
++    }
++  }
++  die "No executable found in path for (", join(' ',@_) ,"). Aborting ...\n";
++}
++
++$progs   = {
++  "SGMLSASP"   => ldt_which("sgmlsasp"),
++  "NSGMLS"     => ldt_which("nsgmls","onsgmls"),
++  "GROFF"      => ldt_which("groff"),
+   "GROFFMACRO" => "-ms",
+-  "AWK" => "/usr/share/linuxdoc-tools/awkwhich"
++#  "NKF" => "@NKF@"
+ };
+-if (! -x $progs->{"NSGMLS"})
+-  { $progs->{"NSGMLS"} = "/usr/bin/onsgmls"; }
+-
+ $ENV{"SGML_CATALOG_FILES"} = "$DataDir/dtd/catalog" .
+   (defined $ENV{SGML_CATALOG_FILES} ? ":$ENV{SGML_CATALOG_FILES}" : "");
+ require "$FindBin::Bin/LinuxDocTools.pm";
+ &LinuxDocTools::init;
+-my @FileList = LinuxDocTools::process_options ("txt", @ARGV);
+-for my $curfile (@FileList)
+-  {
+-    LinuxDocTools::process_file ($curfile);
+-  }
++my @FileList = LinuxDocTools::process_options ($0, @ARGV);
++
++foreach my $curfile (@FileList) {
++  &LinuxDocTools::process_file ($curfile);
++}
+ exit 0;
++
++# Local Variables:
++#  mode: perl
++# End:
diff --git a/distro/pkg/deb/patches/series b/distro/pkg/deb/patches/series
new file mode 100644 (file)
index 0000000..3a10aac
--- /dev/null
@@ -0,0 +1 @@
+0001-Sync-the-linuxdoc-mangled-files-with-linuxdoc-tools_.patch
diff --git a/distro/pkg/deb/prepare-environment b/distro/pkg/deb/prepare-environment
new file mode 100755 (executable)
index 0000000..d782c14
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+set -eu
+
+BIRD_RUN_DIR=/run/bird
+. /etc/bird/envvars
+
+
+mkdir --parents "$BIRD_RUN_DIR";
+
+if [ -n "$BIRD_RUN_USER" ]; then
+    if ! getent passwd $BIRD_RUN_USER >/dev/null; then
+       echo "Configured user '$BIRD_RUN_USER' doesn't exist."
+       exit 1
+    fi
+fi
+
+if [ -n "$BIRD_RUN_GROUP" ]; then
+    if ! getent group $BIRD_RUN_GROUP >/dev/null; then
+       echo "Configured group '$BIRD_RUN_GROUP' doesn't exist."
+       exit 1
+    fi
+fi
+
+chown --silent "$BIRD_RUN_USER:$BIRD_RUN_GROUP" "$BIRD_RUN_DIR"
+chmod 775 "$BIRD_RUN_DIR"
+
+:
diff --git a/distro/pkg/deb/rules b/distro/pkg/deb/rules
new file mode 100755 (executable)
index 0000000..5630ed1
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+DPKG_EXPORT_BUILDFLAGS = 1
+include /usr/share/dpkg/default.mk
+
+COMMON_FLAGS= --prefix=/usr --sysconfdir=/etc/bird --mandir=\$${prefix}/share/man \
+       --infodir=\$${prefix}/share/info --localstatedir=/var --runstatedir=/run/bird \
+       --docdir=\$${prefix}/share/bird2 \
+       --enable-client
+
+CFLAGS += -g -O2 -fno-strict-aliasing -fno-strict-overflow -fPIC
+LDFLAGS += -g -O2 -fno-strict-aliasing -fno-strict-overflow -fPIC -Wl,-z,defs -Wl,--as-needed
+
+%:
+       dh $@
+
+override_dh_auto_configure:
+       CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" dh_auto_configure -- $(COMMON_FLAGS) --with-protocols=all
+
+override_dh_auto_build:
+       dh_auto_build
+       dh_auto_build -- docs
+
+override_dh_auto_install:
+       dh_auto_install --destdir=debian/tmp
+
+override_dh_installinit:
+       dh_installinit --name=bird --restart-after-upgrade
+
+override_dh_installsystemd:
+       dh_installsystemd --name=bird --restart-after-upgrade
+
+DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl
+XP     = xsltproc -''-nonet -''-param man.charmap.use.subset "0"
+
+bird.8: debian/bird.xml
+       $(XP) $(DB2MAN) $<
+
+override_dh_installman: bird.8
+       dh_installman
+
+override_dh_clean:
+       dh_clean
+       -rm -f bird.8 birdc.8
+
+override_dh_missing:
+       dh_missing  --fail-missing
+
+override_dh_compress:
+       dh_compress -X.conf
diff --git a/distro/pkg/deb/source/format b/distro/pkg/deb/source/format
new file mode 100644 (file)
index 0000000..163aaf8
--- /dev/null
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/distro/pkg/deb/watch b/distro/pkg/deb/watch
new file mode 100644 (file)
index 0000000..1874bfb
--- /dev/null
@@ -0,0 +1,2 @@
+version=3
+https://bird.network.cz/download/bird-(2\.[\d.]+).tar.gz
diff --git a/distro/pkg/rpm/bird.service b/distro/pkg/rpm/bird.service
new file mode 100644 (file)
index 0000000..fa203c7
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=BIRD Internet Routing Daemon
+Wants=network.target
+After=network.target
+
+[Service]
+Type=simple
+ExecStart=/usr/sbin/bird -f -u bird -g bird
+ExecReload=/bin/kill -HUP $MAINPID
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/distro/pkg/rpm/bird.spec b/distro/pkg/rpm/bird.spec
new file mode 100644 (file)
index 0000000..1267cf9
--- /dev/null
@@ -0,0 +1,121 @@
+%global _hardened_build 1
+
+%if "x%{?suse_version}" == "x"
+# missing linuxdoc-tools and sgml-common on SUSE
+%define _without_doc 1
+%endif
+
+Name:             bird
+Version:          {{ version }}
+Release:          cznic.{{ release }}%{?dist}
+Summary:          BIRD Internet Routing Daemon
+
+License:          GPLv2+
+URL:              https://bird.network.cz/
+Source0:          https://bird.network.cz/download/bird-%{version}.tar.gz
+Source1:          bird.service
+Source2:          bird.tmpfilesd
+
+BuildRequires:    flex
+BuildRequires:    bison
+BuildRequires:    ncurses-devel
+BuildRequires:    readline-devel
+BuildRequires:    sed
+BuildRequires:    gcc
+BuildRequires:    make
+BuildRequires:    libssh-devel
+%if 0%{?fedora} || (0%{?rhel} && 0%{?rhel} > 7)
+BuildRequires:    systemd-rpm-macros
+%else
+BuildRequires:    systemd
+%endif
+
+Obsoletes:        bird6 < 2.0.2-1
+Provides:         bird6 = %{version}-%{release}
+
+%description
+BIRD is a dynamic IP routing daemon supporting both, IPv4 and IPv6, Border
+Gateway Protocol (BGPv4), Routing Information Protocol (RIPv2, RIPng), Open
+Shortest Path First protocol (OSPFv2, OSPFv3), Babel Routing Protocol (Babel),
+Bidirectional Forwarding Detection (BFD), IPv6 router advertisements, static
+routes, inter-table protocol, command-line interface allowing on-line control
+and inspection of the status of the daemon, soft reconfiguration as well as a
+powerful language for route filtering.
+
+%if 0%{!?_without_doc:1}
+%package doc
+Summary:          Documentation for BIRD Internet Routing Daemon
+BuildRequires:    linuxdoc-tools sgml-common perl(FindBin)
+BuildArch:        noarch
+
+%description doc
+Documentation for users and programmers of the BIRD Internet Routing Daemon.
+
+BIRD is a dynamic IP routing daemon supporting both, IPv4 and IPv6, Border
+Gateway Protocol (BGPv4), Routing Information Protocol (RIPv2, RIPng), Open
+Shortest Path First protocol (OSPFv2, OSPFv3), Babel Routing Protocol (Babel),
+Bidirectional Forwarding Detection (BFD), IPv6 router advertisements, static
+routes, inter-table protocol, command-line interface allowing on-line control
+and inspection of the status of the daemon, soft reconfiguration as well as a
+powerful language for route filtering.
+%endif
+
+%prep
+%setup -q
+
+%build
+%configure --runstatedir=%{_rundir}/bird
+%make_build all %{!?_without_doc:docs}
+
+%install
+%make_install
+
+{% raw %}
+install -d %{buildroot}{%{_localstatedir}/lib/bird,%{_rundir}/bird}
+install -D -p -m 0644 %{SOURCE1} %{buildroot}%{_unitdir}/bird.service
+install -D -p -m 0644 %{SOURCE2} %{buildroot}%{_tmpfilesdir}/bird.conf
+{% endraw %}
+
+%check
+make test
+
+%pre
+getent group bird >/dev/null || groupadd -r bird
+getent passwd bird >/dev/null || \
+  useradd -r -g bird -d %{_localstatedir}/lib/bird -s /sbin/nologin \
+  -c "BIRD daemon user" bird
+exit 0
+
+%post
+%systemd_post bird.service
+
+%preun
+%systemd_preun bird.service
+
+%postun
+%systemd_postun_with_restart bird.service
+
+%files
+%doc NEWS README
+%attr(0640,root,bird) %config(noreplace) %{_sysconfdir}/bird.conf
+%{_unitdir}/bird.service
+%{_tmpfilesdir}/bird.conf
+%{_sbindir}/bird
+%{_sbindir}/birdc
+%{_sbindir}/birdcl
+%dir %attr(0750,bird,bird) %{_localstatedir}/lib/bird
+%dir %attr(0750,bird,bird) %{_rundir}/bird
+
+%if 0%{!?_without_doc:1}
+%files doc
+%doc NEWS README
+%doc doc/bird.conf.*
+%doc obj/doc/bird*.html
+%doc obj/doc/bird.pdf
+%doc obj/doc/prog*.html
+%doc obj/doc/prog.pdf
+%endif
+
+%changelog
+* Wed Apr 07 2021 Jakub Ružička <jakub.ruzicka@nic.cz> - {{ version }}-cznic.1
+- upstream package
diff --git a/distro/pkg/rpm/bird.tmpfilesd b/distro/pkg/rpm/bird.tmpfilesd
new file mode 100644 (file)
index 0000000..a73133a
--- /dev/null
@@ -0,0 +1 @@
+d /run/bird 750 bird bird
diff --git a/tools/make-dev-archive b/tools/make-dev-archive
new file mode 100755 (executable)
index 0000000..227d029
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# This a modified version of gendist script which generates development
+# archive (tarball) without docs from current sources.
+
+BIRD_VERSION=`grep 'BIRD_VERSION \"' sysdep/config.h | sed '/BIRD_VERSION/!d;s/^.*"\(.*\)"$/\1/'`
+# differentiate dev tarballs from upstream ones
+GIT_HASH=$(git rev-parse --short HEAD )
+TIMESTAMP=$(date -u +'%s' 2>/dev/null)
+VERSION=$BIRD_VERSION.$TIMESTAMP.$GIT_HASH
+
+REL=bird-$VERSION
+T=/tmp/bird
+AC=autoreconf
+
+set -e
+
+# prepare output dir
+rm -rf $T/$REL
+mkdir -p $T/$REL
+
+$AC
+
+# cleanup
+find . -name "*~" -exec rm -f '{}' '+'
+rm -rf autom4te*cache
+
+echo Building $REL
+cp -a . $T/$REL
+echo Generating ChangeLog
+git log  >$T/$REL/ChangeLog
+rm -f $T/$REL/bird.conf*
+rm -rf $T/$REL/.git/
+rm -rf `find $T/$REL -name CVS -o -name tmp` $T/$REL/{misc,rfc,doc/slides,doc/slt2001,doc/old,doc/*.out}
+( cd $T ; tar czvvf $REL.tar.gz $REL )
+rm -rf $T/$REL
+
+echo $T/$REL.tar.gz
diff --git a/tools/make-obs b/tools/make-obs
new file mode 100755 (executable)
index 0000000..aeec70a
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/bash
+# create OpenSUSE Build System (OBS) source package
+#
+# this needs to be run on a (Debian-based) system with:
+#
+# * apkg
+# * dpkg-buildpackage
+#
+# run from project root containing distro/ dir:
+#
+#     ./tools/make-obs [path/to/archive.tar.gz]
+#
+# supply archives as optional arguments to build from,
+# otherwise archive will be built from sources by apkg
+#
+# output at ./pkg/obs/ (removed on each run)
+set -o errexit -o nounset
+
+OUTDIR="pkg/obs"
+APKG_OPTS="-O $OUTDIR"
+
+if [ -z $@ ]; then
+    echo "building OBS srcpkg from project files"
+else
+    AR=$1
+    echo "building OBS srcpkg from specified archive(s)"
+    APKG_OPTS="-a $AR $APKG_OPTS"
+fi
+
+if [ -n "$RELEASE" ]; then
+    echo "custom release: $RELEASE"
+    APKG_OPTS="-r $RELEASE $APKG_OPTS"
+fi
+
+set -o xtrace
+: removing existing output files at output dir: $OUTDIR
+rm -rf "$OUTDIR"
+: making debian source package from archive
+apkg srcpkg $APKG_OPTS -d debian
+: removing extra debian source package files
+rm -f $OUTDIR/*_source.*
+: rendering RPM template
+apkg srcpkg $APKG_OPTS -d fedora --render-template
+: fixing RPM .spec to use debian source archive
+sed -i 's/^\(Source0:\s\+\).*/\1bird2_%{version}.orig.tar.gz/' $OUTDIR/*.spec
+echo "OBS srcpkg ready at: $OUTDIR"