In general, you should detect errors by checking return values, and use errno only
to distinguish among the various causes of an error, such as ``File not found''
or ``Permission denied''. (Typically, you use perror or strerror to print
these discriminating error messages.) It's only necessary to detect errors
with errno when a function does not have a unique, unambiguous, out-of-band error
return (i.e. because all of its possible return values are valid; one example is
atoi). In these cases (and in these cases only; check the documentation to be sure
whether a function allows this), you can detect errors by setting errno to 0, calling
the function, then testing errno. (Setting errno to 0 first is important, as no
library function ever does that for you.)
To make error messages useful, they should include all relevant information. Besides
the strerror text derived from errno, it may also be appropriate to print the name
of the program, the operation which failed (preferably in terms which will be meaningful
to the user), the name of the file for which the operation failed, and, if some
input file (script or source file) is being read, the name and current line number
of that file.