#ifndef lint
static char copyright[] =
"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
static char *rcsid = "$Id: misc.c,v 1.24 2005/08/08 19:43:41 abe Exp $";
#endif
#include "lsof.h"
#if defined(HASWIDECHAR) && defined(WIDECHARINCL)
#include WIDECHARINCL
#endif
#if !defined(MAXSYMLINKS)
#define MAXSYMLINKS 32
#endif
_PROTOTYPE(static void closePipes,(void));
_PROTOTYPE(static int dolstat,(char *path, char *buf, int len));
_PROTOTYPE(static int dostat,(char *path, char *buf, int len));
_PROTOTYPE(static int doreadlink,(char *path, char *buf, int len));
_PROTOTYPE(static int doinchild,(int (*fn)(), char *fp, char *rbuf, int rbln));
#if defined(HASINTSIGNAL)
_PROTOTYPE(static int handleint,(int sig));
#else
_PROTOTYPE(static void handleint,(int sig));
#endif
_PROTOTYPE(static char *safepup,(unsigned int c, int *cl));
static pid_t Cpid = 0;
static jmp_buf Jmp_buf;
static int Pipes[] =
{ -1, -1, -1, -1 };
static int CtSigs[] = { 0, SIGINT, SIGKILL };
#define NCTSIGS (sizeof(CtSigs) / sizeof(int))
#if defined(HASNLIST)
static struct drive_Nl *Build_Nl = (struct drive_Nl *)NULL;
void
build_Nl(d)
struct drive_Nl *d;
{
struct drive_Nl *dp;
int i, n;
for (dp = d, n = 0; dp->nn; dp++, n++)
;
if (n < 1) {
(void) fprintf(stderr,
"%s: can't calculate kernel name list length\n", Pn);
Exit(1);
}
if (!(Nl = (struct NLIST_TYPE *)calloc((n + 1),
sizeof(struct NLIST_TYPE))))
{
(void) fprintf(stderr,
"%s: can't allocate %d bytes to kernel name list structure\n",
Pn, (int)((n + 1) * sizeof(struct NLIST_TYPE)));
Exit(1);
}
for (dp = d, i = 0; i < n; dp++, i++) {
Nl[i].NL_NAME = dp->knm;
}
Nll = (int)((n + 1) * sizeof(struct NLIST_TYPE));
Build_Nl = d;
}
#endif
void
childx()
{
int at, sx;
pid_t wpid;
if (Cpid > 1) {
(void) closePipes();
if ((at = TmLimit / NCTSIGS) < TMLIMMIN)
at = TMLIMMIN;
for (sx = 0; sx < NCTSIGS; sx++) {
if (setjmp(Jmp_buf)) {
(void) alarm(0);
(void) signal(SIGALRM, SIG_DFL);
if (sx < (NCTSIGS - 1))
continue;
if (!Fwarn)
(void) fprintf(stderr,
"%s: WARNING -- child process %d may be hung.\n",
Pn, (int)Cpid);
break;
}
if (sx)
(void) kill(Cpid, CtSigs[sx]);
(void) signal(SIGALRM, handleint);
(void) alarm(at);
wpid = (pid_t) wait(NULL);
(void) alarm(0);
(void) signal(SIGALRM, SIG_DFL);
if (wpid == Cpid)
break;
}
Cpid = 0;
}
}
static void
closePipes()
{
int i;
for (i = 0; i < 4; i++) {
if (Pipes[i] >= 0) {
(void) close(Pipes[i]);
Pipes[i] = -1;
}
}
}
int
compdev(a1, a2)
COMP_P *a1, *a2;
{
struct l_dev **p1 = (struct l_dev **)a1;
struct l_dev **p2 = (struct l_dev **)a2;
if ((dev_t)((*p1)->rdev) < (dev_t)((*p2)->rdev))
return(-1);
if ((dev_t)((*p1)->rdev) > (dev_t)((*p2)->rdev))
return(1);
if ((INODETYPE)((*p1)->inode) < (INODETYPE)((*p2)->inode))
return(-1);
if ((INODETYPE)((*p1)->inode) > (INODETYPE)((*p2)->inode))
return(1);
return(strcmp((*p1)->name, (*p2)->name));
}
static int
doinchild(fn, fp, rbuf, rbln)
int (*fn)();
char *fp;
char *rbuf;
int rbln;
{
int en, rv;
if (!Fovhd && rbln > MAXPATHLEN) {
(void) fprintf(stderr,
"%s: doinchild error; response buffer too large: %d\n",
Pn, rbln);
Exit(1);
}
if (!Fovhd) {
if (setjmp(Jmp_buf)) {
(void) alarm(0);
(void) signal(SIGALRM, SIG_DFL);
(void) childx();
errno = ETIMEDOUT;
return(1);
} else if (!Cpid) {
if (pipe(Pipes) < 0 || pipe(&Pipes[2]) < 0) {
(void) fprintf(stderr, "%s: can't open pipes: %s\n",
Pn, strerror(errno));
Exit(1);
}
if ((Cpid = fork()) == 0) {
int fd, nd, r_al, r_rbln;
char r_arg[MAXPATHLEN+1], r_rbuf[MAXPATHLEN+1];
int (*r_fn)();
for (fd = 0, nd = GET_MAX_FD(); fd < nd; fd++) {
if (fd == Pipes[0] || fd == Pipes[3])
continue;
(void) close(fd);
if (fd == Pipes[1])
Pipes[1] = -1;
else if (fd == Pipes[2])
Pipes[2] = -1;
}
if (Pipes[1] >= 0) {
(void) close(Pipes[1]);
Pipes[1] = -1;
}
if (Pipes[2] >= 0) {
(void) close(Pipes[2]);
Pipes[2] = -1;
}
for (;;) {
if (read(Pipes[0], (char *)&r_fn, sizeof(r_fn))
!= (int)sizeof(r_fn)
|| read(Pipes[0], (char *)&r_al, sizeof(int))
!= (int)sizeof(int)
|| r_al < 1
|| r_al > (int)sizeof(r_arg)
|| read(Pipes[0], r_arg, r_al) != r_al
|| read(Pipes[0], (char *)&r_rbln, sizeof(r_rbln))
!= (int)sizeof(r_rbln)
|| r_rbln < 1 || r_rbln > (int)sizeof(r_rbuf))
break;
rv = r_fn(r_arg, r_rbuf, r_rbln);
en = errno;
if (write(Pipes[3], (char *)&rv, sizeof(rv))
!= sizeof(rv)
|| write(Pipes[3], (char *)&en, sizeof(en))
!= sizeof(en)
|| write(Pipes[3], r_rbuf, r_rbln) != r_rbln)
break;
}
(void) _exit(0);
}
if (Cpid < 0) {
(void) fprintf(stderr, "%s: can't fork: %s\n",
Pn, strerror(errno));
Exit(1);
}
(void) close(Pipes[0]);
(void) close(Pipes[3]);
Pipes[0] = Pipes[3] = -1;
}
}
if (!Fovhd) {
int len;
len = strlen(fp) + 1;
(void) signal(SIGALRM, handleint);
(void) alarm(TmLimit);
if (write(Pipes[1], (char *)&fn, sizeof(fn)) != sizeof(fn)
|| write(Pipes[1], (char *)&len, sizeof(len)) != sizeof(len)
|| write(Pipes[1], fp, len) != len
|| write(Pipes[1], (char *)&rbln, sizeof(rbln)) != sizeof(rbln)
|| read(Pipes[2], (char *)&rv, sizeof(rv)) != sizeof(rv)
|| read(Pipes[2], (char *)&en, sizeof(en)) != sizeof(en)
|| read(Pipes[2], rbuf, rbln) != rbln) {
(void) alarm(0);
(void) signal(SIGALRM, SIG_DFL);
(void) childx();
errno = ECHILD;
return(-1);
}
} else {
(void) signal(SIGALRM, handleint);
(void) alarm(TmLimit);
rv = fn(fp, rbuf, rbln);
en = errno;
}
(void) alarm(0);
(void) signal(SIGALRM, SIG_DFL);
errno = en;
return(rv);
}
static int
dolstat(path, rbuf, rbln)
char *path;
char *rbuf;
int rbln;
{
return(lstat(path, (struct stat *)rbuf));
}
static int
doreadlink(path, rbuf, rbln)
char *path;
char *rbuf;
int rbln;
{
return(readlink(path, rbuf, rbln));
}
static int
dostat(path, rbuf, rbln)
char *path;
char *rbuf;
int rbln;
{
return(stat(path, (struct stat *)rbuf));
}
#if defined(WILLDROPGID)
void
dropgid()
{
if (!Setuidroot && Setgid) {
if (setgid(Mygid) < 0) {
(void) fprintf(stderr, "%s: can't setgid(%d): %s\n",
Pn, (int)Mygid, strerror(errno));
Exit(1);
}
Setgid = 0;
}
}
#endif
void
enter_dev_ch(m)
char *m;
{
char *mp;
if (!m || *m == '\0')
return;
if (!(mp = mkstrcpy(m, (MALLOC_S *)NULL))) {
(void) fprintf(stderr, "%s: no more dev_ch space at PID %d: \n",
Pn, Lp->pid);
safestrprt(m, stderr, 1);
Exit(1);
}
if (Lf->dev_ch)
(void) free((FREE_P *)Lf->dev_ch);
Lf->dev_ch = mp;
}
void
enter_nm(m)
char *m;
{
char *mp;
if (!m || *m == '\0')
return;
if (!(mp = mkstrcpy(m, (MALLOC_S *)NULL))) {
(void) fprintf(stderr, "%s: no more nm space at PID %d for: ",
Pn, Lp->pid);
safestrprt(m, stderr, 1);
Exit(1);
}
if (Lf->nm)
(void) free((FREE_P *)Lf->nm);
Lf->nm = mp;
}
void
Exit(xv)
int xv;
{
(void) childx();
#if defined(HASDCACHE)
if (DCrebuilt && !Fwarn)
(void) fprintf(stderr, "%s: WARNING: %s was updated.\n",
Pn, DCpath[DCpathX]);
#endif
exit(xv);
}
#if defined(HASNLIST)
int
get_Nl_value(nn, d, v)
char *nn;
struct drive_Nl *d;
KA_T *v;
{
int i;
if (!Nl || !Nll)
return(-1);
if (!d)
d = Build_Nl;
for (i = 0; d->nn; d++, i++) {
if (strcmp(d->nn, nn) == 0) {
if (v)
*v = (KA_T)Nl[i].n_value;
return(i);
}
}
return(-1);
}
#endif
#if defined(HASINTSIGNAL)
static int
#else
static void
#endif
handleint(sig)
int sig;
{
longjmp(Jmp_buf, 1);
}
int
hashbyname(nm, mod)
char *nm;
int mod;
{
int i, j;
for (i = j = 0; *nm; nm++) {
i ^= (int)*nm << j;
if (++j > 7)
j = 0;
}
return(((int)(i * 31415)) & (mod - 1));
}
int
is_nw_addr(ia, p, af)
unsigned char *ia;
int p;
int af;
{
struct nwad *n;
if (!(n = Nwad))
return(0);
for (; n; n = n->next) {
if (n->proto) {
if (strcasecmp(n->proto, Lf->iproto) != 0)
continue;
}
if (af && n->af && af != n->af)
continue;
#if defined(HASIPv6)
if (af == AF_INET6) {
if (n->a[15] || n->a[14] || n->a[13] || n->a[12]
|| n->a[11] || n->a[10] || n->a[9] || n->a[8]
|| n->a[7] || n->a[6] || n->a[5] || n->a[4]
|| n->a[3] || n->a[2] || n->a[1] || n->a[0]) {
if (ia[15] != n->a[15] || ia[14] != n->a[14]
|| ia[13] != n->a[13] || ia[12] != n->a[12]
|| ia[11] != n->a[11] || ia[10] != n->a[10]
|| ia[9] != n->a[9] || ia[8] != n->a[8]
|| ia[7] != n->a[7] || ia[6] != n->a[6]
|| ia[5] != n->a[5] || ia[4] != n->a[4]
|| ia[3] != n->a[3] || ia[2] != n->a[2]
|| ia[1] != n->a[1] || ia[0] != n->a[0])
continue;
}
} else if (af == AF_INET)
#endif
{
if (n->a[3] || n->a[2] || n->a[1] || n->a[0]) {
if (ia[3] != n->a[3] || ia[2] != n->a[2]
|| ia[1] != n->a[1] || ia[0] != n->a[0])
continue;
}
}
#if defined(HASIPv6)
else
continue;
#endif
if (n->sport == -1 || (p >= n->sport && p <= n->eport)) {
n->f = 1;
return(1);
}
}
return(0);
}
char *
mkstrcpy(src, rlp)
char *src;
MALLOC_S *rlp;
{
MALLOC_S len;
char *ns;
len = (MALLOC_S)(src ? strlen(src) : 0);
ns = (char *)malloc(len + 1);
if (ns) {
if (src)
(void) snpf(ns, len + 1, "%s", src);
else
*ns = '\0';
}
if (rlp)
*rlp = len;
return(ns);
}
char *
mkstrcat(s1, l1, s2, l2, s3, l3, clp)
char *s1;
int l1;
char *s2;
int l2;
char *s3;
int l3 ;
MALLOC_S *clp;
{
MALLOC_S cl, len1, len2, len3;
char *cp;
if (s1)
len1 = (MALLOC_S)((l1 >= 0) ? l1 : strlen(s1));
else
len1 = (MALLOC_S)0;
if (s2)
len2 = (MALLOC_S)((l2 >= 0) ? l2 : strlen(s2));
else
len2 = (MALLOC_S)0;
if (s3)
len3 = (MALLOC_S)((l3 >= 0) ? l3 : strlen(s3));
else
len3 = (MALLOC_S)0;
cl = len1 + len2 + len3;
if ((cp = (char *)malloc(cl + 1))) {
char *tp = cp;
if (s1 && len1) {
(void) strncpy(tp, s1, len1);
tp += len1;
}
if (s2 && len2) {
(void) strncpy(tp, s2, len2);
tp += len2;
}
if (s3 && len3) {
(void) strncpy(tp, s3, len3);
tp += len3;
}
*tp = '\0';
}
if (clp)
*clp = cl;
return(cp);
}
int
is_readable(path, msg)
char *path;
int msg;
{
if (access(path, R_OK) < 0) {
if (!Fwarn && msg == 1)
(void) fprintf(stderr, ACCESSERRFMT, Pn, path, strerror(errno));
return(0);
}
return(1);
}
int
lstatsafely(path, buf)
char *path;
struct stat *buf;
{
if (Fblock) {
if (!Fwarn)
(void) fprintf(stderr,
"%s: avoiding stat(%s): -b was specified.\n",
Pn, path);
errno = EWOULDBLOCK;
return(1);
}
return(doinchild(dolstat, path, (char *)buf, sizeof(struct stat)));
}
char *
Readlink(arg)
char *arg;
{
char abuf[MAXPATHLEN+1];
int alen;
char *ap;
char *argp1, *argp2;
int i, len, llen, slen;
char lbuf[MAXPATHLEN+1];
static char *op = (char *)NULL;
static int ss = 0;
char *s1;
static char **stk = (char **)NULL;
static int sx = 0;
char tbuf[MAXPATHLEN+1];
if (Fblock) {
if (!Fwarn) {
(void) fprintf(stderr, "%s: avoiding readlink(", Pn);
safestrprt(arg, stderr, 0);
(void) fprintf(stderr, "): -b was specified.\n");
}
op = (char *)NULL;
return(arg);
}
if (!op)
op = arg;
for (alen = 0, ap = abuf, argp1 = argp2 = arg; *argp2; argp1 = argp2 ) {
for (argp2 = argp1 + 1; *argp2 && *argp2 != '/'; argp2++)
;
if ((len = argp2 - arg) >= (int)sizeof(tbuf)) {
path_too_long:
if (!Fwarn) {
(void) fprintf(stderr,
"%s: readlink() path too long: ", Pn);
safestrprt(op ? op : arg, stderr, 1);
}
op = (char *)NULL;
return((char *)NULL);
}
(void) strncpy(tbuf, arg, len);
tbuf[len] = '\0';
if ((llen=doinchild(doreadlink,tbuf,lbuf,sizeof(lbuf) - 1)) >= 0) {
if (lbuf[0] == '/') {
(void) strncpy(abuf, lbuf, llen);
ap = &abuf[llen];
*ap = '\0';
alen = llen;
continue;
}
lbuf[llen] = '\0';
s1 = lbuf;
} else {
llen = argp2 - argp1;
s1 = argp1;
}
if (*s1 == '/')
slen = 1;
else {
if (alen > 0) {
if (abuf[alen - 1] == '/')
slen = 1;
else
slen = 2;
} else {
if (s1 == lbuf && tbuf[0] == '/')
slen = 2;
else
slen = 1;
}
}
if ((alen + llen + slen) >= (int)sizeof(abuf))
goto path_too_long;
if (slen == 2)
*ap++ = '/';
(void) strncpy(ap, s1, llen);
ap += llen;
*ap = '\0';
alen += (llen + slen - 1);
}
if (strcmp(arg, abuf) == 0) {
for (i = 0; i < sx; i++) {
if (i < (sx - 1))
(void) free((FREE_P *)stk[i]);
stk[i] = (char *)NULL;
}
sx = 0;
op = (char *)NULL;
return(arg);
}
if (!(s1 = mkstrcpy(abuf, (MALLOC_S *)NULL))) {
no_readlink_space:
(void) fprintf(stderr, "%s: no Readlink string space for ", Pn);
safestrprt(abuf, stderr, 1);
Exit(1);
}
if (sx >= MAXSYMLINKS) {
if (!Fwarn) {
(void) fprintf(stderr,
"%s: too many (> %d) symbolic links in readlink() path: ",
Pn, MAXSYMLINKS);
safestrprt(op ? op : arg, stderr, 1);
}
for (i = 0; i < sx; i++) {
(void) free((FREE_P *)stk[i]);
stk[i] = (char *)NULL;
}
(void) free((FREE_P *)stk);
stk = (char **)NULL;
ss = sx = 0;
op = (char *)NULL;
return((char *)NULL);
}
if (++sx > ss) {
if (!stk)
stk = (char **)malloc(sizeof(char *) * sx);
else
stk = (char **)realloc(stk, sizeof(char *) * sx);
if (!stk)
goto no_readlink_space;
ss = sx;
}
stk[sx - 1] = s1;
return(Readlink(s1));
}
#if defined(HASSTREAMS)
int
readstdata(addr, buf)
KA_T addr;
struct stdata *buf;
{
if (!addr
|| kread(addr, (char *)buf, sizeof(struct stdata))) {
(void) snpf(Namech, Namechl, "no stream data in %s",
print_kptr(addr, (char *)NULL, 0));
return(1);
}
return(0);
}
int
readsthead(addr, buf)
KA_T addr;
struct queue *buf;
{
KA_T qp;
if (!addr) {
(void) snpf(Namech, Namechl, "no stream queue head");
return(1);
}
for (qp = addr; qp; qp = (KA_T)buf->q_next) {
if (kread(qp, (char *)buf, sizeof(struct queue))) {
(void) snpf(Namech, Namechl, "bad stream queue link at %s",
print_kptr(qp, (char *)NULL, 0));
return(1);
}
}
return(0);
}
int
readstidnm(addr, buf, len)
KA_T addr;
char *buf;
READLEN_T len;
{
if (!addr || kread(addr, buf, len)) {
(void) snpf(Namech, Namechl, "can't read module ID name from %s",
print_kptr(addr, (char *)NULL, 0));
return(1);
}
return(0);
}
int
readstmin(addr, buf)
KA_T addr;
struct module_info *buf;
{
if (!addr || kread(addr, (char *)buf, sizeof(struct module_info))) {
(void) snpf(Namech, Namechl, "can't read module info from %s",
print_kptr(addr, (char *)NULL, 0));
return(1);
}
return(0);
}
int
readstqinit(addr, buf)
KA_T addr;
struct qinit *buf;
{
if (!addr || kread(addr, (char *)buf, sizeof(struct qinit))) {
(void) snpf(Namech, Namechl, "can't read queue info from %s",
print_kptr(addr, (char *)NULL, 0));
return(1);
}
return(0);
}
#endif
static char *
safepup(c, cl)
unsigned int c;
int *cl;
{
int len;
char *rp;
static char up[8];
if (c < 0x20) {
switch (c) {
case '\b':
rp = "\\b";
break;
case '\f':
rp = "\\f";
break;
case '\n':
rp = "\\n";
break;
case '\r':
rp = "\\r";
break;
case '\t':
rp = "\\t";
break;
default:
(void) snpf(up, sizeof(up), "^%c", c + 0x40);
rp = up;
}
len = 2;
} else if (c == 0xff) {
rp = "^?";
len = 2;
} else {
(void) snpf(up, sizeof(up), "\\x%02x", (int)(c & 0xff));
rp = up;
len = 4;
}
if (cl)
*cl = len;
return(rp);
}
int
safestrlen(sp, flags)
char *sp;
int flags;
{
char c;
int len = 0;
c = (flags & 2) ? ' ' : '\0';
if (sp) {
for (; *sp; sp++) {
if (!isprint((unsigned char)*sp) || *sp == c) {
if (*sp < 0x20 || (unsigned char)*sp == 0xff)
len += 2;
else
len += 4;
} else
len++;
}
}
return(len);
}
void
safestrprt(sp, fs, flags)
char *sp;
FILE *fs;
int flags;
{
char c;
int lnc, lnt, sl;
#if defined(HASWIDECHAR)
wchar_t w;
int wcmx = MB_CUR_MAX;
#else
static int wcmx = 1;
#endif
c = (flags & 2) ? ' ' : '\0';
if (flags & 4)
putc('"', fs);
if (sp) {
for (sl = strlen(sp); *sp; sl -= lnc, sp += lnc) {
#if defined(HASWIDECHAR)
if (wcmx > 1) {
lnc = mblen(sp, sl);
if (lnc > 1) {
if ((mbtowc(&w, sp, sl) == lnc) && iswprint(w)) {
for (lnt = 0; lnt < lnc; lnt++) {
putc((int)*(sp + lnt), fs);
}
} else {
for (lnt = 0; lnt < lnc; lnt++) {
fputs(safepup((unsigned int)*(sp + lnt),
(int *)NULL), fs);
}
}
continue;
} else
lnc = 1;
} else
lnc = 1;
#else
lnc = 1;
#endif
if (isprint((unsigned char)*sp) && *sp != c)
putc((int)(*sp & 0xff), fs);
else {
if ((flags & 8) && (*sp == '\n') && !*(sp + 1))
break;
fputs(safepup((unsigned int)*sp, (int *)NULL), fs);
}
}
}
if (flags & 4)
putc('"', fs);
if (flags & 1)
putc('\n', fs);
}
void
safestrprtn(sp, len, fs, flags)
char *sp;
int len;
FILE *fs;
int flags;
{
char c, *up;
int cl, i;
if (flags & 4)
putc('"', fs);
if (sp) {
c = (flags & 2) ? ' ' : '\0';
for (i = 0; i < len && *sp; sp++) {
if (isprint((unsigned char)*sp) && *sp != c) {
putc((int)(*sp & 0xff), fs);
i++;
} else {
if ((flags & 8) && (*sp == '\n') && !*(sp + 1))
break;
up = safepup((unsigned int)*sp, &cl);
if ((i + cl) > len)
break;
fputs(up, fs);
i += cl;
}
}
} else
i = 0;
for (; i < len; i++)
putc(' ', fs);
if (flags & 4)
putc('"', fs);
if (flags & 1)
putc('\n', fs);
}
int
statsafely(path, buf)
char *path;
struct stat *buf;
{
if (Fblock) {
if (!Fwarn)
(void) fprintf(stderr,
"%s: avoiding stat(%s): -b was specified.\n",
Pn, path);
errno = EWOULDBLOCK;
return(1);
}
return(doinchild(dostat, path, (char *)buf, sizeof(struct stat)));
}
void
stkdir(p)
char *p;
{
MALLOC_S len;
if (Dstkx >= Dstkn) {
Dstkn += 128;
len = (MALLOC_S)(Dstkn * sizeof(char *));
if (!Dstk)
Dstk = (char **)malloc(len);
else
Dstk = (char **)realloc((MALLOC_P *)Dstk, len);
if (!Dstk) {
(void) fprintf(stderr,
"%s: no space for directory stack at: ", Pn);
safestrprt(p, stderr, 1);
Exit(1);
}
}
if (!(Dstk[Dstkx] = mkstrcpy(p, (MALLOC_S *)NULL))) {
(void) fprintf(stderr, "%s: no space for: ", Pn);
safestrprt(p, stderr, 1);
Exit(1);
}
Dstkx++;
}
char *
x2dev(s, d)
char *s;
dev_t *d;
{
char *cp, *cp1;
int n;
dev_t r;
if (strncasecmp(s, "0x", 2) == 0)
s += 2;
for (cp = s, n = 0; *cp; cp++, n++) {
if (isdigit((unsigned char)*cp))
continue;
if ((unsigned char)*cp >= 'a' && (unsigned char)*cp <= 'f')
continue;
if ((unsigned char)*cp >= 'A' && (unsigned char)*cp <= 'F')
continue;
if (*cp == ' ' || *cp == ',')
break;
return((char *)NULL);
}
if (!n)
return((char *)NULL);
if (n > (2 * (int)sizeof(dev_t))) {
cp1 = s;
s += (n - (2 * sizeof(dev_t)));
while (cp1 < s) {
if (*cp1 != 'f' && *cp1 != 'F')
return((char *)NULL);
cp1++;
}
}
for (r = 0; s < cp; s++) {
r = r << 4;
if (isdigit((unsigned char)*s))
r |= (unsigned char)(*s - '0') & 0xf;
else {
if (isupper((unsigned char)*s))
r |= ((unsigned char)(*s - 'A') + 10) & 0xf;
else
r |= ((unsigned char)(*s - 'a') + 10) & 0xf;
}
}
*d = r;
return(s);
}