Issues in rc scripts (PROVIDES != name != script name)

From: Alexander Leidinger <Alexander_at_Leidinger.net>
Date: Tue, 02 Jul 2024 12:56:52 UTC
Hi,

I'm investigating some issues with the new service jails feature. It 
comes down to the naming of the rc scripts. We have scripts where we 
have a mismatch between the setting of the name variable inside the 
script and the filename. This mail is to get some input on the best way 
forward.

The rc scripting docu 
(https://docs.freebsd.org/en/articles/rc-scripting/) doesn't require 
that the name of the rc script is the same as the name in the name 
variable inside the script, but it suggests it:
---snip---
Now it is the right time to choose a unique name for our script once and 
for all. We will use it in a number of places while developing the 
script. For a start, let us give the same name to the script file, too.
---snip---

The new service jails framework 
(https://docs.freebsd.org/en/books/handbook/jails/#service-jails) makes 
use of this (it uses the name variable to execute the script inside a 
newly created jail).

I wrote a little script which parses the script in the ports collection 
and it found 255 scripts with issues (out of 3361 scripts -> ~7.6% -- 
there are some false positives, to the percentage may even be smaller). 
For 124 of those the variable name uses an underscore and the script 
name uses a hyphen instead (this is where I noticed issues with the 
service jails).

While I was at it, I also checked for a mismatch between the name 
variable and the PROVIDES meta-comment inside. Strictly speaking this is 
not necessary, and there may even be cases where it is a feature that it 
is not the same, but those errors are part of the 255 issues.

Examples:
audio/logitechmediaserver/files/logitechmediaserver.in ERROR: script 
name and name variable do not match (logitechmediaserver != 
%%PORTNAME%%)
  -> probably a false positive (there are other ports which start with 
logitechmediaserver and I haven't checked if they are slave ports)

audio/owntone/files/owntone.in ERROR: PROVIDE and name variable do not 
match (owntone != ${name##*/})
audio/owntone/files/owntone.in ERROR: script name and name variable do 
not match (owntone != ${name##*/})
  -> false positive (this uses an instancing tech which allows to link 
the rc script to a new name and then a second instance can be started 
which reacts on the new name in rc.conf), this is not an issue for 
service jails, as long as the script name is the same as the instance 
name

audio/shairport-sync/files/shairport-sync.in ERROR: script name and name 
variable do not match (shairport-sync != shairport_sync)
  -> real error ('-' instead of '_')

benchmarks/thrulay/files/thrulayd.in ERROR: PROVIDE and name variable do 
not match (thrulay != thrulayd)
comms/svxlink/files/svxreflector.in ERROR: PROVIDE and name variable do 
not match (remotetrx != svxreflector)
  -> while I was at it, I checked PROVIDE too, and here we have some 
issues too

Here is how I generated this:

/tmp/portrc.awk:
---snip---
/PROVIDE/ { provide=$3}
/portname=/ {skip}
/procname=/ {skip}
/:name=/ {
         split($0, tname, "=");
         name=sprintf("%s", tname[2]);
         gsub("\"", "", name)}
END {
         idx = index(provide, name);
         if (idx > 0) {
                 tp=1;
         } else {
                 printf "%s ERROR: PROVIDE and name variable do not match 
(%s != %s)\n", template, provide, name
                 tp=0;
         }

         idx = index(name, fname);
         if (idx > 0) {
                 tn=1;
         } else {
                 printf "%s ERROR: script name and name variable do not 
match (%s != %s)\n", template, fname, name
                 tn=0;
         }
}
---snip---

cd /usr/ports
ls -1 */*/files/*.in | grep -E -v 
'/(pkg-|patch-|extra-patch-.*\.desktop\.|xml\.in)' | xargs grep -E 
'(name=|PROVIDE)' >/tmp/portlist_rc
for s in $(cut -d : -f 1 </tmp/portlist_rc| sort -u ); do
   grep $s /tmp/portlist_rc | awk -v fname=$(basename $s .in) -v 
template=$s -f /tmp/portrc.awk 2>/dev/null
done >/tmp/ports_rc_defects

The list of ports with the underscore/hyphen mix:
   grep "script name" /tmp/ports_rc_defects | grep -v %% | grep -v '##' | 
grep _| grep -v '!= )' | less

Generally I would say for various reasons (not only for service jails, 
but also for the benefit of other tools which may want to make use of 
this info to make it more easy to match meta-data with/in rc scripts) we 
should make this uniform where possible. So renaming all the xxx-xxx.in 
to xxx_xxx.in and have the PROVIDES match what is in the name variable.

There are some high-profile ports affected:
lang/php81/files/php-fpm.in ERROR: script name and name variable do not 
match (php-fpm != php_fpm)
lang/php82/files/php-fpm.in ERROR: script name and name variable do not 
match (php-fpm != php_fpm)
lang/php83/files/php-fpm.in ERROR: script name and name variable do not 
match (php-fpm != php_fpm)
security/amavisd-milter/files/amavisd-milter.in ERROR: script name and 
name variable do not match (amavisd-milter != amavisd_milter)
security/amavisd-new/files/amavis-milter.in ERROR: script name and name 
variable do not match (amavis-milter != amavis_milter)
security/amavisd-new/files/amavis-p0fanalyzer.in ERROR: script name and 
name variable do not match (amavis-p0fanalyzer != amavis_p0fanalyzer)
security/amavisd-new/files/amavisd-snmp.in ERROR: script name and name 
variable do not match (amavisd-snmp != amavisd_snmp)
security/clamav-lts/files/clamav-clamd.in ERROR: script name and name 
variable do not match (clamav-clamd != clamav_clamd)
security/clamav-lts/files/clamav-freshclam.in ERROR: script name and 
name variable do not match (clamav-freshclam != clamav_freshclam)
security/clamav-lts/files/clamav-milter.in ERROR: script name and name 
variable do not match (clamav-milter != clamav_milter)
security/clamav/files/clamav-clamd.in ERROR: script name and name 
variable do not match (clamav-clamd != clamav_clamd)
security/clamav/files/clamav-freshclam.in ERROR: script name and name 
variable do not match (clamav-freshclam != clamav_freshclam)
security/clamav/files/clamav-milter.in ERROR: script name and name 
variable do not match (clamav-milter != clamav_milter)
sysutils/bacula11-server/files/bacula-dir.in ERROR: script name and name 
variable do not match (bacula-dir != bacula_dir)
sysutils/bacula11-server/files/bacula-fd.in ERROR: script name and name 
variable do not match (bacula-fd != bacula_fd)
sysutils/bacula11-server/files/bacula-sd.in ERROR: script name and name 
variable do not match (bacula-sd != bacula_sd)
sysutils/bacula13-server/files/bacula-dir.in ERROR: script name and name 
variable do not match (bacula-dir != bacula_dir)
sysutils/bacula13-server/files/bacula-fd.in ERROR: script name and name 
variable do not match (bacula-fd != bacula_fd)
sysutils/bacula13-server/files/bacula-sd.in ERROR: script name and name 
variable do not match (bacula-sd != bacula_sd)
sysutils/bacula15-server/files/bacula-dir.in ERROR: script name and name 
variable do not match (bacula-dir != bacula_dir)
sysutils/bacula15-server/files/bacula-fd.in ERROR: script name and name 
variable do not match (bacula-fd != bacula_fd)
sysutils/bacula15-server/files/bacula-sd.in ERROR: script name and name 
variable do not match (bacula-sd != bacula_sd)
sysutils/bacula9-server/files/bacula-dir.in ERROR: script name and name 
variable do not match (bacula-dir != bacula_dir)
sysutils/bacula9-server/files/bacula-fd.in ERROR: script name and name 
variable do not match (bacula-fd != bacula_fd)
sysutils/bacula9-server/files/bacula-sd.in ERROR: script name and name 
variable do not match (bacula-sd != bacula_sd)
sysutils/syslog-ng/files/syslog-ng.in ERROR: script name and name 
variable do not match (syslog-ng != syslog_ng)

This will not change the autostart at boot (the rc variables stay the 
same, it is the filenames which would change), but if someone has some 
scripts to automate some stuff (ansible/puppet/chef/cfengine/plain 
shell/...) there may be some surprises.

I would like to:
  - rename the scripts and fix the PROVIDES part (with a suitable 
UPDATING entry)
  - change the rc docu to strongly advise that the script name matches 
the content of the name variable during runtime (allows the instancing 
and the %%PORTNAME%% stuff) with some example where it matters

What's the generic feeling here about this?

Bye,
Alexander.

-- 
http://www.Leidinger.net Alexander@Leidinger.net: PGP 0x8F31830F9F2772BF
http://www.FreeBSD.org    netchild@FreeBSD.org  : PGP 0x8F31830F9F2772BF