Fix two bugs related to command execution:
[dockapps.git] / wmweather+ / warnings.c
blobf1343443cb51d635c68a7184e172706f30938986
1 #include "config.h"
3 /* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #if TM_IN_SYS_TIME
21 # if TIME_WITH_SYS_TIME
22 # include <sys/time.h>
23 # include <time.h>
24 # else
25 # if HAVE_SYS_TIME_H
26 # include <sys/time.h>
27 # else
28 # include <time.h>
29 # endif
30 # endif
31 #else
32 #include <time.h>
33 #endif
34 #include <unistd.h>
35 #include <string.h>
36 #include <sys/stat.h>
37 #include <sys/wait.h>
39 #include <pcre.h>
41 #include "wmweather+.h"
42 #include "download.h"
43 #include "getLine.h"
44 #include "diff.h"
45 #include "die.h"
46 #include "subst.h"
48 /* Important variables */
49 static char *warning_filename1=NULL;
50 static char *warning_endptr1=NULL;
52 static char *filenames[]={
53 "tornado", "flash_flood>warning", "flash_flood>watch",
54 "flash_flood>statement", "flood>warning", "flood>coastal",
55 "flood>statement", "severe_weather_stmt", "special_weather_stmt",
56 "thunderstorm", "special_marine", "urgent_weather_message", "non_precip",
57 "fire_weather", "lake_shore", NULL
59 static char **reqs[sizeof(filenames)/sizeof(*filenames)-1][2];
61 unsigned long current_warnings;
62 static unsigned long *zone_current_warnings;
64 /* Regular Expressions */
65 static pcre *expires;
66 static int ovecsize;
68 /* prototypes */
69 static int check_warning(char *file);
72 /* functions */
74 #define compile(var, re) \
75 var=pcre_compile(re, 0, (const char **)&e, &i, NULL); \
76 if(var==NULL) die("init_warnings PCRE error: %s at %i", e, i); \
77 pcre_fullinfo(var, NULL, PCRE_INFO_CAPTURECOUNT, &i); \
78 if(i>ovecsize) ovecsize=i;
80 void init_warnings(void){
81 int i, j, z=0;
82 char *e;
83 struct subst_val subs[]={
84 { 'z', STRING, NULL },
85 { 'f', STRING, &bigbuf },
86 { 0, 0, 0 }
89 /* Count zones, and find length of longest */
90 for(i=0; warning_zones[i]!=NULL; i++){
91 j=strlen(warning_zones[i]);
92 if(j>z) z=j;
95 /* Allocate char ptrs for each filename for each zone */
96 for(j=0; filenames[j]!=NULL; j++){
97 reqs[j][0]=malloc(sizeof(char *)*i);
98 reqs[j][1]=malloc(sizeof(char *)*i);
99 if(reqs[j][0]==NULL || reqs[j][1]==NULL) die("init_warnings malloc");
101 zone_current_warnings=calloc(i, sizeof(*zone_current_warnings));
102 if(zone_current_warnings==NULL) die("init_warnings malloc");
104 /* Allocate filename base */
105 e=get_pid_filename("");
106 i=strlen(e);
107 warning_filename1=malloc(i+z+32);
108 if(warning_filename1==NULL)
109 die("init_warnings malloc");
111 strcpy(warning_filename1, e);
112 free(e);
113 warning_endptr1=warning_filename1+i;
115 /* Setup misc vars */
116 current_warnings=0;
117 ovecsize=0;
118 compile(expires, "Expires:(\\d+)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d);");
119 ovecsize=(ovecsize+1)*3;
121 /* Remove stale files, and allocate URIs */
122 for(z=0; warning_zones[z]!=NULL; z++){
123 subs[0].val=warning_zones+z;
124 for(i=0; filenames[i]!=NULL; i++){
125 sprintf(warning_endptr1, "%s.%s.txt", warning_zones[z], filenames[i]);
126 unlink(warning_filename1);
127 sprintf(warning_endptr1, "%s.new-%s.txt", warning_zones[z], filenames[i]);
128 unlink(warning_filename1);
129 strncpy(bigbuf, filenames[i], BIGBUF_LEN);
130 bigbuf[BIGBUF_LEN-1]='\0';
131 for(j=0; bigbuf[j]; j++){
132 if(bigbuf[j]=='>') bigbuf[j]='/';
134 if((reqs[i][0][z]=subst(warning_uri, subs))==NULL) die("init_warning");
135 reqs[i][1][z]=NULL;
136 if(warning_post!=NULL && (reqs[i][1][z]=subst(warning_post, subs))==NULL) die("init_warning");
140 #undef compile
142 struct callback_data {
143 int zone;
144 int warning;
147 static void warning_callback(char *filename, void *v){
148 struct stat statbuf;
149 struct callback_data *d=(struct callback_data *)v;
151 sprintf(warning_endptr1, "%s.%s.txt", warning_zones[d->zone], filenames[d->warning]);
152 if(stat(filename, &statbuf)>=0){
153 if(S_ISREG(statbuf.st_mode) && statbuf.st_size!=0
154 && check_warning(filename)
155 && diff(filename, warning_filename1)){
156 current_warnings|=1<<d->warning;
157 zone_current_warnings[d->zone]|=1<<d->warning;
158 rename(filename, warning_filename1);
159 } else {
160 unlink(filename);
165 void warnings_cleanup(void){
166 int i, z;
168 if(warning_filename1==NULL) return;
169 for(z=0; warning_zones[z]!=NULL; z++){
170 for(i=0; filenames[i]!=NULL; i++){
171 sprintf(warning_endptr1, "%s.%s.txt", warning_zones[z], filenames[i]);
172 unlink(warning_filename1);
173 sprintf(warning_endptr1, "%s.new-%s.txt", warning_zones[z], filenames[i]);
174 unlink(warning_filename1);
179 void update_warnings(int force){
180 // time_t t;
181 struct stat statbuf;
182 int i, z;
183 struct callback_data *d;
185 if(warning_filename1==NULL) return;
186 // t=time(NULL)/60;
187 // if(!force && warning_time>t) return;
189 // warning_time=t+15;
191 for(z=0; warning_zones[z]!=NULL; z++){
192 for(i=0; filenames[i]!=NULL; i++){
193 /* expire old wanrings */
194 sprintf(warning_endptr1, "%s.%s.txt", warning_zones[z], filenames[i]);
195 if(stat(warning_filename1, &statbuf)>=0){
196 if(!S_ISREG(statbuf.st_mode) || statbuf.st_size==0
197 || !check_warning(warning_filename1)){
198 unlink(warning_filename1);
199 current_warnings&=~(1<<i);
200 zone_current_warnings[z]&=~(1<<i);
202 } else {
203 current_warnings&=~(1<<i);
204 zone_current_warnings[z]&=~(1<<i);
207 if((d=malloc(sizeof(*d)))==NULL) continue;
208 sprintf(warning_endptr1, "%s.new-%s.txt", warning_zones[z], filenames[i]);
209 d->zone=z;
210 d->warning=i;
211 download_file(warning_filename1, reqs[i][0][z], reqs[i][1][z], DOWNLOAD_NO_404, warning_callback, d);
217 #define get_substr(n, c) \
218 if(pcre_get_substring(s, ovector, ovalue, n, (const char **)&c)<0){ free(s); return 0; }
220 static int check_warning(char *file){
221 FILE *fp;
222 char *s, *c;
223 int len;
224 int i;
225 time_t t;
226 struct tm *tm;
227 int ovector[ovecsize];
228 int ovalue;
230 if((fp=fopen(file, "r"))==NULL) return 0;
231 ovalue=-1;
232 while((len=getLine(&s, fp))>0){
233 ovalue=pcre_exec(expires, NULL, s, len, 0, 0, ovector, ovecsize);
234 if(ovalue>0) break;
235 free(s);
237 fclose(fp);
238 if(ovalue<=0) return 0;
240 t=time(NULL);
241 tm=gmtime(&t);
242 get_substr(1, c); i=atoi(c)-1900; pcre_free_substring(c);
243 if(tm->tm_year<i){ free(s); return 1; }
244 if(tm->tm_year>i){ free(s); return 0; }
245 get_substr(2, c); i=atoi(c)-1; pcre_free_substring(c);
246 if(tm->tm_mon<i){ free(s); return 1; }
247 if(tm->tm_mon>i){ free(s); return 0; }
248 get_substr(3, c); i=atoi(c); pcre_free_substring(c);
249 if(tm->tm_mday<i){ free(s); return 1; }
250 if(tm->tm_mday>i){ free(s); return 0; }
251 get_substr(4, c); i=atoi(c); pcre_free_substring(c);
252 if(tm->tm_hour<i){ free(s); return 1; }
253 if(tm->tm_hour>i){ free(s); return 0; }
254 get_substr(5, c); i=atoi(c); pcre_free_substring(c);
255 if(tm->tm_min<=i){ free(s); return 1; }
256 free(s); return 0;
259 void output_warnings(int all){
260 FILE *fp;
261 int i, z, len;
262 pid_t pid;
263 int pipefd[2];
265 if(!all && current_warnings==0) return;
267 if(pipe(pipefd)) die("output_warnings pipe creation");
269 /* Fork to display the file */
270 pid=fork();
271 if(pid==-1){
272 warn("output_warnings fork");
273 return;
275 /* CHILD: Redirects stdin/stderr/stdout and execs the viewer */
276 if(pid==0){
277 close(pipefd[1]);
278 dup2(pipefd[0], STDIN_FILENO);
279 dup2(devnull, STDOUT_FILENO);
280 execl("/bin/sh", "/bin/sh", "-c", viewer, NULL);
281 die("output_warnings exec");
284 /* PARENT writes warnings to the pipe and returns */
285 close(pipefd[0]);
286 for(z=0; warning_zones[z]!=NULL; z++){
287 if(!zone_current_warnings[z]) continue;
288 for(i=0; filenames[i]!=NULL; i++){
289 if(!all && !(zone_current_warnings[z]&(1<<i))) continue;
291 sprintf(warning_endptr1, "%s.%s.txt", warning_zones[z], filenames[i]);
292 if((fp=fopen(warning_filename1, "r"))==NULL) continue;
293 snprintf(bigbuf, BIGBUF_LEN, "======== BEGIN %s %s ========\n", warning_zones[z], filenames[i]);
294 write(pipefd[1], bigbuf, strlen(bigbuf));
295 while(!feof(fp)){
296 len=fread(bigbuf, sizeof(char), BIGBUF_LEN, fp);
297 write(pipefd[1], bigbuf, len);
299 fclose(fp);
301 if(!all) zone_current_warnings[z]=0;
303 close(pipefd[1]);
304 if(!all) current_warnings=0;
305 return;