From 9f8374622c5b258cabb51b115a839d6cb2faeed6 Mon Sep 17 00:00:00 2001 From: Hartmut Goebel Date: Tue, 5 Mar 2019 23:43:25 +0100 Subject: [PATCH] gnunet-qr: Implement functionality of gnunet-uri, don't spawn. This copies the central part of gnunet-uri. Should better be in some shared code. Also eliminate helper lib "gnunet-qr-utils.h", which is no longer used. --- src/util/gnunet-qr-utils.h | 111 ------------------------------------- src/util/gnunet-qr.c | 103 +++++++++++++++++++++++++++++----- 2 files changed, 89 insertions(+), 125 deletions(-) delete mode 100644 src/util/gnunet-qr-utils.h diff --git a/src/util/gnunet-qr-utils.h b/src/util/gnunet-qr-utils.h deleted file mode 100644 index 6d821633c..000000000 --- a/src/util/gnunet-qr-utils.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - This file is part of GNUnet. - Copyright (C) 2010, 2011, 2012 Christian Grothoff - Copyright (C) 2019 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - or (at your option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - - SPDX-License-Identifier: AGPL3.0-or-later -*/ - -#include "platform.h" - -// -// FIXME: These functions are copied from dns/gnunet-helper-dns.c, -// move them into a common library. Or think about implementing a even -// more elaborate version. -// - -/** - * Open '/dev/null' and make the result the given - * file descriptor. - * - * @param target_fd desired FD to point to /dev/null - * @param flags open flags (O_RDONLY, O_WRONLY) - */ -static void -open_dev_null (int target_fd, - int flags) -{ - int fd; - - fd = open ("/dev/null", flags); - if (-1 == fd) - abort (); - if (fd == target_fd) - return; - if (-1 == dup2 (fd, target_fd)) - { - (void) close (fd); - abort (); - } - (void) close (fd); -} - -/** - * Run the given command and wait for it to complete. - * - * @param file name of the binary to run - * @param cmd command line arguments (as given to 'execv') - * @return 0 on success, 1 on any error - */ -static int -fork_and_exec (const char *file, - char *const cmd[]) -{ - int status; - pid_t pid; - pid_t ret; - - pid = fork (); - if (-1 == pid) - { - fprintf (stderr, - "fork failed: %s\n", - strerror (errno)); - return 1; - } - if (0 == pid) - { - /* we are the child process */ - /* close stdin/stdout to not cause interference - with the helper's main protocol! */ - (void) close (0); - open_dev_null (0, O_RDONLY); - (void) close (1); - open_dev_null (1, O_WRONLY); - (void) execv (file, cmd); - /* can only get here on error */ - fprintf (stderr, - "exec `%s' failed: %s\n", - file, - strerror (errno)); - _exit (1); - } - /* keep running waitpid as long as the only error we get is 'EINTR' */ - while ( (-1 == (ret = waitpid (pid, &status, 0))) && - (errno == EINTR) ); - if (-1 == ret) - { - fprintf (stderr, - "waitpid failed: %s\n", - strerror (errno)); - return 1; - } - if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status)))) - return 1; - /* child process completed and returned success, we're happy */ - return 0; -} - diff --git a/src/util/gnunet-qr.c b/src/util/gnunet-qr.c index b54f352d5..1106d5cb2 100644 --- a/src/util/gnunet-qr.c +++ b/src/util/gnunet-qr.c @@ -23,18 +23,102 @@ #include #include "platform.h" #include "gnunet_util_lib.h" -#include "gnunet-qr-utils.h" #define LOG(fmt, ...) if (verbose == true) printf(fmt, ## __VA_ARGS__) // Command line options -// program exit code -static long unsigned int exit_code = 1; - static char* device = "/dev/video0"; static int verbose = false; static int silent = false; +// Handler exit code +static long unsigned int exit_code = 1; + +// Helper process we started. +static struct GNUNET_OS_Process *p; + +// Pipe used to communicate shutdown via signal. +static struct GNUNET_DISK_PipeHandle *sigpipe; + + +/** + * Task triggered whenever we receive a SIGCHLD (child + * process died) or when user presses CTRL-C. + * + * @param cls closure, NULL + */ +static void +maint_child_death (void *cls) +{ + enum GNUNET_OS_ProcessStatusType type; + + if ( (GNUNET_OK != + GNUNET_OS_process_status (p, &type, &exit_code)) || + (type != GNUNET_OS_PROCESS_EXITED) ) + GNUNET_break (0 == GNUNET_OS_process_kill (p, GNUNET_TERM_SIG)); + GNUNET_OS_process_destroy (p); +} + + +/** + * Dispatch URIs to the appropriate GNUnet helper process + * + * @param cls closure + * @param uri uri to dispatch + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +gnunet_uri (void *cls, const char *uri, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + const char *orig_uri; + const char *slash; + char *subsystem; + char *program; + struct GNUNET_SCHEDULER_Task * rt; + + orig_uri = uri; + if (0 != strncasecmp ("gnunet://", uri, strlen ("gnunet://"))) { + fprintf (stderr, + _("Invalid URI: does not start with `%s'\n"), + "gnunet://"); + return; + } + uri += strlen ("gnunet://"); + if (NULL == (slash = strchr (uri, '/'))) + { + fprintf (stderr, _("Invalid URI: fails to specify subsystem\n")); + return; + } + subsystem = GNUNET_strndup (uri, slash - uri); + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "uri", + subsystem, + &program)) + { + fprintf (stderr, _("No handler known for subsystem `%s'\n"), subsystem); + GNUNET_free (subsystem); + return; + } + GNUNET_free (subsystem); + rt = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_DISK_pipe_handle (sigpipe, + GNUNET_DISK_PIPE_END_READ), + &maint_child_death, NULL); + p = GNUNET_OS_start_process (GNUNET_NO, 0, + NULL, NULL, NULL, + program, + program, + orig_uri, + NULL); + GNUNET_free (program); + if (NULL == p) + GNUNET_SCHEDULER_cancel (rt); +} + + /** * Main function that will be run by the scheduler. * @@ -91,16 +175,7 @@ run (void *cls, LOG("Found %s \"%s\"\n", zbar_get_symbol_name(zbar_symbol_get_type(symbol)), data); - if (configuration == NULL) { - char* command_args[] = {"gnunet-uri", data, NULL }; - LOG("Running `gnunet-uri %s`\n", data); - exit_code = fork_and_exec(BINDIR "gnunet-uri", command_args); - } else { - char* command_args[] = {"gnunet-uri", "-c", configuration, data, NULL }; - LOG("Running `gnunet-uri -c '%s' %s`\n", configuration, data); - exit_code = fork_and_exec(BINDIR "gnunet-uri", command_args); - }; - + gnunet_uri(cls, data, cfgfile, cfg); if (exit_code != 0) { printf("Failed to add URI %s\n", data); } else { -- 2.25.1