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