Code

initial merging of ae's np_runcmd code into selected plugins.
[nagiosplug.git] / plugins / check_by_ssh.c
index 2ceee28f85441df7259a0583f4e09e1711559ae8..b777b072f65d9d325b8ef873bb93f0a4d55c22fc 100644 (file)
@@ -26,7 +26,7 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net";
 #include "common.h"
 #include "netutils.h"
 #include "utils.h"
-#include "popen.h"
+#include "runcmd.h"
 
 int process_arguments (int, char **);
 int validate_arguments (void);
@@ -35,7 +35,7 @@ void print_usage (void);
 
 int commands = 0;
 int services = 0;
-int skip_lines = 0;
+int skip = 0;
 char *remotecmd = NULL;
 char *comm = NULL;
 char *hostname = NULL;
@@ -49,19 +49,16 @@ int
 main (int argc, char **argv)
 {
 
-       char input_buffer[MAX_INPUT_BUFFER];
-       char *result_text;
        char *status_text;
-       char *output;
-       char *eol = NULL;
        int cresult;
        int result = STATE_UNKNOWN;
+       int i;
        time_t local_time;
        FILE *fp = NULL;
+       struct output chld_out, chld_err;
 
-       remotecmd = strdup ("");
+       remotecmd = "";
        comm = strdup (SSH_COMMAND);
-       result_text = strdup ("");
 
        setlocale (LC_ALL, "");
        bindtextdomain (PACKAGE, LOCALEDIR);
@@ -69,100 +66,62 @@ main (int argc, char **argv)
 
        /* process arguments */
        if (process_arguments (argc, argv) == ERROR)
-               usage(_("Could not parse arguments"));
+               usage_va(_("Could not parse arguments"));
 
        /* Set signal handling and alarm timeout */
        if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
-               usage(_("Cannot catch SIGALRM"));
+               usage_va(_("Cannot catch SIGALRM"));
        }
        alarm (timeout_interval);
 
        /* run the command */
-
        if (verbose)
                printf ("%s\n", comm);
 
-       child_process = spopen (comm);
-
-       if (child_process == NULL) {
-               printf (_("Could not open pipe: %s\n"), comm);
+       result = np_runcmd(comm, &chld_out, &chld_err, 0);
+       /* UNKNOWN if output found on stderr */
+       if(chld_err.buflen) {
+               printf(_("Remote command execution failed: %s\n"),
+                          chld_err.buflen ? chld_err.buf : _("Unknown error"));
                return STATE_UNKNOWN;
        }
 
-
-       /* open STDERR  for spopen */
-       child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
-       if (child_stderr == NULL) {
-               printf (_("Could not open stderr for %s\n"), SSH_COMMAND);
+       /* this is simple if we're not supposed to be passive.
+        * Wrap up quickly and keep the tricks below */
+       if(!passive) {
+               printf ("%s\n", skip < chld_out.lines ? chld_out.line[skip] : chld_out.buf);
+               return result;  /* return error status from remote command */
        }
 
 
-       /* build up results from remote command in result_text */
-       while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
-               asprintf (&result_text, "%s%s", result_text, input_buffer);
-
-       /* WARNING if output found on stderr */
-       while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
-               if (skip_lines > 0) {
-                       if (input_buffer[strlen(input_buffer)-1] == '\n') {
-                               skip_lines--;
-                       }
-               } else {
-                       printf ("%s", input_buffer);
-                       result = STATE_WARNING;
-               }
-       }
-       (void) fclose (child_stderr);
-       if (result == STATE_WARNING)
-               return result;
-
-
-       /* close the pipe */
-       result = spclose (child_process);
-
+       /*
+        * Passive mode
+        */
 
        /* process output */
-       if (passive) {
+       if (!(fp = fopen (outputfile, "a"))) {
+               printf (_("SSH WARNING: could not open %s\n"), outputfile);
+               exit (STATE_UNKNOWN);
+       }
 
-               if (!(fp = fopen (outputfile, "a"))) {
-                       printf (_("SSH WARNING: could not open %s\n"), outputfile);
-                       exit (STATE_UNKNOWN);
+       local_time = time (NULL);
+       commands = 0;
+       for(i = skip; chld_out.line[i]; i++) {
+               status_text = strstr (chld_out.line[i], "STATUS CODE: ");
+               if (status_text == NULL) {
+                       printf ("%s", chld_out.line[i]);
+                       return result;
                }
-
-               local_time = time (NULL);
-               commands = 0;
-               while (result_text && strlen(result_text) > 0) {
-                       status_text = strstr (result_text, "STATUS CODE: ");
-                       if (status_text == NULL) {
-                               printf ("%s", result_text);
-                               return result;
-                       }
-                       asprintf (&output, "%s", result_text);
-                       result_text = strnl (status_text);
-                       eol = strpbrk (output, "\r\n");
-                       if (eol != NULL)
-                               eol[0] = 0;
-                       if (service[commands] && status_text
-                                       && sscanf (status_text, "STATUS CODE: %d", &cresult) == 1) {
-                               fprintf (fp, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
-                                                                (int) local_time, host_shortname, service[commands++], cresult,
-                                                                output);
-                       }
+               if (service[commands] && status_text
+                       && sscanf (status_text, "STATUS CODE: %d", &cresult) == 1)
+               {
+                       fprintf (fp, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
+                                (int) local_time, host_shortname, service[commands++],
+                                cresult, chld_out.line[i]);
                }
-
-       }
-
-
-       /* print the first line from the remote command */
-       else {
-               eol = strpbrk (result_text, "\r\n");
-               if (eol)
-                       eol[0] = 0;
-               printf ("%s\n", result_text);
        }
-
-
-       /* return error status from remote command */   
+       
+       /* force an OK state */
        return result;
 }
 
@@ -206,14 +165,12 @@ process_arguments (int argc, char **argv)
 
        while (1) {
                c = getopt_long (argc, argv, "Vvh1246ft:H:O:p:i:u:l:C:S:n:s:", longopts,
-                                                                        &option);
+                                &option);
 
                if (c == -1 || c == EOF)
                        break;
 
                switch (c) {
-               case '?':                                                                       /* help */
-                       usage2 (_("Unknown argument"), optarg);
                case 'V':                                                                       /* version */
                        print_revision (progname, revision);
                        exit (STATE_OK);
@@ -225,18 +182,17 @@ process_arguments (int argc, char **argv)
                        break;
                case 't':                                                                       /* timeout period */
                        if (!is_integer (optarg))
-                               usage2 (_("Timeout interval must be a positive integer"), optarg);
+                               usage_va(_("Timeout interval must be a positive integer"));
                        else
                                timeout_interval = atoi (optarg);
                        break;
                case 'H':                                                                       /* host */
-                       if (!is_host (optarg))
-                               usage2 (_("Invalid hostname/address"), optarg);
+                       host_or_die(optarg);
                        hostname = optarg;
                        break;
                case 'p': /* port number */
                        if (!is_integer (optarg))
-                               usage2 (_("Port must be a positive integer"), optarg);
+                               usage_va(_("Port must be a positive integer"));
                        asprintf (&comm,"%s -p %s", comm, optarg);
                        break;
                case 'O':                                                                       /* output file */
@@ -244,25 +200,27 @@ process_arguments (int argc, char **argv)
                        passive = TRUE;
                        break;
                case 's':                                                                       /* description of service to check */
-                       service = realloc (service, (++services) * sizeof(char *));
                        p1 = optarg;
+                       service = realloc (service, (++services) * sizeof(char *));
                        while ((p2 = index (p1, ':'))) {
                                *p2 = '\0';
-                               asprintf (&service[services-1], "%s", p1);
+                               service[services - 1] = p1;
                                service = realloc (service, (++services) * sizeof(char *));
                                p1 = p2 + 1;
                        }
-                       asprintf (&service[services-1], "%s", p1);
+                       service[services - 1] = p1;
                        break;
                case 'n':                                                                       /* short name of host in nagios configuration */
                        host_shortname = optarg;
                        break;
+
                case 'u':
                        c = 'l';
                case 'l':                                                                       /* login name */
                case 'i':                                                                       /* identity */
                        asprintf (&comm, "%s -%c %s", comm, c, optarg);
                        break;
+
                case '1':                                                                       /* Pass these switches directly to ssh */
                case '2':                                                                       /* 1 to force version 1, 2 to force version 2 */
                case '4':                                                                       /* -4 for IPv4 */
@@ -278,10 +236,12 @@ process_arguments (int argc, char **argv)
                        break;
                case 'S':                                                                       /* Skip n lines in the output to ignore system banner */
                        if (!is_integer (optarg))
-                               usage2 (_("skip lines must be an integer"), optarg);
+                               usage_va(_("skip lines must be an integer"));
                        else
-                               skip_lines = atoi (optarg);
+                               skip = atoi (optarg);
                        break;
+               default:                                                                        /* help */
+                       usage_va(_("Unknown argument - %s"), optarg);
                }
        }
 
@@ -289,8 +249,8 @@ process_arguments (int argc, char **argv)
        if (hostname == NULL) {
                if (c <= argc) {
                        die (STATE_UNKNOWN, _("%s: You must provide a host name\n"), progname);
-               } else if (!is_host (argv[c]))
-                       die (STATE_UNKNOWN, "%s: %s %s\n", progname, _("Invalid hostname/address"), argv[c]);
+               }
+               host_or_die(argv[c]);
                hostname = argv[c++];
        }
 
@@ -306,7 +266,7 @@ process_arguments (int argc, char **argv)
                asprintf (&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd);
 
        if (remotecmd == NULL || strlen (remotecmd) <= 1)
-               usage(_("No remotecmd"));
+               usage_va(_("No remotecmd"));
 
        asprintf (&comm, "%s %s '%s'", comm, hostname, remotecmd);