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