NeoMutt  2025-01-09-117-gace867
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
filter.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <errno.h>
31#include <stdbool.h>
32#include <stddef.h>
33#include <stdio.h>
34#include <string.h>
35#include <sys/types.h>
36#include "mutt/lib.h"
37#include "gui/lib.h"
38#include "expando.h"
39#include "node.h"
40#include "render.h"
41
50bool check_for_pipe(struct ExpandoNode *root)
51{
52 if (!root)
53 return false;
54
55 struct ExpandoNode *last = node_last(root);
56 if (!last || (last->type != ENT_TEXT))
57 return false;
58
59 size_t len = mutt_str_len(last->text);
60 if (len < 1)
61 return false;
62
63 if (last->text[len - 1] != '|')
64 return false;
65
66 // Count any preceding backslashes
67 int count = 0;
68 for (int i = len - 2; i >= 0; i--)
69 {
70 if (last->text[i] == '\\')
71 count++;
72 }
73
74 // The pipe character is escaped with a backslash
75 if ((count % 2) != 0)
76 return false;
77
78 return true;
79}
80
89void filter_text(struct Buffer *buf, char **env_list)
90{
91 // Trim the | (pipe) character
92 size_t len = buf_len(buf);
93 if (len == 0)
94 return;
95
96 if (buf->data[len - 1] == '|')
97 buf->data[len - 1] = '\0';
98
99 mutt_debug(LL_DEBUG3, "execute: %s\n", buf_string(buf));
100 FILE *fp_filter = NULL;
101 pid_t pid = filter_create(buf_string(buf), NULL, &fp_filter, NULL, env_list);
102 if (pid < 0)
103 return; // LCOV_EXCL_LINE
104
105 buf_reset(buf);
106 size_t n = fread(buf->data, 1, buf->dsize - 1, fp_filter);
107 mutt_file_fclose(&fp_filter);
108 buf_fix_dptr(buf);
109
110 int rc = filter_wait(pid);
111 if (rc != 0)
112 mutt_debug(LL_DEBUG1, "filter cmd exited code %d\n", rc);
113
114 if (n == 0)
115 {
116 mutt_debug(LL_DEBUG1, "error reading from filter: %s (errno=%d)\n",
117 strerror(errno), errno);
118 buf_reset(buf);
119 return;
120 }
121
122 char *nl = (char *) buf_find_char(buf, '\n');
123 if (nl)
124 *nl = '\0';
125 mutt_debug(LL_DEBUG3, "received: %s\n", buf_string(buf));
126}
127
139int expando_filter(const struct Expando *exp, const struct ExpandoRenderCallback *erc,
140 void *data, MuttFormatFlags flags, int max_cols,
141 char **env_list, struct Buffer *buf)
142{
143 if (!exp || !exp->node)
144 return 0;
145
146 struct ExpandoNode *node = exp->node;
147
148 bool is_pipe = check_for_pipe(node);
149 int old_cols = max_cols;
150 if (is_pipe)
151 max_cols = -1;
152
153 int rc = expando_render(exp, erc, data, flags, max_cols, buf);
154
155 if (!is_pipe)
156 return rc;
157
158 filter_text(buf, env_list);
159
160 // Strictly truncate to size
161 size_t width = 0;
162 size_t bytes = mutt_wstr_trunc(buf_string(buf), buf_len(buf), old_cols, &width);
163 buf->data[bytes] = '\0';
164
165 return width;
166}
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
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:50
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.
Definition: filter.c:139
void filter_text(struct Buffer *buf, char **env_list)
Filter the text through an external command.
Definition: filter.c:89
#define mutt_file_fclose(FP)
Definition: file.h:139
#define mutt_debug(LEVEL,...)
Definition: logging2.h:90
Convenience wrapper for the gui headers.
@ 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
Convenience wrapper for the library headers.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:497
struct ExpandoNode * node_last(struct ExpandoNode *node)
Find the last Node in a tree.
Definition: node.c:108
Basic Expando Node.
@ ENT_TEXT
Plain text.
Definition: node.h:38
Render Expandos using Data.
uint8_t MuttFormatFlags
Flags for expando_render(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: render.h:32
Sidebar Expando definitions.
String manipulation buffer.
Definition: buffer.h:36
size_t dsize
Length of data.
Definition: buffer.h:39
char * data
Pointer to data.
Definition: buffer.h:37
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
Parsed Expando trees.
Definition: expando.h:41
struct ExpandoNode * node
Parsed tree.
Definition: expando.h:43