Subversion Repositories heizung

Rev

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

Rev Author Line No. Line
1 root 1
/*
5 andreas 2
 * (C) Copyright 2010, 2011 by Andreas Theofilu <andreas@theosys.at>
1 root 3
 * All rights reserved!
4
 */
5
 
6
#include <stdio.h>
7
#include <string.h>
8
#include <unistd.h>
9
#include <stdlib.h>
9 andreas 10
#include <libgen.h>
1 root 11
#include <math.h>
12
#include <time.h>
13
#include <signal.h>
14
#include <syslog.h>
15
#include <errno.h>
16
#include <pthread.h>
17
#include <sys/stat.h>
18
#include <sys/types.h>
19
#include <sys/socket.h>
20
#include <fcntl.h>
21
#include <netdb.h>
9 andreas 22
#include <dirent.h>
1 root 23
#include <netinet/in.h>
24
#include <sys/param.h>
25
#include <sys/ioctl.h>
26
#include <pwd.h>
27
#include <grp.h>
5 andreas 28
#include "sensor.h"
29
#include "usb_comm.h"
30
#include "heizung.h"
1 root 31
 
32
typedef struct
33
{
34
      int wday;
35
      ulong start;
36
      ulong end;
37
      float temp;
38
}HEIZUNG;
39
 
40
typedef struct HEIZINDEX
41
{
42
      HEIZUNG *heizung;
4 andreas 43
      struct HEIZINDEX *next;
1 root 44
}HEIZINDEX;
45
 
9 andreas 46
struct SOCKETS
47
{
48
      int sockfd;
49
      int newfd;
50
};
51
 
1 root 52
CONFIGURE configs;
53
HEIZINDEX *HeizFirst;
54
float ActTemperature;
55
float ActPressure;
56
 
9 andreas 57
static pthread_t pthr_pars, pthr_temp_pars, pthr_process;
1 root 58
 
59
// Prototypes
60
void daemon_start(int ignsigcld);
5 andreas 61
void *pthr_temperature(void *pV_data);
1 root 62
void *pthr_parser(void *pV_data);
63
void sig_child(void);
9 andreas 64
void sendList(int s1);
65
int listSchemas(int s1);
1 root 66
int parseCommand(int s1, char *cmd);
9 andreas 67
void *processCommands(void *pV_data);
4 andreas 68
void changeToUser(char *, char *);
1 root 69
 
70
HEIZINDEX *allocateMemory(void);
4 andreas 71
HEIZINDEX *insertMemory(HEIZINDEX *pos);
1 root 72
void freeMemory(void);
4 andreas 73
HEIZINDEX *freeChainMember(HEIZINDEX *member);
74
void freeDay(int wday);
75
void insertMember(int wday, long endt, float temp);
9 andreas 76
char *makeFileName(char *ret, char *fname, int len);
1 root 77
int readHeizPlan(void);
9 andreas 78
int readHeizPlanName(char *fname);
1 root 79
int writeHeizPlan(void);
9 andreas 80
int writeHeizPlanName(char *fname);
1 root 81
void readConf(void);
82
 
10 andreas 83
HEIZINDEX *allocMem(HEIZINDEX *first);
84
int sortTable(void);
85
 
4 andreas 86
char *readLine(int fd, char *buf, int bufLen);
1 root 87
char *trim(char *str);
2 andreas 88
char *remove_string(char *str, char *search, char *ret);
1 root 89
 
10 andreas 90
//static pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
5 andreas 91
static pthread_mutex_t fastmutex_ser = PTHREAD_MUTEX_INITIALIZER;
9 andreas 92
static pthread_mutex_t fastmutex_proc = PTHREAD_MUTEX_INITIALIZER;
1 root 93
 
94
/*
95
 * The main program, initializing everything and start the daemon.
96
 */
97
int main(int argc, char *argv[])
98
{
99
int fd, index;
100
 
101
	HeizFirst = NULL;
102
	readConf();
5 andreas 103
	// Initialize USB
104
	serialDev.fd = -1;
105
	serialDev.switch_fd = -1;
106
	serialDev.handle = NULL;
1 root 107
	// Now daemonize this application
108
	daemon_start(0);
4 andreas 109
	changeToUser(&configs.User[0], &configs.Grp[0]);
1 root 110
	// Now start our Thread
111
	if (pthread_create(&pthr_pars, NULL, pthr_parser, (void *)0) != 0)
112
	{
113
	   syslog (LOG_DAEMON,"Create of thread \"pthr_parser\" failed!");
114
	   return 1;
115
	}
116
 
5 andreas 117
	// Here we start another thread to read the temperature
118
	if (pthread_create(&pthr_temp_pars, NULL, pthr_temperature, (void *)0) != 0)
119
	{
120
	   syslog(LOG_DAEMON,"Create of thread \"pthr_temperature\" failed!");
121
	   pthread_cancel(pthr_pars);
122
	   return 1;
123
	}
124
 
1 root 125
	while (1)
126
	   sleep(3600);
127
 
5 andreas 128
	pthread_exit(NULL);
1 root 129
	return 0;
130
}
131
 
132
/*
133
 * Detach application from console and make it a daemon.
134
 */
135
void daemon_start (int ignsigcld)
136
{
137
int childpid, fd;
10 andreas 138
char hv0[64];
1 root 139
 
140
        if (getpid () == 1)
141
           goto out;
142
 
143
#ifdef SIGTTOU
144
        signal (SIGTTOU, SIG_IGN);
145
#endif
146
#ifdef SIGTTIN
147
        signal (SIGTTIN, SIG_IGN);
148
#endif
149
#ifdef SIGTSTP
150
        signal (SIGTSTP, SIG_IGN);
151
#endif
152
 
153
        if ((childpid = fork ()) < 0)
154
           fprintf (stderr, "Can't fork this child\n");
155
        else if (childpid > 0)
156
           exit (0);
157
 
158
        if (setpgrp () == -1)
159
           fprintf (stderr, "Can't change process group\n");
160
 
161
        signal (SIGHUP, SIG_IGN);
162
 
163
        if ((childpid = fork ()) < 0)
164
           syslog (LOG_DAEMON, "Can't fork second child");
165
        else if (childpid > 0)
166
           exit (0);            /* first child */
167
 
168
        /* second child */
169
out:
170
        for (fd = 0; fd < NOFILE; fd++)
171
           close (fd);
172
 
173
        errno = 0;
174
        chdir ("/");
175
        umask (0);
176
 
177
        if (ignsigcld)
178
        {
179
//#ifdef SIGTSTP
180
//           signal (SIGCLD, sig_child);
181
//#else
182
           signal (SIGCLD, SIG_IGN);
183
//#endif
184
        }
10 andreas 185
 
186
	// Create PID file
187
	if ((fd = open(configs.Pidfile, O_RDWR | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
188
	{
189
	   syslog(LOG_WARNING,"Can't create PID file %s: %s",configs.Pidfile, strerror(errno));
190
	   return;
191
	}
192
 
193
	sprintf(&hv0[0],"%d", getpid());
194
	write(fd, hv0, strlen(hv0));
195
	close(fd);
1 root 196
}
197
 
198
void sig_child ()
199
{
200
#if defined(BSD) && !defined(sinix) && !defined(Linux)
201
int pid;
202
union wait status;
203
 
204
        while ((pid = wait3 (&status, WNOHANG, (struct rusage *)0)) > 0)
205
                ;
206
#endif
207
}
208
 
209
void changeToUser(char *usr, char *grp)
210
{
211
gid_t gr_gid;
212
 
213
	if (usr && strlen(usr))
214
	{
215
	   /* get uid */
216
	   struct passwd *userpwd;
217
	   struct group *usergrp;
218
 
219
	   if ((userpwd = getpwnam(usr)) == NULL)
220
	   {
221
	      syslog(LOG_DAEMON,"no such user: %s", usr);
222
	      exit(EXIT_FAILURE);
223
	   }
224
 
225
	   if (!grp || strlen(grp) || (usergrp = getgrnam(grp)) == NULL)
226
	   {
227
	      if (grp && strlen(grp))
228
	         syslog(LOG_WARNING,"no such group: %s", grp);
229
 
230
	      gr_gid = userpwd->pw_gid;
231
	   }
232
	   else
233
	      gr_gid = usergrp->gr_gid;
234
 
235
	   if (setgid(gr_gid) == -1)
236
	   {
237
	      syslog(LOG_DAEMON,"cannot setgid of user %s: %s", usr, strerror(errno));
238
	      exit(EXIT_FAILURE);
239
	   }
240
 
241
#ifdef _BSD_SOURCE
242
	   /* init suplementary groups
243
	    * (must be done before we change our uid)
244
	    */
245
	   if (initgroups(usr, gr_gid) == -1)
246
	      syslog(LOG_DAEMON,"cannot init suplementary groups of user %s: %s", usr, strerror(errno));
247
#endif
248
 
249
	   /* set uid */
250
	   if (setuid(userpwd->pw_uid) == -1)
251
	   {
252
	      syslog(LOG_DAEMON,"cannot change to uid of user %s: %s\n", usr, strerror(errno));
253
	      exit(EXIT_FAILURE);
254
	   }
255
 
256
	   if(userpwd->pw_dir)
257
	      setenv("HOME", userpwd->pw_dir, 1);
258
        }
259
}
260
 
5 andreas 261
void *pthr_temperature(void *pV_data)
262
{
263
time_t t, tstart;
264
struct tm *zeit, sz;
265
int sleep_sec;
266
 
267
	// Initialize the serial port.
268
	serial_set_method((strlen(configs.Device)) ? 1 : 0, configs.VID, configs.PID);
269
 
270
	if (strlen(configs.Device))
271
	   serial_set_device(configs.Device);
272
 
273
	if (!serial_open())
274
	   return NULL;
275
 
276
	if (serialDev.switch_fd == -1)
277
	{
278
	   if (!serial_open())
279
	      return NULL;
280
	}
281
 
282
	pthread_mutex_lock (&fastmutex_ser);
8 andreas 283
	sleep(1);	// Give the other thread time to initialize the structure
5 andreas 284
 
285
	while(1)
286
	{
287
	   HEIZINDEX *act;
288
 
8 andreas 289
	   GetTemp();
5 andreas 290
	   sleep_sec = 300;
291
 
292
	   // Compare the actual temperature with the one that should be
293
	   // and switch heating on or off
294
	   if (HeizFirst)
295
	   {
296
	      int wday;
297
	      unsigned long loctm;
298
 
299
	      t = time (NULL);
300
	      sleep_sec = 300 - (int)((t + 300L) % 300L);
301
	      sleep_sec++;
302
	      zeit = localtime (&t);
303
 
304
	      wday = (zeit->tm_wday == 0) ? 7 : zeit->tm_wday;
305
	      memset (&sz, 0, sizeof (struct tm));
306
	      sz.tm_min = 0;
307
	      sz.tm_hour = 0;
308
	      sz.tm_mon = zeit->tm_mon;
309
	      sz.tm_mday = zeit->tm_mday;
310
	      sz.tm_year = zeit->tm_year;
311
	      sz.tm_isdst = zeit->tm_isdst;
312
	      tstart = mktime(&sz);
9 andreas 313
	      loctm = (t - tstart) + 1;	// Seconds since midnight
5 andreas 314
	      act = HeizFirst;
7 andreas 315
 
5 andreas 316
	      while(act)
317
	      {
318
		 if (act->heizung->wday == wday && loctm >= act->heizung->start && loctm <= act->heizung->end)
319
		 {
320
		    if (ActTemperature == 9999.0)
321
		       SwitchOff();		// No temperature, no heating
322
		    else if (ActTemperature < 5.0)
323
		       SwitchOn();		// Make sure it will not freeze
324
		    else if (ActTemperature > 30.0)
325
		       SwitchOff();		// Don't over heat
326
		    else if (ActTemperature <= (act->heizung->temp - 0.5))
327
		       SwitchOn();
328
		    else if (ActTemperature > act->heizung->temp)
329
		       SwitchOff();
330
		 }
331
 
332
		 act = act->next;
333
	      }
334
	   }
335
	   else
336
	      syslog(LOG_INFO,"Structure not initialized!");
337
 
338
	   sleep(sleep_sec);		// Wait 5 Minutes
339
	}
340
 
341
	pthread_mutex_unlock(&fastmutex_ser);
342
}
343
 
9 andreas 344
void *processCommands(void *pV_data)
1 root 345
{
9 andreas 346
char ch, buf[128];
347
int i, s1, s;
348
struct SOCKETS *soc;
349
 
350
	soc = (struct SOCKETS *)pV_data;
351
	s1 = soc->newfd;
352
	s = soc->sockfd;
353
	memset(&buf[0], 0, sizeof(buf));
354
	i = 0;
355
 
356
	while (read(s1,&ch,1) > 0)
357
	{
358
	   if (i < (sizeof(buf) - 1))
359
	   {
360
	      buf[i] = ch;
361
 
362
	      if (ch == ';' || ch == 0x0d)
363
	      {
364
	      int pstat;
365
 
366
		 pthread_mutex_lock (&fastmutex_proc);
367
 
368
		 if (!strncmp(buf, "quit", 4))
369
		    break;
370
 
371
		 if ((pstat = parseCommand(s1,buf)) == 0)
372
		 {
373
		 char hv0[128];
374
 
375
		    sprintf(&hv0[0],"INVALID COMMAND: %s;",buf);
376
		    write(s1,hv0,strlen(hv0));
377
		 }
378
		 else if (pstat == 2)
379
		    write(s1, "NAK;", 4);
380
		 else
381
		    write(s1,"OK;",3);
382
 
383
		 memset(&buf[0], 0, sizeof(buf));
384
		 i = 0;
385
		 pthread_mutex_unlock(&fastmutex_proc);
386
		 continue;
387
	      }
388
	   }
389
 
390
	   i++;
391
	}
392
 
393
	close(s1);
394
}
395
 
396
void *pthr_parser(void *pV_data)
397
{
398
char ch, str[INET_ADDRSTRLEN];
1 root 399
// socket structure
400
struct sockaddr_in client1, server1;
401
struct servent *serviceInfo;
9 andreas 402
int s1, s;
1 root 403
socklen_t length;
9 andreas 404
struct SOCKETS soc;
1 root 405
 
406
	// socket server
407
	if (configs.port > 0)
408
	   server1.sin_port = htons(configs.port);
409
	else if ((serviceInfo = getservbyname ("heizung", "tcp")))
410
	   server1.sin_port = serviceInfo->s_port;
411
	else
412
	{
413
	   syslog(LOG_DAEMON,"Error: No TCP port defined!");
414
	   exit(EXIT_FAILURE);
415
	}
416
 
417
	server1.sin_family = AF_INET;
418
	server1.sin_addr.s_addr = INADDR_ANY;
419
	s = socket(AF_INET,SOCK_STREAM,0);
420
 
421
	if (s < 0)
7 andreas 422
	{
423
	   syslog (LOG_DAEMON, "Error in socket: %s",strerror(errno));
424
	   exit(EXIT_FAILURE);
425
	}
1 root 426
 
427
	if (bind (s, (struct sockaddr *)&server1, sizeof (server1)) < 0)
7 andreas 428
	{
429
	   syslog (LOG_DAEMON, "Error in bind: %s", strerror(errno));
430
	   exit(EXIT_FAILURE);
431
	}
1 root 432
 
433
	if (listen (s, 5) < 0)
7 andreas 434
	{
435
	   syslog (LOG_DAEMON, "Error in listen: %s", strerror(errno));
436
	   exit(EXIT_FAILURE);
437
	}
1 root 438
 
439
	length = sizeof(client1);
440
        syslog (LOG_DEBUG, "Server ready: %d",s);
441
 
442
	while (1)
443
	{
10 andreas 444
//	   pthread_mutex_lock (&fastmutex);
1 root 445
	   // Read time table at every loop, to be sure to have the latest
446
	   // version (User may change it at every time)
447
	   if (!readHeizPlan())
448
	   {
449
	      if (!HeizFirst)
450
	      {
9 andreas 451
		 syslog(LOG_DAEMON, "Error reading table %s with plan!", configs.HeizPath);
452
		 exit(EXIT_FAILURE);
1 root 453
	      }
454
	      else
455
		 syslog(LOG_DAEMON, "Error reading table with plan! Will work with old one.");
456
	   }
457
 
10 andreas 458
//	   pthread_mutex_unlock(&fastmutex);
9 andreas 459
 
1 root 460
	   if ((s1 = accept (s, (struct sockaddr *)&client1, &length)) < 0)
9 andreas 461
	   {
7 andreas 462
	      syslog (LOG_DAEMON, "Error in accept: %d: %s", s1, strerror(errno));
9 andreas 463
	      continue;
464
	   }
1 root 465
 
7 andreas 466
	   inet_ntop(AF_INET, &(client1.sin_addr), str, INET_ADDRSTRLEN);
467
	   syslog (LOG_INFO, "Connected to client %s", str);
9 andreas 468
	   soc.sockfd = s;
469
	   soc.newfd = s1;
1 root 470
 
9 andreas 471
	   if (pthread_create(&pthr_process, NULL, processCommands, (void *)&soc) != 0)
1 root 472
	   {
9 andreas 473
	      syslog (LOG_DAEMON,"Create of thread \"pthr_parser\" failed!");
474
	      close(s1);
475
	   }
476
	}
1 root 477
 
9 andreas 478
	close (s);
479
	serial_close();
480
	return NULL;
481
}
1 root 482
 
9 andreas 483
void sendList(int s1)
484
{
485
char hv0[256];
486
int i, wday = 1;
487
HEIZINDEX *act;
1 root 488
 
9 andreas 489
	// We will write out the week days in the correct order.
490
	// So we need 2 loops. The first one is runnung for every week day
491
	// and the 2nd one will find every entry for the actual week day.
492
	while (wday <= 7)
493
	{
494
	   act = HeizFirst;
495
	   i = 1;		// The line counter --> reset it to 1 for every week day
1 root 496
 
9 andreas 497
	   while (act)
498
	   {
499
	      if (act->heizung->wday == wday)
500
	      {
501
		 sprintf(&hv0[0], "LINE:%d:%d:%lu:%lu:%.1f;", i, act->heizung->wday,
502
			act->heizung->start, act->heizung->end, act->heizung->temp);
503
		 write(s1, &hv0[0], strlen(hv0));
504
		 i++;
1 root 505
	      }
506
 
9 andreas 507
	      act = act->next;
1 root 508
	   }
509
 
9 andreas 510
	   wday++;
1 root 511
	}
9 andreas 512
}
1 root 513
 
9 andreas 514
int listSchemas(int s1)
515
{
516
char hv0[256];
517
DIR *dir;	
518
struct dirent *de;
519
char *ldup, *lp;
520
 
521
	if ((ldup = strdup(configs.HeizPath)) == NULL)
522
	{
523
	   syslog(LOG_DAEMON, "Not enough memory for path: %s", strerror(errno));
524
	   return 2;
525
	}
526
 
527
	lp = dirname(ldup);
528
 
529
	if ((dir = opendir(lp)) == NULL)
530
	{
531
	   syslog(LOG_DAEMON, "Could not open directory %s: %s", lp, strerror(errno));
532
	   free(ldup);
533
	   return 2;
534
	}
535
 
536
	strcpy(&hv0[0], "SCHEMA START;");
537
	write(s1, hv0, strlen(hv0));
538
 
539
	while ((de = readdir(dir)) != NULL)
540
	{
541
	   if (de->d_type == DT_REG && strstr(de->d_name, ".heat") != NULL)
542
	   {
543
	   char dn[256], *p;
544
 
545
	      memset(&dn[0], 0, sizeof(dn));
546
	      strncpy(dn, de->d_name, sizeof(dn)-1);
547
 
548
	      if ((p = strrchr(dn, '.')) != NULL)
549
		 *p = 0;
550
	      else
551
		 continue;
552
 
553
	      sprintf(&hv0[0], "SCHEMA FILE:%s;", dn);
554
	      write(s1, hv0, strlen(hv0));
555
	   }
556
	}
557
 
558
	closedir(dir);
559
	free(ldup);
560
	return 1;
1 root 561
}
562
 
563
int parseCommand(int s1, char *cmd)
564
{
4 andreas 565
char bef[32],par[1024], *p;
566
char hv0[256];
1 root 567
int i,j;
4 andreas 568
HEIZINDEX *act, *last;
1 root 569
 
570
	memset(bef,0,sizeof(bef));
571
	memset(par,0,sizeof(par));
572
 
573
	if ((p = strchr(cmd,':')) != NULL)		// do we have a parameter?
574
	{
4 andreas 575
	   strncpy(bef,cmd,p - cmd);
9 andreas 576
	   strncpy(par,p+1,strlen(p)-2);	// Cut off the trailing semi colon
1 root 577
	}
578
	else
579
	   strncpy(bef,cmd,strlen(cmd)-1);
5 andreas 580
 
4 andreas 581
	if (!strcasecmp(bef, "LIST"))		// Write out current list
9 andreas 582
	   sendList(s1);
1 root 583
 
4 andreas 584
	if (!strcasecmp(bef, "GET WDAY"))		// Write out a particular week day
1 root 585
	{
4 andreas 586
	int wday = atoi(par);
1 root 587
 
588
	   if (wday < 1 || wday > 7)
589
	   {
590
	      strcpy(&hv0[0], "ERROR:Invalid week day");
591
	      write(s1, &hv0[0], strlen(hv0));
592
	      return 0;
593
	   }
594
 
595
	   act = HeizFirst;
596
 
597
	   while (act && act->heizung->wday != wday)
598
	      act = act->next;
599
 
600
	   if (!act)
601
	   {
602
	      sprintf(&hv0[0], "ERROR:No plan for week day %d", wday);
603
	      write(s1, &hv0[0], strlen(hv0));
604
	      return 0;
605
	   }
606
 
607
	   i = 1;
608
 
609
	   while (act && act->heizung->wday == wday)
610
	   {
5 andreas 611
	      sprintf(&hv0[0], "LINE:%d:%d:%lu:%lu:%.1f;", i, act->heizung->wday,
1 root 612
		      act->heizung->start, act->heizung->end, act->heizung->temp);
613
	      write(s1, &hv0[0], strlen(hv0));
614
	      i++;
615
	      act = act->next;
616
	   }
617
	}
618
 
4 andreas 619
	if (!strcasecmp(bef, "GET TEMP"))	// Return actual temperature
1 root 620
	{
5 andreas 621
	   sprintf(&hv0[0], "TEMP:%.1f;", ActTemperature);
1 root 622
	   write(s1, &hv0[0], strlen(hv0));
623
	}
624
 
4 andreas 625
	if (!strcasecmp(bef, "GET PRESSURE"))	// Return the actual air pressure
1 root 626
	{
7 andreas 627
	   sprintf(&hv0[0], "PRESSURE:%.1f;", ActPressure);
1 root 628
	   write(s1, &hv0[0], strlen(hv0));
629
	}
630
 
8 andreas 631
        if (!strcasecmp(bef, "HEATSTAT"))	// Return the status of the heating
632
        {
633
	   sprintf(&hv0[0], "HEATSTAT:%d;", HeatStatus);
634
	   write(s1, &hv0[0], strlen(hv0));
635
	}
636
 
2 andreas 637
	// SET DAY:<count>:<day>:<end1>:<temp>[:<end2>:<temp>[:...]];
638
	// <count>   number of entries following
639
	// <day>     The day of the week
640
	// <end1>    The end time
641
	// <temp>    The temperature wanted until end time is reached
642
	//
4 andreas 643
	if (!strcasecmp(bef, "SET DAY"))		// Set the plan for a particular day
1 root 644
	{
2 andreas 645
	int count, wday, i;
646
	long endt;
647
	float temp;
648
 
4 andreas 649
	   count = atoi(par);
650
	   remove_string(par, ":", &hv0[0]);
651
	   wday = atoi(par);
652
	   freeDay(wday);
653
	   last = NULL;
2 andreas 654
 
655
	   if (count > 0)
656
	   {
657
	      for (i = 0; i < count; i++)
658
	      {
4 andreas 659
		 remove_string(par, ":", &hv0[0]);
660
		 endt = atol(par);
661
		 remove_string(par, ":", &hv0[0]);
662
		 temp = atof(par);
2 andreas 663
 
4 andreas 664
		 if ((act = allocateMemory()) == NULL)
665
		 {
666
		    syslog(LOG_DAEMON,"Error allocating memory for a temperature line.");
667
		    sprintf(&hv0[0], "ERROR:Not enough memory!");
668
		    write(s1, &hv0[0], strlen(hv0));
9 andreas 669
		    return 2;
4 andreas 670
		 }
2 andreas 671
 
4 andreas 672
		 act->heizung->wday = wday;
673
		 act->heizung->end = endt;
674
		 act->heizung->temp = temp;
675
 
676
		 if (last)
5 andreas 677
		    act->heizung->start = last->heizung->end;
4 andreas 678
		 else
679
		    act->heizung->start = 0L;
680
 
681
		 last = act;
2 andreas 682
	      }
5 andreas 683
 
684
	      writeHeizPlan();
2 andreas 685
	   }
1 root 686
	}
687
 
2 andreas 688
	// SET TEMP:<wday>:<end>:<temp>;
5 andreas 689
	if (!strcasecmp(bef, "SET TEMP"))	// Set the temperature for a particular day and line
1 root 690
	{
4 andreas 691
	int wday;
692
	unsigned long endt;
1 root 693
	float tmp;
694
 
4 andreas 695
	   wday = atoi(par);
696
	   remove_string(par, ":", &hv0[0]);
697
	   endt = atol(par);
698
	   remove_string(par, ":", &hv0[0]);
699
	   tmp = atof(par);
700
	   insertMember(wday, endt, tmp);
5 andreas 701
	   writeHeizPlan();
1 root 702
	}
703
 
9 andreas 704
	// SAVE SCHEMA:<name>;
705
	if (!strcasecmp(bef, "SAVE SCHEMA"))	// Save the current heating plan into a file
706
        {
707
	   sprintf(&hv0[0], "%s.heat", par);
708
 
709
	   if (!writeHeizPlanName(hv0))
710
	      return 2;
711
	}
712
 
713
	// LOAD SCHEMA:<name>;
714
	if (!strcasecmp(bef, "LOAD SCHEMA"))	// Load a previous saved schema from a file
715
	{
716
	   sprintf(&hv0[0], "%s.heat", par);
717
 
718
	   if (!readHeizPlanName(hv0))
719
	      return 2;
720
 
721
	   // write the new schema immediately to the default file
722
	   writeHeizPlan();
723
	   sendList(s1);
724
	}
725
 
726
	// DELETE SCHEMA:<name>;
727
	if (!strcasecmp(bef, "DELETE SCHEMA"))	// Delete an existing schema
728
        {
729
	   makeFileName(&hv0[0], par, sizeof(hv0));
730
 
731
	   if (strlen(hv0) < (sizeof(hv0) - 6))
732
	      strcat(&hv0[0], ".heat");
733
	   else
734
	   {
735
	      syslog(LOG_DAEMON, "File name too large for internal buffer");
736
	      return 2;
737
	   }
738
 
739
	   if (access(hv0, R_OK | W_OK))
740
	   {
741
	      syslog(LOG_DAEMON,"No access to file %s: %s", hv0, strerror(errno));
742
	      return 2;
743
	   }
744
 
745
	   if (unlink(hv0) == -1)
746
	   {
747
	      syslog(LOG_DAEMON,"Error deleting file %s: %s", hv0, strerror(errno));
748
	      return 2;
749
	   }
750
 
751
	   return listSchemas(s1);
752
	}
753
 
754
	// LIST SCHEMA;
755
	if (!strcasecmp(bef, "LIST SCHEMA"))	// Return a list of all available schamas
756
	   return listSchemas(s1);
757
 
1 root 758
	return 1;
759
}
760
 
761
/*
2 andreas 762
 * Remove a complete day
763
 */
764
void freeDay(int wday)
765
{
766
HEIZINDEX *act, *next, *prev;
767
 
768
	act = HeizFirst;
769
	prev = NULL;
770
 
771
	while(act)
772
	{
773
	   if (act->heizung->wday == wday)
774
	      act = freeChainMember(act);
775
 
776
	   act = act->next;
777
	}  
778
}
779
 
780
/*
781
 * Insert a new entry
782
 */
783
void insertMember(int wday, long endt, float temp)
784
{
785
HEIZINDEX *act;
786
 
787
	act = HeizFirst;
788
 
789
	while(act)
790
	{
791
	   if (act->heizung->wday == wday && act->heizung->end == endt)
792
	   {
793
	      act->heizung->temp = temp;
794
	      return;
795
	   }
796
 
797
	   act = act->next;
798
	}
799
 
800
	if ((act = allocateMemory()) != NULL)
801
	{
802
	   act->heizung->wday = wday;
803
	   act->heizung->end = endt;
804
	   act->heizung->temp = temp;
805
	}
806
}
807
 
808
/*
1 root 809
 * Free the memory for the actual heizung plan.
810
 */
811
void freeMemory()
812
{
813
HEIZINDEX *act, *next;
814
 
815
	act = HeizFirst;
816
 
817
	while(act)
818
	{
819
	   if (act->heizung)
820
	   {
821
	      free(act->heizung);
822
	      act->heizung = NULL;
823
	   }
824
 
825
	   next = act->next;
826
	   free(act);
827
	   act = next;
828
	}
5 andreas 829
 
830
	HeizFirst = NULL;
1 root 831
}
832
 
833
/*
834
 * Free only one entry in the chain
835
 */
2 andreas 836
HEIZINDEX *freeChainMember(HEIZINDEX *member)
1 root 837
{
838
HEIZINDEX *act,*prev;
839
 
840
	act = HeizFirst;
841
	prev = NULL;
842
 
843
	while(act != member)
844
	{
845
	   prev = act;
846
	   act = act->next;
847
	}
848
 
849
	if (act == member)
850
	{
851
	   if (prev)
2 andreas 852
	      prev->next = act->next;
4 andreas 853
	   else
854
	   {
855
	      prev = act->next;
1 root 856
 
4 andreas 857
	      if (act == HeizFirst)
858
		 HeizFirst = act->next;
859
	   }
860
 
1 root 861
	   if (act->heizung)
862
	      free(act->heizung);
863
 
864
	   free(act);
4 andreas 865
	   return prev;
1 root 866
	}
2 andreas 867
 
868
	return NULL;
1 root 869
}
870
 
871
/*
4 andreas 872
 * Allocate the memory for the actual heizung plan.
873
 * This function appends an element to the end of the chain.
1 root 874
 */
875
HEIZINDEX *allocateMemory()
876
{
877
HEIZINDEX *act, *last;
878
 
879
	if (!HeizFirst)
880
	{
881
	   HeizFirst = malloc(sizeof(HEIZINDEX));
882
 
883
	   if (HeizFirst)
884
	   {
885
	      HeizFirst->heizung = malloc(sizeof(HEIZUNG));
886
	      HeizFirst->next = NULL;
887
	   }
888
	   else
889
	      return NULL;
890
 
891
	   return HeizFirst;
892
	}
893
	else
894
	{
895
	   // Find last element
896
	   last = HeizFirst;
897
 
898
	   while(last->next)
899
	      last = last->next;
900
 
901
	   act = malloc(sizeof(HEIZINDEX));
902
 
903
	   if (act)
904
	   {
905
	      act->heizung = malloc(sizeof(HEIZUNG));
906
	      act->next = NULL;
907
	      last->next = act;
908
	   }
909
	   else
910
	      return NULL;
911
 
912
	   return act;
913
	}
914
 
915
	return NULL;
916
}
917
 
918
/*
4 andreas 919
 * Allocate the memory for the actual heizung plan.
920
 * This function inserts an element into the chain.
921
 */
922
HEIZINDEX *insertMemory(HEIZINDEX *pos)
923
{
924
HEIZINDEX *act;
925
 
926
	if (!HeizFirst)
927
	{
928
	   HeizFirst = malloc(sizeof(HEIZINDEX));
929
 
930
	   if (HeizFirst)
931
	   {
932
	      HeizFirst->heizung = malloc(sizeof(HEIZUNG));
933
	      HeizFirst->next = NULL;
934
	   }
935
	   else
936
	      return NULL;
937
 
938
	   return HeizFirst;
939
	}
940
	else
941
	{
942
	   act = malloc(sizeof(HEIZINDEX));
943
 
944
	   if (act)
945
	   {
946
	      act->heizung = malloc(sizeof(HEIZUNG));
947
	      act->next = pos->next;
948
	      pos->next = act;
949
	   }
950
	   else
951
	      return NULL;
952
 
953
	   return act;
954
	}
955
 
956
	return NULL;
957
}
958
 
959
/*
1 root 960
 * The following functions read a config file and put the
961
 * contents into a structure.
962
 */
963
void readConf(void)
964
{
965
int fd;
966
char confFile[512], line[512];
967
char *home, *p;
968
char hv0[64], hv1[128];
969
 
970
	home = getenv("HOME");
971
	fd = -1;
972
 
973
	if (!access("/etc/heizung.conf",R_OK))
974
	   strcpy(confFile,"/etc/heizung.conf");
975
	else if (!access("/etc/heizung/heizung.conf",R_OK))
976
	   strcpy(confFile,"/etc/heizung/heizung.conf");
977
	else if (!access("/usr/etc/heizung.conf",R_OK))
978
	   strcpy(confFile,"/usr/etc/heizung.conf");
979
	else if (home)
980
	{
981
	   strcpy(confFile,home);
982
	   strcat(confFile,"/.heizung.conf");
983
 
984
	   if (access(confFile,R_OK))
4 andreas 985
	   {
986
	      syslog(LOG_WARNING,"Even config file %s was not found!", confFile);
1 root 987
	      confFile[0] = 0;
4 andreas 988
	   }
1 root 989
	}
990
	else
991
	   confFile[0] = 0;
992
 
5 andreas 993
	memset(&configs, 0, sizeof(configs));
994
	strcpy(configs.User,"nobody");
995
	strcpy(configs.Grp,"nobody");
996
	strcpy(configs.HeizPath, "/var/www/.HeizPlan.conf");
997
	strcpy(configs.Werte, "/var/log/werte.dat");
998
	strcpy(configs.Device, "/dev/ttyS1");
10 andreas 999
	strcpy(configs.Pidfile, "/var/run/heizung.pid");
5 andreas 1000
	configs.port = 11001;
1 root 1001
 
4 andreas 1002
	if (!confFile[0] || (fd = open(confFile,O_RDONLY)) == -1)
1 root 1003
	{
4 andreas 1004
	   if (confFile[0])
1005
	      syslog(LOG_WARNING,"Error opening the config file %s! Using built in defaults. (%s)", confFile, strerror(errno));
1006
	   else
1007
	      syslog(LOG_WARNING,"Error opening the config file! Using built in defaults.");
1008
 
1 root 1009
	   return;
1010
	}
1011
 
4 andreas 1012
	while (readLine(fd, &line[0], sizeof(line)) != NULL)
1 root 1013
	{
1014
	   int len;
1015
 
1016
	   trim (&line[0]);
1017
 
4 andreas 1018
	   if (line[0] == '#' || !strlen(line))
1 root 1019
	      continue;
1020
 
1021
	   if ((p = strchr (line, '=')) == NULL)
1022
	      continue;
1023
 
1024
	   *p = 0;
1025
	   p++;
1026
	   len = strlen(line);
1027
 
1028
	   if (len > sizeof(hv0))
1029
	      len = sizeof(hv0) - 1;
1030
 
1031
	   strncpy (hv0, line, len);
4 andreas 1032
	   hv0[len] = 0;
1 root 1033
	   trim (hv0);
1034
	   len = strlen(p);
1035
 
1036
	   if (len > sizeof(hv1))
1037
	      len = sizeof(hv0) - 1;
1038
 
1039
	   strncpy (hv1, p, len);
4 andreas 1040
	   hv1[len] = 0;
1 root 1041
	   trim (hv1);
1042
 
1043
	   if (!strcasecmp(hv0, "user"))
4 andreas 1044
	   {
1045
	      syslog(LOG_INFO,"Found \"user\": %s", hv1);
1 root 1046
	      strncpy (configs.User, hv1, sizeof(configs.User));
4 andreas 1047
	   }
1 root 1048
 
1049
	   if (!strcasecmp(hv0, "group"))
4 andreas 1050
	   {
1051
	      syslog(LOG_INFO,"Found \"group\": %s", hv1);
1 root 1052
	      strncpy (configs.Grp, hv1, sizeof(configs.Grp));
4 andreas 1053
	   }
1 root 1054
 
1055
	   if (!strcasecmp(hv0, "port"))
4 andreas 1056
	   {
1057
	      syslog(LOG_INFO,"Found \"port\": %s", hv1);
1 root 1058
	      configs.port = atoi (hv1);
4 andreas 1059
	   }
1 root 1060
 
1061
	   if (!strcasecmp(hv0, "heizpath"))
4 andreas 1062
	   {
1063
	      syslog(LOG_INFO,"Found \"heizpath\": %s", hv1);
1 root 1064
	      strncpy (configs.HeizPath, hv1, sizeof(configs.HeizPath));
4 andreas 1065
	   }
5 andreas 1066
 
1067
	   if (!strcasecmp(hv0, "Werte"))
1068
	   {
1069
	      syslog(LOG_INFO,"Found \"Werte\": %s", hv1);
1070
	      strncpy (configs.Werte, hv1, sizeof(configs.Werte));
1071
	   }
1072
 
1073
	   if (!strcasecmp(hv0, "Device"))
1074
	   {
1075
	      syslog(LOG_INFO,"Found \"Device\": %s", hv1);
1076
	      strncpy (configs.Device, hv1, sizeof(configs.Device));
1077
	   }
1078
 
10 andreas 1079
	   if (!strcasecmp(hv0, "Pidfile"))
1080
	   {
1081
	      syslog(LOG_INFO,"Found \"Pidfile\": %s", hv1);
1082
	      strncpy (configs.Pidfile, hv1, sizeof(configs.Pidfile));
1083
	   }
1084
 
5 andreas 1085
	   if (!strcasecmp(hv0, "VID"))
1086
	   {
1087
	      syslog(LOG_INFO,"Found VendorID: %04x", atoi(hv1));
1088
	      configs.VID = atoi(hv1);
1089
	   }
1090
 
1091
	   if (!strcasecmp(hv0, "PID"))
1092
	   {
1093
	      syslog(LOG_INFO,"Found ProductID: %04x", atoi(hv1));
1094
	      configs.PID = atoi(hv1);
1095
	   }
1 root 1096
	}
1097
 
1098
	close (fd);
1099
}
1100
 
9 andreas 1101
char *makeFileName(char *ret, char *fname, int len)
1102
{
1103
char *fdup, *pright, *cfg, *lcfg;
1104
 
1105
	if (ret == NULL || fname == NULL || !len || !strlen(fname))
1106
	   return NULL;
1107
 
1108
	if (!access(fname, R_OK | W_OK))
1109
	{
1110
	   memset(ret, 0, len);
1111
	   strncpy(ret, fname, len-1);
1112
	   return ret;
1113
	}
1114
 
1115
	fdup = strdup(fname);
1116
 
1117
	if (fdup == NULL)
1118
	{
1119
	   syslog(LOG_DAEMON, "Error allocating memory: %s", strerror(errno));
1120
	   return NULL;
1121
	}
1122
 
1123
	cfg = strdup(configs.HeizPath);
1124
 
1125
	if (cfg == NULL)
1126
	{
1127
	   syslog(LOG_DAEMON, "Error allocating memory: %s", strerror(errno));
1128
	   free(fdup);
1129
	   return NULL;
1130
	}
1131
 
1132
	pright = basename(fdup);
1133
	lcfg = dirname(cfg);
1134
	memset(ret, 0, len);
1135
	strncpy(ret, lcfg, len-1);
1136
 
1137
	if (strlen(ret) < (len - (strlen(pright) + 2)))
1138
	{
1139
	   strcat(ret, "/");
1140
	   strcat(ret, pright);
1141
	   free(fdup);
1142
	   free(cfg);
1143
	   return ret;
1144
	}
1145
 
1146
	free(fdup);
1147
	free(cfg);
1148
	return NULL;
1149
}
1150
 
1 root 1151
int readHeizPlan(void)
1152
{
9 andreas 1153
	return readHeizPlanName(configs.HeizPath);
1154
}
1155
 
1156
int readHeizPlanName(char* fname)
1157
{
1 root 1158
int fd, i, wday;
1159
ulong tim;
1160
char line[512];
1161
char *p, *xp;
1162
char hv0[64], hv1[128];
9 andreas 1163
char path[512];
1 root 1164
float temperature;
7 andreas 1165
int counter = 0;
4 andreas 1166
HEIZINDEX *act, *prev;
1 root 1167
 
1168
	fd = -1;
1169
 
9 andreas 1170
	if (makeFileName(&path[0], fname, sizeof(path)) == NULL)
4 andreas 1171
	{
9 andreas 1172
	   syslog(LOG_DAEMON,"No or invalid path %s", fname);
1 root 1173
	   return 0;
4 andreas 1174
	}
1 root 1175
 
9 andreas 1176
	if (access(path, R_OK))
4 andreas 1177
	{
9 andreas 1178
	   syslog(LOG_DAEMON,"Access to file %s denied: %s", path, strerror(errno));
1 root 1179
	   return 0;
4 andreas 1180
	}
1 root 1181
 
9 andreas 1182
	if ((fd = open(path, O_RDONLY)) == -1)
1183
	{
1184
	   syslog(LOG_DAEMON,"Error opening file %s: %s", path, strerror(errno));
1185
	   return 0;
1186
	}
1187
 
4 andreas 1188
	act = prev = NULL;
1189
	freeMemory();
1190
 
1191
	while (readLine(fd, &line[0], sizeof(line)) != NULL)
1 root 1192
	{
1193
	   int len;
1194
 
1195
	   trim (&line[0]);
1196
 
5 andreas 1197
	   if (line[0] == '#' || !strlen(line) || strchr(line, ',') == NULL)
1 root 1198
	      continue;
1199
 
4 andreas 1200
	   // We need a place to store the information
1201
	   prev = act;
1202
 
1203
	   if ((act = allocateMemory()) == NULL)
1204
	   {
1205
	      close(fd);
1206
	      syslog(LOG_DAEMON,"Error allocating memory for a temperature line! Stopped reading file %s.", configs.HeizPath);
1207
	      return 0;
1208
	   }
1209
 
7 andreas 1210
	   counter++;
4 andreas 1211
	   memset(act->heizung, 0, sizeof(HEIZUNG));
1 root 1212
	   // Parse a line. The line has the format:
1213
	   // <wday>,<end>,<temperature>
4 andreas 1214
	   p = strtok(line, ",");
1 root 1215
	   i = 1;
1216
 
1217
	   while(p)
1218
	   {
1219
	      switch(i)
1220
	      {
1221
		 case 1:	// Week day
1222
		    wday = atoi(p);
1223
 
1224
		    if (wday < 1 || wday > 7)	// valid line?
1225
		    {
4 andreas 1226
		       if (prev)
1227
			  wday = prev->heizung->wday;
1 root 1228
 
4 andreas 1229
		       if (wday < 1 || wday > 7)
1230
		       {
1231
			  p = strtok(NULL, ",");
1232
			  i++;
1233
			  continue;
1234
		       }
1 root 1235
		    }
1236
 
1237
		    act->heizung->wday = wday;
1238
		    act->heizung->start = 0;
1239
		 break;
1240
 
1241
		 case 2:	// start/end time
1242
		    if ((xp = strchr(p, ':')) != NULL)
1243
		    {
1244
		    int hour, min;
1245
 
1246
		       hour = atoi(p);
1247
		       min = atoi(xp+1);
1248
 
1249
		       if (hour >= 0 && hour <= 23 && min >= 0 && min <= 59)
1250
		       {
5 andreas 1251
			  act->heizung->end = hour * 3600 + min * 60 + 59;
1 root 1252
 
4 andreas 1253
			  if (prev && prev->heizung->wday == act->heizung->wday)
1254
			     act->heizung->start = prev->heizung->end;
1 root 1255
		       }
1256
		    }
1257
		 break;
1258
 
1259
		 case 3:	// temperature
1260
		    temperature = atof(p);
1261
 
1262
		    if (temperature < 5.0 || temperature > 30.0)
1263
		    {
4 andreas 1264
		       p = strtok(NULL,",");
1265
		       i++;
1 root 1266
		       continue;
1267
		    }
1268
 
1269
		    act->heizung->temp = temperature;
1270
		 break;
1271
	      }
1272
 
4 andreas 1273
	      p = strtok(NULL, ",");
1274
	      i++;
1 root 1275
	   }
1276
	}
1277
 
7 andreas 1278
	syslog(LOG_INFO,"Found %d entries in %s", counter, configs.HeizPath);
1 root 1279
	close (fd);
1280
	return 1;
1281
}
1282
 
1283
/*
1284
 * write the (may be) altered plan.
1285
 * This function allways writes whole plan.
1286
 */
1287
int writeHeizPlan()
1288
{
9 andreas 1289
	return writeHeizPlanName(configs.HeizPath);
1290
}
1291
 
1292
int writeHeizPlanName(char *fname)
1293
{
10 andreas 1294
int fd, wday;
1295
ulong lastEnd;
1296
char hv0[128], path[512];
1 root 1297
HEIZINDEX *act;
1298
 
1299
	fd = -1;
1300
 
9 andreas 1301
	if (makeFileName(&path[0], fname, sizeof(path)) == NULL)
1302
	{
1303
	   syslog(LOG_DAEMON,"No or invalid path %s", fname);
1 root 1304
	   return 0;
9 andreas 1305
	}
1 root 1306
 
10 andreas 1307
	if (!sortTable())
1308
	   return 0;
1309
 
9 andreas 1310
	if ((fd = open(path, O_RDWR | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
1311
	{
1312
	   syslog(LOG_DAEMON, "Error opening/creating file %s: %s", path, strerror(errno));
1 root 1313
	   return 0;
9 andreas 1314
	}
1 root 1315
 
10 andreas 1316
	// Sort table for week days
1317
	for (wday = 1; wday <= 7; wday++)
1318
	{
1319
	   lastEnd = 0L;
1320
	   act = HeizFirst;
1 root 1321
 
10 andreas 1322
	   while(act)
5 andreas 1323
	   {
10 andreas 1324
	      if (act->heizung->wday == wday)
1325
	      {
5 andreas 1326
	      int hour, min;
1327
 
10 andreas 1328
		 hour = act->heizung->end / 3600;
1329
		 min = (act->heizung->end - (hour * 3600)) / 60;
5 andreas 1330
 
10 andreas 1331
		 if (hour > 23)
1332
		 {
1333
		    hour = 23;
1334
		    min = 59;
1335
		 }
1336
 
1337
		 sprintf(&hv0[0], "%d,%02d:%02d,%.1f\n",
1338
		     act->heizung->wday, hour, min,
1339
		     act->heizung->temp);
1340
		 write(fd, &hv0[0], strlen(hv0));
1341
	      }
1342
 
1343
	      act = act->next;
1344
	   }
1345
	}
1346
 
1347
	close(fd);
1348
	return 1;
1349
}
1350
 
1351
/*
1352
 * Allocate the memory for the actual heizung plan.
1353
 * This function appends an element to the end of the chain.
1354
 */
1355
HEIZINDEX *allocMem(HEIZINDEX *first)
1356
{
1357
HEIZINDEX *act, *last;
1358
 
1359
	if (!first)
1360
	{
1361
	   first = malloc(sizeof(HEIZINDEX));
1362
 
1363
	   if (first)
1364
	   {
1365
	      first->heizung = malloc(sizeof(HEIZUNG));
1366
	      first->next = NULL;
1367
	   }
1368
	   else
1369
	      return NULL;
1370
 
1371
	   return first;
1372
	}
1373
	else
1374
	{
1375
	   // Find last element
1376
	   last = first;
1377
 
1378
	   while(last->next)
1379
	      last = last->next;
1380
 
1381
	   act = malloc(sizeof(HEIZINDEX));
1382
 
1383
	   if (act)
1384
	   {
1385
	      act->heizung = malloc(sizeof(HEIZUNG));
1386
	      act->next = NULL;
1387
	      last->next = act;
1388
	   }
1389
	   else
1390
	      return NULL;
1391
 
1392
	   return act;
1393
	}
1394
 
1395
	return NULL;
1396
}
1397
 
1398
// This function sorts the table for week days and every into increasing
1399
// time stamps
1400
int sortTable()
1401
{
1402
int count, actElement, wday, flag;
1403
ulong end;
1404
HEIZINDEX *first, *act, *p;
1405
 
1406
	if (!HeizFirst)
1407
	   return 0;
1408
 
1409
	p = HeizFirst;
1410
	// Count the number of elements
1411
	count = 0;
1412
 
1413
	while (p)
1414
	{
1415
	   if (p->heizung->wday)
1416
	      count++;
1417
 
1418
	   p = p->next;
1419
	}
1420
 
1421
	wday = 1;
1422
	act = first = NULL;
1423
	actElement = 0;
1424
 
1425
	// First loop sorts for week days
1426
	while (actElement < count && wday <= 7)
1427
	{
1428
	int cnt, pos;
1429
 
1430
	   p = HeizFirst;
1431
	   flag = 0;
1432
	   // find number of entries for actual week day
1433
	   cnt = 0;
1434
	   act = HeizFirst;
1435
 
1436
	   while(act)
1437
	   {
1438
	      if (act->heizung->wday == wday)
1439
		 cnt++;
1440
 
1441
	      act = act->next;
1442
	   }
1443
 
1444
	   pos = 0;
1445
	   end = 0L;
1446
 
1447
	   // Second loop sorts the actual week day for end times
1448
	   while (p)
1449
	   {
1450
	      if (p->heizung->wday == wday && p->heizung->start == end && p->heizung->end > end)
5 andreas 1451
	      {
10 andreas 1452
		 actElement++;
1453
		 flag = 1;
1454
		 act = allocMem(first);
1455
 
1456
		 if (!first)
1457
		    first = act;
1458
 
1459
		 // Check for valid memory block
1460
		 if (act)
1461
		 {
1462
		    memmove(act->heizung, p->heizung, sizeof(HEIZUNG));
1463
		    end = p->heizung->end;
1464
		    pos++;
1465
		 }
1466
		 else
1467
		 {
1468
		    syslog(LOG_DAEMON,"Error allocationg memory for sorting table: %s", strerror(errno));
1469
		    // Free allocated memory
1470
		    act = first;
1471
 
1472
		    while(act)
1473
		    {
1474
		       p = act->next;
1475
		       free(act->heizung);
1476
		       free(act);
1477
		       act = p;
1478
		    }
1479
 
1480
		    return 0;
1481
		 }
5 andreas 1482
	      }
1483
 
10 andreas 1484
	      p = p->next;
1485
 
1486
	      // If there are still members left, reset pointer and restart loop
1487
	      if (!p && pos < (cnt - 1) && flag)
1488
	      {
1489
		 p = HeizFirst;
1490
		 flag = 0;
1491
	      }
5 andreas 1492
	   }
1493
 
10 andreas 1494
	   wday++;
1 root 1495
	}
1496
 
10 andreas 1497
	freeMemory();
1498
	HeizFirst = first;
1 root 1499
	return 1;
1500
}
1501
 
4 andreas 1502
char *readLine(int fd, char *buf, int bufLen)
1 root 1503
{
4 andreas 1504
int i, end;
1 root 1505
char ch, *p;
1506
 
1507
        if (fd <= 0)
4 andreas 1508
	{
1509
	   syslog(LOG_DAEMON,"Function readLine was called with an invalid file descriptor of %d!", fd);
1510
           return NULL;
1511
	}
1 root 1512
 
4 andreas 1513
        i = end = 0;
1514
        p = buf;
1 root 1515
 
4 andreas 1516
        while (read(fd, &ch, 1) > 0)
1517
        {
1518
           end = 1;
1 root 1519
 
4 andreas 1520
           if (ch == 0x0a)
1521
           {
1522
             *p = 0;
1523
             return buf;
1524
           }
1 root 1525
 
4 andreas 1526
           if (ch == 0x0d)      // ignore this!
1527
              continue;
1 root 1528
 
4 andreas 1529
           if (i < (bufLen - 1))
1530
           {
1531
              *p = ch;
1532
              p++;
1533
              i++;
1534
           }
1535
        }
1 root 1536
 
4 andreas 1537
        *p = 0;
1538
 
1539
        if (end)
1540
           return buf;
1541
        else
1542
           return NULL;
1 root 1543
}
1544
 
1545
char *trim(char *str)
1546
{
1547
char *p1, *p2, *p;
1548
 
1549
	if (!str)
1550
	   return NULL;
1551
 
4 andreas 1552
	if (!strlen(str))
1553
	   return str;
1554
 
1 root 1555
	p = str;
1556
	p1 = p2 = NULL;
1557
 
1558
	while (*p)
1559
	{
1560
	   if (!p1 && *p != ' ')
1561
	   {
1562
	      p1 = p;
1563
	      break;
1564
	   }
1565
 
1566
	   p++;
1567
	}
1568
 
1569
	p2 = str + (strlen(str) - 1);
1570
 
1571
	while (p2 > str && *p2 == ' ')
1572
	   p2--;
1573
 
1574
	if (p2)
1575
	   *(p2+1) = 0;
1576
 
1577
	if (p1)
1578
	{
1579
	   char *buf = strdup (p1);
1580
	   strcpy (str, buf);
1581
	   free (buf);
1582
	}
1583
 
1584
	return str;
1585
}
2 andreas 1586
 
1587
char *remove_string(char *str, char *search, char *ret)
1588
{
1589
char *p;
1590
 
1591
	if (!strlen(str) || !strlen(search))
1592
	   return NULL;
1593
 
1594
	if ((p = strstr(str, search)) != NULL)
1595
	{
1596
	int len = strlen(search);
1597
 
4 andreas 1598
	   strncpy(ret, str, p - str + len);
5 andreas 1599
	   ret[p - str + len] = 0;
1600
	   memmove(str, p + len, strlen(p+len));
1601
	   str[strlen(p+len)] = 0;
2 andreas 1602
	   return ret;
1603
	}
1604
 
1605
	return NULL;
4 andreas 1606
}