thanks to ISC (Interactive) Unix, we now know a few samples of errnos

that get used, plus one for the realpath-1 regression test; also make
sys_siglist_decl detection nicer and poison strerror() with non-const
return value ifdef DEBUG, make it always const
This commit is contained in:
tg 2012-12-17 23:18:11 +00:00
parent 006d2c3c02
commit 12c662b6e2
10 changed files with 151 additions and 76 deletions

View File

@ -1,5 +1,5 @@
#!/bin/sh
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.601 2012/12/17 22:57:49 tg Exp $'
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.602 2012/12/17 23:18:01 tg Exp $'
#-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012
@ -1527,7 +1527,7 @@ else
#define EXTERN
#define MKSH_INCLUDES_ONLY
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.601 2012/12/17 22:57:49 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.602 2012/12/17 23:18:01 tg Exp $");
int main(void) { printf("Hello, World!\n"); return (0); }
EOF
case $cm in
@ -1779,6 +1779,12 @@ ac_test strerror <<-'EOF'
int main(int ac, char *av[]) { return (*strerror(*av[ac])); }
EOF
ac_test sys_errlist '!' strerror 0 "the sys_signame[] array and sys_nerr" <<-'EOF'
extern int sys_nerr;
extern char *sys_errlist[];
int main(void) { return (*sys_errlist[sys_nerr - 1]); }
EOF
ac_test strlcpy <<-'EOF'
#include <string.h>
int main(int ac, char *av[]) { return (strlcpy(*av, av[1],
@ -1805,11 +1811,15 @@ ac_test '!' revoke_decl revoke 1 'if revoke() does not need to be declared' <<-'
long revoke(void); /* this clashes if defined before */
int main(void) { return ((int)revoke()); }
EOF
ac_test '!' sys_siglist_decl sys_siglist 1 'if sys_siglist[] does not need to be declared' <<-'EOF'
ac_test sys_errlist_decl sys_errlist 0 "for declaration of sys_errlist[] and sys_nerr" <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
extern int sys_siglist[5][5][5][5][5]; /* this clashes happily */
int main(void) { return (sys_siglist[0][0][0][0][0]); }
int main(void) { return (*sys_errlist[sys_nerr - 1]); }
EOF
ac_test sys_siglist_decl sys_siglist 1 'for declaration of sys_siglist[]' <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
int main(void) { return (sys_siglist[0][0]); }
EOF
CC=$save_CC; LDFLAGS=$save_LDFLAGS; LIBS=$save_LIBS

4
eval.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.131 2012/12/08 18:30:29 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.132 2012/12/17 23:18:03 tg Exp $");
/*
* string expansion
@ -1325,7 +1325,7 @@ comsub(Expand *xp, const char *cp, int fn MKSH_A_UNUSED)
maketemp(ATEMP, TT_FUNSUB, &tf);
if (!tf->shf) {
errorf("can't %s temporary file %s: %s",
"create", tf->tffn, strerror(errno));
"create", tf->tffn, cstrerror(errno));
}
/* save stdout and make the temporary file it */
ofd1 = savefd(1);

20
exec.c
View File

@ -23,7 +23,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.108 2012/12/04 01:18:27 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.109 2012/12/17 23:18:03 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
@ -461,7 +461,7 @@ execute(struct op * volatile t,
if (rv == ENOEXEC)
scriptexec(t, (const char **)up);
else
errorf("%s: %s", s, strerror(rv));
errorf("%s: %s", s, cstrerror(rv));
}
Break:
exstat = rv & 0xFF;
@ -688,14 +688,14 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
rv = (tp->u2.errnov == ENOENT) ? 127 : 126;
warningf(true, "%s: %s %s: %s", cp,
"can't find", "function definition file",
strerror(tp->u2.errnov));
cstrerror(tp->u2.errnov));
break;
}
if (include(tp->u.fpath, 0, NULL, false) < 0) {
rv = errno;
warningf(true, "%s: %s %s %s: %s", cp,
"can't open", "function definition file",
tp->u.fpath, strerror(rv));
tp->u.fpath, cstrerror(rv));
rv = 127;
break;
}
@ -789,7 +789,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
} else {
rv = 126;
warningf(true, "%s: %s: %s", cp, "can't execute",
strerror(tp->u2.errnov));
cstrerror(tp->u2.errnov));
}
break;
}
@ -924,7 +924,7 @@ scriptexec(struct op *tp, const char **ap)
execve(args.rw[0], args.rw, cap.rw);
/* report both the programme that was run and the bogus interpreter */
errorf("%s: %s: %s", tp->str, sh, strerror(errno));
errorf("%s: %s: %s", tp->str, sh, cstrerror(errno));
}
int
@ -1363,7 +1363,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
warningf(true, "can't %s %s: %s",
iotype == IODUP ? "dup" :
(iotype == IOREAD || iotype == IOHERE) ?
"open" : "create", cp, strerror(u));
"open" : "create", cp, cstrerror(u));
}
return (-1);
}
@ -1393,7 +1393,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
warningf(true, "%s %s %s",
"can't finish (dup) redirection",
snptreef(NULL, 32, "%R", &iotmp),
strerror(eno));
cstrerror(eno));
if (iotype != IODUP)
close(u);
return (-1);
@ -1486,7 +1486,7 @@ herein(const char *content, int sub, char **resbuf)
if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY, 0)) < 0) {
i = errno;
warningf(true, "can't %s temporary file %s: %s",
!shf ? "create" : "open", h->tffn, strerror(i));
!shf ? "create" : "open", h->tffn, cstrerror(i));
if (shf)
shf_close(shf);
/* special to iosetup(): don't print error */
@ -1503,7 +1503,7 @@ herein(const char *content, int sub, char **resbuf)
i = errno;
close(fd);
warningf(true, "can't %s temporary file %s: %s",
"write", h->tffn, strerror(i));
"write", h->tffn, cstrerror(i));
/* special to iosetup(): don't print error */
return (-2);
}

32
funcs.c
View File

@ -38,7 +38,7 @@
#endif
#endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.234 2012/12/17 23:09:15 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.235 2012/12/17 23:18:04 tg Exp $");
#if HAVE_KILLPG
/*
@ -253,7 +253,7 @@ c_pwd(const char **wp)
p = NULL;
if (!p && !(p = allocd = ksh_get_wd())) {
bi_errorf("%s: %s", "can't determine current directory",
strerror(errno));
cstrerror(errno));
return (1);
}
shprintf("%s\n", p);
@ -1379,7 +1379,7 @@ c_kill(const char **wp)
rv = 1;
} else {
if (mksh_kill(n, sig) < 0) {
bi_errorf("%s: %s", p, strerror(errno));
bi_errorf("%s: %s", p, cstrerror(errno));
rv = 1;
}
}
@ -1726,7 +1726,7 @@ c_dot(const char **wp)
return (1);
}
if ((file = search_path(cp, path, R_OK, &errcode)) == NULL) {
bi_errorf("%s: %s", cp, strerror(errcode));
bi_errorf("%s: %s", cp, cstrerror(errcode));
return (1);
}
@ -1743,7 +1743,7 @@ c_dot(const char **wp)
}
if ((i = include(file, argc, argv, false)) < 0) {
/* should not happen */
bi_errorf("%s: %s", cp, strerror(errno));
bi_errorf("%s: %s", cp, cstrerror(errno));
return (1);
}
return (i);
@ -1834,7 +1834,7 @@ c_read(const char **wp)
#if HAVE_SELECT
case 't':
if (parse_usec(builtin_opt.optarg, &tv)) {
bi_errorf("%s: %s '%s'", Tsynerr, strerror(errno),
bi_errorf("%s: %s '%s'", Tsynerr, cstrerror(errno),
builtin_opt.optarg);
return (2);
}
@ -1916,7 +1916,7 @@ c_read(const char **wp)
rv = 1;
goto c_read_out;
default:
bi_errorf("%s: %s", Tselect, strerror(errno));
bi_errorf("%s: %s", Tselect, cstrerror(errno));
rv = 2;
goto c_read_out;
}
@ -2710,7 +2710,7 @@ c_mknod(const char **wp)
goto c_mknod_failed;
} else if (mkfifo(argv[0], mode)) {
c_mknod_failed:
bi_errorf("%s: %s", argv[0], strerror(errno));
bi_errorf("%s: %s", argv[0], cstrerror(errno));
c_mknod_err:
rv = 1;
}
@ -3610,7 +3610,7 @@ set_ulimit(const struct limits *l, const char *v, int how)
if (errno == EPERM)
bi_errorf("%s exceeds allowable %s limit", v, l->name);
else
bi_errorf("bad %s limit: %s", l->name, strerror(errno));
bi_errorf("bad %s limit: %s", l->name, cstrerror(errno));
return (1);
}
@ -3653,7 +3653,7 @@ c_rename(const char **wp)
bi_errorf(Tsynerr);
else if ((rv = rename(wp[0], wp[1])) != 0) {
rv = errno;
bi_errorf("%s: %s", "failed", strerror(rv));
bi_errorf("%s: %s", "failed", cstrerror(rv));
}
return (rv);
@ -3676,7 +3676,7 @@ c_realpath(const char **wp)
bi_errorf(Tsynerr);
else if ((buf = do_realpath(wp[0])) == NULL) {
rv = errno;
bi_errorf("%s: %s", wp[0], strerror(rv));
bi_errorf("%s: %s", wp[0], cstrerror(rv));
if ((unsigned int)rv > 255)
rv = 255;
} else {
@ -3723,7 +3723,7 @@ c_cat(const char **wp)
fd = STDIN_FILENO;
else if ((fd = open(fn, O_RDONLY)) < 0) {
eno = errno;
bi_errorf("%s: %s", fn, strerror(eno));
bi_errorf("%s: %s", fn, cstrerror(eno));
rv = 1;
continue;
}
@ -3739,7 +3739,7 @@ c_cat(const char **wp)
continue;
}
/* an error occured during reading */
bi_errorf("%s: %s", fn, strerror(eno));
bi_errorf("%s: %s", fn, cstrerror(eno));
rv = 1;
break;
} else if (n == 0)
@ -3754,7 +3754,7 @@ c_cat(const char **wp)
/* an error occured during writing */
eno = errno;
bi_errorf("%s: %s", "<stdout>",
strerror(eno));
cstrerror(eno));
rv = 1;
if (fd != STDIN_FILENO)
close(fd);
@ -3789,7 +3789,7 @@ c_sleep(const char **wp)
if (!wp[0] || wp[1])
bi_errorf(Tsynerr);
else if (parse_usec(wp[0], &tv))
bi_errorf("%s: %s '%s'", Tsynerr, strerror(errno), wp[0]);
bi_errorf("%s: %s '%s'", Tsynerr, cstrerror(errno), wp[0]);
else {
#ifndef MKSH_NOPROSPECTOFWORK
sigset_t omask, bmask;
@ -3819,7 +3819,7 @@ c_sleep(const char **wp)
*/
rv = 0;
else
bi_errorf("%s: %s", Tselect, strerror(errno));
bi_errorf("%s: %s", Tselect, cstrerror(errno));
#ifndef MKSH_NOPROSPECTOFWORK
/* this will re-schedule signal delivery */
sigprocmask(SIG_SETMASK, &omask, NULL);

View File

@ -27,7 +27,7 @@
#include <sys/file.h>
#endif
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.129 2012/12/04 01:18:30 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.130 2012/12/17 23:18:05 tg Exp $");
Trap sigtraps[NSIG + 1];
static struct sigaction Sigact_ign;
@ -297,7 +297,7 @@ c_fc(const char **wp)
tf = maketemp(ATEMP, TT_HIST_EDIT, &e->temps);
if (!(shf = tf->shf)) {
bi_errorf("can't %s temporary file %s: %s",
"create", tf->tffn, strerror(errno));
"create", tf->tffn, cstrerror(errno));
return (1);
}
for (hp = rflag ? hlast : hfirst;
@ -305,7 +305,7 @@ c_fc(const char **wp)
shf_fprintf(shf, "%s\n", *hp);
if (shf_close(shf) == EOF) {
bi_errorf("can't %s temporary file %s: %s",
"write", tf->tffn, strerror(errno));
"write", tf->tffn, cstrerror(errno));
return (1);
}
@ -331,7 +331,7 @@ c_fc(const char **wp)
if (!(shf = shf_open(tf->tffn, O_RDONLY, 0, 0))) {
bi_errorf("can't %s temporary file %s: %s",
"open", tf->tffn, strerror(errno));
"open", tf->tffn, cstrerror(errno));
return (1);
}
@ -351,7 +351,7 @@ c_fc(const char **wp)
}
if (n < 0) {
bi_errorf("can't %s temporary file %s: %s",
"read", tf->tffn, strerror(shf_errno(shf)));
"read", tf->tffn, cstrerror(shf_errno(shf)));
errout:
shf_close(shf);
return (1);
@ -807,7 +807,7 @@ hist_init(Source *s)
}
if (hs != hist_init_retry)
bi_errorf("can't %s %s: %s",
"unlink HISTFILE", hname, strerror(errno));
"unlink HISTFILE", hname, cstrerror(errno));
histfsize = 0;
return;
} else {

30
jobs.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.92 2012/12/04 01:18:31 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.93 2012/12/17 23:18:06 tg Exp $");
#if HAVE_KILLPG
#define mksh_killpg killpg
@ -306,7 +306,7 @@ j_change(void)
if ((ttypgrp = tcgetpgrp(tty_fd)) < 0) {
warningf(false, "%s: %s %s: %s",
"j_init", "tcgetpgrp", "failed",
strerror(errno));
cstrerror(errno));
ttypgrp_ok = false;
break;
}
@ -321,13 +321,13 @@ j_change(void)
if (ttypgrp_ok && kshpgrp != kshpid) {
if (setpgid(0, kshpid) < 0) {
warningf(false, "%s: %s %s: %s", "j_init",
"setpgid", "failed", strerror(errno));
"setpgid", "failed", cstrerror(errno));
ttypgrp_ok = false;
} else {
if (tcsetpgrp(tty_fd, kshpid) < 0) {
warningf(false, "%s: %s %s: %s",
"j_init", "tcsetpgrp", "failed",
strerror(errno));
cstrerror(errno));
ttypgrp_ok = false;
} else
restore_ttypgrp = kshpgrp;
@ -370,7 +370,7 @@ ksh_nice(int ness)
errno = 0;
/* this is gonna annoy users; complain to your distro, people! */
if (nice(ness) == -1 && (eno = errno) != 0)
warningf(false, "%s: %s", "bgnice", strerror(eno));
warningf(false, "%s: %s", "bgnice", cstrerror(eno));
#else
(void)nice(ness);
#endif
@ -735,7 +735,7 @@ j_kill(const char *cp, int sig)
if (j->pgrp == 0) {
/* started when !Flag(FMONITOR) */
if (kill_job(j, sig) < 0) {
bi_errorf("%s: %s", cp, strerror(errno));
bi_errorf("%s: %s", cp, cstrerror(errno));
rv = 1;
}
} else {
@ -744,7 +744,7 @@ j_kill(const char *cp, int sig)
mksh_killpg(j->pgrp, SIGCONT);
#endif
if (mksh_killpg(j->pgrp, sig) < 0) {
bi_errorf("%s: %s", cp, strerror(errno));
bi_errorf("%s: %s", cp, cstrerror(errno));
rv = 1;
}
}
@ -820,7 +820,7 @@ j_resume(const char *cp, int bg)
"1st", "tcsetpgrp", tty_fd,
(long)((j->flags & JF_SAVEDTTYPGRP) ?
j->saved_ttypgrp : j->pgrp), "failed",
strerror(rv));
cstrerror(rv));
return (1);
}
}
@ -840,11 +840,11 @@ j_resume(const char *cp, int bg)
if (ttypgrp_ok && tcsetpgrp(tty_fd, kshpgrp) < 0)
warningf(true, "%s %s(%d, %ld) %s: %s",
"fg: 2nd", "tcsetpgrp", tty_fd,
(long)kshpgrp, "failed", strerror(errno));
(long)kshpgrp, "failed", cstrerror(errno));
}
sigprocmask(SIG_SETMASK, &omask, NULL);
bi_errorf("%s %s %s", "can't continue job",
cp, strerror(eno));
cp, cstrerror(eno));
return (1);
}
if (!bg) {
@ -1131,7 +1131,7 @@ j_waitj(Job *j,
if (tcsetpgrp(tty_fd, kshpgrp) < 0)
warningf(true, "%s %s(%d, %ld) %s: %s",
"j_waitj:", "tcsetpgrp", tty_fd,
(long)kshpgrp, "failed", strerror(errno));
(long)kshpgrp, "failed", cstrerror(errno));
if (j->state == PSTOPPED) {
j->flags |= JF_SAVEDTTY;
mksh_tcget(tty_fd, &j->ttystat);
@ -1822,21 +1822,21 @@ tty_init_talking(void)
#ifndef MKSH_DISABLE_TTY_WARNING
warningf(false, "%s: %s %s: %s",
"No controlling tty", "open", "/dev/tty",
strerror(errno));
cstrerror(errno));
#endif
break;
case 2:
#ifndef MKSH_DISABLE_TTY_WARNING
warningf(false, "%s: %s", "can't find tty fd", strerror(errno));
warningf(false, "%s: %s", "can't find tty fd", cstrerror(errno));
#endif
break;
case 3:
warningf(false, "%s: %s %s: %s", "j_ttyinit",
"dup of tty fd", "failed", strerror(errno));
"dup of tty fd", "failed", cstrerror(errno));
break;
case 4:
warningf(false, "%s: %s: %s", "j_ttyinit",
"can't set close-on-exec flag", strerror(errno));
"can't set close-on-exec flag", cstrerror(errno));
break;
}
}

4
main.c
View File

@ -34,7 +34,7 @@
#include <locale.h>
#endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.248 2012/12/07 23:46:36 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.249 2012/12/17 23:18:07 tg Exp $");
extern char **environ;
@ -484,7 +484,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
SHF_MAPHI | SHF_CLEXEC);
if (s->u.shf == NULL) {
shl_stdout_ok = false;
warningf(true, "%s: %s", s->file, strerror(errno));
warningf(true, "%s: %s", s->file, cstrerror(errno));
/* mandated by SUSv4 */
exstat = 127;
unwind(LERROR);

4
misc.c
View File

@ -30,7 +30,7 @@
#include <grp.h>
#endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.204 2012/12/05 19:38:22 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.205 2012/12/17 23:18:08 tg Exp $");
#define KSH_CHVT_FLAG
#ifdef MKSH_SMALL
@ -1853,7 +1853,7 @@ c_cd(const char **wp)
if (cdnode)
bi_errorf("%s: %s", dir, "bad directory");
else
bi_errorf("%s: %s", tryp, strerror(errno));
bi_errorf("%s: %s", tryp, cstrerror(errno));
afree(allocd, ATEMP);
Xfree(xs, xp);
return (2);

13
sh.h
View File

@ -94,6 +94,10 @@
/* shudder… */
#include <termio.h>
#endif
#ifdef _ISC_UNIX
/* XXX imake style */
#include <sys/sioctl.h>
#endif
#if HAVE_ULIMIT_H
#include <ulimit.h>
#endif
@ -160,7 +164,7 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.617 2012/12/17 22:14:26 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.618 2012/12/17 23:18:09 tg Exp $");
#endif
#define MKSH_VERSION "R41 2012/12/07"
@ -363,8 +367,11 @@ extern int getrusage(int, struct rusage *);
extern int revoke(const char *);
#endif
#if !HAVE_STRERROR
extern char *strerror(int);
#if defined(DEBUG) || !HAVE_STRERROR
#define strerror dontuse_strerror /* poisoned */
extern const char *cstrerror(int);
#else
#define cstrerror(errnum) ((const char *)strerror(errnum))
#endif
#if !HAVE_STRLCPY

88
shf.c
View File

@ -24,7 +24,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.52 2012/12/17 22:57:50 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.53 2012/12/17 23:18:11 tg Exp $");
/* flags to shf_emptybuf() */
#define EB_READSW 0x01 /* about to switch to reading */
@ -1078,21 +1078,79 @@ shf_putc(int c, struct shf *shf)
}
#endif
#if !HAVE_STRERROR
/*
* This is absolutely minimalistic. We could catch a number of well-
* known errors (like ENOENT) and provide real error strings for them,
* but to do that, I'd like a survey of which errors usually occur on
* what systems, to be worth it. Modern systems do have strerror; this
* is a porting aid only right now.
*/
char *
strerror(int errnum)
#ifdef DEBUG
const char *
cstrerror(int errnum)
{
/* "Errno. " + sign + rounded(octal) bits + NUL */
static char errbuf[7 + 1 + (8 * sizeof(int) + 2) / 3 + 1];
#undef strerror
return (strerror(errnum));
#define strerror dontuse_strerror /* poisoned */
}
#elif !HAVE_STRERROR
#if HAVE_SYS_ERRLIST
#if !HAVE_SYS_ERRLIST_DECL
extern int sys_nerr;
extern char *sys_errlist[];
#endif
#endif
const char *
cstrerror(int errnum)
{
/* "Unknown error: " + sign + rough estimate + NUL */
static char errbuf[15 + 1 + (8 * sizeof(int) + 2) / 3 + 1];
shf_snprintf(errbuf, sizeof(errbuf), "Errno. %d", errnum);
return (errbuf);
#if HAVE_SYS_ERRLIST
if (errnum > 0 && errnum < sys_nerr)
return (sys_errlist[errnum]);
#endif
switch (errnum) {
case 0:
return ("Undefined error: 0");
#ifdef EPERM
case EPERM:
return ("Operation not permitted");
#endif
#ifdef ENOENT
case ENOENT:
return ("No such file or directory");
#endif
#ifdef ESRCH
case ESRCH:
return ("No such process");
#endif
#ifdef E2BIG
case E2BIG:
return ("Argument list too long");
#endif
#ifdef ENOEXEC
case ENOEXEC:
return ("Exec format error");
#endif
#ifdef ENOMEM
case ENOMEM:
return ("Cannot allocate memory");
#endif
#ifdef EACCES
case EACCES:
return ("Permission denied");
#endif
#ifdef ENOTDIR
case ENOTDIR:
return ("Not a directory");
#endif
#ifdef EINVAL
case EINVAL:
return ("Invalid argument");
#endif
#ifdef ELOOP
case ELOOP:
return ("Too many levels of symbolic links");
#endif
default:
shf_snprintf(errbuf, sizeof(errbuf),
"Unknown error: %d", errnum);
return (errbuf);
}
}
#endif