Subversion Repositories heizung

Rev

Rev 3 | Rev 5 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 root 1
/*
2
 * (C) Copyright 2010 by Andreas Theofilu <andreas@theosys.at>
3
 * All rights reserved!
4
 */
5
 
6
#include <stdio.h>
7
#include <string.h>
8
#include <unistd.h>
9
#include <stdlib.h>
10
#include <math.h>
11
#include <time.h>
12
#include <signal.h>
13
#include <syslog.h>
14
#include <errno.h>
15
#include <pthread.h>
16
#include <sys/stat.h>
17
#include <sys/types.h>
18
#include <sys/socket.h>
19
#include <fcntl.h>
20
#include <netdb.h>
21
#include <netinet/in.h>
22
#include <sys/param.h>
23
#include <sys/ioctl.h>
24
#include <pwd.h>
25
#include <grp.h>
26
 
27
typedef struct
28
{
29
      char User[32];
30
      char Grp[32];
31
      char HeizPath[256];
32
      int port;
33
}CONFIGURE;
34
 
35
typedef struct
36
{
37
      int wday;
38
      ulong start;
39
      ulong end;
40
      float temp;
41
}HEIZUNG;
42
 
43
typedef struct HEIZINDEX
44
{
45
      HEIZUNG *heizung;
4 andreas 46
      struct HEIZINDEX *next;
1 root 47
}HEIZINDEX;
48
 
49
CONFIGURE configs;
50
HEIZINDEX *HeizFirst;
51
float ActTemperature;
52
float ActPressure;
53
 
54
static pthread_t pthr_pars;
55
 
56
// Prototypes
57
void daemon_start(int ignsigcld);
58
void *pthr_parser(void *pV_data);
59
void sig_child(void);
60
int parseCommand(int s1, char *cmd);
4 andreas 61
void changeToUser(char *, char *);
1 root 62
 
63
HEIZINDEX *allocateMemory(void);
4 andreas 64
HEIZINDEX *insertMemory(HEIZINDEX *pos);
1 root 65
void freeMemory(void);
4 andreas 66
HEIZINDEX *freeChainMember(HEIZINDEX *member);
67
void freeDay(int wday);
68
void insertMember(int wday, long endt, float temp);
1 root 69
int readHeizPlan(void);
70
int writeHeizPlan(void);
71
void readConf(void);
72
 
4 andreas 73
char *readLine(int fd, char *buf, int bufLen);
1 root 74
char *trim(char *str);
2 andreas 75
char *remove_string(char *str, char *search, char *ret);
1 root 76
 
77
static pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
78
 
79
/*
80
 * The main program, initializing everything and start the daemon.
81
 */
82
int main(int argc, char *argv[])
83
{
84
int fd, index;
85
 
86
	HeizFirst = NULL;
87
	readConf();
88
	// Now daemonize this application
89
	daemon_start(0);
4 andreas 90
	changeToUser(&configs.User[0], &configs.Grp[0]);
1 root 91
	// Now start our Thread
92
	if (pthread_create(&pthr_pars, NULL, pthr_parser, (void *)0) != 0)
93
	{
94
	   syslog (LOG_DAEMON,"Create of thread \"pthr_parser\" failed!");
95
	   return 1;
96
	}
97
 
98
	while (1)
99
	   sleep(3600);
100
 
101
	return 0;
102
}
103
 
104
/*
105
 * Detach application from console and make it a daemon.
106
 */
107
void daemon_start (int ignsigcld)
108
{
109
int childpid, fd;
110
 
111
        if (getpid () == 1)
112
           goto out;
113
 
114
#ifdef SIGTTOU
115
        signal (SIGTTOU, SIG_IGN);
116
#endif
117
#ifdef SIGTTIN
118
        signal (SIGTTIN, SIG_IGN);
119
#endif
120
#ifdef SIGTSTP
121
        signal (SIGTSTP, SIG_IGN);
122
#endif
123
 
124
        if ((childpid = fork ()) < 0)
125
           fprintf (stderr, "Can't fork this child\n");
126
        else if (childpid > 0)
127
           exit (0);
128
 
129
        if (setpgrp () == -1)
130
           fprintf (stderr, "Can't change process group\n");
131
 
132
        signal (SIGHUP, SIG_IGN);
133
 
134
        if ((childpid = fork ()) < 0)
135
           syslog (LOG_DAEMON, "Can't fork second child");
136
        else if (childpid > 0)
137
           exit (0);            /* first child */
138
 
139
        /* second child */
140
out:
141
        for (fd = 0; fd < NOFILE; fd++)
142
           close (fd);
143
 
144
        errno = 0;
145
        chdir ("/");
146
        umask (0);
147
 
148
        if (ignsigcld)
149
        {
150
//#ifdef SIGTSTP
151
//           signal (SIGCLD, sig_child);
152
//#else
153
           signal (SIGCLD, SIG_IGN);
154
//#endif
155
        }
156
}
157
 
158
void sig_child ()
159
{
160
#if defined(BSD) && !defined(sinix) && !defined(Linux)
161
int pid;
162
union wait status;
163
 
164
        while ((pid = wait3 (&status, WNOHANG, (struct rusage *)0)) > 0)
165
                ;
166
#endif
167
}
168
 
169
void changeToUser(char *usr, char *grp)
170
{
171
gid_t gr_gid;
172
 
173
	if (usr && strlen(usr))
174
	{
175
	   /* get uid */
176
	   struct passwd *userpwd;
177
	   struct group *usergrp;
178
 
179
	   if ((userpwd = getpwnam(usr)) == NULL)
180
	   {
181
	      syslog(LOG_DAEMON,"no such user: %s", usr);
182
	      exit(EXIT_FAILURE);
183
	   }
184
 
185
	   if (!grp || strlen(grp) || (usergrp = getgrnam(grp)) == NULL)
186
	   {
187
	      if (grp && strlen(grp))
188
	         syslog(LOG_WARNING,"no such group: %s", grp);
189
 
190
	      gr_gid = userpwd->pw_gid;
191
	   }
192
	   else
193
	      gr_gid = usergrp->gr_gid;
194
 
195
	   if (setgid(gr_gid) == -1)
196
	   {
197
	      syslog(LOG_DAEMON,"cannot setgid of user %s: %s", usr, strerror(errno));
198
	      exit(EXIT_FAILURE);
199
	   }
200
 
201
#ifdef _BSD_SOURCE
202
	   /* init suplementary groups
203
	    * (must be done before we change our uid)
204
	    */
205
	   if (initgroups(usr, gr_gid) == -1)
206
	      syslog(LOG_DAEMON,"cannot init suplementary groups of user %s: %s", usr, strerror(errno));
207
#endif
208
 
209
	   /* set uid */
210
	   if (setuid(userpwd->pw_uid) == -1)
211
	   {
212
	      syslog(LOG_DAEMON,"cannot change to uid of user %s: %s\n", usr, strerror(errno));
213
	      exit(EXIT_FAILURE);
214
	   }
215
 
216
	   if(userpwd->pw_dir)
217
	      setenv("HOME", userpwd->pw_dir, 1);
218
        }
219
}
220
 
221
void *pthr_parser( void *pV_data )
222
{
223
int i;
224
char ch, buf[128];
225
// socket structure
226
struct sockaddr_in client1, server1;
227
struct servent *serviceInfo;
228
int s1,s;
229
socklen_t length;
230
 
231
	// socket server
232
	if (configs.port > 0)
233
	   server1.sin_port = htons(configs.port);
234
	else if ((serviceInfo = getservbyname ("heizung", "tcp")))
235
	   server1.sin_port = serviceInfo->s_port;
236
	else
237
	{
238
	   syslog(LOG_DAEMON,"Error: No TCP port defined!");
239
	   exit(EXIT_FAILURE);
240
	}
241
 
242
	server1.sin_family = AF_INET;
243
	server1.sin_addr.s_addr = INADDR_ANY;
244
	s = socket(AF_INET,SOCK_STREAM,0);
245
 
246
	if (s < 0)
247
	   syslog (LOG_DAEMON, "Error in socket");
248
 
249
	if (bind (s, (struct sockaddr *)&server1, sizeof (server1)) < 0)
250
	   syslog (LOG_DAEMON, "Error in bind");
251
 
252
	if (listen (s, 5) < 0)
253
	   syslog (LOG_DAEMON, "Error in listen");
254
 
255
	length = sizeof(client1);
256
        syslog (LOG_DEBUG, "Server ready: %d",s);
257
 
258
	while (1)
259
	{
260
	   // Read time table at every loop, to be sure to have the latest
261
	   // version (User may change it at every time)
262
	   if (!readHeizPlan())
263
	   {
264
	      if (!HeizFirst)
265
	      {
266
	         syslog(LOG_DAEMON, "Error reading table with plan!");
267
	         return NULL;
268
	      }
269
	      else
270
		 syslog(LOG_DAEMON, "Error reading table with plan! Will work with old one.");
271
	   }
272
 
273
	   if ((s1 = accept (s, (struct sockaddr *)&client1, &length)) < 0)
274
	      syslog (LOG_DAEMON, "Error in accept: %d", s1);
275
 
276
	   pthread_mutex_lock (&fastmutex);
277
	   syslog (LOG_INFO, "Connected to client");
278
	   memset(&buf[0], 0, sizeof(buf));
279
	   i = 0;
280
 
281
	   while (read(s1,&ch,1) > 0)
282
	   {
283
	      if (i < (sizeof(buf) - 1))
284
	      {
285
		 buf[i] = ch;
286
 
4 andreas 287
		 if (ch == ';' || ch == 0x0d)
1 root 288
		 {
4 andreas 289
		    if (!strncmp(buf, "quit", 4))
290
		       break;
1 root 291
 
292
		    if (!parseCommand(s1,buf))
293
		    {
294
		    char hv0[128];
295
 
296
		       sprintf(&hv0[0],"INVALID COMMAND: %s;",buf);
297
		       write(s1,hv0,strlen(hv0));
298
		    }
299
		    else
300
		       write(s1,"OK;",3);
301
 
302
		    memset(&buf[0], 0, sizeof(buf));
303
		    i = 0;
304
		    continue;
305
		 }
306
	      }
307
 
308
	      i++;
309
	   }
310
 
311
	   pthread_mutex_unlock(&fastmutex);
312
	   close (s1);
313
	}
314
 
315
	return NULL;
316
}
317
 
318
int parseCommand(int s1, char *cmd)
319
{
4 andreas 320
char bef[32],par[1024], *p;
321
char hv0[256];
1 root 322
int i,j;
4 andreas 323
HEIZINDEX *act, *last;
1 root 324
 
325
	memset(bef,0,sizeof(bef));
326
	memset(par,0,sizeof(par));
327
 
328
	if ((p = strchr(cmd,':')) != NULL)		// do we have a parameter?
329
	{
4 andreas 330
	   strncpy(bef,cmd,p - cmd);
331
	   strncpy(par,p+1,strlen(p+1));
1 root 332
	}
333
	else
334
	   strncpy(bef,cmd,strlen(cmd)-1);
4 andreas 335
sprintf(&hv0[0], "%s --> %s\n", bef, par);
336
write(s1, hv0, strlen(hv0));
337
	if (!strcasecmp(bef, "LIST"))		// Write out current list
1 root 338
	{
339
	   act = HeizFirst;
340
	   i = 1;
341
 
342
	   while (act)
343
	   {
4 andreas 344
	      sprintf(&hv0[0], "LINE:%d:%d:%lu:%lu:%f;", i, act->heizung->wday,
1 root 345
		      act->heizung->start, act->heizung->end, act->heizung->temp);
346
	      write(s1, &hv0[0], strlen(hv0));
347
	      i++;
348
	      act = act->next;
349
	   }
350
	}
351
 
4 andreas 352
	if (!strcasecmp(bef, "GET WDAY"))		// Write out a particular week day
1 root 353
	{
4 andreas 354
	int wday = atoi(par);
1 root 355
 
356
	   if (wday < 1 || wday > 7)
357
	   {
358
	      strcpy(&hv0[0], "ERROR:Invalid week day");
359
	      write(s1, &hv0[0], strlen(hv0));
360
	      return 0;
361
	   }
362
 
363
	   act = HeizFirst;
364
 
365
	   while (act && act->heizung->wday != wday)
366
	      act = act->next;
367
 
368
	   if (!act)
369
	   {
370
	      sprintf(&hv0[0], "ERROR:No plan for week day %d", wday);
371
	      write(s1, &hv0[0], strlen(hv0));
372
	      return 0;
373
	   }
374
 
375
	   i = 1;
376
 
377
	   while (act && act->heizung->wday == wday)
378
	   {
4 andreas 379
	      sprintf(&hv0[0], "LINE:%d:%d:%lu:%lu:%f;", i, act->heizung->wday,
1 root 380
		      act->heizung->start, act->heizung->end, act->heizung->temp);
381
	      write(s1, &hv0[0], strlen(hv0));
382
	      i++;
383
	      act = act->next;
384
	   }
385
	}
386
 
4 andreas 387
	if (!strcasecmp(bef, "GET TEMP"))	// Return actual temperature
1 root 388
	{
389
	   sprintf(&hv0[0], "TEMP:%f;", ActTemperature);
390
	   write(s1, &hv0[0], strlen(hv0));
391
	}
392
 
4 andreas 393
	if (!strcasecmp(bef, "GET PRESSURE"))	// Return the actual air pressure
1 root 394
	{
395
	   sprintf(&hv0[0], "PRESSURE:%f;", ActPressure);
396
	   write(s1, &hv0[0], strlen(hv0));
397
	}
398
 
2 andreas 399
	// SET DAY:<count>:<day>:<end1>:<temp>[:<end2>:<temp>[:...]];
400
	// <count>   number of entries following
401
	// <day>     The day of the week
402
	// <end1>    The end time
403
	// <temp>    The temperature wanted until end time is reached
404
	//
4 andreas 405
	if (!strcasecmp(bef, "SET DAY"))		// Set the plan for a particular day
1 root 406
	{
2 andreas 407
	int count, wday, i;
408
	long endt;
409
	float temp;
410
 
4 andreas 411
	   count = atoi(par);
412
	   remove_string(par, ":", &hv0[0]);
413
	   wday = atoi(par);
414
	   freeDay(wday);
415
	   last = NULL;
2 andreas 416
 
417
	   if (count > 0)
418
	   {
419
	      for (i = 0; i < count; i++)
420
	      {
4 andreas 421
		 remove_string(par, ":", &hv0[0]);
422
		 endt = atol(par);
423
		 remove_string(par, ":", &hv0[0]);
424
		 temp = atof(par);
2 andreas 425
 
4 andreas 426
		 if ((act = allocateMemory()) == NULL)
427
		 {
428
		    syslog(LOG_DAEMON,"Error allocating memory for a temperature line.");
429
		    sprintf(&hv0[0], "ERROR:Not enough memory!");
430
		    write(s1, &hv0[0], strlen(hv0));
431
		    return 0;
432
		 }
2 andreas 433
 
4 andreas 434
		 act->heizung->wday = wday;
435
		 act->heizung->end = endt;
436
		 act->heizung->temp = temp;
437
 
438
		 if (last)
439
		    act->heizung->start = act->heizung->end;
440
		 else
441
		    act->heizung->start = 0L;
442
 
443
		 last = act;
2 andreas 444
	      }
445
	   }
1 root 446
	}
447
 
2 andreas 448
	// SET TEMP:<wday>:<end>:<temp>;
4 andreas 449
	if (!strcasecmp(bef, "SET TEMP:"))	// Set the temperature for a particular day and line
1 root 450
	{
4 andreas 451
	int wday;
452
	unsigned long endt;
1 root 453
	float tmp;
454
 
4 andreas 455
	   wday = atoi(par);
456
	   remove_string(par, ":", &hv0[0]);
457
	   endt = atol(par);
458
	   remove_string(par, ":", &hv0[0]);
459
	   tmp = atof(par);
460
	   insertMember(wday, endt, tmp);
1 root 461
	}
462
 
463
	return 1;
464
}
465
 
466
/*
2 andreas 467
 * Remove a complete day
468
 */
469
void freeDay(int wday)
470
{
471
HEIZINDEX *act, *next, *prev;
472
 
473
	act = HeizFirst;
474
	prev = NULL;
475
 
476
	while(act)
477
	{
478
	   if (act->heizung->wday == wday)
479
	      act = freeChainMember(act);
480
 
481
	   act = act->next;
482
	}  
483
}
484
 
485
/*
486
 * Insert a new entry
487
 */
488
void insertMember(int wday, long endt, float temp)
489
{
490
HEIZINDEX *act;
491
 
492
	act = HeizFirst;
493
 
494
	while(act)
495
	{
496
	   if (act->heizung->wday == wday && act->heizung->end == endt)
497
	   {
498
	      act->heizung->temp = temp;
499
	      return;
500
	   }
501
 
502
	   act = act->next;
503
	}
504
 
505
	if ((act = allocateMemory()) != NULL)
506
	{
507
	   act->heizung->wday = wday;
508
	   act->heizung->end = endt;
509
	   act->heizung->temp = temp;
510
	}
511
}
512
 
513
/*
1 root 514
 * Free the memory for the actual heizung plan.
515
 */
516
void freeMemory()
517
{
518
HEIZINDEX *act, *next;
519
 
520
	act = HeizFirst;
521
 
522
	while(act)
523
	{
524
	   if (act->heizung)
525
	   {
526
	      free(act->heizung);
527
	      act->heizung = NULL;
528
	   }
529
 
530
	   next = act->next;
531
	   free(act);
532
	   act = next;
533
	}
534
}
535
 
536
/*
537
 * Free only one entry in the chain
538
 */
2 andreas 539
HEIZINDEX *freeChainMember(HEIZINDEX *member)
1 root 540
{
541
HEIZINDEX *act,*prev;
542
 
543
	act = HeizFirst;
544
	prev = NULL;
545
 
546
	while(act != member)
547
	{
548
	   prev = act;
549
	   act = act->next;
550
	}
551
 
552
	if (act == member)
553
	{
554
	   if (prev)
2 andreas 555
	      prev->next = act->next;
4 andreas 556
	   else
557
	   {
558
	      prev = act->next;
1 root 559
 
4 andreas 560
	      if (act == HeizFirst)
561
		 HeizFirst = act->next;
562
	   }
563
 
1 root 564
	   if (act->heizung)
565
	      free(act->heizung);
566
 
567
	   free(act);
4 andreas 568
	   return prev;
1 root 569
	}
2 andreas 570
 
571
	return NULL;
1 root 572
}
573
 
574
/*
4 andreas 575
 * Allocate the memory for the actual heizung plan.
576
 * This function appends an element to the end of the chain.
1 root 577
 */
578
HEIZINDEX *allocateMemory()
579
{
580
HEIZINDEX *act, *last;
581
 
582
	if (!HeizFirst)
583
	{
584
	   HeizFirst = malloc(sizeof(HEIZINDEX));
585
 
586
	   if (HeizFirst)
587
	   {
588
	      HeizFirst->heizung = malloc(sizeof(HEIZUNG));
589
	      HeizFirst->next = NULL;
590
	   }
591
	   else
592
	      return NULL;
593
 
594
	   return HeizFirst;
595
	}
596
	else
597
	{
598
	   // Find last element
599
	   last = HeizFirst;
600
 
601
	   while(last->next)
602
	      last = last->next;
603
 
604
	   act = malloc(sizeof(HEIZINDEX));
605
 
606
	   if (act)
607
	   {
608
	      act->heizung = malloc(sizeof(HEIZUNG));
609
	      act->next = NULL;
610
	      last->next = act;
611
	   }
612
	   else
613
	      return NULL;
614
 
615
	   return act;
616
	}
617
 
618
	return NULL;
619
}
620
 
621
/*
4 andreas 622
 * Allocate the memory for the actual heizung plan.
623
 * This function inserts an element into the chain.
624
 */
625
HEIZINDEX *insertMemory(HEIZINDEX *pos)
626
{
627
HEIZINDEX *act;
628
 
629
	if (!HeizFirst)
630
	{
631
	   HeizFirst = malloc(sizeof(HEIZINDEX));
632
 
633
	   if (HeizFirst)
634
	   {
635
	      HeizFirst->heizung = malloc(sizeof(HEIZUNG));
636
	      HeizFirst->next = NULL;
637
	   }
638
	   else
639
	      return NULL;
640
 
641
	   return HeizFirst;
642
	}
643
	else
644
	{
645
	   act = malloc(sizeof(HEIZINDEX));
646
 
647
	   if (act)
648
	   {
649
	      act->heizung = malloc(sizeof(HEIZUNG));
650
	      act->next = pos->next;
651
	      pos->next = act;
652
	   }
653
	   else
654
	      return NULL;
655
 
656
	   return act;
657
	}
658
 
659
	return NULL;
660
}
661
 
662
/*
1 root 663
 * The following functions read a config file and put the
664
 * contents into a structure.
665
 */
666
void readConf(void)
667
{
668
int fd;
669
char confFile[512], line[512];
670
char *home, *p;
671
char hv0[64], hv1[128];
672
 
673
	home = getenv("HOME");
674
	fd = -1;
675
 
676
	if (!access("/etc/heizung.conf",R_OK))
677
	   strcpy(confFile,"/etc/heizung.conf");
678
	else if (!access("/etc/heizung/heizung.conf",R_OK))
679
	   strcpy(confFile,"/etc/heizung/heizung.conf");
680
	else if (!access("/usr/etc/heizung.conf",R_OK))
681
	   strcpy(confFile,"/usr/etc/heizung.conf");
682
	else if (home)
683
	{
684
	   strcpy(confFile,home);
685
	   strcat(confFile,"/.heizung.conf");
686
 
687
	   if (access(confFile,R_OK))
4 andreas 688
	   {
689
	      syslog(LOG_WARNING,"Even config file %s was not found!", confFile);
1 root 690
	      confFile[0] = 0;
4 andreas 691
	   }
1 root 692
	}
693
	else
694
	   confFile[0] = 0;
695
 
696
        memset(&configs, 0, sizeof(configs));
4 andreas 697
        strcpy(configs.User,"nobody");
698
        strcpy(configs.Grp,"nobody");
699
        strcpy(configs.HeizPath, "/var/www/.HeizPlan.conf");
700
        configs.port = 11001;
1 root 701
 
4 andreas 702
	if (!confFile[0] || (fd = open(confFile,O_RDONLY)) == -1)
1 root 703
	{
4 andreas 704
	   if (confFile[0])
705
	      syslog(LOG_WARNING,"Error opening the config file %s! Using built in defaults. (%s)", confFile, strerror(errno));
706
	   else
707
	      syslog(LOG_WARNING,"Error opening the config file! Using built in defaults.");
708
 
1 root 709
	   return;
710
	}
711
 
4 andreas 712
	while (readLine(fd, &line[0], sizeof(line)) != NULL)
1 root 713
	{
714
	   int len;
715
 
716
	   trim (&line[0]);
717
 
4 andreas 718
	   if (line[0] == '#' || !strlen(line))
1 root 719
	      continue;
720
 
721
	   if ((p = strchr (line, '=')) == NULL)
722
	      continue;
723
 
724
	   *p = 0;
725
	   p++;
726
	   len = strlen(line);
727
 
728
	   if (len > sizeof(hv0))
729
	      len = sizeof(hv0) - 1;
730
 
731
	   strncpy (hv0, line, len);
4 andreas 732
	   hv0[len] = 0;
1 root 733
	   trim (hv0);
734
	   len = strlen(p);
735
 
736
	   if (len > sizeof(hv1))
737
	      len = sizeof(hv0) - 1;
738
 
739
	   strncpy (hv1, p, len);
4 andreas 740
	   hv1[len] = 0;
1 root 741
	   trim (hv1);
742
 
743
	   if (!strcasecmp(hv0, "user"))
4 andreas 744
	   {
745
	      syslog(LOG_INFO,"Found \"user\": %s", hv1);
1 root 746
	      strncpy (configs.User, hv1, sizeof(configs.User));
4 andreas 747
	   }
1 root 748
 
749
	   if (!strcasecmp(hv0, "group"))
4 andreas 750
	   {
751
	      syslog(LOG_INFO,"Found \"group\": %s", hv1);
1 root 752
	      strncpy (configs.Grp, hv1, sizeof(configs.Grp));
4 andreas 753
	   }
1 root 754
 
755
	   if (!strcasecmp(hv0, "port"))
4 andreas 756
	   {
757
	      syslog(LOG_INFO,"Found \"port\": %s", hv1);
1 root 758
	      configs.port = atoi (hv1);
4 andreas 759
	   }
1 root 760
 
761
	   if (!strcasecmp(hv0, "heizpath"))
4 andreas 762
	   {
763
	      syslog(LOG_INFO,"Found \"heizpath\": %s", hv1);
1 root 764
	      strncpy (configs.HeizPath, hv1, sizeof(configs.HeizPath));
4 andreas 765
	   }
1 root 766
	}
767
 
768
	close (fd);
769
}
770
 
771
int readHeizPlan(void)
772
{
773
int fd, i, wday;
774
ulong tim;
775
char line[512];
776
char *p, *xp;
777
char hv0[64], hv1[128];
778
float temperature;
779
long offset = 0;
4 andreas 780
HEIZINDEX *act, *prev;
1 root 781
 
782
	fd = -1;
783
 
4 andreas 784
	if (access(configs.HeizPath, R_OK))
785
	{
786
	   syslog(LOG_DAEMON,"Access to file %s denied: %s", configs.HeizPath, strerror(errno));
1 root 787
	   return 0;
4 andreas 788
	}
1 root 789
 
790
	if ((fd = open(configs.HeizPath, O_RDONLY)) == -1)
4 andreas 791
	{
792
	   syslog(LOG_DAEMON,"Error opening file %s: %s", configs.HeizPath, strerror(errno));
1 root 793
	   return 0;
4 andreas 794
	}
1 root 795
 
4 andreas 796
	act = prev = NULL;
797
	freeMemory();
798
 
799
	while (readLine(fd, &line[0], sizeof(line)) != NULL)
1 root 800
	{
801
	   int len;
802
 
803
	   trim (&line[0]);
804
 
805
	   if (line[0] == '#')
806
	      continue;
807
 
4 andreas 808
	   // We need a place to store the information
809
	   prev = act;
810
 
811
	   if ((act = allocateMemory()) == NULL)
812
	   {
813
	      close(fd);
814
	      syslog(LOG_DAEMON,"Error allocating memory for a temperature line! Stopped reading file %s.", configs.HeizPath);
815
	      return 0;
816
	   }
817
 
818
	   memset(act->heizung, 0, sizeof(HEIZUNG));
1 root 819
	   // Parse a line. The line has the format:
820
	   // <wday>,<end>,<temperature>
4 andreas 821
	   p = strtok(line, ",");
1 root 822
	   i = 1;
823
 
824
	   while(p)
825
	   {
826
	      switch(i)
827
	      {
828
		 case 1:	// Week day
829
		    wday = atoi(p);
830
 
831
		    if (wday < 1 || wday > 7)	// valid line?
832
		    {
4 andreas 833
		       if (prev)
834
			  wday = prev->heizung->wday;
1 root 835
 
4 andreas 836
		       if (wday < 1 || wday > 7)
837
		       {
838
			  p = strtok(NULL, ",");
839
			  i++;
840
			  continue;
841
		       }
1 root 842
		    }
843
 
844
		    act->heizung->wday = wday;
845
		    act->heizung->start = 0;
846
		 break;
847
 
848
		 case 2:	// start/end time
849
		    if ((xp = strchr(p, ':')) != NULL)
850
		    {
851
		    int hour, min;
852
 
853
		       hour = atoi(p);
854
		       min = atoi(xp+1);
855
 
856
		       if (hour >= 0 && hour <= 23 && min >= 0 && min <= 59)
857
		       {
4 andreas 858
			  act->heizung->end = hour * 3600 + (min + 1) * 60;
1 root 859
 
4 andreas 860
			  if (prev && prev->heizung->wday == act->heizung->wday)
861
			     act->heizung->start = prev->heizung->end;
1 root 862
		       }
863
		    }
864
		 break;
865
 
866
		 case 3:	// temperature
867
		    temperature = atof(p);
868
 
869
		    if (temperature < 5.0 || temperature > 30.0)
870
		    {
4 andreas 871
		       p = strtok(NULL,",");
872
		       i++;
1 root 873
		       continue;
874
		    }
875
 
876
		    act->heizung->temp = temperature;
877
		 break;
878
	      }
879
 
4 andreas 880
	      p = strtok(NULL, ",");
881
	      i++;
1 root 882
	   }
883
	}
884
 
885
	close (fd);
886
	return 1;
887
}
888
 
889
/*
890
 * write the (may be) altered plan.
891
 * This function allways writes whole plan.
892
 */
893
int writeHeizPlan()
894
{
895
int fd;
896
char hv0[512];
897
HEIZINDEX *act;
898
 
899
	fd = -1;
900
 
901
	if (!access(configs.HeizPath, R_OK))
902
	   return 0;
903
 
904
	if ((fd = open(configs.HeizPath, O_RDWR | O_TRUNC)) == -1)
905
	   return 0;
906
 
907
	act = HeizFirst;
908
 
909
	while(act)
910
	{
4 andreas 911
	   sprintf(&hv0[0], "%d,%lu,%f\n",
1 root 912
		   act->heizung->wday, act->heizung->end,
913
		   act->heizung->temp);
914
	   write(fd, &hv0[0], strlen(hv0));
915
	   act = act->next;
916
	}
917
 
918
	close(fd);
919
	return 1;
920
}
921
 
4 andreas 922
char *readLine(int fd, char *buf, int bufLen)
1 root 923
{
4 andreas 924
int i, end;
1 root 925
char ch, *p;
926
 
927
        if (fd <= 0)
4 andreas 928
	{
929
	   syslog(LOG_DAEMON,"Function readLine was called with an invalid file descriptor of %d!", fd);
930
           return NULL;
931
	}
1 root 932
 
4 andreas 933
        i = end = 0;
934
        p = buf;
1 root 935
 
4 andreas 936
        while (read(fd, &ch, 1) > 0)
937
        {
938
           end = 1;
1 root 939
 
4 andreas 940
           if (ch == 0x0a)
941
           {
942
             *p = 0;
943
             return buf;
944
           }
1 root 945
 
4 andreas 946
           if (ch == 0x0d)      // ignore this!
947
              continue;
1 root 948
 
4 andreas 949
           if (i < (bufLen - 1))
950
           {
951
              *p = ch;
952
              p++;
953
              i++;
954
           }
955
        }
1 root 956
 
4 andreas 957
        *p = 0;
958
 
959
        if (end)
960
           return buf;
961
        else
962
           return NULL;
1 root 963
}
964
 
965
char *trim(char *str)
966
{
967
char *p1, *p2, *p;
968
 
969
	if (!str)
970
	   return NULL;
971
 
4 andreas 972
	if (!strlen(str))
973
	   return str;
974
 
1 root 975
	p = str;
976
	p1 = p2 = NULL;
977
 
978
	while (*p)
979
	{
980
	   if (!p1 && *p != ' ')
981
	   {
982
	      p1 = p;
983
	      break;
984
	   }
985
 
986
	   p++;
987
	}
988
 
989
	p2 = str + (strlen(str) - 1);
990
 
991
	while (p2 > str && *p2 == ' ')
992
	   p2--;
993
 
994
	if (p2)
995
	   *(p2+1) = 0;
996
 
997
	if (p1)
998
	{
999
	   char *buf = strdup (p1);
1000
	   strcpy (str, buf);
1001
	   free (buf);
1002
	}
1003
 
1004
	return str;
1005
}
2 andreas 1006
 
1007
char *remove_string(char *str, char *search, char *ret)
1008
{
1009
char *p;
1010
 
1011
	if (!strlen(str) || !strlen(search))
1012
	   return NULL;
1013
 
1014
	if ((p = strstr(str, search)) != NULL)
1015
	{
1016
	int len = strlen(search);
1017
 
4 andreas 1018
	   strncpy(ret, str, p - str + len);
2 andreas 1019
	   memmove(str, p + len + 1, strlen(p+len));
1020
	   return ret;
1021
	}
1022
 
1023
	return NULL;
4 andreas 1024
}