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.4 (Berkeley) 06/07/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 /* offset relative to start of text image in VM. */ 190 #ifdef hp300 191 reloffset = s->n_value; 192 #endif 193 #ifdef tahoe 194 /* 195 * on tahoe, first 0x800 is reserved for communication 196 * with the console processor. 197 */ 198 reloffset = ((s->n_value & ~KERNBASE) - 0x800); 199 #endif 200 #ifdef vax 201 reloffset = (s->n_value & ~KERNBASE); 202 #endif 203 /* 204 * When loaded, data is rounded 205 * to next page cluster after text, but not in file. 206 */ 207 reloffset -= CLBYTES - (ebuf.a_text % CLBYTES); 208 versoff = N_TXTOFF(ebuf) + reloffset; 209 if (fseek(fstr, versoff, SEEK_SET) == -1) 210 syserrexit("seek (version): %x", s->n_value); 211 /* 212 * Just read version string up to, and 213 * including newline. 214 */ 215 if (fgets(versbuf, LINE_MAX, fstr) == NULL) 216 syserrexit("can't read version"); 217 strcpy(sbuf+1, "VERSION"); 218 key.dsize = (sizeof ("VERSION") - 1) + 1; 219 vers.dptr = versbuf; 220 vers.dsize = strlen(versbuf); 221 if (dbm_store(db, key, vers, DBM_INSERT) < 0) 222 syserrexit("dbm_store: can't store VERSION"); 223 } 224 } 225 (void)fclose(fstr); 226 (void)fclose(fsym); 227 return (0); 228 } 229 230 create_devnames() {} 231 232 #include <varargs.h> 233 234 warning(va_alist) 235 va_dcl 236 { 237 char *fmt; 238 va_list ap; 239 240 fprintf(stderr, "%s: warning: ", progname); 241 va_start(ap); 242 fmt = va_arg(ap, char *); 243 (void) vfprintf(stderr, fmt, ap); 244 va_end(ap); 245 fprintf(stderr, "\n"); 246 } 247 248 249 errexit(va_alist) 250 va_dcl 251 { 252 char *fmt; 253 va_list ap; 254 255 fprintf(stderr, "%s: ", progname); 256 va_start(ap); 257 fmt = va_arg(ap, char *); 258 (void) vfprintf(stderr, fmt, ap); 259 va_end(ap); 260 fprintf(stderr, "\n"); 261 exit(1); 262 } 263 264 265 syserrexit(va_alist) 266 va_dcl 267 { 268 char *fmt; 269 va_list ap; 270 271 fprintf(stderr, "%s: ", progname); 272 va_start(ap); 273 fmt = va_arg(ap, char *); 274 (void) vfprintf(stderr, fmt, ap); 275 va_end(ap); 276 fprintf(stderr, ": %s\n", strerror(errno)); 277 exit(1); 278 } 279