/* -*- mode: C -*- Time-stamp: "2019-01-03 09:44:20 jemarch" * * File: testrec.c * Date: Fri Aug 23 21:41:00 2013 * * GNU recutils - testrec bash loadable builtin. * */ /* Copyright (C) 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2022 * Jose E. Marchesi */ /* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include "builtins.h" #include "shell.h" #include "common.h" #include "builtins/bashgetopt.h" /* The function implementing the builtin. It uses internal_getopt to parse options. It is the same as getopt(3), but it takes a pointer to a WORD_LIST. If the builtin takes no options, call no_options(list) before doing anything else. If it returns a non-zero value, your builtin should immediately return EX_USAGE. A builtin command returns EXECUTION_SUCCESS for success and EXECUTION_FAILURE to indicate failure. */ int testrec_builtin (WORD_LIST *list) { int res = EXECUTION_SUCCESS; char **argv; int argc; SHELL_VAR *var; rec_record_t record; rec_parser_t parser; char *record_str, *sex_str; /* Get arguments and verify them. */ argv = make_builtin_argv (list, &argc); if ((argc != 3) || ((strcmp (argv[0], "[%") == 0) && ((strlen (argv[2]) == 2) && ((argv[2][0] != '%') || (argv[2][1] != ']'))))) { fprintf (stderr, "Usage: [%% SEX %%]\n"); return EXECUTION_FAILURE; } sex_str = argv[1]; /* Get the record to operate on from the REPLY_REC environment variable. */ var = find_variable ("REPLY_REC"); if (!var) return EXECUTION_FAILURE; record_str = get_variable_value (var); parser = rec_parser_new_str (record_str, "REPLY_REC"); if (!parser || !rec_parse_record (parser, &record)) { fprintf (stderr, "testrec: error: invalid record in REPLY_REC\n"); return EXECUTION_FAILURE; } /* Apply the selection expression. */ { bool status = false; rec_sex_t sex = rec_sex_new (false); if (!sex) return EXECUTION_FAILURE; if (!rec_sex_compile (sex, sex_str)) { fprintf (stderr, "testrec: error: wrong selection expression\n"); return EXECUTION_FAILURE; } res = rec_sex_eval (sex, record, &status) ? EXECUTION_SUCCESS : EXECUTION_FAILURE; rec_sex_destroy (sex); } /* Cleanup. */ rec_record_destroy (record); return res; } /* An array of strings forming the `long' documentation for the builtin, which is printed by `help xxx'. It must end with a NULL. By convention, the first line is a short description. */ char *testrec_doc[] = { "Evaluate a selection expression on the record stored in REPLY_REC.", "", "Evaluates a given selection expression on the record stored in the\n\ REPLY_REC variable, if any.\n\ \n\ Exit Status:\n\ The return code is zero if the selection expression evaluates to\n\ true, -1 otherwise.\n", (char *) NULL }; /* The standard structure describing a builtin command. bash keeps an array of these structures. The flags must include BUILTIN_ENABLED so the builtin can be used. */ struct builtin testrec_struct = { "[%", /* builtin name */ testrec_builtin, /* function implementing the builtin */ BUILTIN_ENABLED, /* initial flags for builtin */ testrec_doc, /* array of long documentation strings. */ "testrec", /* usage synopsis; becomes short_doc */ 0 /* reserved for internal use */ };