1*40358Smarc /* 2*40358Smarc * Copyright (c) 1989 The Regents of the University of California. 3*40358Smarc * All rights reserved. 4*40358Smarc * 5*40358Smarc * Redistribution and use in source and binary forms is permitted 6*40358Smarc * provided that all copyright information, including this notice, 7*40358Smarc * is retained in all such forms, and that any documentation, 8*40358Smarc * advertising or other materials related to such distribution and 9*40358Smarc * use acknowledge that the software was 10*40358Smarc * developed by the University of California, Berkeley. The name 11*40358Smarc * of the University may not be used to endorse or promote products 12*40358Smarc * derived from this software without specific prior written permission. 13*40358Smarc * 14*40358Smarc * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15*40358Smarc * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16*40358Smarc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17*40358Smarc */ 18*40358Smarc 19*40358Smarc #ifndef lint 20*40358Smarc char copyright[] = 21*40358Smarc "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 22*40358Smarc All rights reserved.\n"; 23*40358Smarc #endif /* not lint */ 24*40358Smarc 25*40358Smarc /* 26*40358Smarc * kvm_mkdb -- Create kernel information database for running kernel. 27*40358Smarc */ 28*40358Smarc 29*40358Smarc #ifndef lint 30*40358Smarc static char sccsid[] = "@(#)kvm_mkdb.c 5.1 (Berkeley) 03/07/90"; 31*40358Smarc #endif /* not lint */ 32*40358Smarc #include <sys/param.h> 33*40358Smarc #include <sys/file.h> 34*40358Smarc #include <ndbm.h> 35*40358Smarc #include <a.out.h> 36*40358Smarc #include <kvm.h> 37*40358Smarc #include <paths.h> 38*40358Smarc #include <limits.h> 39*40358Smarc #include <errno.h> 40*40358Smarc #include <strings.h> 41*40358Smarc #include <stdio.h> 42*40358Smarc 43*40358Smarc char *tmp; 44*40358Smarc #define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp)) 45*40358Smarc #define USAGE "kvm_mkdb" 46*40358Smarc extern errno; 47*40358Smarc 48*40358Smarc char *progname; 49*40358Smarc 50*40358Smarc main(argc, argv) 51*40358Smarc char *argv[]; 52*40358Smarc { 53*40358Smarc DBM *db; 54*40358Smarc char *nlistpath, *nlistname; 55*40358Smarc char dbtemp[MAXPATHLEN]; 56*40358Smarc char dbname[MAXPATHLEN]; 57*40358Smarc extern char *optarg; 58*40358Smarc extern int optind; 59*40358Smarc int ch; 60*40358Smarc 61*40358Smarc progname = argv[0]; 62*40358Smarc while ((ch = getopt(argc, argv, "")) != EOF) 63*40358Smarc switch((char)ch) { 64*40358Smarc case '?': 65*40358Smarc default: 66*40358Smarc fprintf(stderr, "usage: %s", progname, USAGE); 67*40358Smarc exit(1); 68*40358Smarc } 69*40358Smarc argc -= optind; 70*40358Smarc argv += optind; 71*40358Smarc 72*40358Smarc nlistpath = argc > 1 ? argv[0] : _PATH_UNIX; 73*40358Smarc nlistname = basename(nlistpath); 74*40358Smarc sprintf(dbtemp, "%s/kvm_tmp%s", KVMDBDIR, nlistname); 75*40358Smarc sprintf(dbname, "%s/kvm_%s", KVMDBDIR, nlistname); 76*40358Smarc rmdb(dbtemp); 77*40358Smarc umask(0); 78*40358Smarc if ((db = dbm_open(dbtemp, O_CREAT|O_WRONLY|O_EXCL, 0644)) == NULL) 79*40358Smarc syserrexit("error opening dbmfile"); 80*40358Smarc if (create_knlist(nlistpath, db) == -1) 81*40358Smarc errexit("error creating kernel namelist"); 82*40358Smarc if (create_devnames(db) == -1) 83*40358Smarc errexit("error creating devnames"); 84*40358Smarc rmdb(dbname); 85*40358Smarc mvdb(dbtemp, dbname); 86*40358Smarc 87*40358Smarc exit(0); 88*40358Smarc } 89*40358Smarc 90*40358Smarc rmdb(file) 91*40358Smarc char *file; 92*40358Smarc { 93*40358Smarc int len = strlen(file); 94*40358Smarc 95*40358Smarc if (len > (MAXPATHLEN - 5)) 96*40358Smarc errexit("pathname too long: %s", file); 97*40358Smarc strcpy(file+len, ".dir"); 98*40358Smarc if (unlink(file) < 0 && errno != ENOENT) 99*40358Smarc syserrexit("can't unlink %s", file); 100*40358Smarc strcpy(file+len, ".pag"); 101*40358Smarc if (unlink(file) < 0 && errno != ENOENT) 102*40358Smarc syserrexit("can't unlink %s", file); 103*40358Smarc *(file+len) = '\0'; 104*40358Smarc } 105*40358Smarc 106*40358Smarc mvdb(from, to) 107*40358Smarc char *from; 108*40358Smarc char *to; 109*40358Smarc { 110*40358Smarc int flen = strlen(from); 111*40358Smarc int tlen = strlen(to); 112*40358Smarc 113*40358Smarc if (flen > (MAXPATHLEN - 5) || tlen > (MAXPATHLEN - 5)) 114*40358Smarc errexit("pathname too long: %s or %s", from, to); 115*40358Smarc strcpy(from+flen, ".dir"); 116*40358Smarc strcpy(to+tlen, ".dir"); 117*40358Smarc if (rename(from, to) == -1) 118*40358Smarc syserrexit("rename %s to %s", from, to); 119*40358Smarc strcpy(from+flen, ".pag"); 120*40358Smarc strcpy(to+tlen, ".pag"); 121*40358Smarc if (rename(from, to) == -1) 122*40358Smarc syserrexit("rename %s to %s", from, to); 123*40358Smarc *(from+flen) = *(to+tlen) = '\0'; 124*40358Smarc } 125*40358Smarc 126*40358Smarc /* from libc/nlist.c */ 127*40358Smarc #include <unistd.h> 128*40358Smarc 129*40358Smarc typedef struct nlist NLIST; 130*40358Smarc #define _strx n_un.n_strx 131*40358Smarc #define _name n_un.n_name 132*40358Smarc #define ISVALID(p) (p->_name && p->_name[0]) 133*40358Smarc #define MAXSYMSIZE 256 134*40358Smarc 135*40358Smarc create_knlist(name, db) 136*40358Smarc char *name; 137*40358Smarc DBM *db; 138*40358Smarc { 139*40358Smarc register NLIST *p, *s; 140*40358Smarc struct exec ebuf; 141*40358Smarc FILE *fstr, *fsym; 142*40358Smarc NLIST nbuf; 143*40358Smarc off_t strings_offset, symbol_offset, symbol_size, lseek(); 144*40358Smarc char sbuf[MAXSYMSIZE+1]; 145*40358Smarc register char *bp; 146*40358Smarc register int c, len; 147*40358Smarc datum key, data; 148*40358Smarc 149*40358Smarc if (!(fsym = fopen(name, "r"))) 150*40358Smarc syserrexit("can't open %s", name); 151*40358Smarc if (fread((char *)&ebuf, sizeof(struct exec), 1, fsym) != 1 || 152*40358Smarc N_BADMAG(ebuf)) 153*40358Smarc syserrexit("can't read exec"); 154*40358Smarc 155*40358Smarc symbol_offset = N_SYMOFF(ebuf); 156*40358Smarc symbol_size = ebuf.a_syms; 157*40358Smarc strings_offset = symbol_offset + symbol_size; 158*40358Smarc 159*40358Smarc if (fseek(fsym, symbol_offset, SEEK_SET) == -1) 160*40358Smarc syserrexit("can't seek symbol table: %x", symbol_offset); 161*40358Smarc if ((fstr = fopen(name, "r")) == NULL) 162*40358Smarc syserrexit("can't open %s", name); 163*40358Smarc 164*40358Smarc sbuf[0] = KVMDB_NLIST; 165*40358Smarc key.dptr = sbuf; 166*40358Smarc data.dptr = (char *)&nbuf; 167*40358Smarc data.dsize = sizeof (NLIST); 168*40358Smarc 169*40358Smarc for (s = &nbuf; symbol_size; symbol_size -= sizeof (NLIST)) { 170*40358Smarc if (fread((char *)s, sizeof (NLIST), 1, fsym) != 1) 171*40358Smarc syserrexit("can't read nlist entry"); 172*40358Smarc if (!s->_strx || s->n_type&N_STAB) 173*40358Smarc continue; 174*40358Smarc if (fseek(fstr, strings_offset + s->_strx, SEEK_SET) == -1) 175*40358Smarc syserrexit("can't seek string: %x", 176*40358Smarc strings_offset + s->_strx); 177*40358Smarc /* 178*40358Smarc * read string 179*40358Smarc */ 180*40358Smarc bp = sbuf + 1; 181*40358Smarc len = 0; 182*40358Smarc while ((c = fgetc(fstr)) != EOF && c != '\0') { 183*40358Smarc if (++len == MAXSYMSIZE) 184*40358Smarc errexit("string too long"); 185*40358Smarc *bp++ = c; 186*40358Smarc } 187*40358Smarc *bp = '\0'; 188*40358Smarc /* 189*40358Smarc * and store it 190*40358Smarc */ 191*40358Smarc key.dsize = bp - sbuf; 192*40358Smarc if (dbm_store(db, key, data, DBM_INSERT) < 0) 193*40358Smarc syserrexit("dbm_store"); 194*40358Smarc if (strcmp(sbuf+1, "_version") == 0) { 195*40358Smarc /* 196*40358Smarc * store the value of version in VERSION 197*40358Smarc */ 198*40358Smarc datum vers; 199*40358Smarc char versbuf[LINE_MAX]; 200*40358Smarc long versoff; 201*40358Smarc long reloffset; 202*40358Smarc 203*40358Smarc /* 204*40358Smarc * Offset relative to start of text image in VM. 205*40358Smarc * On tahoe, first 0x800 is reserved for 206*40358Smarc * communication with the console processor. 207*40358Smarc */ 208*40358Smarc #ifdef tahoe 209*40358Smarc reloffset = ((s->n_value & ~KERNBASE) - 0x800); 210*40358Smarc #endif 211*40358Smarc #ifdef vax 212*40358Smarc reloffset = (s->n_value & ~KERNBASE); 213*40358Smarc #endif 214*40358Smarc /* 215*40358Smarc * When loaded, data is rounded 216*40358Smarc * to next 1024 after text, but not in file. 217*40358Smarc */ 218*40358Smarc reloffset -= 1024 - (ebuf.a_text % 1024); 219*40358Smarc versoff = N_TXTOFF(ebuf) + reloffset; 220*40358Smarc if (fseek(fstr, versoff, SEEK_SET) == -1) 221*40358Smarc syserrexit("seek (version): %x", s->n_value); 222*40358Smarc /* 223*40358Smarc * Just read version string up to, and 224*40358Smarc * including newline. 225*40358Smarc */ 226*40358Smarc if (fgets(versbuf, LINE_MAX, fstr) == NULL) 227*40358Smarc syserrexit("can't read version"); 228*40358Smarc strcpy(sbuf+1, "VERSION"); 229*40358Smarc key.dsize = (sizeof ("VERSION") - 1) + 1; 230*40358Smarc vers.dptr = versbuf; 231*40358Smarc vers.dsize = strlen(versbuf); 232*40358Smarc if (dbm_store(db, key, vers, DBM_INSERT) < 0) 233*40358Smarc syserrexit("dbm_store: can't store VERSION"); 234*40358Smarc } 235*40358Smarc } 236*40358Smarc (void)fclose(fstr); 237*40358Smarc (void)fclose(fsym); 238*40358Smarc return (0); 239*40358Smarc } 240*40358Smarc 241*40358Smarc create_devnames() {} 242*40358Smarc 243*40358Smarc #include <varargs.h> 244*40358Smarc 245*40358Smarc warning(va_alist) 246*40358Smarc va_dcl 247*40358Smarc { 248*40358Smarc char *fmt; 249*40358Smarc va_list ap; 250*40358Smarc 251*40358Smarc fprintf(stderr, "%s: warning: ", progname); 252*40358Smarc va_start(ap); 253*40358Smarc fmt = va_arg(ap, char *); 254*40358Smarc (void) vfprintf(stderr, fmt, ap); 255*40358Smarc va_end(ap); 256*40358Smarc fprintf(stderr, "\n"); 257*40358Smarc } 258*40358Smarc 259*40358Smarc 260*40358Smarc errexit(va_alist) 261*40358Smarc va_dcl 262*40358Smarc { 263*40358Smarc char *fmt; 264*40358Smarc va_list ap; 265*40358Smarc 266*40358Smarc fprintf(stderr, "%s: ", progname); 267*40358Smarc va_start(ap); 268*40358Smarc fmt = va_arg(ap, char *); 269*40358Smarc (void) vfprintf(stderr, fmt, ap); 270*40358Smarc va_end(ap); 271*40358Smarc fprintf(stderr, "\n"); 272*40358Smarc exit(1); 273*40358Smarc } 274*40358Smarc 275*40358Smarc 276*40358Smarc syserrexit(va_alist) 277*40358Smarc va_dcl 278*40358Smarc { 279*40358Smarc char *fmt; 280*40358Smarc va_list ap; 281*40358Smarc 282*40358Smarc fprintf(stderr, "%s: ", progname); 283*40358Smarc va_start(ap); 284*40358Smarc fmt = va_arg(ap, char *); 285*40358Smarc (void) vfprintf(stderr, fmt, ap); 286*40358Smarc va_end(ap); 287*40358Smarc fprintf(stderr, ": %s\n", strerror(errno)); 288*40358Smarc exit(1); 289*40358Smarc } 290