/* returns TRUE if 'string' matches the 'regexp' (or is a superstring of it, when we don't HAVE_REGEX_H). The regexp is recompiled with every call, which doesn't really hurt as this function is not called often: at most twice for every prompt. 'string' and 'regexp' may be NULL (in which case FALSE is returned) Only used for the --forget-regexp and the --prompt-regexp options */ int match_regexp (const char *string, const char *regexp, int case_insensitive) { int result; if (!regexp || !string) return FALSE; #ifndef HAVE_REGEX_H { static int been_warned = 0; char *metachars = "*()+?"; char *lc_string = (case_insensitive ? lowercase(string) : mysavestring(string)); char *lc_regexp = (case_insensitive ? lowercase(regexp) : mysavestring(regexp)); if (scan_metacharacters(regexp, metachars) && !been_warned++) /* warn only once if the user specifies a metacharacter */ mywarn("one of the regexp metacharacters \"%s\" occurs in regexp(?) \"%s\"\n" " ...but on your platform, regexp matching is not supported!", metachars, regexp); result = mystrstr(lc_string, lc_regexp); free(lc_string); free(lc_regexp); } #else { regex_t *compiled_regexp = mymalloc(sizeof(regex_t)); int compile_error = regcomp(compiled_regexp, regexp, REG_EXTENDED|REG_NOSUB|(case_insensitive ? REG_ICASE : 0)); if (compile_error) { int size = regerror(compile_error, compiled_regexp, NULL, 0); char *error_message = mymalloc(size); regerror(compile_error, compiled_regexp, error_message, size); errno=0; myerror("in regexp \"%s\": %s", regexp, error_message); } else { result = !regexec(compiled_regexp, string, 0, NULL, 0); free(compiled_regexp); } } #endif return result; }
void spawn_filter(const char *filter_command) { int input_pipe_fds[2]; int output_pipe_fds[2]; mypipe(input_pipe_fds); filter_input_fd = input_pipe_fds[1]; /* rlwrap writes filter input to this */ mypipe(output_pipe_fds); filter_output_fd = output_pipe_fds[0]; /* rlwrap reads filter output from here */ DPRINTF1(DEBUG_FILTERING, "preparing to spawn filter <%s>", filter_command); assert(!command_pid || signal_handlers_were_installed); /* if there is a command, then signal handlers are installed */ if ((filter_pid = fork()) < 0) myerror(FATAL|USE_ERRNO, "Cannot spawn filter '%s'", filter_command); else if (filter_pid == 0) { /* child */ int signals_to_allow[] = {SIGPIPE, SIGCHLD, SIGALRM, SIGUSR1, SIGUSR2}; char **argv; unblock_signals(signals_to_allow); /* when we run a pager from a filter we want to catch these */ DEBUG_RANDOM_SLEEP; i_am_child = TRUE; /* set environment for filter (it needs to know at least the file descriptors for its input and output) */ if (!getenv("RLWRAP_FILTERDIR")) mysetenv("RLWRAP_FILTERDIR", add2strings(DATADIR,"/rlwrap/filters")); mysetenv("PATH", add3strings(getenv("RLWRAP_FILTERDIR"),":",getenv("PATH"))); mysetenv("RLWRAP_VERSION", VERSION); mysetenv("RLWRAP_COMMAND_PID", as_string(command_pid)); mysetenv("RLWRAP_COMMAND_LINE", command_line); if (impatient_prompt) mysetenv("RLWRAP_IMPATIENT", "1"); mysetenv("RLWRAP_INPUT_PIPE_FD", as_string(input_pipe_fds[0])); mysetenv("RLWRAP_OUTPUT_PIPE_FD", as_string(output_pipe_fds[1])); mysetenv("RLWRAP_MASTER_PTY_FD", as_string(master_pty_fd)); close(filter_input_fd); close(filter_output_fd); if (scan_metacharacters(filter_command, "'|\"><")) { /* if filter_command contains shell metacharacters, let the shell unglue them */ char *exec_command = add3strings("exec", " ", filter_command); argv = list4("sh", "-c", exec_command, NULL); } else { /* if not, split and feed to execvp directly (cheaper, better error message) */ argv = split_with(filter_command, " "); } assert(argv[0]); if(execvp(argv[0], argv) < 0) { char *sorry = add3strings("Cannot exec filter '", argv[0], add2strings("': ", strerror(errno))); write_message(output_pipe_fds[1], TAG_ERROR, sorry, "to stdout"); /* this will kill rlwrap */ mymicrosleep(100 * 1000); /* 100 sec for rlwrap to go away should be enough */ exit (-1); } assert(!"not reached"); } else { DEBUG_RANDOM_SLEEP; signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE - we have othere ways to deal with filter death */ DPRINTF1(DEBUG_FILTERING, "spawned filter with pid %d", filter_pid); close (input_pipe_fds[0]); close (output_pipe_fds[1]); } }