To aid in debugging problems with autopush, I've put together a
small program to dump out the autopush table (I still can't get
"autopush -g" to work and I'd be interested to know if anyone can.)

The advantage with this over "ifconfig -a modlist" is that it
should report unplumbed devices too :)

If it compiles without problem, it should "just work" if run as root.

cc dumpap.c -o dumpac -lkvm
gcc dumpap.c -o dumpac -lkvm

Darren

#include <sys/types.h>
#include <sys/conf.h>
#include <sys/stream.h>
#define _KERNEL
#include <sys/sad.h>
#undef _KERNEL

#include <stdio.h>
#include <malloc.h>
#include <fcntl.h>
#include <kvm.h>
#include <nlist.h>
#include <string.h>

struct nlist names[] = {
        { "strpcache" },
        { "strpmask" },
        { "" }
};


struct majordevice {
        char *name;
        int major;
};

struct majordevice **majors;

void read_nametomajor(void);
void buildaplist(kvm_t *k, struct autopush **where);
void printap(struct autopush *a);

int
main(int argc, char *argv[])
{
        struct autopush **base, **local, *a;
        int apsize, i;
        kvm_t *k;

        read_nametomajor();

        k = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0]);
        if (k == NULL) {
                perror("kvm_open");
                exit(1);
        }

        if (kvm_nlist(k, names) == -1) {
                fprintf(stderr, "kvm_nlist failed\n");
                exit(1);
        }

        if (kvm_kread(k, names[0].n_value, &base, sizeof(base)) == -1) {
                fprintf(stderr, "kvm_kread failed for strpcache\n");
                exit(1);
        }

        if (kvm_kread(k, names[1].n_value, &apsize, sizeof(apsize)) == -1) {
                fprintf(stderr, "kvm_kread failed for strpmsk\n");
                exit(1);
        }

        local = calloc(apsize, sizeof(*local));
        if (local == NULL) {
                fprintf(stderr, "calloc failed for (%d,%u)\n",
                        apsize, sizeof(*local));
                exit(1);
        }

        if (kvm_kread(k, (u_long)base, local, apsize * sizeof(*local)) == -1) {
                fprintf(stderr, "kvm_kread failed to get strpcache\n");
                exit(1);
        }

        for (i = 0; i < apsize; i++) {
                if (local[i] == NULL)
                        continue;
                buildaplist(k, local + i);
        }

        for (i = 0; i < apsize; i++) {
                for (a = local[i]; a != NULL; a = a->ap_nextp)
                        printap(a);
        }

        exit(0);
}


void
buildaplist(kvm_t *k, struct autopush **where)
{
        struct autopush *a, *n, **p;

        for (p = where; (n = *p) != NULL; p = &a->ap_nextp) {
                a = malloc(sizeof(*a));
                if (a == NULL) {
                        fprintf(stderr, "malloc sizeof(%u) failed\n",
                                sizeof(*a));
                        break;
                }
                *p = a;
                if (kvm_kread(k, (u_long)n, a, sizeof(*a)) == -1) {
                        fprintf(stderr, "kvm_kread n->a failed\n");
                        break;
                }
        }
        *p = NULL;
}


void
printap(struct autopush *a)
{
        int i;

        if (a->ap_flags == APFREE)
                return;

#if 0
        switch (a->ap_common.apc_cmd)
        {
        case SAP_CLEAR :
                printf("CLEAR");
                break;
        case SAP_ONE :
                printf("ONE");
                break;
        case SAP_RANGE :
                printf("RANGE");
                break;
        case SAP_ALL :
                printf("ALL");
                break;
        default :
                break;
        }
#endif

        printf("%s", majors[a->ap_common.apc_major]->name);
        if (a->ap_common.apc_cmd == SAP_RANGE)
                printf(" [%d-%d]", a->ap_common.apc_minor,
                        a->ap_common.apc_lastminor);
/*              a->ap_common.apc_npush);*/
#if 0
        printf("\tUse %d flags %x\n", a->ap_cnt, a->ap_flags);
#endif

        putchar(':');
        for (i = 0; i < a->ap_common.apc_npush; i++)
                if (a->ap_list[i][0] != '\0')
                        printf(" %s", a->ap_list[i]);
                else
                        printf(" ???");
        putchar('\n');
}

void
read_nametomajor()
{
        struct majordevice *maj, **all;
        int ndevices, maxmajor, i;
        char line[512], *s;
        FILE *fp;

        fp = fopen("/etc/name_to_major", "r");
        if (fp == NULL)
                return;

        maxmajor = 0;
        ndevices = 1;
        all = malloc(sizeof(*all));
        if (all == NULL)
                return;

        while (fgets(line, sizeof(line) - 1, fp) != NULL) {
                s = strchr(line, '\n');
                if (s != NULL)
                        *s = NULL;
                else
                        continue;
                s = strchr(line, ' ');
                if (s == NULL)
                        continue;
                *s++ = '\0';
                if (!isdigit(*s))
                        continue;

                maj = malloc(sizeof(*maj));
                maj->name = strdup(line);
                maj->major = atoi(s);
                if (maj->major > maxmajor)
                        maxmajor = maj->major;
                all[ndevices - 1] = maj;
                ndevices++;
                all = realloc(all, ndevices * sizeof(*all));
                if (all == NULL)
                        return;
                all[ndevices - 1] = NULL;
        }

        majors = calloc(maxmajor + 1, sizeof(*majors));
        if (all == NULL)
                return;

        for (i = 0; i < ndevices; i++) {
                maj = all[i];
                if (maj == NULL)
                        continue;
                majors[maj->major] = maj;
        }

        fclose(fp);
}

Reply via email to