string.h is ANSI C include file
[unix-history] / usr / src / usr.sbin / kvm_mkdb / kvm_mkdb.c
CommitLineData
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
20char 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 30static 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
43char *tmp;
44#define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp))
45#define USAGE "kvm_mkdb"
46extern errno;
47
48char *progname;
49
50main(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
90rmdb(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
106mvdb(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
129typedef 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
135create_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
241create_devnames() {}
242
243#include <varargs.h>
244
245warning(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
260errexit(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
276syserrexit(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}