NeoMutt  2025-09-05-55-g97fc89
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
filter.c File Reference

Expando filtering. More...

#include "config.h"
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "mutt/lib.h"
#include "gui/lib.h"
#include "expando.h"
#include "node.h"
#include "render.h"
+ Include dependency graph for filter.c:

Go to the source code of this file.

Functions

bool check_for_pipe (struct ExpandoNode *root)
 Should the Expando be piped to an external command?
 
void filter_text (struct Buffer *buf, char **env_list)
 Filter the text through an external command.
 
int expando_filter (const struct Expando *exp, const struct ExpandoRenderCallback *erc, void *data, MuttFormatFlags flags, int max_cols, char **env_list, struct Buffer *buf)
 Render an Expando and run the result through a filter.
 

Detailed Description

Expando filtering.

Authors
  • Richard Russon

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 http://www.gnu.org/licenses/.

Definition in file filter.c.

Function Documentation

◆ check_for_pipe()

bool check_for_pipe ( struct ExpandoNode * root)

Should the Expando be piped to an external command?

Parameters
rootRoot Node
Return values
trueYes, pipe it
  • Check the last Node is text
  • Check for a trailing | (pipe) character

Definition at line 49 of file filter.c.

50{
51 if (!root)
52 return false;
53
54 struct ExpandoNode *last = node_last(root);
55 if (!last || (last->type != ENT_TEXT))
56 return false;
57
58 size_t len = mutt_str_len(last->text);
59 if (len < 1)
60 return false;
61
62 if (last->text[len - 1] != '|')
63 return false;
64
65 // Count any preceding backslashes
66 int count = 0;
67 for (int i = len - 2; i >= 0; i--)
68 {
69 if (last->text[i] == '\\')
70 count++;
71 }
72
73 // The pipe character is escaped with a backslash
74 if ((count % 2) != 0)
75 return false;
76
77 return true;
78}
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:498
struct ExpandoNode * node_last(struct ExpandoNode *node)
Find the last Node in a tree.
Definition node.c:108
@ ENT_TEXT
Plain text.
Definition node.h:38
Basic Expando Node.
Definition node.h:67
const char * text
Node-specific text.
Definition node.h:73
enum ExpandoNodeType type
Type of Node, e.g. ENT_EXPANDO.
Definition node.h:68
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ filter_text()

void filter_text ( struct Buffer * buf,
char ** env_list )

Filter the text through an external command.

Parameters
[in,out]bufText
[in]env_listEnvironment

The text is passed unchanged to the shell. The first line of any output (minus the newline) is stored back in buf.

Definition at line 88 of file filter.c.

89{
90 // Trim the | (pipe) character
91 size_t len = buf_len(buf);
92 if (len == 0)
93 return;
94
95 if (buf->data[len - 1] == '|')
96 buf->data[len - 1] = '\0';
97
98 mutt_debug(LL_DEBUG3, "execute: %s\n", buf_string(buf));
99 FILE *fp_filter = NULL;
100 pid_t pid = filter_create(buf_string(buf), NULL, &fp_filter, NULL, env_list);
101 if (pid < 0)
102 return; // LCOV_EXCL_LINE
103
104 buf_reset(buf);
105 size_t n = fread(buf->data, 1, buf->dsize - 1, fp_filter);
106 mutt_file_fclose(&fp_filter);
107 buf_fix_dptr(buf);
108
109 int rc = filter_wait(pid);
110 if (rc != 0)
111 mutt_debug(LL_DEBUG1, "filter cmd exited code %d\n", rc);
112
113 if (n == 0)
114 {
115 mutt_debug(LL_DEBUG1, "error reading from filter: %s (errno=%d)\n",
116 strerror(errno), errno);
117 buf_reset(buf);
118 return;
119 }
120
121 char *nl = (char *) buf_find_char(buf, '\n');
122 if (nl)
123 *nl = '\0';
124 mutt_debug(LL_DEBUG3, "received: %s\n", buf_string(buf));
125}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:491
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition buffer.c:182
const char * buf_find_char(const struct Buffer *buf, const char c)
Return a pointer to a char found in the buffer.
Definition buffer.c:653
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_debug(LEVEL,...)
Definition logging2.h:90
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:46
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:44
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:220
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition filter.c:209
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expando_filter()

int expando_filter ( const struct Expando * exp,
const struct ExpandoRenderCallback * erc,
void * data,
MuttFormatFlags flags,
int max_cols,
char ** env_list,
struct Buffer * buf )

Render an Expando and run the result through a filter.

Parameters
[in]expExpando containing the expando tree
[in]ercExpando Render Callback functions
[in]dataCallback data
[in]flagsCallback flags
[in]max_colsNumber of screen columns (-1 means unlimited)
[in]env_listEnvironment to pass to filter
[out]bufBuffer in which to save string
Return values
objNumber of bytes written to buf and screen columns used

Definition at line 138 of file filter.c.

141{
142 if (!exp || !exp->node)
143 return 0;
144
145 struct ExpandoNode *node = exp->node;
146
147 bool is_pipe = check_for_pipe(node);
148 int old_cols = max_cols;
149 if (is_pipe)
150 max_cols = -1;
151
152 int rc = expando_render(exp, erc, data, flags, max_cols, buf);
153
154 if (!is_pipe)
155 return rc;
156
157 filter_text(buf, env_list);
158
159 // Strictly truncate to size
160 size_t width = 0;
161 size_t bytes = mutt_wstr_trunc(buf_string(buf), buf_len(buf), old_cols, &width);
162 buf->data[bytes] = '\0';
163
164 return width;
165}
size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
Work out how to truncate a widechar string.
Definition curs_lib.c:385
int expando_render(const struct Expando *exp, const struct ExpandoRenderCallback *erc, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Render an Expando + data into a string.
Definition expando.c:118
bool check_for_pipe(struct ExpandoNode *root)
Should the Expando be piped to an external command?
Definition filter.c:49
void filter_text(struct Buffer *buf, char **env_list)
Filter the text through an external command.
Definition filter.c:88
struct ExpandoNode * node
Parsed tree.
Definition expando.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function: