Browse code

- removed implementation of fifo and unixsocket servers from core (it will be implemented in modules instead)

Jan Janak authored on 21/12/2005 17:27:21
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,1032 +0,0 @@
1
-/*
2
- * $Id$
3
- *
4
- * UNIX Domain Socket Server
5
- *
6
- * Copyright (C) 2001-2004 FhG Fokus
7
- *
8
- * This file is part of ser, a free SIP server.
9
- *
10
- * ser is free software; you can redistribute it and/or modify
11
- * it under the terms of the GNU General Public License as published by
12
- * the Free Software Foundation; either version 2 of the License, or
13
- * (at your option) any later version
14
- *
15
- * For a license to use the ser software under conditions
16
- * other than those described here, or to purchase support for this
17
- * software, please contact iptel.org by e-mail at the following addresses:
18
- *    info@iptel.org
19
- *
20
- * ser is distributed in the hope that it will be useful,
21
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
- * GNU General Public License for more details.
24
- *
25
- * You should have received a copy of the GNU General Public License 
26
- * along with this program; if not, write to the Free Software 
27
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28
- */
29
-/* History:
30
- *              created by janakj
31
- *  2004-03-03  added tcp init code (andrei)
32
- *  2004-04-29  added chmod(sock_perm) & chown(sock_user,sock_group)  (andrei)
33
- */
34
-
35
-#include <unistd.h>
36
-#include <errno.h>
37
-#include <string.h>
38
-#include <sys/types.h>
39
-#include <sys/socket.h>
40
-#include <sys/stat.h>
41
-#include <signal.h>
42
-#include <stdarg.h>
43
-#include <time.h>
44
-#include <fcntl.h>
45
-#include "config.h"
46
-#include "ut.h"
47
-#include "globals.h"
48
-#include "trim.h"
49
-#include "pt.h"
50
-#include "sr_module.h"
51
-#include "mem/mem.h"
52
-#include "fifo_server.h" /* CMD_SEPARATOR */
53
-#include "unixsock_server.h"
54
-#include "tsend.h"
55
-
56
-
57
-/* AF_LOCAL is not defined on solaris */
58
-#if !defined(AF_LOCAL)
59
-#define AF_LOCAL AF_UNIX
60
-#endif
61
-#if !defined(PF_LOCAL)
62
-#define PF_LOCAL PF_UNIX
63
-#endif
64
-
65
-
66
-/* solaris doesn't have SUN_LEN */
67
-#ifndef SUN_LEN
68
-#define SUN_LEN(sa)	 ( strlen((sa)->sun_path) + \
69
-					 (size_t)(((struct sockaddr_un*)0)->sun_path) )
70
-#endif
71
-
72
-
73
-#define UNIXSOCK_BUF_SIZE BUF_SIZE
74
-
75
-char* unixsock_name = 0;
76
-int unixsock_children = 1;
77
-int unixsock_tx_timeout = 2000; /* Timeout for sending replies in milliseconds */
78
-
79
-
80
-static int rx_sock, tx_sock;
81
-static struct unixsock_cmd* cmd_list = 0;
82
-static char reply_buf[UNIXSOCK_BUF_SIZE];
83
-static str reply_pos;
84
-static struct sockaddr_un reply_addr;
85
-static unsigned int reply_addr_len;
86
-
87
-static time_t up_since;
88
-static char up_since_ctime[MAX_CTIME_LEN];
89
-
90
-
91
-#define PRINT_CMD "print"     /* Diagnostic command */
92
-#define VERSION_CMD "version" /* Print the version of the server */
93
-#define UPTIME_CMD "uptime"   /* Print server's uptime */
94
-#define WHICH_CMD "which"     /* Print available FIFO commands */
95
-#define PS_CMD "ps"           /* Print server's process table */
96
-#define ARG_CMD "arg"         /* Print server's command line arguments */
97
-#define PWD_CMD "pwd"         /* Get the current working directory */
98
-#define KILL_CMD "kill"       /* Kill the server */
99
-
100
-
101
-/* 
102
- * Diagnostic and hello-world command 
103
- */
104
-static int print_cmd(str* msg)
105
-{
106
-	str line;
107
-	int ret;
108
-
109
-	ret = 0;
110
-
111
-	if (unixsock_read_line(&line, msg) < 0) {
112
-		unixsock_reply_asciiz("500 Error while reading text\n");
113
-		ret = -1;
114
-		goto end;
115
-	}
116
-
117
-	if (unixsock_reply_printf("200 OK\n%.*s\n", line.len, ZSW(line.s)) < 0) {
118
-		unixsock_reply_reset();
119
-		unixsock_reply_asciiz("500 Error while sending reply\n");
120
-		ret = -1;
121
-	}
122
-
123
- end:
124
-	if (unixsock_reply_send() < 0) ret = -1;
125
-	return ret;
126
-}
127
-
128
-
129
-/*
130
- * Print the version of the server
131
- */
132
-static int version_cmd(str* msg)
133
-{
134
-	int ret;
135
-
136
-	ret = 0;
137
-	if (unixsock_reply_asciiz("200 OK\n" SERVER_HDR CRLF) < 0) ret = -1;
138
-	if (unixsock_reply_send() < 0) ret = -1;
139
-	return ret;
140
-}
141
-
142
-
143
-static int uptime_cmd(str* msg)
144
-{
145
-	time_t now;
146
-	int ret;
147
-
148
-	time(&now);
149
-	ret = 0;
150
-	
151
-	if (unixsock_reply_printf("200 OK\nNow: %sUp Since: %sUp time: %.0f [sec]\n",
152
-				  ctime(&now), up_since_ctime, difftime(now, up_since)) < 0) {
153
-		unixsock_reply_reset();
154
-		unixsock_reply_asciiz("500 Error while printing reply\n");
155
-		ret = -1;
156
-	}
157
-	
158
-	if (unixsock_reply_send() < 0) {
159
-		ret = -1;
160
-	}
161
-	
162
-	return ret;
163
-}
164
-
165
-
166
-static int which_cmd(str* msg)
167
-{
168
-	struct unixsock_cmd* c;
169
-	int ret;
170
-
171
-	ret = 0;
172
-	unixsock_reply_asciiz("200 OK\n");
173
-
174
-	for(c = cmd_list; c; c = c->next) {
175
-		if (unixsock_reply_printf("%s\n", c->name) < 0) {
176
-			unixsock_reply_reset();
177
-			unixsock_reply_asciiz("500 Error while creating reply\n");
178
-			ret = -1;
179
-			break;
180
-		}
181
-	}
182
-	
183
-	if (unixsock_reply_send() < 0) {
184
-		ret = -1;
185
-	}
186
-	return ret;
187
-}
188
-
189
-
190
-static int ps_cmd(str* msg)
191
-{
192
-	int p, ret;
193
-
194
-	ret = 0;
195
-	unixsock_reply_asciiz("200 OK\n");
196
-	for (p = 0; p < process_count; p++) {
197
-		if (unixsock_reply_printf("%d\t%d\t%s\n", p, pt[p].pid, pt[p].desc) < 0) {
198
-			unixsock_reply_reset();
199
-			unixsock_reply_asciiz("500 Error while printing reply\n");
200
-			ret = -1;
201
-			break;
202
-		}
203
-	}
204
-	
205
-	if (unixsock_reply_send() < 0) {
206
-		ret = -1;
207
-	}
208
-	return ret;
209
-}
210
-
211
-
212
-static int pwd_cmd(str* msg)
213
-{
214
-	char *cwd_buf;
215
-	int max_len, ret;
216
-
217
-	max_len = pathmax();
218
-	cwd_buf = pkg_malloc(max_len);
219
-	ret = 0;
220
-	if (!cwd_buf) {
221
-		LOG(L_ERR, "pwd_cmd: No memory left\n");
222
-		unixsock_reply_asciiz("500 No Memory Left\n");
223
-		ret = -1;
224
-	}
225
-
226
-	if (getcwd(cwd_buf, max_len)) {
227
-		if (unixsock_reply_printf("200 OK\n%s\n", cwd_buf) < 0) {
228
-			unixsock_reply_reset();
229
-			unixsock_reply_asciiz("500 Error while sending reply\n");
230
-			ret = -1;
231
-		}
232
-	} else {
233
-		unixsock_reply_asciiz("500 getcwd Failed\n");
234
-		ret = -1;
235
-	}
236
-
237
-	pkg_free(cwd_buf);
238
-	if (unixsock_reply_send() < 0) {
239
-		ret = -1;
240
-	}
241
-	return ret;
242
-}
243
-
244
-
245
-static int arg_cmd(str* msg)
246
-{
247
-	int p, ret;
248
-
249
-	ret = 0;
250
-	unixsock_reply_asciiz("200 OK\n");
251
-	for (p = 0; p < my_argc; p++) {
252
-		if (unixsock_reply_printf("%s\n", my_argv[p]) < 0) {
253
-			unixsock_reply_reset();
254
-			unixsock_reply_asciiz("500 Could not create reply\n");
255
-			ret = -1;
256
-			break;
257
-		}
258
-	}
259
-			
260
-	if (unixsock_reply_send() < 0) {
261
-		ret = -1;
262
-	}
263
-	return ret;
264
-}
265
-
266
-
267
-static int kill_cmd(str* msg)
268
-{
269
-	unixsock_reply_asciiz("200 Killing now\n");
270
-	unixsock_reply_send();
271
-	kill(0, SIGTERM);
272
-	return 0;
273
-}
274
-
275
-
276
-static int register_core_commands(void)
277
-{
278
-	if (unixsock_register_cmd(PRINT_CMD, print_cmd) < 0) {
279
-		return -1;
280
-	}
281
-
282
-	if (unixsock_register_cmd(VERSION_CMD, version_cmd) < 0) {
283
-		return -1;
284
-	}
285
-
286
-	if (unixsock_register_cmd(UPTIME_CMD, uptime_cmd) < 0) {
287
-		return -1;
288
-	}
289
-
290
-	if (unixsock_register_cmd(WHICH_CMD, which_cmd) < 0) {
291
-		return -1;
292
-	}
293
-
294
-	if (unixsock_register_cmd(PS_CMD, ps_cmd) < 0) {
295
-		return -1;
296
-	}
297
-
298
-	if (unixsock_register_cmd(PWD_CMD, pwd_cmd) < 0) {
299
-		return -1;
300
-	}
301
-
302
-	if (unixsock_register_cmd(ARG_CMD, arg_cmd) < 0) {
303
-		return -1;
304
-	}
305
-
306
-	if (unixsock_register_cmd(KILL_CMD, kill_cmd) < 0) {
307
-		return -1;
308
-	}
309
-	return 0;
310
-}
311
-
312
-
313
-/*
314
- * Create and bind local socket
315
- */
316
-int init_unixsock_socket(void)
317
-{
318
-	struct sockaddr_un addr;
319
-	int len, flags;
320
-
321
-	if (unixsock_name == 0) {
322
-		DBG("init_unixsock_socket: No unix domain socket"
323
-		    " will be opened\n");
324
-		return 1;
325
-	}
326
-
327
-	len = strlen(unixsock_name);
328
-	if (len == 0) {
329
-		DBG("init_unixsock_socket: Unix domain socket server disabled\n");
330
-		return 1;
331
-	} else if (len > 107) {
332
-		LOG(L_ERR, "ERROR: init_unixsock_socket: Socket name too long\n");
333
-		return -1;
334
-	}
335
-
336
-	DBG("init_unixsock_socket: Initializing Unix domain socket server @ %s\n", 
337
-	    unixsock_name);
338
-
339
-	if (unlink(unixsock_name) == -1) {
340
-		if (errno != ENOENT) {
341
-			LOG(L_ERR, "ERROR: init_unixsock_socket: Error while unlinking "
342
-			    "old socket (%s): %s\n", unixsock_name, strerror(errno));
343
-			return -1;
344
-		}
345
-	}
346
-
347
-	rx_sock = socket(PF_LOCAL, SOCK_DGRAM, 0);
348
-	if (rx_sock == -1) {
349
-		LOG(L_ERR, "ERROR: init_unixsock_socket: Cannot create RX "
350
-				"socket: %s\n", strerror(errno));
351
-		return -1;
352
-	}
353
-
354
-	memset(&addr, 0, sizeof(addr));
355
-	addr.sun_family = PF_LOCAL;
356
-	memcpy(addr.sun_path, unixsock_name, len);
357
-
358
-	if (bind(rx_sock, (struct sockaddr*)&addr, SUN_LEN(&addr)) == -1) {
359
-		LOG(L_ERR, "ERROR: init_unixsock_socket: bind: %s\n", strerror(errno));
360
-		goto err_rx;
361
-	}
362
-	/* try to change the permissions */
363
-	if (sock_mode){ /* sock_mode==0 doesn't make sense, nobody can read/write*/
364
-		if (chmod(unixsock_name, sock_mode)<0){
365
-			LOG(L_ERR, "ERROR: init_unixsock_socket: failed to change the"
366
-					" permissions for %s to %04o: %s[%d]\n",
367
-					unixsock_name, sock_mode, strerror(errno), errno);
368
-			goto err_rx;
369
-		}
370
-	}
371
-	/* try to change the ownership */
372
-	if ((sock_uid!=-1) || (sock_gid!=-1)){
373
-		if (chown(unixsock_name, sock_uid, sock_gid)<0){
374
-			LOG(L_ERR, "ERROR: init_unixsock_socket: failed to change the"
375
-					" owner/group for %s  to %d.%d; %s[%d]\n",
376
-					unixsock_name, sock_uid, sock_gid, strerror(errno), errno);
377
-			goto err_rx;
378
-		}
379
-	}
380
-
381
-	tx_sock = socket(PF_LOCAL, SOCK_DGRAM, 0);
382
-	if (tx_sock == -1) {
383
-		LOG(L_ERR, "ERROR: init_unixsock_socket: Cannot create TX socket:"
384
-				" %s\n", strerror(errno));
385
-		goto err_rx;
386
-	}
387
-
388
-	     /* Turn non-blocking mode on */
389
-	flags = fcntl(tx_sock, F_GETFL);
390
-	if (flags == -1){
391
-		LOG(L_ERR, "ERROR: init_unixsock_socket: fcntl failed: %s\n",
392
-		    strerror(errno));
393
-		goto err_both;
394
-	}
395
-		
396
-	if (fcntl(tx_sock, F_SETFL, flags | O_NONBLOCK) == -1) {
397
-		LOG(L_ERR, "ERROR: init_unixsock_socket: fcntl: "
398
-				"set non-blocking failed: %s\n", strerror(errno));
399
-		goto err_both;
400
-	}
401
-	
402
-	return 1;
403
- err_both:
404
-	close(tx_sock);
405
- err_rx:
406
-	close(rx_sock);
407
-	return -1;
408
-}
409
-
410
-
411
-static struct unixsock_cmd* lookup_cmd(str* cmd)
412
-{
413
-	struct unixsock_cmd* c;
414
-
415
-	for(c = cmd_list; c; c = c->next) {
416
-		if ((cmd->len == c->name.len) &&
417
-		    (strncasecmp(c->name.s, cmd->s, cmd->len) == 0)) {
418
-			return c;
419
-		}
420
-	}
421
-	return 0;
422
-}
423
-
424
-
425
-static int parse_cmd(str* res, str* buffer)
426
-{
427
-	char* cmd_end;
428
-
429
-	if (!res || !buffer) {
430
-		LOG(L_ERR, "parse_cmd: Invalid parameter value\n");
431
-		return -1;
432
-	}
433
-
434
-	if (buffer->len < 3) {
435
-		LOG(L_ERR, "parse_cmd: Message too short\n");
436
-		return -1;
437
-	}
438
-
439
-	if (buffer->s[0] != CMD_SEPARATOR) {
440
-		LOG(L_ERR, "parse_cmd: Command must start with %c\n", 
441
-		    CMD_SEPARATOR);
442
-		return -1;
443
-	}
444
-	
445
-	cmd_end = q_memchr(buffer->s + 1, CMD_SEPARATOR, buffer->len - 1);
446
-	if (!cmd_end) {
447
-		LOG(L_ERR, "parse_cmd: Closing '%c' missing\n", CMD_SEPARATOR);
448
-		return -1;
449
-	}
450
-
451
-	res->s = buffer->s + 1;
452
-	res->len = cmd_end - res->s;
453
-	return 0;
454
-} 
455
-
456
-
457
-static void skip_line(str* buffer)
458
-{
459
-	if (!buffer) return;
460
-
461
-	     /* Find \n */
462
-	while (buffer->len && (buffer->s[0] != '\n')) {
463
-		buffer->s++;
464
-		buffer->len--;
465
-	}
466
-
467
-	if (buffer->len) {
468
-		buffer->s++;
469
-		buffer->len--;
470
-	}
471
-
472
-	     /* Skip CR following LF */
473
-	while (buffer->len && (buffer->s[0] == '\r')) {
474
-		buffer->s++;
475
-		buffer->len--;
476
-	}
477
-}
478
-
479
-
480
-static void unix_server_loop(void)
481
-{
482
-	int ret;
483
-	str cmd, buffer;
484
-	static char buf[UNIXSOCK_BUF_SIZE];
485
-	struct unixsock_cmd* c;
486
-
487
-	
488
-	while(1) {
489
-		reply_addr_len = sizeof(reply_addr);
490
-		ret = recvfrom(rx_sock, buf, UNIXSOCK_BUF_SIZE, 0, 
491
-			       (struct sockaddr*)&reply_addr, &reply_addr_len);
492
-		if (ret == -1) {
493
-			LOG(L_ERR, "unix_server_loop: recvfrom: (%d) %s\n", 
494
-			    errno, strerror(errno));
495
-			if ((errno == EINTR) || 
496
-			    (errno == EAGAIN) || 
497
-			    (errno == EWOULDBLOCK) || 
498
-			    (errno == ECONNREFUSED)) {
499
-				DBG("unix_server_loop: Got %d (%s), going on\n",
500
-				    errno, strerror(errno));
501
-				continue;
502
-			}
503
-			LOG(L_CRIT, "BUG: unix_server_loop: unexpected recvfrom error\n");
504
-			continue;
505
-		}
506
-
507
-		buffer.s = buf;
508
-		buffer.len = ret;
509
-		unixsock_reply_reset();
510
-
511
-		if (parse_cmd(&cmd, &buffer) < 0) {
512
-			unixsock_reply_asciiz("400 First line malformed\n");
513
-			unixsock_reply_send();
514
-			continue;
515
-		}
516
-
517
-		buffer.s = cmd.s + cmd.len + 1;
518
-		buffer.len -= cmd.len + 1 + 1;
519
-		skip_line(&buffer); /* Skip the reply filename */
520
-
521
-		c = lookup_cmd(&cmd);
522
-		if (c == 0) {
523
-			LOG(L_ERR, "unix_server_loop: Could not find "
524
-			    "command '%.*s'\n", cmd.len, ZSW(cmd.s));
525
-			unixsock_reply_printf("500 Command %.*s not found\n", cmd.len, ZSW(cmd.s));
526
-			unixsock_reply_send();
527
-			continue;
528
-		}
529
-
530
-		ret = c->f(&buffer);
531
-		if (ret < 0) {
532
-			LOG(L_ERR, "unix_server_loop: Command '%.*s' failed with "
533
-			    "return value %d\n", cmd.len, ZSW(cmd.s), ret);
534
-			     /* Note that we do not send reply here, the 
535
-			      * function is supposed to do so, it knows the 
536
-			      * reason of the failure better than us
537
-			      */
538
-		}
539
-	}
540
-}
541
-
542
-
543
-static int get_uptime(void)
544
-{
545
-	char* t;
546
-
547
-	time(&up_since);
548
-	t = ctime(&up_since);
549
-	if (strlen(t) + 1 >= MAX_CTIME_LEN) {
550
-		LOG(L_ERR, "get_uptime: Too long date %d\n", (int)strlen(t));
551
-		return -1;
552
-	}
553
-	memcpy(up_since_ctime, t, strlen(t) + 1);
554
-	return 0;
555
-}
556
-
557
-
558
-/*
559
- * Spawn listeners
560
- */
561
-int init_unixsock_children(void)
562
-{
563
-	int i;
564
-	pid_t pid;
565
-#ifdef USE_TCP
566
-	int sockfd[2];
567
-#endif
568
-
569
-	if (!unixsock_name || *unixsock_name == '\0') {
570
-		return 1;
571
-	}
572
-
573
-	if (get_uptime() < 0) {
574
-		return -1;
575
-	}
576
-	
577
-        if (register_core_commands() < 0) {
578
-		close(rx_sock);
579
-		close(tx_sock);
580
-		return -1;
581
-	}
582
-
583
-	for(i = 0; i < unixsock_children; i++) {
584
-		process_no++;
585
-#ifdef USE_TCP
586
-		if(!tcp_disable){
587
- 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
588
-				LOG(L_ERR, "ERROR: init_unixsock_server: socketpair"
589
-						" failed: %s\n", strerror(errno));
590
-				return -1;
591
-			}
592
-		}
593
-#endif
594
-		pid = fork();
595
-		if (pid < 0) {
596
-			LOG(L_ERR, "init_unixsock_server: Unable to fork: %s\n",
597
-			    strerror(errno));
598
-			close(rx_sock);
599
-			close(tx_sock);
600
-			return -1;
601
-		} else if (pid == 0) { /* child */
602
-#ifdef USE_TCP
603
-			if (!tcp_disable){
604
-				close(sockfd[0]);
605
-				unix_tcp_sock=sockfd[1];
606
-			}
607
-#endif
608
-			/* record pid twice to avoid the child using it, before
609
-			 * parent gets a chance to set it*/
610
-			pt[process_no].pid=getpid();
611
-			if (init_child(PROC_UNIXSOCK) < 0) {
612
-				LOG(L_ERR, "init_unixsock_server: Error in "
613
-				    "init_child\n");
614
-				close(rx_sock);
615
-				close(tx_sock);
616
-				return -1;
617
-			}
618
-
619
-			unix_server_loop(); /* Never returns */
620
-		}
621
-
622
-		     /* Parent */
623
-		pt[process_no].pid = pid;
624
-		strncpy(pt[process_no].desc, "unix domain socket server", 
625
-			MAX_PT_DESC);
626
-#ifdef USE_TCP
627
-		if (!tcp_disable){
628
-			close(sockfd[1]);
629
-			pt[process_no].unix_sock=sockfd[0];
630
-			pt[process_no].idx=-1; /* this is not a "tcp"
631
-									  process*/
632
-		}
633
-#endif
634
-
635
-	}
636
-
637
-	DBG("init_unixsock_server: Unix domain socket server successfully initialized @ %s\n",
638
-	    unixsock_name);
639
-	return 1;
640
-}
641
-
642
-
643
-/*
644
- * Clean up
645
- */
646
-void close_unixsock_server(void)
647
-{
648
-	struct unixsock_cmd* c;
649
-	close(rx_sock);
650
-	close(tx_sock);
651
-
652
-	while(cmd_list) {
653
-		c = cmd_list;
654
-		cmd_list = cmd_list->next;
655
-		pkg_free(c);
656
-	}
657
-}
658
-
659
-
660
-/*
661
- * Register a new command
662
- */
663
-int unixsock_register_cmd(char* command, unixsock_f* f)
664
-{
665
-	str cmd;
666
-	struct unixsock_cmd* new_cmd;
667
-
668
-	cmd.s = command;
669
-	cmd.len = strlen(command);
670
-
671
-	if (lookup_cmd(&cmd)) {
672
-		LOG(L_ERR, "unixsock_register_cmd: Function already exists\n");
673
-		return -1;
674
-	}
675
-
676
-	new_cmd = pkg_malloc(sizeof(struct unixsock_cmd));
677
-	if (new_cmd == 0) {
678
-		LOG(L_ERR, "register_unixsock_cmd: Out of mem\n");
679
-		return -1;
680
-	}
681
-
682
-	new_cmd->name = cmd;
683
-	new_cmd->f = f;
684
-
685
-	new_cmd->next = cmd_list;
686
-	cmd_list = new_cmd;
687
-	
688
-	DBG("unixsock_register_cmd: New command (%.*s) registered\n", 
689
-	    cmd.len, ZSW(cmd.s));
690
-	return 1;
691
-}
692
-
693
-
694
-int unixsock_add_to_reply(const char* buf, size_t len)
695
-{
696
-	if (reply_pos.len < len) {
697
-		LOG(L_ERR, "unixsock_add_to_reply: Buffer too small\n");
698
-		return -1;
699
-	}
700
-
701
-	memcpy(reply_pos.s, buf, len);
702
-	reply_pos.s += len;
703
-	reply_pos.len -= len;
704
-	return 0;
705
-}
706
-
707
-
708
-/*
709
- * Send a reply
710
- */
711
-ssize_t unixsock_reply_send(void)
712
-{
713
-	return tsend_dgram(tx_sock, 
714
-			   reply_buf, reply_pos.s - reply_buf,
715
-			   (struct sockaddr*)&reply_addr, reply_addr_len, 
716
-			   unixsock_tx_timeout);
717
-}
718
-
719
-
720
-/*
721
- * Send a reply
722
- */
723
-ssize_t unixsock_reply_sendto(struct sockaddr_un* to)
724
-{
725
-	if (!to) {
726
-		LOG(L_ERR, "unixsock_reply_sendto: Invalid parameter value\n");
727
-		return -1;
728
-	}
729
-
730
-	return tsend_dgram(tx_sock, 
731
-			   reply_buf, reply_pos.s - reply_buf, 
732
-			   (struct sockaddr*)to, SUN_LEN(to), 
733
-			   unixsock_tx_timeout);
734
-}
735
-
736
-
737
-/*
738
- * Read a line, the result will be stored in line
739
- * parameter, the data is not copied, it's just
740
- * a pointer to an existing buffer
741
- */
742
-int unixsock_read_line(str* line, str* source)
743
-{
744
-	if (!line || !source) {
745
-		LOG(L_ERR, "unixsock_read_line: Invalid parameter value\n");
746
-		return -1;
747
-	}
748
-
749
-	*line = *source;
750
-	skip_line(source);
751
-	line->len = source->s - line->s;
752
-	trim_trailing(line);
753
-	if (line->len) {
754
-		return 0;
755
-	} else {
756
-		return 1;
757
-	}
758
-}
759
-
760
-
761
-/*
762
- * Read body until the closing .CRLF, no CRLF recovery
763
- * is done so no additional buffer is necessary, body will
764
- * point to an existing buffer
765
- */
766
-int unixsock_read_body(str* body, str* source)
767
-{
768
-	int i, state, last_dot;
769
-
770
-	enum states {
771
-		ST_BEGIN,
772
-		ST_CRLF,
773
-		ST_DATA,
774
-		ST_NEWLINE
775
-	};
776
-
777
-	if (!body || !source) {
778
-		LOG(L_ERR, "unixsock_read_body: Invalid parameter value\n");
779
-		return -1;
780
-	}
781
-
782
-	if (source->len < 2) {
783
-		LOG(L_ERR, "unixsock_read_body: Not enough input data "
784
-		    "(malformed message ?)\n");
785
-		return -1;
786
-	}
787
-
788
-	state = ST_BEGIN;
789
-	body->s = source->s;
790
-	last_dot = 0;
791
-	for(i = 0; i < source->len; i++) {
792
-		switch(state) {
793
-		case ST_BEGIN:
794
-			if (source->s[i] == '.') {
795
-				last_dot = i;
796
-				state = ST_CRLF;
797
-			} else if (source->s[i] == '\n') {
798
-				state = ST_NEWLINE;
799
-			} else {
800
-				state = ST_DATA;
801
-			}
802
-			break;
803
-			
804
-		case ST_CRLF:
805
-			if (source->s[i] == '\n') {
806
-				body->len = last_dot;
807
-				source->s += i + 1;
808
-				source->len -= i + 1;
809
-				return 0;
810
-			} else if (source->s[i] != '\r') {
811
-				state = ST_DATA;
812
-			}
813
-			break;
814
-
815
-		case ST_DATA:
816
-			if (source->s[i] == '\n') {
817
-				state = ST_NEWLINE;
818
-			}
819
-			break;
820
-
821
-		case ST_NEWLINE:
822
-			if (source->s[i] == '.') {
823
-				last_dot = i;
824
-				state = ST_CRLF;
825
-			}
826
-			break;
827
-		}
828
-	}
829
-
830
-	LOG(L_ERR, "unixsock_read_body: Could not find the end of the body\n");
831
-	return -1;
832
-}
833
-
834
-
835
-/*
836
- * Read a set of lines, the functions performs CRLF recovery,
837
- * therefore lineset must point to an additional buffer
838
- * to which the data will be copied. Initial lineset->len contains
839
- * the size of the buffer
840
- */
841
-int unixsock_read_lineset(str* lineset, str* source)
842
-{
843
-	int i, state, len;
844
-
845
-	enum states {
846
-		ST_BEGIN,
847
-		ST_CRLF,
848
-		ST_DATA,
849
-		ST_NEWLINE
850
-	};
851
-
852
-	if (!lineset || !source) {
853
-		LOG(L_ERR, "unixsock_read_lineset: Invalid parameter value\n");
854
-		return -1;
855
-	}
856
-
857
-	if (!lineset->s || !lineset->len) {
858
-		LOG(L_ERR, "unixsock_read_lineset: Buffer too small\n");
859
-		return -1;
860
-	}
861
-
862
-	if (source->len < 2) {
863
-		LOG(L_ERR, "unixsock_read_lineset: Not enough input "
864
-		    "data (malformed message ?)\n");
865
-		return -1;
866
-	}                 
867
-
868
-	state = ST_BEGIN;
869
-	len = 0;
870
-	for(i = 0; i < source->len; i++) {
871
-		if (source->s[i] == '\r') {
872
-			     /* Filter out CR */
873
-			continue;
874
-		}
875
-
876
-		switch(state) {
877
-		case ST_BEGIN:
878
-			if (source->s[i] == '.') {
879
-				state = ST_CRLF;
880
-			} else if (source->s[i] == '\n') {
881
-				if (len + 2 > lineset->len) goto buf_err;
882
-				lineset->s[len++] = '\r';
883
-				lineset->s[len++] = '\n';
884
-				state = ST_NEWLINE;
885
-			} else {
886
-				if (len + 1 > lineset->len) goto buf_err;
887
-				lineset->s[len++] = source->s[i];
888
-			}
889
-			break;
890
-			
891
-		case ST_CRLF:
892
-			if (source->s[i] == '\n') {
893
-				lineset->len = len;
894
-				source->s += i + 1;
895
-				source->len -= i + 1;
896
-				return 0;
897
-			} else {
898
-				if (len + 2 > lineset->len) goto buf_err;
899
-				lineset->s[len++] = '.';
900
-				lineset->s[len++] = source->s[i];
901
-				state = ST_DATA;
902
-			}
903
-			break;
904
-
905
-		case ST_DATA:
906
-			if (source->s[i] == '\n') {
907
-				if (len + 2 > lineset->len) goto buf_err;
908
-				lineset->s[len++] = '\r';
909