]> git.proxmox.com Git - grub2.git/blob - grub-core/commands/regexp.c
wildcard: Mark unused argument as such.
[grub2.git] / grub-core / commands / regexp.c
1 /* regexp.c -- The regexp command. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2005,2007 Free Software Foundation, Inc.
5 *
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <grub/dl.h>
21 #include <grub/misc.h>
22 #include <grub/mm.h>
23 #include <grub/err.h>
24 #include <grub/env.h>
25 #include <grub/extcmd.h>
26 #include <grub/i18n.h>
27 #include <grub/script_sh.h>
28 #include <regex.h>
29
30 GRUB_MOD_LICENSE ("GPLv3+");
31
32 static const struct grub_arg_option options[] =
33 {
34 { "set", 's', GRUB_ARG_OPTION_REPEATABLE,
35 /* TRANSLATORS: in regexp you can mark some
36 groups with parentheses. These groups are
37 then numbered and you can save some of
38 them in variables. In other programs
39 those components aree often referenced with
40 back slash, e.g. \1. Compare
41 sed -e 's,\([a-z][a-z]*\),lowercase=\1,g'
42 The whole matching component is saved in VARNAME, not its number.
43 */
44 N_("Store matched component NUMBER in VARNAME."),
45 N_("[NUMBER:]VARNAME"), ARG_TYPE_STRING },
46 { 0, 0, 0, 0, 0, 0 }
47 };
48
49 static grub_err_t
50 setvar (char *str, char *v, regmatch_t *m)
51 {
52 char ch;
53 grub_err_t err;
54 ch = str[m->rm_eo];
55 str[m->rm_eo] = '\0';
56 err = grub_env_set (v, str + m->rm_so);
57 str[m->rm_eo] = ch;
58 return err;
59 }
60
61 static grub_err_t
62 set_matches (char **varnames, char *str, grub_size_t nmatches,
63 regmatch_t *matches)
64 {
65 int i;
66 char *p;
67 char *q;
68 grub_err_t err;
69 unsigned long j;
70
71 for (i = 0; varnames && varnames[i]; i++)
72 {
73 err = GRUB_ERR_NONE;
74 p = grub_strchr (varnames[i], ':');
75 if (! p)
76 {
77 /* varname w/o index defaults to 1 */
78 if (nmatches < 2 || matches[1].rm_so == -1)
79 grub_env_unset (varnames[i]);
80 else
81 err = setvar (str, varnames[i], &matches[1]);
82 }
83 else
84 {
85 j = grub_strtoul (varnames[i], &q, 10);
86 if (q != p)
87 return grub_error (GRUB_ERR_BAD_ARGUMENT,
88 "invalid variable name format %s", varnames[i]);
89
90 if (nmatches <= j || matches[j].rm_so == -1)
91 grub_env_unset (p + 1);
92 else
93 err = setvar (str, p + 1, &matches[j]);
94 }
95
96 if (err != GRUB_ERR_NONE)
97 return err;
98 }
99 return GRUB_ERR_NONE;
100 }
101
102 static grub_err_t
103 grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args)
104 {
105 regex_t regex;
106 int ret;
107 grub_size_t s;
108 char *comperr;
109 grub_err_t err;
110 regmatch_t *matches = 0;
111
112 if (argc != 2)
113 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
114
115 ret = regcomp (&regex, args[0], REG_EXTENDED);
116 if (ret)
117 goto fail;
118
119 matches = grub_zalloc (sizeof (*matches) * (regex.re_nsub + 1));
120 if (! matches)
121 goto fail;
122
123 ret = regexec (&regex, args[1], regex.re_nsub + 1, matches, 0);
124 if (!ret)
125 {
126 err = set_matches (ctxt->state[0].args, args[1],
127 regex.re_nsub + 1, matches);
128 regfree (&regex);
129 grub_free (matches);
130 return err;
131 }
132
133 fail:
134 grub_free (matches);
135 s = regerror (ret, &regex, 0, 0);
136 comperr = grub_malloc (s);
137 if (!comperr)
138 {
139 regfree (&regex);
140 return grub_errno;
141 }
142 regerror (ret, &regex, comperr, s);
143 err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr);
144 regfree (&regex);
145 grub_free (comperr);
146 return err;
147 }
148
149 static grub_extcmd_t cmd;
150 \f
151 GRUB_MOD_INIT(regexp)
152 {
153 cmd = grub_register_extcmd ("regexp", grub_cmd_regexp, 0,
154 /* TRANSLATORS: This are two arguments. So it's
155 two separate units to translate and pay
156 attention not to reverse them. */
157 N_("REGEXP STRING"),
158 N_("Test if REGEXP matches STRING."), options);
159
160 /* Setup GRUB script wildcard translator. */
161 grub_wildcard_translator = &grub_filename_translator;
162 }
163
164 GRUB_MOD_FINI(regexp)
165 {
166 grub_unregister_extcmd (cmd);
167 grub_wildcard_translator = 0;
168 }