1 /*
2  * Copyright 1996, 1997, 1998, 1999 by Daniel B. Suthers,
3  * Pleasanton Ca. 94588 USA
4  * E-MAIL dbs@tanj.com
5  *
6  */
7 
8 /*
9  *   This program is free software: you can redistribute it and/or modify
10  *   it under the terms of the GNU General Public License as published by
11  *   the Free Software Foundation, either version 3 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This program is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23 
24 
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <signal.h>
34 #include <setjmp.h>
35 #include <errno.h>
36 #include <syslog.h>
37 #if defined(SYSV) || defined(FREEBSD) || defined(OPENBSD)
38 #include <string.h>
39 #else
40 #include <strings.h>
41 #endif
42 
43 #include <time.h>
44 
45 #include "x10.h"
46 #include "process.h"
47 
48 
49 #ifdef __GLIBC__
50 /* msf - added for glibc/rh 5.0 */
51 #include <sys/types.h>
52 #endif
53 
54 extern int timeout;
55 extern int sptty;
56 extern int i_am_monitor, i_am_state, i_am_relay, i_am_rfxmeter;
57 extern int heyu_parent;
58 extern void fix_tznames ( void );
59 extern void x10state_init_all ();
60 extern int read_x10state_file ();
61 extern CONFIG config;
62 extern CONFIG *configp;
63 extern FILE *fdsout, *fdserr;
64 extern FILE *fprfxo, *fprfxe;
65 extern char *datstrf(void);
66 extern int  clear_data_storage( void );
67 
68 void iquit();
69 jmp_buf mjb;
70 
iquit(int signo)71 void iquit( int signo )
72 {
73     longjmp(mjb, 1);
74 }
75 
engine_quit(int signo)76 void engine_quit ( int signo )
77 {
78    char buffer[PATH_LEN + 1];
79    signal(SIGTERM, engine_quit);
80    syslog(LOG_ERR, "interrupt received\n");
81    write_x10state_file();
82    sprintf(buffer, "%s/LCK..%s%s", LOCKDIR, STATE_LOCKFILE, configp->suffix);
83    unlink(buffer);
84    exit(0);
85 }
86 
c_monitor(int argc,char * argv[])87 int c_monitor( int argc, char *argv[] )
88 {
89     off_t f_offset;
90     int check4poll();
91     struct stat stat_buf;
92     char spoolfile[100];
93     time_t time_now, time_prev;
94 
95     sprintf( spoolfile, "%s/%s%s", SPOOLDIR, SPOOLFILE, configp->suffix);
96     (void) signal(SIGCHLD, iquit);
97     (void) signal(SIGINT, iquit);
98     if (setjmp(mjb))
99 	return(0);
100 
101     i_am_monitor = 1;
102 
103     if ( read_x10state_file() != 0 )
104        x10state_init_all();
105 
106     if ( argc == 3 && strcmp(argv[2], "rfxmeter") == 0 ) {
107        /* Disable display except for RFXMeter setup file pointers */
108        i_am_monitor = 0;
109        i_am_rfxmeter = 1;
110        fdsout = fopen("/dev/null", "w");
111        fdserr = fopen("/dev/null", "w");
112        fprfxo = stdout;
113        fprfxe = stderr;
114     }
115     else {
116        fprintf(stdout, "%s Monitor started\n", datstrf());
117        fflush(stdout);
118     }
119 
120     f_offset = lseek(sptty, 0, SEEK_CUR);  /* find current position */
121 
122     time_now = time_prev = time(NULL);
123 
124 
125     while (1)  {
126 	if( f_offset == lseek(sptty, 0, SEEK_END) )  {  /* find end of file */
127 	    if( stat( spoolfile, &stat_buf ) < 0)
128 	        return(0);
129 
130 	    /* this imposes a delay between the start of new output*/
131 	    /* It keeps the disk from being thrashed. */
132 	    microsleep(configp->engine_poll);
133 	}
134 	else {
135 	    if ( fstat( sptty, &stat_buf ) < 0 )
136 	         return(0);
137 	    lseek(sptty, f_offset, SEEK_SET);
138 	    check4poll(1,1);
139 	    f_offset = lseek(sptty, 0, SEEK_CUR);  /* find current position */
140 	}
141 
142         /* Activate countdown timers */
143         if ( (time_now = time(NULL)) != time_prev ) {
144            second_tick(time_now, (long)(time_now - time_prev));
145            time_prev = time_now;
146         }
147     }
148     /* return(0); */
149 }
150 
c_engine(int argc,char * argv[])151 int c_engine( int argc, char *argv[] )
152 {
153     off_t f_offset;
154     int check4poll();
155     struct stat stat_buf;
156     char spoolfile[100];
157     time_t time_now, time_prev;
158     long   tmin_now, tmin_prev, thour_now, thour_prev;
159     mode_t oldumask;
160     extern FILE *fdsout;
161     extern FILE *fdserr;
162 
163     sprintf( spoolfile, "%s/%s%s", SPOOLDIR, SPOOLFILE, configp->suffix);
164 
165     (void) signal(SIGINT, engine_quit /*iquit*/);
166     (void) signal(SIGTERM, engine_quit);
167 
168     if (setjmp(mjb))
169 	return(0);
170 
171     i_am_state = 1;
172     i_am_monitor = 1;
173     heyu_parent = D_CMDLINE;
174 
175     openlog( "heyu_engine", 0, LOG_DAEMON);
176     syslog(LOG_ERR, "engine setting up-\n");
177 
178     if ( read_x10state_file() != 0 )
179        x10state_init_all();
180 
181     time_now = time_prev = time(NULL);
182     tmin_now = tmin_prev = (long)time_now / 60L;
183     thour_now = thour_prev = (long)time_now / 3600;
184 
185     engine_local_setup(E_START);
186     fix_tznames();
187 
188     f_offset = lseek(sptty, 0, SEEK_CUR);  /* find current position */
189 
190     oldumask = umask(configp->log_umask);
191     fdsout = freopen(configp->logfile, "a", stdout);
192     fdserr = freopen(configp->logfile, "a", stderr);
193     umask(oldumask);
194 
195     fprintf(fdsout, "%s Engine started\n", datstrf());
196     fflush(fdsout);
197 
198     while (1) {
199 	if ( f_offset == lseek(sptty, 0, SEEK_END) )  {  /* find end of file */
200 	    if( stat( spoolfile, &stat_buf ) < 0)
201 	       engine_quit(SIGTERM) /* return(0) */;
202 
203 	    /* this imposes a delay between the start of new output*/
204 	    /* It keeps the disk from being thrashed. */
205 	    microsleep(configp->engine_poll);
206 	}
207 	else {
208 	    if ( fstat( sptty, &stat_buf ) < 0)
209 	         return(0);
210 	    lseek(sptty, f_offset, SEEK_SET);
211 	    check4poll(1,1);
212 	    f_offset = lseek(sptty, 0, SEEK_CUR);  /* find current position */
213 	}
214 
215         if ( (time_now = time(NULL)) != time_prev ) {
216            if ( is_tomorrow(time_now) ) {
217               /* Local Midnight. STD Time */
218               midnight_tick(time_now);
219               set_global_tomorrow(time_now);
220            }
221            if ( (thour_now = (long)time_now / 3600L) != thour_prev ) {
222               /* Once every hour */
223               hour_tick(time_now);
224               thour_prev = thour_now;
225            }
226            if ( (tmin_now = (long)time_now / 60L) != tmin_prev ) {
227               /* Once every minute */
228               minute_tick(time_now);
229               tmin_prev = tmin_now;
230            }
231            /* Once every second */
232            /* Activate countdown timers */
233            second_tick(time_now, (long)(time_now - time_prev));
234            time_prev = time_now;
235         }
236     }
237     /* return(0); */
238 }
239 
240