1/* $FreeBSD$ */
2/*
3 * Copyright (c) 2000 by Matthew Jacob
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions, and the following disclaimer,
11 *    without modification, immediately at the beginning of the file.
12 * 2. The name of the author may not be used to endorse or promote products
13 *    derived from this software without specific prior written permission.
14 *
15 * Alternatively, this software may be distributed under the terms of the
16 * the GNU Public License ("GPL").
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * Matthew Jacob
31 * Feral Software
32 * mjacob@feral.com
33 */
34#include <unistd.h>
35#include <stddef.h>
36#include <stdint.h>
37#include <stdlib.h>
38#include <stdio.h>
39#include <fcntl.h>
40#include <errno.h>
41#include <string.h>
42#include <syslog.h>
43#include <unistd.h>
44#include <sys/ioctl.h>
45#include <cam/scsi/scsi_all.h>
46#include <cam/scsi/scsi_enc.h>
47
48#define	ALLSTAT (SES_ENCSTAT_UNRECOV | SES_ENCSTAT_CRITICAL | \
49	SES_ENCSTAT_NONCRITICAL | SES_ENCSTAT_INFO)
50
51/*
52 * Monitor named SES devices and note (via syslog) any changes in status.
53 */
54
55int
56main(int a, char **v)
57{
58	static const char *usage =
59	    "usage: %s [ -c ] [ -d ] [ -t pollinterval ] device [ device ]\n";
60	int fd, polltime, dev, nodaemon, clear, c;
61	encioc_enc_status_t stat, nstat, *carray;
62
63	if (a < 2) {
64		fprintf(stderr, usage, *v);
65		return (1);
66	}
67
68	nodaemon = 0;
69	polltime = 30;
70	clear = 0;
71	while ((c = getopt(a, v, "cdt:")) != -1) {
72		switch (c) {
73		case 'c':
74			clear = 1;
75			break;
76		case 'd':
77			nodaemon = 1;
78			break;
79		case 't':
80			polltime = atoi(optarg);
81			break;
82		default:
83			fprintf(stderr, usage, *v);
84			return (1);
85		}
86	}
87
88	carray = malloc(a);
89	if (carray == NULL) {
90		perror("malloc");
91		return (1);
92	}
93	for (dev = optind; dev < a; dev++)
94		carray[dev] = (encioc_enc_status_t) -1;
95
96	/*
97	 * Check to make sure we can open all devices
98	 */
99	for (dev = optind; dev < a; dev++) {
100		fd = open(v[dev], O_RDWR);
101		if (fd < 0) {
102			perror(v[dev]);
103			return (1);
104		}
105		if (ioctl(fd, ENCIOC_INIT, NULL) < 0) {
106			fprintf(stderr, "%s: ENCIOC_INIT fails- %s\n",
107			    v[dev], strerror(errno));
108			return (1);
109		}
110		(void) close(fd);
111	}
112	if (nodaemon == 0) {
113		if (daemon(0, 0) < 0) {
114			perror("daemon");
115			return (1);
116		}
117		openlog("sesd", LOG_CONS, LOG_USER);
118	} else {
119		openlog("sesd", LOG_CONS|LOG_PERROR, LOG_USER);
120	}
121
122	for (;;) {
123		for (dev = optind; dev < a; dev++) {
124			fd = open(v[dev], O_RDWR);
125			if (fd < 0) {
126				syslog(LOG_ERR, "%s: %m", v[dev]);
127				continue;
128			}
129
130			/*
131			 * Get the actual current enclosure status.
132			 */
133			if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &stat) < 0) {
134				syslog(LOG_ERR,
135				    "%s: ENCIOC_GETENCSTAT- %m", v[dev]);
136				(void) close(fd);
137				continue;
138			}
139			if (stat != 0 && clear) {
140				nstat = 0;
141				if (ioctl(fd, ENCIOC_SETENCSTAT,
142				    (caddr_t) &nstat) < 0) {
143					syslog(LOG_ERR,
144					    "%s: ENCIOC_SETENCSTAT- %m", v[dev]);
145				}
146			}
147			(void) close(fd);
148
149			if (stat == carray[dev])
150				continue;
151
152			carray[dev] = stat;
153			if ((stat & ALLSTAT) == 0) {
154				syslog(LOG_NOTICE,
155				    "%s: Enclosure Status OK", v[dev]);
156			}
157			if (stat & SES_ENCSTAT_INFO) {
158				syslog(LOG_NOTICE,
159				    "%s: Enclosure Has Information", v[dev]);
160			}
161			if (stat & SES_ENCSTAT_NONCRITICAL) {
162				syslog(LOG_WARNING,
163				    "%s: Enclosure Non-Critical", v[dev]);
164			}
165			if (stat & SES_ENCSTAT_CRITICAL) {
166				syslog(LOG_CRIT,
167				    "%s: Enclosure Critical", v[dev]);
168			}
169			if (stat & SES_ENCSTAT_UNRECOV) {
170				syslog(LOG_ALERT,
171				    "%s: Enclosure Unrecoverable", v[dev]);
172			}
173		}
174		sleep(polltime);
175	}
176	/* NOTREACHED */
177}
178