Code

Standardising translation texts
[nagiosplug.git] / plugins / check_by_ssh.c
1 /******************************************************************************
3  The Nagios Plugins are free software; you can redistribute them
4  and/or modify them under the terms of the GNU General Public
5  License as published by the Free Software Foundation; either
6  version 2 of the License, or (at your option) any later version.
8  This program is distributed in the hope that it will be useful, but
9  WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  General Public License for more details.
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *****************************************************************************/
18  
19 const char *progname = "check_by_ssh";
20 const char *revision = "$Revision$";
21 const char *copyright = "2000-2003";
22 const char *email = "nagiosplug-devel@lists.sourceforge.net";
24 #include "common.h"
25 #include "netutils.h"
26 #include "utils.h"
27 #include "popen.h"
29 int process_arguments (int, char **);
30 int validate_arguments (void);
31 void print_help (void);
32 void print_usage (void);
34 int commands = 0;
35 int services = 0;
36 int skip_lines = 0;
37 char *remotecmd = NULL;
38 char *comm = NULL;
39 char *hostname = NULL;
40 char *outputfile = NULL;
41 char *host_shortname = NULL;
42 char **service;
43 int passive = FALSE;
44 int verbose = FALSE;
46 int
47 main (int argc, char **argv)
48 {
50         char input_buffer[MAX_INPUT_BUFFER];
51         char *result_text;
52         char *status_text;
53         char *output;
54         char *eol = NULL;
55         int cresult;
56         int result = STATE_UNKNOWN;
57         time_t local_time;
58         FILE *fp = NULL;
60         remotecmd = strdup ("");
61         comm = strdup (SSH_COMMAND);
62         result_text = strdup ("");
64         setlocale (LC_ALL, "");
65         bindtextdomain (PACKAGE, LOCALEDIR);
66         textdomain (PACKAGE);
68         /* process arguments */
69         if (process_arguments (argc, argv) == ERROR)
70                 usage (_("Could not parse arguments\n"));
73         /* Set signal handling and alarm timeout */
74         if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
75                 printf (_("Cannot catch SIGALRM"));
76                 return STATE_UNKNOWN;
77         }
78         alarm (timeout_interval);
81         /* run the command */
83         if (verbose)
84                 printf ("%s\n", comm);
86         child_process = spopen (comm);
88         if (child_process == NULL) {
89                 printf (_("Could not open pipe: %s\n"), comm);
90                 return STATE_UNKNOWN;
91         }
94         /* open STDERR  for spopen */
95         child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
96         if (child_stderr == NULL) {
97                 printf (_("Could not open stderr for %s\n"), SSH_COMMAND);
98         }
101         /* build up results from remote command in result_text */
102         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
103                 asprintf (&result_text, "%s%s", result_text, input_buffer);
105         /* WARNING if output found on stderr */
106         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
107                 if (skip_lines > 0) {
108                         if (input_buffer[strlen(input_buffer)-1] == '\n') {
109                                 skip_lines--;
110                         }
111                 } else {
112                         printf ("%s", input_buffer);
113                         result = STATE_WARNING;
114                 }
115         }
116         (void) fclose (child_stderr);
117         if (result == STATE_WARNING)
118                 return result;
121         /* close the pipe */
122         result = spclose (child_process);
125         /* process output */
126         if (passive) {
128                 if (!(fp = fopen (outputfile, "a"))) {
129                         printf (_("SSH WARNING: could not open %s\n"), outputfile);
130                         exit (STATE_UNKNOWN);
131                 }
133                 local_time = time (NULL);
134                 commands = 0;
135                 while (result_text && strlen(result_text) > 0) {
136                         status_text = strstr (result_text, "STATUS CODE: ");
137                         if (status_text == NULL) {
138                                 printf ("%s", result_text);
139                                 return result;
140                         }
141                         asprintf (&output, "%s", result_text);
142                         result_text = strnl (status_text);
143                         eol = strpbrk (output, "\r\n");
144                         if (eol != NULL)
145                                 eol[0] = 0;
146                         if (service[commands] && status_text
147                                         && sscanf (status_text, "STATUS CODE: %d", &cresult) == 1) {
148                                 fprintf (fp, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
149                                                                  (int) local_time, host_shortname, service[commands++], cresult,
150                                                                  output);
151                         }
152                 }
154         }
157         /* print the first line from the remote command */
158         else {
159                 eol = strpbrk (result_text, "\r\n");
160                 if (eol)
161                         eol[0] = 0;
162                 printf ("%s\n", result_text);
163         }
166         /* return error status from remote command */   
167         return result;
174 \f
175 /* process command-line arguments */
176 int
177 process_arguments (int argc, char **argv)
179         int c;
180         char *p1, *p2;
182         int option = 0;
183         static struct option longopts[] = {
184                 {"version", no_argument, 0, 'V'},
185                 {"help", no_argument, 0, 'h'},
186                 {"verbose", no_argument, 0, 'v'},
187                 {"fork", no_argument, 0, 'f'},
188                 {"timeout", required_argument, 0, 't'},
189                 {"host", required_argument, 0, 'H'},
190                 {"port", required_argument,0,'p'},
191                 {"output", required_argument, 0, 'O'},
192                 {"name", required_argument, 0, 'n'},
193                 {"services", required_argument, 0, 's'},
194                 {"identity", required_argument, 0, 'i'},
195                 {"user", required_argument, 0, 'u'},
196                 {"logname", required_argument, 0, 'l'},
197                 {"command", required_argument, 0, 'C'},
198                 {"skip", required_argument, 0, 'S'},
199                 {"proto1", no_argument, 0, '1'},
200                 {"proto2", no_argument, 0, '2'},
201                 {"use-ipv4", no_argument, 0, '4'},
202                 {"use-ipv6", no_argument, 0, '6'},
203                 {0, 0, 0, 0}
204         };
206         if (argc < 2)
207                 return ERROR;
209         for (c = 1; c < argc; c++)
210                 if (strcmp ("-to", argv[c]) == 0)
211                         strcpy (argv[c], "-t");
213         while (1) {
214                 c = getopt_long (argc, argv, "Vvh1246ft:H:O:p:i:u:l:C:S:n:s:", longopts,
215                                                                          &option);
217                 if (c == -1 || c == EOF)
218                         break;
220                 switch (c) {
221                 case '?':                                                                       /* help */
222                         print_usage ();
223                         exit (STATE_UNKNOWN);
224                 case 'V':                                                                       /* version */
225                         print_revision (progname, "$Revision$");
226                         exit (STATE_OK);
227                 case 'h':                                                                       /* help */
228                         print_help ();
229                         exit (STATE_OK);
230                 case 'v':                                                                       /* help */
231                         verbose = TRUE;
232                         break;
233                 case 't':                                                                       /* timeout period */
234                         if (!is_integer (optarg))
235                                 usage2 (_("Timeout interval must be a positive integer"), optarg);
236                         else
237                                 timeout_interval = atoi (optarg);
238                         break;
239                 case 'H':                                                                       /* host */
240                         if (!is_host (optarg))
241                                 usage2 (_("Invalid host name"), optarg);
242                         hostname = optarg;
243                         break;
244                 case 'p': /* port number */
245                         if (!is_integer (optarg))
246                                 usage2 (_("port must be an integer"), optarg);
247                         asprintf (&comm,"%s -p %s", comm, optarg);
248                         break;
249                 case 'O':                                                                       /* output file */
250                         outputfile = optarg;
251                         passive = TRUE;
252                         break;
253                 case 's':                                                                       /* description of service to check */
254                         service = realloc (service, (++services) * sizeof(char *));
255                         p1 = optarg;
256                         while ((p2 = index (p1, ':'))) {
257                                 *p2 = '\0';
258                                 asprintf (&service[services-1], "%s", p1);
259                                 service = realloc (service, (++services) * sizeof(char *));
260                                 p1 = p2 + 1;
261                         }
262                         asprintf (&service[services-1], "%s", p1);
263                         break;
264                 case 'n':                                                                       /* short name of host in nagios configuration */
265                         host_shortname = optarg;
266                         break;
267                 case 'u':
268                         c = 'l';
269                 case 'l':                                                                       /* login name */
270                 case 'i':                                                                       /* identity */
271                         asprintf (&comm, "%s -%c %s", comm, c, optarg);
272                         break;
273                 case '1':                                                                       /* Pass these switches directly to ssh */
274                 case '2':                                                                       /* 1 to force version 1, 2 to force version 2 */
275                 case '4':                                                                       /* -4 for IPv4 */
276                 case '6':                                                               /* -6 for IPv6 */
277                 case 'f':                                                                       /* fork to background */
278                         asprintf (&comm, "%s -%c", comm, c);
279                         break;
280                 case 'C':                                                                       /* Command for remote machine */
281                         commands++;
282                         if (commands > 1)
283                                 asprintf (&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd);
284                         asprintf (&remotecmd, "%s%s", remotecmd, optarg);
285                         break;
286                 case 'S':                                                                       /* Skip n lines in the output to ignore system banner */
287                         if (!is_integer (optarg))
288                                 usage2 (_("skip lines must be an integer"), optarg);
289                         else
290                                 skip_lines = atoi (optarg);
291                         break;
292                 }
293         }
295         c = optind;
296         if (hostname == NULL) {
297                 if (c <= argc) {
298                         die (STATE_UNKNOWN, _("%s: You must provide a host name\n"), progname);
299                 } else if (!is_host (argv[c]))
300                         die (STATE_UNKNOWN, _("%s: Invalid host name %s\n"), progname, argv[c]);
301                 hostname = argv[c++];
302         }
304         if (strlen(remotecmd) == 0) {
305                 for (; c < argc; c++)
306                         if (strlen(remotecmd) > 0)
307                                 asprintf (&remotecmd, "%s %s", remotecmd, argv[c]);
308                         else
309                                 asprintf (&remotecmd, "%s", argv[c]);
310         }
312         if (commands > 1)
313                 asprintf (&remotecmd, "%s;echo STATUS CODE: $?;", remotecmd);
315         if (remotecmd == NULL || strlen (remotecmd) <= 1)
316                 usage (_("No remotecmd\n"));
318         asprintf (&comm, "%s %s '%s'", comm, hostname, remotecmd);
320         return validate_arguments ();
327 int
328 validate_arguments (void)
330         if (remotecmd == NULL || hostname == NULL)
331                 return ERROR;
333         if (passive && commands != services)
334                 die (STATE_UNKNOWN, _("%s: In passive mode, you must provide a service name for each command.\n"), progname);
336         if (passive && host_shortname == NULL)
337                 die (STATE_UNKNOWN, _("%s: In passive mode, you must provide the host short name from the nagios configs.\n"), progname);
339         return OK;
346 \f
347 void
348 print_help (void)
350         print_revision (progname, revision);
352         printf (_("Copyright (c) 1999 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n"));
353         printf (_(COPYRIGHT), copyright, email);
355         printf (_("This plugin uses SSH to execute commands on a remote host\n\n"));
357         print_usage ();
359         printf (_(UT_HELP_VRSN));
361         printf (_(UT_HOST_PORT), 'p', "none");
363         printf (_(UT_IPv46));
365         printf (_("\
366  -1, --proto1\n\
367     tell ssh to use Protocol 1\n\
368  -2, --proto2\n\
369     tell ssh to use Protocol 2\n\
370  -S, --skiplines=n\n\
371     Ignore first n lines on STDERR (to suppress a logon banner)\n\
372  -f\n\
373     tells ssh to fork rather than create a tty\n"));
375         printf (_("\
376  -C, --command='COMMAND STRING'\n\
377     command to execute on the remote machine\n\
378  -l, --logname=USERNAME\n\
379     SSH user name on remote host [optional]\n\
380  -i, --identity=KEYFILE\n\
381     identity of an authorized key [optional]\n\
382  -O, --output=FILE\n\
383     external command file for nagios [optional]\n\
384  -s, --services=LIST\n\
385     list of nagios service names, separated by ':' [optional]\n\
386  -n, --name=NAME\n\
387     short name of host in nagios configuration [optional]\n"));
389         printf (_(UT_WARN_CRIT));
391         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
393         printf (_("\n\
394 The most common mode of use is to refer to a local identity file with\n\
395 the '-i' option. In this mode, the identity pair should have a null\n\
396 passphrase and the public key should be listed in the authorized_keys\n\
397 file of the remote host. Usually the key will be restricted to running\n\
398 only one command on the remote server. If the remote SSH server tracks\n\
399 invocation agruments, the one remote program may be an agent that can\n\
400 execute additional commands as proxy\n"));
402         printf (_("\n\
403 To use passive mode, provide multiple '-C' options, and provide\n\
404 all of -O, -s, and -n options (servicelist order must match '-C'\n\
405 options)\n"));
407         printf (_("\n\
408 $ check_by_ssh -H localhost -n lh -s c1:c2:c3 \\\n\
409     -C uptime -C uptime -C uptime -O /tmp/foo\n\
410 $ cat /tmp/foo\n\
411 [1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c1;0; up 2 days...\n\
412 [1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c2;0; up 2 days...\n\
413 [1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c3;0; up 2 days...\n"));
415         printf (_(UT_SUPPORT));
422 void
423 print_usage (void)
425         printf (_("\n\
426 Usage: %s [-f46] [-t timeout] [-i identity] [-l user] -H <host> \n\
427   -C <command> [-n name] [-s servicelist] [-O outputfile] [-p port]\n"),
428                 progname);
429         printf (_(UT_HLP_VRS), progname, progname);