#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <uv.h>
#include "auto/config.h"
#include "klib/kvec.h"
#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/errors.h"
#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/event/defs.h"
#include "nvim/event/libuv_proc.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/proc.h"
#include "nvim/event/rstream.h"
#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
#include "nvim/ex_cmds.h"
#include "nvim/fileio.h"
#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/shell.h"
#include "nvim/os/signal.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/vim_defs.h"
#define NS_1_SECOND 1000000000U // 1 second, in nanoseconds
#define OUT_DATA_THRESHOLD 1024 * 10U // 10KB, "a few screenfuls" of data.
#define SHELL_SPECIAL "\t \"&'$;<>()\\|"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/shell.c.generated.h"
#endif
static void save_patterns(int num_pat, char **pat, int *num_file, char ***file)
{
*file = xmalloc((size_t)num_pat * sizeof(char *));
for (int i = 0; i < num_pat; i++) {
char *s = xstrdup(pat[i]);
// Be compatible with expand_filename(): halve the number of
// backslashes.
backslash_halve(s);
(*file)[i] = s;
}
*num_file = num_pat;
}
static bool have_wildcard(int num, char **file)
{
for (int i = 0; i < num; i++) {
if (path_has_wildcard(file[i])) {
return true;
}
}
return false;
}
static bool have_dollars(int num, char **file)
{
for (int i = 0; i < num; i++) {
if (vim_strchr(file[i], '$') != NULL) {
return true;
}
}
return false;
}
/// Performs wildcard pattern matching using the shell.
///
/// @param num_pat is the number of input patterns.
/// @param pat is an array of pointers to input patterns.
/// @param[out] num_file is pointer to number of matched file names.
/// Set to the number of pointers in *file.
/// @param[out] file is pointer to array of pointers to matched file names.
/// Memory pointed to by the initial value of *file will
/// not be freed.
/// Set to NULL if FAIL is returned. Otherwise points to
/// allocated memory.
/// @param flags is a combination of EW_* flags used in
/// expand_wildcards().
/// If matching fails but EW_NOTFOUND is set in flags or
/// there are no wildcards, the patterns from pat are
/// copied into *file.
///
/// @returns OK for success or FAIL for error.
int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, int flags)
FUNC_ATTR_NONNULL_ARG(3)
FUNC_ATTR_NONNULL_ARG(4)
{
int i;
size_t len;
char *p;
char *extra_shell_arg = NULL;
int shellopts = kShellOptExpand | kShellOptSilent;
int j;
char *tempname;
#define STYLE_ECHO 0 // use "echo", the default
#define STYLE_GLOB 1 // use "glob", for csh
#define STYLE_VIMGLOB 2 // use "vimglob", for Posix sh
#define STYLE_PRINT 3 // use "print -N", for zsh
#define STYLE_BT 4 // `cmd` expansion, execute the pattern directly
#define STYLE_GLOBSTAR 5 // use extended shell glob for bash (this uses extended
// globbing functionality with globstar, needs bash > 4)
int shell_style = STYLE_ECHO;
int check_spaces;
static bool did_find_nul = false;
bool ampersand = false;
// vimglob() function to define for Posix shell
static char *sh_vimglob_func =
"vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >";
// vimglob() function with globstar setting enabled, only for bash >= 4.X
static char *sh_globstar_opt =
"[[ ${BASH_VERSINFO[0]} -ge 4 ]] && shopt -s globstar; &quo
|