--- plugins/check_by_ssh.c +++ plugins/check_by_ssh.c @@ -38,8 +38,11 @@ const char *email = "nagiosplug-devel@li #include "netutils.h" #include "utils.h" #include "runcmd.h" +#ifndef MAXARGS +#define MAXARGS 255 +#endif -int process_arguments (int, char **); +int process_arguments (int, char **, char **); int validate_arguments (void); void print_help (void); void print_usage (void); @@ -49,7 +52,6 @@ unsigned int services = 0; int skip_stdout = 0; int skip_stderr = 0; char *remotecmd = NULL; -char *comm = NULL; char *hostname = NULL; char *outputfile = NULL; char *host_shortname = NULL; @@ -68,9 +70,16 @@ main (int argc, char **argv) time_t local_time; FILE *fp = NULL; struct output chld_out, chld_err; + char **newargv; + + + if ((newargv = calloc ((MAXARGS + 1), sizeof(char *))) == NULL) + printf (_("malloc failed")); + + newargv[MAXARGS] = (char *)1; remotecmd = ""; - comm = strdup (SSH_COMMAND); + newargv[0] = strdup (SSH_COMMAND); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -80,7 +89,7 @@ main (int argc, char **argv) argv=np_extra_opts (&argc, argv, progname); /* process arguments */ - if (process_arguments (argc, argv) == ERROR) + if (process_arguments (argc, argv, newargv) == ERROR) usage_va(_("Could not parse arguments")); /* Set signal handling and alarm timeout */ @@ -90,11 +99,28 @@ main (int argc, char **argv) alarm (timeout_interval); /* run the command */ - if (verbose) - printf ("%s\n", comm); + if (verbose) { + printf ("%s ", newargv[0]); + for (i=1; i <= MAXARGS; i++) { + if (newargv[i] > (char *)1 ) { + printf ("'%s' ", newargv[i]); + } + } + printf ("\n"); + } + + result = np_runcmdv(newargv[0], newargv, &chld_out, &chld_err, 0); - result = np_runcmd(comm, &chld_out, &chld_err, 0); + // free memory to prevent valgrind errors + for (i=0; i <= MAXARGS; i++) { + if (newargv[i] > (char *)1 ) { + free (newargv[i]); + newargv[i]=0; + } + } + free (newargv); + if (skip_stdout == -1) /* --skip-stdout specified without argument */ skip_stdout = chld_out.lines; if (skip_stderr == -1) /* --skip-stderr specified without argument */ @@ -152,10 +178,11 @@ main (int argc, char **argv) /* process command-line arguments */ int -process_arguments (int argc, char **argv) +process_arguments (int argc, char **argv, char **newargv) { int c; char *p1, *p2; + char **opts = newargv + 2; int option = 0; static struct option longopts[] = { @@ -222,7 +249,8 @@ process_arguments (int argc, char **argv case 'p': /* port number */ if (!is_integer (optarg)) usage_va(_("Port must be a positive integer")); - asprintf (&comm,"%s -p %s", comm, optarg); + add_argument (&opts, "-p"); + add_argument (&opts, optarg); break; case 'O': /* output file */ outputfile = optarg; @@ -246,16 +274,27 @@ process_arguments (int argc, char **argv case 'u': c = 'l'; case 'l': /* login name */ + add_argument (&opts, "-l"); + add_argument (&opts, optarg); + break; case 'i': /* identity */ - asprintf (&comm, "%s -%c %s", comm, c, optarg); + add_argument (&opts, "-i"); + add_argument (&opts, optarg); break; - case '1': /* Pass these switches directly to ssh */ + add_argument (&opts, "-1"); + break; case '2': /* 1 to force version 1, 2 to force version 2 */ + add_argument (&opts, "-2"); + break; case '4': /* -4 for IPv4 */ - case '6': /* -6 for IPv6 */ + add_argument (&opts, "-4"); + break; + case '6': /* -6 for IPv6 */ + add_argument (&opts, "-6"); + break; case 'f': /* fork to background */ - asprintf (&comm, "%s -%c", comm, c); + add_argument (&opts, "-f"); break; case 'C': /* Command for remote machine */ commands++; @@ -280,10 +319,11 @@ process_arguments (int argc, char **argv skip_stderr = atoi (optarg); break; case 'o': /* Extra options for the ssh command */ - asprintf (&comm, "%s -%c '%s'", comm, c, optarg); + add_argument (&opts, "-o"); + add_argument (&opts, optarg); break; case 'q': /* Tell the ssh command to be quiet */ - asprintf (&comm, "%s -%c", comm, c); + add_argument (&opts, "-q"); break; default: /* help */ usage5(); @@ -313,12 +353,25 @@ process_arguments (int argc, char **argv if (remotecmd == NULL || strlen (remotecmd) <= 1) usage_va(_("No remotecmd")); - asprintf (&comm, "%s %s '%s'", comm, hostname, remotecmd); + add_argument (&opts, remotecmd); + opts = newargv+1; + add_argument (&opts, hostname); return validate_arguments (); } +int add_argument (char ***argv, const char *str) +{ + + if (**argv == (char *)1) + die (STATE_UNKNOWN, _("%s: Argument limit of %d exceeded\n"), progname, MAXARGS); + **argv = (char *)malloc((strlen(str) * sizeof(char)) +1); + + strcpy(**argv, str); + (*argv)++; + return 0; +} int validate_arguments (void) --- plugins/runcmd.c +++ plugins/runcmd.c @@ -46,6 +46,7 @@ #ifdef HAVE_SYS_WAIT_H # include #endif +#include /** macros **/ #ifndef WEXITSTATUS @@ -87,6 +88,8 @@ static long maxfd = 0; static int np_runcmd_open(const char *, int *, int *) __attribute__((__nonnull__(1, 2, 3))); +static int np_runcmd_open_argv(const char *, char **, int *, int *); + static int np_fetch_output(int, output *, int) __attribute__((__nonnull__(2))); @@ -118,24 +121,14 @@ void np_runcmd_init(void) static int np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr) { - char *env[2]; char *cmd = NULL; char **argv = NULL; char *str; int argc; size_t cmdlen; - pid_t pid; -#ifdef RLIMIT_CORE - struct rlimit limit; -#endif int i = 0; - if(!np_pids) NP_RUNCMD_INIT; - - env[0] = strdup("LC_ALL=C"); - env[1] = '\0'; - /* if no command was passed, return with no error */ if (cmdstring == NULL) return -1; @@ -191,6 +184,35 @@ np_runcmd_open(const char *cmdstring, in argv[i++] = str; } + + return (np_runcmd_open_argv(argv[0], argv, pfd, pfderr)); +} + +static int +np_runcmd_open_argv(const char *cmdstring, char **argv, int *pfd, int *pfderr) +{ + char *env[2]; + pid_t pid; +#ifdef RLIMIT_CORE + struct rlimit limit; +#endif + + int i = 0; + int master,slave; + + if(!np_pids) NP_RUNCMD_INIT; + + env[0] = strdup("LC_ALL=C"); + env[1] = '\0'; + + /* if no command was passed, return with an error */ + if (cmdstring == NULL) + return -1; + + /* make sure that the command name is also argv[0] */ + if (strcmp(cmdstring, argv[0]) != 0) + return -1; + if (pipe(pfd) < 0 || pipe(pfderr) < 0 || (pid = fork()) < 0) return -1; /* errno set by the failing function */ @@ -202,6 +224,11 @@ np_runcmd_open(const char *cmdstring, in limit.rlim_cur = 0; setrlimit (RLIMIT_CORE, &limit); #endif +#ifdef TIOCNOTTY + /* disassociate from tty to prevent e.g. ssh asking for passwords */ + if(isatty(STDOUT_FILENO)) + ioctl(STDOUT_FILENO, TIOCNOTTY); +#endif close (pfd[0]); if (pfd[1] != STDOUT_FILENO) { dup2 (pfd[1], STDOUT_FILENO); @@ -235,7 +262,6 @@ np_runcmd_open(const char *cmdstring, in return pfd[0]; } - static int np_runcmd_close(int fd) { @@ -360,3 +386,21 @@ np_runcmd(const char *cmd, output *out, return np_runcmd_close(fd); } + +int +np_runcmdv(const char *cmd, char ** argv, output *out, output *err, int flags) +{ + int fd, pfd_out[2], pfd_err[2]; + + /* initialize the structs */ + if(out) memset(out, 0, sizeof(output)); + if(err) memset(err, 0, sizeof(output)); + + if((fd = np_runcmd_open_argv(cmd, argv, pfd_out, pfd_err)) == -1) + die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); + + if(out) out->lines = np_fetch_output(pfd_out[0], out, flags); + if(err) err->lines = np_fetch_output(pfd_err[0], err, flags); + + return np_runcmd_close(fd); +} --- plugins/runcmd.h +++ plugins/runcmd.h @@ -40,6 +40,7 @@ typedef struct output output; /** prototypes **/ int np_runcmd(const char *, output *, output *, int); +int np_runcmdv(const char *, char **, output *, output *, int); void popen_timeout_alarm_handler(int) __attribute__((__noreturn__));