Bug 228299

Summary: usr.sbin/sysrc: Specifying multiple -f flags does not yield results for every specified flag
Product: Base System Reporter: Mateusz Piotrowski <0mp>
Component: miscAssignee: Devin Teske <dteske>
Status: In Progress ---    
Severity: Affects Only Me CC: dteske
Priority: --- Keywords: needs-qa
Version: CURRENT   
Hardware: Any   
OS: Any   

Description Mateusz Piotrowski freebsd_committer freebsd_triage 2018-05-16 16:34:57 UTC
Here's a script to reproduce this issue:

> directory="$(mktemp -d)"
> echo 'A=x' > "$directory/x.txt"
> echo 'A=y' > "$directory/y.txt"
> echo "Actual result of \"sysrc -n -f \"$directory/x.txt\" -f \"$directory/y.txt\" A\":"
> sysrc -n -f "$directory/x.txt" -f "$directory/y.txt" A
> echo Expected:
> echo x
> echo y
Comment 1 Devin Teske freebsd_committer freebsd_triage 2018-06-17 03:09:17 UTC
The "-f file" argument to sysrc is working as-intended (explanation below).

$ cat file1
A=file1
$ cat file2
A=file2
$ sysrc -n -ffile{1,2} A
file2
$ sysrc -n -ffile{2,1} A
file1

Passing "-f file" multiple times does not tell sysrc to output the variable from each file, but rather it tells sysrc to allow overrides.

The point of sysrc is to allow you to modify rc.conf(5) variables which affect the boot process, service(8), and rc.d scripts -- and those things use a collection of files which override each other. The primary purpose of sysrc is to allow you have visibility into what values persist for the boot process, service(8) invocations, and rc.d scripts . Illustrated above you can see that if you change the order in which you specify multiple "-f file" arguments, you have a direct result on which value is printed. Specifically, passing "-f file1 -f file2" has a different result than "-f file2 -f file1" when requesting the value of variable A -- the last file specified overrides all previously specified files.

If you want to use sysrc to get the value from each file, use separate invocations (example below):

$ sysrc -nf file1 A
file1
% sysrc -nf file2 A
file2

But if you must use a single command, you can use:

$ echo file{1,2} | xargs -n1 -Ifile sysrc -nf file A
file1
file2
Comment 2 Devin Teske freebsd_committer freebsd_triage 2018-06-17 03:16:28 UTC
Without additional comment in 72 hours, will close as "Not a bug"
Comment 3 Devin Teske freebsd_committer freebsd_triage 2018-06-21 15:19:19 UTC
Feel free to add comment. Not opposed to re-opening.
Comment 4 Mateusz Piotrowski freebsd_committer freebsd_triage 2018-06-22 15:15:05 UTC
1. Sorry for replying so late.
2. Thanks for your explanation! :)

I think I'll try to submit a patch for the manual page in this case. The description of the -f flag suggests that multiple -f's are for "many files" instead of "overwrite".
Comment 5 Devin Teske freebsd_committer freebsd_triage 2018-06-24 18:55:49 UTC
Re-open; repurpose as bug for clarifying "-f file" option of sysrc
Comment 6 Devin Teske freebsd_committer freebsd_triage 2018-06-24 19:05:05 UTC
Looking forward to reviewing whatever you think will make the manual more clear.

Currently the manual says:

-f file  Operate on the specified file(s) instead of the files obtained
         by reading the `rc_conf_files' entry in the RC_DEFAULTS file.
         This option can be specified multiple times for additional
         files.

Below the list of options in the sysrc manual, rc_conf_files is explained:

(begin quote)
The list of system configuration files is configured in the file
`/etc/defaults/rc.conf' within the variable `rc_conf_files', which by-
default contains a space-separated list of pathnames.  On all FreeBSD
systems, this defaults to the value "/etc/rc.conf /etc/rc.conf.local".
Each pathname is sourced in-order upon startup.  It is in the same
fashion that sysrc sources the configuration files before returning the
value of the given variable.

When supplied a variable name, sysrc will return the value of the
variable.  If the variable does not appear in any of the configured
`rc_conf_files', an error is printed and error status is returned.
(end quote)

So it's already explained that sysrc will return a single value regardless of how many files you give it (where "-f file" just modifies rc_conf_files).

But I welcome any patch to help further clarification.