Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

cmdlinelib.c 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. #include "cmdlinelib.h"
  2. #include "command.h"
  3. #include <gpxe/tables.h>
  4. #include <console.h>
  5. #include <malloc.h>
  6. #include <string.h>
  7. #include <stdarg.h>
  8. static struct command cmd_start[0] __table_start ( commands );
  9. static struct command cmd_end[0] __table_end ( commands );
  10. void cmdl_setgetchar(cmd_line* cmd, cmdl_getchar_t in)
  11. {
  12. cmd->getchar = in;
  13. }
  14. void cmdl_setputchar(cmd_line* cmd, cmdl_putchar_t in)
  15. {
  16. cmd->putchar = in;
  17. }
  18. void cmdl_setprintf(cmd_line* cmd, cmdl_printf_t in)
  19. {
  20. cmd->printf = in;
  21. }
  22. int cmdl_getexit(cmd_line* cmd)
  23. {
  24. if(cmdl_check(cmd) && !cmd->exit){
  25. return 0;
  26. }else{
  27. return 1;
  28. }
  29. }
  30. void cmdl_setexit(cmd_line* cmd, int exit)
  31. {
  32. if(cmdl_check(cmd)){
  33. cmd->exit = exit;
  34. }
  35. }
  36. int cmdl_printf(cmd_line* cmd, const char *format, ...)
  37. {
  38. int ret;
  39. char string[CMDL_BUFFER_SIZE];
  40. va_list ap;
  41. va_start(ap, format);
  42. ret = vsprintf(string, format, ap);
  43. cmdl_addstr(cmd, string);
  44. va_end(ap);
  45. return ret;
  46. }
  47. void cmdl_addstr(cmd_line* cmd, char* str)
  48. {
  49. unsigned int i;
  50. for(i = 0; i < strlen(str); i++){
  51. cmdl_addchar(cmd, str[i]);
  52. }
  53. }
  54. /*void cmdl_addoutput_str(cmd_line* cmd, char output[CMDL_OUTPUT_SIZE])
  55. {
  56. if(cmdl_check(cmd) && output != NULL){
  57. if(!cmd->has_output){
  58. cmdl_clearoutput(cmd);
  59. }
  60. strncat(cmd->output, output, CMDL_OUTPUT_SIZE);
  61. cmd->has_output = 1;
  62. }
  63. }*/
  64. /*char* cmdl_getoutput(cmd_line* cmd)
  65. {
  66. if(cmdl_check(cmd) && cmd->has_output){
  67. cmd->has_output = 0;
  68. return cmd->output;
  69. }else{
  70. return "";
  71. }
  72. }*/
  73. void cmdl_setpropmt(cmd_line* cmd, char prompt[CMDL_PROMPT_SIZE])
  74. {
  75. if(cmdl_check(cmd) && prompt != NULL){
  76. strncat(cmd->prompt, prompt, CMDL_PROMPT_SIZE);
  77. }
  78. }
  79. char *cmdl_getprompt(cmd_line* cmd)
  80. {
  81. if(cmdl_check(cmd)){
  82. return cmd->prompt;
  83. }else{
  84. return "";
  85. }
  86. }
  87. char* cmdl_getbuffer(cmd_line* cmd){
  88. if(cmdl_check(cmd)){
  89. return cmd->buffer;
  90. }else{
  91. return "";
  92. }
  93. }
  94. void cmdl_enterloop(cmd_line* cmd)
  95. {
  96. while(!cmdl_getexit(cmd)){
  97. if(cmd->refresh){
  98. cmd->printf("%s %s", cmd->prompt, cmd->buffer);
  99. cmd->refresh = 0;
  100. }
  101. // cmd->printf("Got %d\n", cmd->getchar());
  102. cmdl_parsechar(cmd, cmd->getchar());
  103. }
  104. }
  105. void cmdl_addreplace(cmd_line* cmd, char in)
  106. {
  107. if(cmd->cursor < CMDL_BUFFER_SIZE - 2){
  108. cmd->buffer[cmd->cursor] = in;
  109. cmd->cursor++;
  110. cmd->putchar((int)in);
  111. }
  112. }
  113. void cmdl_addinsert(cmd_line* cmd, char in)
  114. {
  115. int i;
  116. int to;
  117. if(cmd->cursor < CMDL_BUFFER_SIZE - 2 && cmd->cursor >= 0){
  118. if(strlen(cmd->buffer) < CMDL_BUFFER_SIZE - 2){
  119. to = strlen(cmd->buffer);
  120. }else{
  121. to = CMDL_BUFFER_SIZE - 2;
  122. }
  123. for(i=to; i > cmd->cursor; i--){
  124. cmd->buffer[i] = cmd->buffer[i-1];
  125. }
  126. cmd->buffer[cmd->cursor] = in;
  127. for(i=cmd->cursor; i < to; i++){
  128. cmd->putchar(cmd->buffer[i]);
  129. }
  130. for(i=cmd->cursor; i < to - 1; i++){
  131. cmd->putchar(CMDLK_BS);
  132. }
  133. cmd->cursor++;
  134. //cmdl_movecursor(cmd, CMDL_RIGHT);
  135. }
  136. }
  137. void cmdl_addchar(cmd_line* cmd, char in){
  138. if(cmd->insert){
  139. cmdl_addinsert(cmd, in);
  140. }else{
  141. cmdl_addreplace(cmd, in);
  142. }
  143. }
  144. void cmdl_parsechar(cmd_line* cmd, char in)
  145. {
  146. if(cmdl_check(cmd)){
  147. if(in >= 32){
  148. cmdl_addchar(cmd, in);
  149. }else{
  150. switch(in){
  151. case CMDLK_BS:
  152. if(cmdl_movecursor(cmd, CMDL_LEFT)){
  153. cmdl_del(cmd);
  154. }
  155. break;
  156. case CMDLK_RETURN:
  157. cmd->putchar('\n');
  158. cmdl_exec(cmd);
  159. cmd->refresh = 1;
  160. break;
  161. case CMDLK_BW:
  162. cmdl_movecursor(cmd, CMDL_LEFT);
  163. break;
  164. case CMDLK_FW:
  165. //cmdl_movecursor(cmd, CMDL_RIGHT);
  166. break;
  167. case CMDLK_TAB:
  168. cmdl_tabcomplete(cmd);
  169. break;
  170. }
  171. }
  172. }
  173. }
  174. void cmdl_tabcomplete(cmd_line *cmd)
  175. {
  176. struct command *ccmd;
  177. int count=0;
  178. char* result[CMDL_MAX_TAB_COMPLETE_RESULT];
  179. for ( ccmd = cmd_start ; ccmd < cmd_end ; ccmd++ ) {
  180. if(!strncmp(ccmd->name, cmd->buffer, strlen(cmd->buffer))){
  181. if(count <= CMDL_MAX_TAB_COMPLETE_RESULT){
  182. result[count++] = (char*)(ccmd->name);
  183. }
  184. }
  185. }
  186. if( count == 1 ){
  187. cmdl_addstr(cmd, (char*)(result[0] + strlen(cmd->buffer)));
  188. cmd->tabstate = 0;
  189. cmdl_addchar(cmd, ' ');
  190. } else if( count > 1 ) {
  191. int i, i2, minlen=CMDL_BUFFER_SIZE, same=1;
  192. char last;
  193. for(i = 0; i < count; i ++) {
  194. if(minlen > (int)strlen( result[i] ) ){
  195. minlen = strlen(result[i]);
  196. }
  197. }
  198. if((int)strlen(cmd->buffer) < minlen){
  199. for(i = strlen(cmd->buffer); i < minlen; i++){
  200. last = result[0][i];
  201. for(i2 = 1; i2 < count; i2 ++) {
  202. if(result[i2][i] != last){
  203. same = 0;
  204. break;
  205. }
  206. }
  207. if(same){
  208. cmdl_addchar(cmd, last);
  209. }
  210. }
  211. }
  212. cmd->tabstate++;
  213. }
  214. if(count > 1 && cmd->tabstate > 1){
  215. int i;
  216. cmd->tabstate = 0;
  217. cmd->refresh = 1;
  218. cmd->putchar('\n');
  219. for(i = 0; i < count; i ++){
  220. cmd->printf("%s\t", result[i]);
  221. }
  222. cmd->putchar('\n');
  223. }
  224. }
  225. void cmdl_exec(cmd_line* cmd)
  226. {
  227. cmdl_param_list* params;
  228. int unknown=1;
  229. struct command *ccmd;
  230. params = cmdl_getparams(cmd->buffer);
  231. if(params == NULL){
  232. cmdl_clearbuffer(cmd);
  233. return;
  234. }
  235. if(params->argc > 0){
  236. if(!strcmp(params->argv[0], "exit") || !strcmp(params->argv[0], "quit")){
  237. cmdl_setexit(cmd, 1);
  238. /* }else if(!strcmp(params->argv[0], "help")){
  239. if(params->argc > 1){
  240. cmdl_builtin_help(cmd, params->argv[1]);
  241. }else{
  242. cmdl_builtin_help(cmd, "");
  243. }*/
  244. }else{
  245. for ( ccmd = cmd_start ; ccmd < cmd_end ; ccmd++ ) {
  246. if(!strcmp(ccmd->name, params->argv[0])){
  247. unknown = 0;
  248. ccmd->exec(params->argc, params->argv);
  249. break;
  250. }
  251. }
  252. if(unknown){
  253. cmd->printf("%s: unknown command\n", params->argv[0]);
  254. }
  255. }
  256. }
  257. free(params);
  258. cmdl_clearbuffer(cmd);
  259. }
  260. /*void cmdl_builtin_help(cmd_line* cmd, char* command){
  261. struct command *ccmd;
  262. int unknown = 1;
  263. if(strcmp(command, "") == 0){
  264. cmd->printf("Built in commands:\n\n\thelp\t\tCommand usage help (\"help help\" for more info)\n\texit, quit\t\tExit the command line and boot\n\nCompiled in commands:\n\n");
  265. for ( ccmd = cmd_start ; ccmd < cmd_end ; ccmd++ ) {
  266. cmd->printf ("\t%s\t\t%s\n", ccmd->name, ccmd->desc );
  267. }
  268. }else{
  269. if(!strcmp(command, "help")){
  270. cmd->printf("help - The help command\n\nUsage: help <command>\n\n\tExample:\n\t\thelp help\n");
  271. }else if(!strcmp(command, "exit") || !strcmp(command, "quit")){
  272. cmd->printf("exit, quit - The quit command\n\nUsage:\nquit or exit\n\n\tExample:\n\t\texit\n");
  273. }else{
  274. for ( ccmd = cmd_start ; ccmd < cmd_end ; ccmd++ ) {
  275. if(!strcmp(ccmd->name, command)){
  276. unknown = 0;
  277. cmd->printf ("\t%s - %s\n\nUsage:\n%s\n", ccmd->name, ccmd->desc, ccmd->usage );
  278. break;
  279. }
  280. if(unknown){
  281. cmd->printf("\"%s\" isn't compiled in (does it exist?).\n", command);
  282. }
  283. }
  284. }
  285. }
  286. }*/
  287. cmdl_param_list* cmdl_getparams(const char* command){
  288. cmdl_param_list* this;
  289. char *result = NULL;
  290. int count=0;
  291. char *command2;
  292. this = (cmdl_param_list*)malloc(sizeof(cmdl_param_list));
  293. if(this == NULL){
  294. return NULL;
  295. }
  296. command2 = malloc(strlen(command) + 1);
  297. this->argc=0;
  298. strcpy(command2, command);
  299. result = strtok(command2, " ");
  300. while( result != NULL ) {
  301. this->argc++;
  302. result = strtok( NULL, " ");
  303. }
  304. this->argv = (char**)malloc(sizeof(char*) * this->argc);
  305. if(this->argv == NULL){
  306. free(this);
  307. return NULL;
  308. }
  309. strcpy(command2, command);
  310. result = strtok(command2, " ");
  311. while( result != NULL && this->argc > count) {
  312. this->argv[count] = (char*)malloc(sizeof(char) * (strlen(result) + 1));
  313. if(this->argv[count] == NULL){
  314. free(this);
  315. return NULL;
  316. }
  317. strcpy(this->argv[count], result);
  318. count++;
  319. result = strtok( NULL, " ");
  320. }
  321. free(command2);
  322. return this;
  323. }
  324. /*char* cmdl_parse_getcmd(cmd_line* cmd){
  325. int i;
  326. char* ret;
  327. ret = (char*)malloc(1);
  328. ret[0] = 0;
  329. for(i=0; i < CMDL_BUFFER_SIZE - 1; i++){
  330. if(cmd->buffer[i + 1] == ' ' || cmd->buffer[i + 1] == '\0'){
  331. free(ret);
  332. ret = (char*)malloc(i+1);
  333. strncat(ret, cmd->buffer, i+1);
  334. break;
  335. }
  336. }
  337. return ret;
  338. }*/
  339. void cmdl_clearbuffer(cmd_line* cmd)
  340. {
  341. if(cmdl_check(cmd)){
  342. int i;
  343. cmd->cursor = 0;
  344. for(i=0; i < CMDL_BUFFER_SIZE; i++){
  345. cmd->buffer[i] = 0;
  346. }
  347. }
  348. }
  349. /*void cmdl_clearoutput(cmd_line* cmd)
  350. {
  351. if(cmdl_check(cmd)){
  352. int i;
  353. for(i=0; i < CMDL_OUTPUT_SIZE; i++){
  354. cmd->output[i] = 0;
  355. }
  356. }
  357. }*/
  358. int cmdl_movecursor(cmd_line* cmd, int direction)
  359. {
  360. if(cmdl_check(cmd)){
  361. switch(direction){
  362. case CMDL_LEFT:
  363. if(cmd->cursor > 0){
  364. cmd->cursor--;
  365. cmd->putchar(CMDLK_BS);
  366. }else{
  367. return 0;
  368. }
  369. break;
  370. case CMDL_RIGHT:
  371. if(cmd->cursor < CMDL_BUFFER_SIZE - 2){
  372. cmd->cursor++;
  373. cmd->putchar(' ');
  374. }else{
  375. return 0;
  376. }
  377. break;
  378. }
  379. }
  380. return 1;
  381. }
  382. void cmdl_del(cmd_line* cmd)
  383. {
  384. if(cmdl_check(cmd) && cmd->cursor < CMDL_BUFFER_SIZE - 2 && cmd->cursor >= 0){
  385. int i;
  386. for(i = cmd->cursor; i < (int)strlen(cmd->buffer); i++){
  387. cmd->buffer[i] = cmd->buffer[i + 1];
  388. if(!cmd->buffer[i]){
  389. cmd->putchar(' ');
  390. }else{
  391. cmd->putchar(cmd->buffer[i]);
  392. }
  393. }
  394. for(i = cmd->cursor; i < (int)strlen(cmd->buffer) + 1; i++){
  395. cmd->putchar(CMDLK_BS);
  396. }
  397. }
  398. }
  399. int cmdl_check(cmd_line* cmd)
  400. {
  401. if(
  402. cmd != NULL &&
  403. cmd->buffer != NULL &&
  404. cmd->prompt != NULL &&
  405. cmd->cursor >= 0 &&
  406. cmd->cursor < CMDL_BUFFER_SIZE - 1 &&
  407. cmd->buffer[CMDL_BUFFER_SIZE - 1] == 0 &&
  408. cmd->prompt[CMDL_PROMPT_SIZE - 1] == 0
  409. ){
  410. return 1;
  411. }else{
  412. return 0;
  413. }
  414. }
  415. cmd_line* cmdl_create()
  416. {
  417. cmd_line* this;
  418. int i;
  419. /* Initiate the command line */
  420. this = (cmd_line*)malloc(sizeof(cmd_line));
  421. if(this == NULL){
  422. return NULL;
  423. }
  424. /* Allocate output buffer */
  425. /*this->output = (char*)malloc(CMDL_OUTPUT_SIZE);
  426. if(this->output == NULL){
  427. free(this);
  428. return NULL;
  429. }*/
  430. /* for(i = 0; i < CMDL_OUTPUT_SIZE; i++){
  431. this->output[i] = 0;
  432. }*/
  433. /* Allocate command line buffer */
  434. this->buffer = (char*)malloc(CMDL_BUFFER_SIZE);
  435. if(this->buffer == NULL){
  436. free(this);
  437. return NULL;
  438. }
  439. for(i = 0; i < CMDL_BUFFER_SIZE; i++){
  440. this->buffer[i] = 0;
  441. }
  442. /* Allocate prompt buffer */
  443. this->prompt = (char*)malloc(CMDL_PROMPT_SIZE);
  444. if(this->prompt == NULL){
  445. free(this);
  446. return NULL;
  447. }
  448. for(i = 0; i < CMDL_PROMPT_SIZE; i++){
  449. this->prompt[i] = 0;
  450. }
  451. /* Initiate cursor position etc.*/
  452. this->cursor = 0;
  453. //this->has_output = 0;
  454. this->exit = 0;
  455. this->refresh = 1;
  456. this->tabstate = 0;
  457. this->insert = 0;
  458. /* set callbacks to NULL */
  459. this->getchar = NULL;
  460. this->putchar = NULL;
  461. this->printf = NULL;
  462. /* List the commands */
  463. struct command *cmd;
  464. printf ( "Compiled in commands: ");
  465. for ( cmd = cmd_start ; cmd < cmd_end ; cmd++ ) {
  466. printf("%s ", cmd->name);
  467. }
  468. printf("\n");
  469. return this;
  470. }
  471. void cmdl_free(cmd_line* cmd)
  472. {
  473. free(cmd);
  474. }