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 | |
95503932 | 25 | static char sccsid[] = "@(#)savecore.c 5.18 (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) { |
ce104dfd | 148 | Perror(LOG_ERR, "%s: %m", 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 MK |
160 | if (Verbose) |
161 | printf("dumplo = %d (%d * 512)\n", dumplo, dumplo/512); | |
162 | if (Verbose && word != dumpmag) | |
a3e4f1d7 | 163 | printf("magic number mismatch: %x != %x\n", word, dumpmag); |
261f5d78 | 164 | return (word == dumpmag); |
739955be KM |
165 | } |
166 | ||
167 | clear_dump() | |
168 | { | |
739955be KM |
169 | int zero = 0; |
170 | ||
865f9d47 SL |
171 | Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET); |
172 | Write(dumpfd, (char *)&zero, sizeof (zero)); | |
739955be KM |
173 | } |
174 | ||
97d6da0b BJ |
175 | char * |
176 | find_dev(dev, type) | |
177 | register dev_t dev; | |
178 | register int type; | |
d112e9ff | 179 | { |
d112e9ff | 180 | struct stat statb; |
f0326588 | 181 | char *dp; |
d112e9ff | 182 | |
7abf8d65 | 183 | strcpy(devname, _PATH_DEV); |
97d6da0b | 184 | if (stat(devname, &statb)) { |
d112e9ff | 185 | perror(devname); |
97d6da0b BJ |
186 | continue; |
187 | } | |
188 | if ((statb.st_mode&S_IFMT) != type) | |
189 | continue; | |
190 | if (dev == statb.st_rdev) { | |
4d1d39b2 | 191 | dp = malloc(strlen(devname)+1); |
97d6da0b | 192 | strcpy(dp, devname); |
865f9d47 | 193 | return (dp); |
d112e9ff BJ |
194 | } |
195 | } | |
ce104dfd | 196 | log(LOG_ERR, "Can't find device %d/%d\n", major(dev), minor(dev)); |
97d6da0b BJ |
197 | exit(1); |
198 | /*NOTREACHED*/ | |
d112e9ff BJ |
199 | } |
200 | ||
95503932 MK |
201 | char * |
202 | rawname(s) | |
203 | char *s; | |
204 | { | |
205 | static char name[MAXPATHLEN]; | |
206 | char *sl, *rindex(); | |
207 | ||
208 | if ((sl = rindex(s, '/')) == NULL || sl[1] == '0') { | |
209 | log(LOG_ERR, "can't make raw dump device name from %s?\n", s); | |
210 | return (s); | |
211 | } | |
212 | sprintf(name, "%.*s/r%s", sl - s, s, sl + 1); | |
213 | return (name); | |
214 | } | |
215 | ||
865f9d47 SL |
216 | int cursyms[] = |
217 | { X_DUMPDEV, X_DUMPLO, X_VERSION, X_DUMPMAG, -1 }; | |
218 | int dumpsyms[] = | |
219 | { X_TIME, X_DUMPSIZE, X_VERSION, X_PANICSTR, X_DUMPMAG, -1 }; | |
d112e9ff BJ |
220 | read_kmem() |
221 | { | |
d112e9ff | 222 | register char *cp; |
865f9d47 | 223 | FILE *fp; |
a3e4f1d7 | 224 | char *dump_sys; |
865f9d47 | 225 | int kmem, i; |
a3e4f1d7 | 226 | |
f76fd03c KB |
227 | dump_sys = system ? system : _PATH_UNIX; |
228 | nlist(_PATH_UNIX, current_nl); | |
a3e4f1d7 | 229 | nlist(dump_sys, dump_nl); |
a3e4f1d7 RC |
230 | /* |
231 | * Some names we need for the currently running system, | |
232 | * others for the system that was running when the dump was made. | |
233 | * The values obtained from the current system are used | |
234 | * to look for things in /dev/kmem that cannot be found | |
235 | * in the dump_sys namelist, but are presumed to be the same | |
236 | * (since the disk partitions are probably the same!) | |
237 | */ | |
865f9d47 SL |
238 | for (i = 0; cursyms[i] != -1; i++) |
239 | if (current_nl[cursyms[i]].n_value == 0) { | |
f76fd03c | 240 | log(LOG_ERR, "%s: %s not in namelist\n", _PATH_UNIX, |
865f9d47 SL |
241 | current_nl[cursyms[i]].n_name); |
242 | exit(1); | |
243 | } | |
244 | for (i = 0; dumpsyms[i] != -1; i++) | |
245 | if (dump_nl[dumpsyms[i]].n_value == 0) { | |
99b8650e | 246 | log(LOG_ERR, "%s: %s not in namelist\n", dump_sys, |
865f9d47 SL |
247 | dump_nl[dumpsyms[i]].n_name); |
248 | exit(1); | |
249 | } | |
f76fd03c | 250 | kmem = Open(_PATH_KMEM, O_RDONLY); |
865f9d47 | 251 | Lseek(kmem, (long)current_nl[X_DUMPDEV].n_value, L_SET); |
261f5d78 | 252 | Read(kmem, (char *)&dumpdev, sizeof (dumpdev)); |
865f9d47 | 253 | Lseek(kmem, (long)current_nl[X_DUMPLO].n_value, L_SET); |
261f5d78 | 254 | Read(kmem, (char *)&dumplo, sizeof (dumplo)); |
865f9d47 | 255 | Lseek(kmem, (long)current_nl[X_DUMPMAG].n_value, L_SET); |
261f5d78 | 256 | Read(kmem, (char *)&dumpmag, sizeof (dumpmag)); |
f53aabcb | 257 | dumplo *= DEV_BSIZE; |
d112e9ff | 258 | ddname = find_dev(dumpdev, S_IFBLK); |
95503932 | 259 | dumpfd = Open(ddname, O_RDWR); |
865f9d47 SL |
260 | fp = fdopen(kmem, "r"); |
261 | if (fp == NULL) { | |
99b8650e | 262 | log(LOG_ERR, "Couldn't fdopen kmem\n"); |
97d6da0b | 263 | exit(1); |
d112e9ff | 264 | } |
f6cc4b0d BJ |
265 | if (system) |
266 | return; | |
865f9d47 SL |
267 | fseek(fp, (long)current_nl[X_VERSION].n_value, L_SET); |
268 | fgets(vers, sizeof (vers), fp); | |
d112e9ff | 269 | fclose(fp); |
798fe693 SL |
270 | } |
271 | ||
5638c7c2 SL |
272 | check_kmem() |
273 | { | |
798fe693 SL |
274 | FILE *fp; |
275 | register char *cp; | |
276 | ||
95503932 | 277 | fp = fdopen(dumpfd, "r"); |
865f9d47 | 278 | if (fp == NULL) { |
95503932 | 279 | log(LOG_ERR, "Can't fdopen dumpfd"); |
97d6da0b | 280 | exit(1); |
d112e9ff | 281 | } |
865f9d47 SL |
282 | fseek(fp, (off_t)(dumplo+ok(dump_nl[X_VERSION].n_value)), L_SET); |
283 | fgets(core_vers, sizeof (core_vers), fp); | |
99b8650e | 284 | if (!eq(vers, core_vers) && system == 0) { |
f76fd03c | 285 | log(LOG_WARNING, "Warning: %s version mismatch:\n", _PATH_UNIX); |
99b8650e MK |
286 | log(LOG_WARNING, "\t%s\n", vers); |
287 | log(LOG_WARNING, "and\t%s\n", core_vers); | |
288 | } | |
865f9d47 SL |
289 | fseek(fp, (off_t)(dumplo + ok(dump_nl[X_PANICSTR].n_value)), L_SET); |
290 | fread((char *)&panicstr, sizeof (panicstr), 1, fp); | |
97d6da0b | 291 | if (panicstr) { |
865f9d47 | 292 | fseek(fp, dumplo + ok(panicstr), L_SET); |
d112e9ff BJ |
293 | cp = panic_mesg; |
294 | do | |
295 | *cp = getc(fp); | |
95503932 | 296 | while (*cp++ && cp < &panic_mesg[sizeof(panic_mesg)]); |
d112e9ff | 297 | } |
95503932 | 298 | /* don't fclose(fp); we want the file descriptor */ |
f6cc4b0d | 299 | } |
d112e9ff | 300 | |
97d6da0b BJ |
301 | get_crashtime() |
302 | { | |
20f89b8d | 303 | time_t clobber = (time_t)0; |
d112e9ff | 304 | |
865f9d47 | 305 | Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), L_SET); |
97d6da0b | 306 | Read(dumpfd, (char *)&dumptime, sizeof dumptime); |
a3e4f1d7 RC |
307 | if (dumptime == 0) { |
308 | if (Verbose) | |
c6e3f9fb | 309 | printf("Dump time is zero.\n"); |
261f5d78 | 310 | return (0); |
a3e4f1d7 | 311 | } |
d112e9ff BJ |
312 | printf("System went down at %s", ctime(&dumptime)); |
313 | if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) { | |
865f9d47 | 314 | printf("dump time is unreasonable\n"); |
261f5d78 | 315 | return (0); |
d112e9ff | 316 | } |
261f5d78 | 317 | return (1); |
d112e9ff BJ |
318 | } |
319 | ||
97d6da0b BJ |
320 | char * |
321 | path(file) | |
322 | char *file; | |
d112e9ff | 323 | { |
4d1d39b2 | 324 | register char *cp = malloc(strlen(file) + strlen(dirname) + 2); |
d112e9ff | 325 | |
97d6da0b BJ |
326 | (void) strcpy(cp, dirname); |
327 | (void) strcat(cp, "/"); | |
328 | (void) strcat(cp, file); | |
261f5d78 | 329 | return (cp); |
d112e9ff BJ |
330 | } |
331 | ||
d112e9ff BJ |
332 | check_space() |
333 | { | |
334 | struct stat dsb; | |
335 | register char *ddev; | |
e84afc49 | 336 | int dfd, spacefree; |
798fe693 | 337 | struct fs fs; |
d112e9ff | 338 | |
97d6da0b | 339 | if (stat(dirname, &dsb) < 0) { |
ce104dfd | 340 | Perror(LOG_ERR, "%s: %m", dirname); |
97d6da0b BJ |
341 | exit(1); |
342 | } | |
d112e9ff | 343 | ddev = find_dev(dsb.st_dev, S_IFBLK); |
865f9d47 | 344 | dfd = Open(ddev, O_RDONLY); |
a66ab591 | 345 | Lseek(dfd, SBOFF, L_SET); |
865f9d47 | 346 | Read(dfd, (char *)&fs, sizeof (fs)); |
d112e9ff | 347 | close(dfd); |
865f9d47 SL |
348 | spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024; |
349 | if (spacefree < read_number("minfree")) { | |
99b8650e | 350 | log(LOG_WARNING, "Dump omitted, not enough space on device\n"); |
97d6da0b | 351 | return (0); |
d112e9ff | 352 | } |
ce104dfd SL |
353 | if (freespace(&fs, fs.fs_minfree) < 0) |
354 | log(LOG_WARNING, | |
99b8650e | 355 | "Dump performed, but free space threshold crossed\n"); |
97d6da0b | 356 | return (1); |
d112e9ff BJ |
357 | } |
358 | ||
d112e9ff | 359 | read_number(fn) |
97d6da0b | 360 | char *fn; |
d112e9ff BJ |
361 | { |
362 | char lin[80]; | |
363 | register FILE *fp; | |
364 | ||
865f9d47 SL |
365 | fp = fopen(path(fn), "r"); |
366 | if (fp == NULL) | |
261f5d78 | 367 | return (0); |
97d6da0b BJ |
368 | if (fgets(lin, 80, fp) == NULL) { |
369 | fclose(fp); | |
261f5d78 | 370 | return (0); |
d112e9ff | 371 | } |
97d6da0b | 372 | fclose(fp); |
261f5d78 | 373 | return (atoi(lin)); |
d112e9ff BJ |
374 | } |
375 | ||
95503932 | 376 | #define BUFPAGES (256*1024/NBPG) /* 1/4 Mb */ |
4d1d39b2 | 377 | |
d112e9ff BJ |
378 | save_core() |
379 | { | |
380 | register int n; | |
4d1d39b2 | 381 | register char *cp; |
d112e9ff | 382 | register int ifd, ofd, bounds; |
95503932 | 383 | char *bfile; |
d112e9ff BJ |
384 | register FILE *fp; |
385 | ||
95503932 | 386 | cp = malloc(BUFPAGES*NBPG); |
865f9d47 | 387 | if (cp == 0) { |
95503932 | 388 | log(LOG_ERR, "savecore: Can't allocate i/o buffer.\n"); |
4d1d39b2 MK |
389 | return; |
390 | } | |
d112e9ff | 391 | bounds = read_number("bounds"); |
f76fd03c | 392 | ifd = Open(system ? system : _PATH_UNIX, O_RDONLY); |
95503932 | 393 | while((n = Read(ifd, cp, BUFPAGES*NBPG)) > 0) |
d112e9ff BJ |
394 | Write(ofd, cp, n); |
395 | close(ifd); | |
396 | close(ofd); | |
95503932 MK |
397 | if ((ifd = open(rawname(ddname), O_RDONLY)) == -1) { |
398 | log(LOG_WARNING, "Can't open %s (%m); using block device", | |
399 | rawname(ddname)); | |
400 | ifd = dumpfd; | |
401 | } | |
865f9d47 | 402 | Lseek(ifd, (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), L_SET); |
5638c7c2 | 403 | Read(ifd, (char *)&dumpsize, sizeof (dumpsize)); |
9bd38ba8 | 404 | (void)sprintf(cp, "vmcore.%d", bounds); |
798fe693 | 405 | ofd = Create(path(cp), 0644); |
865f9d47 | 406 | Lseek(ifd, (off_t)dumplo, L_SET); |
ce104dfd SL |
407 | log(LOG_NOTICE, "Saving %d bytes of image in vmcore.%d\n", |
408 | NBPG*dumpsize, bounds); | |
261f5d78 | 409 | while (dumpsize > 0) { |
4d1d39b2 | 410 | n = Read(ifd, cp, |
865f9d47 | 411 | (dumpsize > BUFPAGES ? BUFPAGES : dumpsize) * NBPG); |
f53aabcb | 412 | if (n == 0) { |
99b8650e | 413 | log(LOG_WARNING, "WARNING: vmcore may be incomplete\n"); |
f53aabcb JB |
414 | break; |
415 | } | |
d112e9ff | 416 | Write(ofd, cp, n); |
261f5d78 | 417 | dumpsize -= n/NBPG; |
d112e9ff BJ |
418 | } |
419 | close(ifd); | |
420 | close(ofd); | |
95503932 MK |
421 | bfile = path("bounds"); |
422 | fp = fopen(bfile, "w"); | |
423 | if (fp) { | |
424 | fprintf(fp, "%d\n", bounds+1); | |
425 | fclose(fp); | |
426 | } else | |
427 | Perror(LOG_ERR, "Can't create bounds file %s: %m", bfile); | |
4d1d39b2 | 428 | free(cp); |
d112e9ff BJ |
429 | } |
430 | ||
97d6da0b BJ |
431 | /* |
432 | * Versions of std routines that exit on error. | |
433 | */ | |
97d6da0b BJ |
434 | Open(name, rw) |
435 | char *name; | |
436 | int rw; | |
437 | { | |
438 | int fd; | |
439 | ||
865f9d47 SL |
440 | fd = open(name, rw); |
441 | if (fd < 0) { | |
ce104dfd | 442 | Perror(LOG_ERR, "%s: %m", name); |
97d6da0b BJ |
443 | exit(1); |
444 | } | |
865f9d47 | 445 | return (fd); |
97d6da0b BJ |
446 | } |
447 | ||
448 | Read(fd, buff, size) | |
449 | int fd, size; | |
450 | char *buff; | |
451 | { | |
452 | int ret; | |
453 | ||
865f9d47 SL |
454 | ret = read(fd, buff, size); |
455 | if (ret < 0) { | |
95503932 | 456 | Perror(LOG_ERR, "read: %m", "read"); |
97d6da0b BJ |
457 | exit(1); |
458 | } | |
865f9d47 | 459 | return (ret); |
97d6da0b BJ |
460 | } |
461 | ||
462 | off_t | |
463 | Lseek(fd, off, flag) | |
464 | int fd, flag; | |
465 | long off; | |
466 | { | |
467 | long ret; | |
468 | ||
865f9d47 SL |
469 | ret = lseek(fd, off, flag); |
470 | if (ret == -1) { | |
95503932 | 471 | Perror(LOG_ERR, "lseek: %m", "lseek"); |
97d6da0b BJ |
472 | exit(1); |
473 | } | |
865f9d47 | 474 | return (ret); |
97d6da0b BJ |
475 | } |
476 | ||
477 | Create(file, mode) | |
478 | char *file; | |
479 | int mode; | |
480 | { | |
481 | register int fd; | |
482 | ||
865f9d47 SL |
483 | fd = creat(file, mode); |
484 | if (fd < 0) { | |
ce104dfd | 485 | Perror(LOG_ERR, "%s: %m", file); |
97d6da0b BJ |
486 | exit(1); |
487 | } | |
865f9d47 | 488 | return (fd); |
97d6da0b BJ |
489 | } |
490 | ||
491 | Write(fd, buf, size) | |
492 | int fd, size; | |
493 | char *buf; | |
97d6da0b BJ |
494 | { |
495 | ||
496 | if (write(fd, buf, size) < size) { | |
95503932 | 497 | Perror(LOG_ERR, "write: %m", "write"); |
97d6da0b BJ |
498 | exit(1); |
499 | } | |
500 | } | |
ce104dfd | 501 | |
95503932 | 502 | /* VARARGS2 */ |
ce104dfd SL |
503 | log(level, msg, a1, a2) |
504 | int level; | |
505 | char *msg; | |
506 | { | |
507 | ||
508 | fprintf(stderr, msg, a1, a2); | |
509 | syslog(level, msg, a1, a2); | |
510 | } | |
511 | ||
512 | Perror(level, msg, s) | |
513 | int level; | |
514 | char *msg; | |
515 | { | |
516 | int oerrno = errno; | |
517 | ||
518 | perror(s); | |
519 | errno = oerrno; | |
520 | syslog(level, msg, s); | |
521 | } |