[BACK]Return to kstat.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / kstat

Annotation of src/usr.bin/kstat/kstat.c, Revision 1.13

1.13    ! dlg         1: /* $OpenBSD: kstat.c,v 1.12 2023/11/16 02:45:54 dlg Exp $ */
1.1       dlg         2:
                      3: /*
                      4:  * Copyright (c) 2020 David Gwynne <dlg@openbsd.org>
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                      9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     15:  */
                     16:
                     17: #include <ctype.h>
1.10      cheloha    18: #include <limits.h>
                     19: #include <signal.h>
1.1       dlg        20: #include <stdio.h>
                     21: #include <stdlib.h>
                     22: #include <stddef.h>
                     23: #include <string.h>
                     24: #include <inttypes.h>
1.2       dlg        25: #include <fnmatch.h>
1.1       dlg        26: #include <fcntl.h>
1.3       dlg        27: #include <unistd.h>
1.1       dlg        28: #include <errno.h>
                     29: #include <err.h>
                     30: #include <vis.h>
                     31:
                     32: #include <sys/tree.h>
                     33: #include <sys/ioctl.h>
                     34: #include <sys/time.h>
1.2       dlg        35: #include <sys/queue.h>
1.1       dlg        36:
                     37: #include <sys/kstat.h>
                     38:
                     39: #ifndef roundup
1.2       dlg        40: #define roundup(x, y)          ((((x)+((y)-1))/(y))*(y))
1.1       dlg        41: #endif
                     42:
1.2       dlg        43: #ifndef nitems
                     44: #define nitems(_a)             (sizeof((_a)) / sizeof((_a)[0]))
                     45: #endif
                     46:
                     47: #ifndef ISSET
                     48: #define ISSET(_i, _m)          ((_i) & (_m))
                     49: #endif
                     50:
                     51: #ifndef SET
                     52: #define SET(_i, _m)            ((_i) |= (_m))
                     53: #endif
                     54:
1.12      dlg        55: struct fmt_result {
                     56:        uint64_t                val;
                     57:        unsigned int            frac;
                     58:        unsigned int            exp;
                     59: };
                     60:
                     61: static void
                     62: fmt_thing(struct fmt_result *fr, uint64_t val, uint64_t chunk)
                     63: {
                     64:        unsigned int exp = 0;
                     65:        uint64_t rem = 0;
                     66:
                     67:        while (val > chunk) {
                     68:                rem = val % chunk;
                     69:                val /= chunk;
                     70:                exp++;
                     71:        }
                     72:
                     73:        fr->val = val;
                     74:        fr->exp = exp;
                     75:        fr->frac = (rem * 1000) / chunk;
                     76: }
                     77:
1.2       dlg        78: #define str_is_empty(_str)     (*(_str) == '\0')
                     79:
1.1       dlg        80: #define DEV_KSTAT "/dev/kstat"
                     81:
1.2       dlg        82: struct kstat_filter {
                     83:        TAILQ_ENTRY(kstat_filter)        kf_entry;
                     84:        const char                      *kf_provider;
                     85:        const char                      *kf_name;
                     86:        unsigned int                     kf_flags;
                     87: #define KSTAT_FILTER_F_INST                    (1 << 0)
                     88: #define KSTAT_FILTER_F_UNIT                    (1 << 1)
                     89:        unsigned int                     kf_instance;
                     90:        unsigned int                     kf_unit;
                     91: };
                     92:
                     93: TAILQ_HEAD(kstat_filters, kstat_filter);
                     94:
1.4       dlg        95: struct kstat_entry {
                     96:        struct kstat_req        kstat;
                     97:        RBT_ENTRY(kstat_entry)  entry;
                     98:        int                     serrno;
                     99: };
                    100:
                    101: RBT_HEAD(kstat_tree, kstat_entry);
                    102:
                    103: static inline int
                    104: kstat_cmp(const struct kstat_entry *ea, const struct kstat_entry *eb)
                    105: {
                    106:        const struct kstat_req *a = &ea->kstat;
                    107:        const struct kstat_req *b = &eb->kstat;
                    108:        int rv;
                    109:
                    110:        rv = strncmp(a->ks_provider, b->ks_provider, sizeof(a->ks_provider));
                    111:        if (rv != 0)
                    112:                return (rv);
                    113:        if (a->ks_instance > b->ks_instance)
                    114:                return (1);
                    115:        if (a->ks_instance < b->ks_instance)
                    116:                return (-1);
                    117:
                    118:        rv = strncmp(a->ks_name, b->ks_name, sizeof(a->ks_name));
                    119:        if (rv != 0)
                    120:                return (rv);
                    121:        if (a->ks_unit > b->ks_unit)
                    122:                return (1);
                    123:        if (a->ks_unit < b->ks_unit)
                    124:                return (-1);
                    125:
                    126:        return (0);
                    127: }
                    128:
                    129: RBT_PROTOTYPE(kstat_tree, kstat_entry, entry, kstat_cmp);
                    130: RBT_GENERATE(kstat_tree, kstat_entry, entry, kstat_cmp);
                    131:
1.10      cheloha   132: static void handle_alrm(int);
1.2       dlg       133: static struct kstat_filter *
                    134:                kstat_filter_parse(char *);
                    135: static int     kstat_filter_entry(struct kstat_filters *,
                    136:                    const struct kstat_req *);
                    137:
1.3       dlg       138: static void    kstat_list(struct kstat_tree *, int, unsigned int,
                    139:                    struct kstat_filters *);
                    140: static void    kstat_print(struct kstat_tree *);
1.5       dlg       141: static void    kstat_read(struct kstat_tree *, int);
1.1       dlg       142:
                    143: __dead static void
                    144: usage(void)
                    145: {
                    146:        extern char *__progname;
1.2       dlg       147:
1.5       dlg       148:        fprintf(stderr, "usage: %s [-w wait] "
1.11      kn        149:            "[name | provider:instance:name:unit] ...\n", __progname);
1.2       dlg       150:
1.1       dlg       151:        exit(1);
                    152: }
                    153:
                    154: int
                    155: main(int argc, char *argv[])
                    156: {
1.2       dlg       157:        struct kstat_filters kfs = TAILQ_HEAD_INITIALIZER(kfs);
1.3       dlg       158:        struct kstat_tree kt = RBT_INITIALIZER();
1.1       dlg       159:        unsigned int version;
                    160:        int fd;
1.5       dlg       161:        const char *errstr;
                    162:        int ch;
1.10      cheloha   163:        struct itimerval itv;
                    164:        sigset_t empty, mask;
1.2       dlg       165:        int i;
1.10      cheloha   166:        unsigned int wait = 0;
1.2       dlg       167:
1.5       dlg       168:        while ((ch = getopt(argc, argv, "w:")) != -1) {
                    169:                switch (ch) {
                    170:                case 'w':
1.10      cheloha   171:                        wait = strtonum(optarg, 1, UINT_MAX, &errstr);
1.5       dlg       172:                        if (errstr != NULL)
1.10      cheloha   173:                                errx(1, "wait is %s: %s", errstr, optarg);
1.5       dlg       174:                        break;
                    175:                default:
                    176:                        usage();
                    177:                }
                    178:        }
                    179:
                    180:        argc -= optind;
                    181:        argv += optind;
                    182:
                    183:        for (i = 0; i < argc; i++) {
1.2       dlg       184:                struct kstat_filter *kf = kstat_filter_parse(argv[i]);
                    185:                TAILQ_INSERT_TAIL(&kfs, kf, kf_entry);
                    186:        }
1.1       dlg       187:
                    188:        fd = open(DEV_KSTAT, O_RDONLY);
                    189:        if (fd == -1)
                    190:                err(1, "%s", DEV_KSTAT);
                    191:
                    192:        if (ioctl(fd, KSTATIOC_VERSION, &version) == -1)
                    193:                err(1, "kstat version");
                    194:
1.3       dlg       195:        kstat_list(&kt, fd, version, &kfs);
1.13    ! dlg       196:        kstat_read(&kt, fd);
1.3       dlg       197:        kstat_print(&kt);
1.2       dlg       198:
1.10      cheloha   199:        if (wait == 0)
1.5       dlg       200:                return (0);
                    201:
1.10      cheloha   202:        if (signal(SIGALRM, handle_alrm) == SIG_ERR)
                    203:                err(1, "signal");
                    204:        sigemptyset(&empty);
                    205:        sigemptyset(&mask);
                    206:        sigaddset(&mask, SIGALRM);
                    207:        if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
                    208:                err(1, "sigprocmask");
                    209:
                    210:        itv.it_value.tv_sec = wait;
                    211:        itv.it_value.tv_usec = 0;
                    212:        itv.it_interval = itv.it_value;
                    213:        if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
                    214:                err(1, "setitimer");
                    215:
1.5       dlg       216:        for (;;) {
1.10      cheloha   217:                sigsuspend(&empty);
1.5       dlg       218:                kstat_read(&kt, fd);
                    219:                kstat_print(&kt);
                    220:        }
                    221:
1.2       dlg       222:        return (0);
                    223: }
                    224:
                    225: static struct kstat_filter *
                    226: kstat_filter_parse(char *arg)
                    227: {
                    228:        struct kstat_filter *kf;
                    229:        const char *errstr;
                    230:        char *argv[4];
                    231:        size_t argc;
                    232:
                    233:        for (argc = 0; argc < nitems(argv); argc++) {
                    234:                char *s = strsep(&arg, ":");
                    235:                if (s == NULL)
                    236:                        break;
                    237:
                    238:                argv[argc] = s;
                    239:        }
                    240:        if (arg != NULL)
                    241:                usage();
                    242:
                    243:        kf = malloc(sizeof(*kf));
                    244:        if (kf == NULL)
                    245:                err(1, NULL);
                    246:
                    247:        memset(kf, 0, sizeof(*kf));
                    248:
                    249:        switch (argc) {
                    250:        case 1:
                    251:                if (str_is_empty(argv[0]))
                    252:                        errx(1, "empty name");
                    253:
                    254:                kf->kf_name = argv[0];
                    255:                break;
                    256:        case 4:
                    257:                if (!str_is_empty(argv[0]))
                    258:                        kf->kf_provider = argv[0];
                    259:                if (!str_is_empty(argv[1])) {
                    260:                        kf->kf_instance =
                    261:                            strtonum(argv[1], 0, 0xffffffffU, &errstr);
                    262:                        if (errstr != NULL) {
                    263:                                errx(1, "%s:%s:%s:%s: instance %s: %s",
                    264:                                    argv[0], argv[1], argv[2], argv[3],
                    265:                                    argv[1], errstr);
                    266:                        }
                    267:                        SET(kf->kf_flags, KSTAT_FILTER_F_INST);
                    268:                }
                    269:                if (!str_is_empty(argv[2]))
                    270:                        kf->kf_name = argv[2];
                    271:                if (!str_is_empty(argv[3])) {
                    272:                        kf->kf_unit =
                    273:                            strtonum(argv[3], 0, 0xffffffffU, &errstr);
                    274:                        if (errstr != NULL) {
1.8       dlg       275:                                errx(1, "%s:%s:%s:%s: unit %s: %s",
1.2       dlg       276:                                    argv[0], argv[1], argv[2], argv[3],
1.8       dlg       277:                                    argv[3], errstr);
1.2       dlg       278:                        }
1.8       dlg       279:                        SET(kf->kf_flags, KSTAT_FILTER_F_UNIT);
1.2       dlg       280:                }
                    281:                break;
                    282:        default:
                    283:                usage();
                    284:        }
                    285:
                    286:        return (kf);
                    287: }
                    288:
                    289: static int
                    290: kstat_filter_entry(struct kstat_filters *kfs, const struct kstat_req *ksreq)
                    291: {
                    292:        struct kstat_filter *kf;
                    293:
                    294:        if (TAILQ_EMPTY(kfs))
                    295:                return (1);
                    296:
                    297:        TAILQ_FOREACH(kf, kfs, kf_entry) {
                    298:                if (kf->kf_provider != NULL) {
                    299:                        if (fnmatch(kf->kf_provider, ksreq->ks_provider,
                    300:                            FNM_NOESCAPE | FNM_LEADING_DIR) == FNM_NOMATCH)
                    301:                                continue;
                    302:                }
                    303:                if (ISSET(kf->kf_flags, KSTAT_FILTER_F_INST)) {
                    304:                        if (kf->kf_instance != ksreq->ks_instance)
                    305:                                continue;
                    306:                }
                    307:                if (kf->kf_name != NULL) {
                    308:                        if (fnmatch(kf->kf_name, ksreq->ks_name,
                    309:                            FNM_NOESCAPE | FNM_LEADING_DIR) == FNM_NOMATCH)
                    310:                                continue;
                    311:                }
                    312:                if (ISSET(kf->kf_flags, KSTAT_FILTER_F_UNIT)) {
                    313:                        if (kf->kf_unit != ksreq->ks_unit)
                    314:                                continue;
                    315:                }
                    316:
                    317:                return (1);
                    318:        }
1.1       dlg       319:
                    320:        return (0);
                    321: }
                    322:
                    323: static int
                    324: printable(int ch)
                    325: {
                    326:        if (ch == '\0')
                    327:                return ('_');
                    328:        if (!isprint(ch))
                    329:                return ('~');
                    330:        return (ch);
                    331: }
                    332:
                    333: static void
                    334: hexdump(const void *d, size_t datalen)
                    335: {
                    336:        const uint8_t *data = d;
                    337:        size_t i, j = 0;
                    338:
                    339:        for (i = 0; i < datalen; i += j) {
                    340:                printf("%4zu: ", i);
                    341:
                    342:                for (j = 0; j < 16 && i+j < datalen; j++)
                    343:                        printf("%02x ", data[i + j]);
                    344:                while (j++ < 16)
                    345:                        printf("   ");
                    346:                printf("|");
                    347:
                    348:                for (j = 0; j < 16 && i+j < datalen; j++)
                    349:                        putchar(printable(data[i + j]));
                    350:                printf("|\n");
                    351:        }
                    352: }
                    353:
                    354: static void
                    355: strdump(const void *s, size_t len)
                    356: {
                    357:        const char *str = s;
                    358:        char dst[8];
                    359:        size_t i;
                    360:
                    361:        for (i = 0; i < len; i++) {
                    362:                char ch = str[i];
                    363:                if (ch == '\0')
                    364:                        break;
                    365:
                    366:                vis(dst, ch, VIS_TAB | VIS_NL, 0);
                    367:                printf("%s", dst);
                    368:        }
                    369: }
                    370:
                    371: static void
                    372: strdumpnl(const void *s, size_t len)
                    373: {
                    374:        strdump(s, len);
                    375:        printf("\n");
                    376: }
                    377:
1.12      dlg       378: static const char *si_prefixes[] = { "", "k", "M", "G", "T", "P", "E" };
                    379: #ifdef notyet
                    380: static const char *iec_prefixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
                    381: #endif
                    382:
1.1       dlg       383: static void
                    384: kstat_kv(const void *d, ssize_t len)
                    385: {
                    386:        const uint8_t *buf;
                    387:        const struct kstat_kv *kv;
                    388:        ssize_t blen;
                    389:        void (*trailer)(const void *, size_t);
                    390:        double f;
1.12      dlg       391:        struct fmt_result fr;
1.1       dlg       392:
                    393:        if (len < (ssize_t)sizeof(*kv)) {
                    394:                warn("short kv (len %zu < size %zu)", len, sizeof(*kv));
                    395:                return;
                    396:        }
                    397:
                    398:        buf = d;
                    399:        do {
                    400:                kv = (const struct kstat_kv *)buf;
                    401:
                    402:                buf += sizeof(*kv);
                    403:                len -= sizeof(*kv);
                    404:
                    405:                blen = 0;
                    406:                trailer = hexdump;
                    407:
                    408:                printf("%16.16s: ", kv->kv_key);
                    409:
                    410:                switch (kv->kv_type) {
                    411:                case KSTAT_KV_T_NULL:
                    412:                        printf("null");
                    413:                        break;
                    414:                case KSTAT_KV_T_BOOL:
                    415:                        printf("%s", kstat_kv_bool(kv) ? "true" : "false");
                    416:                        break;
                    417:                case KSTAT_KV_T_COUNTER64:
                    418:                case KSTAT_KV_T_UINT64:
                    419:                        printf("%" PRIu64, kstat_kv_u64(kv));
                    420:                        break;
                    421:                case KSTAT_KV_T_INT64:
                    422:                        printf("%" PRId64, kstat_kv_s64(kv));
                    423:                        break;
                    424:                case KSTAT_KV_T_COUNTER32:
                    425:                case KSTAT_KV_T_UINT32:
                    426:                        printf("%" PRIu32, kstat_kv_u32(kv));
                    427:                        break;
                    428:                case KSTAT_KV_T_INT32:
                    429:                        printf("%" PRId32, kstat_kv_s32(kv));
1.9       dlg       430:                        break;
                    431:                case KSTAT_KV_T_COUNTER16:
                    432:                case KSTAT_KV_T_UINT16:
                    433:                        printf("%" PRIu16, kstat_kv_u16(kv));
                    434:                        break;
                    435:                case KSTAT_KV_T_INT16:
                    436:                        printf("%" PRId16, kstat_kv_s16(kv));
1.1       dlg       437:                        break;
                    438:                case KSTAT_KV_T_STR:
                    439:                        blen = kstat_kv_len(kv);
                    440:                        trailer = strdumpnl;
                    441:                        break;
                    442:                case KSTAT_KV_T_BYTES:
                    443:                        blen = kstat_kv_len(kv);
                    444:                        trailer = hexdump;
                    445:
                    446:                        printf("\n");
                    447:                        break;
                    448:
                    449:                case KSTAT_KV_T_ISTR:
                    450:                        strdump(kstat_kv_istr(kv), sizeof(kstat_kv_istr(kv)));
                    451:                        break;
                    452:
                    453:                case KSTAT_KV_T_TEMP:
                    454:                        f = kstat_kv_temp(kv);
                    455:                        printf("%.2f degC", (f - 273150000.0) / 1000000.0);
1.12      dlg       456:                        break;
                    457:
                    458:                case KSTAT_KV_T_FREQ:
                    459:                        fmt_thing(&fr, kstat_kv_freq(kv), 1000);
                    460:                        printf("%llu", fr.val);
                    461:                        if (fr.frac > 10)
                    462:                                printf(".%02u", fr.frac / 10);
                    463:                        printf(" %sHz", si_prefixes[fr.exp]);
                    464:                        break;
                    465:
                    466:                case KSTAT_KV_T_VOLTS_DC: /* uV */
                    467:                        f = kstat_kv_volts(kv);
                    468:                        printf("%.2f VDC", f / 1000000.0);
                    469:                        break;
                    470:
                    471:                case KSTAT_KV_T_VOLTS_AC: /* uV */
                    472:                        f = kstat_kv_volts(kv);
                    473:                        printf("%.2f VAC", f / 1000000.0);
1.1       dlg       474:                        break;
                    475:
                    476:                default:
                    477:                        printf("unknown type %u, stopping\n", kv->kv_type);
                    478:                        return;
                    479:                }
                    480:
                    481:                switch (kv->kv_unit) {
                    482:                case KSTAT_KV_U_NONE:
                    483:                        break;
                    484:                case KSTAT_KV_U_PACKETS:
                    485:                        printf(" packets");
                    486:                        break;
                    487:                case KSTAT_KV_U_BYTES:
                    488:                        printf(" bytes");
                    489:                        break;
                    490:                case KSTAT_KV_U_CYCLES:
                    491:                        printf(" cycles");
                    492:                        break;
                    493:
                    494:                default:
                    495:                        printf(" unit-type-%u", kv->kv_unit);
                    496:                        break;
                    497:                }
                    498:
                    499:                if (blen > 0) {
                    500:                        if (blen > len) {
                    501:                                blen = len;
                    502:                        }
                    503:
                    504:                        (*trailer)(buf, blen);
                    505:                } else
                    506:                        printf("\n");
                    507:
                    508:                blen = roundup(blen, KSTAT_KV_ALIGN);
                    509:                buf += blen;
                    510:                len -= blen;
                    511:        } while (len >= (ssize_t)sizeof(*kv));
                    512: }
                    513:
                    514: static void
1.3       dlg       515: kstat_list(struct kstat_tree *kt, int fd, unsigned int version,
                    516:     struct kstat_filters *kfs)
1.1       dlg       517: {
                    518:        struct kstat_entry *kse;
                    519:        struct kstat_req *ksreq;
                    520:        uint64_t id = 0;
                    521:
                    522:        for (;;) {
                    523:                kse = malloc(sizeof(*kse));
                    524:                if (kse == NULL)
                    525:                        err(1, NULL);
                    526:
                    527:                memset(kse, 0, sizeof(*kse));
                    528:                ksreq = &kse->kstat;
                    529:                ksreq->ks_version = version;
                    530:                ksreq->ks_id = ++id;
                    531:
                    532:                if (ioctl(fd, KSTATIOC_NFIND_ID, ksreq) == -1) {
                    533:                        if (errno == ENOENT) {
                    534:                                free(ksreq->ks_data);
                    535:                                free(kse);
                    536:                                break;
                    537:                        }
1.2       dlg       538:                } else
                    539:                        id = ksreq->ks_id;
                    540:
                    541:                if (!kstat_filter_entry(kfs, ksreq)) {
                    542:                        free(ksreq->ks_data);
                    543:                        free(kse);
                    544:                        continue;
1.1       dlg       545:                }
                    546:
1.3       dlg       547:                if (RBT_INSERT(kstat_tree, kt, kse) != NULL)
1.2       dlg       548:                        errx(1, "duplicate kstat entry");
                    549:
1.13    ! dlg       550:                ksreq->ks_data = malloc(ksreq->ks_datalen);
        !           551:                if (ksreq->ks_data == NULL)
        !           552:                        err(1, "kstat data alloc");
1.1       dlg       553:        }
1.3       dlg       554: }
                    555:
                    556: static void
                    557: kstat_print(struct kstat_tree *kt)
                    558: {
                    559:        struct kstat_entry *kse;
                    560:        struct kstat_req *ksreq;
1.1       dlg       561:
1.3       dlg       562:        RBT_FOREACH(kse, kstat_tree, kt) {
1.1       dlg       563:                ksreq = &kse->kstat;
                    564:                printf("%s:%u:%s:%u\n",
                    565:                    ksreq->ks_provider, ksreq->ks_instance,
                    566:                    ksreq->ks_name, ksreq->ks_unit);
                    567:                if (kse->serrno != 0) {
1.13    ! dlg       568:                        printf("\tkstat read error: %s\n",
        !           569:                            strerror(kse->serrno));
1.1       dlg       570:                        continue;
                    571:                }
                    572:                switch (ksreq->ks_type) {
                    573:                case KSTAT_T_RAW:
                    574:                        hexdump(ksreq->ks_data, ksreq->ks_datalen);
                    575:                        break;
                    576:                case KSTAT_T_KV:
                    577:                        kstat_kv(ksreq->ks_data, ksreq->ks_datalen);
                    578:                        break;
                    579:                default:
                    580:                        hexdump(ksreq->ks_data, ksreq->ks_datalen);
                    581:                        break;
                    582:                }
1.5       dlg       583:        }
1.7       dlg       584:
                    585:        fflush(stdout);
1.5       dlg       586: }
                    587:
                    588: static void
                    589: kstat_read(struct kstat_tree *kt, int fd)
                    590: {
                    591:        struct kstat_entry *kse;
                    592:        struct kstat_req *ksreq;
                    593:
                    594:        RBT_FOREACH(kse, kstat_tree, kt) {
1.13    ! dlg       595:                kse->serrno = 0;
1.5       dlg       596:                ksreq = &kse->kstat;
                    597:                if (ioctl(fd, KSTATIOC_FIND_ID, ksreq) == -1)
1.13    ! dlg       598:                        kse->serrno = errno;
1.1       dlg       599:        }
1.10      cheloha   600: }
                    601:
                    602: static void
                    603: handle_alrm(int signo)
                    604: {
1.1       dlg       605: }