puts sets errno, but manpage doesn't mention it
From: Edwin Török <hidden>
Date: 2025-04-22 23:02:20
Hello,
The manpage for puts [1] doesn't mention errno.
Therefore for a long time I've avoided looking at errno when any of the
stdio functions fail (errno could've been leftover from a previous
call, or some internal, potentially unrelated and handled error).
What the manpage says is accurate when looking at the C23 standard [2],
however on POSIX systems one can do better!
Both POSIX 2008 [3] and POSIX 2024 [4] say that 'puts' sets 'errno',
and that this is an extension to the C standard.
The FreeBSD manpage says this too [5], although it doesn't mention that
this is an extension.
It would be useful if the Linux manpages got updated with information
about which stdio functions set errno, and that setting errno is a
POSIX extension (I'm hoping that POSIX is consistent and all stdio
functions would set errno, but I haven't checked in detail).
Should I send a patch that attempts to update the manpages, or do we
need to check with the libc mailing list whether this is in fact
guaranteed? (e.g. if they've implemented it according to the Linux
manpage, instead of the POSIX standard, then errno may not be set in
all cases that it should...)
I've also tested whether this is true in practice, and the following
program prints a 'Broken pipe' message on 3 libc implementations on
Fedora 42: GNU libc 2.41, musl-libc 1.2.5, dietlibc 0.34, when run as
'./x | dd count=5 of=/dev/null'
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main(void)
{
signal(SIGPIPE, SIG_IGN);
while(puts("foo") != EOF);
perror("puts");
return EXIT_FAILURE;
}
Or perhaps even simpler, this prints 'No such file or directory':
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *f = fopen("/nonexistent", "r");
if (!f) {
perror("fopen");
return EXIT_FAILURE;
}
fclose(f);
return EXIT_SUCCESS;
}
P.S. I discovered the possibility that puts may set errno while reading
(the excellent!) book "Modern C"
https://gustedt.gitlabpages.inria.fr/modern-c/
[1]: https://www.man7.org/linux/man-pages/man3/puts.3.html
[2]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf from
https://www.c-language.org/
[3]:
https://pubs.opengroup.org/onlinepubs/9699919799/functions/puts.html
[4]:
https://pubs.opengroup.org/onlinepubs/9799919799/functions/puts.html
[5]: https://man.freebsd.org/cgi/man.cgi?fputs
Best regards,
--Edwin