Hi Jason, On 2026-07-07T06:54:49-0400, Jason Yundt wrote: > On Mon Jul 6, 2026 at 11:27 AM EDT, Alejandro Colomar wrote: > > Hi Jason, > > > > On 2026-07-06T10:26:20-0400, Jason Yundt wrote: > >> Before this change, environ(7) said this: > >> > >> > By convention, the strings in environ have the form "name=value". The > >> > name is case-sensitive and may not contain the character "=". The > >> > value can be anything that can be represented as a string. The name > >> > and the value may not contain an embedded null byte ('\0'), since this > >> > is assumed to terminate the string. > >> > >> That description has a few problems: > >> > >> 1. It talks about ‘the character "="’, but it doesn’t specify what > >> character encoding would be used to represent that character. Two > >> different character encodings could represent that same “=” character > >> using two different bytes (or even sequences of bytes). > > > > POSIX says that '=' is part of the portable character set. > > I don’t really think that '=' being a part of the POSIX Portable > Character Set matters here. For one thing, environ(7) doesn’t mention > the POSIX Portable Character Set at all. Even if it did, the POSIX > Portable Character Set does not specify that the character encoding of > '=' is 0x3D so it wouldn’t really help us. Oh, I thought POSIX required ASCII-compatible encoding, but it seems I was likely wrong. > > Do we really need to care about the value of '='? > > There needs to be a specification somewhere that says what the character > encoding would be. You can’t represent any characters on a computer > without choosing a character encoding. After reading the POSIX specification of putenv(3), I have some doubts. putenv(3) is specified to use '=', not 0x3D. Thus, if working on a system that uses a different value for '=', it seems that the specification says that environ will still contain '=' in that encoding, regardless of the value it has. In fact, reading the musl and glibc implementations, they use '=', not 0x3D (maybe those libc implementations don't support encodings of '=' that don't use 0x3D; I don't know). Have a lovely day! Alex > > Is this really possible? > > Definitely. Anyone can create whatever character encoding that they > want to. There’s nothing that would force people to always encode the > “=” character as 0x3D in every character encoding that they create. > There are already character encodings in existence where “=” is not > encoded as a 0x3D byte. For example, “=” is encoded as a 0x7E byte in > EBCDIC [1]. > > > > >> 2. It mentions that ‘The name is case-sensitive and may not contain the > >> character "=".’ It doesn’t clearly say what what is allowed to be in > >> a name. It only says that those two things are explicitly > >> disallowed. > > > > Anything else is allowed, obviously. > > I don’t think that the current wording clearly specifies what is allowed > to be in a name. It’s definitely not obvious to me. > > > > >> This change fixes those two problems. For the first problem, this > >> change makes it so that the description is all about bytes, not > >> characters. Describing the format in terms of bytes allows us to > >> sidestep the question of character encoding entirely. Additionally, it > >> is more accurate to describe strings in environ as being sequences of > >> bytes instead of sequences of characters. Both the name and value of an > >> environment variable could be sequences of bytes that don’t contain any > >> characters at all. > >> > >> For the second problem, this change clarifies that the name of an > >> environment variable can contain any byte except for 0x3D. It also > >> clarifies that while it’s OK for environment variable values to be > >> empty, it’s not OK for environment variable names to be empty. > >> > >> Additionally, this change replaces "=" with '='. In the C programming > >> language, "=" refers to two bytes: one for the equals character plus one > >> for the terminating null byte. In the C programming language, '=' > >> refers to a single byte. In this particular instance, we’re talking > >> about a single byte, so it’s better to use '='. Using '=' also makes > >> environ(7) more internally consistent. Before this change, environ(7) > >> used '\0' and "=". This change makes it so that environ(7) uses '\0' > >> and '='. > >> > >> I was able to obtain obtain the information that I needed in order to > >> create this change by writing a test program. You can find the test > >> program here [1]. Additionally, I got the information about the setenv(3) > >> and unsetenv(3) functions from their man pages (specifically, the parts > >> of their man pages that talk about EINVAL). > >> > >> [1]: > > > > Please include the C program in the commit message so that it can be > > compiled and run easily, without having to understand Nix stuff. > > OK. I created a shorter version of the test code that’s available at > that link. I have embedded the new shorter version in the commit > message for the second version of this patch. > > > > >> > >> Signed-off-by: Jason Yundt > >> --- > >> man/man7/environ.7 | 23 +++++++++++++++++------ > >> 1 file changed, 17 insertions(+), 6 deletions(-) > >> > >> diff --git a/man/man7/environ.7 b/man/man7/environ.7 > >> index 31a69017cf75..bf5726e32429 100644 > >> --- a/man/man7/environ.7 > >> +++ b/man/man7/environ.7 > >> @@ -28,12 +28,23 @@ .SH DESCRIPTION > >> .I environ > >> have the form > >> .RI \[dq] name\f[B]=\f[]value \[dq]. > >> -The name is case-sensitive and may not contain > >> -the character > >> -.RB \[dq] = \[dq]. > >> -The value can be anything that can be represented as a string. > >> -The name and the value may not contain an embedded null byte (\[aq]\[rs]0\[aq]), > >> -since this is assumed to terminate the string. > > > > I liked the old wording about the terminating null byte more. > > OK. In the second version of this patch, I brought back the old wording > about the terminating null byte. > > > > >> +The name is case-sensitive > >> +and may contain any byte > >> +other than null (\[aq]\[rs]0\[aq]) and 0x3D (the > >> +.BR ascii (7) > >> +.RB \[aq] = \[aq] > >> +character). > >> +The name must be at least one byte long, > >> +or else programs will not be able to manipulate it using the > >> +.BR setenv (3) > >> +or > >> +.BR unsetenv (3) > >> +functions. > >> +Immediately after the name, there should be a 0x3D byte. > > > > What should readers interpret of 'should'? Is it a recommendation or an > > obligation? This is unclear wording. > > OK. In the second version of this patch, I replaced the word “should” > with the word “must”. > > > > >> +Immediately after the 0x3D byte is the value. > > > > This seems redundant with the sentence that shows the format > > "name=value". > > OK. In the second version of this patch, I got rid of that sentence. > > > > >> +The value may contain any byte except for null. > > > > What is the null value? You mean an empty string? Or you mean embedded > > null bytes in the string? Please clarify. > > When I wrote “The value may contain any byte except for null.”, I meant > “The value may contain any byte except for the null byte.” That being > said, I have removed that sentence from the second version of this > patch. > > > > >> +The value may be zero bytes long. > > > > That's commonly known as an empty string. > > > > I think saying that the value can be anything that can be represented as > > a string is fine (the old wording). > > OK. In the second version of this patch, I got rid of the sentence “The > value may be zero bytes long.” > > > > >> +Immediately after the value, there must be a terminating null byte. > > > > The fact that it's a string already implied this. > > OK. In the second version of this patch, I got rid of the sentence > “Immediately after the value, there must be a terminating null byte.” > > > > > > > Have a lovely day! > > Alex > > > >> .P > >> Environment variables may be placed in the shell's environment by the > >> .I export > >> > >> Range-diff against v0: > >> -: ------------ > 1: d5b0d9b86029 man/man7/environ.7: Fix underspecification of "name=value" strings > >> -- > >> 2.54.0 > >> > >> > > [1]: --