]> git.ipfire.org Git - thirdparty/util-linux.git/blob - sys-utils/wdctl.c
wdctl: align with other util-linux commands
[thirdparty/util-linux.git] / sys-utils / wdctl.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: t -*-*/
2
3 /*
4 * wdctl(8) - show hardware watchdog status
5 *
6 * Copyright (C) 2012 Lennart Poettering
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #include <linux/watchdog.h>
24 #include <sys/ioctl.h>
25 #include <getopt.h>
26 #include <stdio.h>
27 #include <unistd.h>
28
29 #include "nls.h"
30 #include "c.h"
31 #include "closestream.h"
32 #include "pathnames.h"
33
34 static const struct {
35 uint32_t flag;
36 const char *name;
37 } flag_names[] = {
38 { WDIOF_OVERHEAT, N_("OVERHEAT: Reset due to CPU overheat") },
39 { WDIOF_FANFAULT, N_("FANFAULT: Fan failed") },
40 { WDIOF_EXTERN1, N_("EXTERN1: External relay 1") },
41 { WDIOF_EXTERN2, N_("EXTERN2: External relay 2") },
42 { WDIOF_POWERUNDER, N_("POWERUNDER: Power bad/power fault") },
43 { WDIOF_CARDRESET, N_("CARDRESET: Card previously reset the CPU") },
44 { WDIOF_POWEROVER, N_("POWEROVER: Power over voltage") },
45 { WDIOF_SETTIMEOUT, N_("SETTIMEOUT: Set timeout (in seconds)") },
46 { WDIOF_MAGICCLOSE, N_("MAGICCLOSE: Supports magic close char") },
47 { WDIOF_PRETIMEOUT, N_("PRETIMEOUT: Pretimeout (in seconds)") },
48 { WDIOF_KEEPALIVEPING, N_("KEEPALIVEPING: Keep alive ping reply") }
49 };
50
51 static void usage(int status)
52 {
53 FILE *out = status == EXIT_SUCCESS ? stdout : stderr;
54
55 fputs(USAGE_HEADER, out);
56 fprintf(out,
57 _(" %s [options]\n"), program_invocation_short_name);
58
59 fputs(USAGE_OPTIONS, out);
60 fprintf(out,
61 _(" -d, --device <path> device to use (default is %s)\n"), _PATH_WATCHDOG_DEV);
62
63 fputs(USAGE_SEPARATOR, out);
64 fputs(USAGE_HELP, out);
65 fputs(USAGE_VERSION, out);
66 fprintf(out, USAGE_MAN_TAIL("wdctl(1)"));
67
68 exit(status);
69 }
70
71 static void print_options(uint32_t options)
72 {
73 unsigned i;
74
75 if (options == 0) {
76 puts(_("\tNo flags set."));
77 return;
78 }
79
80 for (i = 0; i < ARRAY_SIZE(flag_names); i++) {
81 if (options & flag_names[i].flag)
82 printf("\t%s\n", _(flag_names[i].name));
83 options &= ~flag_names[i].flag;
84 }
85
86 if (options)
87 printf(_("\tUnknown flags 0x%x\n"), options);
88 }
89
90 int main(int argc, char *argv[])
91 {
92 static const struct option longopts[] = {
93 { "help", no_argument, 0, 'h' },
94 { "version", no_argument, 0, 'V'},
95 { "device", required_argument, 0, 'd' },
96 { NULL, 0, 0, 0 }
97 };
98
99 int c, status, sec, fd;
100 const char *device = _PATH_WATCHDOG_DEV;
101 struct watchdog_info ident;
102
103 setlocale(LC_MESSAGES, "");
104 bindtextdomain(PACKAGE, LOCALEDIR);
105 textdomain(PACKAGE);
106 atexit(close_stdout);
107
108 while((c = getopt_long(argc, argv, "hVd:", longopts, NULL)) != -1) {
109
110 switch(c) {
111 case 'h':
112 usage(EXIT_SUCCESS);
113 case 'V':
114 printf(UTIL_LINUX_VERSION);
115 return EXIT_SUCCESS;
116 case 'd':
117 device = optarg;
118 break;
119 default:
120 usage(EXIT_FAILURE);
121 }
122 }
123
124 if (optind < argc)
125 usage(EXIT_FAILURE);
126
127 fd = open(device, O_WRONLY|O_CLOEXEC);
128 if (fd < 0) {
129 if (errno == EBUSY)
130 errx(EXIT_FAILURE, _("Watchdog already in use, terminating."));
131
132 err(EXIT_FAILURE, _("Failed to open watchdog device"));
133 }
134
135 if (ioctl(fd, WDIOC_GETSUPPORT, &ident) >= 0) {
136 printf(_("Identity:\n\t%s\n"
137 "Firmware version:\n\t%x\n"
138 "Supported options:\n"),
139 ident.identity,
140 ident.firmware_version);
141 print_options(ident.options);
142 }
143
144 if (ioctl(fd, WDIOC_GETSTATUS, &status) >= 0) {
145 puts(_("Status:"));
146 print_options((uint32_t) status);
147 }
148
149 if (ioctl(fd, WDIOC_GETBOOTSTATUS, &status) >= 0) {
150 puts(_("Boot status:"));
151 print_options((uint32_t) status);
152 }
153
154 if (ioctl(fd, WDIOC_GETTIMEOUT, &sec) >= 0)
155 printf(_("Timeout:\n\t%is\n"), sec);
156
157 if (ioctl(fd, WDIOC_GETPRETIMEOUT, &sec) >= 0)
158 printf(_("Pre-Timeout:\n\t%is\n"), sec);
159
160 if (ioctl(fd, WDIOC_GETTIMELEFT, &sec) >= 0)
161 printf(_("Time Left:\n\t%is\n"), sec);
162
163 for (;;) {
164 /* We just opened this to query the state, not to arm
165 * it hence use the magic close character */
166
167 static const char v = 'V';
168
169 if (write(fd, &v, 1) >= 0)
170 break;
171
172 if (errno != EINTR) {
173 warn(_("Failed to disarm watchdog"));
174 break;
175 }
176
177 /* Let's try hard, since if we don't get this right
178 * the machine might end up rebooting. */
179 }
180
181 close(fd);
182
183 return EXIT_SUCCESS;
184 }