xref: /freebsd/share/examples/ses/srcs/sesd.c (revision b00ab754)
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 
55 int
56 main(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