Commit 375ffa14 375ffa14056f4165c9674fa94c243bd632c43742 by Sergey Poznyakoff

ali: executable file inclusion.

The "< file" construct tests if file is executable and begins with
the shell interpreter magic (#!/ or #! /).  If so, this file is
executed and its output is collected.  This provides a way for
building aliases on the fly.

* mh/mh_alias.l (buffer_ctx) <exec_p>: New member.
(exec_p): New static variable.
(push_source): If the file is executable and begins with
the "#!/" magic, run it and collect its output.
(pop_source): Use exec_p to decide how to close the file.
* mh/tests/ali.at: Test executable file inclusion.
* NEWS: Update.
1 parent efa51304
1 GNU mailutils NEWS -- history of user-visible changes. 2012-11-12 1 GNU mailutils NEWS -- history of user-visible changes. 2013-02-16
2 Copyright (C) 2002-2012 Free Software Foundation, Inc. 2 Copyright (C) 2002-2012 Free Software Foundation, Inc.
3 See the end of file for copying conditions. 3 See the end of file for copying conditions.
4 4
...@@ -203,6 +203,14 @@ option: ...@@ -203,6 +203,14 @@ option:
203 "yes", the mailbox will be truncated after successful processing. 203 "yes", the mailbox will be truncated after successful processing.
204 If BOOL is "no", the source mailbox will not be truncated. 204 If BOOL is "no", the source mailbox will not be truncated.
205 205
206 ** MH aliases
207
208 The "< FILE" construct has been extended to allow for building the
209 list of aliases on the fly. If FILE is an executable file and its
210 first line begins with a shell interpreter magic (#!/ or #! /), then
211 instead of being included, such file is run using "/bin/sh -c", its
212 output is collected and included in the aliases.
213
206 ** mailutils-config is deprecated. 214 ** mailutils-config is deprecated.
207 215
208 Use `mu cflags' and `mu ldflags' instead. The mailutils-config is 216 Use `mu cflags' and `mu ldflags' instead. The mailutils-config is
......
...@@ -219,10 +219,12 @@ struct buffer_ctx { ...@@ -219,10 +219,12 @@ struct buffer_ctx {
219 int line; 219 int line;
220 ino_t i_node; 220 ino_t i_node;
221 FILE *yyin; 221 FILE *yyin;
222 int exec_p;
222 LEX_BUFFER_STATE state; 223 LEX_BUFFER_STATE state;
223 }; 224 };
224 225
225 static struct buffer_ctx *context_stack; 226 static struct buffer_ctx *context_stack;
227 static int exec_p;
226 228
227 static struct buffer_ctx * 229 static struct buffer_ctx *
228 ctx_lookup (ino_t ino) 230 ctx_lookup (ino_t ino)
...@@ -242,7 +244,8 @@ push_source (const char *name, int fail) ...@@ -242,7 +244,8 @@ push_source (const char *name, int fail)
242 struct buffer_ctx *ctx; 244 struct buffer_ctx *ctx;
243 struct stat st; 245 struct stat st;
244 char *filename; 246 char *filename;
245 247 int ex = 0;
248
246 filename = mh_expand_name (NULL, name, 0); 249 filename = mh_expand_name (NULL, name, 0);
247 if (stat (filename, &st)) 250 if (stat (filename, &st))
248 { 251 {
...@@ -251,7 +254,7 @@ push_source (const char *name, int fail) ...@@ -251,7 +254,7 @@ push_source (const char *name, int fail)
251 free (filename); 254 free (filename);
252 return 1; 255 return 1;
253 } 256 }
254 257
255 if (ali_filename && st.st_ino == ali_source_inode) 258 if (ali_filename && st.st_ino == ali_source_inode)
256 { 259 {
257 ali_parse_error (_("recursive inclusion")); 260 ali_parse_error (_("recursive inclusion"));
...@@ -279,12 +282,35 @@ push_source (const char *name, int fail) ...@@ -279,12 +282,35 @@ push_source (const char *name, int fail)
279 free (filename); 282 free (filename);
280 return 1; 283 return 1;
281 } 284 }
285 if (access (filename, X_OK) == 0)
286 {
287 char sig[4];
288
289 if (fread (sig, sizeof(sig), 1, fp) == 1 &&
290 (memcmp(sig, "#!/", 3) == 0 ||
291 memcmp(sig, "#! /", 4) == 0))
292 {
293 ex = 1;
294 fclose (fp);
295 fp = popen (filename, "r");
296 if (!fp)
297 {
298 ali_parse_error (_("can't execute `%s': %s"),
299 filename, strerror (errno));
300 free (filename);
301 return 1;
302 }
303 }
304 else
305 rewind (fp);
306 }
282 307
283 /* Push current context */ 308 /* Push current context */
284 if (ali_filename) 309 if (ali_filename)
285 { 310 {
286 ctx = mu_alloc (sizeof (*ctx)); 311 ctx = mu_alloc (sizeof (*ctx));
287 ctx->filename = ali_filename; 312 ctx->filename = ali_filename;
313 ctx->exec_p = exec_p;
288 ctx->line = ali_line_num; 314 ctx->line = ali_line_num;
289 ctx->i_node = ali_source_inode; 315 ctx->i_node = ali_source_inode;
290 ctx->yyin = yyin; 316 ctx->yyin = yyin;
...@@ -307,6 +333,7 @@ push_source (const char *name, int fail) ...@@ -307,6 +333,7 @@ push_source (const char *name, int fail)
307 ali_filename = filename; 333 ali_filename = filename;
308 ali_line_num = 1; 334 ali_line_num = 1;
309 ali_source_inode = st.st_ino; 335 ali_source_inode = st.st_ino;
336 exec_p = ex;
310 return 0; 337 return 0;
311 } 338 }
312 339
...@@ -316,7 +343,7 @@ pop_source () ...@@ -316,7 +343,7 @@ pop_source ()
316 struct buffer_ctx *ctx; 343 struct buffer_ctx *ctx;
317 344
318 if (yyin) 345 if (yyin)
319 fclose (yyin); 346 (exec_p ? pclose : fclose) (yyin);
320 #ifndef FLEX_SCANNER 347 #ifndef FLEX_SCANNER
321 lex_delete_buffer (current_buffer); 348 lex_delete_buffer (current_buffer);
322 #endif 349 #endif
...@@ -332,6 +359,7 @@ pop_source () ...@@ -332,6 +359,7 @@ pop_source ()
332 ali_filename = context_stack->filename; 359 ali_filename = context_stack->filename;
333 ali_line_num = context_stack->line + 1; /* < line did not increment it */ 360 ali_line_num = context_stack->line + 1; /* < line did not increment it */
334 ali_source_inode = context_stack->i_node; 361 ali_source_inode = context_stack->i_node;
362 exec_p = context_stack->exec_p;
335 RESTORE_BUFFER_STATE (context_stack->state); 363 RESTORE_BUFFER_STATE (context_stack->state);
336 ctx = context_stack->prev; 364 ctx = context_stack->prev;
337 free (context_stack); 365 free (context_stack);
......
...@@ -108,15 +108,19 @@ ali -list -a ./mh_aliases everybody ...@@ -108,15 +108,19 @@ ali -list -a ./mh_aliases everybody
108 [0], 108 [0],
109 [expout]) 109 [expout])
110 110
111 MH_CHECK([ali: simple aliases],[ali00],[ 111 MH_CHECK([ali: executable file inlcusion],[ali02 ali-xinclude],[
112 AT_DATA([Mail/ali.sh],[#! /bin/sh
113 echo "admin: gray, jeff"
114 ])
115 chmod +x Mail/ali.sh
112 AT_DATA([mh_aliases],[ 116 AT_DATA([mh_aliases],[
113 devel: gray, polak 117 devel: gray, polak, admin
114 admin: gray, jeff 118 <ali.sh
115 ]) 119 ])
116 ali -a ./mh_aliases devel 120 ali -a ./mh_aliases devel
117 ], 121 ],
118 [0], 122 [0],
119 [gray, polak 123 [gray, polak, gray, jeff
120 ]) 124 ])
121 125
122 m4_popdef[MH_KEYWORDS]) 126 m4_popdef[MH_KEYWORDS])
......