NeoMutt  2024-10-02-37-gfa9146
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 "globals.h"
40#include "node.h"
41#include "render.h"
42
51bool check_for_pipe(struct ExpandoNode *root)
52{
53 if (!root)
54 return false;
55
56 struct ExpandoNode *last = node_last(root);
57 if (!last || (last->type != ENT_TEXT))
58 return false;
59
60 size_t len = mutt_str_len(last->text);
61 if (len < 1)
62 return false;
63
64 if (last->text[len - 1] != '|')
65 return false;
66
67 // Count any preceding backslashes
68 int count = 0;
69 for (int i = len - 2; i >= 0; i--)
70 {
71 if (last->text[i] == '\\')
72 count++;
73 }
74
75 // The pipe character is escaped with a backslash
76 if ((count % 2) != 0)
77 return false;
78
79 return true;
80}
81
89void filter_text(struct Buffer *buf)
90{
91 if (buf_is_empty(buf))
92 return;
93
94 // Trim the | (pipe) character
95 size_t len = buf_len(buf);
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, EnvList);
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
138int expando_filter(const struct Expando *exp, const struct ExpandoRenderData *rdata,
139 void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
140{
141 if (!exp || !exp->node)
142 return 0;
143
144 struct ExpandoNode *node = exp->node;
145
146 bool is_pipe = check_for_pipe(node);
147 int old_cols = max_cols;
148 if (is_pipe)
149 max_cols = -1;
150
151 int rc = expando_render(exp, rdata, data, flags, max_cols, buf);
152
153 if (!is_pipe)
154 return rc;
155
156 filter_text(buf);
157
158 // Strictly truncate to size
159 size_t width = 0;
160 size_t bytes = mutt_wstr_trunc(buf_string(buf), buf_len(buf), old_cols, &width);
161 buf->data[bytes] = '\0';
162
163 return width;
164}
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
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
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:655
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:383
int expando_filter(const struct Expando *exp, const struct ExpandoRenderData *rdata, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Render an Expando and run the result through a filter.
Definition: filter.c:138
bool check_for_pipe(struct ExpandoNode *root)
Should the Expando be piped to an external command?
Definition: filter.c:51
void filter_text(struct Buffer *buf)
Filter the text through an external command.
Definition: filter.c:89
int expando_render(const struct Expando *exp, const struct ExpandoRenderData *rdata, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Render an Expando + data into a string.
Definition: expando.c:124
Parsed Expando.
#define mutt_file_fclose(FP)
Definition: file.h:138
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:75
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
Convenience wrapper for the gui headers.
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
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:496
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
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