[PATCH] Move *NIX functions into separate file.
by emaste@adaranet.com
This is in advance of changes to bring in FreeBSD support.
Sponsored-by: ADARA Networks
Signed-off-by: Ed Maste <emaste(a)adaranet.com>
---
Build- and sanity-tested on CentOS 6.3, this change mirrors refactoring in
my github repo for the FreeBSD port.
src/Makefile.am | 4 +
src/drv_debian.c | 1 +
src/drv_redhat.c | 1 +
src/drv_suse.c | 1 +
src/dutil_linux.c | 238 -----------------------------------------
src/dutil_linux.h | 22 ----
src/dutil_posix.c | 306 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/dutil_posix.h | 57 ++++++++++
8 files changed, 370 insertions(+), 260 deletions(-)
create mode 100644 src/dutil_posix.c
create mode 100644 src/dutil_posix.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 008629d..97ccbbe 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,6 +24,7 @@ endif
DRIVER_SOURCES_COMMON = dutil.h dutil.c
DRIVER_SOURCES_LINUX = dutil_linux.h dutil_linux.c
DRIVER_SOURCES_MSWINDOWS = dutil_mswindows.h dutil_mswindows.c drv_mswindows.c
+DRIVER_SOURCES_POSIX = dutil_posix.c
DRIVER_SOURCES_REDHAT = drv_redhat.c
DRIVER_SOURCES_DEBIAN = drv_debian.c
DRIVER_SOURCES_SUSE = drv_suse.c
@@ -42,18 +43,21 @@ EXTRA_DIST = netcf_public.syms \
if NETCF_DRIVER_REDHAT
DRIVER_SOURCES = \
$(DRIVER_SOURCES_COMMON) \
+ $(DRIVER_SOURCES_POSIX) \
$(DRIVER_SOURCES_LINUX) \
$(DRIVER_SOURCES_REDHAT)
endif
if NETCF_DRIVER_DEBIAN
DRIVER_SOURCES = \
$(DRIVER_SOURCES_COMMON) \
+ $(DRIVER_SOURCES_POSIX) \
$(DRIVER_SOURCES_LINUX) \
$(DRIVER_SOURCES_DEBIAN)
endif
if NETCF_DRIVER_SUSE
DRIVER_SOURCES = \
$(DRIVER_SOURCES_COMMON) \
+ $(DRIVER_SOURCES_POSIX) \
$(DRIVER_SOURCES_LINUX) \
$(DRIVER_SOURCES_SUSE)
endif
diff --git a/src/drv_debian.c b/src/drv_debian.c
index d264dce..ceeed94 100644
--- a/src/drv_debian.c
+++ b/src/drv_debian.c
@@ -36,6 +36,7 @@
#include "ref.h"
#include "list.h"
#include "dutil.h"
+#include "dutil_posix.h"
#include "dutil_linux.h"
#include <libxml/parser.h>
diff --git a/src/drv_redhat.c b/src/drv_redhat.c
index 40658dd..4040f5e 100644
--- a/src/drv_redhat.c
+++ b/src/drv_redhat.c
@@ -36,6 +36,7 @@
#include "ref.h"
#include "list.h"
#include "dutil.h"
+#include "dutil_posix.h"
#include "dutil_linux.h"
#include <libxml/parser.h>
diff --git a/src/drv_suse.c b/src/drv_suse.c
index f88764c..0d4a0af 100644
--- a/src/drv_suse.c
+++ b/src/drv_suse.c
@@ -42,6 +42,7 @@
#include "ref.h"
#include "list.h"
#include "dutil.h"
+#include "dutil_posix.h"
#include "dutil_linux.h"
#include <libxml/parser.h>
diff --git a/src/dutil_linux.c b/src/dutil_linux.c
index da7a586..1fe9b26 100644
--- a/src/dutil_linux.c
+++ b/src/dutil_linux.c
@@ -100,224 +100,6 @@ static struct nl_cache *__rtnl_addr_alloc_cache(struct nl_sock *sk)
}
/*
- * Executing external programs
- */
-
-static int
-exec_program(struct netcf *ncf,
- const char *const*argv,
- const char *commandline,
- pid_t *pid,
- int *outfd)
-{
- sigset_t oldmask, newmask;
- struct sigaction sig_action;
- char errbuf[128];
- int pipeout[2] = {-1, -1};
-
- /* commandline is only used for error reporting */
- if (commandline == NULL)
- commandline = argv[0];
-
- /* create a pipe to receive stdout+stderr from child */
- if (outfd) {
- if (pipe(pipeout) < 0) {
- report_error(ncf, NETCF_EEXEC,
- "failed to create pipe while forking for '%s': %s",
- commandline, strerror_r(errno, errbuf, sizeof(errbuf)));
- goto error;
- }
- *outfd = pipeout[0];
- }
-
- /*
- * Need to block signals now, so that child process can safely
- * kill off caller's signal handlers without a race.
- */
- sigfillset(&newmask);
- if (pthread_sigmask(SIG_SETMASK, &newmask, &oldmask) != 0) {
- report_error(ncf, NETCF_EEXEC,
- "failed to set signal mask while forking for '%s': %s",
- commandline, strerror_r(errno, errbuf, sizeof(errbuf)));
- goto error;
- }
-
- *pid = fork();
-
- ERR_THROW(*pid < 0, ncf, EEXEC, "failed to fork for '%s': %s",
- commandline, strerror_r(errno, errbuf, sizeof(errbuf)));
-
- if (*pid) { /* parent */
- /* Restore our original signal mask now that the child is
- safely running */
- ERR_THROW(pthread_sigmask(SIG_SETMASK, &oldmask, NULL) != 0,
- ncf, EEXEC,
- "failed to restore signal mask while forking for '%s': %s",
- commandline, strerror_r(errno, errbuf, sizeof(errbuf)));
-
- /* parent doesn't use write side of the pipe */
- if (pipeout[1] >= 0)
- close(pipeout[1]);
-
- return 0;
- }
-
- /* child */
-
- /* Clear out all signal handlers from parent so nothing unexpected
- can happen in our child once we unblock signals */
-
- sig_action.sa_handler = SIG_DFL;
- sig_action.sa_flags = 0;
- sigemptyset(&sig_action.sa_mask);
-
- int i;
- for (i = 1; i < NSIG; i++) {
- /* Only possible errors are EFAULT or EINVAL
- The former wont happen, the latter we
- expect, so no need to check return value */
-
- sigaction(i, &sig_action, NULL);
- }
-
- /* Unmask all signals in child, since we've no idea what the
- caller's done with their signal mask and don't want to
- propagate that to children */
- sigemptyset(&newmask);
- if (pthread_sigmask(SIG_SETMASK, &newmask, NULL) != 0) {
- /* return a unique code and let the parent log the error */
- _exit(EXIT_SIGMASK);
- }
-
- if (pipeout[1] >= 0) {
- /* direct stdout and stderr to the pipe */
- if (dup2(pipeout[1], fileno(stdout)) < 0
- || dup2(pipeout[1], fileno(stderr)) < 0) {
- /* return a unique code and let the parent log the error */
- _exit(EXIT_DUP2);
- }
- }
- /* child doesn't use the read side of the pipe */
- if (pipeout[0] >= 0)
- close(pipeout[0]);
-
- /* close all open file descriptors */
- int openmax = sysconf (_SC_OPEN_MAX);
- for (i = 3; i < openmax; i++)
- close(i);
-
- execvp(argv[0], (char **) argv);
-
- /* if execvp() returns, it has failed */
- /* return a unique code and let the parent log the error */
- _exit(errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
-
-error:
- /* This is cleanup of parent process only - child
- should never jump here on error */
- if (pipeout[0] >= 0)
- close(pipeout[0]);
- if (pipeout[1] >= 0)
- close(pipeout[1]);
- if (outfd)
- *outfd = -1;
- return -1;
-}
-
-/**
- * Run a command without using the shell.
- *
- * return 0 if the command run and exited with 0 status; Otherwise
- * return -1
- *
- */
-int run_program(struct netcf *ncf, const char *const *argv, char **output)
-{
-
- pid_t childpid = -1;
- int exitstatus, waitret;
- char *argv_str;
- int ret = -1;
- char errbuf[128];
- char *outtext = NULL;
- int outfd = -1;
- FILE *outfile = NULL;
- size_t outlen;
-
- if (!output)
- output = &outtext;
-
- argv_str = argv_to_string(argv);
- ERR_NOMEM(argv_str == NULL, ncf);
-
- exec_program(ncf, argv, argv_str, &childpid, &outfd);
- ERR_BAIL(ncf);
-
- outfile = fdopen(outfd, "r");
- ERR_THROW(outfile == NULL, ncf, EEXEC,
- "Failed to create file stream for output while executing '%s': %s",
- argv_str, strerror_r(errno, errbuf, sizeof(errbuf)));
-
- *output = fread_file(outfile, &outlen);
- ERR_THROW(*output == NULL, ncf, EEXEC,
- "Error while reading output from execution of '%s': %s",
- argv_str, strerror_r(errno, errbuf, sizeof(errbuf)));
-
- /* finished with the stream. Close it so the child can exit. */
- fclose(outfile);
- outfile = NULL;
-
- while ((waitret = waitpid(childpid, &exitstatus, 0) == -1) &&
- errno == EINTR) {
- /* empty loop */
- }
-
- ERR_THROW(waitret == -1, ncf, EEXEC,
- "Failed waiting for completion of '%s': %s",
- argv_str, strerror_r(errno, errbuf, sizeof(errbuf)));
- ERR_THROW(!WIFEXITED(exitstatus) && WIFSIGNALED(exitstatus), ncf, EEXEC,
- "'%s' terminated by signal: %d",
- argv_str, WTERMSIG(exitstatus));
- ERR_THROW(!WIFEXITED(exitstatus), ncf, EEXEC,
- "'%s' terminated improperly", argv_str);
- ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_ENOENT, ncf, EEXEC,
- "Running '%s' program not found", argv_str);
- ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_CANNOT_INVOKE, ncf, EEXEC,
- "Running '%s' program located but not usable", argv_str);
- ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_SIGMASK, ncf, EEXEC,
- "Running '%s' failed to reset child process signal mask",
- argv_str);
- ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_DUP2, ncf, EEXEC,
- "Running '%s' failed to dup2 child process stdout/stderr",
- argv_str);
- ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_INVALID_IN_THIS_STATE, ncf, EINVALIDOP,
- "Running '%s' operation is invalid in this state",
- argv_str);
- ERR_THROW(WEXITSTATUS(exitstatus) != 0, ncf, EEXEC,
- "Running '%s' failed with exit code %d: %s",
- argv_str, WEXITSTATUS(exitstatus), *output);
- ret = 0;
-
-error:
- if (outfile)
- fclose(outfile);
- else if (outfd >= 0)
- close(outfd);
- FREE(outtext);
- FREE(argv_str);
- return ret;
-}
-
-/* Run the program PROG with the single argument ARG */
-void run1(struct netcf *ncf, const char *prog, const char *arg) {
- const char *const argv[] = {
- prog, arg, NULL
- };
-
- run_program(ncf, argv, NULL);
-}
-
-/*
* augeas-related utilities
*/
int add_augeas_xfm_table(struct netcf *ncf,
@@ -671,26 +453,6 @@ void modprobed_unalias_bond(struct netcf *ncf, const char *name) {
* ioctl and netlink-related utilities
*/
-int init_ioctl_fd(struct netcf *ncf) {
- int ioctl_fd;
- int flags;
-
- ioctl_fd = socket(AF_INET, SOCK_STREAM, 0);
- ERR_THROW(ioctl_fd < 0, ncf, EINTERNAL, "failed to open socket for interface ioctl");
-
- flags = fcntl(ioctl_fd, F_GETFD);
- ERR_THROW(flags < 0, ncf, EINTERNAL, "failed to get flags for ioctl socket");
-
- flags = fcntl(ioctl_fd, F_SETFD, flags | FD_CLOEXEC);
- ERR_THROW(flags < 0, ncf, EINTERNAL, "failed to set FD_CLOEXEC flag on ioctl socket");
- return ioctl_fd;
-
-error:
- if (ioctl_fd >= 0)
- close(ioctl_fd);
- return -1;
-}
-
int if_is_active(struct netcf *ncf, const char *intf) {
struct ifreq ifr;
diff --git a/src/dutil_linux.h b/src/dutil_linux.h
index 4b122db..64fe64f 100644
--- a/src/dutil_linux.h
+++ b/src/dutil_linux.h
@@ -58,25 +58,6 @@ struct augeas_xfm_table {
};
-enum
-{
- EXIT_DUP2=124, /* dup2() of stdout/stderr in child failed */
- EXIT_SIGMASK=125, /* failed to reset signal mask of child */
- EXIT_CANNOT_INVOKE=126, /* program located, but not usable. */
- EXIT_ENOENT=127, /* could not find program to execute */
-
- /* any application-specific exit codes returned by the exec'ed
- * binary should be in the range 193-199 to avoid various
- *ambiguities (confusion with signals, truncation...
- */
- /* NB: the following code matches that in the netcf-transact script */
- EXIT_INVALID_IN_THIS_STATE=199, /* wrong state to perform this operation */
-};
-
-/* run an external program */
-int run_program(struct netcf *ncf, const char *const *argv, char **output);
-void run1(struct netcf *ncf, const char *prog, const char *arg);
-
/* Add a table of transformations that the next GET_AUGEAS should run */
int add_augeas_xfm_table(struct netcf *ncf,
const struct augeas_xfm_table *table);
@@ -128,9 +109,6 @@ void modprobed_alias_bond(struct netcf *ncf, const char *name);
/* Remove an 'alias NAME bonding' as created by modprobed_alias_bond */
void modprobed_unalias_bond(struct netcf *ncf, const char *name);
-/* Get a file descriptor to a ioctl socket */
-int init_ioctl_fd(struct netcf *ncf);
-
/* setup the netlink socket */
int netlink_init(struct netcf *ncf);
diff --git a/src/dutil_posix.c b/src/dutil_posix.c
new file mode 100644
index 0000000..609d7bd
--- /dev/null
+++ b/src/dutil_posix.c
@@ -0,0 +1,306 @@
+/*
+ * dutil_posix.c: *NIX utility functions for driver backends.
+ *
+ * Copyright (C) 2009-2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+#include <internal.h>
+
+#include <augeas.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <dirent.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <c-ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "safe-alloc.h"
+#include "read-file.h"
+#include "ref.h"
+#include "list.h"
+#include "netcf.h"
+#include "dutil.h"
+#include "dutil_posix.h"
+
+/*
+ * Executing external programs
+ */
+
+static int
+exec_program(struct netcf *ncf,
+ const char *const*argv,
+ const char *commandline,
+ pid_t *pid,
+ int *outfd)
+{
+ sigset_t oldmask, newmask;
+ struct sigaction sig_action;
+ char errbuf[128];
+ int pipeout[2] = {-1, -1};
+
+ /* commandline is only used for error reporting */
+ if (commandline == NULL)
+ commandline = argv[0];
+
+ /* create a pipe to receive stdout+stderr from child */
+ if (outfd) {
+ if (pipe(pipeout) < 0) {
+ report_error(ncf, NETCF_EEXEC,
+ "failed to create pipe while forking for '%s': %s",
+ commandline, strerror_r(errno, errbuf, sizeof(errbuf)));
+ goto error;
+ }
+ *outfd = pipeout[0];
+ }
+
+ /*
+ * Need to block signals now, so that child process can safely
+ * kill off caller's signal handlers without a race.
+ */
+ sigfillset(&newmask);
+ if (pthread_sigmask(SIG_SETMASK, &newmask, &oldmask) != 0) {
+ report_error(ncf, NETCF_EEXEC,
+ "failed to set signal mask while forking for '%s': %s",
+ commandline, strerror_r(errno, errbuf, sizeof(errbuf)));
+ goto error;
+ }
+
+ *pid = fork();
+
+ ERR_THROW(*pid < 0, ncf, EEXEC, "failed to fork for '%s': %s",
+ commandline, strerror_r(errno, errbuf, sizeof(errbuf)));
+
+ if (*pid) { /* parent */
+ /* Restore our original signal mask now that the child is
+ safely running */
+ ERR_THROW(pthread_sigmask(SIG_SETMASK, &oldmask, NULL) != 0,
+ ncf, EEXEC,
+ "failed to restore signal mask while forking for '%s': %s",
+ commandline, strerror_r(errno, errbuf, sizeof(errbuf)));
+
+ /* parent doesn't use write side of the pipe */
+ if (pipeout[1] >= 0)
+ close(pipeout[1]);
+
+ return 0;
+ }
+
+ /* child */
+
+ /* Clear out all signal handlers from parent so nothing unexpected
+ can happen in our child once we unblock signals */
+
+ sig_action.sa_handler = SIG_DFL;
+ sig_action.sa_flags = 0;
+ sigemptyset(&sig_action.sa_mask);
+
+ int i;
+ for (i = 1; i < NSIG; i++) {
+ /* Only possible errors are EFAULT or EINVAL
+ The former wont happen, the latter we
+ expect, so no need to check return value */
+
+ sigaction(i, &sig_action, NULL);
+ }
+
+ /* Unmask all signals in child, since we've no idea what the
+ caller's done with their signal mask and don't want to
+ propagate that to children */
+ sigemptyset(&newmask);
+ if (pthread_sigmask(SIG_SETMASK, &newmask, NULL) != 0) {
+ /* return a unique code and let the parent log the error */
+ _exit(EXIT_SIGMASK);
+ }
+
+ if (pipeout[1] >= 0) {
+ /* direct stdout and stderr to the pipe */
+ if (dup2(pipeout[1], fileno(stdout)) < 0
+ || dup2(pipeout[1], fileno(stderr)) < 0) {
+ /* return a unique code and let the parent log the error */
+ _exit(EXIT_DUP2);
+ }
+ }
+ /* child doesn't use the read side of the pipe */
+ if (pipeout[0] >= 0)
+ close(pipeout[0]);
+
+ /* close all open file descriptors */
+ int openmax = sysconf (_SC_OPEN_MAX);
+ for (i = 3; i < openmax; i++)
+ close(i);
+
+ execvp(argv[0], (char **) argv);
+
+ /* if execvp() returns, it has failed */
+ /* return a unique code and let the parent log the error */
+ _exit(errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+
+error:
+ /* This is cleanup of parent process only - child
+ should never jump here on error */
+ if (pipeout[0] >= 0)
+ close(pipeout[0]);
+ if (pipeout[1] >= 0)
+ close(pipeout[1]);
+ if (outfd)
+ *outfd = -1;
+ return -1;
+}
+
+/**
+ * Run a command without using the shell.
+ *
+ * return 0 if the command run and exited with 0 status; Otherwise
+ * return -1
+ *
+ */
+int run_program(struct netcf *ncf, const char *const *argv, char **output)
+{
+
+ pid_t childpid = -1;
+ int exitstatus, waitret;
+ char *argv_str;
+ int ret = -1;
+ char errbuf[128];
+ char *outtext = NULL;
+ int outfd = -1;
+ FILE *outfile = NULL;
+ size_t outlen;
+
+ if (!output)
+ output = &outtext;
+
+ argv_str = argv_to_string(argv);
+ ERR_NOMEM(argv_str == NULL, ncf);
+
+ exec_program(ncf, argv, argv_str, &childpid, &outfd);
+ ERR_BAIL(ncf);
+
+ outfile = fdopen(outfd, "r");
+ ERR_THROW(outfile == NULL, ncf, EEXEC,
+ "Failed to create file stream for output while executing '%s': %s",
+ argv_str, strerror_r(errno, errbuf, sizeof(errbuf)));
+
+ *output = fread_file(outfile, &outlen);
+ ERR_THROW(*output == NULL, ncf, EEXEC,
+ "Error while reading output from execution of '%s': %s",
+ argv_str, strerror_r(errno, errbuf, sizeof(errbuf)));
+
+ /* finished with the stream. Close it so the child can exit. */
+ fclose(outfile);
+ outfile = NULL;
+
+ while ((waitret = waitpid(childpid, &exitstatus, 0) == -1) &&
+ errno == EINTR) {
+ /* empty loop */
+ }
+
+ ERR_THROW(waitret == -1, ncf, EEXEC,
+ "Failed waiting for completion of '%s': %s",
+ argv_str, strerror_r(errno, errbuf, sizeof(errbuf)));
+ ERR_THROW(!WIFEXITED(exitstatus) && WIFSIGNALED(exitstatus), ncf, EEXEC,
+ "'%s' terminated by signal: %d",
+ argv_str, WTERMSIG(exitstatus));
+ ERR_THROW(!WIFEXITED(exitstatus), ncf, EEXEC,
+ "'%s' terminated improperly", argv_str);
+ ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_ENOENT, ncf, EEXEC,
+ "Running '%s' program not found", argv_str);
+ ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_CANNOT_INVOKE, ncf, EEXEC,
+ "Running '%s' program located but not usable", argv_str);
+ ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_SIGMASK, ncf, EEXEC,
+ "Running '%s' failed to reset child process signal mask",
+ argv_str);
+ ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_DUP2, ncf, EEXEC,
+ "Running '%s' failed to dup2 child process stdout/stderr",
+ argv_str);
+ ERR_THROW(WEXITSTATUS(exitstatus) == EXIT_INVALID_IN_THIS_STATE, ncf, EINVALIDOP,
+ "Running '%s' operation is invalid in this state",
+ argv_str);
+ ERR_THROW(WEXITSTATUS(exitstatus) != 0, ncf, EEXEC,
+ "Running '%s' failed with exit code %d: %s",
+ argv_str, WEXITSTATUS(exitstatus), *output);
+ ret = 0;
+
+error:
+ if (outfile)
+ fclose(outfile);
+ else if (outfd >= 0)
+ close(outfd);
+ FREE(outtext);
+ FREE(argv_str);
+ return ret;
+}
+
+/* Run the program PROG with the single argument ARG */
+void run1(struct netcf *ncf, const char *prog, const char *arg) {
+ const char *const argv[] = {
+ prog, arg, NULL
+ };
+
+ run_program(ncf, argv, NULL);
+}
+
+/*
+ * ioctl and netlink-related utilities
+ */
+
+int init_ioctl_fd(struct netcf *ncf) {
+ int ioctl_fd;
+ int flags;
+
+ ioctl_fd = socket(AF_INET, SOCK_STREAM, 0);
+ ERR_THROW(ioctl_fd < 0, ncf, EINTERNAL, "failed to open socket for interface ioctl");
+
+ flags = fcntl(ioctl_fd, F_GETFD);
+ ERR_THROW(flags < 0, ncf, EINTERNAL, "failed to get flags for ioctl socket");
+
+ flags = fcntl(ioctl_fd, F_SETFD, flags | FD_CLOEXEC);
+ ERR_THROW(flags < 0, ncf, EINTERNAL, "failed to set FD_CLOEXEC flag on ioctl socket");
+ return ioctl_fd;
+
+error:
+ if (ioctl_fd >= 0)
+ close(ioctl_fd);
+ return -1;
+}
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+/* vim: set ts=4 sw=4 et: */
diff --git a/src/dutil_posix.h b/src/dutil_posix.h
new file mode 100644
index 0000000..097ce32
--- /dev/null
+++ b/src/dutil_posix.h
@@ -0,0 +1,57 @@
+/*
+ * dutil_posix.h: *NIX utility functions for driver backends.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef DUTIL_POSIX_H_
+#define DUTIL_POSIX_H_
+
+enum
+{
+ EXIT_DUP2=124, /* dup2() of stdout/stderr in child failed */
+ EXIT_SIGMASK=125, /* failed to reset signal mask of child */
+ EXIT_CANNOT_INVOKE=126, /* program located, but not usable. */
+ EXIT_ENOENT=127, /* could not find program to execute */
+
+ /* any application-specific exit codes returned by the exec'ed
+ * binary should be in the range 193-199 to avoid various
+ *ambiguities (confusion with signals, truncation...
+ */
+ /* NB: the following code matches that in the netcf-transact script */
+ EXIT_INVALID_IN_THIS_STATE=199, /* wrong state to perform this operation */
+};
+
+/* run an external program */
+int run_program(struct netcf *ncf, const char *const *argv, char **output);
+void run1(struct netcf *ncf, const char *prog, const char *arg);
+
+/* Get a file descriptor to a ioctl socket */
+int init_ioctl_fd(struct netcf *ncf);
+
+#endif
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+/* vim: set ts=4 sw=4 et: */
--
1.7.10.3
11 years, 5 months