Add a generic interface for parsing the text protocol.
[collectd.git] / src / utils_cmds.c
1 /**
2  * collectd - src/utils_cmds.c
3  * Copyright (C) 2016       Sebastian 'tokkee' Harl
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Sebastian 'tokkee' Harl <sh at tokkee.org>
25  **/
26
27 #include "utils_cmds.h"
28 #include "utils_cmd_putval.h"
29 #include "utils_parse_option.h"
30 #include "daemon/common.h"
31
32 #include <stdbool.h>
33 #include <string.h>
34
35 /*
36  * public API
37  */
38
39 void cmd_error (cmd_status_t status, cmd_error_handler_t *err,
40                 const char *format, ...)
41 {
42         va_list ap;
43
44         if ((err == NULL) || (err->cb == NULL))
45                 return;
46
47         va_start (ap, format);
48         err->cb (err->ud, status, format, ap);
49         va_end (ap);
50 } /* void cmd_error */
51
52 cmd_status_t cmd_parse (char *buffer,
53                 cmd_t *ret_cmd, cmd_error_handler_t *err)
54 {
55         char *command = NULL;
56         int status;
57
58         if ((buffer == NULL) || (ret_cmd == NULL))
59         {
60                 errno = EINVAL;
61                 cmd_error (CMD_ERROR, err, "Invalid arguments to cmd_parse.");
62                 return CMD_ERROR;
63         }
64
65         if ((status = parse_string (&buffer, &command)) != 0)
66         {
67                 cmd_error (CMD_PARSE_ERROR, err,
68                                 "Failed to extract command from `%s'.", buffer);
69                 return (CMD_PARSE_ERROR);
70         }
71         assert (command != NULL);
72
73         memset (ret_cmd, 0, sizeof (*ret_cmd));
74         if (strcasecmp ("PUTVAL", command) == 0)
75         {
76                 ret_cmd->type = CMD_PUTVAL;
77                 return cmd_parse_putval (buffer, &ret_cmd->cmd.putval, err);
78         }
79         else
80         {
81                 ret_cmd->type = CMD_UNKNOWN;
82                 cmd_error (CMD_UNKNOWN_COMMAND, err,
83                                 "Unknown command `%s'.", command);
84                 return (CMD_UNKNOWN_COMMAND);
85         }
86
87         return (CMD_OK);
88 } /* cmd_status_t cmd_parse */
89
90 void cmd_destroy (cmd_t *cmd)
91 {
92         if (cmd == NULL)
93                 return;
94
95         switch (cmd->type)
96         {
97                 case CMD_UNKNOWN:
98                         /* nothing to do */
99                         break;
100                 case CMD_PUTVAL:
101                         cmd_destroy_putval (&cmd->cmd.putval);
102                         break;
103         }
104 } /* void cmd_destroy */
105
106 void cmd_error_fh (void *ud, cmd_status_t status,
107                 const char *format, va_list ap)
108 {
109         FILE *fh = ud;
110         int code = -1;
111         char buf[1024];
112
113         if (status == CMD_OK)
114                 code = 0;
115
116         vsnprintf (buf, sizeof(buf), format, ap);
117         buf[sizeof (buf) - 1] = '\0';
118         if (fprintf (fh, "%i %s\n", code, buf) < 0)
119         {
120                 char errbuf[1024];
121                 WARNING ("utils_cmds: failed to write to file-handle #%i: %s",
122                                 fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf)));
123                 return;
124         }
125
126         fflush (fh);
127 } /* void cmd_error_fh */
128
129 /* vim: set sw=4 ts=4 tw=78 noexpandtab : */