static char hexchars[16] = "0123456789abcdef";
static char hexchars[] = "0123456789abcdef";
vfmtmsg(char *buf, int buflen, char *fmt, va_list args){    int c, i, n;    int width, prec, fillch;    int base, len, neg, quoted;    unsigned long val;      char *str, *f, *buf0;    unsigned char *p;    va_list a;     char num[32];    time_t t;    static char hexchars[16] = "0123456789abcdef";        buf0 = buf;    --buflen;    while (buflen > 0) {        for (f = fmt; *f != '%' && *f != 0; ++f)            ;        if (f > fmt) {            len = f - fmt;            if (len > buflen)                len = buflen;            memcpy(buf, fmt, len);            buf += len;            buflen -= len;            fmt = f;        }        if (*fmt == 0)            break;        c = *++fmt;        width = prec = 0;        fillch = ' ';           if (c == '0') {              fillch = '0';            c = *++fmt;        }        if (c == '*') {            width = va_arg(args, int);            c = *++fmt;        } else {            while (isdigit(c)) {                width = width * 10 + c - '0';                c = *++fmt;            }        }        if (c == '.') {               c = *++fmt;            if (c == '*') {                  prec = va_arg(args, int);                c = *++fmt;            } else {                while (isdigit(c)) {                    prec = prec * 10 + c - '0';                    c = *++fmt;                }             }        }        str = 0;        base = 0;        neg = 0;        ++fmt;        switch (c) {        case 'd':            i = va_arg(args, int);            if (i < 0) {                neg = 1;                val = -i;            } else                val = i;               base = 10;            break;        case 'o':            val = va_arg(args, unsigned int);            base = 8;            break;        case 'x':            val = va_arg(args, unsigned int);            base = 16;            break;        case 'p':            val = (unsigned long) va_arg(args, void *);            base = 16;            neg = 2;            break;        case 's':            str = va_arg(args, char *);            break;        case 'c':               num[0] = va_arg(args, int);            num[1] = 0;            str = num;              break;        case 'm':            str = strerror(errno);            break;        case 'I':            str = ip_ntoa(va_arg(args, u_int32_t));            break;        case 'r':            f = va_arg(args, char *);            a = va_arg(args, va_list);            n = vfmtmsg(buf, buflen + 1, f, a);            buf += n;            buflen -= n;            continue;        case 't':            time(&t);            str = ctime(&t);            str += 4;           /* chop off the day name */            str[15] = 0;        /* chop off year and newline */            break;        case 'v':               /* "visible" string */        case 'q':               /* quoted string */            quoted = c == 'q';            p = va_arg(args, unsigned char *);            if (fillch == '0' && prec > 0) {                n = prec;            } else {                n = strlen((char *)p);                if (prec > 0 && prec < n)                    n = prec;            }            while (n > 0 && buflen > 0) {                c = *p++;                --n;                if (!quoted && c >= 0x80) {                    OUTCHAR('M');                    OUTCHAR('-');                    c -= 0x80;                }                if (quoted && (c == '"' || c == '\\'))                    OUTCHAR('\\');                if (c < 0x20 || 0x7f <= c && c < 0xa0) {                    if (quoted) {                        OUTCHAR('\\');                        switch (c) {                        case '\t':      OUTCHAR('t');   break;                        case '\n':      OUTCHAR('n');   break;                        case '\b':      OUTCHAR('b');   break;                        case '\f':      OUTCHAR('f');   break;                        default:                            OUTCHAR('x');                               OUTCHAR(hexchars[c >> 4]);                            OUTCHAR(hexchars[c & 0xf]);                        }                    } else {                        if (c == '\t')                            OUTCHAR(c);                        else {                            OUTCHAR('^');                            OUTCHAR(c ^ 0x40);                        }                    }                } else                    OUTCHAR(c);            }            continue;        default:            *buf++ = '%';            if (c != '%')                --fmt;          /* so %z outputs %z etc. */            --buflen;            continue;        }        if (base != 0) {            str = num + sizeof(num);            *--str = 0;            while (str > num + neg) {                *--str = hexchars[val % base];                val = val / base;                if (--prec <= 0 && val == 0)                    break;              }            switch (neg) {            case 1:                *--str = '-';                break;            case 2:                *--str = 'x';                *--str = '0';                break;            }            len = num + sizeof(num) - 1 - str;        } else {            len = strlen(str);            if (prec > 0 && len > prec)                len = prec;        }        if (width > 0) {            if (width > buflen)                width = buflen;            if ((n = width - len) > 0) {                buflen -= n;                for (; n > 0; --n)                       *buf++ = fillch;            }        }        if (len > buflen)               len = buflen;        memcpy(buf, str, len);        buf += len;        buflen -= len;    }    *buf = 0;    return buf - buf0;}