This repository has been archived by the owner on Sep 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsys_err_init.c
64 lines (54 loc) · 2.3 KB
/
sys_err_init.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <stdlib.h>
#include <errno.h>
/* Reporting integer errno values is not nice, even in init, but linking
sterror() from libc brings in the whole syserrlist. This is while init
itself can only produce a handful of different errno values.
The idea is to choose the middle ground, providing readable messages
for expected errors and printing anything unexpected as a integer.
Getting something unexpected in init is already a sign of a big trouble,
so making the user go on and use strerror(3)/perror(1)/etc to get
the message should not make things much worse.
Finally, I don't like verbose messages like "No such file or directory",
especially when they aren't accompanied by respective error code.
Most man pages only list symbolic constants, ENOENT in this case, with
a syscall-specific description, so searching for "No such file ..."
is pointless. Showing symbolic constants, on the other hand, makes it
easy to read both errno(3) and relevant section 2 pages
(when it's clear from the message which syscall failed, that is) */
/* The whole symbol-or-int thing only works via sys_printf %m.
dietlibc printf can't handle NULL return properly, and neither glibc
nor musl printfs use strerror internally. */
/* For a long time this has been a switch(err), but it turns out gcc generates
relatively large jump table here. The same does not seem to happen with
telinit and run errlists, strange. */
struct errlist {
unsigned char err;
char name[11]; /* EADDRINUSE is 10+1 bytes long */
} errlist[] = {
#define r(e) { e, #e }
r(ENOENT), /* open */
r(ELOOP), /* open, unlikely */
r(EADDRINUSE), /* bind */
r(ENFILE), /* open, socket, accept */
r(ENOSPC), /* open(..., O_CREAT) for process logging */
r(EPIPE), /* sendmsg */
r(ENOMEM), /* mmap and a buch of other calls */
r(EINTR), /* poll, unlikely for other syscalls */
r(EINVAL), /* generic, unlikely */
r(EAGAIN), /* fork */
r(EACCES), /* execve */
r(ENOEXEC), /* execve */
r(ENOTDIR), /* execve */
r(E2BIG), /* execve, very large service file */
r(EIO), /* unlikely, bad news */
r(EPERM) /* reboot and some other calls */
};
#define endof(a) (a + sizeof(a)/sizeof(*a))
char* strerror(int err)
{
struct errlist* p;
for(p = errlist; p < endof(errlist); p++)
if((int)p->err == err)
return p->name;
return NULL;
}