fw_env_main.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2000-2008
  4. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  5. */
  6. /*
  7. * Command line user interface to firmware (=U-Boot) environment.
  8. *
  9. * Implements:
  10. * fw_printenv [ -a key ] [[ -n name ] | [ name ... ]]
  11. * - prints the value of a single environment variable
  12. * "name", the ``name=value'' pairs of one or more
  13. * environment variables "name", or the whole
  14. * environment if no names are specified.
  15. * fw_setenv [ -a key ] name [ value ... ]
  16. * - If a name without any values is given, the variable
  17. * with this name is deleted from the environment;
  18. * otherwise, all "value" arguments are concatenated,
  19. * separated by single blank characters, and the
  20. * resulting string is assigned to the environment
  21. * variable "name"
  22. *
  23. * If '-a key' is specified, the env block is encrypted with AES 128 CBC.
  24. * The 'key' argument is in the format of 32 hexadecimal numbers (16 bytes
  25. * of AES key), eg. '-a aabbccddeeff00112233445566778899'.
  26. */
  27. #include <env.h>
  28. #include <fcntl.h>
  29. #include <getopt.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <sys/file.h>
  34. #include <unistd.h>
  35. #include <version.h>
  36. #include "fw_env_private.h"
  37. #include "fw_env.h"
  38. #define CMD_PRINTENV "fw_printenv"
  39. #define CMD_SETENV "fw_setenv"
  40. static int do_printenv;
  41. static struct option long_options[] = {
  42. {"config", required_argument, NULL, 'c'},
  43. {"help", no_argument, NULL, 'h'},
  44. {"script", required_argument, NULL, 's'},
  45. {"noheader", no_argument, NULL, 'n'},
  46. {"lock", required_argument, NULL, 'l'},
  47. {"version", no_argument, NULL, 'v'},
  48. {NULL, 0, NULL, 0}
  49. };
  50. static struct env_opts env_opts;
  51. /* setenv options */
  52. static int noheader;
  53. /* getenv options */
  54. static char *script_file;
  55. void usage_printenv(void)
  56. {
  57. fprintf(stderr,
  58. "Usage: fw_printenv [OPTIONS]... [VARIABLE]...\n"
  59. "Print variables from U-Boot environment\n"
  60. "\n"
  61. " -h, --help print this help.\n"
  62. " -v, --version display version\n"
  63. #ifdef CONFIG_FILE
  64. " -c, --config configuration file, default:" CONFIG_FILE "\n"
  65. #endif
  66. " -n, --noheader do not repeat variable name in output\n"
  67. " -l, --lock lock node, default:/var/lock\n"
  68. "\n");
  69. }
  70. void usage_env_set(void)
  71. {
  72. fprintf(stderr,
  73. "Usage: fw_setenv [OPTIONS]... [VARIABLE]...\n"
  74. "Modify variables in U-Boot environment\n"
  75. "\n"
  76. " -h, --help print this help.\n"
  77. " -v, --version display version\n"
  78. #ifdef CONFIG_FILE
  79. " -c, --config configuration file, default:" CONFIG_FILE "\n"
  80. #endif
  81. " -l, --lock lock node, default:/var/lock\n"
  82. " -s, --script batch mode to minimize writes\n"
  83. "\n"
  84. "Examples:\n"
  85. " fw_setenv foo bar set variable foo equal bar\n"
  86. " fw_setenv foo clear variable foo\n"
  87. " fw_setenv --script file run batch script\n"
  88. "\n"
  89. "Script Syntax:\n"
  90. " key [space] value\n"
  91. " lines starting with '#' are treated as comment\n"
  92. "\n"
  93. " A variable without value will be deleted. Any number of spaces are\n"
  94. " allowed between key and value. Space inside of the value is treated\n"
  95. " as part of the value itself.\n"
  96. "\n"
  97. "Script Example:\n"
  98. " netdev eth0\n"
  99. " kernel_addr 400000\n"
  100. " foo empty empty empty empty empty empty\n"
  101. " bar\n"
  102. "\n");
  103. }
  104. static void parse_common_args(int argc, char *argv[])
  105. {
  106. int c;
  107. #ifdef CONFIG_FILE
  108. env_opts.config_file = CONFIG_FILE;
  109. #endif
  110. while ((c = getopt_long(argc, argv, ":a:c:l:h:v", long_options, NULL)) !=
  111. EOF) {
  112. switch (c) {
  113. #ifdef CONFIG_FILE
  114. case 'c':
  115. env_opts.config_file = optarg;
  116. break;
  117. #endif
  118. case 'l':
  119. env_opts.lockname = optarg;
  120. break;
  121. case 'h':
  122. do_printenv ? usage_printenv() : usage_env_set();
  123. exit(EXIT_SUCCESS);
  124. break;
  125. case 'v':
  126. fprintf(stderr, "Compiled with " U_BOOT_VERSION "\n");
  127. exit(EXIT_SUCCESS);
  128. break;
  129. default:
  130. /* ignore unknown options */
  131. break;
  132. }
  133. }
  134. /* Reset getopt for the next pass. */
  135. opterr = 1;
  136. optind = 1;
  137. }
  138. int parse_printenv_args(int argc, char *argv[])
  139. {
  140. int c;
  141. parse_common_args(argc, argv);
  142. while ((c = getopt_long(argc, argv, "a:c:ns:l:h:v", long_options, NULL))
  143. != EOF) {
  144. switch (c) {
  145. case 'n':
  146. noheader = 1;
  147. break;
  148. case 'a':
  149. case 'c':
  150. case 'h':
  151. case 'l':
  152. /* ignore common options */
  153. break;
  154. default: /* '?' */
  155. usage_printenv();
  156. exit(EXIT_FAILURE);
  157. break;
  158. }
  159. }
  160. return 0;
  161. }
  162. int parse_setenv_args(int argc, char *argv[])
  163. {
  164. int c;
  165. parse_common_args(argc, argv);
  166. while ((c = getopt_long(argc, argv, "a:c:ns:l:h:v", long_options, NULL))
  167. != EOF) {
  168. switch (c) {
  169. case 's':
  170. script_file = optarg;
  171. break;
  172. case 'a':
  173. case 'c':
  174. case 'h':
  175. case 'l':
  176. /* ignore common options */
  177. break;
  178. default: /* '?' */
  179. usage_env_set();
  180. exit(EXIT_FAILURE);
  181. break;
  182. }
  183. }
  184. return 0;
  185. }
  186. int main(int argc, char *argv[])
  187. {
  188. char *lockname = "/var/lock/" CMD_PRINTENV ".lock";
  189. int lockfd = -1;
  190. int retval = EXIT_SUCCESS;
  191. char *_cmdname;
  192. _cmdname = *argv;
  193. if (strrchr(_cmdname, '/') != NULL)
  194. _cmdname = strrchr(_cmdname, '/') + 1;
  195. if (strcmp(_cmdname, CMD_PRINTENV) == 0) {
  196. do_printenv = 1;
  197. } else if (strcmp(_cmdname, CMD_SETENV) == 0) {
  198. do_printenv = 0;
  199. } else {
  200. fprintf(stderr,
  201. "Identity crisis - may be called as `%s' or as `%s' but not as `%s'\n",
  202. CMD_PRINTENV, CMD_SETENV, _cmdname);
  203. exit(EXIT_FAILURE);
  204. }
  205. if (do_printenv) {
  206. if (parse_printenv_args(argc, argv))
  207. exit(EXIT_FAILURE);
  208. } else {
  209. if (parse_setenv_args(argc, argv))
  210. exit(EXIT_FAILURE);
  211. }
  212. /* shift parsed flags, jump to non-option arguments */
  213. argc -= optind;
  214. argv += optind;
  215. if (env_opts.lockname) {
  216. lockname = malloc(strlen(env_opts.lockname) +
  217. sizeof(CMD_PRINTENV) + 10);
  218. if (!lockname) {
  219. fprintf(stderr, "Unable allocate memory");
  220. exit(EXIT_FAILURE);
  221. }
  222. sprintf(lockname, "%s/%s.lock",
  223. env_opts.lockname, CMD_PRINTENV);
  224. }
  225. lockfd = open(lockname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  226. if (-1 == lockfd) {
  227. fprintf(stderr, "Error opening lock file %s\n", lockname);
  228. return EXIT_FAILURE;
  229. }
  230. if (-1 == flock(lockfd, LOCK_EX)) {
  231. fprintf(stderr, "Error locking file %s\n", lockname);
  232. close(lockfd);
  233. return EXIT_FAILURE;
  234. }
  235. if (do_printenv) {
  236. if (fw_printenv(argc, argv, noheader, &env_opts) != 0)
  237. retval = EXIT_FAILURE;
  238. } else {
  239. if (!script_file) {
  240. if (fw_env_set(argc, argv, &env_opts) != 0)
  241. retval = EXIT_FAILURE;
  242. } else {
  243. if (fw_parse_script(script_file, &env_opts) != 0)
  244. retval = EXIT_FAILURE;
  245. }
  246. }
  247. if (env_opts.lockname)
  248. free(lockname);
  249. flock(lockfd, LOCK_UN);
  250. close(lockfd);
  251. return retval;
  252. }