140358Smarc /* 240358Smarc * Copyright (c) 1989 The Regents of the University of California. 340358Smarc * All rights reserved. 440358Smarc * 540358Smarc * Redistribution and use in source and binary forms is permitted 640358Smarc * provided that all copyright information, including this notice, 740358Smarc * is retained in all such forms, and that any documentation, 840358Smarc * advertising or other materials related to such distribution and 940358Smarc * use acknowledge that the software was 1040358Smarc * developed by the University of California, Berkeley. The name 1140358Smarc * of the University may not be used to endorse or promote products 1240358Smarc * derived from this software without specific prior written permission. 1340358Smarc * 1440358Smarc * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1540358Smarc * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1640358Smarc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1740358Smarc */ 1840358Smarc 1940358Smarc #ifndef lint 2040358Smarc char copyright[] = 2140358Smarc "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 2240358Smarc All rights reserved.\n"; 2340358Smarc #endif /* not lint */ 2440358Smarc 2540358Smarc /* 2640358Smarc * kvm_mkdb -- Create kernel information database for running kernel. 2740358Smarc */ 2840358Smarc 2940358Smarc #ifndef lint 30*42064Sbostic static char sccsid[] = "@(#)kvm_mkdb.c 5.2 (Berkeley) 05/15/90"; 3140358Smarc #endif /* not lint */ 3240358Smarc #include <sys/param.h> 3340358Smarc #include <sys/file.h> 3440358Smarc #include <ndbm.h> 3540358Smarc #include <a.out.h> 3640358Smarc #include <kvm.h> 3740358Smarc #include <paths.h> 3840358Smarc #include <limits.h> 3940358Smarc #include <errno.h> 40*42064Sbostic #include <string.h> 4140358Smarc #include <stdio.h> 4240358Smarc 4340358Smarc char *tmp; 4440358Smarc #define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp)) 4540358Smarc #define USAGE "kvm_mkdb" 4640358Smarc extern errno; 4740358Smarc 4840358Smarc char *progname; 4940358Smarc 5040358Smarc main(argc, argv) 5140358Smarc char *argv[]; 5240358Smarc { 5340358Smarc DBM *db; 5440358Smarc char *nlistpath, *nlistname; 5540358Smarc char dbtemp[MAXPATHLEN]; 5640358Smarc char dbname[MAXPATHLEN]; 5740358Smarc extern char *optarg; 5840358Smarc extern int optind; 5940358Smarc int ch; 6040358Smarc 6140358Smarc progname = argv[0]; 6240358Smarc while ((ch = getopt(argc, argv, "")) != EOF) 6340358Smarc switch((char)ch) { 6440358Smarc case '?': 6540358Smarc default: 6640358Smarc fprintf(stderr, "usage: %s", progname, USAGE); 6740358Smarc exit(1); 6840358Smarc } 6940358Smarc argc -= optind; 7040358Smarc argv += optind; 7140358Smarc 7240358Smarc nlistpath = argc > 1 ? argv[0] : _PATH_UNIX; 7340358Smarc nlistname = basename(nlistpath); 7440358Smarc sprintf(dbtemp, "%s/kvm_tmp%s", KVMDBDIR, nlistname); 7540358Smarc sprintf(dbname, "%s/kvm_%s", KVMDBDIR, nlistname); 7640358Smarc rmdb(dbtemp); 7740358Smarc umask(0); 7840358Smarc if ((db = dbm_open(dbtemp, O_CREAT|O_WRONLY|O_EXCL, 0644)) == NULL) 7940358Smarc syserrexit("error opening dbmfile"); 8040358Smarc if (create_knlist(nlistpath, db) == -1) 8140358Smarc errexit("error creating kernel namelist"); 8240358Smarc if (create_devnames(db) == -1) 8340358Smarc errexit("error creating devnames"); 8440358Smarc rmdb(dbname); 8540358Smarc mvdb(dbtemp, dbname); 8640358Smarc 8740358Smarc exit(0); 8840358Smarc } 8940358Smarc 9040358Smarc rmdb(file) 9140358Smarc char *file; 9240358Smarc { 9340358Smarc int len = strlen(file); 9440358Smarc 9540358Smarc if (len > (MAXPATHLEN - 5)) 9640358Smarc errexit("pathname too long: %s", file); 9740358Smarc strcpy(file+len, ".dir"); 9840358Smarc if (unlink(file) < 0 && errno != ENOENT) 9940358Smarc syserrexit("can't unlink %s", file); 10040358Smarc strcpy(file+len, ".pag"); 10140358Smarc if (unlink(file) < 0 && errno != ENOENT) 10240358Smarc syserrexit("can't unlink %s", file); 10340358Smarc *(file+len) = '\0'; 10440358Smarc } 10540358Smarc 10640358Smarc mvdb(from, to) 10740358Smarc char *from; 10840358Smarc char *to; 10940358Smarc { 11040358Smarc int flen = strlen(from); 11140358Smarc int tlen = strlen(to); 11240358Smarc 11340358Smarc if (flen > (MAXPATHLEN - 5) || tlen > (MAXPATHLEN - 5)) 11440358Smarc errexit("pathname too long: %s or %s", from, to); 11540358Smarc strcpy(from+flen, ".dir"); 11640358Smarc strcpy(to+tlen, ".dir"); 11740358Smarc if (rename(from, to) == -1) 11840358Smarc syserrexit("rename %s to %s", from, to); 11940358Smarc strcpy(from+flen, ".pag"); 12040358Smarc strcpy(to+tlen, ".pag"); 12140358Smarc if (rename(from, to) == -1) 12240358Smarc syserrexit("rename %s to %s", from, to); 12340358Smarc *(from+flen) = *(to+tlen) = '\0'; 12440358Smarc } 12540358Smarc 12640358Smarc /* from libc/nlist.c */ 12740358Smarc #include <unistd.h> 12840358Smarc 12940358Smarc typedef struct nlist NLIST; 13040358Smarc #define _strx n_un.n_strx 13140358Smarc #define _name n_un.n_name 13240358Smarc #define ISVALID(p) (p->_name && p->_name[0]) 13340358Smarc #define MAXSYMSIZE 256 13440358Smarc 13540358Smarc create_knlist(name, db) 13640358Smarc char *name; 13740358Smarc DBM *db; 13840358Smarc { 13940358Smarc register NLIST *p, *s; 14040358Smarc struct exec ebuf; 14140358Smarc FILE *fstr, *fsym; 14240358Smarc NLIST nbuf; 14340358Smarc off_t strings_offset, symbol_offset, symbol_size, lseek(); 14440358Smarc char sbuf[MAXSYMSIZE+1]; 14540358Smarc register char *bp; 14640358Smarc register int c, len; 14740358Smarc datum key, data; 14840358Smarc 14940358Smarc if (!(fsym = fopen(name, "r"))) 15040358Smarc syserrexit("can't open %s", name); 15140358Smarc if (fread((char *)&ebuf, sizeof(struct exec), 1, fsym) != 1 || 15240358Smarc N_BADMAG(ebuf)) 15340358Smarc syserrexit("can't read exec"); 15440358Smarc 15540358Smarc symbol_offset = N_SYMOFF(ebuf); 15640358Smarc symbol_size = ebuf.a_syms; 15740358Smarc strings_offset = symbol_offset + symbol_size; 15840358Smarc 15940358Smarc if (fseek(fsym, symbol_offset, SEEK_SET) == -1) 16040358Smarc syserrexit("can't seek symbol table: %x", symbol_offset); 16140358Smarc if ((fstr = fopen(name, "r")) == NULL) 16240358Smarc syserrexit("can't open %s", name); 16340358Smarc 16440358Smarc sbuf[0] = KVMDB_NLIST; 16540358Smarc key.dptr = sbuf; 16640358Smarc data.dptr = (char *)&nbuf; 16740358Smarc data.dsize = sizeof (NLIST); 16840358Smarc 16940358Smarc for (s = &nbuf; symbol_size; symbol_size -= sizeof (NLIST)) { 17040358Smarc if (fread((char *)s, sizeof (NLIST), 1, fsym) != 1) 17140358Smarc syserrexit("can't read nlist entry"); 17240358Smarc if (!s->_strx || s->n_type&N_STAB) 17340358Smarc continue; 17440358Smarc if (fseek(fstr, strings_offset + s->_strx, SEEK_SET) == -1) 17540358Smarc syserrexit("can't seek string: %x", 17640358Smarc strings_offset + s->_strx); 17740358Smarc /* 17840358Smarc * read string 17940358Smarc */ 18040358Smarc bp = sbuf + 1; 18140358Smarc len = 0; 18240358Smarc while ((c = fgetc(fstr)) != EOF && c != '\0') { 18340358Smarc if (++len == MAXSYMSIZE) 18440358Smarc errexit("string too long"); 18540358Smarc *bp++ = c; 18640358Smarc } 18740358Smarc *bp = '\0'; 18840358Smarc /* 18940358Smarc * and store it 19040358Smarc */ 19140358Smarc key.dsize = bp - sbuf; 19240358Smarc if (dbm_store(db, key, data, DBM_INSERT) < 0) 19340358Smarc syserrexit("dbm_store"); 19440358Smarc if (strcmp(sbuf+1, "_version") == 0) { 19540358Smarc /* 19640358Smarc * store the value of version in VERSION 19740358Smarc */ 19840358Smarc datum vers; 19940358Smarc char versbuf[LINE_MAX]; 20040358Smarc long versoff; 20140358Smarc long reloffset; 20240358Smarc 20340358Smarc /* 20440358Smarc * Offset relative to start of text image in VM. 20540358Smarc * On tahoe, first 0x800 is reserved for 20640358Smarc * communication with the console processor. 20740358Smarc */ 20840358Smarc #ifdef tahoe 20940358Smarc reloffset = ((s->n_value & ~KERNBASE) - 0x800); 21040358Smarc #endif 21140358Smarc #ifdef vax 21240358Smarc reloffset = (s->n_value & ~KERNBASE); 21340358Smarc #endif 21440358Smarc /* 21540358Smarc * When loaded, data is rounded 21640358Smarc * to next 1024 after text, but not in file. 21740358Smarc */ 21840358Smarc reloffset -= 1024 - (ebuf.a_text % 1024); 21940358Smarc versoff = N_TXTOFF(ebuf) + reloffset; 22040358Smarc if (fseek(fstr, versoff, SEEK_SET) == -1) 22140358Smarc syserrexit("seek (version): %x", s->n_value); 22240358Smarc /* 22340358Smarc * Just read version string up to, and 22440358Smarc * including newline. 22540358Smarc */ 22640358Smarc if (fgets(versbuf, LINE_MAX, fstr) == NULL) 22740358Smarc syserrexit("can't read version"); 22840358Smarc strcpy(sbuf+1, "VERSION"); 22940358Smarc key.dsize = (sizeof ("VERSION") - 1) + 1; 23040358Smarc vers.dptr = versbuf; 23140358Smarc vers.dsize = strlen(versbuf); 23240358Smarc if (dbm_store(db, key, vers, DBM_INSERT) < 0) 23340358Smarc syserrexit("dbm_store: can't store VERSION"); 23440358Smarc } 23540358Smarc } 23640358Smarc (void)fclose(fstr); 23740358Smarc (void)fclose(fsym); 23840358Smarc return (0); 23940358Smarc } 24040358Smarc 24140358Smarc create_devnames() {} 24240358Smarc 24340358Smarc #include <varargs.h> 24440358Smarc 24540358Smarc warning(va_alist) 24640358Smarc va_dcl 24740358Smarc { 24840358Smarc char *fmt; 24940358Smarc va_list ap; 25040358Smarc 25140358Smarc fprintf(stderr, "%s: warning: ", progname); 25240358Smarc va_start(ap); 25340358Smarc fmt = va_arg(ap, char *); 25440358Smarc (void) vfprintf(stderr, fmt, ap); 25540358Smarc va_end(ap); 25640358Smarc fprintf(stderr, "\n"); 25740358Smarc } 25840358Smarc 25940358Smarc 26040358Smarc errexit(va_alist) 26140358Smarc va_dcl 26240358Smarc { 26340358Smarc char *fmt; 26440358Smarc va_list ap; 26540358Smarc 26640358Smarc fprintf(stderr, "%s: ", progname); 26740358Smarc va_start(ap); 26840358Smarc fmt = va_arg(ap, char *); 26940358Smarc (void) vfprintf(stderr, fmt, ap); 27040358Smarc va_end(ap); 27140358Smarc fprintf(stderr, "\n"); 27240358Smarc exit(1); 27340358Smarc } 27440358Smarc 27540358Smarc 27640358Smarc syserrexit(va_alist) 27740358Smarc va_dcl 27840358Smarc { 27940358Smarc char *fmt; 28040358Smarc va_list ap; 28140358Smarc 28240358Smarc fprintf(stderr, "%s: ", progname); 28340358Smarc va_start(ap); 28440358Smarc fmt = va_arg(ap, char *); 28540358Smarc (void) vfprintf(stderr, fmt, ap); 28640358Smarc va_end(ap); 28740358Smarc fprintf(stderr, ": %s\n", strerror(errno)); 28840358Smarc exit(1); 28940358Smarc } 290