source: cmd.c @ 488ebf6

owl
Last change on this file since 488ebf6 was fa00c5c, checked in by James M. Kretchmar <kretch@mit.edu>, 15 years ago
Correct license.
  • Property mode set to 100644
File size: 8.7 KB
Line 
1/* Copyright (c) 2002,2003,2004,2009 James M. Kretchmar
2 *
3 * This file is part of Owl.
4 *
5 * Owl is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Owl is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Owl.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 * ---------------------------------------------------------------
19 *
20 * As of Owl version 2.1.12 there are patches contributed by
21 * developers of the branched BarnOwl project, Copyright (c)
22 * 2006-2009 The BarnOwl Developers. All rights reserved.
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29#include "owl.h"
30
31static const char fileIdent[] = "$Id$";
32
33extern owl_cmd commands_to_init[];
34
35/**************************************************************************/
36/***************************** COMMAND DICT *******************************/
37/**************************************************************************/
38
39int owl_cmddict_setup(owl_cmddict *cd) {
40  if (0 != owl_cmddict_init(cd)) return(-1);
41  if (0 != owl_cmddict_add_from_list(cd, commands_to_init)) return(-1);
42  return(0);
43}
44
45int owl_cmddict_init(owl_cmddict *cd) {
46  if (owl_dict_create(cd)) return(-1);
47  return(0);
48}
49
50/* for bulk initialization at startup */
51int owl_cmddict_add_from_list(owl_cmddict *cd, owl_cmd *cmds) {
52  owl_cmd *cur, *cmd;
53  for (cur = cmds; cur->name != NULL; cur++) { 
54    cmd = owl_malloc(sizeof(owl_cmd));
55    owl_cmd_create_from_template(cmd, cur);
56    owl_dict_insert_element(cd, cmd->name, (void*)cmd, NULL);
57  }
58  return 0;
59}
60
61/* free the list with owl_cmddict_namelist_free */
62void owl_cmddict_get_names(owl_cmddict *d, owl_list *l) {
63  owl_dict_get_keys(d, l);
64}
65
66owl_cmd *owl_cmddict_find(owl_cmddict *d, char *name) {
67  return (owl_cmd*)owl_dict_find_element(d, name);
68}
69
70void owl_cmddict_namelist_free(owl_list *l) {
71  owl_list_free_all(l, owl_free);
72}
73
74/* creates a new command alias */
75int owl_cmddict_add_alias(owl_cmddict *cd, char *alias_from, char *alias_to) {
76  owl_cmd *cmd;
77  cmd = owl_malloc(sizeof(owl_cmd));
78  owl_cmd_create_alias(cmd, alias_from, alias_to);
79  owl_dict_insert_element(cd, cmd->name, (void*)cmd, (void(*)(void*))owl_cmd_free);   
80  return(0);
81}
82
83char *owl_cmddict_execute(owl_cmddict *cd, owl_context *ctx, char *cmdbuff) {
84  char **argv;
85  int argc;
86  char *tmpbuff;
87  char *retval = NULL;
88  owl_cmd *cmd;
89
90  tmpbuff=strdup(cmdbuff);
91  argv=owl_parseline(tmpbuff, &argc);
92  if (argc < 0) {
93    owl_free(tmpbuff);
94    sepbar(NULL);
95    owl_function_makemsg("Unbalanced quotes");
96    return NULL;
97  } 
98 
99  if (argc < 1) return(NULL);
100
101  if (!strcmp(argv[0], "")) {
102  } else if (NULL != (cmd = (owl_cmd*)owl_dict_find_element(cd, argv[0]))) {
103    retval = owl_cmd_execute(cmd, cd, ctx, argc, argv, cmdbuff);
104  } else {
105    owl_function_makemsg("Unknown command '%s'.", cmdbuff);
106  }
107  owl_parsefree(argv, argc);
108  owl_free(tmpbuff);
109  sepbar(NULL);
110  return retval;
111}
112
113/*********************************************************************/
114/***************************** COMMAND *******************************/
115/*********************************************************************/
116
117/* sets up a new command based on a template, copying strings */
118int owl_cmd_create_from_template(owl_cmd *cmd, owl_cmd *templ) {
119  *cmd = *templ;
120  if (!templ->name) return(-1);
121  cmd->name = owl_strdup(templ->name);
122  if (templ->summary)     cmd->summary     = owl_strdup(templ->summary);
123  if (templ->usage)       cmd->usage       = owl_strdup(templ->usage);
124  if (templ->description) cmd->description = owl_strdup(templ->description);
125  if (templ->cmd_aliased_to) cmd->cmd_aliased_to = owl_strdup(templ->cmd_aliased_to);
126  return(0);
127}
128
129int owl_cmd_create_alias(owl_cmd *cmd, char *name, char *aliased_to) {
130  memset(cmd, 0, sizeof(owl_cmd));
131  cmd->name = owl_strdup(name);
132  cmd->cmd_aliased_to = owl_strdup(aliased_to);
133  cmd->summary = owl_malloc(strlen(aliased_to)+strlen(OWL_CMD_ALIAS_SUMMARY_PREFIX)+2);
134  strcpy(cmd->summary, OWL_CMD_ALIAS_SUMMARY_PREFIX);
135  strcat(cmd->summary, aliased_to);
136  return(0);
137}
138
139void owl_cmd_free(owl_cmd *cmd) {
140  if (cmd->name) owl_free(cmd->name);
141  if (cmd->summary) owl_free(cmd->summary);
142  if (cmd->usage) owl_free(cmd->usage);
143  if (cmd->description) owl_free(cmd->description);
144}
145
146int owl_cmd_is_context_valid(owl_cmd *cmd, owl_context *ctx) { 
147  if (owl_context_matches(ctx, cmd->validctx)) return 1;
148  else return 0;
149}
150
151char *owl_cmd_execute(owl_cmd *cmd, owl_cmddict *cd, owl_context *ctx, int argc, char **argv, char *cmdbuff) {
152  static int alias_recurse_depth = 0;
153  int ival=0;
154  char *cmdbuffargs, *newcmd, *rv=NULL;
155
156  if (argc < 1) return(NULL);
157
158  /* Recurse if this is an alias */
159  if (cmd->cmd_aliased_to) {
160    if (alias_recurse_depth++ > 50) {
161      owl_function_makemsg("Alias loop detected for '%s'.", cmdbuff);
162    } else {
163      cmdbuffargs = skiptokens(cmdbuff, 1);
164      newcmd = owl_malloc(strlen(cmd->cmd_aliased_to)+strlen(cmdbuffargs)+2);
165      strcpy(newcmd, cmd->cmd_aliased_to);
166      strcat(newcmd, " ");
167      strcat(newcmd, cmdbuffargs);
168      rv = owl_function_command(newcmd);
169      owl_free(newcmd);
170    } 
171    alias_recurse_depth--;
172    return rv;
173  }
174
175  /* Do validation and conversions */
176  if (cmd->cmd_ctxargs_fn || cmd->cmd_ctxv_fn || cmd->cmd_ctxi_fn) {
177    if (!owl_cmd_is_context_valid(cmd, ctx)) {
178      owl_function_makemsg("Invalid context for command '%s'.", cmdbuff);
179      return NULL;
180    }
181  }
182
183  if ((argc != 1) && (cmd->cmd_v_fn || cmd->cmd_ctxv_fn)) {
184    owl_function_makemsg("Wrong number of arguments for %s command.", argv[0]);
185    return NULL;
186  }
187
188  if (cmd->cmd_i_fn || cmd->cmd_ctxi_fn) {
189      char *ep = "x";
190      if (argc != 2) {
191        owl_function_makemsg("Wrong number of arguments for %s command.", argv[0]);
192        return NULL;
193      }
194      ival = strtol(argv[1], &ep, 10);
195      if (*ep || ep==argv[1]) {
196        owl_function_makemsg("Invalid argument '%s' for %s command.", argv[1], argv[0]);
197        return(NULL);
198      }
199  }
200
201  if (cmd->cmd_args_fn) {
202    return cmd->cmd_args_fn(argc, argv, cmdbuff);
203  } else if (cmd->cmd_v_fn) {   
204    cmd->cmd_v_fn();
205  } else if (cmd->cmd_i_fn) {
206    cmd->cmd_i_fn(ival);
207  } else if (cmd->cmd_ctxargs_fn) {
208    return cmd->cmd_ctxargs_fn(owl_context_get_data(ctx), argc, argv, cmdbuff);
209  } else if (cmd->cmd_ctxv_fn) {   
210    cmd->cmd_ctxv_fn(owl_context_get_data(ctx));
211  } else if (cmd->cmd_ctxi_fn) {
212    cmd->cmd_ctxi_fn(owl_context_get_data(ctx), ival);
213  }
214
215  return NULL;
216}
217
218/* returns a reference */
219char *owl_cmd_get_summary(owl_cmd *cmd) {
220  return cmd->summary;
221}
222
223/* returns a summary line describing this keymap.  the caller must free. */
224char *owl_cmd_describe(owl_cmd *cmd) {
225  char *s;
226  int slen;
227  if (!cmd || !cmd->name || !cmd->summary) return NULL;
228  slen = strlen(cmd->name)+strlen(cmd->summary)+30;
229  s = owl_malloc(slen);
230  snprintf(s, slen-1, "%-25s - %s", cmd->name, cmd->summary);
231  return s;
232}
233
234
235
236void owl_cmd_get_help(owl_cmddict *d, char *name, owl_fmtext *fm) {
237  char *indent, *s;
238  owl_cmd *cmd;
239
240  if (!name || (cmd = owl_dict_find_element(d, name)) == NULL) {
241    owl_fmtext_append_bold(fm, "OWL HELP\n\n");
242    owl_fmtext_append_normal(fm, "No such command...\n");
243    return;
244  }
245
246  owl_fmtext_append_bold(fm, "OWL HELP\n\n");
247  owl_fmtext_append_bold(fm, "NAME\n\n");
248  owl_fmtext_append_normal(fm, OWL_TABSTR);
249  owl_fmtext_append_normal(fm, cmd->name);
250
251  if (cmd->summary && *cmd->summary) {
252    owl_fmtext_append_normal(fm, " - ");
253    owl_fmtext_append_normal(fm, cmd->summary);
254  }
255  owl_fmtext_append_normal(fm, "\n");
256
257  if (cmd->usage && *cmd->usage) {
258    s = cmd->usage;
259    indent = owl_malloc(strlen(s)+(owl_text_num_lines(s)+3)*OWL_TAB+1);
260    owl_text_indent(indent, s, OWL_TAB);
261    owl_fmtext_append_bold(fm, "\nSYNOPSIS\n");
262    owl_fmtext_append_normal(fm, indent);
263    owl_fmtext_append_normal(fm, "\n");
264    owl_free(indent);
265  } else {
266    owl_fmtext_append_bold(fm, "\nSYNOPSIS\n");
267    owl_fmtext_append_normal(fm, OWL_TABSTR);
268    owl_fmtext_append_normal(fm, cmd->name);
269    owl_fmtext_append_normal(fm, "\n");
270  }
271
272  if (cmd->description && *cmd->description) {
273    s = cmd->description;
274    indent = owl_malloc(strlen(s)+(owl_text_num_lines(s)+3)*OWL_TAB+1);
275    owl_text_indent(indent, s, OWL_TAB);
276    owl_fmtext_append_bold(fm, "\nDESCRIPTION\n");
277    owl_fmtext_append_normal(fm, indent);
278    owl_fmtext_append_normal(fm, "\n");
279    owl_free(indent);
280  }
281
282  owl_fmtext_append_normal(fm, "\n\n"); 
283}
Note: See TracBrowser for help on using the repository browser.