This provides a reliable and portable way to
test whether an environment variable is defined.
(Of course, if you are using glibc you may get
false positives if you include a = in the query.)
Signed-off-by: Mattias Andrée <maandree@kth.se>
reproduce: touch -t 12345678 mytralala
would only give a warning and use uninitialised time values. The proper
way is to treat it as an error. Clear the "struct tm" and kill some lines
just in case.
In eb9bda8787, a bug was introduced in the
handling of -1 return values from getline. Since the type of the len
field in struct line is unsigned, the break condition was never true.
This caused sort -c to never succeed.
A bug was introduced in the NUL support refactor leading to
the length of the previous line only being saved if the
previous line was shorter than the current line. If triggered
this lead to copying too much data into the previous line buffer.
Behavior before:
printf '1234\na\n' | ./uniq
1234
a
4
Behavior after:
printf '1234\na\n' | ./uniq
1234
a
because we can't call the syslog-syscall without becoming unportable.
The syslog() libc-function does not accept a length though, so we're
fucked. Anyway, let's carry on.
Thing is, we don't yet have an updated utflen() ready for use. Although
prints the lines completely, it does not add a proper spacing between
each entry. This will be fixed later.
For sort(1) we need memmem(), which I imported from OpenBSD.
Inside sort(1), the changes involved working with the explicit lengths
given by getlines() earlier and rewriting some of the functions.
Now we can handle NUL-characters in the input just fine.
Forgot that in case there is a second argument given with -s you
probably want to have your characters substituted.
I changed it so that shortly before "deploying" we check if the
"to be written"-Rune is equal to the last Rune, and proceed as
needed.
Our libutil concat() always uses a buffer for input wich is obviously
not compatible with unbuffered io. Here is a local uconcat() which
naively copies input to stdout char by char.
Use strtol and strtoul respectively for d, i and o, u, x, X conversions.
This way we can convert other bases than 10, which strtonum doesn't
provide.
Also don't exit on conversion error but display a warning, set a return
error code, and continue.
The assumption of NUL-terminated strings is actually quite a good one in
most cases. You don't have to worry about paths, because they may not
contain NUL.
Same applies to arguments passed to you. Unless you have to unescape,
there is no way for you to receive a NUL.
There are two important exceptions though, and it's important that we
address them, or else we get unexpected behaviour:
1) All tools using unescape() have to be strict about delimlen.
Else they end up for instance unescaping
'\\0abc'
to
'\0abc',
which in C's string-vision is an empty string.
2) All tools doing line wrenching and putting them out
again as lines again.
puts() will cut each line containing NULs off at the first
occurence.
strmem() was not very well thought out. The thing is the following:
If the string contains a zero character, we want to match it, and not
stop right there in place.
The "real" solution is to use memmem() where needed and replace all
functions that assume zero-terminated-strings from standard input, which
could lead to early string-breakoffs.
This requires a strict tracking of string lengths.
We want our delimiters to also contain 0 characters and have them
handled gracefully.
To accomplish this, I wrote a function strmem(), which looks for a
certain, arbitrarily long memory subset in a given string.
memmem() is a GNU extension and forces you to call strlen every time.