xref: /original-bsd/usr.sbin/kvm_mkdb/kvm_mkdb.c (revision 7596ee73)
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