Bug 265399

Summary: /bin/sh: improve echo -e builtin
Product: Base System Reporter: Helge Oldach <freebsd>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed Not A Bug    
Severity: Affects Many People CC: jilles, rb
Priority: ---    
Version: 13.1-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
naive fix to echo -n -e
none
235434: naive fix to echo -n -e
none
naive fix to echo -n -e none

Description Helge Oldach 2022-07-23 06:40:37 UTC
Created attachment 235434 [details]
naive fix to echo -n -e

The "echo" builtin has an (undocumented) escape sequence expansion feature, called for by the '-e' flag. Unfortunately that collides with the (documented) '-n' flag, as the builtin only checks the first flag on the command line.

The patch adds a naive fix to this, making this snippet DTRT:

echo -n -e '\a'

A proper fix should probably employ getopt.
Comment 1 Helge Oldach 2022-07-23 06:42:11 UTC
Created attachment 235435 [details]
235434: naive fix to echo -n -e
Comment 2 Helge Oldach 2022-07-23 06:44:32 UTC
Created attachment 235436 [details]
naive fix to echo -n -e
Comment 3 Jilles Tjoelker freebsd_committer freebsd_triage 2022-08-19 20:19:23 UTC
It is indeed unfortunate that /bin/echo and /bin/sh's echo builtin behave differently, but it is documented (sh(1) describes the echo builtin, and echo(1) warns that shell builtins may differ) and changing it now will cause breakage for little benefit.

For example, the existing echo builtin allows 'echo -n STRING' for any string, while the proposed patch breaks this for the string "-e".

Also note that -ne can be replaced by -e and adding \c to the last operand.

An alternative is replacing echo use with an appropriate printf command.
Comment 4 Bob Bishop 2022-08-19 20:34:40 UTC
Just to observe that other builtins have similar oddities, see eg: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263901
Comment 5 Helge Oldach 2022-08-20 09:20:43 UTC
(In reply to Jilles Tjoelker from comment #3)
> For example, the existing echo builtin allows 'echo -n STRING' for any string, while the proposed patch breaks this for the string "-e".

True, so we shouldn't loop over the arguments but only validate the first argument against being a string of options and check for '-en' or '-ne'. This will also keep it in line with other built-ins.

> Also note that -ne can be replaced by -e and adding \c to the last operand.

True as well, but then the '-e' option and the '\\' detection logic could be removed as it's undocumented anyhow...