Changeset 3231


Ignore:
Timestamp:
Jun 30, 2010 5:29:59 AM (11 years ago)
Author:
ming
Message:

Implemented CLI (re #1098)

  • pjlib-util:
    • implement telnet CLI
  • pjsip-apps/samples:
    • sample CLI demo application
  • build:
    • VS6 and Makefile
Location:
pjproject/branches/projects/cli
Files:
3 added
12 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/cli/pjlib-util/build/Makefile

    r3211 r3231  
    2828export PJLIB_UTIL_SRCDIR = ../src/pjlib-util 
    2929export PJLIB_UTIL_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \ 
    30                 base64.o cli.o cli_console.o crc32.o errno.o dns.o \ 
     30                base64.o cli.o cli_console.o cli_telnet.o crc32.o errno.o dns.o \ 
    3131                dns_dump.o dns_server.o getopt.o hmac_md5.o hmac_sha1.o \ 
    3232                http_client.o md5.o pcap.o resolver.o scanner.o sha1.o \ 
  • pjproject/branches/projects/cli/pjlib-util/build/pjlib_util.vcproj

    r3211 r3231  
    27782778                        </File> 
    27792779                        <File 
     2780                                RelativePath="..\src\pjlib-util\cli_telnet.c" 
     2781                                > 
     2782                        </File> 
     2783                        <File 
    27802784                                RelativePath="..\src\pjlib-util\crc32.c" 
    27812785                                > 
     
    47354739                        </File> 
    47364740                        <File 
     4741                                RelativePath="..\include\pjlib-util\cli_telnet.h" 
     4742                                > 
     4743                        </File> 
     4744                        <File 
    47374745                                RelativePath="..\include\pjlib-util\config.h" 
    47384746                                > 
  • pjproject/branches/projects/cli/pjlib-util/include/pjlib-util/cli.h

    r3211 r3231  
    3838 
    3939/** 
    40  * Maximum length of command buffer. 
    41  */ 
    42 #ifndef PJ_CLI_MAX_CMDBUF 
    43 #   define PJ_CLI_MAX_CMDBUF            120 
    44 #endif 
    45  
    46 /** 
    47  * Maximum command arguments. 
    48  */ 
    49 #ifndef PJ_CLI_MAX_ARGS 
    50 #   define PJ_CLI_MAX_ARGS              8 
    51 #endif 
    52  
    53 /** 
    54  * Maximum short name version (shortcuts) for a command. 
    55  */ 
    56 #ifndef PJ_CLI_MAX_SHORTCUTS 
    57 #   define PJ_CLI_MAX_SHORTCUTS         4 
    58 #endif 
    59  
    60 /* 
    61  *  New error constants (note: to be placed in errno.h with new values) 
    62  */ 
    63 /** 
    64  * @hideinitializer 
    65  * End the current session. This is a special error code returned by 
    66  * pj_cli_exec() to indicate that "exit" or equivalent command has been 
    67  * called to end the current session. 
    68  */ 
    69 #define PJ_CLI_EEXIT                    -101 
    70 /** 
    71  * @hideinitializer 
    72  * A required CLI argument is not specified. 
    73  */ 
    74 #define PJ_CLI_EMISSINGARG              -104 
    75  /** 
    76  * @hideinitializer 
    77  * Too many CLI arguments. 
    78  */ 
    79 #define PJ_CLI_ETOOMANYARGS             -105 
    80 /** 
    81  * @hideinitializer 
    82  * Invalid CLI argument. Typically this is caused by extra characters 
    83  * specified in the command line which does not match any arguments. 
    84  */ 
    85 #define PJ_CLI_EINVARG                  -106 
    86 /** 
    87  * @hideinitializer 
    88  * CLI command with the specified name already exist. 
    89  */ 
    90 #define PJ_CLI_EBADNAME                 -107 
    91  
    92 /** 
    9340 * This opaque structure represents a CLI application. A CLI application is 
    9441 * the root placeholder of other CLI objects. In an application, one (and 
     
    14693     */ 
    14794    pj_pool_factory *pf; 
    148  
    149     /** 
    150      * Specify whether only exact matching command will be executed. If 
    151      * PJ_FALSE, the framework will accept any unique abbreviations of 
    152      * the command. Please see the description of pj_cli_parse() function 
    153      * for more info. 
    154      * 
    155      * Default: PJ_FALSE 
    156      */ 
    157     pj_bool_t exact_cmd; 
    15895 
    15996} pj_cli_cfg; 
     
    383320 */ 
    384321PJ_DECL(void) pj_cli_exec_info_default(pj_cli_exec_info *param); 
     322 
     323/** 
     324 * Write a log message to the CLI application. The CLI application 
     325 * will send the log message to all the registered front-ends. 
     326 * 
     327 * @param cli           The CLI application instance. 
     328 * @param level         Verbosity level of this message message. 
     329 * @param buffer        The message itself. 
     330 * @param len           Length of this message. 
     331 */ 
     332PJ_DECL(void) pj_cli_write_log(pj_cli_t *cli, 
     333                               int level, 
     334                               const char *buffer, 
     335                               int len); 
    385336 
    386337/** 
     
    498449 * registered in the CLI application. 
    499450 * 
    500  * By default, a command may be matched by any shorter abbreviations of the 
    501  * command that uniquely identify the command. For example, suppose two 
    502  * commands "help" and "hold" are currently the only commands registered in 
    503  * the CLI application. In this case, specifying "he" and "hel" would also 
    504  * match "help" command, and similarly "ho" and "hol" would also match "hold" 
    505  * command, but specifying "h" only would yield an error as it would match 
    506  * more than one commands. This matching behavior can be turned off by 
    507  * setting \a pj_cli_cfg.exact_cmd to PJ_TRUE. 
    508  * 
    509451 * Zero or more arguments follow the command name. Arguments are separated by 
    510452 * one or more whitespaces. Argument may be placed inside a pair of quotes, 
     
    517459 * 
    518460 * The cmdline may be followed by an extra newline (LF or CR-LF characters), 
    519  * which simply will be ignored. However any more characters following this 
    520  * newline will cause an error to be returned. 
     461 * which will be removed by the function. However any more characters 
     462 * following this newline will cause an error to be returned. 
    521463 * 
    522464 * @param sess          The CLI session. 
  • pjproject/branches/projects/cli/pjlib-util/include/pjlib-util/cli_console.h

    r3211 r3231  
    8686 * instead of the standard gets() or fgets(), since unlike these functions, 
    8787 * this is able to end the blocking when pj_cli_quit() is called by other 
    88  * session. 
     88 * session. This function requires a thread support. 
    8989 * 
    9090 * Note that this function would also remove the trailing newlines from the 
  • pjproject/branches/projects/cli/pjlib-util/include/pjlib-util/config.h

    r3087 r3231  
    267267#endif 
    268268 
     269/* ************************************************************************** 
     270 * CLI configuration 
     271 */ 
     272 
     273/** 
     274 * Initial pool size for CLI. 
     275 * Default: 1024 bytes 
     276 */ 
     277#ifndef PJ_CLI_POOL_SIZE 
     278#   define PJ_CLI_POOL_SIZE    1024 
     279#endif 
     280 
     281/** 
     282 * Pool increment size for CLI. 
     283 * Default: 512 bytes 
     284 */ 
     285#ifndef PJ_CLI_POOL_INC 
     286#   define PJ_CLI_POOL_INC     512 
     287#endif 
     288 
     289/** 
     290 * Maximum length of command buffer. 
     291 * Default: 120 
     292 */ 
     293#ifndef PJ_CLI_MAX_CMDBUF 
     294#   define PJ_CLI_MAX_CMDBUF            120 
     295#endif 
     296 
     297/** 
     298 * Maximum command arguments. 
     299 * Default: 8 
     300 */ 
     301#ifndef PJ_CLI_MAX_ARGS 
     302#   define PJ_CLI_MAX_ARGS              8 
     303#endif 
     304 
     305/** 
     306 * Maximum short name version (shortcuts) for a command. 
     307 * Default: 4 
     308 */ 
     309#ifndef PJ_CLI_MAX_SHORTCUTS 
     310#   define PJ_CLI_MAX_SHORTCUTS         4 
     311#endif 
     312 
     313/** 
     314 * Initial pool size for console CLI. 
     315 * Default: 256 bytes 
     316 */ 
     317#ifndef PJ_CLI_CONSOLE_POOL_SIZE 
     318#   define PJ_CLI_CONSOLE_POOL_SIZE    256 
     319#endif 
     320 
     321/** 
     322 * Pool increment size for console CLI. 
     323 * Default: 256 bytes 
     324 */ 
     325#ifndef PJ_CLI_CONSOLE_POOL_INC 
     326#   define PJ_CLI_CONSOLE_POOL_INC     256 
     327#endif 
     328 
     329/** 
     330 * Initial pool size for telnet CLI. 
     331 * Default: 1024 bytes 
     332 */ 
     333#ifndef PJ_CLI_TELNET_POOL_SIZE 
     334#   define PJ_CLI_TELNET_POOL_SIZE 1024 
     335#endif 
     336 
     337/** 
     338 * Pool increment size for telnet CLI. 
     339 * Default: 512 bytes 
     340 */ 
     341#ifndef PJ_CLI_TELNET_POOL_INC 
     342#   define PJ_CLI_TELNET_POOL_INC  512 
     343#endif 
     344 
     345 
    269346/** 
    270347 * @} 
  • pjproject/branches/projects/cli/pjlib-util/include/pjlib-util/errno.h

    r3087 r3231  
    387387#define PJLIB_UTIL_EHTTPLOST        (PJLIB_UTIL_ERRNO_START+155)/* 320155 */ 
    388388 
     389/************************************************************ 
     390 * CLI ERROR 
     391 ***********************************************************/ 
     392 
     393/** 
     394 * @hideinitializer 
     395 * End the current session. This is a special error code returned by 
     396 * pj_cli_exec() to indicate that "exit" or equivalent command has been 
     397 * called to end the current session. 
     398 */ 
     399#define PJ_CLI_EEXIT                (PJLIB_UTIL_ERRNO_START+201)/* 320201 */ 
     400/** 
     401 * @hideinitializer 
     402 * A required CLI argument is not specified. 
     403 */ 
     404#define PJ_CLI_EMISSINGARG          (PJLIB_UTIL_ERRNO_START+202)/* 320202 */ 
     405 /** 
     406 * @hideinitializer 
     407 * Too many CLI arguments. 
     408 */ 
     409#define PJ_CLI_ETOOMANYARGS         (PJLIB_UTIL_ERRNO_START+203)/* 320203 */ 
     410/** 
     411 * @hideinitializer 
     412 * Invalid CLI argument. Typically this is caused by extra characters 
     413 * specified in the command line which does not match any arguments. 
     414 */ 
     415#define PJ_CLI_EINVARG              (PJLIB_UTIL_ERRNO_START+204)/* 320204 */ 
     416/** 
     417 * @hideinitializer 
     418 * CLI command with the specified name already exist. 
     419 */ 
     420#define PJ_CLI_EBADNAME             (PJLIB_UTIL_ERRNO_START+205)/* 320205 */ 
     421/** 
     422 * @hideinitializer 
     423 * Invalid XML format for CLI command specification. 
     424 */ 
     425#define PJ_CLI_EBADXML              (PJLIB_UTIL_ERRNO_START+206)/* 320206 */ 
     426/** 
     427 * @hideinitializer 
     428 * Telnet connection lost. 
     429 */ 
     430#define PJ_CLI_ETELNETLOST          (PJLIB_UTIL_ERRNO_START+211)/* 320211 */ 
     431 
    389432/** 
    390433 * @} 
  • pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli.c

    r3211 r3231  
    3030#include <pjlib-util/xml.h> 
    3131 
     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 
    3237#if 1 
    3338    /* Enable some tracing */ 
     
    3843#endif 
    3944 
    40 #define CMD_HASH_TABLE_SIZE 63          /* Hash table size */ 
    41  
    4245struct pj_cli_t 
    4346{ 
    44     pj_pool_t          *pool;          /* Pool to allocate memory from */ 
     47    pj_pool_t          *pool;           /* Pool to allocate memory from */ 
    4548    pj_cli_cfg          cfg;            /* CLI configuration */ 
    4649    pj_cli_cmd_spec     root;           /* Root of command tree structure */ 
    4750    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 */ 
    4952 
    5053    pj_bool_t           is_quitting; 
     
    6871} 
    6972 
     73PJ_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 */ 
     91static 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 
    70111PJ_DEF(pj_status_t) pj_cli_create(pj_cli_cfg *cfg, 
    71112                                  pj_cli_t **p_cli) 
     
    73114    pj_pool_t *pool; 
    74115    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    }; 
    75126 
    76127    PJ_ASSERT_RETURN(cfg && cfg->pf && p_cli, PJ_EINVAL); 
    77128 
    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; 
    79133    cli = PJ_POOL_ZALLOC_T(pool, struct pj_cli_t); 
    80     if (!cli) 
    81         return PJ_ENOMEM; 
    82134 
    83135    pj_memcpy(&cli->cfg, cfg, sizeof(*cfg)); 
     
    89141    cli->root.sub_cmd = PJ_POOL_ZALLOC_T(pool, pj_cli_cmd_spec); 
    90142    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    } 
    91152 
    92153    *p_cli = cli; 
     
    167228    pj_assert(sess); 
    168229 
    169     if (sess->op->destroy) 
     230    if (sess->op && sess->op->destroy) 
    170231        (*sess->op->destroy)(sess); 
    171232} 
     
    184245                                            pj_cli_cmd_spec *p_cmd) 
    185246{ 
     247    #define ERROR_(STATUS) \ 
     248        do {status = STATUS; goto on_exit;} while(0) 
    186249    pj_pool_t *pool; 
    187250    pj_xml_node *root; 
     
    197260    /* Parse the xml */ 
    198261    pool = pj_pool_create(cli->cfg.pf, "xml", 1024, 1024, NULL); 
     262    if (!pool) 
     263        return PJ_ENOMEM; 
    199264    root = pj_xml_parse(pool, xml->ptr, xml->slen); 
    200265    if (!root) { 
    201266        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); 
    210272 
    211273    /* Initialize the command spec */ 
    212274    cmd = PJ_POOL_ZALLOC_T(cli->pool, struct pj_cli_cmd_spec); 
    213     if (!cmd) { 
    214         status = PJ_ENOMEM; 
    215         goto on_exit; 
    216     } 
    217275     
    218276    /* Get the command attributes */ 
     
    227285                            attr->value.slen, NULL)) 
    228286            { 
    229                 status = PJ_CLI_EBADNAME; 
    230                 goto on_exit; 
     287                ERROR_(PJ_CLI_EBADNAME); 
    231288            } 
    232289 
     
    267324            PJ_CATCH_ANY { 
    268325                pj_scan_fini(&scanner); 
    269                 status = PJ_GET_EXCEPTION(); 
    270                 goto on_exit; 
     326                ERROR_(PJ_GET_EXCEPTION()); 
    271327            } 
    272328            PJ_END; 
     
    290346                    pj_cli_arg_spec *arg; 
    291347 
    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); 
    296350                    arg = &args[cmd->arg_cnt]; 
    297351                    pj_bzero(arg, sizeof(*arg)); 
     
    323377    if (cmd->id == PJ_CLI_CMD_ID_GROUP) { 
    324378        /* 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); 
    329381        cmd->sub_cmd = PJ_POOL_ALLOC_T(cli->pool, struct pj_cli_cmd_spec); 
    330382        pj_list_init(cmd->sub_cmd); 
    331383    } 
    332384 
    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); 
    337387 
    338388    if (cmd->arg_cnt) { 
     
    341391        cmd->arg = (pj_cli_arg_spec *)pj_pool_zalloc(cli->pool, cmd->arg_cnt * 
    342392                                                     sizeof(pj_cli_arg_spec)); 
    343         if (!cmd->arg) { 
    344             status = PJ_ENOMEM; 
    345             goto on_exit; 
    346         } 
    347393        for (i = 0; i < cmd->arg_cnt; i++) { 
    348394            pj_strdup(cli->pool, &cmd->arg[i].name, &args[i].name); 
     
    357403        cmd->sc = (pj_str_t *)pj_pool_zalloc(cli->pool, cmd->sc_cnt * 
    358404                                             sizeof(pj_str_t)); 
    359         if (!cmd->sc) { 
    360             status = PJ_ENOMEM; 
    361             goto on_exit; 
    362         } 
    363405        for (i = 0; i < cmd->sc_cnt; i++) { 
    364406            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); 
    367409        } 
    368410    } 
     
    384426 
    385427    return status; 
     428#undef ERROR_ 
    386429} 
    387430 
     
    406449    /* Parse the command line. */ 
    407450    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    } 
    408456    pj_scan_init(&scanner, cmdline, len, PJ_SCAN_AUTOSKIP_WS,  
    409457                 &on_syntax_error); 
     
    441489         
    442490        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); 
    446492        } 
    447493    } 
     
    478524        info = &einfo; 
    479525    status = pj_cli_parse(sess, cmdline, &val, info); 
    480  
    481526    if (status != PJ_SUCCESS) 
    482527        return status; 
  • pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/cli_console.c

    r3211 r3231  
    2222#include <pj/assert.h> 
    2323#include <pj/errno.h> 
     24#include <pj/log.h> 
    2425#include <pj/os.h> 
    2526#include <pj/pool.h> 
     
    4445}; 
    4546 
     47static void cli_console_write_log(pj_cli_front_end *fe, int level, 
     48                                  const char *data, int len) 
     49{ 
     50    struct cli_console_fe * cfe = (struct cli_console_fe *)fe; 
     51 
     52    if (cfe->sess->log_level > level) 
     53        printf("%.*s", len, data); 
     54} 
     55 
     56 
    4657static void cli_console_quit(pj_cli_front_end *fe, pj_cli_sess *req) 
    4758{ 
     
    6576    cli_console_quit(fe, NULL); 
    6677 
     78    if (cfe->input_thread) 
     79        pj_thread_destroy(cfe->input_thread); 
    6780    pj_sem_destroy(cfe->thread_sem); 
    6881    pj_sem_destroy(cfe->input.sem); 
     
    90103 
    91104    pool = pj_pool_create(pj_cli_get_param(cli)->pf, "console_fe", 
    92                           256, 256, NULL); 
     105                          PJ_CLI_CONSOLE_POOL_SIZE, PJ_CLI_CONSOLE_POOL_INC, 
     106                          NULL); 
     107    if (!pool) 
     108        return PJ_ENOMEM; 
    93109    sess = PJ_POOL_ZALLOC_T(pool, pj_cli_sess); 
    94110    fe = PJ_POOL_ZALLOC_T(pool, struct cli_console_fe); 
    95     if (!sess || !fe) 
    96         return PJ_ENOMEM; 
    97111 
    98112    if (!param) { 
     
    102116    sess->fe = &fe->base; 
    103117    sess->log_level = param->log_level; 
     118    sess->op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_sess_op); 
     119    fe->base.op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_front_end_op); 
    104120    fe->base.cli = cli; 
    105121    fe->base.type = PJ_CLI_CONSOLE_FRONT_END; 
    106     fe->base.op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_front_end_op); 
     122    fe->base.op->on_write_log = &cli_console_write_log; 
    107123    fe->base.op->on_quit = &cli_console_quit; 
    108124    fe->base.op->on_destroy = &cli_console_destroy; 
     
    128144        fgets(fe->input.buf, fe->input.maxlen, stdin); 
    129145        for (i = pj_ansi_strlen(fe->input.buf) - 1; i >= 0; i--) { 
    130             if (fe->input.buf[i] == '\n') 
     146            if (fe->input.buf[i] == '\n' || fe->input.buf[i] == '\r') 
    131147                fe->input.buf[i] = 0; 
    132148            else 
     
    137153        pj_sem_wait(fe->thread_sem); 
    138154    } 
    139     pj_sem_post(fe->input.sem); 
    140155    fe->input_thread = NULL; 
    141156 
     
    155170 
    156171    if (!fe->input_thread) { 
    157         if (pj_thread_create(fe->pool, NULL, &readline_thread, fe, 
    158                              0, 0, &fe->input_thread) != PJ_SUCCESS) 
    159         { 
    160             return PJ_EUNKNOWN; 
    161         } 
     172        pj_status_t status; 
     173 
     174        status = pj_thread_create(fe->pool, NULL, &readline_thread, fe, 
     175                                  0, 0, &fe->input_thread); 
     176        if (status != PJ_SUCCESS) 
     177            return status; 
    162178    } else { 
    163179        /* Wake up readline thread */ 
     
    166182 
    167183    pj_sem_wait(fe->input.sem); 
    168      
    169     return (fe->thread_quit ? PJ_CLI_EEXIT : PJ_SUCCESS); 
     184 
     185    return (pj_cli_is_quitting(fe->base.cli)? PJ_CLI_EEXIT : PJ_SUCCESS); 
    170186} 
  • pjproject/branches/projects/cli/pjlib-util/src/pjlib-util/errno.c

    r3087 r3231  
    9696    PJ_BUILD_ERR( PJLIB_UTIL_EHTTPINSBUF,       "Insufficient buffer"), 
    9797    PJ_BUILD_ERR( PJLIB_UTIL_EHTTPLOST,         "Connection lost"), 
     98 
     99    /* CLI */ 
     100    PJ_BUILD_ERR( PJ_CLI_EEXIT,                 "Exit current session"), 
     101    PJ_BUILD_ERR( PJ_CLI_EMISSINGARG,           "Missing argument"), 
     102    PJ_BUILD_ERR( PJ_CLI_ETOOMANYARGS,          "Too many arguments"), 
     103    PJ_BUILD_ERR( PJ_CLI_EINVARG,               "Invalid argument"), 
     104    PJ_BUILD_ERR( PJ_CLI_EBADNAME,              "Command name already exists"), 
     105    PJ_BUILD_ERR( PJ_CLI_EBADXML,               "Invalid XML format"), 
     106    PJ_BUILD_ERR( PJ_CLI_ETELNETLOST,           "Connection lost"), 
    98107}; 
    99108#endif  /* PJ_HAS_ERROR_STRING */ 
  • pjproject/branches/projects/cli/pjsip-apps/build/Samples-vc.mak

    r3141 r3231  
    6161SAMPLES = $(BINDIR)\auddemo.exe \ 
    6262          $(BINDIR)\aectest.exe \ 
     63          $(BINDIR)\clidemo.exe \ 
    6364          $(BINDIR)\confsample.exe \ 
    6465          $(BINDIR)\confbench.exe \ 
  • pjproject/branches/projects/cli/pjsip-apps/build/Samples.mak

    r3141 r3231  
    1616SAMPLES := auddemo \ 
    1717           aectest \ 
     18           clidemo \ 
    1819           confsample \ 
    1920           encdec \ 
  • pjproject/branches/projects/cli/pjsip-apps/build/samples.vcproj

    r3087 r3231  
    15991599                        </File> 
    16001600                        <File 
     1601                                RelativePath="..\src\samples\clidemo.c" 
     1602                                > 
     1603                        </File> 
     1604                        <File 
    16011605                                RelativePath="..\src\samples\confbench.c" 
    16021606                                > 
Note: See TracChangeset for help on using the changeset viewer.