Advertisement
Guest User

ipxe clear screen command /scr/core/exec.c

a guest
Oct 15th, 2012
310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.93 KB | None | 0 0
  1. /*
  2. * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. */
  19.  
  20. FILE_LICENCE ( GPL2_OR_LATER );
  21.  
  22. #include <stdint.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <curses.h>
  28. #include <unistd.h>
  29. #include <getopt.h>
  30. #include <errno.h>
  31. #include <assert.h>
  32. #include <ipxe/tables.h>
  33. #include <ipxe/command.h>
  34. #include <ipxe/parseopt.h>
  35. #include <ipxe/settings.h>
  36. #include <ipxe/console.h>
  37. #include <ipxe/keys.h>
  38. #include <ipxe/process.h>
  39. #include <ipxe/nap.h>
  40. #include <ipxe/shell.h>
  41.  
  42. /** @file
  43. *
  44. * Command execution
  45. *
  46. */
  47.  
  48. /** Shell stop state */
  49. static int stop_state;
  50.  
  51. /**
  52. * Execute command
  53. *
  54. * @v command Command name
  55. * @v argv Argument list
  56. * @ret rc Return status code
  57. *
  58. * Execute the named command. Unlike a traditional POSIX execv(),
  59. * this function returns the exit status of the command.
  60. */
  61. int execv ( const char *command, char * const argv[] ) {
  62. struct command *cmd;
  63. int argc;
  64. int rc;
  65.  
  66. /* Count number of arguments */
  67. for ( argc = 0 ; argv[argc] ; argc++ ) {}
  68.  
  69. /* An empty command is deemed to do nothing, successfully */
  70. if ( command == NULL ) {
  71. rc = 0;
  72. goto done;
  73. }
  74.  
  75. /* Sanity checks */
  76. if ( argc == 0 ) {
  77. DBG ( "%s: empty argument list\n", command );
  78. rc = -EINVAL;
  79. goto done;
  80. }
  81.  
  82. /* Reset getopt() library ready for use by the command. This
  83. * is an artefact of the POSIX getopt() API within the context
  84. * of Etherboot; see the documentation for reset_getopt() for
  85. * details.
  86. */
  87. reset_getopt();
  88.  
  89. /* Hand off to command implementation */
  90. for_each_table_entry ( cmd, COMMANDS ) {
  91. if ( strcmp ( command, cmd->name ) == 0 ) {
  92. rc = cmd->exec ( argc, ( char ** ) argv );
  93. goto done;
  94. }
  95. }
  96.  
  97. printf ( "%s: command not found\n", command );
  98. rc = -ENOEXEC;
  99.  
  100. done:
  101. /* Store error number, if an error occurred */
  102. if ( rc ) {
  103. errno = rc;
  104. if ( errno < 0 )
  105. errno = -errno;
  106. }
  107.  
  108. return rc;
  109. }
  110.  
  111. /**
  112. * Split command line into tokens
  113. *
  114. * @v command Command line
  115. * @v tokens Token list to populate, or NULL
  116. * @ret count Number of tokens
  117. *
  118. * Splits the command line into whitespace-delimited tokens. If @c
  119. * tokens is non-NULL, any whitespace in the command line will be
  120. * replaced with NULs.
  121. */
  122. static int split_command ( char *command, char **tokens ) {
  123. int count = 0;
  124.  
  125. while ( 1 ) {
  126. /* Skip over any whitespace / convert to NUL */
  127. while ( isspace ( *command ) ) {
  128. if ( tokens )
  129. *command = '\0';
  130. command++;
  131. }
  132. /* Check for end of line */
  133. if ( ! *command )
  134. break;
  135. /* We have found the start of the next argument */
  136. if ( tokens )
  137. tokens[count] = command;
  138. count++;
  139. /* Skip to start of next whitespace, if any */
  140. while ( *command && ! isspace ( *command ) ) {
  141. command++;
  142. }
  143. }
  144. return count;
  145. }
  146.  
  147. /**
  148. * Process next command only if previous command succeeded
  149. *
  150. * @v rc Status of previous command
  151. * @ret process Process next command
  152. */
  153. static int process_on_success ( int rc ) {
  154. return ( rc == 0 );
  155. }
  156.  
  157. /**
  158. * Process next command only if previous command failed
  159. *
  160. * @v rc Status of previous command
  161. * @ret process Process next command
  162. */
  163. static int process_on_failure ( int rc ) {
  164. return ( rc != 0 );
  165. }
  166.  
  167. /**
  168. * Process next command regardless of status from previous command
  169. *
  170. * @v rc Status of previous command
  171. * @ret process Process next command
  172. */
  173. static int process_always ( int rc __unused ) {
  174. return 1;
  175. }
  176.  
  177. /**
  178. * Find command terminator
  179. *
  180. * @v tokens Token list
  181. * @ret process_next "Should next command be processed?" function
  182. * @ret argc Argument count
  183. */
  184. static int command_terminator ( char **tokens,
  185. int ( **process_next ) ( int rc ) ) {
  186. unsigned int i;
  187.  
  188. /* Find first terminating token */
  189. for ( i = 0 ; tokens[i] ; i++ ) {
  190. if ( tokens[i][0] == '#' ) {
  191. /* Start of a comment */
  192. break;
  193. } else if ( strcmp ( tokens[i], "||" ) == 0 ) {
  194. /* Short-circuit logical OR */
  195. *process_next = process_on_failure;
  196. return i;
  197. } else if ( strcmp ( tokens[i], "&&" ) == 0 ) {
  198. /* Short-circuit logical AND */
  199. *process_next = process_on_success;
  200. return i;
  201. } else if ( strcmp ( tokens[i], ";" ) == 0 ) {
  202. /* Process next command unconditionally */
  203. *process_next = process_always;
  204. return i;
  205. }
  206. }
  207.  
  208. /* End of token list */
  209. *process_next = NULL;
  210. return i;
  211. }
  212.  
  213. /**
  214. * Set shell stop state
  215. *
  216. * @v stop Shell stop state
  217. */
  218. void shell_stop ( int stop ) {
  219. stop_state = stop;
  220. }
  221.  
  222. /**
  223. * Test and consume shell stop state
  224. *
  225. * @v stop Shell stop state to consume
  226. * @v stopped Shell had been stopped
  227. */
  228. int shell_stopped ( int stop ) {
  229. int stopped;
  230.  
  231. /* Test to see if we need to stop */
  232. stopped = ( stop_state >= stop );
  233.  
  234. /* Consume stop state */
  235. if ( stop_state <= stop )
  236. stop_state = 0;
  237.  
  238. return stopped;
  239. }
  240.  
  241. /**
  242. * Expand settings within a token list
  243. *
  244. * @v argc Argument count
  245. * @v tokens Token list
  246. * @v argv Argument list to fill in
  247. * @ret rc Return status code
  248. */
  249. static int expand_tokens ( int argc, char **tokens, char **argv ) {
  250. int i;
  251.  
  252. /* Expand each token in turn */
  253. for ( i = 0 ; i < argc ; i++ ) {
  254. argv[i] = expand_settings ( tokens[i] );
  255. if ( ! argv[i] )
  256. goto err_expand_settings;
  257. }
  258.  
  259. return 0;
  260.  
  261. err_expand_settings:
  262. assert ( argv[i] == NULL );
  263. for ( ; i >= 0 ; i-- )
  264. free ( argv[i] );
  265. return -ENOMEM;
  266. }
  267.  
  268. /**
  269. * Free an expanded token list
  270. *
  271. * @v argv Argument list
  272. */
  273. static void free_tokens ( char **argv ) {
  274.  
  275. /* Free each expanded argument */
  276. while ( *argv )
  277. free ( *(argv++) );
  278. }
  279.  
  280. /**
  281. * Execute command line
  282. *
  283. * @v command Command line
  284. * @ret rc Return status code
  285. *
  286. * Execute the named command and arguments.
  287. */
  288. int system ( const char *command ) {
  289. int count = split_command ( ( char * ) command, NULL );
  290. char *all_tokens[ count + 1 ];
  291. int ( * process_next ) ( int rc );
  292. char *command_copy;
  293. char **tokens;
  294. int argc;
  295. int process;
  296. int rc = 0;
  297.  
  298. /* Create modifiable copy of command */
  299. command_copy = strdup ( command );
  300. if ( ! command_copy )
  301. return -ENOMEM;
  302.  
  303. /* Split command into tokens */
  304. split_command ( command_copy, all_tokens );
  305. all_tokens[count] = NULL;
  306.  
  307. /* Process individual commands */
  308. process = 1;
  309. for ( tokens = all_tokens ; ; tokens += ( argc + 1 ) ) {
  310.  
  311. /* Find command terminator */
  312. argc = command_terminator ( tokens, &process_next );
  313.  
  314. /* Expand tokens and execute command */
  315. if ( process ) {
  316. char *argv[ argc + 1 ];
  317.  
  318. /* Expand tokens */
  319. if ( ( rc = expand_tokens ( argc, tokens, argv ) ) != 0)
  320. break;
  321. argv[argc] = NULL;
  322.  
  323. /* Execute command */
  324. rc = execv ( argv[0], argv );
  325.  
  326. /* Free tokens */
  327. free_tokens ( argv );
  328. }
  329.  
  330. /* Stop processing, if applicable */
  331. if ( shell_stopped ( SHELL_STOP_COMMAND ) )
  332. break;
  333.  
  334. /* Stop processing if we have reached the end of the
  335. * command.
  336. */
  337. if ( ! process_next )
  338. break;
  339.  
  340. /* Determine whether or not to process next command */
  341. process = process_next ( rc );
  342. }
  343.  
  344. /* Free modified copy of command */
  345. free ( command_copy );
  346.  
  347. return rc;
  348. }
  349.  
  350. /**
  351. * Concatenate arguments
  352. *
  353. * @v args Argument list (NULL-terminated)
  354. * @ret string Concatenated arguments
  355. *
  356. * The returned string is allocated with malloc(). The caller is
  357. * responsible for eventually free()ing this string.
  358. */
  359. char * concat_args ( char **args ) {
  360. char **arg;
  361. size_t len;
  362. char *string;
  363. char *ptr;
  364.  
  365. /* Calculate total string length */
  366. len = 1 /* NUL */;
  367. for ( arg = args ; *arg ; arg++ )
  368. len += ( 1 /* possible space */ + strlen ( *arg ) );
  369.  
  370. /* Allocate string */
  371. string = zalloc ( len );
  372. if ( ! string )
  373. return NULL;
  374.  
  375. /* Populate string */
  376. ptr = string;
  377. for ( arg = args ; *arg ; arg++ ) {
  378. ptr += sprintf ( ptr, "%s%s",
  379. ( ( arg == args ) ? "" : " " ), *arg );
  380. }
  381. assert ( ptr < ( string + len ) );
  382.  
  383. return string;
  384. }
  385.  
  386. /** "echo" options */
  387. struct echo_options {
  388. /** Do not print trailing newline */
  389. int no_newline;
  390. };
  391.  
  392. /** "echo" option list */
  393. static struct option_descriptor echo_opts[] = {
  394. OPTION_DESC ( "n", 'n', no_argument,
  395. struct echo_options, no_newline, parse_flag ),
  396. };
  397.  
  398. /** "echo" command descriptor */
  399. static struct command_descriptor echo_cmd =
  400. COMMAND_DESC ( struct echo_options, echo_opts, 0, MAX_ARGUMENTS,
  401. "[-n] [...]" );
  402.  
  403. /**
  404. * "echo" command
  405. *
  406. * @v argc Argument count
  407. * @v argv Argument list
  408. * @ret rc Return status code
  409. */
  410. static int echo_exec ( int argc, char **argv ) {
  411. struct echo_options opts;
  412. char *text;
  413. int rc;
  414.  
  415. /* Parse options */
  416. if ( ( rc = parse_options ( argc, argv, &echo_cmd, &opts ) ) != 0 )
  417. return rc;
  418.  
  419. /* Parse text */
  420. text = concat_args ( &argv[optind] );
  421. if ( ! text )
  422. return -ENOMEM;
  423.  
  424. /* Print text */
  425. printf ( "%s%s", text, ( opts.no_newline ? "" : "\n" ) );
  426.  
  427. free ( text );
  428. return 0;
  429. }
  430.  
  431. /** "echo" command */
  432. struct command echo_command __command = {
  433. .name = "echo",
  434. .exec = echo_exec,
  435. };
  436.  
  437. /** "exit" options */
  438. struct exit_options {};
  439.  
  440. /** "exit" option list */
  441. static struct option_descriptor exit_opts[] = {};
  442.  
  443. /** "exit" command descriptor */
  444. static struct command_descriptor exit_cmd =
  445. COMMAND_DESC ( struct exit_options, exit_opts, 0, 1, "[<status>]" );
  446.  
  447. /**
  448. * "exit" command
  449. *
  450. * @v argc Argument count
  451. * @v argv Argument list
  452. * @ret rc Return status code
  453. */
  454. static int exit_exec ( int argc, char **argv ) {
  455. struct exit_options opts;
  456. unsigned int exit_code = 0;
  457. int rc;
  458.  
  459. /* Parse options */
  460. if ( ( rc = parse_options ( argc, argv, &exit_cmd, &opts ) ) != 0 )
  461. return rc;
  462.  
  463. /* Parse exit status, if present */
  464. if ( optind != argc ) {
  465. if ( ( rc = parse_integer ( argv[optind], &exit_code ) ) != 0 )
  466. return rc;
  467. }
  468.  
  469. /* Stop shell processing */
  470. shell_stop ( SHELL_STOP_COMMAND_SEQUENCE );
  471.  
  472. return exit_code;
  473. }
  474.  
  475. /** "exit" command */
  476. struct command exit_command __command = {
  477. .name = "exit",
  478. .exec = exit_exec,
  479. };
  480.  
  481. /**
  482. * "clearscreen" command
  483. *
  484. * @v argc Argument count
  485. * @v argv Argument list
  486. * @ret rc Return status code
  487. */
  488. static int clearscreen_exec ( int argc __unused, char **argv __unused ) {
  489. initscr();
  490. erase();
  491. endwin();
  492. return 0;
  493. }
  494.  
  495. /** "clearscreen" command */
  496. struct command clearscreen_command __command = {
  497. .name = "clearscreen",
  498. .exec = clearscreen_exec,
  499. };
  500.  
  501.  
  502. /** "isset" options */
  503. struct isset_options {};
  504.  
  505. /** "isset" option list */
  506. static struct option_descriptor isset_opts[] = {};
  507.  
  508. /** "isset" command descriptor */
  509. static struct command_descriptor isset_cmd =
  510. COMMAND_DESC ( struct isset_options, isset_opts, 1, 1, "<value>" );
  511.  
  512. /**
  513. * "isset" command
  514. *
  515. * @v argc Argument count
  516. * @v argv Argument list
  517. * @ret rc Return status code
  518. */
  519. static int isset_exec ( int argc, char **argv ) {
  520. struct isset_options opts;
  521. int rc;
  522.  
  523. /* Parse options */
  524. if ( ( rc = parse_options ( argc, argv, &isset_cmd, &opts ) ) != 0 )
  525. return rc;
  526.  
  527. /* Return success iff argument is non-empty */
  528. return ( argv[optind][0] ? 0 : -ENOENT );
  529. }
  530.  
  531. /** "isset" command */
  532. struct command isset_command __command = {
  533. .name = "isset",
  534. .exec = isset_exec,
  535. };
  536.  
  537. /** "iseq" options */
  538. struct iseq_options {};
  539.  
  540. /** "iseq" option list */
  541. static struct option_descriptor iseq_opts[] = {};
  542.  
  543. /** "iseq" command descriptor */
  544. static struct command_descriptor iseq_cmd =
  545. COMMAND_DESC ( struct iseq_options, iseq_opts, 2, 2,
  546. "<value1> <value2>" );
  547.  
  548. /**
  549. * "iseq" command
  550. *
  551. * @v argc Argument count
  552. * @v argv Argument list
  553. * @ret rc Return status code
  554. */
  555. static int iseq_exec ( int argc, char **argv ) {
  556. struct iseq_options opts;
  557. int rc;
  558.  
  559. /* Parse options */
  560. if ( ( rc = parse_options ( argc, argv, &iseq_cmd, &opts ) ) != 0 )
  561. return rc;
  562.  
  563. /* Return success iff arguments are equal */
  564. return ( ( strcmp ( argv[optind], argv[ optind + 1 ] ) == 0 ) ?
  565. 0 : -ERANGE );
  566. }
  567.  
  568. /** "iseq" command */
  569. struct command iseq_command __command = {
  570. .name = "iseq",
  571. .exec = iseq_exec,
  572. };
  573.  
  574. /** "sleep" options */
  575. struct sleep_options {};
  576.  
  577. /** "sleep" option list */
  578. static struct option_descriptor sleep_opts[] = {};
  579.  
  580. /** "sleep" command descriptor */
  581. static struct command_descriptor sleep_cmd =
  582. COMMAND_DESC ( struct sleep_options, sleep_opts, 1, 1, "<seconds>" );
  583.  
  584. /**
  585. * "sleep" command
  586. *
  587. * @v argc Argument count
  588. * @v argv Argument list
  589. * @ret rc Return status code
  590. */
  591. static int sleep_exec ( int argc, char **argv ) {
  592. struct sleep_options opts;
  593. unsigned int seconds;
  594. unsigned long start;
  595. unsigned long delay;
  596. int rc;
  597.  
  598. /* Parse options */
  599. if ( ( rc = parse_options ( argc, argv, &sleep_cmd, &opts ) ) != 0 )
  600. return rc;
  601.  
  602. /* Parse number of seconds */
  603. if ( ( rc = parse_integer ( argv[optind], &seconds ) ) != 0 )
  604. return rc;
  605.  
  606. /* Delay for specified number of seconds */
  607. start = currticks();
  608. delay = ( seconds * TICKS_PER_SEC );
  609. while ( ( currticks() - start ) <= delay ) {
  610. step();
  611. if ( iskey() && ( getchar() == CTRL_C ) )
  612. return -ECANCELED;
  613. cpu_nap();
  614. }
  615.  
  616. return 0;
  617. }
  618.  
  619. /** "sleep" command */
  620. struct command sleep_command __command = {
  621. .name = "sleep",
  622. .exec = sleep_exec,
  623. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement