Avoid unused static function warning on non-mingw!
[xapian.git] / xapian-applications / omega / runfilter.h
blob94d3aa644d74b20411d62f47ca4c723e7d6bfe67
1 /** @file
2 * @brief run an external filter and capture its output in a std::string.
3 */
4 /* Copyright (C) 2007,2013,2015,2019,2024 Olly Betts
6 * This program 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 2 of the License, or
9 * (at your option) any later version.
11 * This program 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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifndef OMEGA_INCLUDED_RUNFILTER_H
22 #define OMEGA_INCLUDED_RUNFILTER_H
24 #include <string>
25 #include <cstdio>
27 /// Exception thrown if we encounter a read error.
28 struct ReadError {
29 const char* msg = NULL;
30 int status;
31 explicit ReadError(const char * m) : msg(m) { }
32 explicit ReadError(int s) : status(s) { }
33 std::string str() const {
34 if (msg) return msg;
35 char buf[32];
36 std::snprintf(buf, sizeof(buf), "0x%08x", status);
37 return buf;
41 /// Exception thrown if the filter program isn't found.
42 struct NoSuchFilter { };
44 /** Analyse if a command needs the shell.
46 * The return value of this function can be passed as the second argument of
47 * run_filter()/stdout_to_string().
49 bool command_needs_shell(const char * p);
51 /// Initialise the runfilter module.
52 void runfilter_init();
54 /** Run command @a cmd, optionally capturing its stdout.
56 * @param fd_in FD for piped input, or -1 for input from file.
57 * @param cmd The command to run as a NULL terminated argv array.
58 * @param out Pointer to std::string to put stdout in or NULL to
59 * discard stdout. (default: NULL)
60 * @param alt_status Exit status to treat as success in addition to 0
61 * (default: Only treat exit status 0 as success).
63 * If the command isn't installed (detected by exit status 127) then
64 * NoSuchFilter is thrown.
66 * If the command fails to completed successfully (detected by an exit status
67 * other than 0 or alt_status) then ReadError is thrown.
69 void run_filter(int fd_in,
70 const char* const cmd[],
71 std::string* out = nullptr,
72 int alt_status = 0);
74 /** Run command @a cmd, optionally capturing its stdout.
76 * @param fd_in FD for piped input, or -1 for input from file.
77 * @param cmd The command to run.
78 * @param use_shell If false, try to avoid using a shell to run the command.
79 * @param out Pointer to std::string to put stdout in or NULL to
80 * discard stdout. (default: NULL)
81 * @param alt_status Exit status to treat as success in addition to 0
82 * (default: Only treat exit status 0 as success).
84 * This is like the overloaded version taking an argv array except that
85 * it takes the command as a single string, plus a use_shell flag
86 * indicating whether the command string can be run without a shell.
88 * Note: use_shell=false mode makes some assumptions about the command:
90 * * only single quotes are used (double quotes and backslash quoting are
91 * not currently handled, aside from in the four character sequence '\''
92 * within single quotes).
93 * * the following redirections are supported, but they must be unquoted and
94 * appear exactly as shown, and each be a separate word in the command:
95 * >/dev/null 2>/dev/null 2>&1 1>&2
96 * * environment variables set before the command are handled correctly,
97 * for example: LANG=C some-command
99 * The command_needs_shell() function above can be used to check a command,
100 * but is somewhat more conservative than what this function actually
101 * supports.
103 * Currently the shell is only actually avoided for systems with both fork()
104 * and socketpair(). Other systems will ignore use_shell and always use the
105 * same code path (which may or may not involve some analog of the Unix
106 * shell).
108 * If the command isn't installed (detected by exit status 127) then
109 * NoSuchFilter is thrown.
111 * If the command fails to completed successfully (detected by an exit status
112 * other than 0 or alt_status) then ReadError is thrown.
114 void run_filter(int fd_in,
115 const std::string& cmd,
116 bool use_shell,
117 std::string* out = nullptr,
118 int alt_status = 0);
120 static inline void
121 run_filter(const char* const cmd[],
122 std::string* out = nullptr,
123 int alt_status = 0)
125 run_filter(-1, cmd, out, alt_status);
128 static inline void
129 run_filter(const std::string& cmd,
130 bool use_shell,
131 std::string* out = nullptr,
132 int alt_status = 0)
134 run_filter(-1, cmd, use_shell, out, alt_status);
137 /** Run command @a cmd, capture its stdout, and return it as a std::string.
139 * This is a simple wrapper around run_filter().
141 static inline std::string
142 stdout_to_string(const char* const cmd[], int alt_status = 0)
144 std::string out;
145 run_filter(cmd, &out, alt_status);
146 return out;
149 /** Run command @a cmd, capture its stdout, and return it as a std::string.
151 * This is a simple wrapper around run_filter().
153 static inline std::string
154 stdout_to_string(const std::string& cmd, bool use_shell, int alt_status = 0)
156 std::string out;
157 run_filter(cmd, use_shell, &out, alt_status);
158 return out;
161 #endif // OMEGA_INCLUDED_RUNFILTER_H