mount does now work in server and standalone mode.
[gnupg.git] / g13 / runner.c
blob27d03702ac166d0685d441344bea0950e16d8c78
1 /* runner.c - Run and watch the backend engines
2 * Copyright (C) 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <assert.h>
27 #include <pth.h>
29 #include "g13.h"
30 #include "i18n.h"
31 #include "keyblob.h"
32 #include "runner.h"
33 #include "../common/exechelp.h"
36 /* The runner object. */
37 struct runner_s
39 char *name; /* The name of this runner. */
41 int spawned; /* True if runner_spawn has been called. */
42 pth_t threadid; /* The TID of the runner thread. */
43 runner_t next_running; /* Builds a list of all running threads. */
44 int canceled; /* Set if a cancel has already been send once. */
46 int cancel_flag; /* If set the thread should terminate itself. */
49 /* We use a reference counter to know when it is safe to remove the
50 object. Lackiong an explicit ref fucntion this counter will take
51 only these two values:
53 1 = Thread not running or only the thread is still running.
54 2 = Thread is running and someone is holding a reference. */
55 int refcount;
57 pid_t pid; /* PID of the backend's process (the engine). */
58 int in_fd; /* File descriptors to read from the engine. */
59 int out_fd; /* File descriptors to write to the engine. */
60 engine_handler_fnc_t handler; /* The handler functions. */
61 engine_handler_cleanup_fnc_t handler_cleanup;
62 void *handler_data; /* Private data of HANDLER and HANDLER_CLEANUP. */
64 /* Instead of IN_FD we use an estream. Note that the runner thread
65 may close the stream and set status_fp to NULL at any time. Thus
66 it won't be a good idea to use it while the runner thread is
67 running. */
68 estream_t status_fp;
72 /* The head of the list of all running threads. */
73 static runner_t running_threads;
78 /* Write NBYTES of BUF to file descriptor FD. */
79 static int
80 writen (int fd, const void *buf, size_t nbytes)
82 size_t nleft = nbytes;
83 int nwritten;
85 while (nleft > 0)
87 nwritten = pth_write (fd, buf, nleft);
88 if (nwritten < 0)
90 if (errno == EINTR)
91 nwritten = 0;
92 else
93 return -1;
95 nleft -= nwritten;
96 buf = (const char*)buf + nwritten;
99 return 0;
103 static int
104 check_already_spawned (runner_t runner, const char *funcname)
106 if (runner->spawned)
108 log_error ("BUG: runner already spawned - ignoring call to %s\n",
109 funcname);
110 return 1;
112 else
113 return 0;
117 /* Return the number of active threads. */
118 unsigned int
119 runner_get_threads (void)
121 unsigned int n = 0;
122 runner_t r;
124 for (r = running_threads; r; r = r->next_running)
125 n++;
126 return n;
130 /* The public release function. */
131 void
132 runner_release (runner_t runner)
134 if (!runner)
135 return;
137 if (!--runner->refcount)
138 return;
140 es_fclose (runner->status_fp);
141 if (runner->in_fd != -1)
142 close (runner->in_fd);
143 if (runner->out_fd != -1)
144 close (runner->out_fd);
146 /* Fixme: close the process. */
148 /* Tell the engine to release its data. */
149 if (runner->handler_cleanup)
150 runner->handler_cleanup (runner->handler_data);
152 if (runner->pid != (pid_t)(-1))
154 /* The process has not been cleaned up - do it now. */
155 gnupg_kill_process (runner->pid);
156 /* (Actually we should use the program name and not the
157 arbitrary NAME of the runner object. However it does not
158 matter because that information is only used for
159 diagnostics.) */
160 gnupg_wait_process (runner->name, runner->pid, NULL);
163 xfree (runner->name);
164 xfree (runner);
168 /* Create a new runner context. On success a new runner object is
169 stored at R_RUNNER. On failure NULL is stored at this address and
170 an error code returned. */
171 gpg_error_t
172 runner_new (runner_t *r_runner, const char *name)
174 runner_t runner;
176 *r_runner = NULL;
178 runner = xtrycalloc (1, sizeof *runner);
179 if (!runner)
180 return gpg_error_from_syserror ();
181 runner->name = xtrystrdup (name? name: "[unknown]");
182 if (!runner->name)
184 xfree (runner);
185 return gpg_error_from_syserror ();
187 runner->refcount = 1;
188 runner->pid = (pid_t)(-1);
189 runner->in_fd = -1;
190 runner->out_fd = -1;
193 *r_runner = runner;
194 return 0;
198 /* A runner usually maintaines two file descriptors to control the
199 backend engine. This function is used to set these file
200 descriptors. The function takes ownership of these file
201 descriptors. IN_FD will be used to read from engine and OUT_FD to
202 send data to the engine. */
203 void
204 runner_set_fds (runner_t runner, int in_fd, int out_fd)
206 if (check_already_spawned (runner, "runner_set_fds"))
207 return;
209 if (runner->in_fd != -1)
210 close (runner->in_fd);
211 if (runner->out_fd != -1)
212 close (runner->out_fd);
213 runner->in_fd = in_fd;
214 runner->out_fd = out_fd;
218 /* Set the PID of the backend engine. After this call the engine is
219 owned by the runner object. */
220 void
221 runner_set_pid (runner_t runner, pid_t pid)
223 if (check_already_spawned (runner, "runner_set_fds"))
224 return;
226 runner->pid = pid;
230 /* Register the engine handler fucntions HANDLER and HANDLER_CLEANUP
231 and its private HANDLER_DATA with RUNNER. */
232 void
233 runner_set_handler (runner_t runner,
234 engine_handler_fnc_t handler,
235 engine_handler_cleanup_fnc_t handler_cleanup,
236 void *handler_data)
238 if (check_already_spawned (runner, "runner_set_handler"))
239 return;
241 runner->handler = handler;
242 runner->handler_cleanup = handler_cleanup;
243 runner->handler_data = handler_data;
247 /* The thread spawned by runner_spawn. */
248 static void *
249 runner_thread (void *arg)
251 runner_t runner = arg;
252 gpg_error_t err = 0;
254 log_debug ("starting runner thread\n");
255 /* If a status_fp is available, the thread's main task is to read
256 from that stream and invoke the backend's handler function. This
257 is done on a line by line base and the line length is limited to
258 a reasonable value (about 1000 characters). Other work will
259 continue either due to an EOF of the stream or by demand of the
260 engine. */
261 if (runner->status_fp)
263 int c, cont_line;
264 unsigned int pos;
265 char buffer[1024];
266 estream_t fp = runner->status_fp;
268 pos = 0;
269 cont_line = 0;
270 while (!err && !runner->cancel_flag && (c=es_getc (fp)) != EOF)
272 buffer[pos++] = c;
273 if (pos >= sizeof buffer - 5 || c == '\n')
275 buffer[pos - (c == '\n')] = 0;
276 if (opt.verbose)
277 log_info ("%s%s: %s\n",
278 runner->name, cont_line? "(cont)":"", buffer);
279 /* We handle only complete lines and ignore any stuff we
280 possibly had to truncate. That is - at least for the
281 encfs engine - not an issue because our changes to
282 the tool make sure that only relatively short prompt
283 lines are of interest. */
284 if (!cont_line && runner->handler)
285 err = runner->handler (runner->handler_data,
286 runner, buffer);
287 pos = 0;
288 cont_line = (c != '\n');
291 if (!err && runner->cancel_flag)
292 log_debug ("runner thread noticed cancel flag\n");
293 else
294 log_debug ("runner thread saw EOF\n");
295 if (pos)
297 buffer[pos] = 0;
298 if (opt.verbose)
299 log_info ("%s%s: %s\n",
300 runner->name, cont_line? "(cont)":"", buffer);
301 if (!cont_line && !err && runner->handler)
302 err = runner->handler (runner->handler_data,
303 runner, buffer);
305 if (!err && es_ferror (fp))
307 err = gpg_error_from_syserror ();
308 log_error ("error reading from %s: %s\n",
309 runner->name, gpg_strerror (err));
312 runner->status_fp = NULL;
313 es_fclose (fp);
314 log_debug ("runner thread closed status fp\n");
317 /* Now wait for the process to finish. */
318 if (!err && runner->pid != (pid_t)(-1))
320 int exitcode;
322 log_debug ("runner thread waiting ...\n");
323 err = gnupg_wait_process (runner->name, runner->pid, &exitcode);
324 runner->pid = (pid_t)(-1);
325 if (err)
326 log_error ("running `%s' failed (exitcode=%d): %s\n",
327 runner->name, exitcode, gpg_strerror (err));
328 log_debug ("runner thread waiting finished\n");
331 /* Get rid of the runner object (note: it is refcounted). */
332 log_debug ("runner thread releasing runner ...\n");
334 runner_t r, rprev;
336 for (r = running_threads, rprev = NULL; r; rprev = r, r = r->next_running)
337 if (r == runner)
339 if (!rprev)
340 running_threads = r->next_running;
341 else
342 rprev->next_running = r->next_running;
343 r->next_running = NULL;
344 break;
347 runner_release (runner);
348 log_debug ("runner thread runner released\n");
350 return NULL;
354 /* Spawn a new thread to let RUNNER work as a coprocess. */
355 gpg_error_t
356 runner_spawn (runner_t runner)
358 gpg_error_t err;
359 pth_attr_t tattr;
360 pth_t tid;
362 if (check_already_spawned (runner, "runner_spawn"))
363 return gpg_error (GPG_ERR_BUG);
365 /* In case we have an input fd, open it as an estream so that the
366 Pth scheduling will work. The stdio functions don't work with
367 Pth because they don't call the pth counterparts of read and
368 write unless linker tricks are used. */
369 if (runner->in_fd != -1)
371 estream_t fp;
373 fp = es_fdopen (runner->in_fd, "r");
374 if (!fp)
376 err = gpg_error_from_syserror ();
377 log_error ("can't fdopen pipe for reading: %s\n", gpg_strerror (err));
378 return err;
380 runner->status_fp = fp;
381 runner->in_fd = -1; /* Now owned by status_fp. */
384 tattr = pth_attr_new ();
385 pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
386 pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
387 pth_attr_set (tattr, PTH_ATTR_NAME, runner->name);
389 tid = pth_spawn (tattr, runner_thread, runner);
390 if (!tid)
392 err = gpg_error_from_syserror ();
393 log_error ("error spawning runner thread: %s\n", gpg_strerror (err));
394 return err;
396 /* The scheduler has not yet kicked in, thus we can safely set the
397 spawned flag and the tid. */
398 runner->spawned = 1;
399 runner->threadid = tid;
400 runner->next_running = running_threads;
401 running_threads = runner;
403 pth_attr_destroy (tattr);
405 /* The runner thread is now runnable. */
407 return 0;
411 /* Cancel a running thread. */
412 void
413 runner_cancel (runner_t runner)
415 /* Warning: runner_cancel_all has knowledge of this code. */
416 if (runner->spawned)
418 runner->canceled = 1; /* Mark that we canceled this one already. */
419 /* FIXME: This does only work if the thread emits status lines. We
420 need to change the trhead to wait on an event. */
421 runner->cancel_flag = 1;
422 /* For now we use the brutal way and kill the process. */
423 gnupg_kill_process (runner->pid);
428 /* Cancel all runner threads. */
429 void
430 runner_cancel_all (void)
432 runner_t r;
436 for (r = running_threads; r; r = r->next_running)
437 if (r->spawned && !r->canceled)
439 runner_cancel (r);
440 break;
443 while (r);
447 /* Send a line of data down to the engine. This line may not contain
448 a binary Nul or a LF character. This function is used by the
449 engine's handler. */
450 gpg_error_t
451 runner_send_line (runner_t runner, const void *data, size_t datalen)
453 gpg_error_t err = 0;
455 if (!runner->spawned)
457 log_error ("BUG: runner for %s not spawned\n", runner->name);
458 err = gpg_error (GPG_ERR_INTERNAL);
460 else if (runner->out_fd == -1)
462 log_error ("no output file descriptor for runner %s\n", runner->name);
463 err = gpg_error (GPG_ERR_EBADF);
465 else if (data && datalen)
467 if (memchr (data, '\n', datalen))
469 log_error ("LF detected in response data\n");
470 err = gpg_error (GPG_ERR_BUG);
472 else if (memchr (data, 0, datalen))
474 log_error ("Nul detected in response data\n");
475 err = gpg_error (GPG_ERR_BUG);
477 else if (writen (runner->out_fd, data, datalen))
478 err = gpg_error_from_syserror ();
481 if (!err)
482 if (writen (runner->out_fd, "\n", 1))
483 err = gpg_error_from_syserror ();
485 return err;