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