ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/util.C
Revision: 1.25
Committed: Tue Mar 8 17:33:31 2011 UTC (13 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_25
Changes since 1.24: +102 -1 lines
Log Message:
async functionality, unused

File Contents

# User Rev Content
1 pcg 1.1 /*
2     util.C -- process management and other utility functions
3 root 1.25 Copyright (C) 2003-2011 Marc Lehmann <gvpe@schmorp.de>
4 pcg 1.1
5 pcg 1.3 Some of these are taken from tinc, see the AUTHORS file.
6 pcg 1.1
7 pcg 1.16 This file is part of GVPE.
8    
9 pcg 1.22 GVPE is free software; you can redistribute it and/or modify it
10     under the terms of the GNU General Public License as published by the
11     Free Software Foundation; either version 3 of the License, or (at your
12     option) any later version.
13    
14     This program is distributed in the hope that it will be useful, but
15     WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17     Public License for more details.
18    
19     You should have received a copy of the GNU General Public License along
20     with this program; if not, see <http://www.gnu.org/licenses/>.
21    
22     Additional permission under GNU GPL version 3 section 7
23    
24     If you modify this Program, or any covered work, by linking or
25     combining it with the OpenSSL project's OpenSSL library (or a modified
26     version of that library), containing parts covered by the terms of the
27     OpenSSL or SSLeay licenses, the licensors of this Program grant you
28     additional permission to convey the resulting work. Corresponding
29     Source for a non-source form of such a combination shall include the
30     source code for the parts of OpenSSL used as well as that of the
31     covered work.
32 pcg 1.1 */
33    
34     #include "config.h"
35    
36     #include <cstdio>
37 pcg 1.12 #include <cstdlib>
38 pcg 1.1 #include <cstring>
39    
40 root 1.25 #include <queue>
41    
42 pcg 1.1 #include <errno.h>
43     #include <signal.h>
44     #include <sys/types.h>
45 pcg 1.4 #include <sys/wait.h>
46 pcg 1.1 #include <unistd.h>
47     #include <time.h>
48    
49 root 1.25 #if ENABLE_PTHREADS
50     # include <pthread.h>
51     #endif
52    
53 pcg 1.8 #include "netcompat.h"
54 pcg 1.1
55 pcg 1.18 #include "gettext.h"
56 pcg 1.1 #include "pidfile.h"
57     #include "dropin.h"
58    
59     #include "global.h"
60     #include "conf.h"
61 pcg 1.5 #include "util.h"
62 pcg 1.1 #include "slog.h"
63    
64     int
65     write_pidfile (void)
66     {
67     int pid;
68    
69 pcg 1.13 pid = check_pid (conf.pidfilename);
70 pcg 1.1
71     if (pid)
72     {
73 pcg 1.15 fprintf (stderr, _("A gvpe daemon is already running with pid %d.\n"), pid);
74 pcg 1.1 return 1;
75     }
76    
77     /* if it's locked, write-protected, or whatever */
78 pcg 1.13 if (!write_pid (conf.pidfilename))
79 pcg 1.1 return 1;
80    
81     return 0;
82     }
83    
84     int
85     kill_other (int signal)
86     {
87     int pid;
88    
89 pcg 1.13 pid = read_pid (conf.pidfilename);
90 pcg 1.1
91     if (!pid)
92     {
93 pcg 1.15 fprintf (stderr, _("No other gvpe daemon is running.\n"));
94 pcg 1.1 return 1;
95     }
96    
97     errno = 0; /* No error, sometimes errno is only changed on error */
98    
99     /* ESRCH is returned when no process with that pid is found */
100     if (kill (pid, signal) && errno == ESRCH)
101     {
102 pcg 1.15 fprintf (stderr, _("The gvpe daemon is no longer running. "));
103 pcg 1.1
104     fprintf (stderr, _("Removing stale lock file.\n"));
105 pcg 1.13 remove_pid (conf.pidfilename);
106 pcg 1.1 }
107    
108     return 0;
109     }
110    
111     int
112     detach (int do_detach)
113     {
114     /* First check if we can open a fresh new pidfile */
115    
116     if (write_pidfile ())
117     return -1;
118    
119     /* If we succeeded in doing that, detach */
120    
121     log_to (0);
122    
123     if (do_detach)
124     {
125     if (daemon (0, 0) < 0)
126     {
127     log_to (LOGTO_SYSLOG | LOGTO_STDERR);
128    
129     slog (L_ERR, _("couldn't detach from terminal: %s"), strerror (errno));
130     return -1;
131     }
132    
133     /* Now UPDATE the pid in the pidfile, because we changed it... */
134    
135 pcg 1.13 if (!write_pid (conf.pidfilename))
136 pcg 1.1 return -1;
137    
138     log_to (LOGTO_SYSLOG);
139     }
140     else
141     log_to (LOGTO_SYSLOG | LOGTO_STDERR);
142    
143 pcg 1.24 slog (L_INFO, _("gvpe daemon %s (%s %s) starting up."), VERSION, __DATE__, __TIME__);
144 pcg 1.1
145     return 0;
146     }
147    
148 root 1.25 /*****************************************************************************/
149    
150 pcg 1.23 pid_t
151     run_script (const run_script_cb &cb, bool wait)
152 pcg 1.4 {
153 pcg 1.23 sigset_t oldset;
154    
155 pcg 1.20 if (wait)
156 pcg 1.23 {
157     sigset_t sigchld;
158     sigemptyset (&sigchld);
159     sigaddset (&sigchld, SIGCHLD);
160     sigprocmask (SIG_BLOCK, &sigchld, &oldset);
161     }
162 pcg 1.4
163 pcg 1.23 pid_t pid = fork ();
164 pcg 1.20
165     if (pid == 0)
166 pcg 1.4 {
167 pcg 1.23 sigprocmask (SIG_SETMASK, &oldset, 0);
168    
169 pcg 1.19 execl ("/bin/sh", "/bin/sh", "-c", cb (), (char *) 0);
170     exit (EXIT_FAILURE);
171 pcg 1.4 }
172     else if (pid > 0)
173     {
174     if (wait)
175     {
176 pcg 1.19 int status;
177 pcg 1.20 int res = waitpid (pid, &status, 0);
178    
179 pcg 1.23 sigprocmask (SIG_SETMASK, &oldset, 0);
180 pcg 1.19
181 pcg 1.20 if (res < 0)
182 pcg 1.19 {
183     slog (L_WARN, _("waiting for an external command failed: %s."),
184     strerror (errno));
185 pcg 1.23 return 0;
186 pcg 1.19 }
187     else if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS)
188     {
189     slog (L_WARN, _("external command returned with exit status %d (%04x)."),
190     WEXITSTATUS (status), status);
191 pcg 1.23 return 0;
192 pcg 1.19 }
193 pcg 1.4 }
194     }
195 pcg 1.20 else
196     {
197     slog (L_ERR, _("unable to fork, exiting: %s"), strerror (errno));
198     exit (EXIT_FAILURE);
199     }
200 pcg 1.19
201 pcg 1.23 return pid;
202 pcg 1.4 }
203 pcg 1.7
204 root 1.25 /*****************************************************************************/
205    
206     #if 0 /* not yet used */
207    
208     #if ENABLE_PTHREADS
209     struct async_cb
210     {
211     callback<void ()> work_cb;
212     callback<void ()> done_cb;
213     };
214    
215     static ev::async async_done_w;
216     static std::queue< callback<void ()> > async_q;
217    
218     static callback<void ()> work_cb;
219    
220     static void *
221     async_exec (void *)
222     {
223     work_cb ();
224     async_done_w.send ();
225    
226     return 0;
227     }
228    
229     static void
230     async_q_next ()
231     {
232     work_cb = async_q.front (); async_q.pop ();
233    
234     sigset_t fullsigset, oldsigset;
235     pthread_attr_t attr;
236     pthread_t tid;
237    
238     pthread_attr_init (&attr);
239     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
240     //pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < X_STACKSIZE ? X_STACKSIZE : PTHREAD_STACK_MIN);
241     sigfillset (&fullsigset);
242     pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
243    
244     if (pthread_create (&tid, &attr, async_exec, 0))
245     async_exec (0);
246    
247     pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
248     pthread_attr_destroy (&attr);
249     }
250    
251     namespace {
252     void
253     async_done (ev::async &w, int revents)
254     {
255     callback<void ()> done_cb = async_q.front (); async_q.pop ();
256    
257     if (async_q.empty ())
258     async_done_w.stop ();
259     else
260     async_q_next ();
261    
262     done_cb ();
263     }
264     };
265    
266     void
267     async (callback<void ()> work_cb, callback<void ()> done_cb)
268     {
269     bool was_empty = async_q.empty ();
270    
271     async_q.push (work_cb);
272     async_q.push (done_cb);
273    
274     if (was_empty)
275     {
276     async_done_w.set<async_done> ();
277     async_done_w.start ();
278     async_q_next ();
279     }
280     }
281    
282     #else
283    
284     void
285     async (callback<void ()> work_cb, callback<void ()> done_cb)
286     {
287     work_cb ();
288     done_cb ();
289     }
290    
291     #endif
292    
293     #endif
294    
295     /*****************************************************************************/
296    
297 pcg 1.7 #if ENABLE_HTTP_PROXY
298     // works like strdup
299     u8 *
300     base64_encode (const u8 *data, unsigned int len)
301     {
302     const static char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
303    
304     unsigned int t, i;
305     const u8 *end = data + len;
306     u8 *res = new u8 [4 * ((len + 2) / 3) + 1];
307     u8 *out = res;
308    
309     while (data <= end - 3)
310     {
311     t = (((data[0] << 8) | data[1]) << 8) | data[2];
312     data += 3;
313    
314     *out++ = base64[(t >> 18) & 0x3f];
315     *out++ = base64[(t >> 12) & 0x3f];
316     *out++ = base64[(t >> 6) & 0x3f];
317     *out++ = base64[(t ) & 0x3f];
318     }
319    
320     for (t = 0, i = 0; data < end; i++)
321     t = (t << 8) | *data++;
322    
323     switch (i)
324     {
325     case 2:
326     *out++ = base64[(t >> 10) & 0x3f];
327     *out++ = base64[(t >> 4) & 0x3f];
328     *out++ = base64[(t << 2) & 0x3f];
329     *out++ = '=';
330     break;
331     case 1:
332     *out++ = base64[(t >> 2) & 0x3f];
333     *out++ = base64[(t << 4) & 0x3f];
334     *out++ = '=';
335     *out++ = '=';
336     break;
337     }
338    
339     *out++ = 0;
340    
341     return res;
342     }
343     #endif
344    
345 pcg 1.10 void
346     id2mac (unsigned int id, void *m)
347     {
348     mac &p = *(mac *)m;
349    
350     if (id)
351     {
352     p[0] = 0xfe;
353     p[1] = 0xfd;
354     p[2] = 0x80;
355     p[3] = 0x00;
356     p[4] = id >> 8;
357     p[5] = id;
358     }
359     else
360     {
361     p[0] = 0xff;
362     p[1] = 0xff;
363     p[2] = 0xff;
364     p[3] = 0xff;
365     p[4] = 0xff;
366     p[5] = 0xff;
367     }
368     }
369