sercmd.c 53 KB

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