Browse Source

working daemon

master
Olaf Rempel 10 years ago
parent
commit
8a0fc420d9
19 changed files with 1540 additions and 171 deletions
  1. 0
    1
      .gitignore
  2. 0
    9
      Host/Makefile
  3. 0
    160
      Host/i2c-test.c
  4. 1
    1
      alix-usv.c
  5. 6
    0
      daemon/.gitignore
  6. 28
    0
      daemon/Makefile
  7. 105
    0
      daemon/alix-usv.c
  8. 333
    0
      daemon/alix-usvd.c
  9. 21
    0
      daemon/alix-usvd.conf
  10. 216
    0
      daemon/configfile.c
  11. 15
    0
      daemon/configfile.h
  12. 298
    0
      daemon/event.c
  13. 42
    0
      daemon/event.h
  14. 0
    0
      daemon/i2c-dev.h
  15. 268
    0
      daemon/list.h
  16. 101
    0
      daemon/logging.c
  17. 19
    0
      daemon/logging.h
  18. 80
    0
      daemon/unixsocket.c
  19. 7
    0
      daemon/unixsocket.h

+ 0
- 1
.gitignore View File

@@ -4,4 +4,3 @@
4 4
 *.hex
5 5
 *.lst
6 6
 *.map
7
-Host/i2c-test

+ 0
- 9
Host/Makefile View File

@@ -1,9 +0,0 @@
1
-all:
2
-	gcc -O2 -Wall i2c-test.c -o i2c-test
3
-
4
-driver:
5
-	sudo modprobe i2c-dev
6
-
7
-perm:
8
-	sudo chgrp dialout /dev/i2c-0
9
-

+ 0
- 160
Host/i2c-test.c View File

@@ -1,160 +0,0 @@
1
-/*
2
- * config file:
3
- * - i2c device
4
- * - i2c address
5
- * - email-address
6
- * - reporting config (when logging / mailing)
7
- * - thresholds for do shutdown
8
- *
9
- * parameters:
10
- * -d run as daemon
11
- * -f foreground
12
- * -v debug
13
- * -c [idle|charge|test|poweroff] command (not with -d)
14
- * --config
15
- * --help
16
- *
17
- * in command mode try to use daemon first (via unix-socket)
18
- * then fallback to i2c
19
- */
20
-#include <stdint.h>
21
-#include <stdio.h>
22
-#include <stdlib.h>
23
-#include <unistd.h>
24
-#include <string.h>
25
-
26
-#include <sys/ioctl.h>
27
-#include <sys/types.h>
28
-#include <sys/stat.h>
29
-#include <fcntl.h>
30
-
31
-#include "i2c-dev.h"
32
-
33
-enum {
34
-	REG_STATUS	= 0x00,
35
-
36
-	REG_CURRENT	= 0x10,
37
-	REG_UBAT	= 0x11,
38
-	REG_UIN		= 0x12,
39
-
40
-	REG_UIN_LOSS	= 0x20,
41
-	REG_UIN_RESTORE	= 0x21,
42
-	REG_UBAT_FULL	= 0x22,
43
-	REG_UBAT_LOW	= 0x23,
44
-	REG_UBAT_CRIT	= 0x24,
45
-	REG_IBAT_FULL	= 0x25,
46
-	REG_CRC		= 0x26,
47
-};
48
-
49
-struct usv_data {
50
-	uint16_t sys_state;
51
-
52
-	int16_t adc_current;
53
-	int16_t adc_ubat;
54
-	int16_t adc_uin;
55
-
56
-	int16_t uin_loss;
57
-	int16_t uin_restore;
58
-	int16_t ubat_full;
59
-	int16_t ubat_low;
60
-	int16_t ubat_critical;
61
-	int16_t ibat_full;
62
-	uint16_t crc16;
63
-};
64
-
65
-enum {
66
-	STATE_IDLE	= 0x01,
67
-	STATE_TEST	= 0x02,
68
-	STATE_CHARGE	= 0x04,
69
-	STATE_DISCHARGE	= 0x08,
70
-	STATE_POWEROFF	= 0x10,
71
-};
72
-
73
-static char * state2str(uint8_t state)
74
-{
75
-	switch (state) {
76
-	case STATE_IDLE:
77
-		return "STATE_IDLE";
78
-
79
-	case STATE_TEST:
80
-		return "STATE_TEST";
81
-
82
-	case STATE_CHARGE:
83
-		return "STATE_CHARGE";
84
-
85
-	case STATE_DISCHARGE:
86
-		return "STATE_DISCHARGE";
87
-
88
-	case STATE_POWEROFF:
89
-		return "STATE_POWEROFF";
90
-
91
-	default:
92
-		return "<UNKNOWN>";
93
-	}
94
-}
95
-
96
-static int i2c_open(const char *path)
97
-{
98
-	int fd = open(path, O_RDWR);
99
-	if (fd < 0) {
100
-		perror("open()");
101
-		return -1;
102
-	}
103
-
104
-	unsigned long funcs;
105
-	if (ioctl(fd, I2C_FUNCS, &funcs)) {
106
-		perror("ioctl(I2C_FUNCS)");
107
-		close(fd);
108
-		return -1;
109
-	}
110
-
111
-	if ((funcs & I2C_FUNC_SMBUS_WORD_DATA) != I2C_FUNC_SMBUS_WORD_DATA) {
112
-		fprintf(stderr, "I2C_FUNC_SMBUS_WORD_DATA not supported!\n");
113
-		close(fd);
114
-		return -1;
115
-	}
116
-
117
-	return fd;
118
-}
119
-
120
-static int i2c_setaddress(int fd, int address)
121
-{
122
-	if (ioctl(fd, I2C_SLAVE, address) < 0) {
123
-		perror("ioctl(I2C_SLAVE)");
124
-		close(fd);
125
-		return -1;
126
-	}
127
-	return 0;
128
-}
129
-
130
-int main(int argc, char *argv[])
131
-{
132
-	int fd = i2c_open("/dev/i2c-0");
133
-	if (fd < 0)
134
-		exit(-1);
135
-
136
-	if (i2c_setaddress(fd, 0x10) < 0)
137
-		exit(-1);
138
-
139
-	while (1) {
140
-		struct usv_data usv;
141
-		memset(&usv, 0, sizeof(usv));
142
-
143
-		usv.sys_state = i2c_smbus_read_word_data(fd, REG_STATUS);
144
-		usv.adc_current = i2c_smbus_read_word_data(fd, REG_CURRENT);
145
-		usv.adc_ubat = i2c_smbus_read_word_data(fd, REG_UBAT);
146
-		usv.adc_uin = i2c_smbus_read_word_data(fd, REG_UIN);
147
-
148
-		printf("state:0x%02x I:%5dmA Ubat:%5dmV Usup:%5dmV (%s) [%5d,%5d,%5d,%5d,%5d,%5d,0x%04x]\n",
149
-			usv.sys_state, usv.adc_current, usv.adc_ubat,
150
-			usv.adc_uin, state2str(usv.sys_state),
151
-			usv.uin_loss, usv.uin_restore, usv.ubat_full,
152
-			usv.ubat_low, usv.ubat_critical, usv.ibat_full,
153
-			usv.crc16);
154
-
155
-		sleep(1);
156
-	}
157
-	close(fd);
158
-
159
-	return 0;
160
-}

+ 1
- 1
alix-usv.c View File

@@ -151,7 +151,7 @@ uint8_t usi_read(uint8_t bcnt)
151 151
 		return ptr[index];
152 152
 	}
153 153
 
154
-	return 0xFF;
154
+	return 0x00;
155 155
 }
156 156
 
157 157
 /*

+ 6
- 0
daemon/.gitignore View File

@@ -0,0 +1,6 @@
1
+*.o
2
+*.d
3
+alix-usv
4
+alix-usvd
5
+alix-usvd.sock
6
+alix-usvd.log

+ 28
- 0
daemon/Makefile View File

@@ -0,0 +1,28 @@
1
+TARGET1 = alix-usv
2
+TARGET2 = alix-usvd
3
+
4
+CFLAGS = -Wall -O2 -MD -MP -MF $(*F).d
5
+
6
+# ------
7
+
8
+SRC1 := alix-usv.c logging.c unixsocket.c
9
+SRC2 := alix-usvd.c configfile.c event.c logging.c unixsocket.c
10
+
11
+all: $(TARGET1) $(TARGET2)
12
+
13
+$(TARGET1): $(SRC1:.c=.o)
14
+	@echo " Linking file:  $@"
15
+	@$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) > /dev/null
16
+
17
+$(TARGET2): $(SRC2:.c=.o)
18
+	@echo " Linking file:  $@"
19
+	@$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) > /dev/null
20
+
21
+%.o: %.c
22
+	@echo " Building file: $<"
23
+	@$(CC) -c $(CFLAGS) $< -o $@
24
+
25
+clean:
26
+	rm -rf $(TARGET1) $(TARGET2) *.o *.d
27
+
28
+-include $(shell find . -name \*.d 2> /dev/null)

+ 105
- 0
daemon/alix-usv.c View File

@@ -0,0 +1,105 @@
1
+/***************************************************************************
2
+ *   Copyright (C) 03/2009 by Olaf Rempel                                  *
3
+ *   razzor@kopf-tisch.de                                                  *
4
+ *                                                                         *
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; version 2 of the License                *
8
+ *                                                                         *
9
+ *   This program is distributed in the hope that it will be useful,       *
10
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12
+ *   GNU General Public License for more details.                          *
13
+ *                                                                         *
14
+ *   You should have received a copy of the GNU General Public License     *
15
+ *   along with this program; if not, write to the                         *
16
+ *   Free Software Foundation, Inc.,                                       *
17
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18
+ ***************************************************************************/
19
+#include <stdio.h>
20
+#include <stdlib.h>
21
+#include <unistd.h>
22
+#include <string.h>
23
+
24
+#include <getopt.h>
25
+
26
+#include "logging.h"
27
+#include "unixsocket.h"
28
+
29
+#define DEFAULT_SOCKET "alix-usvd.sock"
30
+
31
+static struct option opts[] = {
32
+	{"command",	1, 0, 'c'},
33
+	{"help",	0, 0, 'h'},
34
+	{"socket",	1, 0, 's'},
35
+	{0, 0, 0, 0}
36
+};
37
+
38
+int main(int argc, char *argv[])
39
+{
40
+	char *socket_path = DEFAULT_SOCKET;
41
+	char *cmd = NULL;
42
+
43
+	int code, arg = 0;
44
+	do {
45
+		code = getopt_long(argc, argv, "c:hs:", opts, &arg);
46
+		switch (code) {
47
+		case 'c': /* command */
48
+			if (strncasecmp(optarg, "IDLE", 4) == 0)
49
+				cmd = optarg;
50
+
51
+			else if (strncasecmp(optarg, "TEST", 4) == 0)
52
+				cmd = optarg;
53
+
54
+			else if (strncasecmp(optarg, "CHARGE", 6) == 0)
55
+				cmd = optarg;
56
+
57
+			else if (strncasecmp(optarg, "POWEROFF", 8) == 0)
58
+				cmd = optarg;
59
+
60
+			else if (strncasecmp(optarg, "STATUS", 6) == 0)
61
+				cmd = optarg;
62
+
63
+			break;
64
+
65
+		case 's': /* socket */
66
+			socket_path = optarg;
67
+			break;
68
+
69
+		case 'h': /* help */
70
+			printf("Usage: alix-usv [-s socket] -c <status|idle|charge|test|poweroff>\n\n");
71
+			exit(0);
72
+			break;
73
+
74
+		case '?': /* error */
75
+			exit(1);
76
+			break;
77
+
78
+		default: /* unknown / all options parsed */
79
+			break;
80
+		}
81
+	} while (code != -1);
82
+
83
+	if (cmd == NULL) {
84
+		log_print(LOG_ERROR, "invalid command: %s", cmd);
85
+		return -1;
86
+	}
87
+
88
+	int sock = unix_connect(socket_path);
89
+	if (sock < 0)
90
+		return -1;
91
+
92
+	write(sock, cmd, strlen(cmd));
93
+
94
+	char buf[64];
95
+	int len = read(sock, buf, sizeof(buf));
96
+	if (len <= 0) {
97
+		log_print(LOG_ERROR, "no answer from server");
98
+		return -1;
99
+	}
100
+
101
+	log_print(LOG_INFO, "%s", buf);
102
+
103
+	close(sock);
104
+	return 0;
105
+}

+ 333
- 0
daemon/alix-usvd.c View File

@@ -0,0 +1,333 @@
1
+/***************************************************************************
2
+ *   Copyright (C) 03/2009 by Olaf Rempel                                  *
3
+ *   razzor@kopf-tisch.de                                                  *
4
+ *                                                                         *
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; version 2 of the License                *
8
+ *                                                                         *
9
+ *   This program is distributed in the hope that it will be useful,       *
10
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12
+ *   GNU General Public License for more details.                          *
13
+ *                                                                         *
14
+ *   You should have received a copy of the GNU General Public License     *
15
+ *   along with this program; if not, write to the                         *
16
+ *   Free Software Foundation, Inc.,                                       *
17
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18
+ ***************************************************************************/
19
+#include <stdio.h>
20
+#include <stdlib.h>
21
+#include <unistd.h>
22
+#include <string.h>
23
+#include <stdint.h>
24
+
25
+#include <getopt.h>
26
+#include <sys/types.h>
27
+#include <sys/socket.h>
28
+#include <sys/ioctl.h>
29
+#include <sys/stat.h>
30
+#include <fcntl.h>
31
+
32
+#include "i2c-dev.h"
33
+
34
+#include "configfile.h"
35
+#include "event.h"
36
+#include "logging.h"
37
+#include "unixsocket.h"
38
+
39
+#define DEFAULT_CONFIG "alix-usvd.conf"
40
+#define DEFAULT_LOGFILE "alix-usvd.log"
41
+#define DEFAULT_SOCKET "alix-usvd.sock"
42
+
43
+enum {
44
+	REG_STATUS	= 0x00,
45
+
46
+	REG_CURRENT	= 0x10,
47
+	REG_UBAT	= 0x11,
48
+	REG_UIN		= 0x12,
49
+
50
+	REG_UIN_LOSS	= 0x20,
51
+	REG_UIN_RESTORE	= 0x21,
52
+	REG_UBAT_FULL	= 0x22,
53
+	REG_UBAT_LOW	= 0x23,
54
+	REG_UBAT_CRIT	= 0x24,
55
+	REG_IBAT_FULL	= 0x25,
56
+	REG_CRC		= 0x26,
57
+};
58
+
59
+enum {
60
+	STATE_IDLE	= 0x01,
61
+	STATE_TEST	= 0x02,
62
+	STATE_CHARGE	= 0x04,
63
+	STATE_DISCHARGE	= 0x08,
64
+	STATE_POWEROFF	= 0x10,
65
+};
66
+
67
+static struct option opts[] = {
68
+	{"nofork",	0, 0, 'd'},
69
+	{"config",	1, 0, 'c'},
70
+	{"help",	0, 0, 'h'},
71
+	{0, 0, 0, 0}
72
+};
73
+
74
+static int i2cdev_open(const char *i2c_device, int i2c_address)
75
+{
76
+	int fd = open(i2c_device, O_RDWR);
77
+	if (fd < 0)
78
+		return -1;
79
+
80
+	unsigned long funcs;
81
+	if (ioctl(fd, I2C_FUNCS, &funcs)) {
82
+		close(fd);
83
+		return -1;
84
+	}
85
+
86
+	if ((funcs & I2C_FUNC_SMBUS_WORD_DATA) != I2C_FUNC_SMBUS_WORD_DATA) {
87
+		close(fd);
88
+		return -1;
89
+	}
90
+
91
+	if (ioctl(fd, I2C_SLAVE, i2c_address) < 0) {
92
+		close(fd);
93
+		return -1;
94
+	}
95
+
96
+	return fd;
97
+}
98
+
99
+static int i2cdev_open_wrap(void)
100
+{
101
+	static const char *i2c_device;
102
+	static int i2c_address;
103
+	static int i2c_last_opened;
104
+
105
+	if (i2c_device == NULL) {
106
+		i2c_device = config_get_string("global", "i2c-device", "/dev/i2c-0");
107
+		i2c_address = config_get_int("global", "i2c-address" , 16);
108
+	}
109
+
110
+	int dev = i2cdev_open(i2c_device, i2c_address);
111
+	if (dev < 0) {
112
+		if (i2c_last_opened != -1)
113
+			log_print(LOG_WARN, "failed to open %s:0x%02x", i2c_device, i2c_address);
114
+
115
+		i2c_last_opened = -1;
116
+		return -1;
117
+	}
118
+
119
+	if (i2c_last_opened < 1)
120
+		log_print(LOG_INFO, "successfully opened %s:0x%02x", i2c_device, i2c_address);
121
+
122
+	i2c_last_opened = 1;
123
+	return dev;
124
+}
125
+
126
+static char * state2str(int state)
127
+{
128
+	switch (state) {
129
+	case STATE_IDLE:
130
+		return "IDLE";
131
+
132
+	case STATE_TEST:
133
+		return "TEST";
134
+
135
+	case STATE_CHARGE:
136
+		return "CHARGE";
137
+
138
+	case STATE_DISCHARGE:
139
+		return "DISCHARGE";
140
+
141
+	case STATE_POWEROFF:
142
+		return "POWEROFF";
143
+
144
+	default:
145
+		return "UNKNOWN";
146
+	}
147
+}
148
+
149
+static int str2state(char *buf)
150
+{
151
+	int state = -1;
152
+	if (strncasecmp(buf, "IDLE", 4) == 0)
153
+		state = STATE_IDLE;
154
+
155
+	else if (strncasecmp(buf, "TEST", 4) == 0)
156
+		state = STATE_TEST;
157
+
158
+	else if (strncasecmp(buf, "CHARGE", 6) == 0)
159
+		state = STATE_CHARGE;
160
+
161
+	else if (strncasecmp(buf, "DISCHARGE", 9) == 0)
162
+		state = STATE_DISCHARGE;
163
+
164
+	else if (strncasecmp(buf, "POWEROFF", 8) == 0)
165
+		state = STATE_POWEROFF;
166
+
167
+	return state;
168
+}
169
+
170
+static int usv_state = -1;
171
+
172
+static void check_state(int old_state, int new_state)
173
+{
174
+	log_print(LOG_INFO, "usv state changed: %s(%d) => %s(%d)",
175
+				state2str(old_state), old_state,
176
+				state2str(new_state), new_state);
177
+}
178
+
179
+static int unix_read_cb(int fd, void *privdata)
180
+{
181
+	char buf[64];
182
+	int len = read(fd, buf, sizeof(buf));
183
+	if (len < 0)
184
+		return -1;
185
+
186
+	int dev = i2cdev_open_wrap();
187
+	if (dev < 0)
188
+		return 0;
189
+
190
+	int new_state = str2state(buf);
191
+	if (new_state != -1) {
192
+		if (i2c_smbus_write_word_data(dev, REG_STATUS, new_state) == 0) {
193
+			usv_state = new_state;
194
+			log_print(LOG_INFO, "set state to %s", state2str(usv_state));
195
+		}
196
+
197
+		int len = snprintf(buf, sizeof(buf), "%s", state2str(usv_state));
198
+		write(fd, buf, len);
199
+
200
+	} else if (strncmp(buf, "status", 6) == 0) {
201
+		new_state = i2c_smbus_read_word_data(dev, REG_STATUS);
202
+		int adc_ibat = i2c_smbus_read_word_data(dev, REG_CURRENT);
203
+		int adc_ubat = i2c_smbus_read_word_data(dev, REG_UBAT);
204
+		int adc_uin = i2c_smbus_read_word_data(dev, REG_UIN);
205
+
206
+		if (new_state < 0 || adc_ibat < 0 || adc_ubat < 0 || adc_uin < 0) {
207
+			new_state = -1;
208
+			adc_ibat = 0;
209
+			adc_ubat = 0;
210
+			adc_uin = 0;
211
+
212
+		} else if (new_state != usv_state) {
213
+			check_state(usv_state, new_state);
214
+			usv_state = new_state;
215
+		}
216
+
217
+		int len = snprintf(buf, sizeof(buf), "%s:%d:%d:%d",
218
+					state2str(new_state),
219
+					(int16_t)adc_ibat, adc_ubat, adc_uin);
220
+		write(fd, buf, len);
221
+	}
222
+
223
+	close(dev);
224
+	return -1;
225
+}
226
+
227
+static int unix_accept_cb(int fd, void *privdata)
228
+{
229
+	int con = accept(fd, NULL, NULL);
230
+	if (con < 0) {
231
+		log_print(LOG_ERROR, "unix_accept_cb: accept()");
232
+		return 0;
233
+	}
234
+
235
+	event_add_readfd(NULL, con, unix_read_cb, NULL);
236
+	return 0;
237
+}
238
+
239
+static int status_interval(void *privdata)
240
+{
241
+	int dev = i2cdev_open_wrap();
242
+	if (dev < 0)
243
+		return 0;
244
+
245
+	int new_state = i2c_smbus_read_word_data(dev, REG_STATUS);
246
+	if (new_state == -1) {
247
+		log_print(LOG_WARN, "failed to get status from i2c-device");
248
+		return 0;
249
+	}
250
+
251
+	if (new_state != usv_state) {
252
+		check_state(usv_state, new_state);
253
+		usv_state = new_state;
254
+	}
255
+
256
+	close(dev);
257
+	return 0;
258
+}
259
+
260
+int main(int argc, char *argv[])
261
+{
262
+	char *config = DEFAULT_CONFIG;
263
+	int debug = 0;
264
+
265
+	int code, arg = 0;
266
+	do {
267
+		code = getopt_long(argc, argv, "dc:h", opts, &arg);
268
+		switch (code) {
269
+		case 'd': /* debug */
270
+			debug = 1;
271
+			break;
272
+		case 'c': /* configfile path */
273
+			config = optarg;
274
+			break;
275
+
276
+		case 'h': /* help */
277
+			printf( "Usage: alix-usvd [-d] [-c config]\n"
278
+				"Options: \n"
279
+				"  --debug        -d              do not fork and log to stderr\n"
280
+				"  --config       -c  configfile  use this configfile\n"
281
+				"  --help         -h              this help\n"
282
+				"\n");
283
+			exit(0);
284
+			break;
285
+
286
+		case '?': /* error */
287
+			exit(1);
288
+			break;
289
+
290
+		default: /* unknown / all options parsed */
291
+			break;
292
+		}
293
+	} while (code != -1);
294
+
295
+	/* parse config file */
296
+	if (config_parse(config) < 0)
297
+		exit(1);
298
+
299
+	if (debug == 0) {
300
+		/* start logging */
301
+		const char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE);
302
+		if (log_init(logfile) < 0)
303
+			exit(1);
304
+
305
+		/* zum daemon mutieren */
306
+		daemon(-1, 0);
307
+
308
+		/* TODO: write PID-file */
309
+	}
310
+
311
+	log_print(LOG_INFO, "alix-usvd started (pid: %d)", getpid());
312
+
313
+	const char *socket_path = config_get_string("global", "socket", DEFAULT_SOCKET);
314
+	unlink(socket_path);
315
+	int sockfd = unix_listen(socket_path);
316
+	if (sockfd < 0)
317
+		exit(1);
318
+
319
+	event_add_readfd(NULL, sockfd, unix_accept_cb, NULL);
320
+
321
+	int interval = config_get_int("global", "check-interval", 60);
322
+	struct timeval tv = { .tv_sec = interval, .tv_usec = 0 };
323
+	event_add_timeout(&tv, status_interval, NULL);
324
+
325
+	int dev = i2cdev_open_wrap();
326
+	if (dev != -1) {
327
+		/* TODO: check thresholds */
328
+		close(dev);
329
+	}
330
+
331
+	event_loop();
332
+	return 0;
333
+}

+ 21
- 0
daemon/alix-usvd.conf View File

@@ -0,0 +1,21 @@
1
+[global]
2
+i2c-device /dev/i2c-0
3
+i2c-address 16
4
+
5
+check-interval 10
6
+
7
+socket alix-usvd.sock
8
+logfile alix-usvd.log
9
+pidfile alix-usvd.pid
10
+
11
+[alerts]
12
+mail-to root@localhost
13
+mail-from root@localhost
14
+
15
+[thresholds]
16
+uin_loss 12000
17
+uin_restore 14000
18
+ubat_full 13300
19
+ubat_low 12000
20
+ubat_crit 11000
21
+ibat_full 150

+ 216
- 0
daemon/configfile.c View File

@@ -0,0 +1,216 @@
1
+/***************************************************************************
2
+ *   Copyright (C) 07/2007 by Olaf Rempel                                  *
3
+ *   razzor@kopf-tisch.de                                                  *
4
+ *                                                                         *
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; version 2 of the License                *
8
+ *                                                                         *
9
+ *   This program is distributed in the hope that it will be useful,       *
10
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12
+ *   GNU General Public License for more details.                          *
13
+ *                                                                         *
14
+ *   You should have received a copy of the GNU General Public License     *
15
+ *   along with this program; if not, write to the                         *
16
+ *   Free Software Foundation, Inc.,                                       *
17
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18
+ ***************************************************************************/
19
+#include <stdio.h>
20
+#include <stdlib.h>
21
+#include <string.h>
22
+#include <unistd.h>
23
+
24
+#include <sys/socket.h>
25
+#include <netinet/in.h>
26
+#include <netinet/ip.h>
27
+#include <arpa/inet.h>
28
+
29
+#include "configfile.h"
30
+#include "list.h"
31
+#include "logging.h"
32
+
33
+#define BUFSIZE 1024
34
+
35
+struct conf_section {
36
+	struct list_head list;
37
+	struct list_head tupel_list;
38
+	const char *name;
39
+};
40
+
41
+struct conf_tupel {
42
+	struct list_head list;
43
+	const char *option;
44
+	const char *parameter;
45
+};
46
+
47
+static LIST_HEAD(config_list);
48
+
49
+static struct conf_section * config_add_section(const char *name)
50
+{
51
+	struct conf_section *section;
52
+	section = malloc(sizeof(struct conf_section) + strlen(name));
53
+	if (section == NULL)
54
+		return NULL;
55
+
56
+	INIT_LIST_HEAD(&section->list);
57
+	INIT_LIST_HEAD(&section->tupel_list);
58
+
59
+	section->name = strdup(name);
60
+	if (section->name == NULL) {
61
+		free(section);
62
+		return NULL;
63
+	}
64
+
65
+	list_add_tail(&section->list, &config_list);
66
+	return section;
67
+}
68
+
69
+static int config_add_tupel(struct conf_section *section, const char *option, const char *parameter)
70
+{
71
+	struct conf_tupel *tupel = malloc(sizeof(struct conf_tupel));
72
+	if (tupel == NULL)
73
+		return -1;
74
+
75
+	INIT_LIST_HEAD(&tupel->list);
76
+	tupel->option = strdup(option);
77
+	tupel->parameter = strdup(parameter);
78
+
79
+	if (tupel->option == NULL || tupel->parameter == NULL) {
80
+		free(tupel);
81
+		return -1;
82
+	}
83
+
84
+	list_add_tail(&tupel->list, &section->tupel_list);
85
+	return 0;
86
+}
87
+
88
+int config_parse(const char *config)
89
+{
90
+	FILE *fz = fopen(config, "r");
91
+	if (fz == NULL) {
92
+		log_print(LOG_ERROR, "config_parse(): %s", config);
93
+		return -1;
94
+	}
95
+
96
+	char *line = malloc(BUFSIZE);
97
+	if (line == NULL) {
98
+		log_print(LOG_ERROR, "config_parse(): out of memory");
99
+		fclose(fz);
100
+		return -1;
101
+	}
102
+
103
+	int linenum = 0;
104
+	struct conf_section *section = NULL;
105
+	while (fgets(line, BUFSIZE, fz) != NULL) {
106
+		linenum++;
107
+
108
+		if (line[0] == '#' || line[0] <= ' ') {
109
+			continue;
110
+
111
+		} else if (line[0] == '[') {
112
+			char *tok = strtok(line +1, " ]\n");
113
+
114
+			if (tok == NULL || (section = config_add_section(tok)) == NULL) {
115
+				log_print(LOG_WARN, "config_parse(): invalid section in row %d", linenum);
116
+				free(line);
117
+				fclose(fz);
118
+				return -1;
119
+			}
120
+			continue;
121
+
122
+		} else if (section == NULL) {
123
+			log_print(LOG_WARN, "config_parse(): missing section in row %d", linenum);
124
+			free(line);
125
+			fclose(fz);
126
+			return -1;
127
+		}
128
+
129
+		char *tok = strtok(line, " \n");
130
+		if (tok != NULL) {
131
+			char *tok2;
132
+			while ((tok2 = strtok(NULL, " \n"))) {
133
+				if (config_add_tupel(section, tok, tok2) != 0)
134
+					log_print(LOG_WARN, "config_parse(): invalid row %d", linenum);
135
+			}
136
+		}
137
+	}
138
+
139
+	fclose(fz);
140
+	free(line);
141
+	return 0;
142
+}
143
+
144
+void config_free(void)
145
+{
146
+	struct conf_section *section, *section_tmp;
147
+	struct conf_tupel *tupel, *tupel_tmp;
148
+
149
+	list_for_each_entry_safe(section, section_tmp, &config_list, list) {
150
+		list_for_each_entry_safe(tupel, tupel_tmp, &section->tupel_list, list) {
151
+			list_del(&tupel->list);
152
+			free((char *)tupel->option);
153
+			free((char *)tupel->parameter);
154
+			free(tupel);
155
+		}
156
+		list_del(&section->list);
157
+		free(section);
158
+	}
159
+}
160
+
161
+static struct conf_section * config_get_section(const char *name)
162
+{
163
+	struct conf_section *section;
164
+
165
+	list_for_each_entry(section, &config_list, list) {
166
+		if (!strcmp(section->name, name))
167
+			return section;
168
+	}
169
+	return NULL;
170
+}
171
+
172
+const char * config_get_string(const char *section_str, const char *option, const char *def)
173
+{
174
+	struct conf_section *section = config_get_section(section_str);
175
+	if (section != NULL) {
176
+		struct conf_tupel *tupel;
177
+		list_for_each_entry(tupel, &section->tupel_list, list) {
178
+			if (!strcmp(tupel->option, option))
179
+				return tupel->parameter;
180
+		}
181
+	}
182
+
183
+	if (def != NULL)
184
+		log_print(LOG_WARN, "config [%s:%s] not found, using default: '%s'",
185
+			section_str, option, def);
186
+	return def;
187
+}
188
+
189
+int config_get_int(const char *section, const char *option, int def)
190
+{
191
+	const char *ret = config_get_string(section, option, NULL);
192
+	if (ret == NULL) {
193
+		log_print(LOG_WARN, "config [%s:%s] not found, using default: '%d'",
194
+			section, option, def);
195
+		return def;
196
+	}
197
+	return atoi(ret);
198
+}
199
+
200
+int config_get_strings(const char *section_str, const char *option,
201
+			int (*callback)(const char *value, void *privdata),
202
+			void *privdata)
203
+{
204
+	struct conf_section *section = config_get_section(section_str);
205
+	if (section == NULL)
206
+		return -1;
207
+
208
+	int cnt = 0;
209
+	struct conf_tupel *tupel;
210
+	list_for_each_entry(tupel, &section->tupel_list, list) {
211
+		if (!strcmp(tupel->option, option))
212
+			if (callback(tupel->parameter, privdata) == 0)
213
+				cnt++;
214
+	}
215
+	return cnt;
216
+}

+ 15
- 0
daemon/configfile.h View File

@@ -0,0 +1,15 @@
1
+#ifndef _CONFIG_H_
2
+#define _CONFIG_H_
3
+
4
+int config_parse(const char *config);
5
+void config_free(void);
6
+
7
+const char * config_get_string(const char *section_str, const char *option, const char *def);
8
+
9
+int config_get_int(const char *section, const char *option, int def);
10
+
11
+int config_get_strings(const char *section_str, const char *option,
12
+			int (*callback)(const char *value, void *privdata),
13
+			void *privdata);
14
+
15
+#endif /* _CONFIG_H_ */

+ 298
- 0
daemon/event.c View File

@@ -0,0 +1,298 @@
1
+/***************************************************************************
2
+ *   Copyright (C) 07/2007 by Olaf Rempel                                  *
3
+ *   razzor@kopf-tisch.de                                                  *
4
+ *                                                                         *
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; version 2 of the License                *
8
+ *                                                                         *
9
+ *   This program is distributed in the hope that it will be useful,       *
10
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12
+ *   GNU General Public License for more details.                          *
13
+ *                                                                         *
14
+ *   You should have received a copy of the GNU General Public License     *
15
+ *   along with this program; if not, write to the                         *
16
+ *   Free Software Foundation, Inc.,                                       *
17
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18
+ ***************************************************************************/
19
+#include <stdlib.h>
20
+#include <unistd.h>
21
+#include <string.h>
22
+
23
+#include <sys/time.h>
24
+#include <sys/types.h>
25
+
26
+#include "list.h"
27
+#include "logging.h"
28
+
29
+#include "event.h"
30
+
31
+static LIST_HEAD(event_fd_list);
32
+static LIST_HEAD(event_timeout_list);
33
+
34
+struct event_fd {
35
+	struct list_head list;
36
+	unsigned int flags;
37
+	int fd;
38
+	int (*read_cb)(int fd, void *privdata);
39
+	int (*write_cb)(int fd, void *privdata);
40
+	void *read_priv;
41
+	void *write_priv;
42
+};
43
+
44
+struct event_timeout {
45
+	struct list_head list;
46
+	unsigned int flags;
47
+	struct timeval intervall;
48
+	struct timeval nextrun;
49
+	int (*callback)(void *privdata);
50
+	void *privdata;
51
+};
52
+
53
+struct event_fd * event_add_fd(
54
+			struct event_fd *entry,
55
+			int fd,
56
+			int type,
57
+			int (*callback)(int fd, void *privdata),
58
+			void *privdata)
59
+{
60
+	/* check valid filediskriptor */
61
+	if (fd < 0 || fd > FD_SETSIZE) {
62
+		log_print(LOG_ERROR, "event_add_fd(): invalid fd");
63
+		return NULL;
64
+	}
65
+
66
+	/* check valid type (read/write) */
67
+	if (!(type & FD_TYPES)) {
68
+		log_print(LOG_ERROR, "event_add_fd(): invalid type");
69
+		return NULL;
70
+	}
71
+
72
+	/* create new entry */
73
+	if (entry == NULL) {
74
+		entry = malloc(sizeof(struct event_fd));
75
+		if (entry == NULL) {
76
+			log_print(LOG_ERROR, "event_add_fd(): out of memory");
77
+			return NULL;
78
+		}
79
+
80
+		memset(entry, 0, sizeof(struct event_fd));
81
+		entry->flags |= EVENT_NEW;
82
+		entry->fd = fd;
83
+
84
+		/* put it on the list */
85
+		list_add_tail(&entry->list, &event_fd_list);
86
+	}
87
+
88
+	if (type & FD_READ) {
89
+		entry->flags = (callback != NULL) ? (entry->flags | FD_READ | EVENT_NEW) : (entry->flags & ~FD_READ);
90
+		entry->read_cb = callback;
91
+		entry->read_priv = privdata;
92
+
93
+	} else if (type & FD_WRITE) {
94
+		entry->flags = (callback != NULL) ? (entry->flags | FD_WRITE | EVENT_NEW) : (entry->flags & ~FD_WRITE);
95
+		entry->write_cb = callback;
96
+		entry->write_priv = privdata;
97
+	}
98
+
99
+	return entry;
100
+}
101
+
102
+int event_get_fd(struct event_fd *entry)
103
+{
104
+	return (entry != NULL) ? entry->fd: -1;
105
+}
106
+
107
+void event_remove_fd(struct event_fd *entry)
108
+{
109
+	/* mark the event as deleted -> remove in select() loop */
110
+	entry->flags |= EVENT_DELETE;
111
+}
112
+
113
+static void add_timeval(struct timeval *ret, struct timeval *a, struct timeval *b)
114
+{
115
+	ret->tv_usec = a->tv_usec + b->tv_usec;
116
+	ret->tv_sec = a->tv_sec + b->tv_sec;
117
+
118
+	if (ret->tv_usec >= 1000000) {
119
+		ret->tv_usec -= 1000000;
120
+		ret->tv_sec++;
121
+	}
122
+}
123
+
124
+static void sub_timeval(struct timeval *ret, struct timeval *a, struct timeval *b)
125
+{
126
+	ret->tv_usec = a->tv_usec - b->tv_usec;
127
+	ret->tv_sec = a->tv_sec - b->tv_sec;
128
+
129
+	if (ret->tv_usec < 0) {
130
+		ret->tv_usec += 1000000;
131
+		ret->tv_sec--;
132
+	}
133
+}
134
+
135
+static int cmp_timeval(struct timeval *a, struct timeval *b)
136
+{
137
+	if (a->tv_sec > b->tv_sec)
138
+		return -1;
139
+
140
+	if (a->tv_sec < b->tv_sec)
141
+		return 1;
142
+
143
+	if (a->tv_usec > b->tv_usec)
144
+		return -1;
145
+
146
+	if (a->tv_usec < b->tv_usec)
147
+		return 1;
148
+
149
+	return 0;
150
+}
151
+
152
+static void schedule_nextrun(struct event_timeout *entry, struct timeval *now)
153
+{
154
+	add_timeval(&entry->nextrun, now, &entry->intervall);
155
+
156
+	struct event_timeout *search;
157
+	list_for_each_entry(search, &event_timeout_list, list) {
158
+		if (search->nextrun.tv_sec > entry->nextrun.tv_sec) {
159
+			list_add_tail(&entry->list, &search->list);
160
+			return;
161
+
162
+		} else if (search->nextrun.tv_sec == entry->nextrun.tv_sec &&
163
+			   search->nextrun.tv_usec > entry->nextrun.tv_usec) {
164
+				list_add_tail(&entry->list, &search->list);
165
+				return;
166
+		}
167
+	}
168
+	list_add_tail(&entry->list, &event_timeout_list);
169
+}
170
+
171
+struct event_timeout * event_add_timeout(
172
+			struct timeval *timeout,
173
+			int (*callback)(void *privdata),
174
+			void *privdata)
175
+{
176
+	struct event_timeout *entry;
177
+	entry = malloc(sizeof(struct event_timeout));
178
+	if (entry == NULL) {
179
+		log_print(LOG_ERROR, "event_add_timeout(): out of memory");
180
+		return NULL;
181
+	}
182
+
183
+	entry->flags = 0;
184
+	memcpy(&entry->intervall, timeout, sizeof(entry->intervall));
185
+	entry->callback = callback;
186
+	entry->privdata = privdata;
187
+
188
+	struct timeval now;
189
+	gettimeofday(&now, NULL);
190
+
191
+	schedule_nextrun(entry, &now);
192
+	return entry;
193
+}
194
+
195
+void event_remove_timeout(struct event_timeout *entry)
196
+{
197
+	/* mark the event as deleted -> remove in select() loop */
198
+	entry->flags |= EVENT_DELETE;
199
+}
200
+
201
+int event_loop(void)
202
+{
203
+	fd_set *fdsets = malloc(sizeof(fd_set) * 2);
204
+	if (fdsets == NULL) {
205
+		log_print(LOG_ERROR, "event_loop(): out of memory");
206
+		return -1;
207
+	}
208
+
209
+	while (1) {
210
+		struct timeval timeout, *timeout_p = NULL;
211
+		if (!list_empty(&event_timeout_list)) {
212
+			struct timeval now;
213
+			gettimeofday(&now, NULL);
214
+
215
+			struct event_timeout *entry, *tmp;
216
+			list_for_each_entry_safe(entry, tmp, &event_timeout_list, list) {
217
+				if (entry->flags & EVENT_DELETE) {
218
+					list_del(&entry->list);
219
+					free(entry);
220
+					continue;
221
+				}
222
+
223
+				/* first timeout not elapsed, exit search (since list is sorted) */
224
+				if (cmp_timeval(&entry->nextrun, &now) == -1)
225
+					break;
226
+
227
+				/* remove event from list */
228
+				list_del(&entry->list);
229
+
230
+				/* execute callback, when callback returns 0 -> schedule event again */
231
+				if (entry->callback(entry->privdata)) {
232
+					free(entry);
233
+
234
+				} else {
235
+					schedule_nextrun(entry, &now);
236
+				}
237
+			}
238
+
239
+			if (!list_empty(&event_timeout_list)) {
240
+				entry = list_entry(event_timeout_list.next, typeof(*entry), list);
241
+
242
+				/* calc select() timeout */
243
+				sub_timeval(&timeout, &entry->nextrun, &now);
244
+				timeout_p = &timeout;
245
+			}
246
+		}
247
+
248
+		fd_set *readfds = NULL, *writefds = NULL;
249
+		struct event_fd *entry, *tmp;
250
+
251
+		list_for_each_entry_safe(entry, tmp, &event_fd_list, list) {
252
+			entry->flags &= ~EVENT_NEW;
253
+
254
+			if (entry->flags & EVENT_DELETE) {
255
+				list_del(&entry->list);
256
+				free(entry);
257
+				continue;
258
+			}
259
+
260
+			if (entry->flags & FD_READ) {
261
+				if (readfds == NULL) {
262
+					readfds = &fdsets[0];
263
+					FD_ZERO(readfds);
264
+				}
265
+				FD_SET(entry->fd, readfds);
266
+			}
267
+
268
+			if (entry->flags & FD_WRITE) {
269
+				if (writefds == NULL) {
270
+					writefds = &fdsets[1];
271
+					FD_ZERO(writefds);
272
+				}
273
+				FD_SET(entry->fd, writefds);
274
+			}
275
+		}
276
+
277
+		int i = select(FD_SETSIZE, readfds, writefds, NULL, timeout_p);
278
+		if (i <= 0) {
279
+			/* On error, -1 is returned, and errno is set
280
+			 * appropriately; the sets and timeout become
281
+			 * undefined, so do not rely on their contents
282
+			 * after an error.
283
+			 */
284
+			continue;
285
+		}
286
+
287
+		list_for_each_entry(entry, &event_fd_list, list) {
288
+			if (((entry->flags & (FD_READ | EVENT_NEW)) == FD_READ) && FD_ISSET(entry->fd, readfds))
289
+				if (entry->read_cb(entry->fd, entry->read_priv) != 0)
290
+					entry->flags |= EVENT_DELETE;
291
+
292
+			if (((entry->flags & (FD_WRITE | EVENT_NEW)) == FD_WRITE) && FD_ISSET(entry->fd, writefds))
293
+				if (entry->write_cb(entry->fd, entry->write_priv) != 0)
294
+					entry->flags |= EVENT_DELETE;
295
+		}
296
+	}
297
+	free(fdsets);
298
+}

+ 42
- 0
daemon/event.h View File

@@ -0,0 +1,42 @@
1
+#ifndef _EVENT_H_
2
+#define _EVENT_H_
3
+
4
+#include <sys/time.h>
5
+
6
+#define EVENT_NEW	0x1000
7
+#define EVENT_DELETE	0x2000
8
+
9
+#define FD_READ		0x0001
10
+#define FD_WRITE	0x0002
11
+#define FD_TYPES	(FD_READ | FD_WRITE)
12
+
13
+#define event_add_readfd(entry, fd, callback, privdata) \
14
+	event_add_fd(entry, fd, FD_READ, callback, privdata)
15
+
16
+#define event_add_writefd(entry, fd, callback, privdata) \
17
+	event_add_fd(entry, fd, FD_WRITE, callback, privdata)
18
+
19
+/* inner details are not visible to external users (TODO: size unknown) */
20
+struct event_fd;
21
+struct event_timeout;
22
+
23
+struct event_fd * event_add_fd(
24
+			struct event_fd *entry,
25
+			int fd,
26
+			int type,
27
+			int (*callback)(int fd, void *privdata),
28
+			void *privdata);
29
+
30
+int event_get_fd(struct event_fd *entry);
31
+void event_remove_fd(struct event_fd *entry);
32
+
33
+struct event_timeout * event_add_timeout(
34
+			struct timeval *timeout,
35
+			int (*callback)(void *privdata),
36
+			void *privdata);
37
+
38
+void event_remove_timeout(struct event_timeout *entry);
39
+
40
+int event_loop(void);
41
+
42
+#endif /* _EVENT_H_ */

Host/i2c-dev.h → daemon/i2c-dev.h View File


+ 268
- 0
daemon/list.h View File

@@ -0,0 +1,268 @@
1
+#ifndef _LIST_H_
2
+#define _LIST_H_
3
+
4
+/*
5
+ * stolen from linux kernel 2.6.11 (http://kernel.org/)
6
+ * linux/include/linux/stddef.h (offsetoff)
7
+ * linux/include/linux/kernel.h (container_of)
8
+ * linux/include/linux/list.h (*list*)
9
+ * linux/include/linux/netfilter_ipv4/listhelp.h (LIST_FIND)
10
+ *
11
+ * modified by Olaf Rempel <razzor@kopf-tisch.de>
12
+ */
13
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
14
+
15
+#define container_of(ptr, type, member) ({ \
16
+		const typeof( ((type *)0)->member ) *__mptr = (ptr); \
17
+		(type *)( (char *)__mptr - offsetof(type,member) );})
18
+
19
+struct list_head {
20
+	struct list_head *next, *prev;
21
+};
22
+
23
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
24
+
25
+#define LIST_HEAD(name) \
26
+	struct list_head name = LIST_HEAD_INIT(name)
27
+
28
+#define INIT_LIST_HEAD(ptr) do { \
29
+	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
30
+} while (0)
31
+
32
+/*
33
+ * Insert a new entry between two known consecutive entries.
34
+ *
35
+ * This is only for internal list manipulation where we know
36
+ * the prev/next entries already!
37
+ */
38
+static inline void __list_add(struct list_head *new,
39
+			      struct list_head *prev,
40
+			      struct list_head *next)
41
+{
42
+	next->prev = new;
43
+	new->next = next;
44
+	new->prev = prev;
45
+	prev->next = new;
46
+}
47
+
48
+/*
49
+ * list_add - add a new entry
50
+ * @new: new entry to be added
51
+ * @head: list head to add it after
52
+ *
53
+ * Insert a new entry after the specified head.
54
+ * This is good for implementing stacks.
55
+ */
56
+static inline void list_add(struct list_head *new, struct list_head *head)
57
+{
58
+	__list_add(new, head, head->next);
59
+}
60
+
61
+/*
62
+ * list_add_tail - add a new entry
63
+ * @new: new entry to be added
64
+ * @head: list head to add it before
65
+ *
66
+ * Insert a new entry before the specified head.
67
+ * This is useful for implementing queues.
68
+ */
69
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
70
+{
71
+	__list_add(new, head->prev, head);
72
+}
73
+
74
+/*
75
+ * Delete a list entry by making the prev/next entries
76
+ * point to each other.
77
+ *
78
+ * This is only for internal list manipulation where we know
79
+ * the prev/next entries already!
80
+ */
81
+static inline void __list_del(struct list_head * prev, struct list_head * next)
82
+{
83
+	next->prev = prev;
84
+	prev->next = next;
85
+}
86
+
87
+/*
88
+ * list_del - deletes entry from list.
89
+ * @entry: the element to delete from the list.
90
+ * Note: list_empty on entry does not return true after this, the entry is
91
+ * in an undefined state.
92
+ */
93
+static inline void list_del(struct list_head *entry)
94
+{
95
+	__list_del(entry->prev, entry->next);
96
+	entry->next = NULL;
97
+	entry->prev = NULL;
98
+}
99
+
100
+/*
101
+ * list_del_init - deletes entry from list and reinitialize it.
102
+ * entry: the element to delete from the list.
103
+ */
104
+static inline void list_del_init(struct list_head *entry)
105
+{
106
+	__list_del(entry->prev, entry->next);
107
+	INIT_LIST_HEAD(entry);
108
+}
109
+
110
+/*
111
+ * list_move - delete from one list and add as another's head
112
+ * @list: the entry to move
113
+ * @head: the head that will precede our entry
114
+ */
115
+static inline void list_move(struct list_head *list, struct list_head *head)
116
+{
117
+        __list_del(list->prev, list->next);
118
+        list_add(list, head);
119
+}
120
+
121
+/*
122
+ * list_move_tail - delete from one list and add as another's tail
123
+ * @list: the entry to move
124
+ * @head: the head that will follow our entry
125
+ */
126
+static inline void list_move_tail(struct list_head *list,
127
+				  struct list_head *head)
128
+{
129
+        __list_del(list->prev, list->next);
130
+        list_add_tail(list, head);
131
+}
132
+
133
+/*
134
+ * list_empty - tests whether a list is empty
135
+ * @head: the list to test.
136
+ */
137
+static inline int list_empty(const struct list_head *head)
138
+{
139
+	return head->next == head;
140
+}
141
+
142
+static inline void __list_splice(struct list_head *list,
143
+				 struct list_head *head)
144
+{
145
+	struct list_head *first = list->next;
146
+	struct list_head *last = list->prev;
147
+	struct list_head *at = head->next;
148
+
149
+	first->prev = head;
150
+	head->next = first;
151
+
152
+	last->next = at;
153
+	at->prev = last;
154
+}
155
+
156
+/*
157
+ * list_splice - join two lists
158
+ * @list: the new list to add.
159
+ * @head: the place to add it in the first list.
160
+ */
161
+static inline void list_splice(struct list_head *list, struct list_head *head)
162
+{
163
+	if (!list_empty(list))
164
+		__list_splice(list, head);
165
+}
166
+
167
+/*
168
+ * list_splice_init - join two lists and reinitialise the emptied list.
169
+ * @list: the new list to add.
170
+ * @head: the place to add it in the first list.
171
+ *
172
+ * The list at @list is reinitialised
173
+ */
174
+static inline void list_splice_init(struct list_head *list,
175
+				    struct list_head *head)
176
+{
177
+	if (!list_empty(list)) {
178
+		__list_splice(list, head);
179
+		INIT_LIST_HEAD(list);
180
+	}
181
+}
182
+
183
+/*
184
+ * list_entry - get the struct for this entry
185
+ * @ptr:	the &struct list_head pointer.
186
+ * @type:	the type of the struct this is embedded in.
187
+ * @member:	the name of the list_struct within the struct.
188
+ */
189
+#define list_entry(ptr, type, member) \
190
+	container_of(ptr, type, member)
191
+
192
+/*
193
+ * list_for_each	-	iterate over a list
194
+ * @pos:	the &struct list_head to use as a loop counter.
195
+ * @head:	the head for your list.
196
+ */
197
+#define list_for_each(pos, head) \
198
+	for (pos = (head)->next; pos != (head); pos = pos->next)
199
+
200
+/*
201
+ * list_for_each_prev	-	iterate over a list backwards
202
+ * @pos:	the &struct list_head to use as a loop counter.
203
+ * @head:	the head for your list.
204
+ */
205
+#define list_for_each_prev(pos, head) \
206
+	for (pos = (head)->prev; pos != (head); pos = pos->prev)
207
+
208
+/*
209
+ * list_for_each_safe	-	iterate over a list safe against removal of list entry
210
+ * @pos:	the &struct list_head to use as a loop counter.
211
+ * @n:		another &struct list_head to use as temporary storage
212
+ * @head:	the head for your list.
213
+ */
214
+#define list_for_each_safe(pos, n, head) \
215
+	for (pos = (head)->next, n = pos->next; pos != (head); \
216
+		pos = n, n = pos->next)
217
+
218
+/*
219
+ * list_for_each_entry	-	iterate over list of given type
220
+ * @pos:	the type * to use as a loop counter.
221
+ * @head:	the head for your list.
222
+ * @member:	the name of the list_struct within the struct.
223
+ */
224
+#define list_for_each_entry(pos, head, member)				\
225
+	for (pos = list_entry((head)->next, typeof(*pos), member);	\
226
+	     &pos->member != (head); 					\
227
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
228
+
229
+/*
230
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
231
+ * @pos:	the type * to use as a loop counter.
232
+ * @head:	the head for your list.
233
+ * @member:	the name of the list_struct within the struct.
234
+ */
235
+#define list_for_each_entry_reverse(pos, head, member)			\
236
+	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
237
+	     &pos->member != (head); 					\
238
+	     pos = list_entry(pos->member.prev, typeof(*pos), member))
239
+
240
+/*
241
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
242
+ * @pos:	the type * to use as a loop counter.
243
+ * @n:		another type * to use as temporary storage
244
+ * @head:	the head for your list.
245
+ * @member:	the name of the list_struct within the struct.
246
+ */
247
+#define list_for_each_entry_safe(pos, n, head, member)			\
248
+	for (pos = list_entry((head)->next, typeof(*pos), member),	\
249
+		n = list_entry(pos->member.next, typeof(*pos), member);	\
250
+	     &pos->member != (head); 					\
251
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
252
+
253
+
254
+/* Return pointer to first true entry, if any, or NULL.  A macro
255
+   required to allow inlining of cmpfn. */
256
+#define LIST_FIND(head, cmpfn, type, args...)           \
257
+({                                                      \
258
+        const struct list_head *__i, *__j = NULL;       \
259
+                                                        \
260
+        list_for_each(__i, (head))                      \
261
+                if (cmpfn((const type)__i , ## args)) { \
262
+                        __j = __i;                      \
263
+                        break;                          \
264
+                }                                       \
265
+        (type)__j;                                      \
266
+})
267
+
268
+#endif /* _LIST_H_ */

+ 101
- 0
daemon/logging.c View File

@@ -0,0 +1,101 @@
1
+/***************************************************************************
2
+ *   Copyright (C) 07/2007 by Olaf Rempel                                  *
3
+ *   razzor@kopf-tisch.de                                                  *
4
+ *                                                                         *
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; version 2 of the License                *
8
+ *                                                                         *
9
+ *   This program is distributed in the hope that it will be useful,       *
10
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12
+ *   GNU General Public License for more details.                          *
13
+ *                                                                         *
14
+ *   You should have received a copy of the GNU General Public License     *
15
+ *   along with this program; if not, write to the                         *
16
+ *   Free Software Foundation, Inc.,                                       *
17
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18
+ ***************************************************************************/
19
+#include <stdio.h>
20
+#include <stdlib.h>
21
+#include <time.h>
22
+#include <stdarg.h>
23
+#include <errno.h>
24
+#include <string.h>
25
+
26
+#include "logging.h"
27
+
28
+#define BUFSIZE 8192
29
+
30
+static FILE *log_fd = NULL;
31
+static int log_prio = LOG_EVERYTIME;
32
+static char *buffer = NULL;
33
+
34
+int log_print(int prio, const char *fmt, ...)
35
+{
36
+	va_list az;
37
+	int len = 0, retval;
38
+
39
+	if (prio < log_prio)
40
+		return 0;
41
+
42
+	if (buffer == NULL) {
43
+		buffer = malloc(BUFSIZE);
44
+		if (buffer == NULL) {
45
+			fprintf(stderr, "log_print(): out of memory\n");
46
+			return -1;
47
+		}
48
+	}
49
+
50
+	if (log_fd != NULL) {
51
+		time_t  tzgr;
52
+		time(&tzgr);
53
+
54
+		len += strftime(buffer, BUFSIZE, "%b %d %H:%M:%S :", localtime(&tzgr));
55
+	}
56
+
57
+	va_start(az, fmt);
58
+	len += vsnprintf(buffer + len, BUFSIZE - len, fmt, az);
59
+	va_end(az);
60
+
61
+	if (len < 0 || len >= BUFSIZE) {
62
+		errno = 0;
63
+		return log_print(LOG_ERROR, "log_print: arguments too long");
64
+	}
65
+
66
+	if (errno) {
67
+		len += snprintf(buffer + len, BUFSIZE - len, ": %s", strerror(errno));
68
+		errno = 0;
69
+	}
70
+
71
+	retval = fprintf((log_fd ? log_fd : stderr), "%s\n", buffer);
72
+	fflush(log_fd);
73
+	return retval;
74
+}
75
+
76
+void log_close(void)
77
+{
78
+	if (buffer)
79
+		free(buffer);
80
+
81
+	if (log_fd)
82
+		fclose(log_fd);
83
+}
84
+
85
+int log_init(const char *logfile)
86
+{
87
+	if (log_fd != NULL)
88
+		log_close();
89
+
90
+	log_fd = fopen(logfile, "a");
91
+	if (log_fd == NULL) {
92
+		fprintf(stderr, "log_init(): can not open logfile");
93
+		return -1;
94
+	}
95
+	return 0;
96
+}
97
+
98
+void log_setprio(int prio)
99
+{
100
+	log_prio = prio;
101
+}

+ 19
- 0
daemon/logging.h View File

@@ -0,0 +1,19 @@
1
+#ifndef _LOGGING_H_
2
+#define _LOGGING_H_
3
+
4
+#define LOG_DEBUG 5
5
+#define LOG_INFO  4
6
+#define LOG_NOTICE 3
7
+#define LOG_WARN 2
8
+#define LOG_ERROR 1
9
+#define LOG_CRIT 0
10
+
11
+#define LOG_EVERYTIME 0
12
+
13
+int log_init(const char *logfile);
14
+void log_close(void);
15
+void log_setprio(int prio);
16
+
17
+int log_print(int prio, const char *fmt, ... );
18
+
19
+#endif /* _LOGGING_H_ */

+ 80
- 0
daemon/unixsocket.c View File

@@ -0,0 +1,80 @@
1
+/***************************************************************************
2
+ *   Copyright (C) 07/2007 by Olaf Rempel                                  *
3
+ *   razzor@kopf-tisch.de                                                  *
4
+ *                                                                         *
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; version 2 of the License                *
8
+ *                                                                         *
9
+ *   This program is distributed in the hope that it will be useful,       *
10
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12
+ *   GNU General Public License for more details.                          *
13
+ *                                                                         *
14
+ *   You should have received a copy of the GNU General Public License     *
15
+ *   along with this program; if not, write to the                         *
16
+ *   Free Software Foundation, Inc.,                                       *
17
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18
+ ***************************************************************************/
19
+#include <unistd.h>
20
+#include <string.h>
21
+#include <sys/types.h>
22
+#include <sys/socket.h>
23
+#include <sys/un.h>
24
+#include <sys/stat.h>
25
+
26
+#include "logging.h"
27
+
28
+int unix_listen(const char *filename)
29
+{
30
+	int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
31
+	if (sockfd == -1) {
32
+		log_print(LOG_ERROR, "unix_listen: socket()");
33
+		return -1;
34
+	}
35
+
36
+	struct sockaddr_un addr;
37
+	addr.sun_family = AF_UNIX;
38
+	strncpy(addr.sun_path, filename, sizeof(addr.sun_path));
39
+	int len = sizeof(addr.sun_family) + strlen(addr.sun_path);
40
+
41
+	mode_t old_umask = umask(0077);
42
+	int ret = bind(sockfd, (struct sockaddr *) &addr, len);
43
+	umask(old_umask);
44
+
45
+	if (ret == -1) {
46
+		log_print(LOG_ERROR, "unix_listen: bind(%s)", filename);
47
+		close(sockfd);
48
+		return -1;
49
+	}
50
+
51
+	if (listen(sockfd, 5) == -1) {
52
+		log_print(LOG_ERROR, "unix_listen: listen()");
53
+		close(sockfd);
54
+		return -1;
55
+	}
56
+
57
+	return sockfd;
58
+}
59
+
60
+int unix_connect(const char *filename)
61
+{
62
+	int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
63
+	if (sockfd == -1) {
64
+		log_print(LOG_ERROR, "unix_connect: socket()");
65
+		return -1;
66
+	}
67
+
68
+	struct sockaddr_un addr;
69
+	addr.sun_family = AF_UNIX;
70
+	strncpy(addr.sun_path, filename, sizeof(addr.sun_path));
71
+	int len = sizeof(addr.sun_family) + strlen(addr.sun_path);
72
+
73
+	if (connect(sockfd, (struct sockaddr *)&addr, len) < 0) {
74
+		log_print(LOG_ERROR, "unix_connect: connect(%s)", filename);
75
+		close(sockfd);
76
+		return -1;
77
+	}
78
+
79
+	return sockfd;
80
+}

+ 7
- 0
daemon/unixsocket.h View File

@@ -0,0 +1,7 @@
1
+#ifndef _UNIXSOCKET_H_
2
+#define _UNIXSOCKET_H_
3
+
4
+int unix_listen(const char *filename);
5
+int unix_connect(const char *filename);
6
+
7
+#endif // _UNIXSOCKET_H_

Loading…
Cancel
Save