1 /*
2  * ipmi_cmdlang.h
3  *
4  * A command interpreter for OpenIPMI
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2004 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public License
14  *  as published by the Free Software Foundation; either version 2 of
15  *  the License, or (at your option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU Lesser General Public
30  *  License along with this program; if not, write to the Free
31  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33 
34 #ifndef OPENIPMI_CMDLANG_H
35 #define OPENIPMI_CMDLANG_H
36 
37 #include <OpenIPMI/selector.h>
38 #include <OpenIPMI/ipmi_bits.h>
39 #include <OpenIPMI/ipmi_types.h>
40 #include <OpenIPMI/ipmi_addr.h>
41 
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45 
46 /* Forward declaration */
47 typedef struct ipmi_cmd_info_s ipmi_cmd_info_t;
48 
49 /*
50  * A structure that must be passed into the command parser; it has
51  * general information about the how the parser should handle thing
52  * and generate its output.
53  */
54 typedef struct ipmi_cmdlang_s ipmi_cmdlang_t;
55 
56 /* Output is done in name:value pairs.  If you don't have a value,
57    pass in NULL. */
58 typedef void (*cmd_out_cb)(ipmi_cmdlang_t *info,
59 			   const char     *name,
60 			   const char     *value);
61 typedef void (*cmd_out_b_cb)(ipmi_cmdlang_t *info,
62 			     const char     *name,
63 			     const char     *value,
64 			     unsigned int   len);
65 
66 /* Command-specific info. */
67 typedef void (*cmd_info_cb)(ipmi_cmdlang_t *info);
68 
69 /* The user provides one of these when they call the command language
70    interpreter.  It is used to report errors and generate output. */
71 struct ipmi_cmdlang_s
72 {
73     cmd_out_cb   out;	   /* Generate output with this. */
74     cmd_info_cb  down;     /* Go down a level (new indention or
75 			      nesting) */
76     cmd_info_cb  up;       /* Go up a level (leave the current
77 			      indention or nesting) */
78     cmd_info_cb  done;     /* Called when the command is done.  If
79 			      there was an error, the err value in
80 			      info will be non-null. */
81     cmd_out_b_cb out_binary; /* Generate binary output with this. */
82     cmd_out_b_cb out_unicode; /* Generate unicode output with this. */
83 
84     /* OS handler to use for the commands.  Note that this may be set
85        to NULL if not required, don't depend on them except in certain
86        circumstances. */
87     os_handler_t *os_hnd;
88 
89     /* Tells if we are outputting help. */
90     int         help;
91 
92     /*
93      * Error reporting
94      */
95     int          err;      /* If non-zero, the errno code of the error
96 			      that occurred. */
97 
98     /* If non-NULL, an error occurred and this is the error info.  If
99        the error string is dynamically allocated (and thus should be
100        freed), errstr_dynalloc should be set to true. */
101     char         *errstr;
102     int          errstr_dynalloc;
103 
104     /* If an error occurs, this will be set to the object name that
105        was dealing with the error.  It may be an empty string if
106        no object is handling the error.  This must be pre-allocated
107        and the length set properly. */
108     char         *objstr;
109     int          objstr_len;
110 
111     /* This is the location of an error. */
112     char         *location;
113 
114 
115     void         *user_data; /* User data for anything the user wants */
116 };
117 
118 /* Parse and handle the given command string.  This always calls the
119    done function when complete. */
120 void ipmi_cmdlang_handle(ipmi_cmdlang_t *cmdlang, char *str);
121 
122 /* If the event info is true, then the system will output object
123    information with each add or change event. */
124 void ipmi_cmdlang_set_evinfo(int evinfo);
125 int ipmi_cmdlang_get_evinfo(void);
126 
127 /*
128  * This is used to hold command information.
129  */
130 typedef struct ipmi_cmdlang_cmd_s ipmi_cmdlang_cmd_t;
131 
132 typedef void (*ipmi_cmdlang_handler_cb)(ipmi_cmd_info_t *cmd_info);
133 typedef void (*ipmi_help_finisher_cb)(ipmi_cmdlang_t *cmdlang);
134 
135 /* Register a command as a subcommand of the parent, or into the main
136    command list if parent is NULL.  The command will have the given
137    name and help text.  When the command is executed, the handler will
138    be called with a cmd_info structure passed in.  The handler_data parm
139    passed in below will be in the "handler_data" field of the cmd_info
140    structure.  Note that if you are attaching subcommands to this
141    command, you should pass in a NULL handler.  Returns an error value. */
142 int ipmi_cmdlang_reg_cmd(ipmi_cmdlang_cmd_t      *parent,
143 			 char                    *name,
144 			 char                    *help,
145 			 ipmi_cmdlang_handler_cb handler,
146 			 void                    *handler_data,
147 			 ipmi_help_finisher_cb   help_finish,
148 			 ipmi_cmdlang_cmd_t      **rv);
149 
150 /* Register a table of commands. */
151 typedef struct ipmi_cmdlang_init_s
152 {
153     char                    *name;
154     ipmi_cmdlang_cmd_t      **parent;
155     char                    *help;
156     ipmi_cmdlang_handler_cb handler;
157     void                    *cb_data;
158     ipmi_cmdlang_cmd_t      **new_val;
159     ipmi_help_finisher_cb   help_finish;
160 } ipmi_cmdlang_init_t;
161 int ipmi_cmdlang_reg_table(ipmi_cmdlang_init_t *table, int len);
162 
163 
164 /* The following functions handle parsing various OpenIPMI objects
165    according to the naming standard.  If you pass it into a command
166    registration as the handler and pass your function as the
167    handler_data, your function will be called with the specified
168    object.  The specific function type is given in the individual
169    functions.  The cmd_info will be passed in as the cb_data.
170 
171    For instance, if you have a command that take an entity argument,
172    then you could write:
173      void ent_cmd_hnd(ipmi_entity_t *entity, void *cb_data)
174      {
175          ipmi_cmd_info_t *cmd_info = cb_data;
176      }
177 
178      rv = ipmi_cmdlang_reg_cmd(parent, "ent_cmd", "The ent command",
179 			       ipmi_cmdlang_entity_handler, ent_cmd_hnd,
180 			       &cmd);
181 */
182 
183 /* ipmi_domain_ptr_cb */
184 void ipmi_cmdlang_domain_handler(ipmi_cmd_info_t *cmd_info);
185 
186 /* ipmi_entity_ptr_cb */
187 void ipmi_cmdlang_entity_handler(ipmi_cmd_info_t *cmd_info);
188 
189 /* ipmi_sensor_ptr_cb */
190 void ipmi_cmdlang_sensor_handler(ipmi_cmd_info_t *cmd_info);
191 
192 /* ipmi_control_ptr_cb */
193 void ipmi_cmdlang_control_handler(ipmi_cmd_info_t *cmd_info);
194 
195 /* ipmi_mc_ptr_cb */
196 void ipmi_cmdlang_mc_handler(ipmi_cmd_info_t *cmd_info);
197 
198 /* ipmi_connection_ptr_cb */
199 void ipmi_cmdlang_connection_handler(ipmi_cmd_info_t *cmd_info);
200 
201 /* ipmi_pet_ptr_cb */
202 void ipmi_cmdlang_pet_handler(ipmi_cmd_info_t *cmd_info);
203 
204 /* ipmi_lanparm_ptr_cb */
205 void ipmi_cmdlang_lanparm_handler(ipmi_cmd_info_t *cmd_info);
206 
207 /* ipmi_solparm_ptr_cb */
208 void ipmi_cmdlang_solparm_handler(ipmi_cmd_info_t *cmd_info);
209 
210 /* ipmi_fru_ptr_cb */
211 void ipmi_cmdlang_fru_handler(ipmi_cmd_info_t *cmd_info);
212 
213 /* ipmi_pef_ptr_cb */
214 void ipmi_cmdlang_pef_handler(ipmi_cmd_info_t *cmd_info);
215 
216 
217 /* All output from the command language is in name/value pairs.  The
218    value field may be NULL. */
219 void ipmi_cmdlang_out(ipmi_cmd_info_t *info,
220 		      const char      *name,
221 		      const char      *value);
222 void ipmi_cmdlang_out_int(ipmi_cmd_info_t *info,
223 			  const char      *name,
224 			  int             value);
225 void ipmi_cmdlang_out_double(ipmi_cmd_info_t *info,
226 			     const char      *name,
227 			     double          value);
228 void ipmi_cmdlang_out_hex(ipmi_cmd_info_t *info,
229 			  const char      *name,
230 			  int             value);
231 void ipmi_cmdlang_out_long(ipmi_cmd_info_t *info,
232 			   const char      *name,
233 			   long            value);
234 void ipmi_cmdlang_out_binary(ipmi_cmd_info_t *info,
235 			     const char      *name,
236 			     const char      *value,
237 			     unsigned int    len);
238 void ipmi_cmdlang_out_unicode(ipmi_cmd_info_t *info,
239 			      const char      *name,
240 			      const char      *value,
241 			      unsigned int    len);
242 void ipmi_cmdlang_out_type(ipmi_cmd_info_t      *info,
243 			   char                 *name,
244 			   enum ipmi_str_type_e type,
245 			   const char           *value,
246 			   unsigned int         len);
247 void ipmi_cmdlang_out_ip(ipmi_cmd_info_t *info,
248 			 const char      *name,
249 			 struct in_addr  *ip_addr);
250 void ipmi_cmdlang_out_mac(ipmi_cmd_info_t *info,
251 			  const char      *name,
252 			  unsigned char   mac_addr[6]);
253 void ipmi_cmdlang_out_bool(ipmi_cmd_info_t *info,
254 			   const char      *name,
255 			   int             value);
256 void ipmi_cmdlang_out_time(ipmi_cmd_info_t *info,
257 			   const char      *name,
258 			   ipmi_time_t     value);
259 void ipmi_cmdlang_out_timeout(ipmi_cmd_info_t *info,
260 			      const char      *name,
261 			      ipmi_timeout_t  value);
262 
263 /* Generate info for an event. */
264 void ipmi_cmdlang_event_out(ipmi_event_t    *event,
265 			    ipmi_cmd_info_t *cmd_info);
266 
267 /* The output from the command language is done at a nesting level.
268    When you start outputting data for a new thing, you should "down"
269    to create a new nesting level.  When you are done, you should
270    "up". */
271 void ipmi_cmdlang_down(ipmi_cmd_info_t *info);
272 void ipmi_cmdlang_up(ipmi_cmd_info_t *info);
273 
274 /* A cmd info structure is refcounted, if you save a pointer to it you
275    must "get" it.  When you are done, you must "put" it.  It will be
276    destroyed (and the done routine called) after the last user puts it. */
277 void ipmi_cmdlang_cmd_info_get(ipmi_cmd_info_t *info);
278 void ipmi_cmdlang_cmd_info_put(ipmi_cmd_info_t *info);
279 
280 /* Helper functions */
281 void ipmi_cmdlang_get_int(char *str, int *val, ipmi_cmd_info_t *info);
282 void ipmi_cmdlang_get_double(char *str, double *val, ipmi_cmd_info_t *info);
283 void ipmi_cmdlang_get_uchar(char *str, unsigned char *val,
284 			    ipmi_cmd_info_t *info);
285 void ipmi_cmdlang_get_user(char *str, int *val, ipmi_cmd_info_t *info);
286 void ipmi_cmdlang_get_time(char *str, ipmi_time_t *val, ipmi_cmd_info_t *info);
287 void ipmi_cmdlang_get_timeout(char *str, ipmi_timeout_t *val,
288 			      ipmi_cmd_info_t *info);
289 void ipmi_cmdlang_get_bool(char *str, int *val, ipmi_cmd_info_t *info);
290 void ipmi_cmdlang_get_ip(char *str, struct in_addr *val,
291 			 ipmi_cmd_info_t *info);
292 void ipmi_cmdlang_get_mac(char *str, unsigned char val[6],
293 			  ipmi_cmd_info_t *info);
294 void ipmi_cmdlang_get_color(char *str, int *val, ipmi_cmd_info_t *info);
295 void ipmi_cmdlang_get_threshold_ev(char                        *str,
296 				   enum ipmi_thresh_e          *rthresh,
297 				   enum ipmi_event_value_dir_e *rvalue_dir,
298 				   enum ipmi_event_dir_e       *rdir,
299 				   ipmi_cmd_info_t             *info);
300 void ipmi_cmdlang_get_discrete_ev(char                  *str,
301 				  int                   *roffset,
302 				  enum ipmi_event_dir_e *rdir,
303 				  ipmi_cmd_info_t       *info);
304 void ipmi_cmdlang_get_threshold(char               *str,
305 				enum ipmi_thresh_e *rthresh,
306 				ipmi_cmd_info_t    *info);
307 
308 /* Call these to initialize and setup the command interpreter.  init
309    should be called after the IPMI library proper is initialized, but
310    before using it. */
311 int ipmi_cmdlang_init(os_handler_t *os_hnd);
312 void ipmi_cmdlang_cleanup(void);
313 
314 
315 /* Allocate a cmd info structure that can be used to generate
316    information to an event.  Make sure to call the put function when
317    all the data has been output.  Note that the refcounts work like
318    normal, you get it at one, when it goes to zero the structure will
319    be returned. */
320 ipmi_cmd_info_t *ipmi_cmdlang_alloc_event_info(void);
321 
322 typedef struct ipmi_cmdlang_event_s ipmi_cmdlang_event_t;
323 
324 /* Move to the first field. */
325 void ipmi_cmdlang_event_restart(ipmi_cmdlang_event_t *event);
326 
327 enum ipmi_cmdlang_out_types {
328     IPMI_CMDLANG_STRING,
329     IPMI_CMDLANG_BINARY,
330     IPMI_CMDLANG_UNICODE
331 };
332 
333 /* Returns true if successful, false if no more fields left. */
334 int ipmi_cmdlang_event_next_field(ipmi_cmdlang_event_t        *event,
335 				  unsigned int                *level,
336 				  enum ipmi_cmdlang_out_types *type,
337 				  char                        **name,
338 				  unsigned int                *len,
339 				  char                        **value);
340 
341 /* Supplied by the user, used to report global errors (ones that don't
342    deal with a specific command invocation).  The objstr is the name
343    of the object dealing with the error (like the domain name, entity
344    name, etc) or NULL if none.  The location is the file and procedure
345    where the error occurred.  The errstr is a descriptive string and
346    errval is an IPMI error value to be printed. */
347 void ipmi_cmdlang_global_err(char *objstr,
348 			     char *location,
349 			     char *errstr,
350 			     int  errval);
351 
352 /* Supplied by the user to report events. */
353 void ipmi_cmdlang_report_event(ipmi_cmdlang_event_t *event);
354 
355 /* In callbacks, you must use these to lock the cmd_info structure. */
356 void ipmi_cmdlang_lock(ipmi_cmd_info_t *info);
357 void ipmi_cmdlang_unlock(ipmi_cmd_info_t *info);
358 
359 int ipmi_cmdlang_get_argc(ipmi_cmd_info_t *info);
360 char **ipmi_cmdlang_get_argv(ipmi_cmd_info_t *info);
361 int ipmi_cmdlang_get_curr_arg(ipmi_cmd_info_t *info);
362 ipmi_cmdlang_t *ipmi_cmdinfo_get_cmdlang(ipmi_cmd_info_t *info);
363 
364 #ifdef __cplusplus
365 }
366 #endif
367 
368 #endif /* OPENIPMI_CMDLANG_H */
369