Commit | Line | Data |
---|---|---|
5ff67f98 | 1 | /* |
95503932 | 2 | * Copyright (c) 1980, 1986, 1989 The Regents of the University of California. |
5c709f29 KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
6 | * provided that the above copyright notice and this paragraph are | |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
5ff67f98 DF |
16 | */ |
17 | ||
261f5d78 | 18 | #ifndef lint |
5ff67f98 | 19 | char copyright[] = |
95503932 | 20 | "@(#) Copyright (c) 1980, 1986, 1989 The Regents of the University of California.\n\ |
5ff67f98 | 21 | All rights reserved.\n"; |
5c709f29 | 22 | #endif /* not lint */ |
5ff67f98 DF |
23 | |
24 | #ifndef lint | |
bfda3826 | 25 | static char sccsid[] = "@(#)savecore.c 5.20 (Berkeley) %G%"; |
5c709f29 | 26 | #endif /* not lint */ |
261f5d78 | 27 | |
d112e9ff | 28 | /* |
97d6da0b | 29 | * savecore |
d112e9ff | 30 | */ |
a3e4f1d7 | 31 | |
d112e9ff BJ |
32 | #include <sys/param.h> |
33 | #include <sys/dir.h> | |
34 | #include <sys/stat.h> | |
ce4fd43b | 35 | #include <sys/time.h> |
865f9d47 | 36 | #include <sys/file.h> |
a8bf8cf3 | 37 | #include <sys/syslog.h> |
f76fd03c KB |
38 | #include <stdio.h> |
39 | #include <nlist.h> | |
7abf8d65 | 40 | #include <paths.h> |
d112e9ff | 41 | |
97d6da0b BJ |
42 | #define DAY (60L*60L*24L) |
43 | #define LEEWAY (3*DAY) | |
44 | ||
45 | #define eq(a,b) (!strcmp(a,b)) | |
261f5d78 | 46 | #ifdef vax |
97d6da0b | 47 | #define ok(number) ((number)&0x7fffffff) |
261f5d78 | 48 | #else |
ce104dfd SL |
49 | #ifdef tahoe |
50 | #define ok(number) ((number)&~0xc0000000) | |
51 | #else | |
261f5d78 SL |
52 | #define ok(number) (number) |
53 | #endif | |
ce104dfd | 54 | #endif |
97d6da0b | 55 | |
a3e4f1d7 | 56 | struct nlist current_nl[] = { /* namelist for currently running system */ |
d112e9ff BJ |
57 | #define X_DUMPDEV 0 |
58 | { "_dumpdev" }, | |
59 | #define X_DUMPLO 1 | |
60 | { "_dumplo" }, | |
61 | #define X_TIME 2 | |
62 | { "_time" }, | |
261f5d78 SL |
63 | #define X_DUMPSIZE 3 |
64 | { "_dumpsize" }, | |
d112e9ff BJ |
65 | #define X_VERSION 4 |
66 | { "_version" }, | |
67 | #define X_PANICSTR 5 | |
68 | { "_panicstr" }, | |
261f5d78 SL |
69 | #define X_DUMPMAG 6 |
70 | { "_dumpmag" }, | |
71 | { "" }, | |
d112e9ff BJ |
72 | }; |
73 | ||
a3e4f1d7 RC |
74 | struct nlist dump_nl[] = { /* name list for dumped system */ |
75 | { "_dumpdev" }, /* entries MUST be the same as */ | |
76 | { "_dumplo" }, /* those in current_nl[] */ | |
77 | { "_time" }, | |
78 | { "_dumpsize" }, | |
79 | { "_version" }, | |
80 | { "_panicstr" }, | |
81 | { "_dumpmag" }, | |
82 | { "" }, | |
83 | }; | |
84 | ||
f6cc4b0d | 85 | char *system; |
97d6da0b BJ |
86 | char *dirname; /* directory to save dumps in */ |
87 | char *ddname; /* name of dump device */ | |
95503932 | 88 | int dumpfd; /* read/write descriptor on block dev */ |
97d6da0b BJ |
89 | char *find_dev(); |
90 | dev_t dumpdev; /* dump device */ | |
91 | time_t dumptime; /* time the dump was taken */ | |
92 | int dumplo; /* where dump starts on dumpdev */ | |
261f5d78 SL |
93 | int dumpsize; /* amount of memory dumped */ |
94 | int dumpmag; /* magic number in dump */ | |
97d6da0b BJ |
95 | time_t now; /* current date */ |
96 | char *path(); | |
4d1d39b2 | 97 | char *malloc(); |
97d6da0b BJ |
98 | char *ctime(); |
99 | char vers[80]; | |
100 | char core_vers[80]; | |
101 | char panic_mesg[80]; | |
102 | int panicstr; | |
97d6da0b BJ |
103 | off_t lseek(); |
104 | off_t Lseek(); | |
a3e4f1d7 | 105 | int Verbose; |
c6e3f9fb | 106 | int force; |
99b8650e | 107 | int clear; |
a8bf8cf3 | 108 | extern int errno; |
d112e9ff BJ |
109 | |
110 | main(argc, argv) | |
97d6da0b BJ |
111 | char **argv; |
112 | int argc; | |
d112e9ff | 113 | { |
865f9d47 SL |
114 | char *cp; |
115 | ||
116 | argc--, argv++; | |
117 | while (argc > 0 && argv[0][0] == '-') { | |
118 | for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { | |
97d6da0b | 119 | |
c6e3f9fb MK |
120 | case 'f': |
121 | force++; | |
122 | break; | |
123 | ||
a3e4f1d7 | 124 | case 'v': |
95503932 | 125 | case 'd': |
865f9d47 | 126 | Verbose++; |
a3e4f1d7 | 127 | break; |
865f9d47 | 128 | |
99b8650e MK |
129 | case 'c': |
130 | clear++; | |
131 | break; | |
132 | ||
a3e4f1d7 | 133 | default: |
865f9d47 | 134 | usage: |
a3e4f1d7 | 135 | fprintf(stderr, |
95503932 | 136 | "usage: savecore [-f] [-v] [-c] dirname [ system ]\n"); |
a3e4f1d7 RC |
137 | exit(1); |
138 | } | |
865f9d47 | 139 | argc--, argv++; |
d112e9ff | 140 | } |
865f9d47 SL |
141 | if (argc != 1 && argc != 2) |
142 | goto usage; | |
143 | dirname = argv[0]; | |
144 | if (argc == 2) | |
145 | system = argv[1]; | |
a96b688d | 146 | openlog("savecore", LOG_ODELAY, LOG_AUTH); |
865f9d47 | 147 | if (access(dirname, W_OK) < 0) { |
bfda3826 | 148 | Perror(LOG_ERR, "%s: %m\n", dirname); |
97d6da0b | 149 | exit(1); |
d112e9ff | 150 | } |
d112e9ff | 151 | read_kmem(); |
d112e9ff BJ |
152 | } |
153 | ||
739955be KM |
154 | dump_exists() |
155 | { | |
739955be KM |
156 | int word; |
157 | ||
865f9d47 SL |
158 | Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET); |
159 | Read(dumpfd, (char *)&word, sizeof (word)); | |
95503932 | 160 | if (Verbose && word != dumpmag) |
a3e4f1d7 | 161 | printf("magic number mismatch: %x != %x\n", word, dumpmag); |
261f5d78 | 162 | return (word == dumpmag); |
739955be KM |
163 | } |
164 | ||
165 | clear_dump() | |
166 | { | |
739955be KM |
167 | int zero = 0; |
168 | ||
865f9d47 SL |
169 | Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET); |
170 | Write(dumpfd, (char *)&zero, sizeof (zero)); | |
739955be KM |
171 | } |
172 | ||
97d6da0b BJ |
173 | char * |
174 | find_dev(dev, type) | |
175 | register dev_t dev; | |
176 | register int type; | |
d112e9ff | 177 | { |
d112e9ff | 178 | struct stat statb; |
f0326588 | 179 | char *dp; |
d112e9ff | 180 | |
7abf8d65 | 181 | strcpy(devname, _PATH_DEV); |
97d6da0b | 182 | if (stat(devname, &statb)) { |
d112e9ff | 183 | perror(devname); |
97d6da0b BJ |
184 | continue; |
185 | } | |
186 | if ((statb.st_mode&S_IFMT) != type) | |
187 | continue; | |
188 | if (dev == statb.st_rdev) { | |
4d1d39b2 | 189 | dp = malloc(strlen(devname)+1); |
97d6da0b | 190 | strcpy(dp, devname); |
865f9d47 | 191 | return (dp); |
d112e9ff BJ |
192 | } |
193 | } | |
ce104dfd | 194 | log(LOG_ERR, "Can't find device %d/%d\n", major(dev), minor(dev)); |
97d6da0b BJ |
195 | exit(1); |
196 | /*NOTREACHED*/ | |
d112e9ff BJ |
197 | } |
198 | ||
95503932 MK |
199 | char * |
200 | rawname(s) | |
201 | char *s; | |
202 | { | |
203 | static char name[MAXPATHLEN]; | |
204 | char *sl, *rindex(); | |
205 | ||
206 | if ((sl = rindex(s, '/')) == NULL || sl[1] == '0') { | |
207 | log(LOG_ERR, "can't make raw dump device name from %s?\n", s); | |
208 | return (s); | |
209 | } | |
210 | sprintf(name, "%.*s/r%s", sl - s, s, sl + 1); | |
211 | return (name); | |
212 | } | |
213 | ||
865f9d47 SL |
214 | int cursyms[] = |
215 | { X_DUMPDEV, X_DUMPLO, X_VERSION, X_DUMPMAG, -1 }; | |
216 | int dumpsyms[] = | |
217 | { X_TIME, X_DUMPSIZE, X_VERSION, X_PANICSTR, X_DUMPMAG, -1 }; | |
d112e9ff BJ |
218 | read_kmem() |
219 | { | |
d112e9ff | 220 | register char *cp; |
865f9d47 | 221 | FILE *fp; |
a3e4f1d7 | 222 | char *dump_sys; |
865f9d47 | 223 | int kmem, i; |
a3e4f1d7 | 224 | |
f76fd03c KB |
225 | dump_sys = system ? system : _PATH_UNIX; |
226 | nlist(_PATH_UNIX, current_nl); | |
a3e4f1d7 | 227 | nlist(dump_sys, dump_nl); |
a3e4f1d7 RC |
228 | /* |
229 | * Some names we need for the currently running system, | |
230 | * others for the system that was running when the dump was made. | |
231 | * The values obtained from the current system are used | |
232 | * to look for things in /dev/kmem that cannot be found | |
233 | * in the dump_sys namelist, but are presumed to be the same | |
234 | * (since the disk partitions are probably the same!) | |
235 | */ | |
865f9d47 SL |
236 | for (i = 0; cursyms[i] != -1; i++) |
237 | if (current_nl[cursyms[i]].n_value == 0) { | |
f76fd03c | 238 | log(LOG_ERR, "%s: %s not in namelist\n", _PATH_UNIX, |
865f9d47 SL |
239 | current_nl[cursyms[i]].n_name); |
240 | exit(1); | |
241 | } | |
242 | for (i = 0; dumpsyms[i] != -1; i++) | |
243 | if (dump_nl[dumpsyms[i]].n_value == 0) { | |
99b8650e | 244 | log(LOG_ERR, "%s: %s not in namelist\n", dump_sys, |
865f9d47 SL |
245 | dump_nl[dumpsyms[i]].n_name); |
246 | exit(1); | |
247 | } | |
f76fd03c | 248 | kmem = Open(_PATH_KMEM, O_RDONLY); |
865f9d47 | 249 | Lseek(kmem, (long)current_nl[X_DUMPDEV].n_value, L_SET); |
261f5d78 | 250 | Read(kmem, (char *)&dumpdev, sizeof (dumpdev)); |
865f9d47 | 251 | Lseek(kmem, (long)current_nl[X_DUMPLO].n_value, L_SET); |
261f5d78 | 252 | Read(kmem, (char *)&dumplo, sizeof (dumplo)); |
4085e419 MK |
253 | if (Verbose) |
254 | printf("dumplo = %d (%d * %d)\n", dumplo, dumplo/DEV_BSIZE, | |
255 | DEV_BSIZE); | |
865f9d47 | 256 | Lseek(kmem, (long)current_nl[X_DUMPMAG].n_value, L_SET); |
261f5d78 | 257 | Read(kmem, (char *)&dumpmag, sizeof (dumpmag)); |
f53aabcb | 258 | dumplo *= DEV_BSIZE; |
d112e9ff | 259 | ddname = find_dev(dumpdev, S_IFBLK); |
95503932 | 260 | dumpfd = Open(ddname, O_RDWR); |
865f9d47 SL |
261 | fp = fdopen(kmem, "r"); |
262 | if (fp == NULL) { | |
99b8650e | 263 | log(LOG_ERR, "Couldn't fdopen kmem\n"); |
97d6da0b | 264 | exit(1); |
d112e9ff | 265 | } |
f6cc4b0d BJ |
266 | if (system) |
267 | return; | |
865f9d47 SL |
268 | fseek(fp, (long)current_nl[X_VERSION].n_value, L_SET); |
269 | fgets(vers, sizeof (vers), fp); | |
d112e9ff | 270 | fclose(fp); |
798fe693 SL |
271 | } |
272 | ||
5638c7c2 SL |
273 | check_kmem() |
274 | { | |
798fe693 SL |
275 | FILE *fp; |
276 | register char *cp; | |
277 | ||
95503932 | 278 | fp = fdopen(dumpfd, "r"); |
865f9d47 | 279 | if (fp == NULL) { |
bfda3826 | 280 | log(LOG_ERR, "Can't fdopen dumpfd\n"); |
97d6da0b | 281 | exit(1); |
d112e9ff | 282 | } |
865f9d47 SL |
283 | fseek(fp, (off_t)(dumplo+ok(dump_nl[X_VERSION].n_value)), L_SET); |
284 | fgets(core_vers, sizeof (core_vers), fp); | |
99b8650e | 285 | if (!eq(vers, core_vers) && system == 0) { |
f76fd03c | 286 | log(LOG_WARNING, "Warning: %s version mismatch:\n", _PATH_UNIX); |
99b8650e MK |
287 | log(LOG_WARNING, "\t%s\n", vers); |
288 | log(LOG_WARNING, "and\t%s\n", core_vers); | |
289 | } | |
865f9d47 SL |
290 | fseek(fp, (off_t)(dumplo + ok(dump_nl[X_PANICSTR].n_value)), L_SET); |
291 | fread((char *)&panicstr, sizeof (panicstr), 1, fp); | |
97d6da0b | 292 | if (panicstr) { |
865f9d47 | 293 | fseek(fp, dumplo + ok(panicstr), L_SET); |
d112e9ff BJ |
294 | cp = panic_mesg; |
295 | do | |
296 | *cp = getc(fp); | |
95503932 | 297 | while (*cp++ && cp < &panic_mesg[sizeof(panic_mesg)]); |
d112e9ff | 298 | } |
95503932 | 299 | /* don't fclose(fp); we want the file descriptor */ |
f6cc4b0d | 300 | } |
d112e9ff | 301 | |
97d6da0b BJ |
302 | get_crashtime() |
303 | { | |
20f89b8d | 304 | time_t clobber = (time_t)0; |
d112e9ff | 305 | |
865f9d47 | 306 | Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), L_SET); |
97d6da0b | 307 | Read(dumpfd, (char *)&dumptime, sizeof dumptime); |
a3e4f1d7 RC |
308 | if (dumptime == 0) { |
309 | if (Verbose) | |
c6e3f9fb | 310 | printf("Dump time is zero.\n"); |
261f5d78 | 311 | return (0); |
a3e4f1d7 | 312 | } |
d112e9ff BJ |
313 | printf("System went down at %s", ctime(&dumptime)); |
314 | if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) { | |
865f9d47 | 315 | printf("dump time is unreasonable\n"); |
261f5d78 | 316 | return (0); |
d112e9ff | 317 | } |
261f5d78 | 318 | return (1); |
d112e9ff BJ |
319 | } |
320 | ||
97d6da0b BJ |
321 | char * |
322 | path(file) | |
323 | char *file; | |
d112e9ff | 324 | { |
4d1d39b2 | 325 | register char *cp = malloc(strlen(file) + strlen(dirname) + 2); |
d112e9ff | 326 | |
97d6da0b BJ |
327 | (void) strcpy(cp, dirname); |
328 | (void) strcat(cp, "/"); | |
329 | (void) strcat(cp, file); | |
261f5d78 | 330 | return (cp); |
d112e9ff BJ |
331 | } |
332 | ||
d112e9ff BJ |
333 | check_space() |
334 | { | |
335 | struct stat dsb; | |
336 | register char *ddev; | |
e84afc49 | 337 | int dfd, spacefree; |
798fe693 | 338 | struct fs fs; |
d112e9ff | 339 | |
97d6da0b | 340 | if (stat(dirname, &dsb) < 0) { |
bfda3826 | 341 | Perror(LOG_ERR, "%s: %m\n", dirname); |
97d6da0b BJ |
342 | exit(1); |
343 | } | |
d112e9ff | 344 | ddev = find_dev(dsb.st_dev, S_IFBLK); |
865f9d47 | 345 | dfd = Open(ddev, O_RDONLY); |
a66ab591 | 346 | Lseek(dfd, SBOFF, L_SET); |
865f9d47 | 347 | Read(dfd, (char *)&fs, sizeof (fs)); |
d112e9ff | 348 | close(dfd); |
865f9d47 SL |
349 | spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024; |
350 | if (spacefree < read_number("minfree")) { | |
99b8650e | 351 | log(LOG_WARNING, "Dump omitted, not enough space on device\n"); |
97d6da0b | 352 | return (0); |
d112e9ff | 353 | } |
ce104dfd SL |
354 | if (freespace(&fs, fs.fs_minfree) < 0) |
355 | log(LOG_WARNING, | |
99b8650e | 356 | "Dump performed, but free space threshold crossed\n"); |
97d6da0b | 357 | return (1); |
d112e9ff BJ |
358 | } |
359 | ||
d112e9ff | 360 | read_number(fn) |
97d6da0b | 361 | char *fn; |
d112e9ff BJ |
362 | { |
363 | char lin[80]; | |
364 | register FILE *fp; | |
365 | ||
865f9d47 SL |
366 | fp = fopen(path(fn), "r"); |
367 | if (fp == NULL) | |
261f5d78 | 368 | return (0); |
97d6da0b BJ |
369 | if (fgets(lin, 80, fp) == NULL) { |
370 | fclose(fp); | |
261f5d78 | 371 | return (0); |
d112e9ff | 372 | } |
97d6da0b | 373 | fclose(fp); |
261f5d78 | 374 | return (atoi(lin)); |
d112e9ff BJ |
375 | } |
376 | ||
4085e419 | 377 | #define BUFSIZE (256*1024) /* 1/4 Mb */ |
4d1d39b2 | 378 | |
d112e9ff BJ |
379 | save_core() |
380 | { | |
381 | register int n; | |
4d1d39b2 | 382 | register char *cp; |
d112e9ff | 383 | register int ifd, ofd, bounds; |
bfda3826 | 384 | int ret; |
95503932 | 385 | char *bfile; |
d112e9ff BJ |
386 | register FILE *fp; |
387 | ||
4085e419 | 388 | cp = malloc(BUFSIZE); |
865f9d47 | 389 | if (cp == 0) { |
95503932 | 390 | log(LOG_ERR, "savecore: Can't allocate i/o buffer.\n"); |
4d1d39b2 MK |
391 | return; |
392 | } | |
d112e9ff | 393 | bounds = read_number("bounds"); |
f76fd03c | 394 | ifd = Open(system ? system : _PATH_UNIX, O_RDONLY); |
4085e419 | 395 | while((n = Read(ifd, cp, BUFSIZE)) > 0) |
d112e9ff BJ |
396 | Write(ofd, cp, n); |
397 | close(ifd); | |
398 | close(ofd); | |
95503932 MK |
399 | if ((ifd = open(rawname(ddname), O_RDONLY)) == -1) { |
400 | log(LOG_WARNING, "Can't open %s (%m); using block device", | |
401 | rawname(ddname)); | |
402 | ifd = dumpfd; | |
403 | } | |
4085e419 MK |
404 | Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), L_SET); |
405 | Read(dumpfd, (char *)&dumpsize, sizeof (dumpsize)); | |
9bd38ba8 | 406 | (void)sprintf(cp, "vmcore.%d", bounds); |
798fe693 | 407 | ofd = Create(path(cp), 0644); |
865f9d47 | 408 | Lseek(ifd, (off_t)dumplo, L_SET); |
4085e419 | 409 | dumpsize *= NBPG; |
ce104dfd | 410 | log(LOG_NOTICE, "Saving %d bytes of image in vmcore.%d\n", |
4085e419 | 411 | dumpsize, bounds); |
261f5d78 | 412 | while (dumpsize > 0) { |
4085e419 MK |
413 | n = read(ifd, cp, |
414 | dumpsize > BUFSIZE ? BUFSIZE : dumpsize); | |
415 | if (n <= 0) { | |
416 | if (n == 0) | |
417 | log(LOG_WARNING, | |
bfda3826 MK |
418 | "WARNING: EOF on dump device; %s\n", |
419 | "vmcore may be incomplete"); | |
4085e419 | 420 | else |
bfda3826 MK |
421 | Perror(LOG_ERR, "read from dumpdev: %m", |
422 | "read"); | |
423 | break; | |
424 | } | |
425 | if ((ret = write(ofd, cp, n)) < n) { | |
426 | if (ret < 0) | |
427 | Perror(LOG_ERR, "write: %m", "write"); | |
428 | else | |
429 | log(LOG_ERR, "short write: wrote %d of %d\n", | |
430 | ret, n); | |
431 | log(LOG_WARNING, "WARNING: vmcore may be incomplete\n"); | |
f53aabcb JB |
432 | break; |
433 | } | |
4085e419 | 434 | dumpsize -= n; |
d112e9ff BJ |
435 | } |
436 | close(ifd); | |
437 | close(ofd); | |
95503932 MK |
438 | bfile = path("bounds"); |
439 | fp = fopen(bfile, "w"); | |
440 | if (fp) { | |
441 | fprintf(fp, "%d\n", bounds+1); | |
442 | fclose(fp); | |
443 | } else | |
444 | Perror(LOG_ERR, "Can't create bounds file %s: %m", bfile); | |
4d1d39b2 | 445 | free(cp); |
d112e9ff BJ |
446 | } |
447 | ||
97d6da0b BJ |
448 | /* |
449 | * Versions of std routines that exit on error. | |
450 | */ | |
97d6da0b BJ |
451 | Open(name, rw) |
452 | char *name; | |
453 | int rw; | |
454 | { | |
455 | int fd; | |
456 | ||
865f9d47 SL |
457 | fd = open(name, rw); |
458 | if (fd < 0) { | |
ce104dfd | 459 | Perror(LOG_ERR, "%s: %m", name); |
97d6da0b BJ |
460 | exit(1); |
461 | } | |
865f9d47 | 462 | return (fd); |
97d6da0b BJ |
463 | } |
464 | ||
465 | Read(fd, buff, size) | |
466 | int fd, size; | |
467 | char *buff; | |
468 | { | |
469 | int ret; | |
470 | ||
865f9d47 SL |
471 | ret = read(fd, buff, size); |
472 | if (ret < 0) { | |
95503932 | 473 | Perror(LOG_ERR, "read: %m", "read"); |
97d6da0b BJ |
474 | exit(1); |
475 | } | |
865f9d47 | 476 | return (ret); |
97d6da0b BJ |
477 | } |
478 | ||
479 | off_t | |
480 | Lseek(fd, off, flag) | |
481 | int fd, flag; | |
482 | long off; | |
483 | { | |
484 | long ret; | |
485 | ||
865f9d47 SL |
486 | ret = lseek(fd, off, flag); |
487 | if (ret == -1) { | |
95503932 | 488 | Perror(LOG_ERR, "lseek: %m", "lseek"); |
97d6da0b BJ |
489 | exit(1); |
490 | } | |
865f9d47 | 491 | return (ret); |
97d6da0b BJ |
492 | } |
493 | ||
494 | Create(file, mode) | |
495 | char *file; | |
496 | int mode; | |
497 | { | |
498 | register int fd; | |
499 | ||
865f9d47 SL |
500 | fd = creat(file, mode); |
501 | if (fd < 0) { | |
ce104dfd | 502 | Perror(LOG_ERR, "%s: %m", file); |
97d6da0b BJ |
503 | exit(1); |
504 | } | |
865f9d47 | 505 | return (fd); |
97d6da0b BJ |
506 | } |
507 | ||
508 | Write(fd, buf, size) | |
509 | int fd, size; | |
510 | char *buf; | |
97d6da0b | 511 | { |
bfda3826 | 512 | int n; |
97d6da0b | 513 | |
bfda3826 MK |
514 | if ((n = write(fd, buf, size)) < size) { |
515 | if (n < 0) | |
516 | Perror(LOG_ERR, "write: %m", "write"); | |
517 | else | |
518 | log(LOG_ERR, "short write: wrote %d of %d\n", n, size); | |
97d6da0b BJ |
519 | exit(1); |
520 | } | |
521 | } | |
ce104dfd | 522 | |
95503932 | 523 | /* VARARGS2 */ |
ce104dfd SL |
524 | log(level, msg, a1, a2) |
525 | int level; | |
526 | char *msg; | |
527 | { | |
528 | ||
529 | fprintf(stderr, msg, a1, a2); | |
530 | syslog(level, msg, a1, a2); | |
531 | } | |
532 | ||
533 | Perror(level, msg, s) | |
534 | int level; | |
535 | char *msg; | |
536 | { | |
537 | int oerrno = errno; | |
538 | ||
539 | perror(s); | |
540 | errno = oerrno; | |
541 | syslog(level, msg, s); | |
542 | } |