diff options
Diffstat (limited to 'src/daemon.c')
-rw-r--r-- | src/daemon.c | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/src/daemon.c b/src/daemon.c new file mode 100644 index 00000000..f3949276 --- /dev/null +++ b/src/daemon.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2005 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/daemon.c | ||
23 | * @brief code for gnunet-gtk gnunetd interaction | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "daemon.h" | ||
29 | #include "main.h" | ||
30 | #include "helper.h" | ||
31 | #ifndef MINGW | ||
32 | #include <sys/wait.h> | ||
33 | #endif | ||
34 | #include <GNUnet/gnunet_util.h> | ||
35 | #include <GNUnet/gnunet_protocols.h> | ||
36 | |||
37 | /** | ||
38 | * Checks if gnunetd is running | ||
39 | * | ||
40 | * NOTE: Uses CS_PROTO_CLIENT_COUNT query to determine if | ||
41 | * gnunetd is running | ||
42 | */ | ||
43 | static int checkDaemonRunning(void) { | ||
44 | GNUNET_TCP_SOCKET * sock; | ||
45 | CS_HEADER csHdr; | ||
46 | int ret; | ||
47 | |||
48 | sock = getClientSocket(); | ||
49 | if(sock == NULL) { | ||
50 | BREAK(); | ||
51 | return SYSERR; | ||
52 | } | ||
53 | |||
54 | csHdr.size | ||
55 | = htons(sizeof(CS_HEADER)); | ||
56 | csHdr.type | ||
57 | = htons(CS_PROTO_CLIENT_COUNT); | ||
58 | if (SYSERR == writeToSocket(sock, | ||
59 | &csHdr)) { | ||
60 | LOG(LOG_DEBUG, | ||
61 | _("gnunetd is NOT running.\n")); | ||
62 | releaseClientSocket(sock); | ||
63 | return SYSERR; | ||
64 | } | ||
65 | if (SYSERR == readTCPResult(sock, | ||
66 | &ret)) { | ||
67 | releaseClientSocket(sock); | ||
68 | return SYSERR; | ||
69 | } | ||
70 | releaseClientSocket(sock); | ||
71 | |||
72 | return OK; | ||
73 | } | ||
74 | |||
75 | |||
76 | |||
77 | #if LINUX || OSX || SOLARIS || SOMEBSD | ||
78 | static int launchWithExec() { | ||
79 | pid_t pid; | ||
80 | |||
81 | pid = fork(); | ||
82 | if (pid == 0) { | ||
83 | char * args[4]; | ||
84 | char * path; | ||
85 | char * cp; | ||
86 | |||
87 | path = NULL; | ||
88 | cp = getConfigurationString("MAIN", | ||
89 | "ARGV[0]"); | ||
90 | if (cp != NULL) { | ||
91 | int i = strlen(cp); | ||
92 | while ( (i >= 0) && | ||
93 | (cp[i] != DIR_SEPARATOR) ) | ||
94 | i--; | ||
95 | if ( i != -1 ) { | ||
96 | cp[i+1] = '\0'; | ||
97 | path = MALLOC(i+1+strlen("gnunetd")); | ||
98 | strcpy(path, cp); | ||
99 | strcat(path, "gnunetd"); | ||
100 | args[0] = path; | ||
101 | FREE(cp); | ||
102 | } else { | ||
103 | args[0] = "gnunetd"; | ||
104 | } | ||
105 | } | ||
106 | cp = getConfigurationString("GNUNET-GTK", | ||
107 | "GNUNETD-CONFIG"); | ||
108 | if (cp != NULL) { | ||
109 | args[1] = "-c"; | ||
110 | args[2] = cp; | ||
111 | } else { | ||
112 | args[1] = NULL; | ||
113 | } | ||
114 | args[3] = NULL; | ||
115 | errno = 0; | ||
116 | nice(10); /* return value is not well-defined */ | ||
117 | if (errno != 0) | ||
118 | LOG_STRERROR(LOG_WARNING, "nice"); | ||
119 | if (path != NULL) | ||
120 | execv(path, | ||
121 | args); | ||
122 | else | ||
123 | execvp("gnunetd", | ||
124 | args); | ||
125 | LOG_STRERROR(LOG_FAILURE, "exec"); | ||
126 | LOG(LOG_FAILURE, | ||
127 | _("Attempted path to '%s' was '%s'.\n"), | ||
128 | "gnunetd", | ||
129 | (path == NULL) ? "gnunetd" : path); | ||
130 | FREENONNULL(path); /* yeah, right, like we're likely to get | ||
131 | here... */ | ||
132 | FREENONNULL(args[1]); | ||
133 | _exit(-1); | ||
134 | } else { | ||
135 | pid_t ret; | ||
136 | int status; | ||
137 | |||
138 | ret = waitpid(pid, &status, 0); | ||
139 | if (ret == -1) { | ||
140 | LOG_STRERROR(LOG_ERROR, "waitpid"); | ||
141 | return SYSERR; | ||
142 | } | ||
143 | if ( (WIFEXITED(status) && | ||
144 | (0 != WEXITSTATUS(status)) ) ) { | ||
145 | guiMessage(_("Starting gnunetd failed, error code: %d"), | ||
146 | WEXITSTATUS(status)); | ||
147 | return SYSERR; | ||
148 | } | ||
149 | #ifdef WCOREDUMP | ||
150 | if (WCOREDUMP(status)) { | ||
151 | guiMessage(_("Starting gnunetd failed (core dumped).")); | ||
152 | return SYSERR; | ||
153 | } | ||
154 | #endif | ||
155 | if (WIFSIGNALED(status) || | ||
156 | WTERMSIG(status) ) { | ||
157 | guiMessage(_("Starting gnunetd failed (aborted by signal).")); | ||
158 | return SYSERR; | ||
159 | } | ||
160 | return OK; | ||
161 | } | ||
162 | } | ||
163 | #endif | ||
164 | |||
165 | static int doLaunch() { | ||
166 | |||
167 | #if LINUX || OSX || SOLARIS || SOMEBSD | ||
168 | return launchWithExec(); | ||
169 | #elif MINGW | ||
170 | char szCall[_MAX_PATH + 1], szWd[_MAX_PATH + 1], szCWd[_MAX_PATH + 1]; | ||
171 | char *args[1]; | ||
172 | |||
173 | conv_to_win_path("/bin/gnunetd.exe", szCall); | ||
174 | conv_to_win_path("/bin", szWd); | ||
175 | _getcwd(szCWd, _MAX_PATH); | ||
176 | |||
177 | chdir(szWd); | ||
178 | args[0] = NULL; | ||
179 | spawnvp(_P_NOWAIT, szCall, (const char *const *) args); | ||
180 | chdir(szCWd); | ||
181 | |||
182 | return OK; | ||
183 | #else | ||
184 | /* any system out there that does not support THIS!? */ | ||
185 | system("gnunetd"); /* we may not have nice, | ||
186 | so let's be minimalistic here. */ | ||
187 | return OK; | ||
188 | #endif | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * Launch gnunetd w/ checks | ||
193 | */ | ||
194 | void on_startDaemon_clicked(GtkWidget * widget, | ||
195 | gpointer data) { | ||
196 | if (OK == checkDaemonRunning() ) { | ||
197 | cronCheckDaemon(NULL); | ||
198 | return; | ||
199 | } else { | ||
200 | addLogEntry(_("Launching gnunetd...")); | ||
201 | doLaunch(); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * Kill gnunetd | ||
207 | */ | ||
208 | void on_stopDaemon_clicked(GtkWidget * widget, | ||
209 | gpointer data) { | ||
210 | if (OK == checkDaemonRunning() ) { | ||
211 | GNUNET_TCP_SOCKET * sock; | ||
212 | CS_HEADER csHdr; | ||
213 | int ret; | ||
214 | |||
215 | sock = getClientSocket(); | ||
216 | if (sock == NULL) { | ||
217 | cronCheckDaemon(NULL); | ||
218 | /* well, probably already dead */ | ||
219 | return; | ||
220 | } | ||
221 | csHdr.size | ||
222 | = htons(sizeof(CS_HEADER)); | ||
223 | csHdr.type | ||
224 | = htons(CS_PROTO_SHUTDOWN_REQUEST); | ||
225 | if (SYSERR == writeToSocket(sock, | ||
226 | &csHdr)) { | ||
227 | guiMessage(_("Error sending shutdown request to gnunetd.")); | ||
228 | releaseClientSocket(sock); | ||
229 | cronCheckDaemon(NULL); | ||
230 | return; | ||
231 | } | ||
232 | if (SYSERR == readTCPResult(sock, | ||
233 | &ret)) { | ||
234 | guiMessage(_("Error reading shutdown confirmation from gnunetd.")); | ||
235 | releaseClientSocket(sock); | ||
236 | cronCheckDaemon(NULL); | ||
237 | return; | ||
238 | } | ||
239 | if (ret == OK) { | ||
240 | static GtkWidget * killEntry; | ||
241 | killEntry | ||
242 | = glade_xml_get_widget(mainXML, | ||
243 | "stopDaemon"); | ||
244 | gtk_widget_set_sensitive(killEntry, FALSE); | ||
245 | addLogEntry(_("Terminating gnunetd...")); | ||
246 | } else { | ||
247 | guiMessage(_("gnunetd refused to shut down (error code '%d')."), | ||
248 | ret); | ||
249 | } | ||
250 | releaseClientSocket(sock); | ||
251 | } | ||
252 | cronCheckDaemon(NULL); | ||
253 | } | ||
254 | |||
255 | static gint doUpdateMenus(SaveCall * call) { | ||
256 | static GtkWidget * killEntry = NULL; | ||
257 | static GtkWidget * launchEntry = NULL; | ||
258 | static GtkWidget * statsEntryYes = NULL; | ||
259 | static GtkWidget * statsEntryNo = NULL; | ||
260 | static int once = 1; | ||
261 | static int isLocal; | ||
262 | char * host; | ||
263 | int ret; | ||
264 | |||
265 | ret = * (int*) call->args; | ||
266 | if (once) { | ||
267 | once = 0; | ||
268 | killEntry | ||
269 | = glade_xml_get_widget(mainXML, | ||
270 | "stopDaemon"); | ||
271 | launchEntry | ||
272 | = glade_xml_get_widget(mainXML, | ||
273 | "startDaemon"); | ||
274 | statsEntryYes | ||
275 | = glade_xml_get_widget(mainXML, | ||
276 | "statusPixmapYes"); | ||
277 | statsEntryNo | ||
278 | = glade_xml_get_widget(mainXML, | ||
279 | "statusPixmapNo"); | ||
280 | host = getConfigurationString("NETWORK", | ||
281 | "HOST"); | ||
282 | if ( (host == NULL) || | ||
283 | (strcmp(host, "localhost")==0) ) | ||
284 | isLocal = TRUE; | ||
285 | else | ||
286 | isLocal = FALSE; | ||
287 | FREENONNULL(host); | ||
288 | } | ||
289 | if (ret == SYSERR) { | ||
290 | gtk_widget_hide(statsEntryYes); | ||
291 | gtk_widget_show_all(statsEntryNo); | ||
292 | gtk_widget_set_sensitive(killEntry, FALSE); | ||
293 | gtk_widget_set_sensitive(launchEntry, (TRUE & isLocal) ); | ||
294 | } else { | ||
295 | gtk_widget_hide(statsEntryNo); | ||
296 | gtk_widget_show_all(statsEntryYes); | ||
297 | gtk_widget_set_sensitive(killEntry, TRUE); | ||
298 | gtk_widget_set_sensitive(launchEntry, FALSE); | ||
299 | } | ||
300 | gtkSaveCallDone(call->sem); | ||
301 | return FALSE; | ||
302 | } | ||
303 | |||
304 | void cronCheckDaemon(void * dummy) { | ||
305 | static int last = 42; | ||
306 | int ret; | ||
307 | |||
308 | ret = checkDaemonRunning(); | ||
309 | if (ret != last) { | ||
310 | last = ret; | ||
311 | gtkSaveCall((GtkFunction) doUpdateMenus, &ret); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | /* end of daemon.c */ | ||