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