diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-12-08 12:38:21 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-12-08 12:38:21 +0200 |
commit | 9e253b395de6ea7839b7f2b04b1a28892af514e7 (patch) | |
tree | 43cb95b7addede641e0818bc94544e3ba7215753 /comsat/action.c | |
parent | 835ee6b03a098d8566e9b9ba2c22ab2403d41cba (diff) | |
download | mailutils-9e253b395de6ea7839b7f2b04b1a28892af514e7.tar.gz mailutils-9e253b395de6ea7839b7f2b04b1a28892af514e7.tar.bz2 |
comsat: improve biffrc evaluation.
* comsat/.gitignore: Add biff.rc.h
* comsat/Makefile.am (comsatd_SOURCES, BUILT_SOURCES): Add biff.rc.h
(EXTRA_DIST): Add biffrc.sed and biff.rc
* comsat/action.c (default_action): Include biff.rc.h.
(biffrc_environ): New struct.
(eval_biffrc): New function.
(run_user_action): Rewrite via eval_biffrc. Default action is
evaluated if biff.rc cannot be opened, or it contains the "default"
keyword.
* comsat/tests/testsuite.at: Add "default" statement where necessary.
Diffstat (limited to 'comsat/action.c')
-rw-r--r-- | comsat/action.c | 277 |
1 files changed, 166 insertions, 111 deletions
diff --git a/comsat/action.c b/comsat/action.c index ab185c5fc..f0647237a 100644 --- a/comsat/action.c +++ b/comsat/action.c @@ -181,13 +181,8 @@ expand_line (const char *str, mu_message_t msg) } const char *default_action = -"Mail to \a$u@$h\a\n" -"---\n" -"From: $H{from}\n" -"Subject: $H{Subject}\n" -"---\n" -"$B(,5)\n" -"---\n"; +#include "biff.rc.h" +; static void action_beep (mu_stream_t tty) @@ -439,126 +434,186 @@ open_default_tty (const char *device) default_filters); } +struct biffrc_environ +{ + mu_stream_t tty; + mu_message_t msg; + mu_stream_t input; + struct mu_locus locus; + int use_default; +}; + +void +eval_biffrc (struct biffrc_environ *env) +{ + char *stmt = NULL; + size_t size = 0; + size_t n; + struct mu_wordsplit ws; + int wsflags; + + ws.ws_comment = "#"; + wsflags = MU_WRDSF_DEFFLAGS | MU_WRDSF_COMMENT; + while (mu_stream_getline (env->input, &stmt, &size, &n) == 0 && n > 0) + { + mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, + MU_IOCTL_LOGSTREAM_SET_LOCUS, &env->locus); + if (mu_wordsplit (stmt, &ws, wsflags) == 0 && ws.ws_wordc) + { + if (strcmp (ws.ws_wordv[0], "beep") == 0) + { + /* FIXME: excess arguments are ignored */ + action_beep (env->tty); + } + else + { + /* Rest of actions require keyword expansion */ + int i; + int n_option = ws.ws_wordc > 1 && + strcmp (ws.ws_wordv[1], "-n") == 0; + + for (i = 1; i < ws.ws_wordc; i++) + { + char *oldarg = ws.ws_wordv[i]; + ws.ws_wordv[i] = expand_line (ws.ws_wordv[i], env->msg); + free (oldarg); + if (!ws.ws_wordv[i]) + break; + } + + if (strcmp (ws.ws_wordv[0], "tty") == 0) + { + mu_stream_t ntty = open_tty (ws.ws_wordv[1], + ws.ws_wordc - 2, + ws.ws_wordv + 2); + if (!ntty) + { + mu_stream_printf (env->tty, + _("%s:%d: cannot open tty\n"), + env->locus.mu_file, + env->locus.mu_line); + break; + } + mu_stream_destroy (&env->tty); + env->tty = ntty; + } + else if (strcmp (ws.ws_wordv[0], "echo") == 0) + { + int argc = ws.ws_wordc - 1; + char **argv = ws.ws_wordv + 1; + if (n_option) + { + argc--; + argv++; + } + action_echo (env->tty, n_option, argc, argv); + } + else if (strcmp (ws.ws_wordv[0], "exec") == 0) + { + action_exec (env->tty, ws.ws_wordc - 1, ws.ws_wordv + 1); + } + else if (strcmp (ws.ws_wordv[0], "default") == 0) + { + env->use_default = 1; + } + else + { + mu_stream_printf (env->tty, + _("%s:%d: unknown keyword\n"), + env->locus.mu_file, + env->locus.mu_line); + mu_diag_output (MU_DIAG_ERROR, _("unknown keyword %s"), + ws.ws_wordv[0]); + break; + } + } + } + else + { + const char *diag = mu_wordsplit_strerror (&ws); + mu_stream_printf (env->tty, + _("%s:%d: %s\n"), + env->locus.mu_file, + env->locus.mu_line, + diag); + mu_diag_output (MU_DIAG_ERROR, "%s", diag); + } + + wsflags |= MU_WRDSF_REUSE; + /* FIXME: line number is incorrect if .biffrc contains + escaped newlines */ + env->locus.mu_line++; + } + free (stmt); + mu_wordsplit_free (&ws); +} + + void run_user_action (const char *device, mu_message_t msg) { - mu_stream_t input; - int nact = 0; - mu_stream_t tty = open_default_tty (device); + mu_stream_t stream; + struct biffrc_environ env; - if (!tty) + env.tty = open_default_tty (device); + if (!env.tty) return; - input = open_rc (biffrc, tty); - if (input) + env.msg = msg; + + env.input = open_rc (biffrc, env.tty); + if (env.input) { - char *stmt = NULL; - size_t size = 0; - size_t n; char *cwd = mu_getcwd (); char *rcname; - struct mu_locus locus; - struct mu_wordsplit ws; - int wsflags; - rcname = mu_make_file_name (cwd, BIFF_RC); free (cwd); if (!rcname) - { + { mu_diag_funcall (MU_DIAG_ERROR, "mu_make_file_name", NULL, ENOMEM); - locus.mu_file = BIFF_RC; - } + env.locus.mu_file = BIFF_RC; + } else - locus.mu_file = rcname; - - locus.mu_line = 1; - locus.mu_col = 0; + env.locus.mu_file = rcname; + + env.locus.mu_line = 1; + env.locus.mu_col = 0; + env.use_default = 0; + eval_biffrc (&env); + mu_stream_destroy (&env.input); + free (rcname); + } + else + env.use_default = 1; - ws.ws_comment = "#"; - wsflags = MU_WRDSF_DEFFLAGS | MU_WRDSF_COMMENT; - while (mu_stream_getline (input, &stmt, &size, &n) == 0 && n > 0) + if (env.use_default && + mu_static_memory_stream_create (&stream, default_action, + strlen (default_action)) == 0) + { + int rc = mu_filter_create (&env.input, stream, "LINECON", + MU_FILTER_DECODE, + MU_STREAM_READ); + mu_stream_unref (stream); + if (rc) { - if (mu_wordsplit (stmt, &ws, wsflags) == 0 && ws.ws_wordc) - { - mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, - MU_IOCTL_LOGSTREAM_SET_LOCUS, &locus); - if (strcmp (ws.ws_wordv[0], "beep") == 0) - { - /* FIXME: excess arguments are ignored */ - action_beep (tty); - nact++; - } - else - { - /* Rest of actions require keyword expansion */ - int i; - int n_option = ws.ws_wordc > 1 && - strcmp (ws.ws_wordv[1], "-n") == 0; - - for (i = 1; i < ws.ws_wordc; i++) - { - char *oldarg = ws.ws_wordv[i]; - ws.ws_wordv[i] = expand_line (ws.ws_wordv[i], msg); - free (oldarg); - if (!ws.ws_wordv[i]) - break; - } - - if (strcmp (ws.ws_wordv[0], "tty") == 0) - { - mu_stream_t ntty = open_tty (ws.ws_wordv[1], - ws.ws_wordc - 2, - ws.ws_wordv + 2); - if (!ntty) - { - mu_stream_printf (tty, - _(".biffrc:%d: cannot open tty\n"), - locus.mu_line); - break; - } - mu_stream_destroy (&tty); - tty = ntty; - } - else if (strcmp (ws.ws_wordv[0], "echo") == 0) - { - int argc = ws.ws_wordc - 1; - char **argv = ws.ws_wordv + 1; - if (n_option) - { - argc--; - argv++; - } - action_echo (tty, n_option, argc, argv); - nact++; - } - else if (strcmp (ws.ws_wordv[0], "exec") == 0) - { - action_exec (tty, ws.ws_wordc - 1, ws.ws_wordv + 1); - nact++; - } - else - { - mu_stream_printf (tty, - _(".biffrc:%d: unknown keyword\n"), - locus.mu_line); - mu_diag_output (MU_DIAG_ERROR, _("unknown keyword %s"), - ws.ws_wordv[0]); - break; - } - } - } - wsflags |= MU_WRDSF_REUSE; - /* FIXME: line number is incorrect if .biffrc contains - escaped newlines */ - locus.mu_line++; + mu_stream_printf (env.tty, + _("Cannot create filter for the default action: %s\n"), + mu_strerror (rc)); + mu_diag_output (MU_DIAG_NOTICE, + _("cannot create default filter for %s: %s"), + username, mu_strerror (rc)); + } + else + { + env.locus.mu_file = "<default>"; + env.locus.mu_line = 1; + env.locus.mu_col = 0; + eval_biffrc (&env); + mu_stream_destroy (&env.input); } - mu_wordsplit_free (&ws); - mu_stream_destroy (&input); - mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, - MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL); - free (rcname); } + + mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, + MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL); - if (nact == 0) - echo_string (tty, expand_line (default_action, msg)); - mu_stream_destroy (&tty); + mu_stream_destroy (&env.tty); } |