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