1*77cc846aSpgoyette /* $NetBSD: wdogctl.c,v 1.21 2015/05/06 23:08:30 pgoyette Exp $ */
2fb6f7d6fSthorpej
3fb6f7d6fSthorpej /*-
4fb6f7d6fSthorpej * Copyright (c) 2000 Zembu Labs, Inc.
5fb6f7d6fSthorpej * All rights reserved.
6fb6f7d6fSthorpej *
7fb6f7d6fSthorpej * Author: Jason R. Thorpe <thorpej@zembu.com>
8fb6f7d6fSthorpej *
9fb6f7d6fSthorpej * Redistribution and use in source and binary forms, with or without
10fb6f7d6fSthorpej * modification, are permitted provided that the following conditions
11fb6f7d6fSthorpej * are met:
12fb6f7d6fSthorpej * 1. Redistributions of source code must retain the above copyright
13fb6f7d6fSthorpej * notice, this list of conditions and the following disclaimer.
14fb6f7d6fSthorpej * 2. Redistributions in binary form must reproduce the above copyright
15fb6f7d6fSthorpej * notice, this list of conditions and the following disclaimer in the
16fb6f7d6fSthorpej * documentation and/or other materials provided with the distribution.
17fb6f7d6fSthorpej * 3. All advertising materials mentioning features or use of this software
18fb6f7d6fSthorpej * must display the following acknowledgement:
19fb6f7d6fSthorpej * This product includes software developed by Zembu Labs, Inc.
20fb6f7d6fSthorpej * 4. Neither the name of Zembu Labs nor the names of its employees may
21fb6f7d6fSthorpej * be used to endorse or promote products derived from this software
22fb6f7d6fSthorpej * without specific prior written permission.
23fb6f7d6fSthorpej *
24fb6f7d6fSthorpej * THIS SOFTWARE IS PROVIDED BY ZEMBU LABS, INC. ``AS IS'' AND ANY EXPRESS
25fb6f7d6fSthorpej * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAR-
26fb6f7d6fSthorpej * RANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS-
27fb6f7d6fSthorpej * CLAIMED. IN NO EVENT SHALL ZEMBU LABS BE LIABLE FOR ANY DIRECT, INDIRECT,
28fb6f7d6fSthorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29fb6f7d6fSthorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30fb6f7d6fSthorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31fb6f7d6fSthorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32fb6f7d6fSthorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33fb6f7d6fSthorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34fb6f7d6fSthorpej */
35c2a3b5ecSagc #include <sys/cdefs.h>
36c2a3b5ecSagc
37c2a3b5ecSagc #ifndef lint
38*77cc846aSpgoyette __RCSID("$NetBSD: wdogctl.c,v 1.21 2015/05/06 23:08:30 pgoyette Exp $");
39c2a3b5ecSagc #endif
40c2a3b5ecSagc
41fb6f7d6fSthorpej
42fb6f7d6fSthorpej #include <sys/param.h>
43fb6f7d6fSthorpej #include <sys/ioctl.h>
44fb6f7d6fSthorpej #include <sys/wdog.h>
45fb6f7d6fSthorpej
46fb6f7d6fSthorpej #include <err.h>
47fb6f7d6fSthorpej #include <errno.h>
48fb6f7d6fSthorpej #include <fcntl.h>
49fb6f7d6fSthorpej #include <stdio.h>
50fb6f7d6fSthorpej #include <stdlib.h>
51fb6f7d6fSthorpej #include <time.h>
52fb6f7d6fSthorpej #include <signal.h>
53fb6f7d6fSthorpej #include <syslog.h>
54fb6f7d6fSthorpej #include <unistd.h>
55f23be04bSminoura #include <string.h>
56*77cc846aSpgoyette #include <paths.h>
57fb6f7d6fSthorpej
58b7935600Sjoerg static void enable_kernel(const char *, u_int);
59b7935600Sjoerg static void enable_user(const char *, u_int, int);
60b7935600Sjoerg static void enable_ext(const char *, u_int);
61b7935600Sjoerg static void tickle_ext(void);
62b7935600Sjoerg static void disable(void);
63b7935600Sjoerg static void prep_wmode(struct wdog_mode *, int, const char *, u_int);
64b7935600Sjoerg static void list_timers(void);
65b7935600Sjoerg __dead static void usage(void);
66fb6f7d6fSthorpej
67b7935600Sjoerg static int Aflag;
68fb6f7d6fSthorpej
69ddd2ade2Ssmb /* Caution -- ordered list; entries >= CMD_EXT_TICKLE set timers */
70ddd2ade2Ssmb enum cmd {
71ddd2ade2Ssmb CMD_NONE, /* No verb given */
72ddd2ade2Ssmb CMD_DISABLE,
73ddd2ade2Ssmb CMD_DOTICKLE,
74ddd2ade2Ssmb CMD_EXT_TICKLE,
75ddd2ade2Ssmb CMD_KERN_TICKLE,
76a79c18d7Sdyoung CMD_NOCANCEL_TICKLE,
77ddd2ade2Ssmb CMD_USER_TICKLE
78ddd2ade2Ssmb };
79ddd2ade2Ssmb
80fb6f7d6fSthorpej int
main(int argc,char * argv[])81fb6f7d6fSthorpej main(int argc, char *argv[])
82fb6f7d6fSthorpej {
83ddd2ade2Ssmb enum cmd command = CMD_NONE;
84ddd2ade2Ssmb int period_flag = 0;
8507f76885Slukem int ch, tmp;
86fb6f7d6fSthorpej u_int period = WDOG_PERIOD_DEFAULT;
87fb6f7d6fSthorpej
88a79c18d7Sdyoung while ((ch = getopt(argc, argv, "Adekp:utx")) != -1) {
89fb6f7d6fSthorpej switch (ch) {
90fb6f7d6fSthorpej case 'A':
91fb6f7d6fSthorpej Aflag = 1;
92fb6f7d6fSthorpej break;
93fb6f7d6fSthorpej
94fb6f7d6fSthorpej case 'd':
95ddd2ade2Ssmb if (command != CMD_NONE)
96ddd2ade2Ssmb usage();
97ddd2ade2Ssmb command = CMD_DISABLE;
98ddd2ade2Ssmb break;
99ddd2ade2Ssmb
100ddd2ade2Ssmb case 'e':
101ddd2ade2Ssmb if (command != CMD_NONE)
102ddd2ade2Ssmb usage();
103ddd2ade2Ssmb command = CMD_EXT_TICKLE;
104fb6f7d6fSthorpej break;
105fb6f7d6fSthorpej
106fb6f7d6fSthorpej case 'k':
107ddd2ade2Ssmb if (command != CMD_NONE)
108ddd2ade2Ssmb usage();
109ddd2ade2Ssmb command = CMD_KERN_TICKLE;
110ddd2ade2Ssmb break;
111ddd2ade2Ssmb
112ddd2ade2Ssmb case 't':
113ddd2ade2Ssmb if (command != CMD_NONE)
114ddd2ade2Ssmb usage();
115ddd2ade2Ssmb command = CMD_DOTICKLE;
116fb6f7d6fSthorpej break;
117fb6f7d6fSthorpej
118fb6f7d6fSthorpej case 'p':
119ddd2ade2Ssmb period_flag = 1;
12007f76885Slukem tmp = atoi(optarg);
12107f76885Slukem if (tmp < 0)
122fb6f7d6fSthorpej usage();
12307f76885Slukem period = (unsigned int)tmp;
124fb6f7d6fSthorpej break;
125fb6f7d6fSthorpej
126a79c18d7Sdyoung case 'x':
127fb6f7d6fSthorpej case 'u':
128ddd2ade2Ssmb if (command != CMD_NONE)
129ddd2ade2Ssmb usage();
130a79c18d7Sdyoung command =
131a79c18d7Sdyoung (ch == 'u') ? CMD_USER_TICKLE : CMD_NOCANCEL_TICKLE;
132fb6f7d6fSthorpej break;
133fb6f7d6fSthorpej
134fb6f7d6fSthorpej default:
135fb6f7d6fSthorpej usage();
136fb6f7d6fSthorpej }
137fb6f7d6fSthorpej }
138fb6f7d6fSthorpej
139fb6f7d6fSthorpej argc -= optind;
140fb6f7d6fSthorpej argv += optind;
141fb6f7d6fSthorpej
142ddd2ade2Ssmb if (command < CMD_EXT_TICKLE) {
143ddd2ade2Ssmb if (Aflag || period_flag)
144fb6f7d6fSthorpej usage();
145fb6f7d6fSthorpej if (argc != 0)
146fb6f7d6fSthorpej usage();
1471c952b1bSdyoung } else if (argc != 1)
148ddd2ade2Ssmb usage();
149fb6f7d6fSthorpej
150ddd2ade2Ssmb switch (command) {
151ddd2ade2Ssmb case CMD_NONE:
152ddd2ade2Ssmb list_timers();
153ddd2ade2Ssmb break;
154ddd2ade2Ssmb case CMD_DISABLE:
155ddd2ade2Ssmb disable();
156ddd2ade2Ssmb break;
157ddd2ade2Ssmb case CMD_DOTICKLE:
158ddd2ade2Ssmb tickle_ext();
159ddd2ade2Ssmb break;
160ddd2ade2Ssmb case CMD_EXT_TICKLE:
161ddd2ade2Ssmb enable_ext(argv[0], period);
162ddd2ade2Ssmb break;
163ddd2ade2Ssmb case CMD_KERN_TICKLE:
164ddd2ade2Ssmb enable_kernel(argv[0], period);
165ddd2ade2Ssmb break;
166a79c18d7Sdyoung case CMD_NOCANCEL_TICKLE:
167ddd2ade2Ssmb case CMD_USER_TICKLE:
168a79c18d7Sdyoung enable_user(argv[0], period, command == CMD_USER_TICKLE);
169ddd2ade2Ssmb break;
170ddd2ade2Ssmb }
1711c952b1bSdyoung exit(EXIT_SUCCESS);
172fb6f7d6fSthorpej }
173fb6f7d6fSthorpej
174b7935600Sjoerg static void
prep_wmode(struct wdog_mode * wp,int mode,const char * name,u_int period)175ddd2ade2Ssmb prep_wmode(struct wdog_mode *wp, int mode, const char *name, u_int period)
176ddd2ade2Ssmb {
177ddd2ade2Ssmb if (strlen(name) >= WDOG_NAMESIZE)
1781c952b1bSdyoung errx(EXIT_FAILURE, "invalid watchdog timer name: %s", name);
179ddd2ade2Ssmb
180ddd2ade2Ssmb strlcpy(wp->wm_name, name, sizeof(wp->wm_name));
181ddd2ade2Ssmb wp->wm_mode = mode;
182ddd2ade2Ssmb wp->wm_period = period;
183ddd2ade2Ssmb if (Aflag)
184ddd2ade2Ssmb wp->wm_mode |= WDOG_FEATURE_ALARM;
185ddd2ade2Ssmb }
186ddd2ade2Ssmb
187b7935600Sjoerg static void
enable_kernel(const char * name,u_int period)188fb6f7d6fSthorpej enable_kernel(const char *name, u_int period)
189fb6f7d6fSthorpej {
190fb6f7d6fSthorpej struct wdog_mode wm;
191fb6f7d6fSthorpej int fd;
192fb6f7d6fSthorpej
193ddd2ade2Ssmb prep_wmode(&wm, WDOG_MODE_KTICKLE, name, period);
194fb6f7d6fSthorpej
195fb6f7d6fSthorpej fd = open(_PATH_WATCHDOG, O_RDWR, 0644);
196fb6f7d6fSthorpej if (fd == -1)
1971c952b1bSdyoung err(EXIT_FAILURE, "open %s", _PATH_WATCHDOG);
198fb6f7d6fSthorpej
199fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_SMODE, &wm) == -1)
2001c952b1bSdyoung err(EXIT_FAILURE, "WDOGIOC_SMODE");
201a8861125Swiz
202a8861125Swiz (void)close(fd);
203fb6f7d6fSthorpej }
204fb6f7d6fSthorpej
205b7935600Sjoerg static void
enable_ext(const char * name,u_int period)206ddd2ade2Ssmb enable_ext(const char *name, u_int period)
207ddd2ade2Ssmb {
208ddd2ade2Ssmb struct wdog_mode wm;
209ddd2ade2Ssmb int fd;
210ddd2ade2Ssmb
211ddd2ade2Ssmb prep_wmode(&wm, WDOG_MODE_ETICKLE, name, period);
212ddd2ade2Ssmb
213ddd2ade2Ssmb fd = open(_PATH_WATCHDOG, O_RDWR, 0644);
214ddd2ade2Ssmb if (fd == -1)
2151c952b1bSdyoung err(EXIT_FAILURE, "open %s", _PATH_WATCHDOG);
216ddd2ade2Ssmb if (ioctl(fd, WDOGIOC_SMODE, &wm) == -1) {
2171c952b1bSdyoung err(EXIT_FAILURE, "WDOGIOC_SMODE");
218ddd2ade2Ssmb }
219ddd2ade2Ssmb if (ioctl(fd, WDOGIOC_TICKLE) == -1)
220ddd2ade2Ssmb syslog(LOG_EMERG, "unable to tickle watchdog timer %s: %m",
221ddd2ade2Ssmb wm.wm_name);
222a8861125Swiz
223a8861125Swiz (void)close(fd);
224ddd2ade2Ssmb return;
225ddd2ade2Ssmb }
226ddd2ade2Ssmb
227b7935600Sjoerg static void
enable_user(const char * name,u_int period,int cancel_on_close)228a79c18d7Sdyoung enable_user(const char *name, u_int period, int cancel_on_close)
229fb6f7d6fSthorpej {
230fb6f7d6fSthorpej struct wdog_mode wm;
231fb6f7d6fSthorpej struct timespec ts;
232fb6f7d6fSthorpej pid_t tickler;
233fb6f7d6fSthorpej int fd, rv;
234fb6f7d6fSthorpej
235a79c18d7Sdyoung prep_wmode(&wm,
236a79c18d7Sdyoung (cancel_on_close) ? WDOG_MODE_UTICKLE : WDOG_MODE_ETICKLE, name,
237a79c18d7Sdyoung period);
238fb6f7d6fSthorpej
239fb6f7d6fSthorpej fd = open(_PATH_WATCHDOG, O_RDWR, 0644);
240fb6f7d6fSthorpej if (fd == -1)
2411c952b1bSdyoung err(EXIT_FAILURE, "open %s", _PATH_WATCHDOG);
242fb6f7d6fSthorpej
243fb6f7d6fSthorpej /* ...so we can log failures to tickle the timer. */
2440645f2f6Slukem openlog("wdogctl", LOG_PERROR|LOG_PID, LOG_DAEMON);
245fb6f7d6fSthorpej
246fb6f7d6fSthorpej /*
247fb6f7d6fSthorpej * We fork a child process which detaches from the controlling
248fb6f7d6fSthorpej * terminal once the timer is armed, and tickles the timer
249fb6f7d6fSthorpej * until we send it a SIGTERM.
250fb6f7d6fSthorpej */
251fb6f7d6fSthorpej tickler = fork();
252fb6f7d6fSthorpej if (tickler == -1)
2531c952b1bSdyoung err(EXIT_FAILURE, "unable to fork tickler process");
254fb6f7d6fSthorpej else if (tickler != 0) {
255fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_SMODE, &wm) == -1) {
256fb6f7d6fSthorpej (void)kill(tickler, SIGTERM);
257fab04101Sdyoung err(EXIT_FAILURE, "WDOGIOC_SMODE");
258fb6f7d6fSthorpej }
259fb6f7d6fSthorpej (void)close(fd);
260fb6f7d6fSthorpej return;
261fb6f7d6fSthorpej }
262fb6f7d6fSthorpej
263fb6f7d6fSthorpej
264fb6f7d6fSthorpej /*
265fb6f7d6fSthorpej * Wait for the watchdog to be armed. When it is, loop,
266fb6f7d6fSthorpej * tickling the timer, then waiting 1/2 the period before
267fb6f7d6fSthorpej * doing it again.
268fb6f7d6fSthorpej *
269fb6f7d6fSthorpej * If the parent fails to enable the watchdog, it will kill
270fb6f7d6fSthorpej * us.
271fb6f7d6fSthorpej */
272fb6f7d6fSthorpej do {
273fb6f7d6fSthorpej rv = ioctl(fd, WDOGIOC_WHICH, &wm);
274fb6f7d6fSthorpej } while (rv == -1);
275fb6f7d6fSthorpej
276fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_TICKLE) == -1)
277fb6f7d6fSthorpej syslog(LOG_EMERG, "unable to tickle watchdog timer %s: %m",
278fb6f7d6fSthorpej wm.wm_name);
279fb6f7d6fSthorpej
280fb6f7d6fSthorpej /*
281fb6f7d6fSthorpej * Now detach from the controlling terminal, and just run
282fb6f7d6fSthorpej * in the background. The kernel will keep track of who
283fb6f7d6fSthorpej * we are, each time we tickle the timer.
284fb6f7d6fSthorpej */
285fb6f7d6fSthorpej if (daemon(0, 0) == -1) {
286fb6f7d6fSthorpej /*
287fb6f7d6fSthorpej * We weren't able to go into the background. When
288fb6f7d6fSthorpej * we exit, the kernel will disable the watchdog so
289fb6f7d6fSthorpej * that the system won't die.
290fb6f7d6fSthorpej */
2911c952b1bSdyoung err(EXIT_FAILURE, "unable to detach from terminal");
292fb6f7d6fSthorpej }
293fb6f7d6fSthorpej
294fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_TICKLE) == -1)
295fb6f7d6fSthorpej syslog(LOG_EMERG, "unable to tickle watchdog timer %s: %m",
296fb6f7d6fSthorpej wm.wm_name);
297fb6f7d6fSthorpej
298fb6f7d6fSthorpej for (;;) {
299fb6f7d6fSthorpej ts.tv_sec = wm.wm_period / 2;
300fb6f7d6fSthorpej ts.tv_nsec = 0;
301fb6f7d6fSthorpej (void)nanosleep(&ts, NULL);
302fb6f7d6fSthorpej
303fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_TICKLE) == -1)
304fb6f7d6fSthorpej syslog(LOG_EMERG,
305fb6f7d6fSthorpej "unable to tickle watchdog timer %s: %m",
306fb6f7d6fSthorpej wm.wm_name);
307fb6f7d6fSthorpej }
308fb6f7d6fSthorpej /* NOTREACHED */
309fb6f7d6fSthorpej }
310fb6f7d6fSthorpej
311b7935600Sjoerg static void
tickle_ext(void)312b7935600Sjoerg tickle_ext(void)
313ddd2ade2Ssmb {
314ddd2ade2Ssmb int fd;
315ddd2ade2Ssmb
316ddd2ade2Ssmb fd = open(_PATH_WATCHDOG, O_RDWR, 0644);
317ddd2ade2Ssmb if (fd == -1)
3181c952b1bSdyoung err(EXIT_FAILURE, "open %s", _PATH_WATCHDOG);
319ddd2ade2Ssmb if (ioctl(fd, WDOGIOC_TICKLE) == -1)
320ddd2ade2Ssmb fprintf(stderr, "Cannot tickle timer\n");
321a8861125Swiz
322a8861125Swiz (void)close(fd);
323ddd2ade2Ssmb }
324ddd2ade2Ssmb
325b7935600Sjoerg static void
disable(void)326fb6f7d6fSthorpej disable(void)
327fb6f7d6fSthorpej {
328fb6f7d6fSthorpej struct wdog_mode wm;
329fb6f7d6fSthorpej pid_t tickler;
330bad83216Sdrochner int fd, mode;
331fb6f7d6fSthorpej
332fb6f7d6fSthorpej fd = open(_PATH_WATCHDOG, O_RDWR, 0644);
333fb6f7d6fSthorpej if (fd == -1)
3341c952b1bSdyoung err(EXIT_FAILURE, "open %s", _PATH_WATCHDOG);
335fb6f7d6fSthorpej
336fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_WHICH, &wm) == -1) {
337fb6f7d6fSthorpej printf("No watchdog timer running.\n");
338a8861125Swiz (void)close(fd);
339fb6f7d6fSthorpej return;
340fb6f7d6fSthorpej }
341bad83216Sdrochner mode = wm.wm_mode & WDOG_MODE_MASK;
342fb6f7d6fSthorpej
343fb6f7d6fSthorpej /*
344fb6f7d6fSthorpej * If the timer is running in UTICKLE mode, we need
345fb6f7d6fSthorpej * to kill the wdogctl(8) process that is tickling
346fb6f7d6fSthorpej * the timer.
347fb6f7d6fSthorpej */
348bad83216Sdrochner if (mode == WDOG_MODE_UTICKLE) {
349fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_GTICKLER, &tickler) == -1)
3501c952b1bSdyoung err(EXIT_FAILURE, "WDOGIOC_GTICKLER");
351fb6f7d6fSthorpej (void)close(fd);
352fb6f7d6fSthorpej (void)kill(tickler, SIGTERM);
353fb6f7d6fSthorpej } else {
354fb6f7d6fSthorpej wm.wm_mode = WDOG_MODE_DISARMED;
3551c952b1bSdyoung if (ioctl(fd, WDOGIOC_SMODE, &wm) == -1) {
3561c952b1bSdyoung err(EXIT_FAILURE, "unable to disarm watchdog %s",
3571c952b1bSdyoung wm.wm_name);
3581c952b1bSdyoung }
359fb6f7d6fSthorpej (void)close(fd);
360fb6f7d6fSthorpej }
361fb6f7d6fSthorpej }
362fb6f7d6fSthorpej
363b7935600Sjoerg static void
list_timers(void)364fb6f7d6fSthorpej list_timers(void)
365fb6f7d6fSthorpej {
366fb6f7d6fSthorpej struct wdog_conf wc;
367fb6f7d6fSthorpej struct wdog_mode wm;
368fb6f7d6fSthorpej char *buf, *cp;
369bad83216Sdrochner int fd, count, i, mode;
370fb6f7d6fSthorpej pid_t tickler;
371fb6f7d6fSthorpej
372fb6f7d6fSthorpej fd = open(_PATH_WATCHDOG, O_RDONLY, 0644);
373fb6f7d6fSthorpej if (fd == -1)
3741c952b1bSdyoung err(EXIT_FAILURE, "open %s", _PATH_WATCHDOG);
375fb6f7d6fSthorpej
376fb6f7d6fSthorpej wc.wc_names = NULL;
377fb6f7d6fSthorpej wc.wc_count = 0;
378fb6f7d6fSthorpej
379fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_GWDOGS, &wc) == -1)
3801c952b1bSdyoung err(EXIT_FAILURE, "ioctl WDOGIOC_GWDOGS for count");
381fb6f7d6fSthorpej
382fb6f7d6fSthorpej count = wc.wc_count;
383fb6f7d6fSthorpej if (count == 0) {
384fb6f7d6fSthorpej printf("No watchdog timers present.\n");
385fb6f7d6fSthorpej goto out;
386fb6f7d6fSthorpej }
387fb6f7d6fSthorpej
388fb6f7d6fSthorpej buf = malloc(count * WDOG_NAMESIZE);
389fb6f7d6fSthorpej if (buf == NULL)
3901c952b1bSdyoung err(EXIT_FAILURE, "malloc %d byte for watchdog names",
391fb6f7d6fSthorpej count * WDOG_NAMESIZE);
392fb6f7d6fSthorpej
393fb6f7d6fSthorpej wc.wc_names = buf;
394fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_GWDOGS, &wc) == -1)
3951c952b1bSdyoung err(EXIT_FAILURE, "ioctl WDOGIOC_GWDOGS for names");
396fb6f7d6fSthorpej
397fb6f7d6fSthorpej count = wc.wc_count;
398fb6f7d6fSthorpej if (count == 0) {
399fb6f7d6fSthorpej printf("No watchdog timers present.\n");
400fb6f7d6fSthorpej free(buf);
401fb6f7d6fSthorpej goto out;
402fb6f7d6fSthorpej }
403fb6f7d6fSthorpej
404fb6f7d6fSthorpej printf("Available watchdog timers:\n");
405fb6f7d6fSthorpej for (i = 0, cp = buf; i < count; i++, cp += WDOG_NAMESIZE) {
406fb6f7d6fSthorpej cp[WDOG_NAMESIZE - 1] = '\0';
4078883e1fbSitojun strlcpy(wm.wm_name, cp, sizeof(wm.wm_name));
408fb6f7d6fSthorpej
409fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_GMODE, &wm) == -1)
410bad83216Sdrochner continue;
411bad83216Sdrochner mode = wm.wm_mode & WDOG_MODE_MASK;
412bad83216Sdrochner if (mode == WDOG_MODE_UTICKLE) {
413fb6f7d6fSthorpej if (ioctl(fd, WDOGIOC_GTICKLER, &tickler) == -1)
414fb6f7d6fSthorpej tickler = (pid_t) -1;
415fb6f7d6fSthorpej }
416fb6f7d6fSthorpej
417fb6f7d6fSthorpej printf("\t%s, %u second period", cp, wm.wm_period);
418bad83216Sdrochner if (mode != WDOG_MODE_DISARMED) {
419bad83216Sdrochner switch(mode) {
420ddd2ade2Ssmb case WDOG_MODE_KTICKLE:
421ddd2ade2Ssmb printf(" [armed, kernel tickle");
422ddd2ade2Ssmb break;
423ddd2ade2Ssmb case WDOG_MODE_UTICKLE:
424ddd2ade2Ssmb printf(" [armed, user tickle");
425ddd2ade2Ssmb if (tickler != (pid_t) -1)
426fb6f7d6fSthorpej printf(", pid %d", tickler);
427ddd2ade2Ssmb break;
428ddd2ade2Ssmb case WDOG_MODE_ETICKLE:
429ddd2ade2Ssmb printf(" [armed, external tickle");
430ddd2ade2Ssmb break;
431ddd2ade2Ssmb }
432fb6f7d6fSthorpej printf("]");
433fb6f7d6fSthorpej }
434fb6f7d6fSthorpej printf("\n");
435fb6f7d6fSthorpej }
436fb6f7d6fSthorpej out:
437fb6f7d6fSthorpej (void)close(fd);
438fb6f7d6fSthorpej }
439fb6f7d6fSthorpej
440b7935600Sjoerg static void
usage(void)441fb6f7d6fSthorpej usage(void)
442fb6f7d6fSthorpej {
443da2ab5caSwiz
444b635f565Sjmmv fprintf(stderr, "usage: %s\n", getprogname());
445da2ab5caSwiz fprintf(stderr, " %s -d\n", getprogname());
446ddd2ade2Ssmb fprintf(stderr, " %s -e [-A] [-p seconds] timer\n",
447ddd2ade2Ssmb getprogname());
448d7666f6cScgd fprintf(stderr, " %s -k [-A] [-p seconds] timer\n",
449d7666f6cScgd getprogname());
450da2ab5caSwiz fprintf(stderr, " %s -t\n", getprogname());
451d7666f6cScgd fprintf(stderr, " %s -u [-A] [-p seconds] timer\n",
452d7666f6cScgd getprogname());
45300352349Swiz fprintf(stderr, " %s -x [-A] [-p seconds] timer\n",
45400352349Swiz getprogname());
455fb6f7d6fSthorpej
456fb6f7d6fSthorpej exit(1);
457fb6f7d6fSthorpej }
458