2 * ========================================================================
3 * Copyright 2013-2022 Eduardo Chappa
4 * Copyright 2006-2007 University of Washington
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
18 #include "../c-client/c-client.h"
20 #include "../pith/osdep/canaccess.h"
21 #include "../pith/osdep/color.h"
22 #include "../pith/osdep/pipe.h"
24 #include "../pith/charconv/utf8.h"
25 #include "../pith/charconv/filesys.h"
27 #include "../pith/status.h"
28 #include "../pith/pipe.h"
29 #include "../pith/debug.h"
30 #include "../pith/detach.h"
37 /* Internal prototypes */
38 int test_message_with_cmd(MAILSTREAM
*, long, char *, long, int *);
42 * pattern_filter_command - filter given message
45 pattern_filter_command(char **cat_cmds
, SEARCHSET
*srchset
, MAILSTREAM
*stream
, long cat_lim
, INTVL_S
*cat
)
52 char *just_arg0
= NULL
;
53 char *cmd_start
, *cmd_end
;
56 if(!(cat_cmds
&& cat_cmds
[0]))
59 just_one
= !(cat_cmds
[1]);
61 /* find the first command that exists on this host */
62 for(l
= cat_cmds
; l
&& *l
; l
++){
67 *cmd_start
&& isspace(*cmd_start
); cmd_start
++)
70 for(cmd_end
= cmd_start
+1;
71 *cmd_end
&& !isspace(*cmd_end
); cmd_end
++)
74 just_arg0
= (char *) fs_get((cmd_end
-cmd_start
+1)
76 strncpy(just_arg0
, cmd_start
, cmd_end
- cmd_start
);
77 just_arg0
[cmd_end
- cmd_start
] = '\0';
80 if(valid_filter_command(&just_arg0
))
84 if(can_access(just_arg0
, ACCESS_EXISTS
) != 0)
85 q_status_message1(SM_ORDER
, 0, 3,
86 "\"%s\" does not exist",
89 q_status_message1(SM_ORDER
, 0, 3,
90 "\"%s\" is not executable",
95 fs_give((void **) &just_arg0
);
97 fs_give((void **) &cmd
);
101 if(!just_arg0
&& !just_one
)
102 q_status_message(SM_ORDER
, 0, 3,
103 "None of the category cmds exists and is executable");
106 * If category_cmd isn't executable, it isn't a match.
108 if(!just_arg0
|| !cmd
){
110 * If we couldn't run the pipe command,
111 * we declare no match
113 for(s
= srchset
; s
; s
= s
->next
)
114 for(i
= s
->first
; i
<= s
->last
; i
++)
115 if(i
> 0L && stream
&& i
<= stream
->nmsgs
116 && (mc
=mail_elt(stream
, i
)) && mc
->searched
)
120 for(s
= srchset
; s
; s
= s
->next
)
121 for(i
= s
->first
; i
<= s
->last
; i
++)
122 if(i
> 0L && stream
&& i
<= stream
->nmsgs
123 && (mc
=mail_elt(stream
, i
)) && mc
->searched
){
126 * If there was an error, or the exitval is out of
127 * range, then it is not a match.
128 * Default range is (0,0),
129 * which is right for matching
132 if(test_message_with_cmd(stream
, i
, cmd
,
133 cat_lim
, &exitval
) != 0)
141 for(iv
= cat
; iv
; iv
= iv
->next
)
142 if((long) exitval
>= iv
->imin
143 && (long) exitval
<= iv
->imax
)
147 mc
->searched
= NIL
; /* not in any interval */
150 /* default to interval containing only zero */
158 fs_give((void **) &just_arg0
);
161 fs_give((void **) &cmd
);
167 * Returns 0 if ok, -1 if not ok.
168 * If ok then exitval contains the exit value of the cmd.
171 test_message_with_cmd(MAILSTREAM
*stream
, long int msgno
, char *cmd
,
172 long char_limit
, /* limit testing to this many chars from body */
177 int status
= 0, flags
, err
= 0;
178 char *resultfile
= NULL
, *pipe_err
;
182 flags
= PIPE_WRITE
| PIPE_NOSHELL
| PIPE_STDERR
| PIPE_NONEWMAIL
;
184 dprint((7, "test_message_with_cmd(msgno=%ld cmd=%s)\n",
187 if((tpipe
= cmd_pipe_open(cmd
, &resultfile
, flags
, &pc
))){
189 prime_raw_pipe_getc(stream
, msgno
, char_limit
, FT_PEEK
);
191 gf_link_filter(gf_nvtnl_local
, NULL
);
192 if((pipe_err
= gf_pipe(raw_pipe_getc
, pc
)) != NULL
){
193 q_status_message1(SM_ORDER
|SM_DING
, 3, 3,
194 "Internal Error: %.200s", pipe_err
);
199 * Don't call new_mail in close_system_pipe because we're probably
200 * already here from new_mail and we don't want to get loopy.
202 status
= close_system_pipe(&tpipe
, exitval
, pipe_callback
);
205 * This is a place where the command can put its output, which we
206 * are not interested in.
209 our_unlink(resultfile
);
210 fs_give((void **) &resultfile
);
213 return((err
|| status
) ? -1 : 0);