Souvent méconnues, ces fonctions sont pourtant présentes partout (“non-standard BSD extensions” dit le man sous Linux) et elles simplifient pas mal la vie..
#include <err.h> void err(int eval, const char *fmt, ...); void errx(int eval, const char *fmt, ...); void warn(const char *fmt, ...); void warnx(const char *fmt, ...);
Les 2 premières affichent un message d'erreur printf-style, et appellent exit() avec la valeur passée en 1er paramêtre. Les 2 dernières affichent juste le message d'erreur. De plus, err() et warn() affichent le message d'erreur standard correspondant a la dernière valeur de errno via strerror().
$cat l.c #include <err.h> #include <stdio.h> int main() { int fd = 0; char str[] = "ZOMG"; if ((fd = open("/foo/bar", "r")) == -1) warn("%s, i can has warning ? ", str); if (3 != 4) warnx("%s, 3 is not 4 !", str); if (close(fd) == -1) err(1, "%s, i can has error ? ", str); return 0; /* NOTREACHED */ }
$gcc l.c -o l $./l l: ZOMG, i can has warning ? : No such file or directory l: ZOMG, 3 is not 4 ! l: ZOMG, i can has error ? : Bad file descriptor $echo $? 1
Les *BSD dispose de codes de retour bien définis disponibles dans <sysexits.h> ou sysexits(3). Ces codes sont des codes d'exit prédéfinis que l'on a l'habitude de traiter nous même en général… C'est une spécificité des *BSD, bien que présent sur OpenSolaris (voir ici).
Et voilà une manière de plus pour écrire du code BSD compliant.
cat toto.c #include <stdio.h> #include <stdlib.h> #include <sysexits.h> #include <unistd.h> extern char *__progname; static int usage(void) { fprintf(stderr,"usage: %s <arg1> \n", __progname); return EX_USAGE; } int main(int argc, char *argv[]) { int fd, ch; while ((ch = getopt(argc, argv, "h")) != -1) { switch (ch) { case 'h': default: return usage(); } } argc -= optind; argv += optind; if (argc != 0) return usage(); if (fd = open("/tmp/baz",'r') == -1) return EX_OSFILE; return EX_OK; }
% touch /tmp/baz % make toto cc -O2 -fstrict-aliasing -pipe -march=pentium-m toto.c -o toto % toto % echo $? 0 toto -h usage: toto <arg1> % echo $? 64 % rm -rf /tmp/baz % toto % echo $? 72