1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker * It comes originally from the musl libc project and is licensed under the
4*0d6140beSAndroid Build Coastguard Worker * terms of the MIT license.
5*0d6140beSAndroid Build Coastguard Worker *
6*0d6140beSAndroid Build Coastguard Worker * Copyringht (C) 2023 Rich Felker and the musl authors
7*0d6140beSAndroid Build Coastguard Worker * Adjusted for flashrom by Thomas Heijligen<[email protected]>
8*0d6140beSAndroid Build Coastguard Worker *
9*0d6140beSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
10*0d6140beSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to deal
11*0d6140beSAndroid Build Coastguard Worker * in the Software without restriction, including without limitation the rights
12*0d6140beSAndroid Build Coastguard Worker * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13*0d6140beSAndroid Build Coastguard Worker * copies of the Software, and to permit persons to whom the Software is
14*0d6140beSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
15*0d6140beSAndroid Build Coastguard Worker *
16*0d6140beSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
17*0d6140beSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
18*0d6140beSAndroid Build Coastguard Worker *
19*0d6140beSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20*0d6140beSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21*0d6140beSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22*0d6140beSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23*0d6140beSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24*0d6140beSAndroid Build Coastguard Worker * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25*0d6140beSAndroid Build Coastguard Worker * SOFTWARE.
26*0d6140beSAndroid Build Coastguard Worker */
27*0d6140beSAndroid Build Coastguard Worker
28*0d6140beSAndroid Build Coastguard Worker #include <unistd.h>
29*0d6140beSAndroid Build Coastguard Worker #include <wchar.h>
30*0d6140beSAndroid Build Coastguard Worker #include <string.h>
31*0d6140beSAndroid Build Coastguard Worker #include <limits.h>
32*0d6140beSAndroid Build Coastguard Worker #include <stdlib.h>
33*0d6140beSAndroid Build Coastguard Worker #include "cli_classic.h"
34*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
35*0d6140beSAndroid Build Coastguard Worker
36*0d6140beSAndroid Build Coastguard Worker char *optarg;
37*0d6140beSAndroid Build Coastguard Worker int optind=1, opterr=1, optopt, optpos;
38*0d6140beSAndroid Build Coastguard Worker
getopt_msg(const char * a,const char * b,const char * c,size_t l)39*0d6140beSAndroid Build Coastguard Worker static void getopt_msg(const char *a, const char *b, const char *c, size_t l)
40*0d6140beSAndroid Build Coastguard Worker {
41*0d6140beSAndroid Build Coastguard Worker msg_gerr("%s%s%*c\n", a, b, l, c);
42*0d6140beSAndroid Build Coastguard Worker }
43*0d6140beSAndroid Build Coastguard Worker
getopt(int argc,char * const argv[],const char * optstring)44*0d6140beSAndroid Build Coastguard Worker int getopt(int argc, char * const argv[], const char *optstring)
45*0d6140beSAndroid Build Coastguard Worker {
46*0d6140beSAndroid Build Coastguard Worker int i;
47*0d6140beSAndroid Build Coastguard Worker wchar_t c, d;
48*0d6140beSAndroid Build Coastguard Worker int k, l;
49*0d6140beSAndroid Build Coastguard Worker char *optchar;
50*0d6140beSAndroid Build Coastguard Worker
51*0d6140beSAndroid Build Coastguard Worker if (!optind) {
52*0d6140beSAndroid Build Coastguard Worker optind = 1;
53*0d6140beSAndroid Build Coastguard Worker optpos = 0;
54*0d6140beSAndroid Build Coastguard Worker }
55*0d6140beSAndroid Build Coastguard Worker
56*0d6140beSAndroid Build Coastguard Worker if (optind >= argc || !argv[optind])
57*0d6140beSAndroid Build Coastguard Worker return -1;
58*0d6140beSAndroid Build Coastguard Worker
59*0d6140beSAndroid Build Coastguard Worker if (argv[optind][0] != '-') {
60*0d6140beSAndroid Build Coastguard Worker if (optstring[0] == '-') {
61*0d6140beSAndroid Build Coastguard Worker optarg = argv[optind++];
62*0d6140beSAndroid Build Coastguard Worker return 1;
63*0d6140beSAndroid Build Coastguard Worker }
64*0d6140beSAndroid Build Coastguard Worker return -1;
65*0d6140beSAndroid Build Coastguard Worker }
66*0d6140beSAndroid Build Coastguard Worker
67*0d6140beSAndroid Build Coastguard Worker if (!argv[optind][1])
68*0d6140beSAndroid Build Coastguard Worker return -1;
69*0d6140beSAndroid Build Coastguard Worker
70*0d6140beSAndroid Build Coastguard Worker if (argv[optind][1] == '-' && !argv[optind][2])
71*0d6140beSAndroid Build Coastguard Worker return optind++, -1;
72*0d6140beSAndroid Build Coastguard Worker
73*0d6140beSAndroid Build Coastguard Worker if (!optpos)
74*0d6140beSAndroid Build Coastguard Worker optpos++;
75*0d6140beSAndroid Build Coastguard Worker if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) {
76*0d6140beSAndroid Build Coastguard Worker k = 1;
77*0d6140beSAndroid Build Coastguard Worker c = 0xfffd; /* replacement char */
78*0d6140beSAndroid Build Coastguard Worker }
79*0d6140beSAndroid Build Coastguard Worker optchar = argv[optind]+optpos;
80*0d6140beSAndroid Build Coastguard Worker optpos += k;
81*0d6140beSAndroid Build Coastguard Worker
82*0d6140beSAndroid Build Coastguard Worker if (!argv[optind][optpos]) {
83*0d6140beSAndroid Build Coastguard Worker optind++;
84*0d6140beSAndroid Build Coastguard Worker optpos = 0;
85*0d6140beSAndroid Build Coastguard Worker }
86*0d6140beSAndroid Build Coastguard Worker
87*0d6140beSAndroid Build Coastguard Worker if (optstring[0] == '-' || optstring[0] == '+')
88*0d6140beSAndroid Build Coastguard Worker optstring++;
89*0d6140beSAndroid Build Coastguard Worker
90*0d6140beSAndroid Build Coastguard Worker i = 0;
91*0d6140beSAndroid Build Coastguard Worker d = 0;
92*0d6140beSAndroid Build Coastguard Worker do {
93*0d6140beSAndroid Build Coastguard Worker l = mbtowc(&d, optstring+i, MB_LEN_MAX);
94*0d6140beSAndroid Build Coastguard Worker if (l>0) i+=l; else i++;
95*0d6140beSAndroid Build Coastguard Worker } while (l && d != c);
96*0d6140beSAndroid Build Coastguard Worker
97*0d6140beSAndroid Build Coastguard Worker if (d != c || c == ':') {
98*0d6140beSAndroid Build Coastguard Worker optopt = c;
99*0d6140beSAndroid Build Coastguard Worker if (optstring[0] != ':' && opterr)
100*0d6140beSAndroid Build Coastguard Worker getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
101*0d6140beSAndroid Build Coastguard Worker return '?';
102*0d6140beSAndroid Build Coastguard Worker }
103*0d6140beSAndroid Build Coastguard Worker if (optstring[i] == ':') {
104*0d6140beSAndroid Build Coastguard Worker optarg = 0;
105*0d6140beSAndroid Build Coastguard Worker if (optstring[i+1] != ':' || optpos) {
106*0d6140beSAndroid Build Coastguard Worker optarg = argv[optind++] + optpos;
107*0d6140beSAndroid Build Coastguard Worker optpos = 0;
108*0d6140beSAndroid Build Coastguard Worker }
109*0d6140beSAndroid Build Coastguard Worker if (optind > argc) {
110*0d6140beSAndroid Build Coastguard Worker optopt = c;
111*0d6140beSAndroid Build Coastguard Worker if (optstring[0] == ':')
112*0d6140beSAndroid Build Coastguard Worker return ':';
113*0d6140beSAndroid Build Coastguard Worker if (opterr) getopt_msg(argv[0],
114*0d6140beSAndroid Build Coastguard Worker ": option requires an argument: ",
115*0d6140beSAndroid Build Coastguard Worker optchar, k);
116*0d6140beSAndroid Build Coastguard Worker return '?';
117*0d6140beSAndroid Build Coastguard Worker }
118*0d6140beSAndroid Build Coastguard Worker }
119*0d6140beSAndroid Build Coastguard Worker return c;
120*0d6140beSAndroid Build Coastguard Worker }
121*0d6140beSAndroid Build Coastguard Worker
__getopt_long_core(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * idx,int longonly)122*0d6140beSAndroid Build Coastguard Worker static int __getopt_long_core(int argc, char *const *argv, const char *optstring,
123*0d6140beSAndroid Build Coastguard Worker const struct option *longopts, int *idx, int longonly)
124*0d6140beSAndroid Build Coastguard Worker {
125*0d6140beSAndroid Build Coastguard Worker optarg = 0;
126*0d6140beSAndroid Build Coastguard Worker if (longopts && argv[optind][0] == '-' &&
127*0d6140beSAndroid Build Coastguard Worker ((longonly && argv[optind][1] && argv[optind][1] != '-') ||
128*0d6140beSAndroid Build Coastguard Worker (argv[optind][1] == '-' && argv[optind][2])))
129*0d6140beSAndroid Build Coastguard Worker {
130*0d6140beSAndroid Build Coastguard Worker int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
131*0d6140beSAndroid Build Coastguard Worker int i, cnt, match = 0;
132*0d6140beSAndroid Build Coastguard Worker char *arg = NULL, *opt, *start = argv[optind]+1;
133*0d6140beSAndroid Build Coastguard Worker for (cnt=i=0; longopts[i].name; i++) {
134*0d6140beSAndroid Build Coastguard Worker const char *name = longopts[i].name;
135*0d6140beSAndroid Build Coastguard Worker opt = start;
136*0d6140beSAndroid Build Coastguard Worker if (*opt == '-') opt++;
137*0d6140beSAndroid Build Coastguard Worker while (*opt && *opt != '=' && *opt == *name)
138*0d6140beSAndroid Build Coastguard Worker name++, opt++;
139*0d6140beSAndroid Build Coastguard Worker if (*opt && *opt != '=') continue;
140*0d6140beSAndroid Build Coastguard Worker arg = opt;
141*0d6140beSAndroid Build Coastguard Worker match = i;
142*0d6140beSAndroid Build Coastguard Worker if (!*name) {
143*0d6140beSAndroid Build Coastguard Worker cnt = 1;
144*0d6140beSAndroid Build Coastguard Worker break;
145*0d6140beSAndroid Build Coastguard Worker }
146*0d6140beSAndroid Build Coastguard Worker cnt++;
147*0d6140beSAndroid Build Coastguard Worker }
148*0d6140beSAndroid Build Coastguard Worker if (cnt==1 && longonly && arg-start == mblen(start, MB_LEN_MAX)) {
149*0d6140beSAndroid Build Coastguard Worker int l = arg-start;
150*0d6140beSAndroid Build Coastguard Worker for (i=0; optstring[i]; i++) {
151*0d6140beSAndroid Build Coastguard Worker int j;
152*0d6140beSAndroid Build Coastguard Worker for (j=0; j<l && start[j]==optstring[i+j]; j++);
153*0d6140beSAndroid Build Coastguard Worker if (j==l) {
154*0d6140beSAndroid Build Coastguard Worker cnt++;
155*0d6140beSAndroid Build Coastguard Worker break;
156*0d6140beSAndroid Build Coastguard Worker }
157*0d6140beSAndroid Build Coastguard Worker }
158*0d6140beSAndroid Build Coastguard Worker }
159*0d6140beSAndroid Build Coastguard Worker if (cnt==1) {
160*0d6140beSAndroid Build Coastguard Worker i = match;
161*0d6140beSAndroid Build Coastguard Worker opt = arg;
162*0d6140beSAndroid Build Coastguard Worker optind++;
163*0d6140beSAndroid Build Coastguard Worker if (*opt == '=') {
164*0d6140beSAndroid Build Coastguard Worker if (!longopts[i].has_arg) {
165*0d6140beSAndroid Build Coastguard Worker optopt = longopts[i].val;
166*0d6140beSAndroid Build Coastguard Worker if (colon || !opterr)
167*0d6140beSAndroid Build Coastguard Worker return '?';
168*0d6140beSAndroid Build Coastguard Worker getopt_msg(argv[0],
169*0d6140beSAndroid Build Coastguard Worker ": option does not take an argument: ",
170*0d6140beSAndroid Build Coastguard Worker longopts[i].name,
171*0d6140beSAndroid Build Coastguard Worker strlen(longopts[i].name));
172*0d6140beSAndroid Build Coastguard Worker return '?';
173*0d6140beSAndroid Build Coastguard Worker }
174*0d6140beSAndroid Build Coastguard Worker optarg = opt+1;
175*0d6140beSAndroid Build Coastguard Worker } else if (longopts[i].has_arg == required_argument) {
176*0d6140beSAndroid Build Coastguard Worker if (!(optarg = argv[optind])) {
177*0d6140beSAndroid Build Coastguard Worker optopt = longopts[i].val;
178*0d6140beSAndroid Build Coastguard Worker if (colon) return ':';
179*0d6140beSAndroid Build Coastguard Worker if (!opterr) return '?';
180*0d6140beSAndroid Build Coastguard Worker getopt_msg(argv[0],
181*0d6140beSAndroid Build Coastguard Worker ": option requires an argument: ",
182*0d6140beSAndroid Build Coastguard Worker longopts[i].name,
183*0d6140beSAndroid Build Coastguard Worker strlen(longopts[i].name));
184*0d6140beSAndroid Build Coastguard Worker return '?';
185*0d6140beSAndroid Build Coastguard Worker }
186*0d6140beSAndroid Build Coastguard Worker optind++;
187*0d6140beSAndroid Build Coastguard Worker }
188*0d6140beSAndroid Build Coastguard Worker if (idx)
189*0d6140beSAndroid Build Coastguard Worker *idx = i;
190*0d6140beSAndroid Build Coastguard Worker if (longopts[i].flag) {
191*0d6140beSAndroid Build Coastguard Worker *longopts[i].flag = longopts[i].val;
192*0d6140beSAndroid Build Coastguard Worker return 0;
193*0d6140beSAndroid Build Coastguard Worker }
194*0d6140beSAndroid Build Coastguard Worker return longopts[i].val;
195*0d6140beSAndroid Build Coastguard Worker }
196*0d6140beSAndroid Build Coastguard Worker if (argv[optind][1] == '-') {
197*0d6140beSAndroid Build Coastguard Worker optopt = 0;
198*0d6140beSAndroid Build Coastguard Worker if (!colon && opterr)
199*0d6140beSAndroid Build Coastguard Worker getopt_msg(argv[0], cnt ?
200*0d6140beSAndroid Build Coastguard Worker ": option is ambiguous: " :
201*0d6140beSAndroid Build Coastguard Worker ": unrecognized option: ",
202*0d6140beSAndroid Build Coastguard Worker argv[optind]+2,
203*0d6140beSAndroid Build Coastguard Worker strlen(argv[optind]+2));
204*0d6140beSAndroid Build Coastguard Worker optind++;
205*0d6140beSAndroid Build Coastguard Worker return '?';
206*0d6140beSAndroid Build Coastguard Worker }
207*0d6140beSAndroid Build Coastguard Worker }
208*0d6140beSAndroid Build Coastguard Worker return getopt(argc, argv, optstring);
209*0d6140beSAndroid Build Coastguard Worker }
210*0d6140beSAndroid Build Coastguard Worker
permute(char * const * argv,int dest,int src)211*0d6140beSAndroid Build Coastguard Worker static void permute(char *const *argv, int dest, int src)
212*0d6140beSAndroid Build Coastguard Worker {
213*0d6140beSAndroid Build Coastguard Worker char **av = (char **)argv;
214*0d6140beSAndroid Build Coastguard Worker char *tmp = av[src];
215*0d6140beSAndroid Build Coastguard Worker int i;
216*0d6140beSAndroid Build Coastguard Worker for (i=src; i>dest; i--)
217*0d6140beSAndroid Build Coastguard Worker av[i] = av[i-1];
218*0d6140beSAndroid Build Coastguard Worker av[dest] = tmp;
219*0d6140beSAndroid Build Coastguard Worker }
220*0d6140beSAndroid Build Coastguard Worker
__getopt_long(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * idx,int longonly)221*0d6140beSAndroid Build Coastguard Worker static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
222*0d6140beSAndroid Build Coastguard Worker {
223*0d6140beSAndroid Build Coastguard Worker int ret, skipped, resumed;
224*0d6140beSAndroid Build Coastguard Worker if (!optind) {
225*0d6140beSAndroid Build Coastguard Worker optind = 1;
226*0d6140beSAndroid Build Coastguard Worker optpos = 0;
227*0d6140beSAndroid Build Coastguard Worker }
228*0d6140beSAndroid Build Coastguard Worker
229*0d6140beSAndroid Build Coastguard Worker if (optind >= argc || !argv[optind])
230*0d6140beSAndroid Build Coastguard Worker return -1;
231*0d6140beSAndroid Build Coastguard Worker skipped = optind;
232*0d6140beSAndroid Build Coastguard Worker if (optstring[0] != '+' && optstring[0] != '-') {
233*0d6140beSAndroid Build Coastguard Worker int i;
234*0d6140beSAndroid Build Coastguard Worker for (i=optind; ; i++) {
235*0d6140beSAndroid Build Coastguard Worker if (i >= argc || !argv[i])
236*0d6140beSAndroid Build Coastguard Worker return -1;
237*0d6140beSAndroid Build Coastguard Worker if (argv[i][0] == '-' && argv[i][1])
238*0d6140beSAndroid Build Coastguard Worker break;
239*0d6140beSAndroid Build Coastguard Worker }
240*0d6140beSAndroid Build Coastguard Worker optind = i;
241*0d6140beSAndroid Build Coastguard Worker }
242*0d6140beSAndroid Build Coastguard Worker resumed = optind;
243*0d6140beSAndroid Build Coastguard Worker ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly);
244*0d6140beSAndroid Build Coastguard Worker if (resumed > skipped) {
245*0d6140beSAndroid Build Coastguard Worker int i, cnt = optind-resumed;
246*0d6140beSAndroid Build Coastguard Worker for (i=0; i<cnt; i++)
247*0d6140beSAndroid Build Coastguard Worker permute(argv, skipped, optind-1);
248*0d6140beSAndroid Build Coastguard Worker optind = skipped + cnt;
249*0d6140beSAndroid Build Coastguard Worker }
250*0d6140beSAndroid Build Coastguard Worker return ret;
251*0d6140beSAndroid Build Coastguard Worker }
252*0d6140beSAndroid Build Coastguard Worker
getopt_long(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * idx)253*0d6140beSAndroid Build Coastguard Worker int getopt_long(int argc, char *const *argv, const char *optstring,
254*0d6140beSAndroid Build Coastguard Worker const struct option *longopts, int *idx)
255*0d6140beSAndroid Build Coastguard Worker {
256*0d6140beSAndroid Build Coastguard Worker return __getopt_long(argc, argv, optstring, longopts, idx, 0);
257*0d6140beSAndroid Build Coastguard Worker }
258*0d6140beSAndroid Build Coastguard Worker
getopt_long_only(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * idx)259*0d6140beSAndroid Build Coastguard Worker int getopt_long_only(int argc, char *const *argv, const char *optstring,
260*0d6140beSAndroid Build Coastguard Worker const struct option *longopts, int *idx)
261*0d6140beSAndroid Build Coastguard Worker {
262*0d6140beSAndroid Build Coastguard Worker return __getopt_long(argc, argv, optstring, longopts, idx, 1);
263*0d6140beSAndroid Build Coastguard Worker }
264