I am using a system call and in case it fails, I need to do different things for different errnos.
I need to write code that looks something like this:
int res;
res = systemCall();
if (res == -1)
{
if (errno == ENOMSG)
{
doSomething();
}
else
{
doSomethingElse();
}
}
perror doesn't help, because it only prints the value.
As for strerro - if it is what I need, I am not suer how to use it, because here it says that the actual string is not the same as the error. Quote from the man page: "(For example, if errnum is EINVAL, the returned description will be "Invalid argument")".
I am using Linux. System calls: msgsend and msgrcv (https://linux.die.net/man/2/msgrcv). I am not sure what C libraries you are asking about.
I see I didn't explain myself well.
Is the statement if (errno == ENOMSG) valid? Is there such a variable errno? Basically my question is: What should go in the if
statement in order to test the errno?
I assume you are using Linux, and I suppose that you don't directly use the system call, but some of the (simple) wrappers (from your C library) listed in syscalls(2). Notice that some weird system calls are not wrapped by the C library (a well known example of unwrapped system call would be sigreturn(2) which you probably should never use). Quite often the C library is GNU glibc, but it might be musl-libc etc. Notice also that kernel raw system calls have different calling conventions than ordinary C function (so in practice a libc wrapper is required, and is in charge of dealing with errno
). Notice also that errno(3) is generally a macro (almost behaving as some variable).
The msgrcv(2) man page documents that errno
could be one of E2BIG
, EACCES
, EFAULT
... ENOMSG
, ENOSYS
... (refer to that man page to get the list of all possible errors).
So you would code something like
ssize_t siz = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
if (siz<0) { // msgrcv failed and has set errno
if (errno == ENOMSG)
dosomething();
else if (errno == EAGAIN)
dosomethingelse();
/// etc
else {
syslog(LOG_DAEMON|LOG_ERR, "msgrcv failure with %s\n",
strerror(errno));
exit(EXIT_FAILURE);
};
};
Is the statement
if (errno == ENOMSG)
.... valid?
Yes it is; you want to test errno
only after some system call failure (e.g. when siz<0
).
Is there such a variable
errno
?
Not any more. Please read carefully errno(3) documentation. You should not declare extern int errno;
(this was possible in the 1980s, not in 21st century) but you should always #include <errno.h>
and use errno
as if it was a variable, but it is almost always some macro (whose definition appears in /usr/include/bits/errno.h
which is included by /usr/include/errno.h
).
BTW, SysV-style facilities tend to become obsolete and are not always available. I recommend using POSIX message queues facilities, read mq_overview(7).
You might want to read the freely downloadable Advanced Linux Programming (an old book; you can buy something better & newer) and/or all the man pages reachable from intro(2) & syscalls(2) & intro(3).