1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: pattern.c 169 2006-10-04 23:26:48Z hubert@u.washington.edu $";
5 * ========================================================================
6 * Copyright 2013-2018 Eduardo Chappa
7 * Copyright 2006-2007 University of Washington
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * ========================================================================
21 #include "../c-client/c-client.h"
23 #include "../pith/osdep/canaccess.h"
24 #include "../pith/osdep/color.h"
25 #include "../pith/osdep/pipe.h"
27 #include "../pith/charconv/utf8.h"
28 #include "../pith/charconv/filesys.h"
30 #include "../pith/status.h"
31 #include "../pith/pipe.h"
32 #include "../pith/debug.h"
33 #include "../pith/detach.h"
40 /* Internal prototypes */
41 int test_message_with_cmd(MAILSTREAM
*, long, char *, long, int *);
45 * pattern_filter_command - filter given message
48 pattern_filter_command(char **cat_cmds
, SEARCHSET
*srchset
, MAILSTREAM
*stream
, long cat_lim
, INTVL_S
*cat
)
55 char *just_arg0
= NULL
;
56 char *cmd_start
, *cmd_end
;
59 if(!(cat_cmds
&& cat_cmds
[0]))
62 just_one
= !(cat_cmds
[1]);
64 /* find the first command that exists on this host */
65 for(l
= cat_cmds
; l
&& *l
; l
++){
70 *cmd_start
&& isspace(*cmd_start
); cmd_start
++)
73 for(cmd_end
= cmd_start
+1;
74 *cmd_end
&& !isspace(*cmd_end
); cmd_end
++)
77 just_arg0
= (char *) fs_get((cmd_end
-cmd_start
+1)
79 strncpy(just_arg0
, cmd_start
, cmd_end
- cmd_start
);
80 just_arg0
[cmd_end
- cmd_start
] = '\0';
83 if(valid_filter_command(&just_arg0
))
87 if(can_access(just_arg0
, ACCESS_EXISTS
) != 0)
88 q_status_message1(SM_ORDER
, 0, 3,
89 "\"%s\" does not exist",
92 q_status_message1(SM_ORDER
, 0, 3,
93 "\"%s\" is not executable",
98 fs_give((void **) &just_arg0
);
100 fs_give((void **) &cmd
);
104 if(!just_arg0
&& !just_one
)
105 q_status_message(SM_ORDER
, 0, 3,
106 "None of the category cmds exists and is executable");
109 * If category_cmd isn't executable, it isn't a match.
111 if(!just_arg0
|| !cmd
){
113 * If we couldn't run the pipe command,
114 * we declare no match
116 for(s
= srchset
; s
; s
= s
->next
)
117 for(i
= s
->first
; i
<= s
->last
; i
++)
118 if(i
> 0L && stream
&& i
<= stream
->nmsgs
119 && (mc
=mail_elt(stream
, i
)) && mc
->searched
)
123 for(s
= srchset
; s
; s
= s
->next
)
124 for(i
= s
->first
; i
<= s
->last
; i
++)
125 if(i
> 0L && stream
&& i
<= stream
->nmsgs
126 && (mc
=mail_elt(stream
, i
)) && mc
->searched
){
129 * If there was an error, or the exitval is out of
130 * range, then it is not a match.
131 * Default range is (0,0),
132 * which is right for matching
135 if(test_message_with_cmd(stream
, i
, cmd
,
136 cat_lim
, &exitval
) != 0)
144 for(iv
= cat
; iv
; iv
= iv
->next
)
145 if((long) exitval
>= iv
->imin
146 && (long) exitval
<= iv
->imax
)
150 mc
->searched
= NIL
; /* not in any interval */
153 /* default to interval containing only zero */
161 fs_give((void **) &just_arg0
);
164 fs_give((void **) &cmd
);
170 * Returns 0 if ok, -1 if not ok.
171 * If ok then exitval contains the exit value of the cmd.
174 test_message_with_cmd(MAILSTREAM
*stream
, long int msgno
, char *cmd
,
175 long char_limit
, /* limit testing to this many chars from body */
180 int status
= 0, flags
, err
= 0;
181 char *resultfile
= NULL
, *pipe_err
;
185 flags
= PIPE_WRITE
| PIPE_NOSHELL
| PIPE_STDERR
| PIPE_NONEWMAIL
;
187 dprint((7, "test_message_with_cmd(msgno=%ld cmd=%s)\n",
190 if((tpipe
= cmd_pipe_open(cmd
, &resultfile
, flags
, &pc
))){
192 prime_raw_pipe_getc(stream
, msgno
, char_limit
, FT_PEEK
);
194 gf_link_filter(gf_nvtnl_local
, NULL
);
195 if((pipe_err
= gf_pipe(raw_pipe_getc
, pc
)) != NULL
){
196 q_status_message1(SM_ORDER
|SM_DING
, 3, 3,
197 "Internal Error: %.200s", pipe_err
);
202 * Don't call new_mail in close_system_pipe because we're probably
203 * already here from new_mail and we don't want to get loopy.
205 status
= close_system_pipe(&tpipe
, exitval
, pipe_callback
);
208 * This is a place where the command can put its output, which we
209 * are not interested in.
212 our_unlink(resultfile
);
213 fs_give((void **) &resultfile
);
216 return((err
|| status
) ? -1 : 0);