00001 #ifndef NDO_LIBNAGIOS_RUNCMD_H_INCLUDED 00002 #define NDO_LIBNAGIOS_RUNCMD_H_INCLUDED 00003 #include <signal.h> 00004 00005 /** 00006 * @file runcmd.h 00007 * @brief runcmd library function declarations 00008 * 00009 * A simple interface to executing programs from other programs, using an 00010 * optimized and safer popen()-like implementation. It is considered safer in 00011 * that no shell needs to be spawned for simple commands, and the environment 00012 * passed to the execve()'d program is essentially empty. 00013 * 00014 * This code is based on popen.c, which in turn was taken from 00015 * "Advanced Programming in the UNIX Environment" by W. Richard Stevens. 00016 * 00017 * Care has been taken to make sure the functions are async-safe. The exception 00018 * is runcmd_init() which multithreaded applications or plugins must call in a 00019 * non-reentrant manner before calling any other runcmd function. 00020 * 00021 * @note This is inherited from the nagiosplugins project, although 00022 * it might need refactoring for performance later. 00023 * @{ 00024 */ 00025 00026 /** Return code bitflags for runcmd_cmd2strv() */ 00027 #define RUNCMD_HAS_REDIR (1 << 0) /**< I/O redirection */ 00028 #define RUNCMD_HAS_SUBCOMMAND (1 << 1) /**< subcommands present */ 00029 #define RUNCMD_HAS_PAREN (1 << 2) /**< parentheses present in command */ 00030 #define RUNCMD_HAS_JOBCONTROL (1 << 3) /**< job control stuff present */ 00031 #define RUNCMD_HAS_UBSQ (1 << 4) /**< unbalanced single quotes */ 00032 #define RUNCMD_HAS_UBDQ (1 << 5) /**< unbalanced double quotes */ 00033 #define RUNCMD_HAS_WILDCARD (1 << 6) /**< wildcards present */ 00034 #define RUNCMD_HAS_SHVAR (1 << 7) /**< shell variables present */ 00035 00036 00037 #define RUNCMD_EFD (-1) /**< Failed to pipe() or open() */ 00038 #define RUNCMD_EALLOC (-2) /**< Failed to alloc */ 00039 #define RUNCMD_ECMD (-3) /**< Bad command */ 00040 #define RUNCMD_EFORK (-4) /**< Failed to fork() */ 00041 #define RUNCMD_EINVAL (-5) /**< Invalid parameters */ 00042 #define RUNCMD_EWAIT (-6) /**< Failed to wait() */ 00043 00044 /** 00045 * Initialize the runcmd library. 00046 * 00047 * Only multi-threaded programs that might launch the first external 00048 * program from multiple threads simultaneously need to bother with 00049 * this, and they must ensure this is called at least once in a non-reentrant 00050 * manner before calling any other runcmd function. 00051 */ 00052 extern void runcmd_init(void); 00053 00054 /** 00055 * Return pid of a command with a specific file descriptor 00056 * @param[in] fd stdout filedescriptor of the child to get pid from 00057 * @return pid of the child, or 0 on errors 00058 */ 00059 extern pid_t runcmd_pid(int fd); 00060 00061 /** 00062 * Return explanation of which system call or operation failed 00063 * @param code Error code returned by a library function 00064 * @return A non-free()'able string explaining where the error occurred 00065 */ 00066 extern const char *runcmd_strerror(int code); 00067 00068 /** 00069 * Start a command from a command string 00070 * @param[in] cmd The command to launch 00071 * @param[out] pfd Child's stdout filedescriptor 00072 * @param[out] pfderr Child's stderr filedescriptor 00073 * @param[in] env Currently ignored for portability 00074 * @param[in] iobreg The callback function to register the iobrokers for the read ends of the pipe 00075 * @param[in] iobregarg The "arg" value to pass to iobroker_register() 00076 */ 00077 extern int runcmd_open(const char *cmd, int *pfd, int *pfderr, char **env, 00078 void (*iobreg)(int, int, void *), void *iobregarg); 00079 00080 /** 00081 * Close a command and return its exit status 00082 * @note Don't use this. It's a retarded way to reap children suitable 00083 * only for launching a one-shot program. 00084 * 00085 * @param[in] fd The child's stdout filedescriptor 00086 * @return exit-status of the child, or -1 in case of errors 00087 */ 00088 extern int runcmd_close(int fd); 00089 00090 /** 00091 * Convert a string to a vector of arguments like a shell would 00092 * @note This might have bugs and is only tested to behave similar 00093 * to how /bin/sh does things. For csh or other non bash-ish shells 00094 * there are no guarantees. 00095 * @note The out_argv array has to be large enough to hold all strings 00096 * found in the command. 00097 * @param[in] str The string to convert to an argument vector 00098 * @param[out] out_argc The number of arguments found 00099 * @param[out] out_argv The argument vector 00100 * @return 0 on (great) success, or a bitmask of failure-codes 00101 * representing f.e. unclosed quotes, job control or output redirection. 00102 * See the RUNCMD_HAS_* and their ilk to find out about the flag. 00103 */ 00104 extern int runcmd_cmd2strv(const char *str, int *out_argc, char **out_argv); 00105 00106 /** 00107 * If you're using libnagios to execute a remote command, the 00108 * static pid_t pids is not freed after runcmd_open 00109 * You can call this function when you're sure pids is no longer 00110 * in use, to keep down memory leaks 00111 */ 00112 extern void runcmd_free_pids(void); 00113 00114 /** @} */ 00115 /* INCLUDE_runcmd_h__ */ 00116 #endif