NeoMutt  2024-04-25-127-g771158
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 for a trailing | (pipe) character
  • Check the first Node is text

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 if (!last->start || !last->end)
61 return false;
62
63 int len = last->end - last->start;
64 if (len < 1)
65 return false;
66
67 if (last->start[len - 1] != '|')
68 return false;
69
70 // Count any preceding backslashes
71 int count = 0;
72 for (int i = len - 2; i >= 0; i--)
73 {
74 if (last->start[i] == '\\')
75 count++;
76 }
77
78 // The pipe character is escaped with a backslash
79 if ((count % 2) != 0)
80 return false;
81
82 return true;
83}
struct ExpandoNode * node_last(struct ExpandoNode *node)
Find the last Node in a tree.
Definition: node.c:138
@ ENT_TEXT
Plain text.
Definition: node.h:38
Basic Expando Node.
Definition: node.h:69
const char * end
End of string data.
Definition: node.h:80
enum ExpandoNodeType type
Type of Node, e.g. ENT_EXPANDO.
Definition: node.h:70
const char * start
Start of string data.
Definition: node.h:79
+ 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 92 of file filter.c.

93{
94 if (buf_is_empty(buf))
95 return;
96
97 // Trim the | (pipe) character
98 size_t len = buf_len(buf);
99 if (buf->data[len - 1] == '|')
100 buf->data[len - 1] = '\0';
101
102 mutt_debug(LL_DEBUG3, "execute: %s\n", buf_string(buf));
103 FILE *fp_filter = NULL;
104 pid_t pid = filter_create(buf_string(buf), NULL, &fp_filter, NULL, EnvList);
105 if (pid < 0)
106 return; // LCOV_EXCL_LINE
107
108 buf_reset(buf);
109 size_t n = fread(buf->data, 1, buf->dsize - 1, fp_filter);
110 mutt_file_fclose(&fp_filter);
111 buf_fix_dptr(buf);
112
113 int rc = filter_wait(pid);
114 if (rc != 0)
115 mutt_debug(LL_DEBUG1, "filter cmd exited code %d\n", rc);
116
117 if (n == 0)
118 {
119 mutt_debug(LL_DEBUG1, "error reading from filter: %s (errno=%d)\n",
120 strerror(errno), errno);
121 buf_reset(buf);
122 return;
123 }
124
125 char *nl = (char *) buf_find_char(buf, '\n');
126 if (nl)
127 *nl = '\0';
128 mutt_debug(LL_DEBUG3, "received: %s\n", buf_string(buf));
129}
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:76
#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 141 of file filter.c.

143{
144 if (!exp || !exp->node)
145 return 0;
146
147 struct ExpandoNode *node = exp->node;
148
149 bool is_pipe = check_for_pipe(node);
150 int old_cols = max_cols;
151 if (is_pipe)
152 max_cols = -1;
153
154 int rc = expando_render(exp, rdata, data, flags, max_cols, buf);
155
156 if (!is_pipe)
157 return rc;
158
159 filter_text(buf);
160
161 // Strictly truncate to size
162 size_t width = 0;
163 size_t bytes = mutt_wstr_trunc(buf_string(buf), buf_len(buf), old_cols, &width);
164 buf->data[bytes] = '\0';
165
166 return width;
167}
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:92
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:109
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: