Subversion Repositories heizung

Rev

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