blob: 4eb71fd79ea9f57cf2080f04d8537006942b87bc [file] [log] [blame]
/*************************************************************/
/* Small utility to identify hardware watchdog */
/* */
/* Idea and most of the implementation by */
/* Corey Minyard <minyard@acm.org> */
/* */
/* The rest was written by me, Michael Meskes */
/* meskes@debian.org */
/* */
/*************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <errno.h>
#include <stdio.h>
#include <linux/watchdog.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <libgen.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define DEVICE "watchdog-device"
int watchdog = -1;
char *devname = NULL, *progname = NULL;
static void usage(void)
{
fprintf(stderr, "%s version %d.%d, usage:\n", progname, MAJOR_VERSION, MINOR_VERSION);
fprintf(stderr, "%s \n", progname);
exit(1);
}
void terminate(void)
{
if (watchdog != -1) {
if (write(watchdog, "V", 1) < 0 )
perror(progname);
if (close(watchdog) == -1)
perror(progname);
}
exit(0);
}
static int spool(char *line, int *i, int offset)
{
for ( (*i) += offset; line[*i] == ' ' || line[*i] == '\t'; (*i)++ );
if ( line[*i] == '=' )
(*i)++;
for ( ; line[*i] == ' ' || line[*i] == '\t'; (*i)++ );
if ( line[*i] == '\0' )
return(1);
else
return(0);
}
static void read_config(char *configfile, char *progname)
{
FILE *wc;
if ( (wc = fopen(configfile, "r")) == NULL ) {
perror(progname);
exit(1);
}
while ( !feof(wc) ) {
char *line = NULL;
size_t n;
if (getline(&line, &n, wc) == -1) {
if ( !ferror(wc) )
break;
else {
perror(progname);
exit(1);
}
}
else {
int i, j;
/* scan the actual line for an option */
/* first remove the leading blanks */
for ( i = 0; line[i] == ' ' || line[i] == '\t'; i++ );
/* if the next sign is a '#' we have a comment */
if ( line[i] == '#' )
continue;
/* also remove the trailing blanks and the \n */
for ( j = strlen(line) - 1; line[j] == ' ' || line[j] == '\t' || line[j] == '\n'; j-- );
line[j + 1] = '\0';
/* if the line is empty now, we don't have to parse it */
if ( strlen(line + i) == 0 )
continue;
/* now check for an option */
if ( strncmp(line + i, DEVICE, strlen(DEVICE)) == 0 ) {
if ( spool(line, &i, strlen(DEVICE)) )
devname = NULL;
else
devname = strdup(line + i);
}
else {
/*
* do not print an error message here because we usually use
* watchdog's config file which may contain far more valid
* options than we understand
*/
/* fprintf(stderr, "Ignoring config line: %s\n", line); */
}
}
}
if ( fclose(wc) != 0 ) {
perror(progname);
exit(1);
}
}
int main(int argc, char *const argv[])
{
char *configfile = CONFIG_FILENAME;
int c;
struct watchdog_info ident;
char *opts = "c:";
struct option long_options[] =
{
{"config-file", required_argument, NULL, 'c'},
{NULL, 0, NULL, 0}
};
progname = basename(argv[0]);
/* check for the one option we understand */
while ((c = getopt_long(argc, argv, opts, long_options, NULL)) != EOF) {
if (c == -1)
break;
switch (c) {
case 'c':
configfile = optarg;
break;
default:
usage();
}
}
read_config(configfile, progname);
/* this program has no other function than iidentifying the hardware behind
* this device i.e. if there is no device given we better punt */
if ( devname == NULL )
exit(0);
/* open the device */
watchdog = open(devname, O_WRONLY);
if ( watchdog == -1 ) {
perror(progname);
exit(1);
}
/* Print watchdog identity */
if (ioctl(watchdog, WDIOC_GETSUPPORT, &ident) < 0) {
perror(progname);
}
else {
ident.identity[sizeof(ident.identity) - 1] = '\0'; /* Be sure */
printf("%s\n", ident.identity);
}
if (write(watchdog, "V", 1) < 0 )
perror(progname);
if (close(watchdog) == -1)
perror(progname);
exit(0);
}