tools: env: introduce setenv/printenv argument structs
[platform/kernel/u-boot.git] / tools / env / fw_env_main.c
1 /*
2  * (C) Copyright 2000-2008
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 /*
9  * Command line user interface to firmware (=U-Boot) environment.
10  *
11  * Implements:
12  *      fw_printenv [ -a key ] [[ -n name ] | [ name ... ]]
13  *              - prints the value of a single environment variable
14  *                "name", the ``name=value'' pairs of one or more
15  *                environment variables "name", or the whole
16  *                environment if no names are specified.
17  *      fw_setenv [ -a key ] name [ value ... ]
18  *              - If a name without any values is given, the variable
19  *                with this name is deleted from the environment;
20  *                otherwise, all "value" arguments are concatenated,
21  *                separated by single blank characters, and the
22  *                resulting string is assigned to the environment
23  *                variable "name"
24  *
25  * If '-a key' is specified, the env block is encrypted with AES 128 CBC.
26  * The 'key' argument is in the format of 32 hexadecimal numbers (16 bytes
27  * of AES key), eg. '-a aabbccddeeff00112233445566778899'.
28  */
29
30 #include <fcntl.h>
31 #include <getopt.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <sys/file.h>
36 #include <unistd.h>
37 #include "fw_env.h"
38
39 #define CMD_PRINTENV    "fw_printenv"
40 #define CMD_SETENV      "fw_setenv"
41
42 static struct option long_options[] = {
43         {"script", required_argument, NULL, 's'},
44         {"help", no_argument, NULL, 'h'},
45         {NULL, 0, NULL, 0}
46 };
47
48 struct printenv_args printenv_args;
49 struct setenv_args setenv_args;
50
51 void usage(void)
52 {
53
54         fprintf(stderr, "fw_printenv/fw_setenv, "
55                 "a command line interface to U-Boot environment\n\n"
56 #ifndef CONFIG_FILE
57                 "usage:\tfw_printenv [-a key] [-n] [variable name]\n"
58                 "\tfw_setenv [-a key] [variable name] [variable value]\n"
59 #else
60                 "usage:\tfw_printenv [-c /my/fw_env.config] [-a key] [-n] [variable name]\n"
61                 "\tfw_setenv [-c /my/fw_env.config] [-a key] [variable name] [variable value]\n"
62 #endif
63                 "\tfw_setenv -s [ file ]\n"
64                 "\tfw_setenv -s - < [ file ]\n\n"
65                 "The file passed as argument contains only pairs "
66                 "name / value\n"
67                 "Example:\n"
68                 "# Any line starting with # is treated as comment\n"
69                 "\n"
70                 "\t      netdev         eth0\n"
71                 "\t      kernel_addr    400000\n"
72                 "\t      var1\n"
73                 "\t      var2          The quick brown fox jumps over the "
74                 "lazy dog\n"
75                 "\n"
76                 "A variable without value will be dropped. It is possible\n"
77                 "to put any number of spaces between the fields, but any\n"
78                 "space inside the value is treated as part of the value "
79                 "itself.\n\n"
80         );
81 }
82
83 int parse_printenv_args(int argc, char *argv[])
84 {
85         int c;
86
87         while ((c = getopt_long (argc, argv, "a:c:ns:h",
88                 long_options, NULL)) != EOF) {
89                 switch (c) {
90                 case 'a':
91                         /* AES key, handled later */
92                         break;
93                 case 'c':
94                         /* handled later */
95                         break;
96                 case 'n':
97                         /* handled in fw_printenv */
98                         break;
99                 case 'h':
100                         usage();
101                         exit(EXIT_SUCCESS);
102                         break;
103                 default: /* '?' */
104                         usage();
105                         exit(EXIT_FAILURE);
106                         break;
107                 }
108         }
109         return 0;
110 }
111
112 int parse_setenv_args(int argc, char *argv[])
113 {
114         int c;
115
116         while ((c = getopt_long (argc, argv, "a:c:ns:h",
117                 long_options, NULL)) != EOF) {
118                 switch (c) {
119                 case 'a':
120                         /* AES key, handled later */
121                         break;
122                 case 'c':
123                         /* handled later */
124                         break;
125                 case 's':
126                         setenv_args.script_file = optarg;
127                         break;
128                 case 'h':
129                         usage();
130                         exit(EXIT_SUCCESS);
131                         break;
132                 default: /* '?' */
133                         usage();
134                         exit(EXIT_FAILURE);
135                         break;
136                 }
137         }
138         return 0;
139 }
140
141 int main(int argc, char *argv[])
142 {
143         char *cmdname = *argv;
144         const char *lockname = "/var/lock/" CMD_PRINTENV ".lock";
145         int lockfd = -1;
146         int retval = EXIT_SUCCESS;
147
148         if (strrchr(cmdname, '/') != NULL)
149                 cmdname = strrchr(cmdname, '/') + 1;
150
151         if (strcmp(cmdname, CMD_PRINTENV) == 0) {
152                 if (parse_printenv_args(argc, argv))
153                         exit(EXIT_FAILURE);
154         } else if (strcmp(cmdname, CMD_SETENV) == 0) {
155                 if (parse_setenv_args(argc, argv))
156                         exit(EXIT_FAILURE);
157         } else {
158                 fprintf(stderr,
159                         "Identity crisis - may be called as `%s' or as `%s' but not as `%s'\n",
160                         CMD_PRINTENV, CMD_SETENV, cmdname);
161                 exit(EXIT_FAILURE);
162         }
163
164         lockfd = open(lockname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
165         if (-1 == lockfd) {
166                 fprintf(stderr, "Error opening lock file %s\n", lockname);
167                 return EXIT_FAILURE;
168         }
169
170         if (-1 == flock(lockfd, LOCK_EX)) {
171                 fprintf(stderr, "Error locking file %s\n", lockname);
172                 close(lockfd);
173                 return EXIT_FAILURE;
174         }
175
176         if (strcmp(cmdname, CMD_PRINTENV) == 0) {
177                 if (fw_printenv(argc, argv) != 0)
178                         retval = EXIT_FAILURE;
179         } else if (strcmp(cmdname, CMD_SETENV) == 0) {
180                 if (!setenv_args.script_file) {
181                         if (fw_setenv(argc, argv) != 0)
182                                 retval = EXIT_FAILURE;
183                 } else {
184                         if (fw_parse_script(setenv_args.script_file) != 0)
185                                 retval = EXIT_FAILURE;
186                 }
187         }
188
189         flock(lockfd, LOCK_UN);
190         close(lockfd);
191         return retval;
192 }