kamcmd.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223
  1. /*
  2. * Copyright (C) 2006 iptelorg GmbH
  3. *
  4. * This file is part of kamcmd, a free cli tool for Kamailio SIP server.
  5. *
  6. * kamailio is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * For a license to use the kamailio software under conditions
  12. * other than those described here, or to purchase support for this
  13. * software, please contact iptel.org by e-mail at the following addresses:
  14. * [email protected]
  15. *
  16. * kamailio is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. */
  25. /*
  26. * send commands using binrpc
  27. *
  28. */
  29. #include <stdlib.h> /* exit, abort */
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. #include <errno.h>
  34. #include <ctype.h> /* isprint */
  35. #include <sys/socket.h>
  36. #include <sys/un.h> /* unix sock*/
  37. #include <netinet/in.h> /* udp sock */
  38. #include <sys/uio.h> /* writev */
  39. #include <netdb.h> /* gethostbyname */
  40. #include <fcntl.h>
  41. #include <time.h> /* time */
  42. #include <sys/time.h>
  43. #ifdef USE_READLINE
  44. #include <readline/readline.h>
  45. #include <readline/history.h>
  46. #define USE_CFG_VARS /* cfg group and vars completion */
  47. #define USE_COUNTERS /* counters/statistics completion */
  48. #endif
  49. #include "parse_listen_id.h"
  50. #include "license.h"
  51. #include "../../src/modules/ctl/ctl_defaults.h" /* default socket & port */
  52. #include "../../src/modules/ctl/binrpc.h"
  53. #include "../../src/modules/ctl/binrpc.c" /* ugly hack */
  54. #ifndef NAME
  55. #define NAME "kamcmd"
  56. #endif
  57. #ifndef VERSION
  58. #define VERSION "1.5"
  59. #endif
  60. #define IOVEC_CNT 20
  61. #define MAX_LINE_SIZE 16*1024 /* for non readline mode */
  62. #define MAX_REPLY_SIZE 128*1024
  63. #define MAX_BODY_SIZE 128*1024
  64. #define MAX_BINRPC_ARGS 256
  65. #ifndef UNIX_PATH_MAX
  66. #define UNIX_PATH_MAX 104
  67. #endif
  68. static char version[]= NAME " " VERSION;
  69. #ifdef VERSION_NODATE
  70. static char compiled[] = "";
  71. #else
  72. #ifdef VERSION_DATE
  73. static char compiled[]= VERSION_DATE;
  74. #else
  75. static char compiled[]= __TIME__ " " __DATE__;
  76. #endif
  77. #endif
  78. static char help_msg[]="\
  79. Usage: " NAME " [options][-s address] [ cmd ]\n\
  80. Options:\n\
  81. -s address unix socket name or host name to send the commands on\n\
  82. -R name force reply socket name, for the unix datagram socket mode\n\
  83. -D dir create the reply socket in the directory <dir> if no reply \n\
  84. socket is forced (-R) and a unix datagram socket is selected\n\
  85. as the transport\n\
  86. -f format print the result using format. Format is a string containing\n\
  87. %v at the places where values read from the reply should be\n\
  88. substituted. To print '%v', escape it using '%': %%v.\n\
  89. -v Verbose \n\
  90. -V Version number\n\
  91. -h This help message\n\
  92. address:\n\
  93. [proto:]name[:port] where proto is one of tcp, udp, unixs or unixd\n\
  94. e.g.: tcp:localhost:2048 , unixs:/tmp/kamailio_ctl\n\
  95. cmd:\n\
  96. method [arg1 [arg2...]]\n\
  97. arg:\n\
  98. string or number; to force a number to be interpreted as string \n\
  99. prefix it by \"s:\", e.g. s:1\n\
  100. Examples:\n\
  101. " NAME " -s unixs:/tmp/" NAME "_ctl system.listMethods\n\
  102. " NAME " -f \"pid: %v desc: %v\\n\" -s udp:localhost:2047 core.ps \n\
  103. " NAME " ps # uses default ctl socket \n\
  104. " NAME " # enters interactive mode on the default socket \n\
  105. " NAME " -s tcp:localhost # interactive mode, default port \n\
  106. ";
  107. int verbose=0;
  108. char* reply_socket=0; /* unix datagram reply socket name */
  109. char* sock_dir=0; /* same as above, but only the directory */
  110. char* unix_socket=0;
  111. struct sockaddr_un mysun;
  112. int quit; /* used only in interactive mode */
  113. struct binrpc_val* rpc_array;
  114. int rpc_no=0;
  115. #ifdef USE_CFG_VARS
  116. struct binrpc_val* cfg_vars_array;
  117. int cfg_vars_no;
  118. struct cfg_var_grp{
  119. struct cfg_var_grp* next;
  120. str grp_name; /**< group name */
  121. str* var_names; /**< str array, null terminated */
  122. int var_no;
  123. };
  124. struct cfg_var_grp* cfg_grp_lst; /** cfg groups list, allong with var names*/
  125. struct cfg_var_grp* crt_cfg_grp;
  126. #endif /* USE_CFG_VARS */
  127. #ifdef USE_COUNTERS
  128. struct binrpc_val* cnt_grps_array; /* response array */
  129. int cnt_grps_no; /* number of response records */
  130. struct cnt_var_grp {
  131. struct cnt_var_grp * next;
  132. str grp_name;
  133. str* var_names; /**< str array (null terminated strings)*/
  134. int var_no;
  135. struct binrpc_val* cnt_vars_array; /* var_name will point here */
  136. int cnt_vars_no; /* cnt_vars_array size (no. of response records) */
  137. };
  138. struct cnt_var_grp* cnt_grp_lst; /* counters groups list, allong with vars */
  139. struct cnt_var_grp* crt_cnt_grp;
  140. #endif /* USE_COUNTERS */
  141. #define IOV_SET(vect, str) \
  142. do{\
  143. (vect).iov_base=(str); \
  144. (vect).iov_len=strlen((str)); \
  145. }while(0)
  146. #define INT2STR_MAX_LEN (19+1+1) /* 2^64~= 16*10^18 => 19+1 digits + \0 */
  147. /* returns a pointer to a static buffer containing l in asciiz & sets len */
  148. static inline char* int2str(unsigned int l, int* len)
  149. {
  150. static char r[INT2STR_MAX_LEN];
  151. int i;
  152. i=INT2STR_MAX_LEN-2;
  153. r[INT2STR_MAX_LEN-1]=0; /* null terminate */
  154. do{
  155. r[i]=l%10+'0';
  156. i--;
  157. l/=10;
  158. }while(l && (i>=0));
  159. if (l && (i<0)){
  160. fprintf(stderr, "BUG: int2str: overflow\n");
  161. }
  162. if (len) *len=(INT2STR_MAX_LEN-2)-i;
  163. return &r[i+1];
  164. }
  165. static char* trim_ws(char* l)
  166. {
  167. char* ret;
  168. for(;*l && ((*l==' ')||(*l=='\t')||(*l=='\n')||(*l=='\r')); l++);
  169. ret=l;
  170. if (*ret==0) return ret;
  171. for(l=l+strlen(l)-1; (l>ret) &&
  172. ((*l==' ')||(*l=='\t')||(*l=='\n')||(*l=='\r')); l--);
  173. *(l+1)=0;
  174. return ret;
  175. }
  176. int gen_cookie()
  177. {
  178. return rand();
  179. }
  180. struct binrpc_cmd{
  181. char* method;
  182. int argc;
  183. struct binrpc_val argv[MAX_BINRPC_ARGS];
  184. };
  185. struct cmd_alias{
  186. char* name;
  187. char* method;
  188. char* format; /* reply print format */
  189. };
  190. struct kamcmd_builtin{
  191. char* name;
  192. int (*f)(int, struct binrpc_cmd*);
  193. char* doc;
  194. };
  195. static int kamcmd_help(int s, struct binrpc_cmd* cmd);
  196. static int kamcmd_ver(int s, struct binrpc_cmd* cmd);
  197. static int kamcmd_quit(int s, struct binrpc_cmd* cmd);
  198. static int kamcmd_warranty(int s, struct binrpc_cmd* cmd);
  199. static struct cmd_alias cmd_aliases[]={
  200. { "ps", "core.ps", "%v\t%v\n" },
  201. { "psx", "core.psx", 0 },
  202. { "list", "system.listMethods", 0 },
  203. { "ls", "system.listMethods", 0 },
  204. { "ver", "core.version", 0 },
  205. { "version", "core.version", 0 },
  206. { "who", "ctl.who", "[%v] %v: %v %v -> %v %v\n"},
  207. { "listen", "ctl.listen", "[%v] %v: %v %v\n"},
  208. { "dns_mem_info", "dns.mem_info", "%v / %v\n"},
  209. { "dns_debug", "dns.debug",
  210. "%v (%v): size=%v ref=%v expire=%vs last=%vs ago f=%v\n"},
  211. { "dns_debug_all", "dns.debug_all",
  212. "%v (%v) [%v]: size=%v ref=%v expire=%vs last=%vs ago f=%v\n"
  213. "\t\t%v:%v expire=%vs f=%v\n"},
  214. { "dst_blacklist_mem_info", "dst_blacklist.mem_info", "%v / %v\n"},
  215. { "dst_blacklist_debug", "dst_blacklist.debug",
  216. "%v:%v:%v expire:%v flags: %v\n"},
  217. {0,0,0}
  218. };
  219. static struct kamcmd_builtin builtins[]={
  220. { "?", kamcmd_help, "help"},
  221. { "help", kamcmd_help, "displays help for a command"},
  222. { "version", kamcmd_ver, "displays " NAME "version"},
  223. { "quit", kamcmd_quit, "exits " NAME },
  224. { "exit", kamcmd_quit, "exits " NAME },
  225. { "warranty", kamcmd_warranty, "displays " NAME "'s warranty info"},
  226. { "license", kamcmd_warranty, "displays " NAME "'s license"},
  227. {0,0}
  228. };
  229. #ifdef USE_READLINE
  230. enum complete_states {
  231. COMPLETE_INIT,
  232. COMPLETE_CMD_NAME,
  233. #ifdef USE_CFG_VARS
  234. COMPLETE_CFG_GRP,
  235. COMPLETE_CFG_VAR,
  236. #endif /* USE_CFG_VARS */
  237. #ifdef USE_COUNTERS
  238. COMPLETE_CNT_GRP,
  239. COMPLETE_CNT_VAR,
  240. #endif /* USE_COUNTERS */
  241. COMPLETE_NOTHING
  242. };
  243. /* instead of rl_attempted_completion_over which is not present in
  244. some readline emulations, use attempted_completion_state */
  245. static enum complete_states attempted_completion_state;
  246. static int crt_param_no;
  247. /* commands for which we complete the params to other method names */
  248. char* complete_params_methods[]={
  249. "?",
  250. "h",
  251. "help",
  252. "system.methodSignature",
  253. "system.methodHelp",
  254. 0
  255. };
  256. #ifdef USE_CFG_VARS
  257. /* commands for which we complete the first param with a cfg var grp*/
  258. char* complete_params_cfg_var[]={
  259. "cfg.get",
  260. "cfg.help",
  261. "cfg.set_delayed_int",
  262. "cfg.set_delayed_string",
  263. "cfg.set_now_int",
  264. "cfg.set_now_string",
  265. 0
  266. };
  267. #endif /* USE_CFG_VARS */
  268. #ifdef USE_COUNTERS
  269. /* commands for which we complete the first param with a counter group */
  270. char* complete_param1_counter_grp[] = {
  271. "cnt.get",
  272. "cnt.get_raw",
  273. "cnt.grp_get_all",
  274. "cnt.reset",
  275. "cnt.var_list",
  276. "cnt.help",
  277. 0
  278. };
  279. /* commands for which we completed the 2nd param with a counter name */
  280. char* complete_param2_counter_name[] = {
  281. "cnt.get",
  282. "cnt.get_raw",
  283. "cnt.reset",
  284. "cnt.help",
  285. 0
  286. };
  287. #endif /* USE_COUNTERS */
  288. #endif /* USE_READLINE */
  289. static int parse_arg(struct binrpc_val* v, char* arg)
  290. {
  291. int i;
  292. double f;
  293. char* tmp;
  294. int len;
  295. i=strtol(arg, &tmp, 10);
  296. if ((tmp==0) || (*tmp)){
  297. f=strtod(arg, &tmp);
  298. if ((tmp==0) || (*tmp)){
  299. /* not an int or a float => string */
  300. len=strlen(arg);
  301. if ((len>=2) && (arg[0]=='s') && (arg[1]==':')){
  302. tmp=&arg[2];
  303. len-=2;
  304. }else{
  305. tmp=arg;
  306. }
  307. v->type=BINRPC_T_STR;
  308. v->u.strval.s=tmp;
  309. v->u.strval.len=len;
  310. }else{ /* float */
  311. v->type=BINRPC_T_DOUBLE;
  312. v->u.fval=f;
  313. }
  314. }else{ /* int */
  315. v->type=BINRPC_T_INT;
  316. v->u.intval=i;
  317. }
  318. return 0;
  319. }
  320. static int parse_cmd(struct binrpc_cmd* cmd, char** argv, int count)
  321. {
  322. int r;
  323. cmd->method=argv[0];
  324. if ((count-1)>MAX_BINRPC_ARGS){
  325. fprintf(stderr, "ERROR: too many args %d, only %d allowed\n",
  326. count-1, MAX_BINRPC_ARGS);
  327. return -1;
  328. }
  329. for (r=1; r<count; r++){
  330. if (parse_arg(&cmd->argv[r-1], argv[r])<0)
  331. return -1;
  332. }
  333. cmd->argc=r-1;
  334. return 0;
  335. }
  336. void print_binrpc_val(struct binrpc_val* v, int ident)
  337. {
  338. int r;
  339. if ((v->type==BINRPC_T_STRUCT) && !v->u.end)
  340. ident--; /* fix to have struct beg. idented differently */
  341. for (r=0; r<ident; r++) putchar(' ');
  342. if (v->name.s){
  343. printf("%.*s: ", v->name.len, v->name.s);
  344. }
  345. switch(v->type){
  346. case BINRPC_T_INT:
  347. printf("%d", v->u.intval);
  348. break;
  349. case BINRPC_T_STR:
  350. case BINRPC_T_BYTES:
  351. printf("%.*s", v->u.strval.len, v->u.strval.s);
  352. break;
  353. case BINRPC_T_ARRAY:
  354. printf("%c", (v->u.end)?']':'[');
  355. break;
  356. case BINRPC_T_STRUCT:
  357. printf("%c", (v->u.end)?'}':'{');
  358. break;
  359. case BINRPC_T_DOUBLE:
  360. printf("%f", v->u.fval);
  361. break;
  362. default:
  363. printf("ERROR: unknown type %d\n", v->type);
  364. };
  365. }
  366. /* opens, and connects on a STREAM unix socket
  367. * returns socket fd or -1 on error */
  368. int connect_unix_sock(char* name, int type)
  369. {
  370. struct sockaddr_un ifsun;
  371. int s;
  372. int len;
  373. int ret;
  374. int retries;
  375. retries=0;
  376. s=-1;
  377. memset(&ifsun, 0, sizeof (struct sockaddr_un));
  378. len=strlen(name);
  379. if (len>UNIX_PATH_MAX){
  380. fprintf(stderr, "ERROR: connect_unix_sock: name too long "
  381. "(%d > %d): %s\n", len, UNIX_PATH_MAX, name);
  382. goto error;
  383. }
  384. ifsun.sun_family=AF_UNIX;
  385. memcpy(ifsun.sun_path, name, len);
  386. #ifdef HAVE_SOCKADDR_SA_LEN
  387. ifsun.sun_len=len;
  388. #endif
  389. s=socket(PF_UNIX, type, 0);
  390. if (s==-1){
  391. fprintf(stderr, "ERROR: connect_unix_sock: cannot create unix socket"
  392. " %s: %s [%d]\n", name, strerror(errno), errno);
  393. goto error;
  394. }
  395. if (type==SOCK_DGRAM){
  396. /* we must bind so that we can receive replies */
  397. if (reply_socket==0){
  398. if (sock_dir==0)
  399. sock_dir="/tmp";
  400. retry:
  401. ret=snprintf(mysun.sun_path, UNIX_PATH_MAX, "%s/" NAME "_%d",
  402. sock_dir, rand());
  403. if ((ret<0) ||(ret>=UNIX_PATH_MAX)){
  404. fprintf(stderr, "ERROR: buffer overflow while trying to"
  405. "generate unix datagram socket name");
  406. goto error;
  407. }
  408. }else{
  409. if (strlen(reply_socket)>UNIX_PATH_MAX){
  410. fprintf(stderr, "ERROR: buffer overflow while trying to"
  411. "use the provided unix datagram socket name (%s)",
  412. reply_socket);
  413. goto error;
  414. }
  415. strcpy(mysun.sun_path, reply_socket);
  416. }
  417. mysun.sun_family=AF_UNIX;
  418. if (bind(s, (struct sockaddr*)&mysun, sizeof(mysun))==-1){
  419. if (errno==EADDRINUSE && (reply_socket==0) && (retries < 10)){
  420. retries++;
  421. /* try another one */
  422. goto retry;
  423. }
  424. fprintf(stderr, "ERROR: could not bind the unix socket to"
  425. " %s: %s (%d)\n",
  426. mysun.sun_path, strerror(errno), errno);
  427. goto error;
  428. }
  429. unix_socket=mysun.sun_path;
  430. }
  431. if (connect(s, (struct sockaddr *)&ifsun, sizeof(ifsun))==-1){
  432. fprintf(stderr, "ERROR: connect_unix_sock: connect(%s): %s [%d]\n",
  433. name, strerror(errno), errno);
  434. goto error;
  435. }
  436. return s;
  437. error:
  438. if (s!=-1) close(s);
  439. return -1;
  440. }
  441. int connect_tcpudp_socket(char* address, int port, int type)
  442. {
  443. struct sockaddr_in addr;
  444. struct hostent* he;
  445. int sock;
  446. sock=-1;
  447. /* resolve destination */
  448. he=gethostbyname(address);
  449. if (he==0){
  450. fprintf(stderr, "ERROR: could not resolve %s\n", address);
  451. goto error;
  452. }
  453. /* open socket*/
  454. addr.sin_family=he->h_addrtype;
  455. addr.sin_port=htons(port);
  456. memcpy(&addr.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
  457. sock = socket(he->h_addrtype, type, 0);
  458. if (sock==-1){
  459. fprintf(stderr, "ERROR: socket: %s\n", strerror(errno));
  460. goto error;
  461. }
  462. if (connect(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr))!=0){
  463. fprintf(stderr, "ERROR: connect: %s\n", strerror(errno));
  464. goto error;
  465. }
  466. return sock;
  467. error:
  468. if (sock!=-1) close(sock);
  469. return -1;
  470. }
  471. static void hexdump(unsigned char* buf, int len, int ascii)
  472. {
  473. int r, i;
  474. /* dump it in hex */
  475. for (r=0; r<len; r++){
  476. if ((r) && ((r%16)==0)){
  477. if (ascii){
  478. putchar(' ');
  479. for (i=r-16; i<r; i++){
  480. if (isprint(buf[i]))
  481. putchar(buf[i]);
  482. else
  483. putchar('.');
  484. }
  485. }
  486. putchar('\n');
  487. }
  488. printf("%02x ", buf[r]);
  489. };
  490. if (ascii){
  491. for (i=r;i%16; i++)
  492. printf(" ");
  493. putchar(' ');
  494. for (i=16*(r/16); i<r; i++){
  495. if (isprint(buf[i]))
  496. putchar(buf[i]);
  497. else
  498. putchar('.');
  499. }
  500. }
  501. putchar('\n');
  502. }
  503. /* returns: -1 on error, number of bytes written on success */
  504. static int send_binrpc_cmd(int s, struct binrpc_cmd* cmd, int cookie)
  505. {
  506. struct iovec v[IOVEC_CNT];
  507. int r;
  508. unsigned char msg_body[MAX_BODY_SIZE];
  509. unsigned char msg_hdr[BINRPC_MAX_HDR_SIZE];
  510. struct binrpc_pkt body;
  511. int ret;
  512. int n;
  513. ret=binrpc_init_pkt(&body, msg_body, MAX_BODY_SIZE);
  514. if (ret<0) goto binrpc_err;
  515. ret=binrpc_addstr(&body, cmd->method, strlen(cmd->method));
  516. if (ret<0) goto binrpc_err;
  517. for (r=0; r<cmd->argc; r++){
  518. switch(cmd->argv[r].type){
  519. case BINRPC_T_STR:
  520. ret=binrpc_addstr(&body, cmd->argv[r].u.strval.s,
  521. cmd->argv[r].u.strval.len);
  522. break;
  523. case BINRPC_T_INT:
  524. ret=binrpc_addint(&body, cmd->argv[r].u.intval);
  525. break;
  526. case BINRPC_T_DOUBLE:
  527. ret=binrpc_adddouble(&body, cmd->argv[r].u.fval);
  528. break;
  529. default:
  530. fprintf(stderr, "ERROR: unsupported type %d\n",
  531. cmd->argv[r].type);
  532. }
  533. if (ret<0) goto binrpc_err;
  534. }
  535. ret=binrpc_build_hdr(BINRPC_REQ, binrpc_pkt_len(&body), cookie, msg_hdr,
  536. BINRPC_MAX_HDR_SIZE);
  537. if (ret<0) goto binrpc_err;
  538. v[0].iov_base=msg_hdr;
  539. v[0].iov_len=ret;
  540. v[1].iov_base=msg_body;
  541. v[1].iov_len=binrpc_pkt_len(&body);
  542. write_again:
  543. if ((n=writev(s, v, 2))<0){
  544. if (errno==EINTR)
  545. goto write_again;
  546. goto error_send;
  547. }
  548. return n;
  549. error_send:
  550. return -1;
  551. binrpc_err:
  552. return -2;
  553. }
  554. static int binrpc_errno=0;
  555. /* reads the whole reply
  556. * returns < 0 on error, reply size on success + initializes in_pkt
  557. * if ret==-2 (parse error), sets binrpc_errno to the binrpc error
  558. * error returns: -1 - read error (check errno)
  559. * -2 - binrpc parse error (chekc binrpc_errno)
  560. * -3 - cookie error (the cookied doesn't match)
  561. * -4 - message too big */
  562. static int get_reply(int s, unsigned char* reply_buf, int max_reply_size,
  563. int cookie, struct binrpc_parse_ctx* in_pkt,
  564. unsigned char** body)
  565. {
  566. unsigned char* crt;
  567. unsigned char* hdr_end;
  568. unsigned char* msg_end;
  569. int n;
  570. int ret;
  571. hdr_end=crt=reply_buf;
  572. msg_end=reply_buf+max_reply_size;
  573. binrpc_errno=0;
  574. do{
  575. n=read(s, crt, (int)(msg_end-crt));
  576. if (n<=0){
  577. if (errno==EINTR)
  578. continue;
  579. goto error_read;
  580. }
  581. if (verbose >= 3){
  582. /* dump it in hex */
  583. printf("received %d bytes in reply (@offset %d):\n",
  584. n, (int)(crt-reply_buf));
  585. hexdump(crt, n, 1);
  586. }
  587. crt+=n;
  588. /* parse header if not parsed yet */
  589. if (hdr_end==reply_buf){
  590. hdr_end=binrpc_parse_init(in_pkt, reply_buf, n, &ret);
  591. if (ret<0){
  592. if (ret==E_BINRPC_MORE_DATA)
  593. continue;
  594. goto error_parse;
  595. }
  596. if (verbose>1){
  597. printf("new packet: type %02x, len %d, cookie %02x\n",
  598. in_pkt->type, in_pkt->tlen, in_pkt->cookie);
  599. }
  600. if (in_pkt->cookie!=cookie){
  601. fprintf(stderr, "bad reply, cookie doesn't match: sent %02x "
  602. "and received %02x\n",
  603. cookie, in_pkt->cookie);
  604. goto error;
  605. }
  606. msg_end=hdr_end+in_pkt->tlen;
  607. if ((int)(msg_end-reply_buf)>max_reply_size) {
  608. /* reading the rest from the socket */
  609. struct timeval timeout_save;
  610. unsigned sizeoft = sizeof(timeout_save);
  611. if (getsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
  612. &timeout_save, &sizeoft)==0) {
  613. struct timeval timeout;
  614. timeout.tv_sec = 1;
  615. timeout.tv_usec = 0;
  616. if (setsockopt (s, SOL_SOCKET, SO_RCVTIMEO,
  617. (char*)&timeout,sizeof(timeout))==0) {
  618. while(read(s, reply_buf, max_reply_size)>0);
  619. setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
  620. (char*)&timeout_save,sizeof(timeout_save));
  621. }
  622. }
  623. goto error_toolong;
  624. }
  625. }
  626. }while(crt<msg_end);
  627. *body=hdr_end;
  628. return (int)(msg_end-reply_buf);
  629. error_read:
  630. return -1;
  631. error_parse:
  632. binrpc_errno=ret;
  633. return -2;
  634. error:
  635. return -3;
  636. error_toolong:
  637. return -4;
  638. }
  639. /* returns a malloced copy of str, with all the escapes ('\') resolved */
  640. static char* str_escape(char* str)
  641. {
  642. char* n;
  643. char* ret;
  644. ret=n=malloc(strlen(str)+1);
  645. if (n==0)
  646. goto end;
  647. for(;*str;str++){
  648. *n=*str;
  649. if (*str=='\\'){
  650. switch(*(str+1)){
  651. case 'n':
  652. *n='\n';
  653. str++;
  654. break;
  655. case 'r':
  656. *n='\r';
  657. str++;
  658. break;
  659. case 't':
  660. *n='\t';
  661. str++;
  662. break;
  663. case '\\':
  664. str++;
  665. break;
  666. }
  667. }
  668. n++;
  669. }
  670. *n=*str; /* terminating 0 */
  671. end:
  672. return ret;
  673. }
  674. /* parses strings like "bla bla %v 10%% %v\n test=%v",
  675. * and stops at each %v, returning a pointer after the %v, setting *size
  676. * to the string length (not including %v) and *type to the corresponding
  677. * BINRPC type (for now only BINRPC_T_ALL).
  678. * To escape a '%', use "%%", and check for type==-1 (which means skip an call
  679. * again parse_fmt).
  680. * Usage:
  681. * n="test: %v,%v,%v\n";
  682. * while(*n){
  683. * s=n;
  684. * n=parse_fmt(n, &type, &size);
  685. * printf("%.*s", size, s);
  686. * if (type==-1)
  687. * continue;
  688. * else
  689. * printf("now we should get & print an object of type %d\n", type)
  690. * }
  691. */
  692. static char* parse_fmt(char* fmt, int* type, int* size)
  693. {
  694. char* s;
  695. s=fmt;
  696. do{
  697. for(;*fmt && *fmt!='%'; fmt++);
  698. if (*fmt=='%'){
  699. switch(*(fmt+1)){
  700. case 'v':
  701. *type=BINRPC_T_ALL;
  702. *size=(int)(fmt-s);
  703. return (fmt+2);
  704. break;
  705. case '%':
  706. /* escaped % */
  707. *size=(int)(fmt-s)+1;
  708. *type=-1; /* skip */
  709. return (fmt+2);
  710. break;
  711. }
  712. }
  713. }while(*fmt);
  714. *type=-1; /* no value */
  715. *size=(fmt-s);
  716. return fmt;
  717. }
  718. static int print_body(struct binrpc_parse_ctx* in_pkt,
  719. unsigned char* body, int size, char* fmt)
  720. {
  721. unsigned char* p;
  722. unsigned char* end;
  723. struct binrpc_val val;
  724. int ret;
  725. int rec;
  726. char *f;
  727. char* s;
  728. int f_size;
  729. int fmt_has_values;
  730. p=body;
  731. end=p+size;
  732. rec=0;
  733. f=fmt;
  734. fmt_has_values=0;
  735. /* read body */
  736. while(p<end){
  737. if (f){
  738. do{
  739. if (*f==0)
  740. f=fmt; /* reset */
  741. s=f;
  742. f=parse_fmt(f, &val.type, &f_size);
  743. printf("%.*s", f_size, s);
  744. if (val.type!=-1){
  745. fmt_has_values=1;
  746. goto read_value;
  747. }
  748. }while(*f || fmt_has_values);
  749. val.type=BINRPC_T_ALL;
  750. }else{
  751. val.type=BINRPC_T_ALL;
  752. }
  753. read_value:
  754. val.name.s=0;
  755. val.name.len=0;
  756. p=binrpc_read_record(in_pkt, p, end, &val, 1, &ret);
  757. if (ret<0){
  758. if (fmt)
  759. putchar('\n');
  760. /*if (ret==E_BINRPC_MORE_DATA)
  761. goto error_read_again;*/
  762. if (ret==E_BINRPC_EOP){
  763. printf("end of message detected\n");
  764. break;
  765. }
  766. fprintf(stderr, "ERROR:: while parsing the record %d,"
  767. " @%d: %02x : %s\n", rec,
  768. in_pkt->offset, *p, binrpc_error(ret));
  769. goto error;
  770. }
  771. rec++;
  772. if (fmt){
  773. print_binrpc_val(&val, 0);
  774. }else{
  775. print_binrpc_val(&val, in_pkt->in_struct+in_pkt->in_array);
  776. putchar('\n');
  777. }
  778. }
  779. if (fmt && *f){
  780. /* print the rest, with empty values */
  781. while(*f){
  782. s=f;
  783. f=parse_fmt(f, &val.type, &f_size);
  784. printf("%.*s", f_size, s);
  785. }
  786. }
  787. return 0;
  788. error:
  789. return -1;
  790. /*error_read_again:
  791. fprintf(stderr, "ERROR: more data needed\n");
  792. return -2;
  793. */
  794. }
  795. static int print_fault(struct binrpc_parse_ctx* in_pkt,
  796. unsigned char* body, int size)
  797. {
  798. printf("error: ");
  799. return print_body(in_pkt, body, size, "%v - %v\n");
  800. }
  801. static int run_binrpc_cmd(int s, struct binrpc_cmd * cmd, char* fmt)
  802. {
  803. int cookie;
  804. unsigned char reply_buf[MAX_REPLY_SIZE];
  805. unsigned char* msg_body;
  806. struct binrpc_parse_ctx in_pkt;
  807. int ret;
  808. cookie=gen_cookie();
  809. if ((ret=send_binrpc_cmd(s, cmd, cookie))<0){
  810. if (ret==-1) goto error_send;
  811. else goto binrpc_err;
  812. }
  813. /* read reply */
  814. memset(&in_pkt, 0, sizeof(in_pkt));
  815. if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
  816. &msg_body))<0){
  817. switch(ret){
  818. case -1:
  819. goto error_read;
  820. case -2:
  821. goto error_parse;
  822. case -3:
  823. goto error_cookie;
  824. case -4:
  825. goto error_toobig;
  826. }
  827. goto error;
  828. }
  829. switch(in_pkt.type){
  830. case BINRPC_FAULT:
  831. if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
  832. goto error;
  833. }
  834. break;
  835. case BINRPC_REPL:
  836. if (print_body(&in_pkt, msg_body, in_pkt.tlen, fmt)<0){
  837. goto error;
  838. }
  839. break;
  840. default:
  841. fprintf(stderr, "ERROR: not a reply\n");
  842. goto error;
  843. }
  844. if (verbose) printf(".\n");
  845. /* normal exit */
  846. return 0;
  847. binrpc_err:
  848. fprintf(stderr, "ERROR while building the packet: %s\n",
  849. binrpc_error(ret));
  850. goto error;
  851. error_parse:
  852. fprintf(stderr, "ERROR while parsing the reply: %s\n",
  853. binrpc_error(binrpc_errno));
  854. goto error;
  855. error_cookie:
  856. fprintf(stderr, "ERROR: cookie does not match\n");
  857. goto error;
  858. error_toobig:
  859. fprintf(stderr, "ERROR: reply too big\n");
  860. goto error;
  861. error_send:
  862. fprintf(stderr, "ERROR: send packet failed: %s (%d)\n",
  863. strerror(errno), errno);
  864. goto error;
  865. error_read:
  866. fprintf(stderr, "ERROR: read reply failed: %s (%d)\n",
  867. strerror(errno), errno);
  868. goto error;
  869. error:
  870. return -1;
  871. }
  872. static int parse_line(struct binrpc_cmd* cmd, char* line)
  873. {
  874. char* p;
  875. int count;
  876. cmd->method=strtok(line, " \t");
  877. if (cmd->method==0)
  878. goto error_no_method;
  879. count=0;
  880. for(p=strtok(0, " \t"); p; p=strtok(0, " \t")){
  881. if (count>=MAX_BINRPC_ARGS)
  882. goto error_too_many;
  883. if (parse_arg(&cmd->argv[count], p)<0){
  884. goto error_arg;
  885. }
  886. count++;
  887. }
  888. cmd->argc=count;
  889. return 0;
  890. error_no_method:
  891. printf( "ERROR: no method name\n");
  892. return -1;
  893. error_too_many:
  894. printf("ERROR: too many arguments (%d), no more than %d allowed\n",
  895. count, MAX_BINRPC_ARGS);
  896. return -1;
  897. error_arg:
  898. printf("ERROR: bad argument %d: %s\n", count+1, p);
  899. return -1;
  900. }
  901. /* resolves builtin aliases */
  902. static void fix_cmd(struct binrpc_cmd* cmd, char** format)
  903. {
  904. int r;
  905. for (r=0; cmd_aliases[r].name; r++){
  906. if (strcmp(cmd_aliases[r].name, cmd->method)==0){
  907. cmd->method=cmd_aliases[r].method;
  908. if (*format==0)
  909. *format=cmd_aliases[r].format;
  910. break;
  911. }
  912. }
  913. }
  914. /* intercept builtin commands, returns 1 if intercepted, 0 if not, <0 on error
  915. */
  916. static int run_builtins(int s, struct binrpc_cmd* cmd)
  917. {
  918. int r;
  919. int ret;
  920. for (r=0; builtins[r].name; r++){
  921. if (strcmp(builtins[r].name, cmd->method)==0){
  922. ret=builtins[r].f(s, cmd);
  923. return (ret<0)?ret:1;
  924. }
  925. }
  926. return 0;
  927. }
  928. /* runs command from cmd */
  929. inline static int run_cmd(int s, struct binrpc_cmd* cmd, char* format)
  930. {
  931. int ret;
  932. char* fmt;
  933. fmt=format;
  934. fix_cmd(cmd, &fmt);
  935. if (!(ret=run_builtins(s, cmd))){
  936. ret=run_binrpc_cmd(s, cmd, fmt);
  937. }
  938. return (ret>0)?0:ret;
  939. }
  940. /* runs a command represented in line */
  941. inline static int run_line(int s, char* l, char* format)
  942. {
  943. struct binrpc_cmd cmd;
  944. int ret;
  945. if ((ret=parse_line(&cmd, l))==0){
  946. return run_cmd(s, &cmd, format);
  947. }
  948. return ret;
  949. }
  950. static void free_rpc_array(struct binrpc_val* a, int size)
  951. {
  952. int r;
  953. for (r=0; r<size; r++){
  954. if (a[r].name.s)
  955. free(a[r].name.s);
  956. if ((a[r].type==BINRPC_T_STR || a[r].type==BINRPC_T_BYTES) &&
  957. a[r].u.strval.s){
  958. free(a[r].u.strval.s);
  959. }
  960. }
  961. free(a);
  962. }
  963. /* parse the body into a malloc allocated, binrpc_val array */
  964. static struct binrpc_val* parse_reply_body(int* records,
  965. struct binrpc_parse_ctx* in_pkt,
  966. unsigned char* body, int size)
  967. {
  968. struct binrpc_val* a;
  969. struct binrpc_val* t;
  970. unsigned char* p;
  971. unsigned char* end;
  972. struct binrpc_val val;
  973. int ret;
  974. int rec;
  975. rec=0;
  976. if (*records==0){
  977. *records=100; /* start with a reasonable size */
  978. };
  979. a=malloc(*records*sizeof(struct binrpc_val));
  980. if (a==0)
  981. goto error_mem;
  982. p=body;
  983. end=p+size;
  984. /* read body */
  985. while(p<end){
  986. val.type=BINRPC_T_ALL;
  987. val.name.s=0;
  988. val.name.len=0;
  989. p=binrpc_read_record(in_pkt, p, end, &val, 1, &ret);
  990. if (ret<0){
  991. if (ret==E_BINRPC_EOP){
  992. printf("end of message detected\n");
  993. break;
  994. }
  995. fprintf(stderr, "ERROR: while parsing the record %d,"
  996. " @%d: %02x : %s\n", rec,
  997. in_pkt->offset, *p, binrpc_error(ret));
  998. goto error;
  999. }
  1000. if (rec>=*records){
  1001. t=realloc(a, *records*sizeof(struct binrpc_val)*2);
  1002. if (t==0)
  1003. goto error_mem;
  1004. a=t;
  1005. *records*=2;
  1006. }
  1007. a[rec]=val;
  1008. if (val.name.s){
  1009. if ((a[rec].name.s=malloc(val.name.len+1))==0)
  1010. goto error_mem;
  1011. memcpy(a[rec].name.s, val.name.s, val.name.len);
  1012. a[rec].name.s[val.name.len+1]=0; /* 0-term */
  1013. }
  1014. if (val.u.strval.s){
  1015. if (val.type==BINRPC_T_STR){
  1016. if ((a[rec].u.strval.s=malloc(val.u.strval.len+1))==0)
  1017. goto error_mem;
  1018. memcpy(a[rec].u.strval.s, val.u.strval.s, val.u.strval.len);
  1019. a[rec].u.strval.s[val.u.strval.len]=0; /* 0-term */
  1020. }else if (val.type==BINRPC_T_BYTES){
  1021. if ((a[rec].u.strval.s=malloc(val.u.strval.len))==0)
  1022. goto error_mem;
  1023. memcpy(a[rec].u.strval.s, val.u.strval.s, val.u.strval.len);
  1024. }
  1025. }
  1026. rec++;
  1027. }
  1028. if (rec && (rec<*records)){
  1029. a=realloc(a, rec*sizeof(struct binrpc_val));
  1030. }
  1031. *records=rec;
  1032. return a;
  1033. error_mem:
  1034. fprintf(stderr, "ERROR: parse_reply_body: out of memory\n");
  1035. error:
  1036. if (a){
  1037. free_rpc_array(a, rec);
  1038. }
  1039. *records=0;
  1040. return 0;
  1041. }
  1042. static int get_kamcmd_list(int s)
  1043. {
  1044. struct binrpc_cmd cmd;
  1045. int cookie;
  1046. unsigned char reply_buf[MAX_REPLY_SIZE];
  1047. unsigned char* msg_body;
  1048. struct binrpc_parse_ctx in_pkt;
  1049. int ret;
  1050. cmd.method="system.listMethods";
  1051. cmd.argc=0;
  1052. cookie=gen_cookie();
  1053. if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
  1054. if (ret==-1) goto error_send;
  1055. else goto binrpc_err;
  1056. }
  1057. /* read reply */
  1058. memset(&in_pkt, 0, sizeof(in_pkt));
  1059. if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
  1060. &msg_body))<0){
  1061. goto error;
  1062. }
  1063. switch(in_pkt.type){
  1064. case BINRPC_FAULT:
  1065. if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
  1066. goto error;
  1067. }
  1068. break;
  1069. case BINRPC_REPL:
  1070. rpc_no=100; /* default cmd list */
  1071. if ((rpc_array=parse_reply_body(&rpc_no, &in_pkt, msg_body,
  1072. in_pkt.tlen))==0)
  1073. goto error;
  1074. break;
  1075. default:
  1076. fprintf(stderr, "ERROR: not a reply\n");
  1077. goto error;
  1078. }
  1079. return 0;
  1080. binrpc_err:
  1081. error_send:
  1082. error:
  1083. return -1;
  1084. }
  1085. #if defined(USE_CFG_VARS) || defined (USE_COUNTERS)
  1086. /** check if cmd is a rpc command.
  1087. * Quick check (using the internal rpc_array) if cmd is a valid rpc command.
  1088. * @param cmd - null terminated ascii string
  1089. * @return 1 on success, 0 on failure.
  1090. */
  1091. static int is_rpc_cmd(char* cmd)
  1092. {
  1093. int r;
  1094. int cmd_len;
  1095. cmd_len=strlen(cmd);
  1096. for (r=0; r<rpc_no; r++){
  1097. if ((rpc_array[r].type==BINRPC_T_STR) &&
  1098. (rpc_array[r].u.strval.len==cmd_len) &&
  1099. (strncmp(cmd, rpc_array[r].u.strval.s, cmd_len)==0))
  1100. return 1;
  1101. }
  1102. return 0;
  1103. }
  1104. #endif /* USE_CFG_VARS */
  1105. #ifdef USE_CFG_VARS
  1106. /* retrieve the cfg vars and group list */
  1107. static int get_cfgvars_list(int s)
  1108. {
  1109. struct binrpc_cmd cmd;
  1110. int cookie;
  1111. unsigned char reply_buf[MAX_REPLY_SIZE];
  1112. unsigned char* msg_body;
  1113. struct binrpc_parse_ctx in_pkt;
  1114. struct cfg_var_grp* grp;
  1115. struct cfg_var_grp* last_grp;
  1116. char* p;
  1117. char* end;
  1118. str grp_name;
  1119. str var_name;
  1120. int r;
  1121. int ret;
  1122. cmd.method="cfg.list";
  1123. cmd.argc=0;
  1124. if (!is_rpc_cmd(cmd.method)) goto error;
  1125. cookie=gen_cookie();
  1126. if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
  1127. if (ret==-1) goto error_send;
  1128. else goto binrpc_err;
  1129. }
  1130. /* read reply */
  1131. memset(&in_pkt, 0, sizeof(in_pkt));
  1132. if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
  1133. &msg_body))<0){
  1134. goto error;
  1135. }
  1136. switch(in_pkt.type){
  1137. case BINRPC_FAULT:
  1138. if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
  1139. goto error;
  1140. }
  1141. break;
  1142. case BINRPC_REPL:
  1143. cfg_vars_no=100; /* default cmd list */
  1144. if ((cfg_vars_array=parse_reply_body(&cfg_vars_no, &in_pkt,
  1145. msg_body, in_pkt.tlen))==0)
  1146. goto error;
  1147. break;
  1148. default:
  1149. fprintf(stderr, "ERROR: not a reply\n");
  1150. goto error;
  1151. }
  1152. /* get the config groups */
  1153. last_grp=0;
  1154. for (r=0; r<cfg_vars_no; r++){
  1155. grp_name.s=0; grp_name.len=0;
  1156. if (cfg_vars_array[r].type!=BINRPC_T_STR)
  1157. continue;
  1158. grp_name.s=cfg_vars_array[r].u.strval.s;
  1159. end=cfg_vars_array[r].u.strval.len+grp_name.s;
  1160. /* parse <grp>: <var_name>*/
  1161. for (p=grp_name.s; p<end; p++){
  1162. if (*p==':'){
  1163. grp_name.len=(int)(long)(p-grp_name.s);
  1164. break;
  1165. }
  1166. }
  1167. for (grp=cfg_grp_lst; grp; grp=grp->next){
  1168. if (grp->grp_name.len==grp_name.len &&
  1169. memcmp(grp->grp_name.s, grp_name.s, grp_name.len)==0){
  1170. break; /* found */
  1171. }
  1172. }
  1173. if (grp==0){
  1174. /* not found => create a new one */
  1175. grp=malloc(sizeof(*grp));
  1176. if (grp==0) goto error_mem;
  1177. memset(grp, 0, sizeof(*grp));
  1178. grp->grp_name=grp_name;
  1179. if (last_grp){
  1180. last_grp->next=grp;
  1181. last_grp=grp;
  1182. }else{
  1183. cfg_grp_lst=grp;
  1184. last_grp=cfg_grp_lst;
  1185. }
  1186. }
  1187. grp->var_no++;
  1188. }
  1189. /* alloc the var arrays per group */
  1190. for (grp=cfg_grp_lst; grp; grp=grp->next){
  1191. grp->var_names=malloc(sizeof(str)*grp->var_no);
  1192. if (grp->var_names==0) goto error_mem;
  1193. memset(grp->var_names, 0, sizeof(str)*grp->var_no);
  1194. grp->var_no=0;
  1195. }
  1196. /* reparse to get the var names per group */
  1197. for (r=0; r<cfg_vars_no; r++){
  1198. grp_name.s=0; grp_name.len=0;
  1199. var_name.s=0; var_name.len=0;
  1200. if (cfg_vars_array[r].type!=BINRPC_T_STR)
  1201. continue;
  1202. grp_name.s=cfg_vars_array[r].u.strval.s;
  1203. end=cfg_vars_array[r].u.strval.len+grp_name.s;
  1204. /* parse <grp>: <var_name>*/
  1205. for (p=grp_name.s; p<end; p++){
  1206. if (*p==':'){
  1207. grp_name.len=(int)(long)(p-grp_name.s);
  1208. p++;
  1209. for (; p<end && *p==' '; p++);
  1210. var_name.s=p;
  1211. var_name.len=(int)(long)(end-p);
  1212. if (var_name.len==0) break;
  1213. for (grp=cfg_grp_lst; grp; grp=grp->next){
  1214. if (grp->grp_name.len==grp_name.len &&
  1215. memcmp(grp->grp_name.s, grp_name.s, grp_name.len)==0){
  1216. /* add var */
  1217. grp->var_names[grp->var_no]=var_name;
  1218. grp->var_no++;
  1219. }
  1220. }
  1221. break;
  1222. }
  1223. }
  1224. }
  1225. return 0;
  1226. binrpc_err:
  1227. error_send:
  1228. error:
  1229. error_mem:
  1230. return -1;
  1231. }
  1232. void free_cfg_grp_lst()
  1233. {
  1234. struct cfg_var_grp* grp;
  1235. struct cfg_var_grp* last;
  1236. grp=cfg_grp_lst;
  1237. while(grp){
  1238. last=grp;
  1239. grp=grp->next;
  1240. free(last);
  1241. }
  1242. cfg_grp_lst=0;
  1243. }
  1244. #endif /* USE_CFG_VARS */
  1245. #ifdef USE_COUNTERS
  1246. /* retrieve the counters names and group list */
  1247. static int get_counters_list(int s)
  1248. {
  1249. struct binrpc_cmd cmd;
  1250. int cookie;
  1251. unsigned char reply_buf[MAX_REPLY_SIZE];
  1252. unsigned char* msg_body;
  1253. struct binrpc_parse_ctx in_pkt;
  1254. struct cnt_var_grp* grp;
  1255. struct cnt_var_grp* last_grp;
  1256. str grp_name;
  1257. str var_name;
  1258. int r;
  1259. int ret;
  1260. cmd.method="cnt.grps_list";
  1261. cmd.argc=0;
  1262. if (!is_rpc_cmd(cmd.method)) goto error;
  1263. cookie=gen_cookie();
  1264. if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
  1265. if (ret==-1) goto error_send;
  1266. else goto binrpc_err;
  1267. }
  1268. /* read reply */
  1269. memset(&in_pkt, 0, sizeof(in_pkt));
  1270. if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
  1271. &msg_body))<0){
  1272. goto error;
  1273. }
  1274. switch(in_pkt.type){
  1275. case BINRPC_FAULT:
  1276. if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
  1277. goto error;
  1278. }
  1279. break;
  1280. case BINRPC_REPL:
  1281. cnt_grps_no=20; /* default counter list */
  1282. if ((cnt_grps_array=parse_reply_body(&cnt_grps_no, &in_pkt,
  1283. msg_body, in_pkt.tlen))==0)
  1284. goto error;
  1285. break;
  1286. default:
  1287. fprintf(stderr, "ERROR: not a reply\n");
  1288. goto error;
  1289. }
  1290. /* get the config groups */
  1291. last_grp=0;
  1292. for (r=0; r<cnt_grps_no; r++){
  1293. grp_name.s=0; grp_name.len=0;
  1294. if (cnt_grps_array[r].type!=BINRPC_T_STR)
  1295. continue;
  1296. grp_name=cnt_grps_array[r].u.strval;
  1297. /* check for duplicates */
  1298. for (grp=cnt_grp_lst; grp; grp=grp->next){
  1299. if (grp->grp_name.len==grp_name.len &&
  1300. memcmp(grp->grp_name.s, grp_name.s, grp_name.len)==0){
  1301. break; /* found */
  1302. }
  1303. }
  1304. if (grp==0){
  1305. /* not found => create a new one */
  1306. grp=malloc(sizeof(*grp));
  1307. if (grp==0) goto error_mem;
  1308. memset(grp, 0, sizeof(*grp));
  1309. grp->grp_name=grp_name;
  1310. if (last_grp){
  1311. last_grp->next=grp;
  1312. last_grp=grp;
  1313. }else{
  1314. cnt_grp_lst=grp;
  1315. last_grp=cnt_grp_lst;
  1316. }
  1317. }
  1318. }
  1319. /* gets vars per group */
  1320. for (grp=cnt_grp_lst; grp; grp=grp->next){
  1321. cmd.method="cnt.var_list";
  1322. cmd.argv[0].type=BINRPC_T_STR;
  1323. cmd.argv[0].u.strval=grp->grp_name;
  1324. cmd.argc=1;
  1325. if (!is_rpc_cmd(cmd.method)) goto error;
  1326. cookie=gen_cookie();
  1327. if ((ret=send_binrpc_cmd(s, &cmd, cookie))<0){
  1328. if (ret==-1) goto error_send;
  1329. else goto binrpc_err;
  1330. }
  1331. /* read reply */
  1332. memset(&in_pkt, 0, sizeof(in_pkt));
  1333. if ((ret=get_reply(s, reply_buf, MAX_REPLY_SIZE, cookie, &in_pkt,
  1334. &msg_body))<0){
  1335. goto error;
  1336. }
  1337. switch(in_pkt.type){
  1338. case BINRPC_FAULT:
  1339. if (print_fault(&in_pkt, msg_body, in_pkt.tlen)<0){
  1340. goto error;
  1341. }
  1342. break;
  1343. case BINRPC_REPL:
  1344. grp->cnt_vars_no=100; /* default counter list */
  1345. if ((grp->cnt_vars_array=parse_reply_body(&grp->cnt_vars_no,
  1346. &in_pkt, msg_body,
  1347. in_pkt.tlen))==0)
  1348. goto error;
  1349. break;
  1350. default:
  1351. fprintf(stderr, "ERROR: not a reply\n");
  1352. goto error;
  1353. }
  1354. grp->var_no = 0;
  1355. grp->var_names=malloc(sizeof(str)*grp->cnt_vars_no);
  1356. if (grp->var_names==0) goto error_mem;
  1357. memset(grp->var_names, 0, sizeof(str)*grp->cnt_vars_no);
  1358. for (r=0; r<grp->cnt_vars_no; r++) {
  1359. if (grp->cnt_vars_array[r].type!=BINRPC_T_STR)
  1360. continue;
  1361. var_name=grp->cnt_vars_array[r].u.strval;
  1362. grp->var_names[grp->var_no] = var_name;
  1363. grp->var_no++;
  1364. }
  1365. }
  1366. return 0;
  1367. binrpc_err:
  1368. error_send:
  1369. error:
  1370. error_mem:
  1371. return -1;
  1372. }
  1373. void free_cnt_grp_lst()
  1374. {
  1375. struct cnt_var_grp* grp;
  1376. struct cnt_var_grp* last;
  1377. grp=cnt_grp_lst;
  1378. while(grp){
  1379. last=grp;
  1380. grp=grp->next;
  1381. if (last->cnt_vars_array)
  1382. free_rpc_array(last->cnt_vars_array, last->cnt_vars_no);
  1383. free(last);
  1384. }
  1385. cnt_grp_lst=0;
  1386. }
  1387. #endif /* USE_COUNTERS */
  1388. static void print_formatting(char* prefix, char* format, char* suffix)
  1389. {
  1390. if (format){
  1391. printf("%s", prefix);
  1392. for (;*format;format++){
  1393. switch(*format){
  1394. case '\t':
  1395. printf("\\t");
  1396. break;
  1397. case '\n':
  1398. printf("\\n");
  1399. break;
  1400. case '\r':
  1401. printf("\\r");
  1402. break;
  1403. default:
  1404. putchar(*format);
  1405. }
  1406. }
  1407. printf("%s", suffix);
  1408. }
  1409. }
  1410. static int kamcmd_help(int s, struct binrpc_cmd* cmd)
  1411. {
  1412. int r;
  1413. if (cmd->argc && (cmd->argv[0].type==BINRPC_T_STR)){
  1414. /* if it has args, try command help */
  1415. for (r=0; cmd_aliases[r].name; r++){
  1416. if (strcmp(cmd->argv[0].u.strval.s, cmd_aliases[r].name)==0){
  1417. printf("%s is an alias for %s", cmd->argv[0].u.strval.s,
  1418. cmd_aliases[r].method);
  1419. print_formatting(" with reply formatting: \"",
  1420. cmd_aliases[r].format, "\"");
  1421. putchar('\n');
  1422. return 0;
  1423. }
  1424. }
  1425. for(r=0; builtins[r].name; r++){
  1426. if (strcmp(cmd->argv[0].u.strval.s, builtins[r].name)==0){
  1427. printf("builtin command: %s\n",
  1428. builtins[r].doc?builtins[r].doc:"undocumented");
  1429. return 0;
  1430. }
  1431. }
  1432. cmd->method="system.methodHelp";
  1433. if (run_binrpc_cmd(s, cmd, 0)<0){
  1434. printf("error: no such command %s\n", cmd->argv[0].u.strval.s);
  1435. }
  1436. return 0;
  1437. }
  1438. if (rpc_no==0){
  1439. if (get_kamcmd_list(s)<0)
  1440. goto error;
  1441. }
  1442. for (r=0; r<rpc_no; r++){
  1443. if (rpc_array[r].type==BINRPC_T_STR){
  1444. printf("%s\n", rpc_array[r].u.strval.s);
  1445. }
  1446. }
  1447. for (r=0; cmd_aliases[r].name; r++){
  1448. printf("alias: %s\n", cmd_aliases[r].name);
  1449. }
  1450. for(r=0; builtins[r].name; r++){
  1451. printf("builtin: %s\n", builtins[r].name);
  1452. }
  1453. return 0;
  1454. error:
  1455. return -1;
  1456. }
  1457. static int kamcmd_ver(int s, struct binrpc_cmd* cmd)
  1458. {
  1459. printf("%s\n", version);
  1460. printf("%s compiled on %s \n", __FILE__, compiled);
  1461. #ifdef USE_READLINE
  1462. printf("interactive mode command completion support\n");
  1463. #endif
  1464. return 0;
  1465. }
  1466. static int kamcmd_quit(int s, struct binrpc_cmd* cmd)
  1467. {
  1468. quit=1;
  1469. return 0;
  1470. }
  1471. static int kamcmd_warranty(int s, struct binrpc_cmd *cmd)
  1472. {
  1473. printf("%s %s\n", NAME, VERSION);
  1474. printf("%s\n", COPYRIGHT);
  1475. printf("\n%s\n", LICENSE);
  1476. return 0;
  1477. }
  1478. #ifdef USE_READLINE
  1479. /* readline command generator */
  1480. static char* kamcmd_generator(const char* text, int state)
  1481. {
  1482. static int idx;
  1483. static int list; /* aliases, builtins, rpc_array */
  1484. static int len;
  1485. char* name;
  1486. #ifdef USE_CFG_VARS
  1487. static struct cfg_var_grp* grp;
  1488. #endif
  1489. #ifdef USE_COUNTERS
  1490. static struct cnt_var_grp* cnt_grp;
  1491. #endif
  1492. switch(attempted_completion_state){
  1493. case COMPLETE_INIT:
  1494. case COMPLETE_NOTHING:
  1495. return 0;
  1496. case COMPLETE_CMD_NAME:
  1497. if (state==0){
  1498. /* init */
  1499. idx=list=0;
  1500. len=strlen(text);
  1501. }
  1502. /* return next partial match */
  1503. switch(list){
  1504. case 0: /* aliases*/
  1505. while((name=cmd_aliases[idx].name)){
  1506. idx++;
  1507. if (strncmp(name, text, len)==0)
  1508. return strdup(name);
  1509. }
  1510. list++;
  1511. idx=0;
  1512. /* no break */
  1513. case 1: /* builtins */
  1514. while((name=builtins[idx].name)){
  1515. idx++;
  1516. if (strncmp(name, text, len)==0)
  1517. return strdup(name);
  1518. }
  1519. list++;
  1520. idx=0;
  1521. /* no break */
  1522. case 2: /* rpc_array */
  1523. while(idx < rpc_no){
  1524. if (rpc_array[idx].type==BINRPC_T_STR){
  1525. name=rpc_array[idx].u.strval.s;
  1526. idx++;
  1527. if (strncmp(name, text, len)==0)
  1528. return strdup(name);
  1529. }else{
  1530. idx++;
  1531. }
  1532. }
  1533. }
  1534. break;
  1535. #ifdef USE_CFG_VARS
  1536. case COMPLETE_CFG_GRP:
  1537. if (state==0){
  1538. /* init */
  1539. len=strlen(text);
  1540. grp=cfg_grp_lst;
  1541. }else{
  1542. grp=grp->next;
  1543. }
  1544. for(;grp; grp=grp->next){
  1545. if (len<=grp->grp_name.len &&
  1546. memcmp(text, grp->grp_name.s, len)==0) {
  1547. /* zero-term copy of the grp name */
  1548. name=malloc(grp->grp_name.len+1);
  1549. if (name){
  1550. memcpy(name, grp->grp_name.s, grp->grp_name.len);
  1551. name[grp->grp_name.len]=0;
  1552. }
  1553. return name;
  1554. }
  1555. }
  1556. break;
  1557. case COMPLETE_CFG_VAR:
  1558. if (state==0){
  1559. /* init */
  1560. len=strlen(text);
  1561. idx=0;
  1562. }
  1563. while(idx < crt_cfg_grp->var_no){
  1564. if (len<=crt_cfg_grp->var_names[idx].len &&
  1565. memcmp(text, crt_cfg_grp->var_names[idx].s, len)==0) {
  1566. /* zero-term copy of the var name */
  1567. name=malloc(crt_cfg_grp->var_names[idx].len+1);
  1568. if (name){
  1569. memcpy(name, crt_cfg_grp->var_names[idx].s,
  1570. crt_cfg_grp->var_names[idx].len);
  1571. name[crt_cfg_grp->var_names[idx].len]=0;
  1572. }
  1573. idx++;
  1574. return name;
  1575. }
  1576. idx++;
  1577. }
  1578. break;
  1579. #endif /* USE_CFG_VARS */
  1580. #ifdef USE_COUNTERS
  1581. case COMPLETE_CNT_GRP:
  1582. if (state==0){
  1583. /* init */
  1584. len=strlen(text);
  1585. cnt_grp=cnt_grp_lst;
  1586. }else{
  1587. cnt_grp=cnt_grp->next;
  1588. }
  1589. for(;cnt_grp; cnt_grp=cnt_grp->next){
  1590. if (len<=cnt_grp->grp_name.len &&
  1591. memcmp(text, cnt_grp->grp_name.s, len)==0) {
  1592. /* zero-term copy of the cnt_grp name */
  1593. name=malloc(cnt_grp->grp_name.len+1);
  1594. if (name){
  1595. memcpy(name, cnt_grp->grp_name.s,
  1596. cnt_grp->grp_name.len);
  1597. name[cnt_grp->grp_name.len]=0;
  1598. }
  1599. return name;
  1600. }
  1601. }
  1602. break;
  1603. case COMPLETE_CNT_VAR:
  1604. if (state==0){
  1605. /* init */
  1606. len=strlen(text);
  1607. idx=0;
  1608. }
  1609. while(idx < crt_cnt_grp->var_no){
  1610. if (len<=crt_cnt_grp->var_names[idx].len &&
  1611. memcmp(text, crt_cnt_grp->var_names[idx].s, len)==0) {
  1612. /* zero-term copy of the var name */
  1613. name=malloc(crt_cnt_grp->var_names[idx].len+1);
  1614. if (name){
  1615. memcpy(name, crt_cnt_grp->var_names[idx].s,
  1616. crt_cnt_grp->var_names[idx].len);
  1617. name[crt_cnt_grp->var_names[idx].len]=0;
  1618. }
  1619. idx++;
  1620. return name;
  1621. }
  1622. idx++;
  1623. }
  1624. break;
  1625. #endif /* USE_COUNTERS */
  1626. }
  1627. /* no matches */
  1628. return 0;
  1629. }
  1630. char** kamcmd_completion(const char* text, int start, int end)
  1631. {
  1632. int i, j;
  1633. int cmd_start, cmd_end, cmd_len;
  1634. int whitespace;
  1635. #ifdef USE_CFG_VARS
  1636. struct cfg_var_grp* grp;
  1637. static int grp_start;
  1638. int grp_len;
  1639. #endif /* USE_CFG_VARS */
  1640. #ifdef USE_COUNTERS
  1641. struct cnt_var_grp* cnt_grp;
  1642. static int cnt_grp_start;
  1643. int cnt_grp_len;
  1644. #endif /* USE_COUNTERS */
  1645. crt_param_no=0;
  1646. /* skip over whitespace at the beginning */
  1647. for (j=0; (j<start) && (rl_line_buffer[j]==' ' ||
  1648. rl_line_buffer[j]=='\t'); j++);
  1649. cmd_start=j;
  1650. if (start==cmd_start){
  1651. /* complete cmd name at beginning */
  1652. attempted_completion_state=COMPLETE_CMD_NAME;
  1653. #ifdef USE_CFG_VARS
  1654. grp_start=0;
  1655. #endif /* USE_CFG_VARS */
  1656. #ifdef USE_COUNTERS
  1657. cnt_grp_start=0;
  1658. #endif /* USE_COUNTERS */
  1659. }else{ /* or if this is a command for which we complete the parameters */
  1660. /* find first whitespace after command name*/
  1661. for(; (j<start) && (rl_line_buffer[j]!=' ') &&
  1662. (rl_line_buffer[j]!='\t'); j++);
  1663. cmd_end=j;
  1664. cmd_len=cmd_end-cmd_start;
  1665. /* count params before the current one */
  1666. whitespace=1;
  1667. for (; j<start; j++){
  1668. if (rl_line_buffer[j]!=' ' && rl_line_buffer[j]!='\t'){
  1669. if (whitespace) crt_param_no++;
  1670. whitespace=0;
  1671. }else
  1672. whitespace=1;
  1673. }
  1674. crt_param_no++;
  1675. if (crt_param_no==1){
  1676. for(i=0; complete_params_methods[i]; i++){
  1677. if ((cmd_len==strlen(complete_params_methods[i])) &&
  1678. (strncmp(&rl_line_buffer[cmd_start],
  1679. complete_params_methods[i],
  1680. cmd_len)==0)){
  1681. attempted_completion_state=COMPLETE_CMD_NAME;
  1682. goto end;
  1683. }
  1684. }
  1685. #ifdef USE_CFG_VARS
  1686. /* try complete_param*_cfg_grp */
  1687. for(i=0; complete_params_cfg_var[i]; i++){
  1688. if ((cmd_len==strlen(complete_params_cfg_var[i])) &&
  1689. (strncmp(&rl_line_buffer[cmd_start],
  1690. complete_params_cfg_var[i],
  1691. cmd_len)==0)){
  1692. attempted_completion_state=COMPLETE_CFG_GRP;
  1693. grp_start=start;
  1694. goto end;
  1695. }
  1696. }
  1697. #endif /* USE_CFG_VARS */
  1698. #ifdef USE_COUNTERS
  1699. /* try complete_param*_cfg_grp */
  1700. for(i=0; complete_param1_counter_grp[i]; i++){
  1701. if ((cmd_len==strlen(complete_param1_counter_grp[i])) &&
  1702. (strncmp(&rl_line_buffer[cmd_start],
  1703. complete_param1_counter_grp[i],
  1704. cmd_len)==0)){
  1705. attempted_completion_state=COMPLETE_CNT_GRP;
  1706. cnt_grp_start=start;
  1707. goto end;
  1708. }
  1709. }
  1710. #endif /* USE_COUNTERS */
  1711. }else if (crt_param_no==2){
  1712. #ifdef USE_CFG_VARS
  1713. /* see if we complete cfg. var names for this command */
  1714. for(i=0; complete_params_cfg_var[i]; i++){
  1715. if ((cmd_len==strlen(complete_params_cfg_var[i])) &&
  1716. (strncmp(&rl_line_buffer[cmd_start],
  1717. complete_params_cfg_var[i],
  1718. cmd_len)==0)){
  1719. /* get the group name: */
  1720. /* find grp_start */
  1721. for(j=cmd_end; (j<start) && ((rl_line_buffer[j]==' ') ||
  1722. (rl_line_buffer[j]=='\t')); j++);
  1723. grp_start=j;
  1724. /* find group end / grp_len*/
  1725. for(j=grp_start; (j<start) && (rl_line_buffer[j]!=' ') &&
  1726. (rl_line_buffer[j]!='\t'); j++);
  1727. grp_len=j-grp_start;
  1728. for(grp=cfg_grp_lst; grp; grp=grp->next){
  1729. if (grp_len==grp->grp_name.len &&
  1730. memcmp(&rl_line_buffer[grp_start],
  1731. grp->grp_name.s, grp_len)==0) {
  1732. attempted_completion_state=COMPLETE_CFG_VAR;
  1733. crt_cfg_grp=grp;
  1734. goto end;
  1735. }
  1736. }
  1737. }
  1738. }
  1739. #endif /* USE_CFG_VARS */
  1740. #ifdef USE_COUNTERS
  1741. /* see if we complete counter names for this command */
  1742. for(i=0; complete_param2_counter_name[i]; i++){
  1743. if ((cmd_len==strlen(complete_param2_counter_name[i])) &&
  1744. (strncmp(&rl_line_buffer[cmd_start],
  1745. complete_param2_counter_name[i],
  1746. cmd_len)==0)){
  1747. /* get the group name: */
  1748. /* find grp_start */
  1749. for(j=cmd_end; (j<start) && ((rl_line_buffer[j]==' ') ||
  1750. (rl_line_buffer[j]=='\t')); j++);
  1751. cnt_grp_start=j;
  1752. /* find group end / cnt_grp_len*/
  1753. for(j=cnt_grp_start; (j<start) &&
  1754. (rl_line_buffer[j]!=' ') &&
  1755. (rl_line_buffer[j]!='\t'); j++);
  1756. cnt_grp_len=j-cnt_grp_start;
  1757. for(cnt_grp=cnt_grp_lst; cnt_grp; cnt_grp=cnt_grp->next){
  1758. if (cnt_grp_len==cnt_grp->grp_name.len &&
  1759. memcmp(&rl_line_buffer[cnt_grp_start],
  1760. cnt_grp->grp_name.s, cnt_grp_len)==0) {
  1761. attempted_completion_state=COMPLETE_CNT_VAR;
  1762. crt_cnt_grp=cnt_grp;
  1763. goto end;
  1764. }
  1765. }
  1766. }
  1767. }
  1768. #endif /* COUNTERS */
  1769. }
  1770. attempted_completion_state=COMPLETE_NOTHING;
  1771. }
  1772. end:
  1773. return 0; /* let readline call kamcmd_generator */
  1774. }
  1775. #endif /* USE_READLINE */
  1776. /* on exit cleanup */
  1777. static void cleanup()
  1778. {
  1779. if (unix_socket){
  1780. if (unlink(unix_socket)<0){
  1781. fprintf(stderr, "ERROR: failed to delete %s: %s\n",
  1782. unix_socket, strerror(errno));
  1783. }
  1784. }
  1785. }
  1786. int main(int argc, char** argv)
  1787. {
  1788. int c;
  1789. char* sock_name;
  1790. int sock_type;
  1791. int s;
  1792. struct binrpc_cmd cmd;
  1793. struct id_list* sock_id;
  1794. char* format;
  1795. char* line;
  1796. char* l;
  1797. quit=0;
  1798. format=0;
  1799. line=0;
  1800. s=-1;
  1801. sock_name=0;
  1802. sock_type=UNIXS_SOCK;
  1803. opterr=0;
  1804. while((c=getopt(argc, argv, "UVhs:D:R:vf:"))!=-1){
  1805. switch(c){
  1806. case 'V':
  1807. printf("version: %s\n", version);
  1808. printf("%s compiled on %s \n", __FILE__,
  1809. compiled);
  1810. exit(0);
  1811. break;
  1812. case 'h':
  1813. printf("version: %s\n", version);
  1814. printf("%s", help_msg);
  1815. exit(0);
  1816. break;
  1817. case 's':
  1818. sock_name=optarg;
  1819. break;
  1820. case 'R':
  1821. reply_socket=optarg;
  1822. break;
  1823. case 'D':
  1824. sock_dir=optarg;
  1825. break;
  1826. case 'U':
  1827. sock_type=UDP_SOCK;
  1828. break;
  1829. case 'v':
  1830. verbose++;
  1831. break;
  1832. case 'f':
  1833. format=str_escape(optarg);
  1834. if (format==0){
  1835. fprintf(stderr, "ERROR: memory allocation failure\n");
  1836. goto error;
  1837. }
  1838. break;
  1839. case '?':
  1840. if (isprint(optopt))
  1841. fprintf(stderr, "Unknown option `-%c'.\n", optopt);
  1842. else
  1843. fprintf(stderr,
  1844. "Unknown option character `\\x%x'.\n",
  1845. optopt);
  1846. goto error;
  1847. case ':':
  1848. fprintf(stderr,
  1849. "Option `-%c' requires an argument.\n",
  1850. optopt);
  1851. goto error;
  1852. default:
  1853. abort();
  1854. }
  1855. }
  1856. if (sock_name==0){
  1857. sock_name=DEFAULT_CTL_SOCKET;
  1858. }
  1859. /* init the random number generator */
  1860. srand(getpid()+time(0)); /* we don't need very strong random numbers */
  1861. if (sock_name==0){
  1862. fprintf(stderr, "ERROR: no server socket address specified\n");
  1863. goto error;
  1864. }
  1865. sock_id=parse_listen_id(sock_name, strlen(sock_name), sock_type);
  1866. if (sock_id==0){
  1867. fprintf(stderr, "ERROR: error parsing server socket address %s\n", sock_name);
  1868. goto error;
  1869. }
  1870. switch(sock_id->proto){
  1871. case UDP_SOCK:
  1872. case TCP_SOCK:
  1873. if (sock_id->port==0){
  1874. sock_id->port=DEFAULT_CTL_PORT;
  1875. /*
  1876. fprintf(stderr, "ERROR: no port specified: %s:<port>\n",
  1877. sock_name);
  1878. goto error;
  1879. */
  1880. }
  1881. if ((s=connect_tcpudp_socket(sock_id->name, sock_id->port,
  1882. (sock_id->proto==UDP_SOCK)?SOCK_DGRAM:
  1883. SOCK_STREAM))<0){
  1884. goto error;
  1885. }
  1886. break;
  1887. case UNIXS_SOCK:
  1888. case UNIXD_SOCK:
  1889. if ((s=connect_unix_sock(sock_id->name,
  1890. (sock_id->proto==UNIXD_SOCK)?SOCK_DGRAM:
  1891. SOCK_STREAM))<0)
  1892. goto error;
  1893. break;
  1894. case UNKNOWN_SOCK:
  1895. fprintf(stderr, "ERROR: Bad socket type for %s\n", sock_name);
  1896. goto error;
  1897. }
  1898. free(sock_id); /* not needed anymore */
  1899. sock_id=0;
  1900. if (optind>=argc){
  1901. /*fprintf(stderr, "ERROR: no command specified\n");
  1902. goto error; */
  1903. }else{
  1904. if (parse_cmd(&cmd, &argv[optind], argc-optind)<0)
  1905. goto error;
  1906. if (run_cmd(s, &cmd, format)<0)
  1907. goto error;
  1908. goto end;
  1909. }
  1910. /* interactive mode */
  1911. if (get_kamcmd_list(s)==0){
  1912. #ifdef USE_CFG_VARS
  1913. get_cfgvars_list(s);
  1914. #endif /* USE_CFG_VARS */
  1915. #ifdef USE_COUNTERS
  1916. get_counters_list(s);
  1917. #endif /* USE_COUNTERS */
  1918. }
  1919. /* banners */
  1920. printf("%s %s\n", NAME, VERSION);
  1921. printf("%s\n", COPYRIGHT);
  1922. printf("%s\n", DISCLAIMER);
  1923. #ifdef USE_READLINE
  1924. /* initialize readline */
  1925. /* allow conditional parsing of the ~/.inputrc file*/
  1926. rl_readline_name=NAME;
  1927. rl_completion_entry_function=kamcmd_generator;
  1928. rl_attempted_completion_function=kamcmd_completion;
  1929. while(!quit){
  1930. line=readline(NAME "> ");
  1931. if (line==0) /* EOF */
  1932. break;
  1933. l=trim_ws(line); /* trim whitespace */
  1934. if (*l){
  1935. add_history(l);
  1936. run_line(s, l, format);
  1937. }
  1938. free(line);
  1939. line=0;
  1940. }
  1941. #else
  1942. line=malloc(MAX_LINE_SIZE);
  1943. if (line==0){
  1944. fprintf(stderr, "memory allocation error\n");
  1945. goto error;
  1946. }
  1947. printf(NAME "> "); fflush(stdout); /* prompt */
  1948. while(!quit && fgets(line, MAX_LINE_SIZE, stdin)){
  1949. l=trim_ws(line);
  1950. if (*l){
  1951. run_line(s, l, format);
  1952. }
  1953. printf(NAME "> "); fflush(stdout); /* prompt */
  1954. };
  1955. free(line);
  1956. line=0;
  1957. #endif /* USE_READLINE */
  1958. end:
  1959. /* normal exit */
  1960. if (line)
  1961. free(line);
  1962. if (format)
  1963. free(format);
  1964. if (rpc_array)
  1965. free_rpc_array(rpc_array, rpc_no);
  1966. #ifdef USE_CFG_VARS
  1967. if (cfg_grp_lst)
  1968. free_cfg_grp_lst();
  1969. if (cfg_vars_array){
  1970. free_rpc_array(cfg_vars_array, cfg_vars_no);
  1971. cfg_vars_array=0;
  1972. cfg_vars_no=0;
  1973. }
  1974. #endif /* USE_CFG_VARS */
  1975. #ifdef USE_COUNTERS
  1976. if (cnt_grp_lst)
  1977. free_cnt_grp_lst();
  1978. if (cnt_grps_array){
  1979. free_rpc_array(cnt_grps_array, cnt_grps_no);
  1980. cnt_grps_array=0;
  1981. cnt_grps_no=0;
  1982. }
  1983. #endif /* USE_COUNTERS */
  1984. cleanup();
  1985. exit(0);
  1986. error:
  1987. if (line)
  1988. free(line);
  1989. if (format)
  1990. free(format);
  1991. if (rpc_array)
  1992. free_rpc_array(rpc_array, rpc_no);
  1993. #ifdef USE_CFG_VARS
  1994. if (cfg_grp_lst)
  1995. free_cfg_grp_lst();
  1996. if (cfg_vars_array){
  1997. free_rpc_array(cfg_vars_array, cfg_vars_no);
  1998. cfg_vars_array=0;
  1999. cfg_vars_no=0;
  2000. }
  2001. #endif /* USE_CFG_VARS */
  2002. #ifdef USE_COUNTERS
  2003. if (cnt_grp_lst)
  2004. free_cnt_grp_lst();
  2005. if (cnt_grps_array){
  2006. free_rpc_array(cnt_grps_array, cnt_grps_no);
  2007. cnt_grps_array=0;
  2008. cnt_grps_no=0;
  2009. }
  2010. #endif /* USE_COUNTERS */
  2011. cleanup();
  2012. exit(-1);
  2013. }