GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/watchdogd/watchdogd.c Lines: 0 70 0.0 %
Date: 2017-11-07 Branches: 0 40 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: watchdogd.c,v 1.15 2015/01/16 06:40:22 deraadt Exp $ */
2
3
/*
4
 * Copyright (c) 2005 Marc Balmer <mbalmer@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/resource.h>
21
#include <sys/signal.h>
22
#include <sys/sysctl.h>
23
#include <sys/mman.h>
24
25
#include <err.h>
26
#include <errno.h>
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <unistd.h>
30
31
volatile sig_atomic_t	quit = 0;
32
33
__dead void	usage(void);
34
void		sighdlr(int);
35
int		main(int, char *[]);
36
37
__dead void
38
usage(void)
39
{
40
	extern char *__progname;
41
42
	fprintf(stderr, "usage: %s [-dnq] [-i interval] [-p period]\n",
43
	    __progname);
44
	exit(1);
45
}
46
47
/* ARGSUSED */
48
void
49
sighdlr(int signum)
50
{
51
	quit = 1;
52
}
53
54
int
55
main(int argc, char *argv[])
56
{
57
	struct rlimit	 rlim;
58
	const char	*errstr;
59
	size_t		 len;
60
	u_int		 interval = 0, period = 30, nperiod;
61
	int		 ch, trigauto, sauto, speriod;
62
	int		 quiet = 0, daemonize = 1, retval = 1, do_restore = 1;
63
	int		 mib[3];
64
65
	while ((ch = getopt(argc, argv, "di:np:q")) != -1) {
66
		switch (ch) {
67
		case 'd':
68
			daemonize = 0;
69
			break;
70
		case 'i':
71
			interval = (u_int)strtonum(optarg, 1LL, 86400LL,
72
			    &errstr);
73
			if (errstr)
74
				errx(1, "interval is %s: %s", errstr, optarg);
75
			break;
76
		case 'n':
77
			do_restore = 0;
78
			break;
79
		case 'p':
80
			period = (u_int)strtonum(optarg, 2LL, 86400LL, &errstr);
81
			if (errstr)
82
				errx(1, "period is %s: %s", errstr, optarg);
83
			break;
84
		case 'q':
85
			quiet = 1;
86
			break;
87
		default:
88
			usage();
89
		}
90
	}
91
92
	argc -= optind;
93
	argv += optind;
94
	if (argc > 0)
95
		usage();
96
97
	if (interval == 0 && (interval = period / 3) == 0)
98
		interval = 1;
99
100
	if (period <= interval)
101
		errx(1, "retrigger interval too long");
102
103
	/* save kern.watchdog.period and kern.watchdog.auto for restore */
104
	mib[0] = CTL_KERN;
105
	mib[1] = KERN_WATCHDOG;
106
	mib[2] = KERN_WATCHDOG_PERIOD;
107
108
	len = sizeof(speriod);
109
	if (sysctl(mib, 3, &speriod, &len, &period, sizeof(period)) == -1) {
110
		if (errno == EOPNOTSUPP)
111
			errx(1, "no watchdog timer available");
112
		else
113
			err(1, "can't access kern.watchdog.period");
114
	}
115
116
	mib[2] = KERN_WATCHDOG_AUTO;
117
	len = sizeof(sauto);
118
	trigauto = 0;
119
120
	if (sysctl(mib, 3, &sauto, &len, &trigauto, sizeof(trigauto)) == -1)
121
		err(1, "can't access kern.watchdog.auto");
122
123
	/* Double check the timeout period, some devices change the value */
124
	mib[2] = KERN_WATCHDOG_PERIOD;
125
	len = sizeof(nperiod);
126
	if (sysctl(mib, 3, &nperiod, &len, NULL, 0) == -1) {
127
		warnx("can't read back kern.watchdog.period, "
128
		    "restoring original values");
129
		goto restore;
130
	}
131
132
	if (nperiod != period && !quiet)
133
		warnx("period adjusted to %d by device", nperiod);
134
135
	if (nperiod <= interval) {
136
		warnx("retrigger interval %d too long, "
137
		    "restoring original values", interval);
138
		goto restore;
139
	}
140
141
	if (daemonize && daemon(0, 0)) {
142
		warn("can't daemonize, restoring original values");
143
		goto restore;
144
	}
145
146
	/*
147
	 * mlockall() below will wire the whole stack up to the limit
148
	 * thus we have to reduce stack size to avoid resource abuse
149
	 */
150
	rlim.rlim_cur = 256 * 1024;
151
	rlim.rlim_max = 256 * 1024;
152
	(void)setrlimit(RLIMIT_STACK, &rlim);
153
154
	(void)mlockall(MCL_CURRENT | MCL_FUTURE);
155
	setpriority(PRIO_PROCESS, getpid(), -5);
156
157
	signal(SIGTERM, sighdlr);
158
159
	retval = 0;
160
	while (!quit) {
161
		if (sysctl(mib, 3, NULL, 0, &period, sizeof(period)) == -1)
162
			quit = retval = 1;
163
		sleep(interval);
164
	}
165
166
	if (do_restore) {
167
restore:	sysctl(mib, 3, NULL, 0, &speriod, sizeof(speriod));
168
		mib[2] = KERN_WATCHDOG_AUTO;
169
		sysctl(mib, 3, NULL, 0, &sauto, sizeof(sauto));
170
	}
171
172
	return retval;
173
}