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"
194 if (
sizeof(sig) !=
ret)
198 "GNUNET_DISK_file_read");
200 "Closing control pipe\n");
207 "Got control code %d from parent via pipe\n",
232 if ( (NULL == env_buf) ||
233 (strlen (env_buf) <= 0) )
236 "Not installing a handler because $%s is empty\n",
242 pipe_fd = strtoull (env_buf,
246 (env_buf == env_buf_end) )
256 if (pipe_fd >= FD_SETSIZE)
259 "GNUNET_OS_CONTROL_PIPE `%s' contains garbage?\n",
268 if (NULL == control_pipe)
279 "Adding parent control handler pipe `%s' to the scheduler\n",
307 char csig = (char) sig;
311 "Sending signal %d to pid: %u via pipe\n",
317 if (
sizeof(csig) == iret)
322 "Sending signal %d to pid: %u via system call\n",
355 for (
unsigned int i = 0; i < proc->
envs_size; i++)
361 for (
unsigned int i = 0; i < proc->
map_size; i++)
370 for (
unsigned int i = 0; NULL != proc->
argv[i]; i++)
396 if ( (EBADF == errno) ||
421 fd = open (
"/dev/null",
477 flags &= ~FD_CLOEXEC;
542 for (
unsigned int i=0; i<proc->
map_size; i++)
546 if (fd ==
me->target_fd)
566 int childpipe_read_fd;
583 int dup_childpipe_read_fd = -1;
586 if (NULL == childpipe)
598 if ( (NULL == childpipe_read) ||
602 &childpipe_read_fd)) ||
603 (-1 == (dup_childpipe_read_fd = dup (childpipe_read_fd))) )
606 if (NULL != childpipe_read)
615 childpipe_read_fd = dup_childpipe_read_fd;
620 childpipe_read_fd = -1;
625 unsigned int max_fd = 3;
628 for (
unsigned int i=0; i<proc->
map_size; i++)
636 for (
unsigned int i=0; i<proc->
map_size; i++)
640 if (
me->parent_fd < pos)
642 if (
me->target_fd ==
me->parent_fd)
659 dst = dup2 (
me->parent_fd,
663 if ( (EBADF == errno) ||
691 if (0 <= childpipe_read_fd)
699 if (0 <= childpipe_read_fd)
701 for (
unsigned int i=0; i<proc->
map_size; i++)
706 close (
me->parent_fd));
715 if (0 <= childpipe_read_fd)
761 unsigned int total_lfds = 0;
763 for (
unsigned int i=0; i<proc->
map_size; i++)
767 if (-1 ==
me->parent_fd)
769 if (-1 ==
me->target_fd)
771 me->target_fd = dup (
me->parent_fd);
774 else if (
me->parent_fd !=
me->target_fd)
784 if (
me->systemd_listen_socket)
806 setenv (
"LISTEN_FDS",
810 setenv (
"LISTEN_FDNAMES",
818 for (
unsigned int i=0; i<proc->
envs_size; i++)
822 if (NULL == ee->
value)
859 while (NULL != argv[argc])
863 for (argc = 0; NULL != argv[argc]; argc++)
889 while (NULL != va_arg (ap,
898 while (NULL != (av = va_arg (ap,
929 size_t len = strlen (command);
932 bool quote_on =
false;
937 for (i=0; i<len; i++)
944 quote_on = ! quote_on;
952 while (
' ' == cmd[i + 1])
961 for (i=0; i<len; i++)
968 quote_on = ! quote_on;
980 while (
' ' == cmd[i + 1])
988 cmd[i - skip] = cmd[i];
1002 "Cmd `%s' has imbalanced quotes\n",
1005 if (NULL ==
p->
argv[0])
1008 "Empty command specified, cannot execute\n");
1017 "Specified binary `%s' is not executable\n",
1029 unsigned int num_options,
1032 for (
unsigned int i=0; i<num_options; i++)
1073 .systemd_listen_socket =
true
1093 unsigned long *code)
1098 if (-1 == proc->
pid)
1106 while ( (proc->
pid !=
1107 (
ret = waitpid (proc->
pid,
1109 blocking ? 0 : WNOHANG))) &&
1121 if ( (proc->
pid ==
ret) &&
1122 (WIFCONTINUED (
status)) )
1144 else if (WIFSIGNALED (
status))
1149 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...
struct GNUNET_Process * GNUNET_process_create()
Create a process handle.
enum GNUNET_GenericReturnValue GNUNET_process_set_command(struct GNUNET_Process *p, const char *command)
Set the command to start a process.
enum GNUNET_GenericReturnValue GNUNET_process_set_command_ap(struct GNUNET_Process *p, const char *filename, va_list va)
Set the command to 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.
void GNUNET_process_destroy(struct GNUNET_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
enum GNUNET_GenericReturnValue GNUNET_process_start(struct GNUNET_Process *proc)
Start a process.
enum GNUNET_GenericReturnValue GNUNET_process_set_command_va(struct GNUNET_Process *p, const char *filename,...)
Set the command to start a process.
struct GNUNET_Process * GNUNET_process_current()
Get process structure for current process.
GNUNET_OS_ProcessStatusType
Process status types.
enum GNUNET_GenericReturnValue GNUNET_process_set_command_argv(struct GNUNET_Process *p, const char *filename, const char **argv)
Set the command to start a process.
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.
@ 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_PROCESS_OPTION_STD_INHERITANCE
Option to set inheritance flags.
@ 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 enum GNUNET_GenericReturnValue set_cloexec(int fd)
Set the close-on-exec flag of fd.
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.
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.
enum GNUNET_OS_InheritStdioFlags std_inheritance
Value of if option is GNUNET_PROCESS_OPTION_STD_INHERITANCE.
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.