NeoMutt  2024-10-02-37-gfa9146
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 <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "mutt/lib.h"
#include "gui/lib.h"
#include "expando.h"
#include "globals.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)
 Filter the text through an external command.
 
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.
 

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 51 of file filter.c.

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}
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
@ 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)

Filter the text through an external command.

Parameters
[in,out]bufText

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 89 of file filter.c.

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}
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
#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
@ 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
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 ExpandoRenderData rdata,
void *  data,
MuttFormatFlags  flags,
int  max_cols,
struct Buffer buf 
)

Render an Expando and run the result through a filter.

Parameters
[in]expExpando containing the expando tree
[in]rdataExpando render data
[in]dataCallback data
[in]flagsCallback flags
[in]max_colsNumber of screen columns (-1 means unlimited)
[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.

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 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
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
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: