1 /*-
2  * Copyright (c) 1995-2006 Ederson de Moura <ederbs@ederbs.org>
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  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 
28 #include <stdio.h>   /* Standard input/output definitions */
29 #include <string.h>  /* String function definitions */
30 #include <unistd.h>  /* UNIX standard function definitions */
31 #include <fcntl.h>   /* File control definitions */
32 #include <errno.h>   /* Error number definitions */
33 #include <termios.h> /* POSIX terminal control definitions */
34 #include <syslog.h>  /* Definitions for system error logging */
35 #include <stdlib.h>  /* exit() definition */
36 
37 #define PROG " UpsDaemon"
38 #define VERSION " 1.0"
39 
40 #ifndef PLATFORM
41 #define PLARFORM "Unix"
42 #endif
43 
44 #define WAIT		5*60
45 #define PORT		"/dev/cuad0"
46 #define PID             "/var/run/upsdaemon.pid"
47 
48 #define SH_BATTERY	"/usr/local/libexec/upsdaemon/upsdaemon-alerts -battery"
49 #define SH_DOWN		"/usr/local/libexec/upsdaemon/upsdaemon-alerts -down"
50 #define SH_FAILED	"/usr/local/libexec/upsdaemon/upsdaemon-alerts -failed"
51 #define SH_RECOVERY	"/usr/local/libexec/upsdaemon/upsdaemon-alerts -recovery"
52 
53 int makepid(char *s);
54 static void runcommand();
55 
main(int argc,char ** argv)56 int main(int argc, char **argv)
57 {
58 	int fd;
59 	int lstatus;
60 
61 	int rts_bit = TIOCM_RTS;
62 	int dtr_bit = TIOCM_DTR;
63 	int pfail = 0;
64 
65 	int pfcount = 0;
66 	int prcount = 0;
67 	int blcount = 0;
68 
69 	char *port = PORT;
70 
71 	char *down      = SH_DOWN;
72         char *battery   = SH_BATTERY;
73 	char *failed    = SH_FAILED;
74 	char *recovery  = SH_RECOVERY;
75 
76 
77 	if(argc > 2) {
78 		errx(1,"Usage: upsdaemon <port serial open>: %s\n", strerror(errno));
79 	}
80 	if(argc == 2) {
81 		port = argv[1];
82 	}
83 
84 	/*
85 	 *
86 	 * SGI Pinouts:
87 	 *
88 	 *               	   \ o o o o o /
89 	 *                          \ o o o o /
90 	 *
91 	 *                  Table SGI 9-Pin DSUB Signals
92 	 * -----------------------------------------------------------------
93 	 * | 1 -> Earth Ground           | 6 -> DSR  - Data Set Ready      |
94 	 * | 2 -> TXD - Transmitted Data | 7 -> GND  - Logic Ground        |
95 	 * | 3 -> RXD - Received Data    | 8 -> DCD  - Data Carrier Detect |
96 	 * | 4 -> RTS - Request To Send  | 9 -> DTR  - Data Terminal Ready |
97 	 * | 5 -> CTS - Clear To Send    |                                 |
98 	 * -----------------------------------------------------------------
99 	 *
100 	 */
101 	if((fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY)) < 0) {
102 		perror("Uspdaemon Error: Unable to open " PORT);
103 		exit(1);
104 	}
105 
106 	ioctl(fd, TIOCMBIC, &rts_bit);
107 	ioctl(fd, TIOCMBIS, &dtr_bit);
108 
109 	if(daemon(1,1) < 0) {
110 		syslog(LOG_ERR, "Alert: It was not possible to be daemon: %m");
111 		exit(1);
112 	}
113 
114 	/* Set PID */
115 	(void)makepid(PID);
116 
117 	while(1) {
118 		ioctl(fd, TIOCMBIC, &rts_bit);
119 		ioctl(fd, TIOCMBIC, &dtr_bit);
120 		ioctl(fd, TIOCMBIS, &dtr_bit);
121 		ioctl(fd, TIOCMGET, &lstatus);
122 
123 		if(!(lstatus & TIOCM_CAR)) {
124 
125 			++blcount;
126 			if(blcount == 6) {
127 
128 			syslog(LOG_ALERT, "Alert: Without contact with Ups.", PROG VERSION);
129 
130 			ioctl(fd, TIOCMBIC, &dtr_bit);
131 			ioctl(fd, TIOCMBIS, &dtr_bit);
132 			ioctl(fd, TIOCMGET, &lstatus);
133 
134 			if(!(lstatus & TIOCM_CTS)) {
135 
136 				ioctl(fd, TIOCMBIC, &dtr_bit);
137 				ioctl(fd, TIOCMBIS, &dtr_bit);
138 				ioctl(fd, TIOCMBIS, &rts_bit);
139 
140 				/* It fell in the battery Ups */
141 				runcommand(battery);
142 				sleep(100);
143 				}
144 			}
145 		}
146 		else if(!(lstatus & TIOCM_CTS)) {
147 			++pfcount;
148 			prcount = 0;
149 			blcount = 0;
150 			if(pfcount == 3) {
151 
152 				syslog(LOG_WARNING, "Alert: Failed in the communication with the Ups.", PROG VERSION);
153 
154 				/* Run failed communication Ups */
155 				runcommand(failed);
156 				pfail = 1;
157 			}
158 
159                         /* Time (wait - 5) minutes defined */
160 			if(pfcount == WAIT) {
161 
162 				syslog(LOG_ALERT, "Alert: Failed down server.", PROG VERSION);
163 
164 				ioctl(fd, TIOCMBIC, &dtr_bit);
165 				ioctl(fd, TIOCMBIS, &dtr_bit);
166 				ioctl(fd, TIOCMBIS, &rts_bit);
167 
168 				/* Run shutdown server, now */
169 				runcommand(down);
170 
171 				sleep(100);
172 			}
173 		}
174 		else if(pfail == 1) {
175 
176 			++prcount;
177 			pfcount = 0;
178 			if(prcount == 3) {
179 
180 				/* Run recovery energy */
181 				runcommand(recovery);
182 
183 				pfail = 0;
184 				blcount = 0;
185 				ioctl(fd, TIOCMBIC, &rts_bit);
186 				ioctl(fd, TIOCMBIC, &dtr_bit);
187 				ioctl(fd, TIOCMBIS, &dtr_bit);
188 			}
189 		else blcount = 0;
190 		}
191 	sleep(1);
192 	}
193 }
194 
195 /*
196  * Check Routines Shell
197  */
runcommand(shell_script)198 void runcommand(shell_script)
199 char *shell_script;
200 {
201 	switch(fork()) {
202 	case 0:
203 		system(shell_script);
204 		exit(0);
205 	case -1:
206 		errx(1, "Error: Not found the routine: %s", strerror(errno));
207 		break;
208 	default:
209 		break;
210 	}
211 }
212 
213 /*
214  * To Create PID
215  */
makepid(s)216 int makepid(s)
217 char *s;
218 {
219 	FILE *fp;
220 	pid_t pid;
221 
222 	pid = getpid();
223 	if((fp =  fopen(s, "w")) == NULL)
224 		return -1;
225 	fprintf(fp, "%lu\n", (u_long)pid);
226 	fclose(fp);
227 	return 0;
228 }
229