31#define LOG(kind, ...) GNUNET_log_from (kind, "util-os-process", __VA_ARGS__)
33#define LOG_STRERROR(kind, syscall) \
34 GNUNET_log_from_strerror (kind, "util-os-process", syscall)
36#define LOG_STRERROR_FILE(kind, syscall, filename) \
37 GNUNET_log_from_strerror_file (kind, "util-os-process", syscall, \
40#define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE"
199 if (
sizeof(sig) !=
ret)
203 "GNUNET_DISK_file_read");
205 "Closing control pipe\n");
212 "Got control code %d from parent via pipe\n",
237 if ( (NULL == env_buf) ||
238 (strlen (env_buf) <= 0) )
241 "Not installing a handler because $%s is empty\n",
247 pipe_fd = strtoull (env_buf,
251 (env_buf == env_buf_end) )
261 if (pipe_fd >= FD_SETSIZE)
264 "GNUNET_OS_CONTROL_PIPE `%s' contains garbage?\n",
273 if (NULL == control_pipe)
284 "Adding parent control handler pipe `%s' to the scheduler\n",
312 char csig = (char) sig;
316 "Sending signal %d to pid: %u via pipe\n",
322 if (
sizeof(csig) == iret)
329 "Refusing to send signal %d process `%s': not running\n",
335 "Sending signal %d to pid: %u via system call\n",
368 for (
unsigned int i = 0; i < proc->
envs_size; i++)
374 for (
unsigned int i = 0; i < proc->
map_size; i++)
377 int pfd =
me->parent_fd;
386 for (
unsigned int i = 0; NULL != proc->
argv[i]; i++)
412 if ( (EBADF == errno) ||
437 fd = open (
"/dev/null",
493 flags &= ~FD_CLOEXEC;
523 for (
unsigned int i=0; i<proc->
map_size; i++)
527 if (fd ==
me->target_fd)
548 int childpipe_read_fd;
565 int dup_childpipe_read_fd = -1;
568 if (NULL == childpipe)
580 if ( (NULL == childpipe_read) ||
584 &childpipe_read_fd)) ||
585 (-1 == (dup_childpipe_read_fd = dup (childpipe_read_fd))) )
588 if (NULL != childpipe_read)
597 childpipe_read_fd = dup_childpipe_read_fd;
602 childpipe_read_fd = -1;
607 unsigned int max_fd = 3;
610 for (
unsigned int i=0; i<proc->
map_size; i++)
618 for (
unsigned int i=0; i<proc->
map_size; i++)
622 if (
me->parent_fd < pos)
624 if (
me->target_fd ==
me->parent_fd)
641 dst = dup2 (
me->parent_fd,
645 if ( (EBADF == errno) ||
675 if (0 <= childpipe_read_fd)
683 if (0 <= childpipe_read_fd)
685 for (
unsigned int i=0; i<proc->
map_size; i++)
691 if (-1 !=
me->parent_fd)
694 close (
me->parent_fd));
704 if (0 <= childpipe_read_fd)
750 unsigned int total_lfds = 0;
752 for (
unsigned int i=0; i<proc->
map_size; i++)
756 if (-1 ==
me->parent_fd)
758 if (-1 ==
me->target_fd)
760 me->target_fd = dup (
me->parent_fd);
765 else if (
me->parent_fd !=
me->target_fd)
781 if (
me->systemd_listen_socket)
803 setenv (
"LISTEN_FDS",
807 setenv (
"LISTEN_FDNAMES",
815 for (
unsigned int i=0; i<proc->
envs_size; i++)
819 if (NULL == ee->
value)
855 while (NULL != argv[argc])
859 for (argc = 0; NULL != argv[argc]; argc++)
885 while (NULL != va_arg (ap,
894 while (NULL != (av = va_arg (ap,
925 size_t len = strlen (command);
928 bool quote_on =
false;
933 for (i=0; i<len; i++)
940 quote_on = ! quote_on;
948 while (
' ' == cmd[i + 1])
957 for (i=0; i<len; i++)
964 quote_on = ! quote_on;
976 while (
' ' == cmd[i + 1])
984 cmd[i - skip] = cmd[i];
998 "Cmd `%s' has imbalanced quotes\n",
1001 if (NULL ==
p->
argv[0])
1004 "Empty command specified, cannot execute\n");
1013 "Specified binary `%s' is not executable\n",
1025 unsigned int num_options,
1028 for (
unsigned int i=0; i<num_options; i++)
1067 .systemd_listen_socket =
true,
1088 unsigned long *code)
1093 if (-1 == proc->
pid)
1102 (
ret = waitpid (proc->
pid,
1104 blocking ? 0 : WNOHANG)))
1106 if ( (! blocking) &&
1124 if ( (proc->
pid ==
ret) &&
1125 (WIFCONTINUED (
status)) )
1147 else if (WIFSIGNALED (
status))
1152 else if (WIFSTOPPED (
status))
struct GNUNET_GETOPT_CommandLineOption options[]
enum GNUNET_GenericReturnValue GNUNET_DISK_internal_file_handle_(const struct GNUNET_DISK_FileHandle *fh, int *dst)
Retrieve OS file handle.
Internal DISK related helper functions.
static int start
Set if we are to start default services (including ARM).
static int ret
Final status code.
static GNUNET_NETWORK_STRUCT_END struct GNUNET_PeerIdentity me
Our own peer identity.
static uint32_t type
Type string converted to DNS type value.
static int status
The program status; 0 for success.
static struct GNUNET_Process * p
Helper process we started.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_detach_end(struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end)
Detaches one of the ends from the pipe.
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
@ GNUNET_DISK_PF_NONE
No special options, use non-blocking read/write operations.
@ GNUNET_DISK_PIPE_END_WRITE
The writing-end of a pipe.
@ GNUNET_DISK_PIPE_END_READ
The reading-end of a pipe.
#define GNUNET_log(kind,...)
GNUNET_GenericReturnValue
Named constants for return values.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_OS_InheritStdioFlags
Flags that determine which of the standard streams should be inherited by the child process.
void GNUNET_process_install_parent_control_handler()
Connects this process to its parent via pipe; essentially, the parent control handler will read signa...
enum GNUNET_GenericReturnValue GNUNET_process_run_command_va(struct GNUNET_Process *p, const char *filename,...)
Set the command and start a process.
enum GNUNET_GenericReturnValue GNUNET_process_run_command(struct GNUNET_Process *p, const char *command)
Set the command and start a process.
enum GNUNET_GenericReturnValue GNUNET_process_run_command_argv(struct GNUNET_Process *p, const char *filename, const char **argv)
Set the command and start a process.
enum GNUNET_GenericReturnValue GNUNET_process_wait(struct GNUNET_Process *proc, bool blocking, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Wait for a process to terminate.
enum GNUNET_GenericReturnValue GNUNET_process_set_options_(struct GNUNET_Process *proc, unsigned int num_options, const struct GNUNET_ProcessOptionValue options[])
Set the requested options for the process.
enum GNUNET_GenericReturnValue GNUNET_process_run_command_ap(struct GNUNET_Process *p, const char *filename, va_list va)
Set the command and start a process.
void GNUNET_process_destroy(struct GNUNET_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
struct GNUNET_Process * GNUNET_process_current()
Get process structure for current process.
GNUNET_OS_ProcessStatusType
Process status types.
enum GNUNET_GenericReturnValue GNUNET_OS_check_helper_binary(const char *binary, bool check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
pid_t GNUNET_process_get_pid(const struct GNUNET_Process *proc)
Get the pid of the process in question.
enum GNUNET_GenericReturnValue GNUNET_process_kill(struct GNUNET_Process *proc, int sig)
Sends a signal to the process.
struct GNUNET_Process * GNUNET_process_create(enum GNUNET_OS_InheritStdioFlags std_inheritance)
Create a process handle.
@ GNUNET_OS_INHERIT_STD_IN
When this flag is set, the child process will inherit stdin of the parent.
@ GNUNET_OS_INHERIT_STD_OUT
When this flag is set, the child process will inherit stdout of the parent.
@ GNUNET_OS_INHERIT_STD_ERR
When this flag is set, the child process will inherit stderr of the parent.
@ GNUNET_OS_USE_PIPE_CONTROL
Should a pipe be used to send signals to the child?
@ GNUNET_PROCESS_OPTION_INHERIT_FD
Option to inherit file descriptors.
@ GNUNET_PROCESS_OPTION_END
End of list of options.
@ GNUNET_PROCESS_OPTION_INHERIT_LSOCK
Option to inherit a listen socket systemd-style.
@ GNUNET_PROCESS_OPTION_SET_ENVIRONMENT
Option to set environment variables.
@ GNUNET_OS_PROCESS_SIGNALED
The process was killed by a signal.
@ GNUNET_OS_PROCESS_EXITED
The process exited with a return code.
@ GNUNET_OS_PROCESS_UNKNOWN
The process is not known to the OS (or at least not one of our children).
@ GNUNET_OS_PROCESS_RUNNING
The process is still running.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
void GNUNET_SIGNAL_raise(const int sig)
Raise the given signal by calling the installed signal handlers.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_OS_CONTROL_PIPE
static void parent_control_handler(void *cls)
This handler is called when there are control data to be read on the pipe.
static struct GNUNET_Process current_process
Handle for 'this' process.
static struct GNUNET_SCHEDULER_Task * pch
Handle for the parent_control_handler() Task.
static int safe_dup2(int oldfd, int newfd)
Call dup2() in a way that races and interrupts are safely handled.
#define LOG_STRERROR_FILE(kind, syscall, filename)
static enum GNUNET_GenericReturnValue map_std(struct GNUNET_Process *proc, int fd, int flags)
Map the standard input/output/error file descriptor fd based on the mapping given in proc.
static void shutdown_pch(void *cls)
This handler is called on shutdown to remove the pch.
static struct GNUNET_SCHEDULER_Task * spch
Handle for the shutdown_pch() Task.
#define LOG_STRERROR(kind, syscall)
static enum GNUNET_GenericReturnValue clear_cloexec(int fd)
Clear the close-on-exec flag of fd.
static enum GNUNET_GenericReturnValue open_dev_null(int target_fd, int flags)
Open '/dev/null' and make the result the given file descriptor.
static enum GNUNET_GenericReturnValue process_start(struct GNUNET_Process *proc)
Key-value pairs for setenv().
char * value
Value of the environment variable.
char * key
Environment key to use.
Handle used to access files (and pipes).
Handle used to manage a pipe.
Possible options we can set for a process.
struct GNUNET_ProcessOptionValue::@34::@35 set_environment
Value of if option is GNUNET_PROCESS_OPTION_SET_ENVIRONMENT.
int target_fd
File descriptor in the target process.
const char * key
Name of the environment variable to set.
struct GNUNET_ProcessOptionValue::@34::@36 inherit_fd
Value of if option is GNUNET_PROCESS_OPTION_INHERIT_FD.
int parent_fd
File descriptor in the parent process (must be open!).
enum GNUNET_ProcessOption option
Type of the option being set.
const char * value
Value to set, NULL to clear.
union GNUNET_ProcessOptionValue::@34 details
Specific option value.
int inherit_lsock
Value of if option is GNUNET_PROCESS_OPTION_INHERIT_LSOCK.
struct EnviEntry * envs
Environment variables to set in the target process.
enum GNUNET_OS_ProcessStatusType exit_type
Runtime status of the process.
unsigned int envs_size
Length of the envs.
pid_t pid
PID of the process.
enum GNUNET_OS_InheritStdioFlags std_inheritance
What to do with stdin/stdout/stderr unless already specified in the file map.
struct ProcessFileMapEntry * map
Map of file descriptors to keep and dup2 for the new process.
char * filename
Name of the binary to execute.
char ** argv
Command-line arguments to pass, NULL-terminated.
unsigned long exit_code
Exit status code of the process, interpretation depends on exit_type.
unsigned int map_size
Length of the map.
struct GNUNET_DISK_FileHandle * control_pipe
Pipe we use to signal the process.
Entry in list of pending tasks.
Mapping of file descriptors of the current process to (desired) file descriptors of the child process...
int parent_fd
Original file descriptor of the parent process.
bool systemd_listen_socket
True if this descriptor should be passed in the style of a systemd listen socket with the respective ...
int target_fd
File descriptor to be used in the target process, -1 if it does not matter.
bool owned
True if we own this socket (and thus should also close it).