2N/A/* regexp.c -- The regexp command. */
2N/A/*
2N/A * GRUB -- GRand Unified Bootloader
2N/A * Copyright (C) 2005,2007 Free Software Foundation, Inc.
2N/A *
2N/A * GRUB is free software: you can redistribute it and/or modify
2N/A * it under the terms of the GNU General Public License as published by
2N/A * the Free Software Foundation, either version 3 of the License, or
2N/A * (at your option) any later version.
2N/A *
2N/A * GRUB is distributed in the hope that it will be useful,
2N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of
2N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2N/A * GNU General Public License for more details.
2N/A *
2N/A * You should have received a copy of the GNU General Public License
2N/A * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
2N/A */
2N/A
2N/A#include <grub/dl.h>
2N/A#include <grub/misc.h>
2N/A#include <grub/mm.h>
2N/A#include <grub/err.h>
2N/A#include <grub/env.h>
2N/A#include <grub/extcmd.h>
2N/A#include <grub/i18n.h>
2N/A#include <grub/script_sh.h>
2N/A#include <regex.h>
2N/A
2N/AGRUB_MOD_LICENSE ("GPLv3+");
2N/A
2N/Astatic const struct grub_arg_option options[] =
2N/A {
2N/A { "set", 's', GRUB_ARG_OPTION_REPEATABLE,
2N/A N_("Variable names to update with matches."),
2N/A N_("[NUMBER:]VARNAME"), ARG_TYPE_STRING },
2N/A { 0, 0, 0, 0, 0, 0 }
2N/A };
2N/A
2N/Astatic grub_err_t
2N/Aset_matches (char **varnames, char *str, grub_size_t nmatches,
2N/A regmatch_t *matches)
2N/A{
2N/A int i;
2N/A char ch;
2N/A char *p;
2N/A char *q;
2N/A grub_err_t err;
2N/A unsigned long j;
2N/A
2N/A auto void setvar (char *v, regmatch_t *m);
2N/A void setvar (char *v, regmatch_t *m)
2N/A {
2N/A ch = str[m->rm_eo];
2N/A str[m->rm_eo] = '\0';
2N/A err = grub_env_set (v, str + m->rm_so);
2N/A str[m->rm_eo] = ch;
2N/A }
2N/A
2N/A for (i = 0; varnames && varnames[i]; i++)
2N/A {
2N/A if (! (p = grub_strchr (varnames[i], ':')))
2N/A {
2N/A /* varname w/o index defaults to 1 */
2N/A if (nmatches < 2 || matches[1].rm_so == -1)
2N/A grub_env_unset (varnames[i]);
2N/A else
2N/A setvar (varnames[i], &matches[1]);
2N/A }
2N/A else
2N/A {
2N/A j = grub_strtoul (varnames[i], &q, 10);
2N/A if (q != p)
2N/A return grub_error (GRUB_ERR_BAD_ARGUMENT,
2N/A "invalid variable name format %s", varnames[i]);
2N/A
2N/A if (nmatches <= j || matches[j].rm_so == -1)
2N/A grub_env_unset (p + 1);
2N/A else
2N/A setvar (p + 1, &matches[j]);
2N/A }
2N/A
2N/A if (err != GRUB_ERR_NONE)
2N/A return err;
2N/A }
2N/A return GRUB_ERR_NONE;
2N/A}
2N/A
2N/Astatic grub_err_t
2N/Agrub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args)
2N/A{
2N/A regex_t regex;
2N/A int ret;
2N/A grub_size_t s;
2N/A char *comperr;
2N/A grub_err_t err;
2N/A regmatch_t *matches = 0;
2N/A
2N/A if (argc != 2)
2N/A return grub_error (GRUB_ERR_BAD_ARGUMENT, "2 arguments expected");
2N/A
2N/A ret = regcomp (&regex, args[0], REG_EXTENDED);
2N/A if (ret)
2N/A goto fail;
2N/A
2N/A matches = grub_zalloc (sizeof (*matches) * (regex.re_nsub + 1));
2N/A if (! matches)
2N/A goto fail;
2N/A
2N/A ret = regexec (&regex, args[1], regex.re_nsub + 1, matches, 0);
2N/A if (!ret)
2N/A {
2N/A err = set_matches (ctxt->state[0].args, args[1],
2N/A regex.re_nsub + 1, matches);
2N/A regfree (&regex);
2N/A grub_free (matches);
2N/A return err;
2N/A }
2N/A
2N/A fail:
2N/A grub_free (matches);
2N/A s = regerror (ret, &regex, 0, 0);
2N/A comperr = grub_malloc (s);
2N/A if (!comperr)
2N/A {
2N/A regfree (&regex);
2N/A return grub_errno;
2N/A }
2N/A regerror (ret, &regex, comperr, s);
2N/A err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr);
2N/A regfree (&regex);
2N/A grub_free (comperr);
2N/A return err;
2N/A}
2N/A
2N/Astatic grub_extcmd_t cmd;
2N/A
2N/AGRUB_MOD_INIT(regexp)
2N/A{
2N/A cmd = grub_register_extcmd ("regexp", grub_cmd_regexp, 0, N_("REGEXP STRING"),
2N/A N_("Test if REGEXP matches STRING."), options);
2N/A
2N/A /* Setup GRUB script wildcard translator. */
2N/A grub_wildcard_translator = &grub_filename_translator;
2N/A}
2N/A
2N/AGRUB_MOD_FINI(regexp)
2N/A{
2N/A grub_unregister_extcmd (cmd);
2N/A grub_wildcard_translator = 0;
2N/A}