00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <stdlib.h>
00040 #include <stdio.h>
00041 #include <string.h>
00042 #include <unistd.h>
00043 #include <errno.h>
00044 #include <ctype.h>
00045 #include <sys/socket.h>
00046 #include <sys/un.h>
00047 #include <netinet/in.h>
00048 #include <sys/uio.h>
00049 #include <netdb.h>
00050 #include <time.h>
00051
00052 #ifdef USE_READLINE
00053 #include <readline/readline.h>
00054 #include <readline/history.h>
00055
00056 #define USE_CFG_VARS
00057 #define USE_MI
00058 #define USE_COUNTERS
00059 #endif
00060
00061 #include "parse_listen_id.h"
00062 #include "license.h"
00063
00064 #include "../../modules/ctl/ctl_defaults.h"
00065 #include "../../modules/ctl/binrpc.h"
00066 #include "../../modules/ctl/binrpc.c"
00067
00068
00069 #ifndef NAME
00070 #define NAME "sercmd"
00071 #endif
00072 #ifndef VERSION
00073 #define VERSION "0.2"
00074 #endif
00075
00076 #define IOVEC_CNT 20
00077 #define MAX_LINE_SIZE 16384
00078 #define MAX_REPLY_SIZE 65536
00079 #define MAX_BODY_SIZE 65536
00080 #define MAX_BINRPC_ARGS 256
00081
00082
00083 #ifndef UNIX_PATH_MAX
00084 #define UNIX_PATH_MAX 108
00085 #endif
00086
00087 static char id[]="$Id$";
00088 static char version[]= NAME " " VERSION;
00089 static char compiled[]= __TIME__ " " __DATE__;
00090 static char help_msg[]="\
00091 Usage: " NAME " [options][-s address] [ cmd ]\n\
00092 Options:\n\
00093 -s address unix socket name or host name to send the commands on\n\
00094 -R name force reply socket name, for the unix datagram socket mode\n\
00095 -D dir create the reply socket in the directory <dir> if no reply \n\
00096 socket is forced (-R) and a unix datagram socket is selected\n\
00097 as the transport\n\
00098 -f format print the result using format. Format is a string containing\n\
00099 %v at the places where values read from the reply should be\n\
00100 substituted. To print '%v', escape it using '%': %%v.\n\
00101 -v Verbose \n\
00102 -V Version number\n\
00103 -h This help message\n\
00104 address:\n\
00105 [proto:]name[:port] where proto is one of tcp, udp, unixs or unixd\n\
00106 e.g.: tcp:localhost:2048 , unixs:/tmp/ser_ctl\n\
00107 cmd:\n\
00108 method [arg1 [arg2...]]\n\
00109 arg:\n\
00110 string or number; to force a number to be interpreted as string \n\
00111 prefix it by \"s:\", e.g. s:1\n\
00112 Examples:\n\
00113 " NAME " -s unixs:/tmp/ser_unix system.listMethods\n\
00114 " NAME " -f \"pid: %v desc: %v\\n\" -s udp:localhost:2047 core.ps \n\
00115 " NAME " ps # uses default ctl socket \n\
00116 " NAME " # enters interactive mode on the default socket \n\
00117 " NAME " -s tcp:localhost # interactive mode, default port \n\
00118 ";
00119
00120
00121 int verbose=0;
00122 char* reply_socket=0;
00123 char* sock_dir=0;
00124 char* unix_socket=0;
00125 struct sockaddr_un mysun;
00126 int quit;
00127
00128 struct binrpc_val* rpc_array;
00129 int rpc_no=0;
00130
00131 #ifdef USE_CFG_VARS
00132
00133 struct binrpc_val* cfg_vars_array;
00134 int cfg_vars_no;
00135
00136 struct cfg_var_grp{
00137 struct cfg_var_grp* next;
00138 str grp_name;
00139 str* var_names;
00140 int var_no;
00141 };
00142
00143 struct cfg_var_grp* cfg_grp_lst;
00144 struct cfg_var_grp* crt_cfg_grp;
00145 #endif
00146
00147 #ifdef USE_MI
00148 struct binrpc_val* mi_which_array;
00149 int mi_which_no;
00150
00151 str* mi_cmds;
00152 int mi_cmds_no;
00153 #endif
00154
00155 #ifdef USE_COUNTERS
00156 struct binrpc_val* cnt_grps_array;
00157 int cnt_grps_no;
00158
00159 struct cnt_var_grp {
00160 struct cnt_var_grp * next;
00161 str grp_name;
00162 str* var_names;
00163 int var_no;
00164 struct binrpc_val* cnt_vars_array;
00165 int cnt_vars_no;
00166 };
00167
00168 struct cnt_var_grp* cnt_grp_lst;
00169 struct cnt_var_grp* crt_cnt_grp;
00170 #endif
00171
00172
00173
00174 #define IOV_SET(vect, str) \
00175 do{\
00176 (vect).iov_base=(str); \
00177 (vect).iov_len=strlen((str)); \
00178 }while(0)
00179
00180
00181 #define INT2STR_MAX_LEN (19+1+1)
00182
00183
00184 static inline char* int2str(unsigned int l, int* len)
00185 {
00186 static char r[INT2STR_MAX_LEN];
00187 int i;
00188
00189 i=INT2STR_MAX_LEN-2;
00190 r[INT2STR_MAX_LEN-1]=0;
00191 do{
00192 r[i]=l%10+'0';
00193 i--;
00194 l/=10;
00195 }while(l && (i>=0));
00196 if (l && (i<0)){
00197 fprintf(stderr, "BUG: int2str: overflow\n");
00198 }
00199 if (len) *len=(INT2STR_MAX_LEN-2)-i;
00200 return &r[i+1];
00201 }
00202
00203
00204
00205 static char* trim_ws(char* l)
00206 {
00207 char* ret;
00208
00209 for(;*l && ((*l==' ')||(*l=='\t')||(*l=='\n')||(*l=='\r')); l++);
00210 ret=l;
00211 if (*ret==0) return ret;
00212 for(l=l+strlen(l)-1; (l>ret) &&
00213 ((*l==' ')||(*l=='\t')||(*l=='\n')||(*l=='\r')); l--);
00214 *(l+1)=0;
00215 return ret;
00216 }
00217
00218
00219
00220 int gen_cookie()
00221 {
00222 return rand();
00223 }
00224
00225
00226
00227 struct binrpc_cmd{
00228 char* method;
00229 int argc;
00230 struct binrpc_val argv[MAX_BINRPC_ARGS];
00231 };
00232
00233
00234 struct cmd_alias{
00235 char* name;
00236 char* method;
00237 char* format;
00238 };
00239
00240
00241 struct sercmd_builtin{
00242 char* name;
00243 int (*f)(int, struct binrpc_cmd*);
00244 char* doc;
00245 };
00246
00247
00248 static int sercmd_help(int s, struct binrpc_cmd* cmd);
00249 static int sercmd_ver(int s, struct binrpc_cmd* cmd);
00250 static int sercmd_quit(int s, struct binrpc_cmd* cmd);
00251 static int sercmd_warranty(int s, struct binrpc_cmd* cmd);
00252
00253
00254 static struct cmd_alias cmd_aliases[]={
00255 { "ps", "core.ps", "%v\t%v\n" },
00256 { "list", "system.listMethods", 0 },
00257 { "ls", "system.listMethods", 0 },
00258 { "server", "core.version", 0 },
00259 { "serversion", "core.version", 0 },
00260 { "who", "ctl.who", "[%v] %v: %v %v -> %v %v\n"},
00261 { "listen", "ctl.listen", "[%v] %v: %v %v\n"},
00262 { "dns_mem_info", "dns.mem_info", "%v / %v\n"},
00263 { "dns_debug", "dns.debug",
00264 "%v (%v): size=%v ref=%v expire=%vs last=%vs ago f=%v\n"},
00265 { "dns_debug_all", "dns.debug_all",
00266 "%v (%v) [%v]: size=%v ref=%v expire=%vs last=%vs ago f=%v\n"
00267 "\t\t%v:%v expire=%vs f=%v\n"},
00268 { "dst_blacklist_mem_info", "dst_blacklist.mem_info", "%v / %v\n"},
00269 { "dst_blacklist_debug", "dst_blacklist.debug",
00270 "%v:%v:%v expire:%v flags: %v\n"},
00271 {0,0,0}
00272 };
00273
00274
00275 static struct sercmd_builtin builtins[]={
00276 { "?", sercmd_help, "help"},
00277 { "help", sercmd_help, "displays help for a command"},
00278 { "version", sercmd_ver, "displays " NAME "version"},
00279 { "quit", sercmd_quit, "exits " NAME },
00280 { "exit", sercmd_quit, "exits " NAME },
00281 { "warranty", sercmd_warranty, "displays " NAME "'s warranty info"},
00282 { "license", sercmd_warranty, "displays " NAME "'s license"},
00283 {0,0}
00284 };
00285
00286
00287
00288 #ifdef USE_READLINE
00289
00290 enum complete_states {
00291 COMPLETE_INIT,
00292 COMPLETE_CMD_NAME,
00293 #ifdef USE_CFG_VARS
00294 COMPLETE_CFG_GRP,
00295 COMPLETE_CFG_VAR,
00296 #endif
00297 #ifdef USE_MI
00298 COMPLETE_MI,
00299 #endif
00300 #ifdef USE_COUNTERS
00301 COMPLETE_CNT_GRP,
00302 COMPLETE_CNT_VAR,
00303 #endif
00304 COMPLETE_NOTHING
00305 };
00306
00307
00308
00309 static enum complete_states attempted_completion_state;
00310 static int crt_param_no;
00311
00312
00313 char* complete_params_methods[]={
00314 "?",
00315 "h",
00316 "help",
00317 "system.methodSignature",
00318 "system.methodHelp",
00319 0
00320 };
00321
00322 #ifdef USE_CFG_VARS
00323
00324 char* complete_params_cfg_var[]={
00325 "cfg.get",
00326 "cfg.help",
00327 "cfg.set_delayed_int",
00328 "cfg.set_delayed_string",
00329 "cfg.set_now_int",
00330 "cfg.set_now_string",
00331 0
00332 };
00333 #endif
00334
00335 #ifdef USE_MI
00336
00337 char* complete_params_mi[]={
00338 "mi",
00339 "mi_fifo",
00340 "mi_dg",
00341 "mi_xmlrpc",
00342 0
00343 };
00344 #endif
00345
00346 #ifdef USE_COUNTERS
00347
00348 char* complete_param1_counter_grp[] = {
00349 "cnt.get",
00350 "cnt.get_raw",
00351 "cnt.grp_get_all",
00352 "cnt.reset",
00353 "cnt.var_list",
00354 "cnt.help",
00355 0
00356 };
00357
00358
00359 char* complete_param2_counter_name[] = {
00360 "cnt.get",
00361 "cnt.get_raw",
00362 "cnt.reset",
00363 "cnt.help",
00364 0
00365 };
00366 #endif
00367
00368 #endif
00369
00370
00371
00372 static int parse_arg(struct binrpc_val* v, char* arg)
00373 {
00374 int i;
00375 double f;
00376 char* tmp;
00377 int len;
00378
00379 i=strtol(arg, &tmp, 10);
00380 if ((tmp==0) || (*tmp)){
00381 f=strtod(arg, &tmp);
00382 if ((tmp==0) || (*tmp)){
00383
00384 len=strlen(arg);
00385 if ((len>=2) && (arg[0]=='s') && (arg[1]==':')){
00386 tmp=&arg[2];
00387 len-=2;
00388 }else{
00389 tmp=arg;
00390 }
00391 v->type=BINRPC_T_STR;
00392 v->u.strval.s=tmp;
00393 v->u.strval.len=len;
00394 }else{
00395 v->type=BINRPC_T_DOUBLE;
00396 v->u.fval=f;
00397 }
00398 }else{
00399 v->type=BINRPC_T_INT;
00400 v->u.intval=i;
00401 }
00402 return 0;
00403 }
00404
00405
00406
00407 static int parse_cmd(struct binrpc_cmd* cmd, char** argv, int count)
00408 {
00409 int r;
00410
00411 cmd->method=argv[0];
00412 if ((count-1)>MAX_BINRPC_ARGS){
00413 fprintf(stderr, "ERROR: too many args %d, only %d allowed\n",
00414 count-1, MAX_BINRPC_ARGS);
00415 return -1;
00416 }
00417 for (r=1; r<count; r++){
00418 if (parse_arg(&cmd->argv[r-1], argv[r])<0)
00419 return -1;
00420 }
00421 cmd->argc=r-1;
00422 return 0;
00423 }
00424
00425
00426 void print_binrpc_val(struct binrpc_val* v, int ident)
00427 {
00428 int r;
00429
00430 if ((v->type==BINRPC_T_STRUCT) && !v->u.end)
00431 ident--;
00432 for (r=0; r<ident; r++) putchar(' ');
00433 if (v->name.s){
00434 printf("%.*s: ", v->name.len, v->name.s);
00435 }
00436 switch(v->type){
00437 case BINRPC_T_INT:
00438 printf("%d", v->u.intval);
00439 break;
00440 case BINRPC_T_STR:
00441 case BINRPC_T_BYTES:
00442 printf("%.*s", v->u.strval.len, v->u.strval.s);
00443 break;
00444 case BINRPC_T_ARRAY:
00445 printf("%c", (v->u.end)?']':'[');
00446 break;
00447 case BINRPC_T_STRUCT:
00448 printf("%c", (v->u.end)?'}':'{');
00449 break;
00450 case BINRPC_T_DOUBLE:
00451 printf("%f", v->u.fval);
00452 break;
00453 default:
00454 printf("ERROR: unknown type %d\n", v->type);
00455 };
00456 }
00457
00458
00459
00460
00461
00462 int connect_unix_sock(char* name, int type)
00463 {
00464 struct sockaddr_un ifsun;
00465 int s;
00466 int len;
00467 int ret;
00468 int retries;
00469
00470 retries=0;
00471 s=-1;
00472 memset(&ifsun, 0, sizeof (struct sockaddr_un));
00473 len=strlen(name);
00474 if (len>UNIX_PATH_MAX){
00475 fprintf(stderr, "ERROR: connect_unix_sock: name too long "
00476 "(%d > %d): %s\n", len, UNIX_PATH_MAX, name);
00477 goto error;
00478 }
00479 ifsun.sun_family=AF_UNIX;
00480 memcpy(ifsun.sun_path, name, len);
00481 #ifdef HAVE_SOCKADDR_SA_LEN
00482 ifsun.sun_len=len;
00483 #endif
00484 s=socket(PF_UNIX, type, 0);
00485 if (s==-1){
00486 fprintf(stderr, "ERROR: connect_unix_sock: cannot create unix socket"
00487 " %s: %s [%d]\n", name, strerror(errno), errno);
00488 goto error;
00489 }
00490 if (type==SOCK_DGRAM){
00491
00492 if (reply_socket==0){
00493 if (sock_dir==0)
00494 sock_dir="/tmp";
00495 retry:
00496 ret=snprintf(mysun.sun_path, UNIX_PATH_MAX, "%s/" NAME "_%d",
00497 sock_dir, rand());
00498 if ((ret<0) ||(ret>=UNIX_PATH_MAX)){
00499 fprintf(stderr, "ERROR: buffer overflow while trying to"
00500 "generate unix datagram socket name");
00501 goto error;
00502 }
00503 }else{
00504 if (strlen(reply_socket)>UNIX_PATH_MAX){
00505 fprintf(stderr, "ERROR: buffer overflow while trying to"
00506 "use the provided unix datagram socket name (%s)",
00507 reply_socket);
00508 goto error;
00509 }
00510 strcpy(mysun.sun_path, reply_socket);
00511 }
00512 mysun.sun_family=AF_UNIX;
00513 if (bind(s, (struct sockaddr*)&mysun, sizeof(mysun))==-1){
00514 if (errno==EADDRINUSE && (reply_socket==0) && (retries < 10)){
00515 retries++;
00516
00517 goto retry;
00518 }
00519 fprintf(stderr, "ERROR: could not bind the unix socket to"
00520 " %s: %s (%d)\n",
00521 mysun.sun_path, strerror(errno), errno);
00522 goto error;
00523 }
00524 unix_socket=mysun.sun_path;
00525 }
00526 if (connect(s, (struct sockaddr *)&ifsun, sizeof(ifsun))==-1){
00527 fprintf(stderr, "ERROR: connect_unix_sock: connect(%s): %s [%d]\n",
00528 name, strerror(errno), errno);
00529 goto error;
00530 }
00531 return s;
00532 error:
00533 if (s!=-1) close(s);
00534 return -1;
00535 }
00536
00537
00538
00539 int connect_tcpudp_socket(char* address, int port, int type)
00540 {
00541 struct sockaddr_in addr;
00542 struct hostent* he;
00543 int sock;
00544
00545 sock=-1;
00546
00547 he=gethostbyname(address);
00548 if (he==0){
00549 fprintf(stderr, "ERROR: could not resolve %s\n", address);
00550 goto error;
00551 }
00552
00553 addr.sin_family=he->h_addrtype;
00554 addr.sin_port=htons(port);
00555 memcpy(&addr.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
00556
00557 sock = socket(he->h_addrtype, type, 0);
00558 if (sock==-1){
00559 fprintf(stderr, "ERROR: socket: %s\n", strerror(errno));
00560 goto error;
00561 }
00562 if (connect(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr))!=0){
00563 fprintf(stderr, "ERROR: connect: %s\n", strerror(errno));
00564 goto error;
00565 }
00566 return sock;
00567 error:
00568 if (sock!=-1) close(sock);
00569 return -1;
00570 }
00571
00572
00573
00574 static void hexdump(unsigned char* buf, int len, int ascii)
00575 {
00576 int r, i;
00577
00578
00579 for (r=0; r<len; r++){
00580 if ((r) && ((r%16)==0)){
00581 if (ascii){
00582 putchar(' ');
00583 for (i=r-16; i<r; i++){
00584 if (isprint(buf[i]))
00585 putchar(buf[i]);
00586 else
00587 putchar('.');
00588 }
00589 }
00590 putchar('\n');
00591 }
00592 printf("%02x ", buf[r]);
00593 };
00594 if (ascii){
00595 for (i=r;i%16; i++)
00596 printf(" ");
00597 putchar(' ');
00598 for (i=16*(r/16); i<r; i++){
00599 if (isprint(buf[i]))
00600 putchar(buf[i]);
00601 else
00602 putchar('.');
00603 }
00604 }
00605 putchar('\n');
00606 }
00607
00608
00609
00610
00611 static int send_binrpc_cmd(int s, struct binrpc_cmd* cmd, int cookie)
00612 {
00613 struct iovec v[IOVEC_CNT];
00614 int r;
00615 unsigned char msg_body[MAX_BODY_SIZE];
00616 unsigned char msg_hdr[BINRPC_MAX_HDR_SIZE];
00617 struct binrpc_pkt body;
00618 int ret;
00619 int n;
00620
00621 ret=binrpc_init_pkt(&body, msg_body, MAX_BODY_SIZE);
00622 if (ret<0) goto binrpc_err;
00623 ret=binrpc_addstr(&body, cmd->method, strlen(cmd->method));
00624 if (ret<0) goto binrpc_err;
00625 for (r=0; r<cmd->argc; r++){
00626 switch(cmd->argv[r].type){
00627 case BINRPC_T_STR:
00628 ret=binrpc_addstr(&body, cmd->argv[r].u.strval.s,
00629 cmd->argv[r].u.strval.len);
00630 break;
00631 case BINRPC_T_INT:
00632 ret=binrpc_addint(&body, cmd->argv[r].u.intval);
00633 break;
00634 case BINRPC_T_DOUBLE:
00635 ret=binrpc_adddouble(&body, cmd->argv[r].u.fval);
00636 break;
00637 default:
00638 fprintf(stderr, "ERROR: unsupported type %d\n",
00639 cmd->argv[r].type);
00640 }
00641 if (ret<0) goto binrpc_err;
00642 }
00643 ret=binrpc_build_hdr(BINRPC_REQ, binrpc_pkt_len(&body), cookie, msg_hdr,
00644 BINRPC_MAX_HDR_SIZE);
00645 if (ret<0) goto binrpc_err;
00646 v[0].iov_base=msg_hdr;
00647 v[0].iov_len=ret;
00648 v[1].iov_base=msg_body;
00649 v[1].iov_len=binrpc_pkt_len(&body);
00650 write_again:
00651 if ((n=writev(s, v, 2))<0){
00652 if (errno==EINTR)
00653 goto write_again;
00654 goto error_send;
00655 }
00656
00657 return n;
00658 error_send:
00659 return -1;
00660 binrpc_err:
00661 return -2;
00662 }
00663
00664
00665 static int binrpc_errno=0;
00666
00667
00668
00669
00670
00671
00672
00673
00674 static int get_reply(int s, unsigned char* reply_buf, int max_reply_size,
00675 int cookie, struct binrpc_parse_ctx* in_pkt,
00676 unsigned char** body)
00677 {
00678 unsigned char* crt;
00679 unsigned char* hdr_end;
00680 unsigned char* msg_end;
00681 int n;
00682 int ret;
00683
00684
00685 hdr_end=crt=reply_buf;
00686 msg_end=reply_buf+max_reply_size;
00687 binrpc_errno=0;
00688 do{
00689 n=read(s, crt, (int)(msg_end-crt));
00690 if (n<=0){
00691 if (errno==EINTR)
00692 continue;
00693 goto error_read;
00694 }
00695 if (verbose >= 3){
00696
00697 printf("received %d bytes in reply (@offset %d):\n",
00698 n, (int)(crt-reply_buf));
00699 hexdump(crt, n, 1);
00700 }
00701 crt+=n;
00702
00703 if (hdr_end==reply_buf){
00704 hdr_end=binrpc_parse_init(in_pkt, reply_buf, n, &ret);
00705 if (ret<0){
00706 if (ret==E_BINRPC_MORE_DATA)
00707 continue;
00708 goto error_parse;
00709 }
00710 if (verbose>1){
00711 printf("new packet: type %02x, len %d, cookie %02x\n",
00712 in_pkt->type, in_pkt->tlen, in_pkt->cookie);
00713 }
00714 if (in_pkt->cookie!=cookie){
00715 fprintf(stderr, "bad reply, cookie doesn't match: sent %02x "
00716 "and received %02x\n",
00717 cookie, in_pkt->cookie);
00718 goto error;
00719 }
00720 msg_end=hdr_end+in_pkt->tlen;
00721 if ((int)(msg_end-reply_buf)>max_reply_size)
00722 goto error_toolong;
00723 }
00724 }while(crt<msg_end);
00725
00726 *body=hdr_end;
00727 return (int)(msg_end-reply_buf);
00728 error_read:
00729 return -1;
00730 error_parse:
00731 binrpc_errno=ret;
00732 return -2;
00733 error:
00734 return -3;
00735 error_toolong:
00736 return -4;
00737 }
00738
00739
00740
00741
00742 static char* str_escape(char* str)
00743 {
00744 char* n;
00745 char* ret;
00746
00747 ret=n=malloc(strlen(str)+1);
00748 if (n==0)
00749 goto end;
00750
00751 for(;*str;str++){
00752 *n=*str;
00753 if (*str=='\\'){
00754 switch(*(str+1)){
00755 case 'n':
00756 *n='\n';
00757 str++;
00758 break;
00759 case 'r':
00760 *n='\r';
00761 str++;
00762 break;
00763 case 't':
00764 *n='\t';
00765 str++;
00766 break;
00767 case '\\':
00768 str++;
00769 break;
00770 }
00771 }
00772 n++;
00773 }
00774 *n=*str;
00775 end:
00776 return ret;
00777 }
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 static char* parse_fmt(char* fmt, int* type, int* size)
00800 {
00801 char* s;
00802
00803 s=fmt;
00804 do{
00805 for(;*fmt && *fmt!='%'; fmt++);
00806 if (*fmt=='%'){
00807 switch(*(fmt+1)){
00808 case 'v':
00809 *type=BINRPC_T_ALL;
00810 *size=(int)(fmt-s);
00811 return (fmt+2);
00812 break;
00813 case '%':
00814
00815 *size=(int)(fmt-s)+1;
00816 *type=-1;
00817 return (fmt+2);
00818 break;
00819 }
00820 }
00821 }while(*fmt);
00822 *type=-1;
00823 *size=(fmt-s);
00824 return fmt;
00825 }
00826
00827
00828
00829 static int print_body(struct binrpc_parse_ctx* in_pkt,
00830 unsigned char* body, int size, char* fmt)
00831 {
00832
00833 unsigned char* p;
00834 unsigned char* end;
00835 struct binrpc_val val;
00836 int ret;
00837 int rec;
00838 char *f;
00839 char* s;
00840 int f_size;
00841 int fmt_has_values;
00842
00843 p=body;
00844 end=p+size;
00845 rec=0;
00846 f=fmt;
00847 fmt_has_values=0;
00848
00849 while(p<end){
00850 if (f){
00851
00852 do{
00853 if (*f==0)
00854 f=fmt;
00855 s=f;
00856 f=parse_fmt(f, &val.type, &f_size);
00857 printf("%.*s", f_size, s);
00858 if (val.type!=-1){
00859 fmt_has_values=1;
00860 goto read_value;
00861 }
00862 }while(*f || fmt_has_values);
00863 val.type=BINRPC_T_ALL;
00864 }else{
00865 val.type=BINRPC_T_ALL;
00866 }
00867 read_value:
00868 val.name.s=0;
00869 val.name.len=0;
00870 p=binrpc_read_record(in_pkt, p, end, &val, &ret);
00871 if (ret<0){
00872 if (fmt)
00873 putchar('\n');
00874
00875
00876 if (ret==E_BINRPC_EOP){
00877 printf("end of message detected\n");
00878 break;
00879 }
00880 fprintf(stderr, "ERROR while parsing the record %d,"
00881 " @%d: %02x : %s\n", rec,
00882 in_pkt->offset, *p, binrpc_error(ret));
00883 goto error;
00884 }
00885 rec++;
00886 if (fmt){
00887 print_binrpc_val(&val, 0);
00888 }else{
00889 print_binrpc_val(&val, in_pkt->in_struct+in_pkt->in_array);
00890 putchar('\n');
00891 }
00892 }
00893 if (fmt && *f){
00894
00895 while(*f){
00896 s=f;
00897 f=parse_fmt(f, &val.type, &f_size);
00898 printf("%.*s", f_size, s);
00899 }
00900 }
00901 return 0;
00902 error:
00903 return -1;
00904
00905
00906
00907
00908 }
00909
00910
00911
00912 static int print_fault(struct binrpc_parse_ctx* in_pkt,
00913 unsigned char* body, int size)
00914 {
00915 printf("error: ");
00916 return print_body(in_pkt, body, size, "%v - %v\n");
00917 }
00918
00919
00920
00921 static int run_binrpc_cmd(int s, struct binrpc_cmd * cmd, char* fmt)
00922 {
00923 int cookie;
00924 unsigned char reply_buf[MAX_REPLY_SIZE];
00925 unsigned char* msg_body;
00926 struct binrpc_parse_ctx in_pkt;
00927 int ret;
00928
00929 cookie=gen_cookie();
00930 if ((ret=send_binrpc_cmd(s, cmd, cookie))<0){
00931 if (ret==-1) goto error_send;
00932 else goto binrpc_err;
00933 }
00934
00935 memset(&in_pkt, 0, sizeof(in_pkt));
00936 if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
00937 &msg_body))<0){
00938 switch(ret){
00939 case -1:
00940 goto error_read;
00941 case -2:
00942 goto error_parse;
00943 case -3:
00944 goto error_cookie;
00945 case -4:
00946 goto error_toobig;
00947 }
00948 goto error;
00949 }
00950 switch(in_pkt.type){
00951 case BINRPC_FAULT:
00952 if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
00953 goto error;
00954 }
00955 break;
00956 case BINRPC_REPL:
00957 if (print_body(&in_pkt, msg_body, in_pkt.tlen, fmt)<0){
00958 goto error;
00959 }
00960 break;
00961 default:
00962 fprintf(stderr, "ERROR: not a reply\n");
00963 goto error;
00964 }
00965 if (verbose) printf(".\n");
00966
00967 return 0;
00968 binrpc_err:
00969 fprintf(stderr, "ERROR while building the packet: %s\n",
00970 binrpc_error(ret));
00971 goto error;
00972 error_parse:
00973 fprintf(stderr, "ERROR while parsing the reply: %s\n",
00974 binrpc_error(binrpc_errno));
00975 goto error;
00976 error_cookie:
00977 fprintf(stderr, "ERROR: cookie does not match\n");
00978 goto error;
00979 error_toobig:
00980 fprintf(stderr, "ERROR: reply too big\n");
00981 goto error;
00982 error_send:
00983 fprintf(stderr, "ERROR: send packet failed: %s (%d)\n",
00984 strerror(errno), errno);
00985 goto error;
00986 error_read:
00987 fprintf(stderr, "ERROR: read reply failed: %s (%d)\n",
00988 strerror(errno), errno);
00989 goto error;
00990 error:
00991 return -1;
00992 }
00993
00994
00995
00996 static int parse_line(struct binrpc_cmd* cmd, char* line)
00997 {
00998 char* p;
00999 int count;
01000
01001 cmd->method=strtok(line, " \t");
01002 if (cmd->method==0)
01003 goto error_no_method;
01004 count=0;
01005 for(p=strtok(0, " \t"); p; p=strtok(0, " \t")){
01006 if (count>=MAX_BINRPC_ARGS)
01007 goto error_too_many;
01008 if (parse_arg(&cmd->argv[count], p)<0){
01009 goto error_arg;
01010 }
01011 count++;
01012 }
01013 cmd->argc=count;
01014 return 0;
01015 error_no_method:
01016 printf( "ERROR: no method name\n");
01017 return -1;
01018 error_too_many:
01019 printf("ERROR: too many arguments (%d), no more than %d allowed\n",
01020 count, MAX_BINRPC_ARGS);
01021 return -1;
01022 error_arg:
01023 printf("ERROR: bad argument %d: %s\n", count+1, p);
01024 return -1;
01025 }
01026
01027
01028
01029
01030 static void fix_cmd(struct binrpc_cmd* cmd, char** format)
01031 {
01032 int r;
01033
01034 for (r=0; cmd_aliases[r].name; r++){
01035 if (strcmp(cmd_aliases[r].name, cmd->method)==0){
01036 cmd->method=cmd_aliases[r].method;
01037 if (*format==0)
01038 *format=cmd_aliases[r].format;
01039 break;
01040 }
01041 }
01042 }
01043
01044
01045
01046
01047
01048 static int run_builtins(int s, struct binrpc_cmd* cmd)
01049 {
01050 int r;
01051 int ret;
01052
01053 for (r=0; builtins[r].name; r++){
01054 if (strcmp(builtins[r].name, cmd->method)==0){
01055 ret=builtins[r].f(s, cmd);
01056 return (ret<0)?ret:1;
01057 }
01058 }
01059 return 0;
01060 }
01061
01062
01063
01064
01065 inline static int run_cmd(int s, struct binrpc_cmd* cmd, char* format)
01066 {
01067 int ret;
01068 char* fmt;
01069
01070 fmt=format;
01071
01072 fix_cmd(cmd, &fmt);
01073 if (!(ret=run_builtins(s, cmd))){
01074 ret=run_binrpc_cmd(s, cmd, fmt);
01075 }
01076 return (ret>0)?0:ret;
01077 }
01078
01079
01080
01081
01082 inline static int run_line(int s, char* l, char* format)
01083 {
01084 struct binrpc_cmd cmd;
01085 int ret;
01086
01087 if ((ret=parse_line(&cmd, l))==0){
01088 return run_cmd(s, &cmd, format);
01089 }
01090 return ret;
01091 }
01092
01093
01094
01095 static void free_rpc_array(struct binrpc_val* a, int size)
01096 {
01097 int r;
01098 for (r=0; r<size; r++){
01099 if (a[r].name.s)
01100 free(a[r].name.s);
01101 if ((a[r].type==BINRPC_T_STR || a[r].type==BINRPC_T_BYTES) &&
01102 a[r].u.strval.s){
01103 free(a[r].u.strval.s);
01104 }
01105 }
01106 free(a);
01107 }
01108
01109
01110
01111
01112 static struct binrpc_val* parse_reply_body(int* records,
01113 struct binrpc_parse_ctx* in_pkt,
01114 unsigned char* body, int size)
01115 {
01116 struct binrpc_val* a;
01117 struct binrpc_val* t;
01118 unsigned char* p;
01119 unsigned char* end;
01120 struct binrpc_val val;
01121 int ret;
01122 int rec;
01123
01124 rec=0;
01125 if (*records==0){
01126 *records=100;
01127 };
01128 a=malloc(*records*sizeof(struct binrpc_val));
01129 if (a==0)
01130 goto error_mem;
01131 p=body;
01132 end=p+size;
01133
01134
01135 while(p<end){
01136 val.type=BINRPC_T_ALL;
01137 val.name.s=0;
01138 val.name.len=0;
01139 p=binrpc_read_record(in_pkt, p, end, &val, &ret);
01140 if (ret<0){
01141 if (ret==E_BINRPC_EOP){
01142 printf("end of message detected\n");
01143 break;
01144 }
01145 fprintf(stderr, "ERROR while parsing the record %d,"
01146 " @%d: %02x : %s\n", rec,
01147 in_pkt->offset, *p, binrpc_error(ret));
01148 goto error;
01149 }
01150 if (rec>=*records){
01151 t=realloc(a, *records*sizeof(struct binrpc_val)*2);
01152 if (t==0)
01153 goto error_mem;
01154 a=t;
01155 *records*=2;
01156 }
01157 a[rec]=val;
01158 if (val.name.s){
01159 if ((a[rec].name.s=malloc(val.name.len+1))==0)
01160 goto error_mem;
01161 memcpy(a[rec].name.s, val.name.s, val.name.len);
01162 a[rec].name.s[val.name.len+1]=0;
01163 }
01164 if (val.u.strval.s){
01165 if (val.type==BINRPC_T_STR){
01166 if ((a[rec].u.strval.s=malloc(val.u.strval.len+1))==0)
01167 goto error_mem;
01168 memcpy(a[rec].u.strval.s, val.u.strval.s, val.u.strval.len);
01169 a[rec].u.strval.s[val.u.strval.len]=0;
01170 }else if (val.type==BINRPC_T_BYTES){
01171 if ((a[rec].u.strval.s=malloc(val.u.strval.len))==0)
01172 goto error_mem;
01173 memcpy(a[rec].u.strval.s, val.u.strval.s, val.u.strval.len);
01174 }
01175 }
01176 rec++;
01177 }
01178 if (rec && (rec<*records)){
01179 a=realloc(a, rec*sizeof(struct binrpc_val));
01180 }
01181 *records=rec;
01182 return a;
01183 error_mem:
01184 fprintf(stderr, "ERROR: parse_reply_body: out of memory\n");
01185 error:
01186 if (a){
01187 free_rpc_array(a, rec);
01188 }
01189 *records=0;
01190 return 0;
01191 }
01192
01193
01194
01195 static int get_sercmd_list(int s)
01196 {
01197 struct binrpc_cmd cmd;
01198 int cookie;
01199 unsigned char reply_buf[MAX_REPLY_SIZE];
01200 unsigned char* msg_body;
01201 struct binrpc_parse_ctx in_pkt;
01202 int ret;
01203
01204 cmd.method="system.listMethods";
01205 cmd.argc=0;
01206
01207 cookie=gen_cookie();
01208 if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
01209 if (ret==-1) goto error_send;
01210 else goto binrpc_err;
01211 }
01212
01213 memset(&in_pkt, 0, sizeof(in_pkt));
01214 if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
01215 &msg_body))<0){
01216 goto error;
01217 }
01218 switch(in_pkt.type){
01219 case BINRPC_FAULT:
01220 if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
01221 goto error;
01222 }
01223 break;
01224 case BINRPC_REPL:
01225 rpc_no=100;
01226 if ((rpc_array=parse_reply_body(&rpc_no, &in_pkt, msg_body,
01227 in_pkt.tlen))==0)
01228 goto error;
01229 break;
01230 default:
01231 fprintf(stderr, "ERROR: not a reply\n");
01232 goto error;
01233 }
01234 return 0;
01235 binrpc_err:
01236 error_send:
01237 error:
01238 return -1;
01239 }
01240
01241
01242
01243 #if defined(USE_CFG_VARS) || defined (USE_MI) || defined (USE_COUNTERS)
01244
01249 static int is_rpc_cmd(char* cmd)
01250 {
01251 int r;
01252 int cmd_len;
01253
01254 cmd_len=strlen(cmd);
01255 for (r=0; r<rpc_no; r++){
01256 if ((rpc_array[r].type==BINRPC_T_STR) &&
01257 (rpc_array[r].u.strval.len==cmd_len) &&
01258 (strncmp(cmd, rpc_array[r].u.strval.s, cmd_len)==0))
01259 return 1;
01260 }
01261 return 0;
01262 }
01263 #endif
01264
01265
01266
01267 #ifdef USE_CFG_VARS
01268
01269 static int get_cfgvars_list(int s)
01270 {
01271 struct binrpc_cmd cmd;
01272 int cookie;
01273 unsigned char reply_buf[MAX_REPLY_SIZE];
01274 unsigned char* msg_body;
01275 struct binrpc_parse_ctx in_pkt;
01276 struct cfg_var_grp* grp;
01277 struct cfg_var_grp* last_grp;
01278 char* p;
01279 char* end;
01280 str grp_name;
01281 str var_name;
01282 int r;
01283 int ret;
01284
01285 cmd.method="cfg.list";
01286 cmd.argc=0;
01287 if (!is_rpc_cmd(cmd.method)) goto error;
01288
01289 cookie=gen_cookie();
01290 if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
01291 if (ret==-1) goto error_send;
01292 else goto binrpc_err;
01293 }
01294
01295 memset(&in_pkt, 0, sizeof(in_pkt));
01296 if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
01297 &msg_body))<0){
01298 goto error;
01299 }
01300 switch(in_pkt.type){
01301 case BINRPC_FAULT:
01302 if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
01303 goto error;
01304 }
01305 break;
01306 case BINRPC_REPL:
01307 cfg_vars_no=100;
01308 if ((cfg_vars_array=parse_reply_body(&cfg_vars_no, &in_pkt,
01309 msg_body, in_pkt.tlen))==0)
01310 goto error;
01311 break;
01312 default:
01313 fprintf(stderr, "ERROR: not a reply\n");
01314 goto error;
01315 }
01316
01317 last_grp=0;
01318 for (r=0; r<cfg_vars_no; r++){
01319 grp_name.s=0; grp_name.len=0;
01320 if (cfg_vars_array[r].type!=BINRPC_T_STR)
01321 continue;
01322 grp_name.s=cfg_vars_array[r].u.strval.s;
01323 end=cfg_vars_array[r].u.strval.len+grp_name.s;
01324
01325 for (p=grp_name.s; p<end; p++){
01326 if (*p==':'){
01327 grp_name.len=(int)(long)(p-grp_name.s);
01328 break;
01329 }
01330 }
01331 for (grp=cfg_grp_lst; grp; grp=grp->next){
01332 if (grp->grp_name.len==grp_name.len &&
01333 memcmp(grp->grp_name.s, grp_name.s, grp_name.len)==0){
01334 break;
01335 }
01336 }
01337 if (grp==0){
01338
01339 grp=malloc(sizeof(*grp));
01340 if (grp==0) goto error_mem;
01341 memset(grp, 0, sizeof(*grp));
01342 grp->grp_name=grp_name;
01343 if (last_grp){
01344 last_grp->next=grp;
01345 last_grp=grp;
01346 }else{
01347 cfg_grp_lst=grp;
01348 last_grp=cfg_grp_lst;
01349 }
01350 }
01351 grp->var_no++;
01352 }
01353
01354 for (grp=cfg_grp_lst; grp; grp=grp->next){
01355 grp->var_names=malloc(sizeof(str)*grp->var_no);
01356 if (grp->var_names==0) goto error_mem;
01357 memset(grp->var_names, 0, sizeof(str)*grp->var_no);
01358 grp->var_no=0;
01359 }
01360
01361 for (r=0; r<cfg_vars_no; r++){
01362 grp_name.s=0; grp_name.len=0;
01363 var_name.s=0; var_name.len=0;
01364 if (cfg_vars_array[r].type!=BINRPC_T_STR)
01365 continue;
01366 grp_name.s=cfg_vars_array[r].u.strval.s;
01367 end=cfg_vars_array[r].u.strval.len+grp_name.s;
01368
01369 for (p=grp_name.s; p<end; p++){
01370 if (*p==':'){
01371 grp_name.len=(int)(long)(p-grp_name.s);
01372 p++;
01373 for (; p<end && *p==' '; p++);
01374 var_name.s=p;
01375 var_name.len=(int)(long)(end-p);
01376 if (var_name.len==0) break;
01377 for (grp=cfg_grp_lst; grp; grp=grp->next){
01378 if (grp->grp_name.len==grp_name.len &&
01379 memcmp(grp->grp_name.s, grp_name.s, grp_name.len)==0){
01380
01381 grp->var_names[grp->var_no]=var_name;
01382 grp->var_no++;
01383 }
01384 }
01385 break;
01386 }
01387 }
01388 }
01389 return 0;
01390 binrpc_err:
01391 error_send:
01392 error:
01393 error_mem:
01394 return -1;
01395 }
01396
01397
01398
01399 void free_cfg_grp_lst()
01400 {
01401 struct cfg_var_grp* grp;
01402 struct cfg_var_grp* last;
01403
01404 grp=cfg_grp_lst;
01405 while(grp){
01406 last=grp;
01407 grp=grp->next;
01408 free(last);
01409 }
01410 cfg_grp_lst=0;
01411 }
01412 #endif
01413
01414
01415
01416 #ifdef USE_MI
01417
01418 static int get_mi_list(int s)
01419 {
01420 struct binrpc_cmd cmd;
01421 int cookie;
01422 unsigned char reply_buf[MAX_REPLY_SIZE];
01423 unsigned char* msg_body;
01424 struct binrpc_parse_ctx in_pkt;
01425 char* p;
01426 char* end;
01427 str mi_name;
01428 int mi_which_results;
01429 int r;
01430 int ret;
01431
01432 cmd.method="mi";
01433 cmd.argv[0].type=BINRPC_T_STR;
01434 cmd.argv[0].u.strval.s="which";
01435 cmd.argv[0].u.strval.len=strlen(cmd.argv[0].u.strval.s);
01436 cmd.argc=1;
01437 if (!is_rpc_cmd(cmd.method)) goto error;
01438
01439 cookie=gen_cookie();
01440 if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
01441 if (ret==-1) goto error_send;
01442 else goto binrpc_err;
01443 }
01444
01445 memset(&in_pkt, 0, sizeof(in_pkt));
01446 if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
01447 &msg_body))<0){
01448 goto error;
01449 }
01450 switch(in_pkt.type){
01451 case BINRPC_FAULT:
01452 if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
01453 goto error;
01454 }
01455 break;
01456 case BINRPC_REPL:
01457 mi_which_no=25;
01458 if ((mi_which_array=parse_reply_body(&mi_which_no, &in_pkt,
01459 msg_body, in_pkt.tlen))==0)
01460 goto error;
01461 break;
01462 default:
01463 fprintf(stderr, "ERROR: not a reply\n");
01464 goto error;
01465 }
01466
01467
01468
01469 mi_which_results=0;
01470 for (r=0; r<mi_which_no; r++){
01471 if (mi_which_array[r].type!=BINRPC_T_STR)
01472 continue;
01473
01474
01475 if ((mi_which_array[r].u.strval.len) &&
01476 (mi_which_array[r].u.strval.s[0]==':'))
01477 mi_which_results++;
01478 }
01479
01480 if (mi_which_results==0)
01481 goto error;
01482
01483 mi_cmds=malloc(mi_which_results*sizeof(*mi_cmds));
01484 if (mi_cmds==0) goto error_mem;
01485 memset(mi_cmds, 0, mi_which_results* sizeof(mi_cmds));
01486
01487 for (r=0; r<mi_which_no; r++){
01488 if (mi_which_array[r].type!=BINRPC_T_STR)
01489 continue;
01490 p=mi_which_array[r].u.strval.s;
01491 end=p+mi_which_array[r].u.strval.len;
01492
01493
01494 if ((p>=end) || (*p!=':'))
01495 continue;
01496 p++;
01497
01498 for(;p<end && *p!=':'; p++);
01499 if (p>=end) continue;
01500 p++;
01501
01502 for(;p<end && (*p==' ' || *p=='\t'); p++);
01503 if (p>=end || *p=='\n') continue;
01504 if (mi_cmds_no >= mi_which_results){
01505 fprintf(stderr, "BUG: wrong mi cmds no (%d >= %d)\n",
01506 mi_cmds_no, mi_which_results);
01507 goto error;
01508 }
01509 mi_name.s=p;
01510 for(; p<end && *p!=' ' && *p!='\t' && *p!='\n'; p++);
01511 mi_name.len=(int)(long)(p-mi_name.s);
01512 mi_cmds[mi_cmds_no]=mi_name;
01513 mi_cmds_no++;
01514 }
01515
01516 return 0;
01517 binrpc_err:
01518 error_send:
01519 error:
01520 error_mem:
01521 return -1;
01522 }
01523
01524
01525
01526 void free_mi_cmds()
01527 {
01528 if (mi_cmds){
01529 free(mi_cmds);
01530 mi_cmds=0;
01531 mi_cmds_no=0;
01532 }
01533 }
01534 #endif
01535
01536
01537
01538 #ifdef USE_COUNTERS
01539
01540 static int get_counters_list(int s)
01541 {
01542 struct binrpc_cmd cmd;
01543 int cookie;
01544 unsigned char reply_buf[MAX_REPLY_SIZE];
01545 unsigned char* msg_body;
01546 struct binrpc_parse_ctx in_pkt;
01547 struct cnt_var_grp* grp;
01548 struct cnt_var_grp* last_grp;
01549 str grp_name;
01550 str var_name;
01551 int r;
01552 int ret;
01553
01554 cmd.method="cnt.grps_list";
01555 cmd.argc=0;
01556 if (!is_rpc_cmd(cmd.method)) goto error;
01557
01558 cookie=gen_cookie();
01559 if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
01560 if (ret==-1) goto error_send;
01561 else goto binrpc_err;
01562 }
01563
01564 memset(&in_pkt, 0, sizeof(in_pkt));
01565 if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
01566 &msg_body))<0){
01567 goto error;
01568 }
01569 switch(in_pkt.type){
01570 case BINRPC_FAULT:
01571 if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
01572 goto error;
01573 }
01574 break;
01575 case BINRPC_REPL:
01576 cnt_grps_no=20;
01577 if ((cnt_grps_array=parse_reply_body(&cnt_grps_no, &in_pkt,
01578 msg_body, in_pkt.tlen))==0)
01579 goto error;
01580 break;
01581 default:
01582 fprintf(stderr, "ERROR: not a reply\n");
01583 goto error;
01584 }
01585
01586 last_grp=0;
01587 for (r=0; r<cnt_grps_no; r++){
01588 grp_name.s=0; grp_name.len=0;
01589 if (cnt_grps_array[r].type!=BINRPC_T_STR)
01590 continue;
01591 grp_name=cnt_grps_array[r].u.strval;
01592
01593 for (grp=cnt_grp_lst; grp; grp=grp->next){
01594 if (grp->grp_name.len==grp_name.len &&
01595 memcmp(grp->grp_name.s, grp_name.s, grp_name.len)==0){
01596 break;
01597 }
01598 }
01599 if (grp==0){
01600
01601 grp=malloc(sizeof(*grp));
01602 if (grp==0) goto error_mem;
01603 memset(grp, 0, sizeof(*grp));
01604 grp->grp_name=grp_name;
01605 if (last_grp){
01606 last_grp->next=grp;
01607 last_grp=grp;
01608 }else{
01609 cnt_grp_lst=grp;
01610 last_grp=cnt_grp_lst;
01611 }
01612 }
01613 }
01614
01615 for (grp=cnt_grp_lst; grp; grp=grp->next){
01616 cmd.method="cnt.var_list";
01617 cmd.argv[0].type=BINRPC_T_STR;
01618 cmd.argv[0].u.strval=grp->grp_name;
01619 cmd.argc=1;
01620 if (!is_rpc_cmd(cmd.method)) goto error;
01621 cookie=gen_cookie();
01622 if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
01623 if (ret==-1) goto error_send;
01624 else goto binrpc_err;
01625 }
01626
01627 memset(&in_pkt, 0, sizeof(in_pkt));
01628 if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
01629 &msg_body))<0){
01630 goto error;
01631 }
01632 switch(in_pkt.type){
01633 case BINRPC_FAULT:
01634 if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
01635 goto error;
01636 }
01637 break;
01638 case BINRPC_REPL:
01639 grp->cnt_vars_no=100;
01640 if ((grp->cnt_vars_array=parse_reply_body(&grp->cnt_vars_no,
01641 &in_pkt, msg_body,
01642 in_pkt.tlen))==0)
01643 goto error;
01644 break;
01645 default:
01646 fprintf(stderr, "ERROR: not a reply\n");
01647 goto error;
01648 }
01649 grp->var_no = 0;
01650 grp->var_names=malloc(sizeof(str)*grp->cnt_vars_no);
01651 if (grp->var_names==0) goto error_mem;
01652 memset(grp->var_names, 0, sizeof(str)*grp->var_no);
01653 for (r=0; r<grp->cnt_vars_no; r++) {
01654 if (grp->cnt_vars_array[r].type!=BINRPC_T_STR)
01655 continue;
01656 var_name=grp->cnt_vars_array[r].u.strval;
01657 grp->var_names[grp->var_no] = var_name;
01658 grp->var_no++;
01659 }
01660 }
01661 return 0;
01662 binrpc_err:
01663 error_send:
01664 error:
01665 error_mem:
01666 return -1;
01667 }
01668
01669
01670
01671 void free_cnt_grp_lst()
01672 {
01673 struct cnt_var_grp* grp;
01674 struct cnt_var_grp* last;
01675
01676 grp=cnt_grp_lst;
01677 while(grp){
01678 last=grp;
01679 grp=grp->next;
01680 if (last->cnt_vars_array)
01681 free_rpc_array(last->cnt_vars_array, last->cnt_vars_no);
01682 free(last);
01683 }
01684 cnt_grp_lst=0;
01685 }
01686 #endif
01687
01688
01689
01690
01691 static void print_formatting(char* prefix, char* format, char* suffix)
01692 {
01693 if (format){
01694 printf("%s", prefix);
01695 for (;*format;format++){
01696 switch(*format){
01697 case '\t':
01698 printf("\\t");
01699 break;
01700 case '\n':
01701 printf("\\n");
01702 break;
01703 case '\r':
01704 printf("\\r");
01705 break;
01706 default:
01707 putchar(*format);
01708 }
01709 }
01710 printf("%s", suffix);
01711 }
01712 }
01713
01714
01715
01716 static int sercmd_help(int s, struct binrpc_cmd* cmd)
01717 {
01718 int r;
01719
01720 if (cmd->argc && (cmd->argv[0].type==BINRPC_T_STR)){
01721
01722 for (r=0; cmd_aliases[r].name; r++){
01723 if (strcmp(cmd->argv[0].u.strval.s, cmd_aliases[r].name)==0){
01724 printf("%s is an alias for %s", cmd->argv[0].u.strval.s,
01725 cmd_aliases[r].method);
01726 print_formatting(" with reply formatting: \"",
01727 cmd_aliases[r].format, "\"");
01728 putchar('\n');
01729 return 0;
01730 }
01731 }
01732 for(r=0; builtins[r].name; r++){
01733 if (strcmp(cmd->argv[0].u.strval.s, builtins[r].name)==0){
01734 printf("builtin command: %s\n",
01735 builtins[r].doc?builtins[r].doc:"undocumented");
01736 return 0;
01737 }
01738 }
01739 cmd->method="system.methodHelp";
01740 if (run_binrpc_cmd(s, cmd, 0)<0){
01741 printf("error: no such command %s\n", cmd->argv[0].u.strval.s);
01742 }
01743 return 0;
01744 }
01745
01746 if (rpc_no==0){
01747 if (get_sercmd_list(s)<0)
01748 goto error;
01749 }
01750 for (r=0; r<rpc_no; r++){
01751 if (rpc_array[r].type==BINRPC_T_STR){
01752 printf("%s\n", rpc_array[r].u.strval.s);
01753 }
01754 }
01755 for (r=0; cmd_aliases[r].name; r++){
01756 printf("alias: %s\n", cmd_aliases[r].name);
01757 }
01758 for(r=0; builtins[r].name; r++){
01759 printf("builtin: %s\n", builtins[r].name);
01760 }
01761 return 0;
01762 error:
01763 return -1;
01764 }
01765
01766
01767
01768 static int sercmd_ver(int s, struct binrpc_cmd* cmd)
01769 {
01770 printf("%s\n", version);
01771 printf("%s\n", id);
01772 printf("%s compiled on %s \n", __FILE__, compiled);
01773 #ifdef USE_READLINE
01774 printf("interactive mode command completion support\n");
01775 #endif
01776 return 0;
01777 }
01778
01779
01780
01781 static int sercmd_quit(int s, struct binrpc_cmd* cmd)
01782 {
01783 quit=1;
01784 return 0;
01785 }
01786
01787
01788
01789 static int sercmd_warranty(int s, struct binrpc_cmd *cmd)
01790 {
01791 printf("%s %s\n", NAME, VERSION);
01792 printf("%s\n", COPYRIGHT);
01793 printf("\n%s\n", LICENSE);
01794 return 0;
01795 }
01796
01797
01798 #ifdef USE_READLINE
01799
01800
01801 static char* sercmd_generator(const char* text, int state)
01802 {
01803 static int idx;
01804 static int list;
01805 static int len;
01806 char* name;
01807 #ifdef USE_CFG_VARS
01808 static struct cfg_var_grp* grp;
01809 #endif
01810 #ifdef USE_COUNTERS
01811 static struct cnt_var_grp* cnt_grp;
01812 #endif
01813 switch(attempted_completion_state){
01814 case COMPLETE_INIT:
01815 case COMPLETE_NOTHING:
01816 return 0;
01817 case COMPLETE_CMD_NAME:
01818 if (state==0){
01819
01820 idx=list=0;
01821 len=strlen(text);
01822 }
01823
01824 switch(list){
01825 case 0:
01826 while((name=cmd_aliases[idx].name)){
01827 idx++;
01828 if (strncmp(name, text, len)==0)
01829 return strdup(name);
01830 }
01831 list++;
01832 idx=0;
01833
01834 case 1:
01835 while((name=builtins[idx].name)){
01836 idx++;
01837 if (strncmp(name, text, len)==0)
01838 return strdup(name);
01839 }
01840 list++;
01841 idx=0;
01842
01843 case 2:
01844 while(idx < rpc_no){
01845 if (rpc_array[idx].type==BINRPC_T_STR){
01846 name=rpc_array[idx].u.strval.s;
01847 idx++;
01848 if (strncmp(name, text, len)==0)
01849 return strdup(name);
01850 }else{
01851 idx++;
01852 }
01853 }
01854 }
01855 break;
01856 #ifdef USE_CFG_VARS
01857 case COMPLETE_CFG_GRP:
01858 if (state==0){
01859
01860 len=strlen(text);
01861 grp=cfg_grp_lst;
01862 }else{
01863 grp=grp->next;
01864 }
01865 for(;grp; grp=grp->next){
01866 if (len<=grp->grp_name.len &&
01867 memcmp(text, grp->grp_name.s, len)==0) {
01868
01869 name=malloc(grp->grp_name.len+1);
01870 if (name){
01871 memcpy(name, grp->grp_name.s, grp->grp_name.len);
01872 name[grp->grp_name.len]=0;
01873 }
01874 return name;
01875 }
01876 }
01877 break;
01878 case COMPLETE_CFG_VAR:
01879 if (state==0){
01880
01881 len=strlen(text);
01882 idx=0;
01883 }
01884 while(idx < crt_cfg_grp->var_no){
01885 if (len<=crt_cfg_grp->var_names[idx].len &&
01886 memcmp(text, crt_cfg_grp->var_names[idx].s, len)==0) {
01887
01888 name=malloc(crt_cfg_grp->var_names[idx].len+1);
01889 if (name){
01890 memcpy(name, crt_cfg_grp->var_names[idx].s,
01891 crt_cfg_grp->var_names[idx].len);
01892 name[crt_cfg_grp->var_names[idx].len]=0;
01893 }
01894 idx++;
01895 return name;
01896 }
01897 idx++;
01898 }
01899 break;
01900 #endif
01901 #ifdef USE_MI
01902 case COMPLETE_MI:
01903 if (state==0){
01904
01905 len=strlen(text);
01906 idx=0;
01907 }
01908 while(idx < mi_cmds_no){
01909 if (len<=mi_cmds[idx].len &&
01910 memcmp(text, mi_cmds[idx].s, len)==0) {
01911
01912 name=malloc(mi_cmds[idx].len+1);
01913 if (name){
01914 memcpy(name, mi_cmds[idx].s, mi_cmds[idx].len);
01915 name[mi_cmds[idx].len]=0;
01916 }
01917 idx++;
01918 return name;
01919 }
01920 idx++;
01921 }
01922 break;
01923 #endif
01924 #ifdef USE_COUNTERS
01925 case COMPLETE_CNT_GRP:
01926 if (state==0){
01927
01928 len=strlen(text);
01929 cnt_grp=cnt_grp_lst;
01930 }else{
01931 cnt_grp=cnt_grp->next;
01932 }
01933 for(;cnt_grp; cnt_grp=cnt_grp->next){
01934 if (len<=cnt_grp->grp_name.len &&
01935 memcmp(text, cnt_grp->grp_name.s, len)==0) {
01936
01937 name=malloc(cnt_grp->grp_name.len+1);
01938 if (name){
01939 memcpy(name, cnt_grp->grp_name.s,
01940 cnt_grp->grp_name.len);
01941 name[cnt_grp->grp_name.len]=0;
01942 }
01943 return name;
01944 }
01945 }
01946 break;
01947 case COMPLETE_CNT_VAR:
01948 if (state==0){
01949
01950 len=strlen(text);
01951 idx=0;
01952 }
01953 while(idx < crt_cnt_grp->var_no){
01954 if (len<=crt_cnt_grp->var_names[idx].len &&
01955 memcmp(text, crt_cnt_grp->var_names[idx].s, len)==0) {
01956
01957 name=malloc(crt_cnt_grp->var_names[idx].len+1);
01958 if (name){
01959 memcpy(name, crt_cnt_grp->var_names[idx].s,
01960 crt_cnt_grp->var_names[idx].len);
01961 name[crt_cnt_grp->var_names[idx].len]=0;
01962 }
01963 idx++;
01964 return name;
01965 }
01966 idx++;
01967 }
01968 break;
01969 #endif
01970 }
01971
01972 return 0;
01973 }
01974
01975
01976
01977 char** sercmd_completion(const char* text, int start, int end)
01978 {
01979 int i, j;
01980 int cmd_start, cmd_end, cmd_len;
01981 int whitespace;
01982 #ifdef USE_CFG_VARS
01983 struct cfg_var_grp* grp;
01984 static int grp_start;
01985 int grp_len;
01986 #endif
01987 #ifdef USE_COUNTERS
01988 struct cnt_var_grp* cnt_grp;
01989 static int cnt_grp_start;
01990 int cnt_grp_len;
01991 #endif
01992
01993 crt_param_no=0;
01994
01995 for (j=0; (j<start) && (rl_line_buffer[j]==' ' ||
01996 rl_line_buffer[j]=='\t'); j++);
01997 cmd_start=j;
01998 if (start==cmd_start){
01999
02000 attempted_completion_state=COMPLETE_CMD_NAME;
02001 #ifdef USE_CFG_VARS
02002 grp_start=0;
02003 #endif
02004 #ifdef USE_COUNTERS
02005 cnt_grp_start=0;
02006 #endif
02007 }else{
02008
02009 for(; (j<start) && (rl_line_buffer[j]!=' ') &&
02010 (rl_line_buffer[j]!='\t'); j++);
02011 cmd_end=j;
02012 cmd_len=cmd_end-cmd_start;
02013
02014 whitespace=1;
02015 for (; j<start; j++){
02016 if (rl_line_buffer[j]!=' ' && rl_line_buffer[j]!='\t'){
02017 if (whitespace) crt_param_no++;
02018 whitespace=0;
02019 }else
02020 whitespace=1;
02021 }
02022 crt_param_no++;
02023 if (crt_param_no==1){
02024 for(i=0; complete_params_methods[i]; i++){
02025 if ((cmd_len==strlen(complete_params_methods[i])) &&
02026 (strncmp(&rl_line_buffer[cmd_start],
02027 complete_params_methods[i],
02028 cmd_len)==0)){
02029 attempted_completion_state=COMPLETE_CMD_NAME;
02030 goto end;
02031 }
02032 }
02033 #ifdef USE_CFG_VARS
02034
02035 for(i=0; complete_params_cfg_var[i]; i++){
02036 if ((cmd_len==strlen(complete_params_cfg_var[i])) &&
02037 (strncmp(&rl_line_buffer[cmd_start],
02038 complete_params_cfg_var[i],
02039 cmd_len)==0)){
02040 attempted_completion_state=COMPLETE_CFG_GRP;
02041 grp_start=start;
02042 goto end;
02043 }
02044 }
02045 #endif
02046 #ifdef USE_MI
02047
02048 for(i=0; complete_params_mi[i]; i++){
02049 if ((cmd_len==strlen(complete_params_mi[i])) &&
02050 (strncmp(&rl_line_buffer[cmd_start],
02051 complete_params_mi[i],
02052 cmd_len)==0)){
02053 attempted_completion_state=COMPLETE_MI;
02054 goto end;
02055 }
02056 }
02057 #endif
02058 #ifdef USE_COUNTERS
02059
02060 for(i=0; complete_param1_counter_grp[i]; i++){
02061 if ((cmd_len==strlen(complete_param1_counter_grp[i])) &&
02062 (strncmp(&rl_line_buffer[cmd_start],
02063 complete_param1_counter_grp[i],
02064 cmd_len)==0)){
02065 attempted_completion_state=COMPLETE_CNT_GRP;
02066 cnt_grp_start=start;
02067 goto end;
02068 }
02069 }
02070 #endif
02071 }else if (crt_param_no==2){
02072 #ifdef USE_CFG_VARS
02073
02074 for(i=0; complete_params_cfg_var[i]; i++){
02075 if ((cmd_len==strlen(complete_params_cfg_var[i])) &&
02076 (strncmp(&rl_line_buffer[cmd_start],
02077 complete_params_cfg_var[i],
02078 cmd_len)==0)){
02079
02080
02081 for(j=cmd_end; (j<start) && ((rl_line_buffer[j]==' ') ||
02082 (rl_line_buffer[j]=='\t')); j++);
02083 grp_start=j;
02084
02085 for(j=grp_start; (j<start) && (rl_line_buffer[j]!=' ') &&
02086 (rl_line_buffer[j]!='\t'); j++);
02087 grp_len=j-grp_start;
02088 for(grp=cfg_grp_lst; grp; grp=grp->next){
02089 if (grp_len==grp->grp_name.len &&
02090 memcmp(&rl_line_buffer[grp_start],
02091 grp->grp_name.s, grp_len)==0) {
02092 attempted_completion_state=COMPLETE_CFG_VAR;
02093 crt_cfg_grp=grp;
02094 goto end;
02095 }
02096 }
02097 }
02098 }
02099 #endif
02100 #ifdef USE_COUNTERS
02101
02102 for(i=0; complete_param2_counter_name[i]; i++){
02103 if ((cmd_len==strlen(complete_param2_counter_name[i])) &&
02104 (strncmp(&rl_line_buffer[cmd_start],
02105 complete_param2_counter_name[i],
02106 cmd_len)==0)){
02107
02108
02109 for(j=cmd_end; (j<start) && ((rl_line_buffer[j]==' ') ||
02110 (rl_line_buffer[j]=='\t')); j++);
02111 cnt_grp_start=j;
02112
02113 for(j=cnt_grp_start; (j<start) &&
02114 (rl_line_buffer[j]!=' ') &&
02115 (rl_line_buffer[j]!='\t'); j++);
02116 cnt_grp_len=j-cnt_grp_start;
02117 for(cnt_grp=cnt_grp_lst; cnt_grp; cnt_grp=cnt_grp->next){
02118 if (cnt_grp_len==cnt_grp->grp_name.len &&
02119 memcmp(&rl_line_buffer[cnt_grp_start],
02120 cnt_grp->grp_name.s, cnt_grp_len)==0) {
02121 attempted_completion_state=COMPLETE_CNT_VAR;
02122 crt_cnt_grp=cnt_grp;
02123 goto end;
02124 }
02125 }
02126 }
02127 }
02128 #endif
02129 }
02130 attempted_completion_state=COMPLETE_NOTHING;
02131 }
02132 end:
02133 return 0;
02134 }
02135
02136 #endif
02137
02138
02139
02140
02141 static void cleanup()
02142 {
02143 if (unix_socket){
02144 if (unlink(unix_socket)<0){
02145 fprintf(stderr, "ERROR: failed to delete %s: %s\n",
02146 unix_socket, strerror(errno));
02147 }
02148 }
02149 }
02150
02151
02152
02153 int main(int argc, char** argv)
02154 {
02155 int c;
02156 char* sock_name;
02157 int port_no;
02158 int sock_type;
02159 int s;
02160 struct binrpc_cmd cmd;
02161 int rec;
02162 struct id_list* sock_id;
02163 char* format;
02164 int interactive;
02165 char* line;
02166 char* l;
02167
02168 quit=0;
02169 format=0;
02170 line=0;
02171 interactive=0;
02172 rec=1;
02173 s=-1;
02174 sock_name=0;
02175 port_no=0;
02176 sock_type=UNIXS_SOCK;
02177 opterr=0;
02178 while((c=getopt(argc, argv, "UVhs:D:R:vf:"))!=-1){
02179 switch(c){
02180 case 'V':
02181 printf("version: %s\n", version);
02182 printf("%s\n", id);
02183 printf("%s compiled on %s \n", __FILE__,
02184 compiled);
02185 exit(0);
02186 break;
02187 case 'h':
02188 printf("version: %s\n", version);
02189 printf("%s", help_msg);
02190 exit(0);
02191 break;
02192 case 's':
02193 sock_name=optarg;
02194 break;
02195 case 'R':
02196 reply_socket=optarg;
02197 break;
02198 case 'D':
02199 sock_dir=optarg;
02200 break;
02201 case 'U':
02202 sock_type=UDP_SOCK;
02203 break;
02204 case 'v':
02205 verbose++;
02206 break;
02207 case 'f':
02208 format=str_escape(optarg);
02209 if (format==0){
02210 fprintf(stderr, "ERROR: memory allocation failure\n");
02211 goto error;
02212 }
02213 break;
02214 case '?':
02215 if (isprint(optopt))
02216 fprintf(stderr, "Unknown option `-%c'.\n", optopt);
02217 else
02218 fprintf(stderr,
02219 "Unknown option character `\\x%x'.\n",
02220 optopt);
02221 goto error;
02222 case ':':
02223 fprintf(stderr,
02224 "Option `-%c' requires an argument.\n",
02225 optopt);
02226 goto error;
02227 default:
02228 abort();
02229 }
02230 }
02231 if (sock_name==0){
02232 sock_name=DEFAULT_CTL_SOCKET;
02233 }
02234
02235
02236 srand(getpid()+time(0));
02237
02238 if (sock_name==0){
02239 fprintf(stderr, "ERROR: no ser address specified\n");
02240 goto error;
02241 }
02242 sock_id=parse_listen_id(sock_name, strlen(sock_name), sock_type);
02243 if (sock_id==0){
02244 fprintf(stderr, "ERROR: error parsing ser adress %s\n", sock_name);
02245 goto error;
02246 }
02247
02248 switch(sock_id->proto){
02249 case UDP_SOCK:
02250 case TCP_SOCK:
02251 if (sock_id->port==0){
02252 sock_id->port=DEFAULT_CTL_PORT;
02253
02254
02255
02256
02257
02258 }
02259 if ((s=connect_tcpudp_socket(sock_id->name, sock_id->port,
02260 (sock_id->proto==UDP_SOCK)?SOCK_DGRAM:
02261 SOCK_STREAM))<0){
02262 goto error;
02263 }
02264 break;
02265 case UNIXS_SOCK:
02266 case UNIXD_SOCK:
02267 if ((s=connect_unix_sock(sock_id->name,
02268 (sock_id->proto==UNIXD_SOCK)?SOCK_DGRAM:
02269 SOCK_STREAM))<0)
02270 goto error;
02271 break;
02272 case UNKNOWN_SOCK:
02273 fprintf(stderr, "ERROR: Bad socket type for %s\n", sock_name);
02274 goto error;
02275 }
02276 free(sock_id);
02277 sock_id=0;
02278
02279 if (optind>=argc){
02280 interactive=1;
02281
02282
02283 }else{
02284 if (parse_cmd(&cmd, &argv[optind], argc-optind)<0)
02285 goto error;
02286 if (run_cmd(s, &cmd, format)<0)
02287 goto error;
02288 goto end;
02289 }
02290
02291 if (get_sercmd_list(s)==0){
02292 #ifdef USE_CFG_VARS
02293 get_cfgvars_list(s);
02294 #endif
02295 #ifdef USE_MI
02296 get_mi_list(s);
02297 #endif
02298 #ifdef USE_COUNTERS
02299 get_counters_list(s);
02300 #endif
02301 }
02302
02303 printf("%s %s\n", NAME, VERSION);
02304 printf("%s\n", COPYRIGHT);
02305 printf("%s\n", DISCLAIMER);
02306 #ifdef USE_READLINE
02307
02308
02309
02310 rl_readline_name=NAME;
02311 rl_completion_entry_function=sercmd_generator;
02312 rl_attempted_completion_function=sercmd_completion;
02313
02314 while(!quit){
02315 line=readline(NAME "> ");
02316 if (line==0)
02317 break;
02318 l=trim_ws(line);
02319 if (*l){
02320 add_history(l);
02321 run_line(s, l, format);
02322 }
02323 free(line);
02324 line=0;
02325 }
02326 #else
02327 line=malloc(MAX_LINE_SIZE);
02328 if (line==0){
02329 fprintf(stderr, "memory allocation error\n");
02330 goto error;
02331 }
02332 printf(NAME "> "); fflush(stdout);
02333 while(!quit && fgets(line, MAX_LINE_SIZE, stdin)){
02334 l=trim_ws(line);
02335 if (*l){
02336 run_line(s, l, format);
02337 }
02338 printf(NAME "> "); fflush(stdout);
02339 };
02340 free(line);
02341 line=0;
02342 #endif
02343 end:
02344
02345 if (line)
02346 free(line);
02347 if (format)
02348 free(format);
02349 if (rpc_array)
02350 free_rpc_array(rpc_array, rpc_no);
02351 #ifdef USE_CFG_VARS
02352 if (cfg_grp_lst)
02353 free_cfg_grp_lst();
02354 if (cfg_vars_array){
02355 free_rpc_array(cfg_vars_array, cfg_vars_no);
02356 cfg_vars_array=0;
02357 cfg_vars_no=0;
02358 }
02359 #endif
02360 #ifdef USE_MI
02361 if (mi_cmds)
02362 free_mi_cmds();
02363 if (mi_which_array){
02364 free_rpc_array(mi_which_array, mi_which_no);
02365 mi_which_array=0;
02366 mi_which_no=0;
02367 }
02368 #endif
02369 #ifdef USE_COUNTERS
02370 if (cnt_grp_lst)
02371 free_cnt_grp_lst();
02372 if (cnt_grps_array){
02373 free_rpc_array(cnt_grps_array, cnt_grps_no);
02374 cnt_grps_array=0;
02375 cnt_grps_no=0;
02376 }
02377 #endif
02378 cleanup();
02379 exit(0);
02380 error:
02381 if (line)
02382 free(line);
02383 if (format)
02384 free(format);
02385 if (rpc_array)
02386 free_rpc_array(rpc_array, rpc_no);
02387 #ifdef USE_CFG_VARS
02388 if (cfg_grp_lst)
02389 free_cfg_grp_lst();
02390 if (cfg_vars_array){
02391 free_rpc_array(cfg_vars_array, cfg_vars_no);
02392 cfg_vars_array=0;
02393 cfg_vars_no=0;
02394 }
02395 #endif
02396 #ifdef USE_MI
02397 if (mi_cmds)
02398 free_mi_cmds();
02399 if (mi_which_array){
02400 free_rpc_array(mi_which_array, mi_which_no);
02401 mi_which_array=0;
02402 mi_which_no=0;
02403 }
02404 #endif
02405 #ifdef USE_COUNTERS
02406 if (cnt_grp_lst)
02407 free_cnt_grp_lst();
02408 if (cnt_grps_array){
02409 free_rpc_array(cnt_grps_array, cnt_grps_no);
02410 cnt_grps_array=0;
02411 cnt_grps_no=0;
02412 }
02413 #endif
02414 cleanup();
02415 exit(-1);
02416 }