- Timestamp:
- Jun 30, 2010 5:29:59 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli.c
r3211 r3231 30 30 #include <pjlib-util/xml.h> 31 31 32 #define CMD_HASH_TABLE_SIZE 63 /* Hash table size */ 33 34 #define CLI_CMD_CHANGE_LOG 30000 35 #define CLI_CMD_EXIT 30001 36 32 37 #if 1 33 38 /* Enable some tracing */ … … 38 43 #endif 39 44 40 #define CMD_HASH_TABLE_SIZE 63 /* Hash table size */41 42 45 struct pj_cli_t 43 46 { 44 pj_pool_t *pool; /* Pool to allocate memory from */47 pj_pool_t *pool; /* Pool to allocate memory from */ 45 48 pj_cli_cfg cfg; /* CLI configuration */ 46 49 pj_cli_cmd_spec root; /* Root of command tree structure */ 47 50 pj_cli_front_end fe_head; /* List of front-ends */ 48 pj_hash_table_t *hash; /* Command hash table */51 pj_hash_table_t *hash; /* Command hash table */ 49 52 50 53 pj_bool_t is_quitting; … … 68 71 } 69 72 73 PJ_DEF(void) pj_cli_write_log(pj_cli_t *cli, 74 int level, 75 const char *buffer, 76 int len) 77 { 78 struct pj_cli_front_end *fe; 79 80 pj_assert(cli); 81 82 fe = cli->fe_head.next; 83 while (fe != &cli->fe_head) { 84 if (fe->op && fe->op->on_write_log) 85 (*fe->op->on_write_log)(fe, level, buffer, len); 86 fe = fe->next; 87 } 88 } 89 90 /* Command handler */ 91 static pj_status_t cmd_handler(pj_cli_cmd_val *cval) 92 { 93 unsigned level; 94 95 switch(cval->cmd->id) { 96 case CLI_CMD_CHANGE_LOG: 97 level = pj_strtoul(&cval->argv[1]); 98 if (!level && cval->argv[1].slen > 0 && (cval->argv[1].ptr[0] < '0' || 99 cval->argv[1].ptr[0] > '9')) 100 return PJ_CLI_EINVARG; 101 cval->sess->log_level = level; 102 return PJ_SUCCESS; 103 case CLI_CMD_EXIT: 104 pj_cli_end_session(cval->sess); 105 return PJ_CLI_EEXIT; 106 default: 107 return PJ_SUCCESS; 108 } 109 } 110 70 111 PJ_DEF(pj_status_t) pj_cli_create(pj_cli_cfg *cfg, 71 112 pj_cli_t **p_cli) … … 73 114 pj_pool_t *pool; 74 115 pj_cli_t *cli; 116 unsigned i; 117 char* cmd_xmls[] = { 118 "<CMD name='log' id='30000' sc='' desc='Change log level'>" 119 " <ARGS>" 120 " <ARG name='level' type='int' desc='Log level'/>" 121 " </ARGS>" 122 "</CMD>", 123 "<CMD name='exit' id='30001' sc='' desc='Exit session'>" 124 "</CMD>", 125 }; 75 126 76 127 PJ_ASSERT_RETURN(cfg && cfg->pf && p_cli, PJ_EINVAL); 77 128 78 pool = pj_pool_create(cfg->pf, "cli", 1024, 1024, NULL); 129 pool = pj_pool_create(cfg->pf, "cli", PJ_CLI_POOL_SIZE, 130 PJ_CLI_POOL_INC, NULL); 131 if (!pool) 132 return PJ_ENOMEM; 79 133 cli = PJ_POOL_ZALLOC_T(pool, struct pj_cli_t); 80 if (!cli)81 return PJ_ENOMEM;82 134 83 135 pj_memcpy(&cli->cfg, cfg, sizeof(*cfg)); … … 89 141 cli->root.sub_cmd = PJ_POOL_ZALLOC_T(pool, pj_cli_cmd_spec); 90 142 pj_list_init(cli->root.sub_cmd); 143 144 /* Register some standard commands. */ 145 for (i = 0; i < sizeof(cmd_xmls)/sizeof(cmd_xmls[0]); i++) { 146 pj_str_t xml = pj_str(cmd_xmls[i]); 147 148 if (pj_cli_add_cmd_from_xml(cli, NULL, &xml, &cmd_handler, NULL) != 149 PJ_SUCCESS) 150 TRACE_((THIS_FILE, "Failed to add command #%d", i)); 151 } 91 152 92 153 *p_cli = cli; … … 167 228 pj_assert(sess); 168 229 169 if (sess->op ->destroy)230 if (sess->op && sess->op->destroy) 170 231 (*sess->op->destroy)(sess); 171 232 } … … 184 245 pj_cli_cmd_spec *p_cmd) 185 246 { 247 #define ERROR_(STATUS) \ 248 do {status = STATUS; goto on_exit;} while(0) 186 249 pj_pool_t *pool; 187 250 pj_xml_node *root; … … 197 260 /* Parse the xml */ 198 261 pool = pj_pool_create(cli->cfg.pf, "xml", 1024, 1024, NULL); 262 if (!pool) 263 return PJ_ENOMEM; 199 264 root = pj_xml_parse(pool, xml->ptr, xml->slen); 200 265 if (!root) { 201 266 TRACE_((THIS_FILE, "Error: unable to parse XML")); 202 status = PJ_EINVAL; 203 goto on_exit; 204 } 205 206 if (pj_stricmp2(&root->name, "CMD")) { 207 status = PJ_EINVAL; 208 goto on_exit; 209 } 267 ERROR_(PJ_CLI_EBADXML); 268 } 269 270 if (pj_stricmp2(&root->name, "CMD")) 271 ERROR_(PJ_EINVAL); 210 272 211 273 /* Initialize the command spec */ 212 274 cmd = PJ_POOL_ZALLOC_T(cli->pool, struct pj_cli_cmd_spec); 213 if (!cmd) {214 status = PJ_ENOMEM;215 goto on_exit;216 }217 275 218 276 /* Get the command attributes */ … … 227 285 attr->value.slen, NULL)) 228 286 { 229 status = PJ_CLI_EBADNAME; 230 goto on_exit; 287 ERROR_(PJ_CLI_EBADNAME); 231 288 } 232 289 … … 267 324 PJ_CATCH_ANY { 268 325 pj_scan_fini(&scanner); 269 status = PJ_GET_EXCEPTION(); 270 goto on_exit; 326 ERROR_(PJ_GET_EXCEPTION()); 271 327 } 272 328 PJ_END; … … 290 346 pj_cli_arg_spec *arg; 291 347 292 if (cmd->arg_cnt >= PJ_CLI_MAX_ARGS) { 293 status = PJ_CLI_ETOOMANYARGS; 294 goto on_exit; 295 } 348 if (cmd->arg_cnt >= PJ_CLI_MAX_ARGS) 349 ERROR_(PJ_CLI_ETOOMANYARGS); 296 350 arg = &args[cmd->arg_cnt]; 297 351 pj_bzero(arg, sizeof(*arg)); … … 323 377 if (cmd->id == PJ_CLI_CMD_ID_GROUP) { 324 378 /* Command group shouldn't have any shortcuts nor arguments */ 325 if (!cmd->sc_cnt || !cmd->arg_cnt) { 326 status = PJ_EINVAL; 327 goto on_exit; 328 } 379 if (!cmd->sc_cnt || !cmd->arg_cnt) 380 ERROR_(PJ_EINVAL); 329 381 cmd->sub_cmd = PJ_POOL_ALLOC_T(cli->pool, struct pj_cli_cmd_spec); 330 382 pj_list_init(cmd->sub_cmd); 331 383 } 332 384 333 if (!cmd->name.slen) { 334 status = PJ_CLI_EBADNAME; 335 goto on_exit; 336 } 385 if (!cmd->name.slen) 386 ERROR_(PJ_CLI_EBADNAME); 337 387 338 388 if (cmd->arg_cnt) { … … 341 391 cmd->arg = (pj_cli_arg_spec *)pj_pool_zalloc(cli->pool, cmd->arg_cnt * 342 392 sizeof(pj_cli_arg_spec)); 343 if (!cmd->arg) {344 status = PJ_ENOMEM;345 goto on_exit;346 }347 393 for (i = 0; i < cmd->arg_cnt; i++) { 348 394 pj_strdup(cli->pool, &cmd->arg[i].name, &args[i].name); … … 357 403 cmd->sc = (pj_str_t *)pj_pool_zalloc(cli->pool, cmd->sc_cnt * 358 404 sizeof(pj_str_t)); 359 if (!cmd->sc) {360 status = PJ_ENOMEM;361 goto on_exit;362 }363 405 for (i = 0; i < cmd->sc_cnt; i++) { 364 406 pj_strdup(cli->pool, &cmd->sc[i], &sc[i]); 365 pj_hash_set(cli->pool, cli->hash, cmd->sc[i].ptr,366 cmd->sc[i].slen, 0, cmd);407 pj_hash_set(cli->pool, cli->hash, sc[i].ptr, 408 sc[i].slen, 0, cmd); 367 409 } 368 410 } … … 384 426 385 427 return status; 428 #undef ERROR_ 386 429 } 387 430 … … 406 449 /* Parse the command line. */ 407 450 len = pj_ansi_strlen(cmdline); 451 if (len > 0 && cmdline[len - 1] == '\n') { 452 cmdline[--len] = 0; 453 if (len > 0 && cmdline[len - 1] == '\r') 454 cmdline[--len] = 0; 455 } 408 456 pj_scan_init(&scanner, cmdline, len, PJ_SCAN_AUTOSKIP_WS, 409 457 &on_syntax_error); … … 441 489 442 490 if (!pj_scan_is_eof(&scanner)) { 443 pj_scan_get_newline(&scanner); 444 if (!pj_scan_is_eof(&scanner)) 445 PJ_THROW(PJ_CLI_EINVARG); 491 PJ_THROW(PJ_CLI_EINVARG); 446 492 } 447 493 } … … 478 524 info = &einfo; 479 525 status = pj_cli_parse(sess, cmdline, &val, info); 480 481 526 if (status != PJ_SUCCESS) 482 527 return status;
Note: See TracChangeset
for help on using the changeset viewer.