1 /*-
2 * Copyright (c) 2001, 2002, 2004 Lev Walkin <vlm@lionet.info>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: servers.c,v 1.10 2006/04/07 18:58:02 vlm Exp $
27 */
28
29 #include "ipcad.h"
30 #include "servers.h"
31 #include "opt.h"
32
33 server *servers_head = NULL;
34
35 int
add_server(void * (* func)(void *),char * name,struct in_addr * ip,int hport)36 add_server(void *(*func)(void *), char *name, struct in_addr *ip, int hport) {
37 server *srv;
38
39 if(!func || !name)
40 return -1;
41
42 srv = (server *)calloc(1, sizeof(server));
43 if(!srv)
44 return -1;
45
46 srv->name = strdup(name);
47 if(!srv->name) {
48 free(srv);
49 return -1;
50 }
51
52 srv->server_func = func;
53
54 srv->addr.sin_family = AF_INET;
55 if(ip) srv->addr.sin_addr = *ip;
56 srv->addr.sin_port = htons(hport);
57 srv->sockfd = -1;
58
59 srv->next = servers_head;
60 servers_head = srv;
61
62 return 0;
63 }
64
65 int
start_servers()66 start_servers() {
67 sigset_t old_set;
68 server *srv;
69 int rc;
70
71 if(!servers_head) {
72 if(daemon_mode)
73 printf("No servers defined. How will you gather data? ;)\n");
74 return 0;
75 }
76
77 /*
78 * Do not allow other threads receive signals for the main thread.
79 * The signal mask is inherited from the creating thread.
80 */
81 block_certain_signals(&old_set);
82
83 /* Iterate through defined servers */
84 for(srv = servers_head; srv; srv=srv->next) {
85 if(srv->started_ok)
86 continue;
87
88 rc = pthread_create(&srv->thid, NULL, srv->server_func, (void *)srv);
89
90 if(rc == 0) {
91 /* Wait for thread to terminate or report success */
92 while(
93 (pthread_kill(srv->thid, 0) == 0)
94 && (srv->started_ok == 0)
95 ) {
96 #ifdef HAVE_SCHED_YIELD
97 sched_yield();
98 #else
99 sleep(1);
100 #endif
101 }
102 if(!srv->started_ok)
103 rc = -1;
104 }
105
106 /* Failed to create particular server */
107 if(rc == -1) {
108 srv->thid = 0;
109
110 /* Terminate previously started servers */
111 end_servers();
112 sigprocmask(SIG_SETMASK, &old_set, NULL);
113 return -1;
114 }
115
116 printf("%s thread %lu started.\n",
117 srv->name, (long)srv->thid);
118
119 }
120
121 sigprocmask(SIG_SETMASK, &old_set, NULL);
122
123 return 0;
124 }
125
126 void
end_servers_r(server * srv)127 end_servers_r(server *srv) {
128 if(!srv)
129 return;
130
131 if(srv->next)
132 end_servers_r(srv->next);
133
134 /* If alive */
135 if(srv->thid && srv->started_ok) {
136
137 /* Kick it */
138 pthread_kill(srv->thid, SIGALRM);
139
140 printf("Waiting for %s thread to terminate... ",
141 srv->name);
142 fflush(stdout);
143
144 pthread_join(srv->thid, NULL);
145 printf("DONE.\n");
146
147 } /* if(thid) */
148
149 free(srv);
150 }
151
152
153 void
end_servers()154 end_servers() {
155 sig_atomic_t tmps;
156
157 /* Remember value */
158 tmps = signoff_now;
159
160 /* Enable global signoff flag */
161 signoff_now = 1;
162
163 /* Terminate working servers */
164 end_servers_r(servers_head);
165
166 servers_head = NULL;
167
168 /* Restore previous value */
169 signoff_now = tmps;
170 }
171