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