rc(8) ignores last line without newline of *.conf

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

rc(8) ignores last line without newline of *.conf

George Koehler-2
>Synopsis: rc(8) ignores last line without newline of *.conf
>Category: system
>Environment:
        System      : OpenBSD 6.4
        Details     : OpenBSD 6.4-current (GENERIC) #527: Mon Dec 24 22:16:45 MST 2018
                         [hidden email]:/usr/src/sys/arch/amd64/compile/GENERIC

        Architecture: OpenBSD.amd64
        Machine     : amd64
>Description:
        When /etc/rc reads some configuration files, it ignores the
last line if it doesn't end with a newline.  I noticed this problem
after Reddit's /u/FOSSilized_Daemon reported that the last line of
mixerctl.conf didn't work:
https://www.reddit.com/r/openbsd/comments/a9lnu1/mixerctl_and_audio_configuration/ecmzvvx/
        stripcom() in /etc/rc uses `while read _line ; do ... done`
to read these files, but `read _line` exits 1 when the last line is
without a newline.  This behavior in sh and ksh is consistent with
bash, dash, ksh93, and yash:

$ printf what | ksh -c 'read p; echo $p $?'
what 1
$ printf what | bash -c 'read p; echo $p $?'
what 1

        ksh(1) only says, "If no input is read, *read* exits with
a non-zero status."  bash(1), dash(1), and ksh93(1) mention that
*read* fails when EOF.  yash(1) says, "Note that the exit status is
non-zero if an end of input is encountered before reading the entire
line."

>How-To-Repeat:
        In a machine with no sysctl.conf:
        # printf kern.hostid=1 > /etc/sysctl.conf
        # reboot

        After the reboot:
        $ sysctl kern.hostid
        kern.hostid=0

        Can also copy stripcom() to another script and test it.

>Fix:
        One can work around the problem by ending files like
sysctl.conf(5) with a newline.
        The fix might require fixing stripcom() in /etc/rc, fixing
stripcom() in /etc/netstart, and changing the manuals of sh(1) and
ksh(1) to describe what happens when there is no final newline.
        The following version of stripcom() might work, but I'm not
sure.  It adds `|| [[ -n $_line ]]` to the while condition.

stripcom() {
        local _file=$1 _line

        [[ -s $_file ]] || return

        while read _line || [[ -n $_line ]]; do
                _line=${_line%%#*}
                [[ -n $_line ]] && print -r -- "$_line"
        done <$_file
}

pkg_info -m:
bash-4.4.23         GNU Bourne Again Shell
dash-0.5.10.2       Debian Almquist shell, POSIX-compliant
ksh93-20120801p1    AT&T Korn Shell
quirks-3.67         exceptions to pkg_add rules
yash-2.44p0         POSIX-compliant command line shell

dmesg:
OpenBSD 6.4-current (GENERIC) #527: Mon Dec 24 22:16:45 MST 2018
    [hidden email]:/usr/src/sys/arch/amd64/compile/GENERIC
real mem = 1056956416 (1007MB)
avail mem = 1015595008 (968MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.4 @ 0xf1950 (10 entries)
bios0: vendor SeaBIOS version "1.11.0p0-OpenBSD-vmm" date 01/01/2011
bios0: OpenBSD VMM
acpi at bios0 not configured
cpu0 at mainbus0: (uniprocessor)
cpu0: AMD Phenom(tm) II X2 560 Processor, 3300.56 MHz, 10-04-03
cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,SEP,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,SSE3,CX16,POPCNT,HV,NXE,MMXX,FFXSR,PAGE1GB,LONG,3DNOW2,3DNOW,LAHF,CMPLEG,EAPICSP,AMCR8,ABM,SSE4A,MASSE,3DNOWP,OSVW,IBS,SKINIT,ITSC
cpu0: 64KB 64b/line 2-way I-cache, 64KB 64b/line 2-way D-cache, 512KB 64b/line 16-way L2 cache, 6MB 64b/line 48-way L3 cache
cpu0: ITLB 32 4KB entries fully associative, 16 4MB entries fully associative
cpu0: DTLB 48 4KB entries fully associative, 48 4MB entries fully associative
pvbus0 at mainbus0: OpenBSD
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "OpenBSD VMM Host" rev 0x00
virtio0 at pci0 dev 1 function 0 "Qumranet Virtio RNG" rev 0x00
viornd0 at virtio0
virtio0: irq 3
virtio1 at pci0 dev 2 function 0 "Qumranet Virtio Storage" rev 0x00
vioblk0 at virtio1
scsibus1 at vioblk0: 2 targets
sd0 at scsibus1 targ 0 lun 0: <VirtIO, Block Device, > SCSI3 0/direct fixed
sd0: 51200MB, 512 bytes/sector, 104857600 sectors
virtio1: irq 5
virtio2 at pci0 dev 3 function 0 "Qumranet Virtio Network" rev 0x00
vio0 at virtio2: address fe:e1:bb:d1:2b:78
virtio2: irq 6
virtio3 at pci0 dev 4 function 0 "OpenBSD VMM Control" rev 0x00
vmmci0 at virtio3
virtio3: irq 7
isa0 at mainbus0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16450, no fifo
com0: console
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets
root on sd0a (b0f378d97a139028.a) swap on sd0b dump on sd0b

usbdevs:
usbdevs: no USB controllers found

pcidump:
Domain /dev/pci0:
 0:0:0: OpenBSD VMM Host
        0x0000: Vendor ID: 0b5d Product ID: 0666
        0x0004: Command: 0103 Status: 0000
        0x0008: Class: 06 Subclass: 00 Interface: 00 Revision: 00
        0x000c: BIST: 00 Header Type: 00 Latency Timer: 00 Cache Line Size: 00
        0x0010: BAR empty (00000000)
        0x0014: BAR empty (00000000)
        0x0018: BAR empty (00000000)
        0x001c: BAR empty (00000000)
        0x0020: BAR empty (00000000)
        0x0024: BAR empty (00000000)
        0x0028: Cardbus CIS: 00000000
        0x002c: Subsystem Vendor ID: 0b5d Product ID: 0000
        0x0030: Expansion ROM Base Address: 00000000
        0x0038: 00000000
        0x003c: Interrupt Pin: 00 Line: 00 Min Gnt: 00 Max Lat: 00
        0x0000: 06660b5d 00000103 06000000 00000000
        0x0010: 00000000 00000000 00000000 00000000
        0x0020: 00000000 00000000 00000000 00000b5d
        0x0030: 00000000 00000000 00000000 00000000
        0x0040: 00000000 00000000 00000000 00000000
        0x0050: 00000000 00000000 00000000 00000000
        0x0060: 00000000 00000000 00000000 00000000
        0x0070: 00000000 00000000 00000000 00000000
        0x0080: 00000000 00000000 00000000 00000000
        0x0090: 00000000 00000000 00000000 00000000
        0x00a0: 00000000 00000000 00000000 00000000
        0x00b0: 00000000 00000000 00000000 00000000
        0x00c0: 00000000 00000000 00000000 00000000
        0x00d0: 00000000 00000000 00000000 00000000
        0x00e0: 00000000 00000000 00000000 00000000
        0x00f0: 00000000 00000000 00000000 00000000
 0:1:0: Qumranet Virtio RNG
        0x0000: Vendor ID: 1af4 Product ID: 1005
        0x0004: Command: 0107 Status: 0000
        0x0008: Class: 08 Subclass: 80 Interface: 00 Revision: 00
        0x000c: BIST: 00 Header Type: 00 Latency Timer: 00 Cache Line Size: 00
        0x0010: BAR io addr: 0x00001000/0x1000
        0x0014: BAR empty (00000000)
        0x0018: BAR empty (00000000)
        0x001c: BAR empty (00000000)
        0x0020: BAR empty (00000000)
        0x0024: BAR empty (00000000)
        0x0028: Cardbus CIS: 00000000
        0x002c: Subsystem Vendor ID: 0b5d Product ID: 0004
        0x0030: Expansion ROM Base Address: 00000000
        0x0038: 00000000
        0x003c: Interrupt Pin: 01 Line: 03 Min Gnt: 00 Max Lat: 00
        0x0000: 10051af4 00000107 08800000 00000000
        0x0010: 00001001 00000000 00000000 00000000
        0x0020: 00000000 00000000 00000000 00040b5d
        0x0030: 00000000 00000000 00000000 00000103
        0x0040: 00000001 00000000 00000000 00000000
        0x0050: 00000010 00000000 00000000 00000000
        0x0060: 00000000 40000000 11ec711b 00000013
        0x0070: 00000000 00000000 00000000 00000000
        0x0080: 00000000 00000000 00000000 00000000
        0x0090: 00000000 00000000 00000000 00000000
        0x00a0: 00000000 00000000 00000000 00000000
        0x00b0: 00000000 00000000 00000000 00000000
        0x00c0: 00000000 00000000 00000000 00000000
        0x00d0: 00000000 00000000 00000000 00000000
        0x00e0: 00000000 00000000 00000000 00000000
        0x00f0: 00000000 00000000 00000000 00000000
 0:2:0: Qumranet Virtio Storage
        0x0000: Vendor ID: 1af4 Product ID: 1001
        0x0004: Command: 0107 Status: 0000
        0x0008: Class: 01 Subclass: 00 Interface: 00 Revision: 00
        0x000c: BIST: 00 Header Type: 00 Latency Timer: 00 Cache Line Size: 00
        0x0010: BAR io addr: 0x00002000/0x1000
        0x0014: BAR empty (00000000)
        0x0018: BAR empty (00000000)
        0x001c: BAR empty (00000000)
        0x0020: BAR empty (00000000)
        0x0024: BAR empty (00000000)
        0x0028: Cardbus CIS: 00000000
        0x002c: Subsystem Vendor ID: 0b5d Product ID: 0002
        0x0030: Expansion ROM Base Address: 00000000
        0x0038: 00000000
        0x003c: Interrupt Pin: 01 Line: 05 Min Gnt: 00 Max Lat: 00
        0x0000: 10011af4 00000107 01000000 00000000
        0x0010: 00002001 00000000 00000000 00000000
        0x0020: 00000000 00000000 00000000 00020b5d
        0x0030: 00000000 00000000 00000000 00000105
        0x0040: 00000001 00000000 00000000 00000000
        0x0050: 00000010 00000000 00000000 00000000
        0x0060: 00000000 30000000 11ec7127 00000013
        0x0070: 00000000 00000000 00000000 00000000
        0x0080: 00000000 00000000 00000000 00000000
        0x0090: 00000000 00000000 13fbf253 00000013
        0x00a0: 00000000 00000000 00000000 00000000
        0x00b0: 00000000 00000000 00000000 00000000
        0x00c0: 00000000 00000000 00000000 00000000
        0x00d0: 00000000 00000000 00000000 00000000
        0x00e0: 00000000 00000000 00000000 00000000
        0x00f0: 00000000 00000000 00000000 00000000
 0:3:0: Qumranet Virtio Network
        0x0000: Vendor ID: 1af4 Product ID: 1000
        0x0004: Command: 0107 Status: 0000
        0x0008: Class: 08 Subclass: 80 Interface: 00 Revision: 00
        0x000c: BIST: 00 Header Type: 00 Latency Timer: 00 Cache Line Size: 00
        0x0010: BAR io addr: 0x00003000/0x1000
        0x0014: BAR empty (00000000)
        0x0018: BAR empty (00000000)
        0x001c: BAR empty (00000000)
        0x0020: BAR empty (00000000)
        0x0024: BAR empty (00000000)
        0x0028: Cardbus CIS: 00000000
        0x002c: Subsystem Vendor ID: 0b5d Product ID: 0001
        0x0030: Expansion ROM Base Address: 00000000
        0x0038: 00000000
        0x003c: Interrupt Pin: 01 Line: 06 Min Gnt: 00 Max Lat: 00
        0x0000: 10001af4 00000107 08800000 00000000
        0x0010: 00003001 00000000 00000000 00000000
        0x0020: 00000000 00000000 00000000 00010b5d
        0x0030: 00000000 00000000 00000000 00000106
        0x0040: 00000001 00000000 00000000 00000000
        0x0050: 00000010 00000000 00000000 00000000
        0x0060: 00000000 90000000 11ec712c 00000013
        0x0070: 00000000 00000000 00000000 00000000
        0x0080: 00000000 00000000 00000000 00000000
        0x0090: 00000000 00000000 14336d28 00000013
        0x00a0: 00000000 00000000 00000000 00000000
        0x00b0: 00000000 00000000 00000000 00000000
        0x00c0: 00000000 00000000 00000000 00000000
        0x00d0: 00000000 00000000 00000000 00000000
        0x00e0: 00000000 00000000 00000000 00000000
        0x00f0: 00000000 00000000 00000000 00000000
 0:4:0: OpenBSD VMM Control
        0x0000: Vendor ID: 0b5d Product ID: 0777
        0x0004: Command: 0107 Status: 0000
        0x0008: Class: 07 Subclass: 80 Interface: 00 Revision: 00
        0x000c: BIST: 00 Header Type: 00 Latency Timer: 00 Cache Line Size: 00
        0x0010: BAR io addr: 0x00004000/0x1000
        0x0014: BAR empty (00000000)
        0x0018: BAR empty (00000000)
        0x001c: BAR empty (00000000)
        0x0020: BAR empty (00000000)
        0x0024: BAR empty (00000000)
        0x0028: Cardbus CIS: 00000000
        0x002c: Subsystem Vendor ID: 0b5d Product ID: ffff
        0x0030: Expansion ROM Base Address: 00000000
        0x0038: 00000000
        0x003c: Interrupt Pin: 01 Line: 07 Min Gnt: 00 Max Lat: 00
        0x0000: 07770b5d 00000107 07800000 00000000
        0x0010: 00004001 00000000 00000000 00000000
        0x0020: 00000000 00000000 00000000 ffff0b5d
        0x0030: 00000000 00000000 00000000 00000107
        0x0040: 00000001 00000000 00000000 00000000
        0x0050: 00000010 00000000 00000000 00000000
        0x0060: 00000000 b0000000 11ec713e 00000013
        0x0070: 00000000 00000000 00000000 00000000
        0x0080: 00000000 00000000 00000000 00000000
        0x0090: 00000000 00000000 00000000 00000000
        0x00a0: 00000000 00000000 00000000 00000000
        0x00b0: 00000000 00000000 00000000 00000000
        0x00c0: 00000000 00000000 00000000 00000000
        0x00d0: 00000000 00000000 00000000 00000000
        0x00e0: 00000000 00000000 00000000 00000000
        0x00f0: 00000000 00000000 00000000 00000000

acpidump:

Reply | Threaded
Open this post in threaded view
|

Re: rc(8) ignores last line without newline of *.conf

Ted Unangst-6
George Koehler wrote:
> stripcom() in /etc/rc uses `while read _line ; do ... done`
> to read these files, but `read _line` exits 1 when the last line is
> without a newline.  This behavior in sh and ksh is consistent with
> bash, dash, ksh93, and yash:

http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206

3.206 Line
A sequence of zero or more non- <newline> characters plus a terminating
<newline> character.

A line without a newline is not a line.