sizeof(core_vers) != sizeof(core_vers))
sizeof(core_vers)) != sizeof(core_vers)) {
char	*find_dev __P((dev_t, int));int	 get_crashtime __P((void));void	 kmem_setup __P((void));void	 log __P((int, char *, ...));void	 Lseek __P((int, off_t, int));int	 Open __P((char *, int rw));char	*rawname __P((char *s));void	 save_core __P((void));void	 usage __P((void));void	 Write __P((int, void *, int));intmain(argc, argv)	int argc;	char *argv[];{	int ch;	openlog("savecore", LOG_PERROR, LOG_DAEMON);	while ((ch = getopt(argc, argv, "cdfN:vz")) != -1)		switch(ch) {		case 'c':			clear = 1;			break;		case 'd':		/* Not documented. */		case 'v':			verbose = 1;			break;		case 'f':			force = 1;			break;		case 'N':			kernel = optarg;			break;		case 'z':			compress = 1;			break;		case '?':		default:			usage();		}	argc -= optind;	argv += optind;	if (!clear) {		if (argc != 1 && argc != 2)			usage();		dirname = argv[0];	}	if (argc == 2)		kernel = argv[1];	(void)time(&now);	kmem_setup();	if (clear) {		clear_dump();		exit(0);	}	if (!dump_exists() && !force)		exit(1);	check_kmem();	if (panicstr)		syslog(LOG_ALERT, "reboot after panic: %s", panic_mesg);	else		syslog(LOG_ALERT, "reboot");	if ((!get_crashtime() || !check_space()) && !force)		exit(1);	save_core();	clear_dump();	exit(0);}voidkmem_setup(){	kvm_t	*kd_kern;	char	errbuf[_POSIX2_LINE_MAX];	int	i, hdrsz;	char	*dump_sys;		/*	 * Some names we need for the currently running system, others for	 * the system that was running when the dump was made.  The values	 * obtained from the current system are used to look for things in	 * /dev/kmem that cannot be found in the dump_sys namelist, but are	 * presumed to be the same (since the disk partitions are probably	 * the same!)	 */	kd_kern = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);	if (kd_kern == NULL) {		syslog(LOG_ERR, "%s: kvm_openfiles: %s", _PATH_UNIX, errbuf);		exit(1);	}	if (kvm_nlist(kd_kern, current_nl) == -1)		syslog(LOG_ERR, "%s: kvm_nlist: %s", _PATH_UNIX,			kvm_geterr(kd_kern));		for (i = 0; cursyms[i] != -1; i++)		if (current_nl[cursyms[i]].n_value == 0) {			syslog(LOG_ERR, "%s: %s not in namelist",			    _PATH_UNIX, current_nl[cursyms[i]].n_name);			exit(1);		}	KREAD(kd_kern, current_nl[X_DUMPDEV].n_value, &dumpdev);	if (dumpdev == NODEV) {		syslog(LOG_WARNING, "no core dump (no dumpdev)");		exit(1);	}	KREAD(kd_kern, current_nl[X_DUMPLO].n_value, &dumplo);	dumplo *= DEV_BSIZE;	if (verbose)		(void)printf("dumplo = %d (%d * %d)\n",		    dumplo, dumplo / DEV_BSIZE, DEV_BSIZE);	KREAD(kd_kern, current_nl[X_DUMPMAG].n_value, &dumpmag);	if (kernel == NULL) {		if (kvm_read(kd_kern, current_nl[X_VERSION].n_value,		    vers, sizeof(vers)) == -1) {			syslog(LOG_ERR, "%s: kvm_read: version misread", dump_sys);			exit(1);		}		vers[sizeof(vers) - 1] = '\0';	}	ddname = find_dev(dumpdev, S_IFBLK);	dumpfd = Open(ddname, O_RDWR);	dump_sys = kernel ? kernel : _PATH_UNIX;	kd_dump = kvm_openfiles(dump_sys, ddname, NULL, O_RDWR, errbuf);	if (kd_dump == NULL) {		syslog(LOG_ERR, "%s: kvm_openfiles: %s", dump_sys, errbuf);		exit(1);	}	if (kvm_nlist(kd_dump, dump_nl) == -1)		syslog(LOG_ERR, "%s: kvm_nlist: %s", dump_sys,			kvm_geterr(kd_dump));	for (i = 0; dumpsyms[i] != -1; i++)		if (dump_nl[dumpsyms[i]].n_value == 0) {			syslog(LOG_ERR, "%s: %s not in namelist",			    dump_sys, dump_nl[dumpsyms[i]].n_name);			exit(1);		}	hdrsz = kvm_dump_mkheader(kd_dump, (off_t)dumplo);	if (hdrsz == -1) {		syslog(LOG_ERR, "%s: kvm_dump_mkheader: %s", dump_sys,			kvm_geterr(kd_dump));		exit(1);	}	dumplo += hdrsz;	kvm_close(kd_kern);}voidcheck_kmem(){	register char	*cp;	register int	panicloc;	char core_vers[1024];	if (kvm_read(kd_dump, dump_nl[X_VERSION].n_value, core_vers,	    sizeof(core_vers) != sizeof(core_vers))		syslog(LOG_ERR, "%s: kvm_read: version misread", dump_sys);		exit(1);	}	core_vers[sizeof(core_vers) - 1] = '\0';	if (strcmp(vers, core_vers) && kernel == 0)		syslog(LOG_WARNING,		    "warning: %s version mismatch:\n\t%s\nand\t%s\n",		    _PATH_UNIX, vers, core_vers);	KREAD(kd_dump, dump_nl[X_PANICSTR].n_value, &panicstr);	if (panicstr) {		cp       = panic_mesg;		panicloc = panicstr;		do {			KREAD(kd_dump, panicloc, cp);			panicloc++;		} while (*cp++ && cp < &panic_mesg[sizeof(panic_mesg)]);	}}intdump_exists(){	int newdumpmag;	KREAD(kd_dump, dump_nl[X_DUMPMAG].n_value, &newdumpmag);	/* Read the dump size. */	KREAD(kd_dump, dump_nl[X_DUMPSIZE].n_value, &dumpsize);	dumpsize *= getpagesize();	/*	 * Return zero if core dump doesn't seem to be there, and note	 * it for syslog.  This check and return happens after the dump size	 * is read, so dumpsize is whether or not the core is valid (for -f).	 */	if (newdumpmag != dumpmag) {		if (verbose)			syslog(LOG_WARNING, "magic number mismatch (%x != %x)",			    newdumpmag, dumpmag);		syslog(LOG_WARNING, "no core dump");		return (0);	}	return (1);}voidclear_dump(){	if (kvm_dump_inval(kd_dump) == -1)		syslog(LOG_ERR, "%s: kvm_clear_dump: %s", ddname,			kvm_geterr(kd_dump));}char buf[1024 * 1024];voidsave_core(){	register FILE *fp;	register int bounds, ifd, nr, nw, ofd;	char *rawp, path[MAXPATHLEN];	mode_t um;	um = umask(S_IRWXG|S_IRWXO);	/*	 * Get the current number and update the bounds file.  Do the update	 * now, because may fail later and don't want to overwrite anything.	 */	(void)snprintf(path, sizeof(path), "%s/bounds", dirname);	if ((fp = fopen(path, "r")) == NULL)		goto err1;	if (fgets(buf, sizeof(buf), fp) == NULL) {		if (ferror(fp))err1:			syslog(LOG_WARNING, "%s: %s", path, strerror(errno));		bounds = 0;	} else		bounds = atoi(buf);	if (fp != NULL)		(void)fclose(fp);	if ((fp = fopen(path, "w")) == NULL)		syslog(LOG_ERR, "%s: %m", path);	else {		(void)fprintf(fp, "%d\n", bounds + 1);		(void)fclose(fp);	}	(void)fclose(fp);	/* Create the core file. */	(void)snprintf(path, sizeof(path), "%s%s.%d.core%s",	    dirname, _PATH_UNIX, bounds, compress ? ".Z" : "");	if (compress) {		if ((fp = zopen(path, "w", 0)) == NULL) {			syslog(LOG_ERR, "%s: %s", path, strerror(errno));			exit(1);		}	} else {		ofd = Create(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);		fp  = fdopen(ofd, "w");		if (fp == NULL) {			syslog(LOG_ERR, "%s: fdopen: %s", path);			exit(1);		}	}	/* Open the raw device. */	rawp = rawname(ddname);	if ((ifd = open(rawp, O_RDONLY)) == -1) {		syslog(LOG_WARNING, "%s: %m; using block device", rawp);		ifd = dumpfd;	}	/* Seek to the start of the core. */	Lseek(ifd, (off_t)dumplo, L_SET);	if (kvm_dump_wrtheader(kd_dump, fp, dumpsize) == -1) {		syslog(LOG_ERR, "kvm_dump_wrtheader: %s : %s", path,			kvm_geterr(kd_dump));		exit(1);	}	/* Copy the core file. */	syslog(LOG_NOTICE, "writing %score to %s",	    compress ? "compressed " : "", path);	for (; dumpsize > 0; dumpsize -= nr) {		(void)printf("%6dK\r", dumpsize / 1024);		(void)fflush(stdout);		nr = read(ifd, buf, MIN(dumpsize, sizeof(buf)));		if (nr <= 0) {			if (nr == 0)				syslog(LOG_WARNING,				    "WARNING: EOF on dump device");			else				syslog(LOG_ERR, "%s: %m", rawp);			goto err2;		}		nw = fwrite(buf, 1, nr, fp);		if (nw != nr) {			syslog(LOG_ERR, "%s: %s",			    path, strerror(nw == 0 ? EIO : errno));err2:			syslog(LOG_WARNING,			    "WARNING: core may be incomplete");			(void)printf("\n");			exit(1);		}	}	(void)close(ifd);	(void)fclose(fp);	/* Copy the kernel. */	ifd = Open(kernel ? kernel : _PATH_UNIX, O_RDONLY);	(void)snprintf(path, sizeof(path), "%s%s.%d%s",	    dirname, _PATH_UNIX, bounds, compress ? ".Z" : "");	if (compress) {		if ((fp = zopen(path, "w", 0)) == NULL) {			syslog(LOG_ERR, "%s: %s", path, strerror(errno));			exit(1);		}	} else		ofd = Create(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);	syslog(LOG_NOTICE, "writing %skernel to %s",	    compress ? "compressed " : "", path);	while ((nr = read(ifd, buf, sizeof(buf))) > 0) {		if (compress)			nw = fwrite(buf, 1, nr, fp);		else			nw = write(ofd, buf, nr);		if (nw != nr) {			syslog(LOG_ERR, "%s: %s",			    path, strerror(nw == 0 ? EIO : errno));			syslog(LOG_WARNING,			    "WARNING: kernel may be incomplete");			exit(1);		}	}	if (nr < 0) {		syslog(LOG_ERR, "%s: %s",		    kernel ? kernel : _PATH_UNIX, strerror(errno));		syslog(LOG_WARNING,		    "WARNING: kernel may be incomplete");		exit(1);	}	if (compress)		(void)fclose(fp);	else		(void)close(ofd);	(void)umask(um);}char *find_dev(dev, type)	register dev_t dev;	register int type;{	register DIR *dfd;	struct dirent *dir;	struct stat sb;	char *dp, devname[MAXPATHLEN + 1];	if ((dfd = opendir(_PATH_DEV)) == NULL) {		syslog(LOG_ERR, "%s: %s", _PATH_DEV, strerror(errno));		exit(1);	}	(void)strcpy(devname, _PATH_DEV);	while ((dir = readdir(dfd))) {		(void)strcpy(devname + sizeof(_PATH_DEV) - 1, dir->d_name);		if (lstat(devname, &sb)) {			syslog(LOG_ERR, "%s: %s", devname, strerror(errno));			continue;		}		if ((sb.st_mode & S_IFMT) != type)			continue;		if (dev == sb.st_rdev) {			closedir(dfd);			if ((dp = strdup(devname)) == NULL) {				syslog(LOG_ERR, "%s", strerror(errno));				exit(1);			}			return (dp);		}	}	closedir(dfd);	syslog(LOG_ERR, "can't find device %d/%d", major(dev), minor(dev));	exit(1);}