gnunet-qr: Use the `gnunet-uri` binary installed into PREFIX.
[oweals/gnunet.git] / src / util / gnunet-qr-utils.h
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2010, 2011, 2012 Christian Grothoff
4      Copyright (C) 2019 GNUnet e.V.
5
6      GNUnet is free software: you can redistribute it and/or modify it
7      under the terms of the GNU Affero General Public License as published
8      by the Free Software Foundation, either version 3 of the License,
9      or (at your option) any later version.
10
11      GNUnet is distributed in the hope that it will be useful, but
12      WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14      Affero General Public License for more details.
15
16      You should have received a copy of the GNU Affero General Public License
17      along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19      SPDX-License-Identifier: AGPL3.0-or-later
20 */
21
22 #include "platform.h"
23
24 //
25 // FIXME: These functions are copied from dns/gnunet-helper-dns.c,
26 // move them into a common library. Or think about implementing a even
27 // more elaborate version.
28 //
29
30 /**
31  * Open '/dev/null' and make the result the given
32  * file descriptor.
33  *
34  * @param target_fd desired FD to point to /dev/null
35  * @param flags open flags (O_RDONLY, O_WRONLY)
36  */
37 static void
38 open_dev_null (int target_fd,
39                int flags)
40 {
41   int fd;
42
43   fd = open ("/dev/null", flags);
44   if (-1 == fd)
45     abort ();
46   if (fd == target_fd)
47     return;
48   if (-1 == dup2 (fd, target_fd))
49   {
50     (void) close (fd);
51     abort ();
52   }
53   (void) close (fd);
54 }
55
56 /**
57  * Run the given command and wait for it to complete.
58  *
59  * @param file name of the binary to run
60  * @param cmd command line arguments (as given to 'execv')
61  * @return 0 on success, 1 on any error
62  */
63 static int
64 fork_and_exec (const char *file,
65                char *const cmd[])
66 {
67   int status;
68   pid_t pid;
69   pid_t ret;
70
71   pid = fork ();
72   if (-1 == pid)
73   {
74     fprintf (stderr,
75              "fork failed: %s\n",
76              strerror (errno));
77     return 1;
78   }
79   if (0 == pid)
80   {
81     /* we are the child process */
82     /* close stdin/stdout to not cause interference
83        with the helper's main protocol! */
84     (void) close (0);
85     open_dev_null (0, O_RDONLY);
86     (void) close (1);
87     open_dev_null (1, O_WRONLY);
88     (void) execv (file, cmd);
89     /* can only get here on error */
90     fprintf (stderr,
91              "exec `%s' failed: %s\n",
92              file,
93              strerror (errno));
94     _exit (1);
95   }
96   /* keep running waitpid as long as the only error we get is 'EINTR' */
97   while ( (-1 == (ret = waitpid (pid, &status, 0))) &&
98           (errno == EINTR) );
99   if (-1 == ret)
100   {
101     fprintf (stderr,
102              "waitpid failed: %s\n",
103              strerror (errno));
104     return 1;
105   }
106   if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status))))
107     return 1;
108   /* child process completed and returned success, we're happy */
109   return 0;
110 }
111