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