aboutsummaryrefslogtreecommitdiff
path: root/src/cli/util/gnunet-uri.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli/util/gnunet-uri.c')
-rw-r--r--src/cli/util/gnunet-uri.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/cli/util/gnunet-uri.c b/src/cli/util/gnunet-uri.c
new file mode 100644
index 000000000..128167cc5
--- /dev/null
+++ b/src/cli/util/gnunet-uri.c
@@ -0,0 +1,192 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/gnunet-uri.c
23 * @brief tool to dispatch URIs to the appropriate GNUnet helper process
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29
30/**
31 * Handler exit code
32 */
33static long unsigned int exit_code = 0;
34
35/**
36 * Helper process we started.
37 */
38static struct GNUNET_OS_Process *p;
39
40/**
41 * Pipe used to communicate shutdown via signal.
42 */
43static struct GNUNET_DISK_PipeHandle *sigpipe;
44
45
46/**
47 * Task triggered whenever we receive a SIGCHLD (child
48 * process died) or when user presses CTRL-C.
49 *
50 * @param cls closure, NULL
51 */
52static void
53maint_child_death (void *cls)
54{
55 enum GNUNET_OS_ProcessStatusType type;
56
57 (void) cls;
58 if ((GNUNET_OK != GNUNET_OS_process_status (p, &type, &exit_code)) ||
59 (type != GNUNET_OS_PROCESS_EXITED))
60 GNUNET_break (0 == GNUNET_OS_process_kill (p, GNUNET_TERM_SIG));
61 GNUNET_OS_process_destroy (p);
62}
63
64
65/**
66 * Main function that will be run by the scheduler.
67 *
68 * @param cls closure
69 * @param args remaining command-line arguments
70 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
71 * @param cfg configuration
72 */
73static void
74run (void *cls,
75 char *const *args,
76 const char *cfgfile,
77 const struct GNUNET_CONFIGURATION_Handle *cfg)
78{
79 const char *uri;
80 const char *slash;
81 char *subsystem;
82 char *program;
83 struct GNUNET_SCHEDULER_Task *rt;
84
85 (void) cls;
86 (void) cfgfile;
87 if (NULL == (uri = args[0]))
88 {
89 fprintf (stderr, _ ("No URI specified on command line\n"));
90 return;
91 }
92 if (0 != strncasecmp ("gnunet://", uri, strlen ("gnunet://")))
93 {
94 fprintf (stderr,
95 _ ("Invalid URI: does not start with `%s'\n"),
96 "gnunet://");
97 return;
98 }
99 uri += strlen ("gnunet://");
100 if (NULL == (slash = strchr (uri, '/')))
101 {
102 fprintf (stderr, _ ("Invalid URI: fails to specify subsystem\n"));
103 return;
104 }
105 subsystem = GNUNET_strndup (uri, slash - uri);
106 if (GNUNET_OK !=
107 GNUNET_CONFIGURATION_get_value_string (cfg, "uri", subsystem, &program))
108 {
109 fprintf (stderr, _ ("No handler known for subsystem `%s'\n"), subsystem);
110 GNUNET_free (subsystem);
111 return;
112 }
113 GNUNET_free (subsystem);
114 rt = GNUNET_SCHEDULER_add_read_file (
115 GNUNET_TIME_UNIT_FOREVER_REL,
116 GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ),
117 &maint_child_death,
118 NULL);
119 p = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_NONE,
120 NULL,
121 NULL,
122 NULL,
123 program,
124 program,
125 args[0],
126 NULL);
127 GNUNET_free (program);
128 if (NULL == p)
129 GNUNET_SCHEDULER_cancel (rt);
130}
131
132
133/**
134 * Signal handler called for SIGCHLD. Triggers the
135 * respective handler by writing to the trigger pipe.
136 */
137static void
138sighandler_child_death ()
139{
140 static char c;
141 int old_errno = errno; /* back-up errno */
142
143 GNUNET_break (
144 1 ==
145 GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe,
146 GNUNET_DISK_PIPE_END_WRITE),
147 &c,
148 sizeof(c)));
149 errno = old_errno; /* restore errno */
150}
151
152
153/**
154 * The main function to handle gnunet://-URIs.
155 *
156 * @param argc number of arguments from the command line
157 * @param argv command line arguments
158 * @return 0 ok, 1 on error
159 */
160int
161main (int argc, char *const *argv)
162{
163 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
164 GNUNET_GETOPT_OPTION_END
165 };
166 struct GNUNET_SIGNAL_Context *shc_chld;
167 int ret;
168
169 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
170 return 2;
171 sigpipe = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
172 GNUNET_assert (sigpipe != NULL);
173 shc_chld =
174 GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
175 ret = GNUNET_PROGRAM_run (argc,
176 argv,
177 "gnunet-uri URI",
178 gettext_noop (
179 "Perform default-actions for GNUnet URIs"),
180 options,
181 &run,
182 NULL);
183 GNUNET_SIGNAL_handler_uninstall (shc_chld);
184 shc_chld = NULL;
185 GNUNET_DISK_pipe_close (sigpipe);
186 sigpipe = NULL;
187 GNUNET_free_nz ((void *) argv);
188 return ((GNUNET_OK == ret) && (0 == exit_code)) ? 0 : 1;
189}
190
191
192/* end of gnunet-uri.c */