Keep on hacking on g13. A simple --create and --mount does now work.
[gnupg.git] / g13 / runner.c
1 /* runner.c - Run and watch the backend engines
2  * Copyright (C) 2009 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
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>
28
29 #include "g13.h"
30 #include "i18n.h"
31 #include "keyblob.h"
32 #include "runner.h"
33 #include "../common/exechelp.h"
34
35
36 /* The runner object.  */
37 struct runner_s
38 {
39   char *name;   /* The name of this runner.  */
40
41   int spawned;  /* True if runner_spawn has been called.  */
42   pth_t threadid; /* The TID of the runner thread.  */
43
44   int cancel_flag;  /* If set the thread should terminate itself.  */
45
46   /* We use a reference counter to know when it is safe to remove the
47      object.  Lackiong an explicit ref fucntion this counter will take
48      only these two values:
49
50      1 = Thread not running or only the thread is still running.
51      2 = Thread is running and someone is holding a reference.  */
52   int refcount; 
53
54   pid_t pid;  /* PID of the backend's process (the engine).  */
55   int in_fd;  /* File descriptors to read from the engine.  */
56   int out_fd; /* File descriptors to write to the engine.  */
57   engine_handler_fnc_t handler;  /* The handler functions.  */
58   engine_handler_cleanup_fnc_t handler_cleanup;
59   void *handler_data;  /* Private data of HANDLER and HANDLER_CLEANUP.  */
60
61   /* Instead of IN_FD we use an estream.  Note that the runner thread
62      may close the stream and set status_fp to NULL at any time.  Thus
63      it won't be a good idea to use it while the runner thread is
64      running.  */
65   estream_t status_fp;
66 };
67
68
69 /* Avariabale to track the number of active runner threads.  */
70 static unsigned int thread_count;
71
72
73 \f
74 /* Write NBYTES of BUF to file descriptor FD. */
75 static int
76 writen (int fd, const void *buf, size_t nbytes)
77 {
78   size_t nleft = nbytes;
79   int nwritten;
80   
81   while (nleft > 0)
82     {
83       nwritten = pth_write (fd, buf, nleft);
84       if (nwritten < 0)
85         {
86           if (errno == EINTR)
87             nwritten = 0;
88           else
89             return -1;
90         }
91       nleft -= nwritten;
92       buf = (const char*)buf + nwritten;
93     }
94     
95   return 0;
96 }
97
98
99 static int
100 check_already_spawned (runner_t runner, const char *funcname)
101 {
102   if (runner->spawned)
103     {
104       log_error ("BUG: runner already spawned - ignoring call to %s\n",
105                  funcname);
106       return 1;
107     }
108   else
109     return 0;
110 }
111
112
113 /* Return the number of active threads.  */
114 unsigned int
115 runner_get_threads (void)
116 {
117   return thread_count;
118 }
119
120
121 /* The public release function. */
122 void
123 runner_release (runner_t runner)
124 {
125   if (!runner)
126     return;
127
128   if (!--runner->refcount)
129     return;
130
131   es_fclose (runner->status_fp);
132   if (runner->in_fd != -1)
133     close (runner->in_fd);
134   if (runner->out_fd != -1)
135     close (runner->out_fd);
136   
137   /* Fixme: close the process. */
138
139   /* Tell the engine to release its data.  */
140   if (runner->handler_cleanup)
141     runner->handler_cleanup (runner->handler_data);
142
143   if (runner->pid != (pid_t)(-1))
144     {
145       /* The process has not been cleaned up - do it now.  */
146       gnupg_kill_process (runner->pid);
147       /* (Actually we should use the program name and not the
148           arbitrary NAME of the runner object.  However it does not
149           matter because that information is only used for
150           diagnostics.)  */
151       gnupg_wait_process (runner->name, runner->pid, NULL);
152     }
153
154   xfree (runner->name);
155   xfree (runner);
156 }
157
158
159 /* Create a new runner context.  On success a new runner object is
160    stored at R_RUNNER.  On failure NULL is stored at this address and
161    an error code returned.  */
162 gpg_error_t 
163 runner_new (runner_t *r_runner, const char *name)
164 {
165   runner_t runner;
166
167   *r_runner = NULL;
168
169   runner = xtrycalloc (1, sizeof *runner);
170   if (!runner)
171     return gpg_error_from_syserror ();
172   runner->name = xtrystrdup (name? name: "[unknown]");
173   if (!runner->name)
174     {
175       xfree (runner);
176       return gpg_error_from_syserror ();
177     }
178   runner->refcount = 1;
179   runner->pid = (pid_t)(-1);
180   runner->in_fd = -1;
181   runner->out_fd = -1;
182   
183
184   *r_runner = runner;
185   return 0;
186 }
187
188
189 /* A runner usually maintaines two file descriptors to control the
190    backend engine.  This function is used to set these file
191    descriptors.  The function takes ownership of these file
192    descriptors.  IN_FD will be used to read from engine and OUT_FD to
193    send data to the engine. */
194 void
195 runner_set_fds (runner_t runner, int in_fd, int out_fd)
196 {
197   if (check_already_spawned (runner, "runner_set_fds"))
198     return;
199
200   if (runner->in_fd != -1)
201     close (runner->in_fd);
202   if (runner->out_fd != -1)
203     close (runner->out_fd);
204   runner->in_fd = in_fd;
205   runner->out_fd = out_fd;
206 }
207
208
209 /* Set the PID of the backend engine.  After this call the engine is
210    owned by the runner object.  */
211 void
212 runner_set_pid (runner_t runner, pid_t pid)
213 {
214   if (check_already_spawned (runner, "runner_set_fds"))
215     return;
216
217   runner->pid = pid;
218 }
219
220
221 /* Register the engine handler fucntions HANDLER and HANDLER_CLEANUP
222    and its private HANDLER_DATA with RUNNER.  */
223 void
224 runner_set_handler (runner_t runner,
225                     engine_handler_fnc_t handler, 
226                     engine_handler_cleanup_fnc_t handler_cleanup, 
227                     void *handler_data)
228 {
229   if (check_already_spawned (runner, "runner_set_handler"))
230     return;
231
232   runner->handler = handler;
233   runner->handler_cleanup = handler_cleanup;
234   runner->handler_data = handler_data;
235 }
236
237
238 /* The thread spawned by runner_spawn.  */
239 static void *
240 runner_thread (void *arg)
241 {
242   runner_t runner = arg;
243   gpg_error_t err;
244
245   log_debug ("starting runner thread\n");
246   /* If a status_fp is available, the thread's main task is to read
247      from that stream and invoke the backend's handler function.  This
248      is done on a line by line base and the line length is limited to
249      a reasonable value (about 1000 characters). Other work will
250      continue either due to an EOF of the stream or by demand of the
251      engine.  */
252   if (runner->status_fp)
253     {
254       int c, cont_line;
255       unsigned int pos;
256       char buffer[1024];
257       estream_t fp = runner->status_fp;
258
259       pos = 0;
260       err = 0;
261       cont_line = 0;
262       while (!err && !runner->cancel_flag && (c=es_getc (fp)) != EOF)
263         {
264           buffer[pos++] = c;
265           if (pos >= sizeof buffer - 5 || c == '\n')
266             {
267               buffer[pos - (c == '\n')] = 0;
268               if (opt.verbose)
269                 log_info ("%s%s: %s\n", 
270                           runner->name, cont_line? "(cont)":"", buffer);
271               /* We handle only complete lines and ignore any stuff we
272                  possibly had to truncate.  That is - at least for the
273                  encfs engine - not an issue because our changes to
274                  the tool make sure that only relatively short prompt
275                  lines are of interest.  */
276               if (!cont_line && runner->handler) 
277                 err = runner->handler (runner->handler_data,
278                                        runner, buffer);
279               pos = 0;
280               cont_line = (c != '\n');
281             }
282         }
283       if (!err && runner->cancel_flag)
284         log_debug ("runner thread noticed cancel flag\n");
285       else
286         log_debug ("runner thread saw EOF\n");
287       if (pos)
288         {
289           buffer[pos] = 0;
290           if (opt.verbose)
291             log_info ("%s%s: %s\n",
292                       runner->name, cont_line? "(cont)":"", buffer);
293           if (!cont_line && !err && runner->handler) 
294             err = runner->handler (runner->handler_data,
295                                           runner, buffer);
296         }
297       if (!err && es_ferror (fp))
298         {
299           err = gpg_error_from_syserror ();
300           log_error ("error reading from %s: %s\n",
301                      runner->name, gpg_strerror (err));
302         }
303
304       runner->status_fp = NULL;
305       es_fclose (fp);
306       log_debug ("runner thread closed status fp\n");
307     }
308
309   /* Now wait for the process to finish.  */
310   if (!err && runner->pid != (pid_t)(-1))
311     {
312       int exitcode;
313
314       log_debug ("runner thread waiting ...\n");
315       err = gnupg_wait_process (runner->name, runner->pid, &exitcode);
316       runner->pid = (pid_t)(-1);
317       if (err)
318         log_error ("running `%s' failed (exitcode=%d): %s\n",
319                    runner->name, exitcode, gpg_strerror (err));
320       log_debug ("runner thread waiting finished\n");
321     }
322
323   /* Get rid of the runner object (note: it is refcounted).  */
324   log_debug ("runner thread releasing runner ...\n");
325   runner_release (runner);
326   log_debug ("runner thread runner released\n");
327   thread_count--;
328   
329   return NULL;
330 }
331
332
333 /* Spawn a new thread to let RUNNER work as a coprocess.  */
334 gpg_error_t
335 runner_spawn (runner_t runner)
336 {
337   gpg_error_t err;
338   pth_attr_t tattr;
339   pth_t tid;
340   
341   if (check_already_spawned (runner, "runner_spawn"))
342     return gpg_error (GPG_ERR_BUG);
343
344   /* In case we have an input fd, open it as an estream so that the
345      Pth scheduling will work.  The stdio functions don't work with
346      Pth because they don't call the pth counterparts of read and
347      write unless linker tricks are used.  */
348   if (runner->in_fd != -1)
349     {
350       estream_t fp;
351       
352       fp = es_fdopen (runner->in_fd, "r");
353       if (!fp)
354         {
355           err = gpg_error_from_syserror ();
356           log_error ("can't fdopen pipe for reading: %s\n", gpg_strerror (err));
357           return err;
358         }
359       runner->status_fp = fp;
360       runner->in_fd = -1;  /* Now owned by status_fp.  */
361     }
362
363   tattr = pth_attr_new ();
364   pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
365   pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
366   pth_attr_set (tattr, PTH_ATTR_NAME, runner->name);
367   
368   tid = pth_spawn (tattr, runner_thread, runner);
369   if (!tid)
370     {
371       err = gpg_error_from_syserror ();
372       log_error ("error spawning runner thread: %s\n", gpg_strerror (err));
373       return err;
374     }
375   /* The scheduler has not yet kicked in, thus we can safely set the
376      spawned flag and the tid.  */
377   thread_count++;
378   runner->spawned = 1;
379   runner->threadid = tid;
380   pth_attr_destroy (tattr);
381
382   /* The runner thread is now runnable.  */
383   
384   
385
386   return 0;
387 }
388
389
390 /* Cancel a running thread.  */
391 void
392 runner_cancel (runner_t runner)
393 {
394   if (runner->spawned)
395     {
396       /* FIXME: This does only work if the thread emits status lines.  We
397          need to change the trhead to wait on an event.  */
398       runner->cancel_flag = 1;
399       /* For now we use the brutal way and kill the process. */
400       gnupg_kill_process (runner->pid);
401     }
402 }
403
404
405 /* Send a line of data down to the engine.  This line may not contain
406    a binary Nul or a LF character.  This function is used by the
407    engine's handler.  */
408 gpg_error_t 
409 runner_send_line (runner_t runner, const void *data, size_t datalen)
410 {
411   gpg_error_t err = 0;
412
413   if (!runner->spawned)
414     {
415       log_error ("BUG: runner for %s not spawned\n", runner->name);
416       err = gpg_error (GPG_ERR_INTERNAL);
417     }
418   else if (runner->out_fd == -1)
419     {
420       log_error ("no output file descriptor for runner %s\n", runner->name);
421       err = gpg_error (GPG_ERR_EBADF);
422     }
423   else if (data && datalen)
424     {
425       if (memchr (data, '\n', datalen))
426         {
427           log_error ("LF detected in response data\n");
428           err = gpg_error (GPG_ERR_BUG);
429         }
430       else if (memchr (data, 0, datalen))
431         {
432           log_error ("Nul detected in response data\n");
433           err = gpg_error (GPG_ERR_BUG);
434         }
435       else if (writen (runner->out_fd, data, datalen))
436         err = gpg_error_from_syserror ();
437     }
438
439   if (!err)
440     if (writen (runner->out_fd, "\n", 1))
441       err = gpg_error_from_syserror ();
442   
443   return err;
444 }