NetBSD gnats - hpaluch/hpaluch.github.io GitHub Wiki

NetBSD GNATS install

GNATS is "GNU Problem Report Management System" and is probably used on https://www.netbsd.org/support/query-pr.html

In this article I will try to install it locally.

Tested OS: NetBSD 11 Beta, from: https://nycdn.netbsd.org/pub/NetBSD-daily/netbsd-11/20251223184838Z/

First I installed gnats package using:

which pkgin || \
 PKG_PATH="https://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r|cut -f '1 2' -d.|cut -f 1 -d_)/All" pkg_add pkgin
# pinfo is user-friendly reader for GNU Info manuals,
# use "pinfo gnats" to read GNATS documentation
# - "pine" is full screen e-mail client to read e-mails
pkgin install gnats pinfo pine

Now we have to follow manual + do few additional steps:

  1. add to /etc/services (see https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=59867)

    support         1529/tcp        # GNATS
    
  2. rebuild services database (surprise for non-BSD users):

    services_mkdb
    
  3. Append to /etc/inetd.conf (following install message):

    # gnats
    support stream  tcp     nowait  gnats   /usr/pkg/libexec/gnats/gnatsd   gnatsd
    support stream  tcp6    nowait  gnats   /usr/pkg/libexec/gnats/gnatsd   gnatsd
    

    (I added IPv6 listen port to existing IPv4 port).

  4. Restart inetd(8) with: /etc/rc.d/inetd restart

  5. Verify that there are no error messages in /var/log/messages

  6. Add new line to crontab using command crontab -e -u gnats:

# gnats
*/5 * * * * /usr/pkg/libexec/gnats/queue-pr -r
  1. Append to /etc/mail/aliases (following install message):
gnats-admin:    postmaster
bugs:           "| /usr/pkg/libexec/gnats/queue-pr -q"
query-pr:       "| /usr/pkg/libexec/gnats/mail-query"
  1. Run newaliases to update aliases database (first look to console, postfix may do this for you automatically).

  2. Now we should create default db with:

su - gnats /usr/pkg/libexec/gnats/mkdb default

  Copying default files from /usr/pkg/share/gnats/defaults

Note: if above command fails with errors you probably hit bugs described on:

su - gnats /usr/pkg/libexec/gnats/mkdb default

/usr/pkg/libexec/gnats/mkdb: domkdir: chown: not found
/usr/pkg/libexec/gnats/mkdb: domkdir: chown: not found
/usr/pkg/libexec/gnats/mkdb: domkdir: chown: not found
/usr/pkg/libexec/gnats/mkdb: domkdir: chown: not found
/usr/pkg/libexec/gnats/mkdb: domkdir: chown: not found
Copying default files from /usr/pkg/share/gnats/defaults
/usr/pkg/libexec/gnats/mkdb: docp: chown: not found
/usr/pkg/libexec/gnats/mkdb: docp: chown: not found
/usr/pkg/libexec/gnats/mkdb: docp: chown: not found
cp: /usr/pkg/share/gnats/defaults/gnatsd.user_access: No such file or directory
Can't copy file /usr/pkg/share/gnats/defaults/gnatsd.user_access to /var/db/gnats/gnatsdb/gnats-adm/gnatsd.user_access, exiting

To fix chown: not found apply following patch:

diff -u usr/pkg/libexec/gnats/mkdb.orig usr/pkg/libexec/gnats/mkdb
--- usr/pkg/libexec/gnats/mkdb.orig     2025-12-28 11:55:53.704430031 +0100
+++ usr/pkg/libexec/gnats/mkdb  2025-12-28 11:56:52.590295693 +0100
@@ -22,7 +22,8 @@
 # along with GNU GNATS; see the file COPYING.  If not, see
 # <http://www.gnu.org/licenses/>.
 
-PATH="/usr/pkg/libexec/gnats:/usr/pkg/sbin:/usr/pkg/bin:/bin:/usr/bin:${PATH}"
+# /sbin PATH required for chown
+PATH="/usr/pkg/libexec/gnats:/usr/pkg/sbin:/sbin:/usr/pkg/bin:/bin:/usr/bin:${PATH}"
 export PATH
 
 GNATS_USER=gnats

To fix No such file or directory:

cp /usr/pkg/share/examples/gnats/*_access /usr/pkg/share/gnats/defaults/

And rerun command with:

rm -rf /var/db/gnats/gnatsdb
su - gnats /usr/pkg/libexec/gnats/mkdb default

  Copying default files from /usr/pkg/share/gnats/defaults

Note: default database supports single category pending. To enable few sample categories run:

# run as 'root' or 'gnats' user
sed -i.orig -e '/^#[^ ]*:/s/^#//' /var/db/gnats/gnatsdb/gnats-adm/categorie

This should enable following categories:

# run as 'root' or 'gnats' user:
$ query-pr --valid-values Category

pending
doc
gcc
g++
test

You can now test, whether gnats daemon works:

telnet localhost 1529
# try: dbls
# try: quit

Trying to send first bug with:

send-pr -t bugs@`hostname` "$@"

Because of several issues, I decided to create test script + file:

  • file testt-pr.txt created from output of send-pr -P
  • in same folder script test-send-pr.sh with contents:
#!/bin/sh
set -xeuo pipefail
cd $( dirname $0 )
send-pr -t bugs@`hostname` -f test-pr.txt
exit 0

But received this error mail:

<[email protected]>: Command died with status 2: "
    /usr/pkg/libexec/gnats/queue-pr -q". Command output: queue-pr: Unable to
    open global configuration file /usr/pkg/etc/gnats/databases Problem with
    queue-pr Unable to open global configuration file
    /usr/pkg/etc/gnats/databases

Trying as fix:

nbsd11-gnats# ls -l /usr/pkg/etc/gnats/databases
-rw-------  1 gnats  daemon  686 Dec 28 08:59 /usr/pkg/etc/gnats/databases
nbsd11-gnats# chmod +r /usr/pkg/etc/gnats/databases

Note: if you apply later fix below (suid gnats) you can omit above fix - it should be automatically resolved with suid.

After above fix got new error:

<[email protected]>: Command died with status 2: "
    /usr/pkg/libexec/gnats/queue-pr -q"

Creating ktruss wrapper I found that:

4437   4437 queue-pr CALL  rename(0x7f0b2aec4060,0x7f0b2aebb810)
4437   4437 queue-pr NAMI  "/tmp//gnatsPuacPe"
4437   4437 queue-pr NAMI  "/var/db/gnats/gnatsdb/gnats-queue/gnatsPuacPe"
4437   4437 queue-pr RET   rename -1 errno 13 Permission denied

Trying fix:

chown gnats /usr/pkg/libexec/gnats/queue-pr
chmod u+s /usr/pkg/libexec/gnats/queue-pr
ls -l /usr/pkg/libexec/gnats/queue-pr

  -rwsr-xr-x  1 gnats  wheel  197600 Dec 19 08:19 /usr/pkg/libexec/gnats/queue-pr

To really see processed request you have to wait for cron job to complete (every 5 minutes) from crontab -l -u gnats:

# gnats
*/5 * * * * /usr/pkg/libexec/gnats/queue-pr -r

This will move random queued temporary filenames from /var/db/gnats/gnatsdb/gnats-queue/ to /var/db/gnats/gnatsdb/CATEGORY - and in CATEGORY there will be filename that equals to ID (1, 2, ...).

Note: to be able to use gnatsd commands to at least view tickets you have to:

  • uncomment following line in /var/db/gnats/gnatsdb/gnats-adm/gnatsd.user_access

    *::view:
    
  • no restart needed just connect again to tcp port 1529 on localhost

Querying tickets:

There are theoretically several interfaces to GNATs to query existing PRs

  • e-mail query
  • query-pr CLI
  • gnatsd (SMTP like interface on tcp port 1529)
  • Web UI - not installed, but available in original source under gnats-4.2.0/contrib/juniper-web-reports

Querying tickets: e-mail

Most trivial example using e-mail query-pr:

  • command to query ticket number 4:

    echo . | mail -s "4"  query-pr@`hostname`
    
  • now check your mailbox with mail or pine command - you should receive query results

  • examples with --epxr (generally tricky):

    $ echo . | mail -s '--expr Category="test"'  query-pr@`hostname`
    # Warning! I was unable to pass --expr with spaces:
    $ echo . | mail -s '-f summary --expr Category="test"&State="open"'  query-pr@`hostname`
    

Querying tickets: using CLI

Using CLI:

  • run all commands user gnats:

  • query using switches:

    # return all tickets in category 'test' AND in state 'open' using format summary
    $ query-pr query-pr -f summary -c test -s open
         4 gnats-ad test     open      non-criti low      unknown    This is Synopsis
    
  • query using --expr notice required quoting - so (") are passed as literals (not eaten by shell + expression must be single argument - so using single (') quotes around):

    $ query-pr -f summary --expr 'Category="test" & State="open"'
           4 gnats-ad test     open      non-criti low      unknown    This is Synopsis
    

Querying tickets: telnet to gnatsd

Using gnatsd:

$ telnet localhost 1529
help

Simple query by PR Number:

rset                    # reset query
210 Reset state.
qfmt standard           # set format (mandatory)
210 Ok.
quer 4                  #
300 PRs follow.
>Number:         4
>Category:       test
>Synopsis:       This is Synopsis
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    gnats-admin
>State:          open
>Class:          sw-bug
>Submitter-Id:   unknown
>Arrival-Date:   Mon Dec 29 07:40:01 +0100 2025
>Originator:     [email protected]
>Release:        NetBSD 11.0_BETA

Query PR by Category AND State:

rset
210 Reset state.
qfmt summary
210 Ok.
expr Category="test" & State="open"
210 Ok.
quer
300 PRs follow.
       4 gnats-ad test     open      non-criti low      unknown    This is Synopsis
.

You end gnatsd session with quit command.

Follow-up

Should be easy, reply to address bugs@DOMAIN (same as to create bug), but with subject containing PR number, for example

Subject: Re: doc/5: Test bug from template

Warning! My default configuration uses rather gnats-admin@DOMAIN as reply address so I have to change it to bugs@DOMAIN before sending reply.

After crontab is run you should receive new mail with body like:

Date: Mon, 29 Dec 2025 09:35:01 +0100 (CET)
From: ansible@localhost
To: [email protected], [email protected]
Subject: doc/5: Re: doc/5: Test bug from template

The following reply was made to PR doc/5; it has been noted by GNATS.

From: ansible@localhost
To: [email protected]
Cc: 
Subject: Re: doc/5: Test bug from template
Date: Mon, 29 Dec 2025 09:34:07 +0100 (CET)

 This is my follow-up....

TODO

  • fix Reply-To: (from gnats-admin to bugs) so follow-up will work

  • use proper usernames for Responsible users, defaults in /var/db/gnats/gnatsdb/gnats-adm/categories are:

    $ grep -v -e '^$' -e '^#' /var/db/gnats/gnatsdb/gnats-adm/categories
    pending:Category for faulty PRs:gnats-admin:
    doc:Documentation Bug:jeffrey:pesch
    gcc:The GNU C compiler:wilson:tiemann
    g++:The GNU C++ compiler:brendan:tiemann, mrs
    test:*Test Category:gnats-admin:
    
  • file format is: category:description:responsible:notify