cmdparse.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:7k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  *
  6.  * Improved error handling by Brian Boesch of Stanford University
  7.  * Feb '91 - Bill Simpson
  8.  * bit16cmd for PPP
  9.  * Mar '91 - Glenn McGregor
  10.  * handle string escaped sequences
  11.  */
  12. #include <stdio.h>
  13. #include "global.h"
  14. #include "proc.h"
  15. #include "cmdparse.h"
  16. struct boolcmd {
  17. char *str; /* Token */
  18. int val; /* Value */
  19. };
  20. static struct boolcmd Boolcmds[] = {
  21. "y", 1, /* Synonyms for "true" */
  22. "yes", 1,
  23. "true", 1,
  24. "on", 1,
  25. "1", 1,
  26. "set", 1,
  27. "enable", 1,
  28. "n", 0, /* Synonyms for "false" */
  29. "no", 0,
  30. "false", 0,
  31. "off", 0,
  32. "0", 0,
  33. "clear", 0,
  34. "disable", 0,
  35. NULL
  36. };
  37. static char *stringparse(char *line);
  38. static char *
  39. stringparse(line)
  40. char *line;
  41. {
  42. register char *cp = line;
  43. unsigned long num;
  44. while ( *line != '' && *line != '"' ) {
  45. if ( *line == '\' ) {
  46. line++;
  47. switch ( *line++ ) {
  48. case 'n':
  49. *cp++ = 'n';
  50. break;
  51. case 't':
  52. *cp++ = 't';
  53. break;
  54. case 'v':
  55. *cp++ = 'v';
  56. break;
  57. case 'b':
  58. *cp++ = 'b';
  59. break;
  60. case 'r':
  61. *cp++ = 'r';
  62. break;
  63. case 'f':
  64. *cp++ = 'f';
  65. break;
  66. case 'a':
  67. *cp++ = 'a';
  68. break;
  69. case '\':
  70. *cp++ = '\';
  71. break;
  72. case '?':
  73. *cp++ = '?';
  74. break;
  75. case ''':
  76. *cp++ = ''';
  77. break;
  78. case '"':
  79. *cp++ = '"';
  80. break;
  81. case 'x':
  82. num = strtoul( --line, &line, 16 );
  83. *cp++ = (char) num;
  84. break;
  85. case '0':
  86. case '1':
  87. case '2':
  88. case '3':
  89. case '4':
  90. case '5':
  91. case '6':
  92. case '7':
  93. num = strtoul( --line, &line, 8 );
  94. *cp++ = (char) num;
  95. break;
  96. case '':
  97. return NULL;
  98. default:
  99. *cp++ = *(line - 1);
  100. break;
  101. };
  102. } else {
  103. *cp++ = *line++;
  104. }
  105. }
  106. if ( *line == '"' )
  107. line++;  /* skip final quote */
  108. *cp = ''; /* terminate string */
  109. return line;
  110. }
  111. int
  112. cmdparse(cmds,line,p)
  113. struct cmds cmds[];
  114. register char *line;
  115. void *p;
  116. {
  117. struct cmds *cmdp;
  118. char *argv[NARG],*cp;
  119. char **pargv;
  120. int argc,i;
  121. /* Remove cr/lf */
  122. rip(line);
  123. for(argc = 0;argc < NARG;argc++)
  124. argv[argc] = NULL;
  125. for(argc = 0;argc < NARG;){
  126. register int qflag = FALSE;
  127. /* Skip leading white space */
  128. while(*line == ' ' || *line == 't')
  129. line++;
  130. if(*line == '')
  131. break;
  132. /* return if comment character first non-white */
  133. if ( argc == 0  &&  *line == '#' )
  134. return 0;
  135. /* Check for quoted token */
  136. if(*line == '"'){
  137. line++; /* Suppress quote */
  138. qflag = TRUE;
  139. }
  140. argv[argc++] = line; /* Beginning of token */
  141. if(qflag){
  142. /* Find terminating delimiter */
  143. if((line = stringparse(line)) == NULL){
  144. return -1;
  145. }
  146. } else {
  147. /* Find space or tab. If not present,
  148.  * then we've already found the last
  149.  * token.
  150.  */
  151. if((cp = strchr(line,' ')) == NULL
  152.  && (cp = strchr(line,'t')) == NULL){
  153. break;
  154. }
  155. *cp++ = '';
  156. line = cp;
  157. }
  158. }
  159. if (argc < 1) { /* empty command line */
  160. argc = 1;
  161. argv[0] = "";
  162. }
  163. /* Look up command in table; prefix matches are OK */
  164. for(cmdp = cmds;cmdp->name != NULL;cmdp++){
  165. if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
  166. break;
  167. }
  168. if(cmdp->name == NULL) {
  169. if(cmdp->argc_errmsg != NULL)
  170. printf("%sn",cmdp->argc_errmsg);
  171. return -1;
  172. }
  173. if(argc < cmdp->argcmin) {
  174. /* Insufficient arguments */
  175. printf("Usage: %sn",cmdp->argc_errmsg);
  176. return -1;
  177. }
  178. if(cmdp->func == NULL)
  179. return 0;
  180. if(cmdp->stksize == 0){
  181. return (*cmdp->func)(argc,argv,p);
  182. } else {
  183. /* Make private copy of argv and args,
  184.  * spawn off subprocess and return.
  185.  */
  186. pargv = (char **)callocw(argc,sizeof(char *));
  187. for(i=0;i<argc;i++)
  188. pargv[i] = strdup(argv[i]);
  189. newproc(cmdp->name,cmdp->stksize,
  190. (void (*)())cmdp->func,argc,pargv,p,1);
  191. return 0;
  192. }
  193. }
  194. /* Call a subcommand based on the first token in an already-parsed line */
  195. int
  196. subcmd(tab,argc,argv,p)
  197. struct cmds tab[];
  198. int argc;
  199. char *argv[];
  200. void *p;
  201. {
  202. register struct cmds *cmdp;
  203. char **pargv;
  204. int found = 0;
  205. int i;
  206. /* Strip off first token and pass rest of line to subcommand */
  207. if (argc < 2) {
  208. if (argc < 1)
  209. printf("SUBCMD - Don't know what to do?n");
  210. else
  211. printf(""%s" - takes at least one argumentn",argv[0]);
  212. return -1;
  213. }
  214. argc--;
  215. argv++;
  216. for(cmdp = tab;cmdp->name != NULL;cmdp++){
  217. if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0){
  218. found = 1;
  219. break;
  220. }
  221. }
  222. if(!found){
  223. printf("valid subcommands:");
  224. for(cmdp = tab;cmdp->name != NULL;cmdp++)
  225. printf(" %s",cmdp->name);
  226. printf("n");
  227. return -1;
  228. }
  229. if(argc < cmdp->argcmin){
  230. if(cmdp->argc_errmsg != NULL)
  231. printf("Usage: %sn",cmdp->argc_errmsg);
  232. return -1;
  233. }
  234. if(cmdp->stksize == 0){
  235. return (*cmdp->func)(argc,argv,p);
  236. } else {
  237. /* Make private copy of argv and args */
  238. pargv = (char **)callocw(argc,sizeof(char *));
  239. for(i=0;i<argc;i++)
  240. pargv[i] = strdup(argv[i]);
  241. newproc(cmdp->name,cmdp->stksize,
  242.  (void (*)())cmdp->func,argc,pargv,p,1);
  243. return(0);
  244. }
  245. }
  246. /* Subroutine for setting and displaying boolean flags */
  247. int
  248. setbool(var,label,argc,argv)
  249. int *var;
  250. char *label;
  251. int argc;
  252. char *argv[];
  253. {
  254. struct boolcmd *bc;
  255. if(argc < 2){
  256. printf("%s: %sn",label,*var ? "on":"off");
  257. return 0;
  258. }
  259. for(bc = Boolcmds;bc->str != NULL;bc++){
  260. if(strcmpi(argv[1],bc->str) == 0){
  261. *var = bc->val;
  262. return 0;
  263. }
  264. }
  265. printf("Valid options:");
  266. for(bc = Boolcmds;bc->str != NULL;bc++)
  267. printf(" %s",bc->str);
  268. printf("n");
  269. return 1;
  270. }
  271. /* Subroutine for setting and displaying bit values */
  272. int
  273. bit16cmd(bits,mask,label,argc,argv)
  274. uint16 *bits;
  275. uint16 mask;
  276. char *label;
  277. int argc;
  278. char *argv[];
  279. {
  280. int doing = (*bits & mask);
  281. int result = setbool( &doing, label, argc, argv );
  282. if ( !result ) {
  283. if ( doing )
  284. *bits |= mask;
  285. else
  286. *bits &= ~mask;
  287. }
  288. return result;
  289. }
  290. /* Subroutine for setting and displaying long variables */
  291. int
  292. setlong(var,label,argc,argv)
  293. long *var;
  294. char *label;
  295. int argc;
  296. char *argv[];
  297. {
  298. if(argc < 2)
  299. printf("%s: %ldn",label,*var);
  300. else
  301. *var = atol(argv[1]);
  302. return 0;
  303. }
  304. /* Subroutine for setting and displaying short variables */
  305. int
  306. setshort(var,label,argc,argv)
  307. unsigned short *var;
  308. char *label;
  309. int argc;
  310. char *argv[];
  311. {
  312. if(argc < 2)
  313. printf("%s: %un",label,*var);
  314. else
  315. *var = atoi(argv[1]);
  316. return 0;
  317. }
  318. /* Subroutine for setting and displaying integer variables */
  319. int
  320. setint(var,label,argc,argv)
  321. int *var;
  322. char *label;
  323. int argc;
  324. char *argv[];
  325. {
  326. if(argc < 2)
  327. printf("%s: %in",label,*var);
  328. else
  329. *var = atoi(argv[1]);
  330. return 0;
  331. }
  332. /* Subroutine for setting and displaying unsigned integer variables */
  333. int
  334. setuns(var,label,argc,argv)
  335. unsigned *var;
  336. char *label;
  337. int argc;
  338. char *argv[];
  339. {
  340. if(argc < 2)
  341. printf("%s: %un",label,*var);
  342. else
  343. *var = atoi(argv[1]);
  344. return 0;
  345. }