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.
Showing
6 changed files
with
234 additions
and
112 deletions
... | @@ -19,9 +19,16 @@ INCLUDES = @MU_APP_COMMON_INCLUDES@ | ... | @@ -19,9 +19,16 @@ INCLUDES = @MU_APP_COMMON_INCLUDES@ |
19 | SUBDIRS = . tests | 19 | SUBDIRS = . tests |
20 | sbin_PROGRAMS = comsatd | 20 | sbin_PROGRAMS = comsatd |
21 | 21 | ||
22 | comsatd_SOURCES = action.c comsat.c comsat.h | 22 | comsatd_SOURCES = action.c comsat.c comsat.h biff.rc.h |
23 | AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" | 23 | AM_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" |
24 | 24 | ||
25 | BUILT_SOURCES=biff.rc.h | ||
26 | EXTRA_DIST=biffrc.sed biff.rc | ||
27 | |||
28 | biff.rc.h: $(top_srcdir)/comsat/biff.rc | ||
29 | $(AM_V_GEN)sed -f $(top_srcdir)/comsat/biffrc.sed \ | ||
30 | $(top_srcdir)/comsat/biff.rc > biff.rc.h | ||
31 | |||
25 | comsatd_LDADD = \ | 32 | comsatd_LDADD = \ |
26 | ${MU_APP_LIBRARIES}\ | 33 | ${MU_APP_LIBRARIES}\ |
27 | ${MU_LIB_MBOX}\ | 34 | ${MU_LIB_MBOX}\ | ... | ... |
... | @@ -181,13 +181,8 @@ expand_line (const char *str, mu_message_t msg) | ... | @@ -181,13 +181,8 @@ expand_line (const char *str, mu_message_t msg) |
181 | } | 181 | } |
182 | 182 | ||
183 | const char *default_action = | 183 | const char *default_action = |
184 | "Mail to \a$u@$h\a\n" | 184 | #include "biff.rc.h" |
185 | "---\n" | 185 | ; |
186 | "From: $H{from}\n" | ||
187 | "Subject: $H{Subject}\n" | ||
188 | "---\n" | ||
189 | "$B(,5)\n" | ||
190 | "---\n"; | ||
191 | 186 | ||
192 | static void | 187 | static void |
193 | action_beep (mu_stream_t tty) | 188 | action_beep (mu_stream_t tty) |
... | @@ -439,126 +434,186 @@ open_default_tty (const char *device) | ... | @@ -439,126 +434,186 @@ open_default_tty (const char *device) |
439 | default_filters); | 434 | default_filters); |
440 | } | 435 | } |
441 | 436 | ||
437 | struct biffrc_environ | ||
438 | { | ||
439 | mu_stream_t tty; | ||
440 | mu_message_t msg; | ||
441 | mu_stream_t input; | ||
442 | struct mu_locus locus; | ||
443 | int use_default; | ||
444 | }; | ||
445 | |||
446 | void | ||
447 | eval_biffrc (struct biffrc_environ *env) | ||
448 | { | ||
449 | char *stmt = NULL; | ||
450 | size_t size = 0; | ||
451 | size_t n; | ||
452 | struct mu_wordsplit ws; | ||
453 | int wsflags; | ||
454 | |||
455 | ws.ws_comment = "#"; | ||
456 | wsflags = MU_WRDSF_DEFFLAGS | MU_WRDSF_COMMENT; | ||
457 | while (mu_stream_getline (env->input, &stmt, &size, &n) == 0 && n > 0) | ||
458 | { | ||
459 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
460 | MU_IOCTL_LOGSTREAM_SET_LOCUS, &env->locus); | ||
461 | if (mu_wordsplit (stmt, &ws, wsflags) == 0 && ws.ws_wordc) | ||
462 | { | ||
463 | if (strcmp (ws.ws_wordv[0], "beep") == 0) | ||
464 | { | ||
465 | /* FIXME: excess arguments are ignored */ | ||
466 | action_beep (env->tty); | ||
467 | } | ||
468 | else | ||
469 | { | ||
470 | /* Rest of actions require keyword expansion */ | ||
471 | int i; | ||
472 | int n_option = ws.ws_wordc > 1 && | ||
473 | strcmp (ws.ws_wordv[1], "-n") == 0; | ||
474 | |||
475 | for (i = 1; i < ws.ws_wordc; i++) | ||
476 | { | ||
477 | char *oldarg = ws.ws_wordv[i]; | ||
478 | ws.ws_wordv[i] = expand_line (ws.ws_wordv[i], env->msg); | ||
479 | free (oldarg); | ||
480 | if (!ws.ws_wordv[i]) | ||
481 | break; | ||
482 | } | ||
483 | |||
484 | if (strcmp (ws.ws_wordv[0], "tty") == 0) | ||
485 | { | ||
486 | mu_stream_t ntty = open_tty (ws.ws_wordv[1], | ||
487 | ws.ws_wordc - 2, | ||
488 | ws.ws_wordv + 2); | ||
489 | if (!ntty) | ||
490 | { | ||
491 | mu_stream_printf (env->tty, | ||
492 | _("%s:%d: cannot open tty\n"), | ||
493 | env->locus.mu_file, | ||
494 | env->locus.mu_line); | ||
495 | break; | ||
496 | } | ||
497 | mu_stream_destroy (&env->tty); | ||
498 | env->tty = ntty; | ||
499 | } | ||
500 | else if (strcmp (ws.ws_wordv[0], "echo") == 0) | ||
501 | { | ||
502 | int argc = ws.ws_wordc - 1; | ||
503 | char **argv = ws.ws_wordv + 1; | ||
504 | if (n_option) | ||
505 | { | ||
506 | argc--; | ||
507 | argv++; | ||
508 | } | ||
509 | action_echo (env->tty, n_option, argc, argv); | ||
510 | } | ||
511 | else if (strcmp (ws.ws_wordv[0], "exec") == 0) | ||
512 | { | ||
513 | action_exec (env->tty, ws.ws_wordc - 1, ws.ws_wordv + 1); | ||
514 | } | ||
515 | else if (strcmp (ws.ws_wordv[0], "default") == 0) | ||
516 | { | ||
517 | env->use_default = 1; | ||
518 | } | ||
519 | else | ||
520 | { | ||
521 | mu_stream_printf (env->tty, | ||
522 | _("%s:%d: unknown keyword\n"), | ||
523 | env->locus.mu_file, | ||
524 | env->locus.mu_line); | ||
525 | mu_diag_output (MU_DIAG_ERROR, _("unknown keyword %s"), | ||
526 | ws.ws_wordv[0]); | ||
527 | break; | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | else | ||
532 | { | ||
533 | const char *diag = mu_wordsplit_strerror (&ws); | ||
534 | mu_stream_printf (env->tty, | ||
535 | _("%s:%d: %s\n"), | ||
536 | env->locus.mu_file, | ||
537 | env->locus.mu_line, | ||
538 | diag); | ||
539 | mu_diag_output (MU_DIAG_ERROR, "%s", diag); | ||
540 | } | ||
541 | |||
542 | wsflags |= MU_WRDSF_REUSE; | ||
543 | /* FIXME: line number is incorrect if .biffrc contains | ||
544 | escaped newlines */ | ||
545 | env->locus.mu_line++; | ||
546 | } | ||
547 | free (stmt); | ||
548 | mu_wordsplit_free (&ws); | ||
549 | } | ||
550 | |||
551 | |||
442 | void | 552 | void |
443 | run_user_action (const char *device, mu_message_t msg) | 553 | run_user_action (const char *device, mu_message_t msg) |
444 | { | 554 | { |
445 | mu_stream_t input; | 555 | mu_stream_t stream; |
446 | int nact = 0; | 556 | struct biffrc_environ env; |
447 | mu_stream_t tty = open_default_tty (device); | ||
448 | 557 | ||
449 | if (!tty) | 558 | env.tty = open_default_tty (device); |
559 | if (!env.tty) | ||
450 | return; | 560 | return; |
451 | input = open_rc (biffrc, tty); | 561 | env.msg = msg; |
452 | if (input) | 562 | |
563 | env.input = open_rc (biffrc, env.tty); | ||
564 | if (env.input) | ||
453 | { | 565 | { |
454 | char *stmt = NULL; | ||
455 | size_t size = 0; | ||
456 | size_t n; | ||
457 | char *cwd = mu_getcwd (); | 566 | char *cwd = mu_getcwd (); |
458 | char *rcname; | 567 | char *rcname; |
459 | struct mu_locus locus; | ||
460 | struct mu_wordsplit ws; | ||
461 | int wsflags; | ||
462 | |||
463 | rcname = mu_make_file_name (cwd, BIFF_RC); | 568 | rcname = mu_make_file_name (cwd, BIFF_RC); |
464 | free (cwd); | 569 | free (cwd); |
465 | if (!rcname) | 570 | if (!rcname) |
466 | { | 571 | { |
467 | mu_diag_funcall (MU_DIAG_ERROR, "mu_make_file_name", NULL, ENOMEM); | 572 | mu_diag_funcall (MU_DIAG_ERROR, "mu_make_file_name", NULL, ENOMEM); |
468 | locus.mu_file = BIFF_RC; | 573 | env.locus.mu_file = BIFF_RC; |
469 | } | 574 | } |
470 | else | 575 | else |
471 | locus.mu_file = rcname; | 576 | env.locus.mu_file = rcname; |
472 | 577 | ||
473 | locus.mu_line = 1; | 578 | env.locus.mu_line = 1; |
474 | locus.mu_col = 0; | 579 | env.locus.mu_col = 0; |
580 | env.use_default = 0; | ||
581 | eval_biffrc (&env); | ||
582 | mu_stream_destroy (&env.input); | ||
583 | free (rcname); | ||
584 | } | ||
585 | else | ||
586 | env.use_default = 1; | ||
475 | 587 | ||
476 | ws.ws_comment = "#"; | 588 | if (env.use_default && |
477 | wsflags = MU_WRDSF_DEFFLAGS | MU_WRDSF_COMMENT; | 589 | mu_static_memory_stream_create (&stream, default_action, |
478 | while (mu_stream_getline (input, &stmt, &size, &n) == 0 && n > 0) | 590 | strlen (default_action)) == 0) |
591 | { | ||
592 | int rc = mu_filter_create (&env.input, stream, "LINECON", | ||
593 | MU_FILTER_DECODE, | ||
594 | MU_STREAM_READ); | ||
595 | mu_stream_unref (stream); | ||
596 | if (rc) | ||
479 | { | 597 | { |
480 | if (mu_wordsplit (stmt, &ws, wsflags) == 0 && ws.ws_wordc) | 598 | mu_stream_printf (env.tty, |
481 | { | 599 | _("Cannot create filter for the default action: %s\n"), |
482 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | 600 | mu_strerror (rc)); |
483 | MU_IOCTL_LOGSTREAM_SET_LOCUS, &locus); | 601 | mu_diag_output (MU_DIAG_NOTICE, |
484 | if (strcmp (ws.ws_wordv[0], "beep") == 0) | 602 | _("cannot create default filter for %s: %s"), |
485 | { | 603 | username, mu_strerror (rc)); |
486 | /* FIXME: excess arguments are ignored */ | 604 | } |
487 | action_beep (tty); | 605 | else |
488 | nact++; | 606 | { |
489 | } | 607 | env.locus.mu_file = "<default>"; |
490 | else | 608 | env.locus.mu_line = 1; |
491 | { | 609 | env.locus.mu_col = 0; |
492 | /* Rest of actions require keyword expansion */ | 610 | eval_biffrc (&env); |
493 | int i; | 611 | mu_stream_destroy (&env.input); |
494 | int n_option = ws.ws_wordc > 1 && | ||
495 | strcmp (ws.ws_wordv[1], "-n") == 0; | ||
496 | |||
497 | for (i = 1; i < ws.ws_wordc; i++) | ||
498 | { | ||
499 | char *oldarg = ws.ws_wordv[i]; | ||
500 | ws.ws_wordv[i] = expand_line (ws.ws_wordv[i], msg); | ||
501 | free (oldarg); | ||
502 | if (!ws.ws_wordv[i]) | ||
503 | break; | ||
504 | } | ||
505 | |||
506 | if (strcmp (ws.ws_wordv[0], "tty") == 0) | ||
507 | { | ||
508 | mu_stream_t ntty = open_tty (ws.ws_wordv[1], | ||
509 | ws.ws_wordc - 2, | ||
510 | ws.ws_wordv + 2); | ||
511 | if (!ntty) | ||
512 | { | ||
513 | mu_stream_printf (tty, | ||
514 | _(".biffrc:%d: cannot open tty\n"), | ||
515 | locus.mu_line); | ||
516 | break; | ||
517 | } | ||
518 | mu_stream_destroy (&tty); | ||
519 | tty = ntty; | ||
520 | } | ||
521 | else if (strcmp (ws.ws_wordv[0], "echo") == 0) | ||
522 | { | ||
523 | int argc = ws.ws_wordc - 1; | ||
524 | char **argv = ws.ws_wordv + 1; | ||
525 | if (n_option) | ||
526 | { | ||
527 | argc--; | ||
528 | argv++; | ||
529 | } | ||
530 | action_echo (tty, n_option, argc, argv); | ||
531 | nact++; | ||
532 | } | ||
533 | else if (strcmp (ws.ws_wordv[0], "exec") == 0) | ||
534 | { | ||
535 | action_exec (tty, ws.ws_wordc - 1, ws.ws_wordv + 1); | ||
536 | nact++; | ||
537 | } | ||
538 | else | ||
539 | { | ||
540 | mu_stream_printf (tty, | ||
541 | _(".biffrc:%d: unknown keyword\n"), | ||
542 | locus.mu_line); | ||
543 | mu_diag_output (MU_DIAG_ERROR, _("unknown keyword %s"), | ||
544 | ws.ws_wordv[0]); | ||
545 | break; | ||
546 | } | ||
547 | } | ||
548 | } | ||
549 | wsflags |= MU_WRDSF_REUSE; | ||
550 | /* FIXME: line number is incorrect if .biffrc contains | ||
551 | escaped newlines */ | ||
552 | locus.mu_line++; | ||
553 | } | 612 | } |
554 | mu_wordsplit_free (&ws); | ||
555 | mu_stream_destroy (&input); | ||
556 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
557 | MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL); | ||
558 | free (rcname); | ||
559 | } | 613 | } |
614 | |||
615 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
616 | MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL); | ||
560 | 617 | ||
561 | if (nact == 0) | 618 | mu_stream_destroy (&env.tty); |
562 | echo_string (tty, expand_line (default_action, msg)); | ||
563 | mu_stream_destroy (&tty); | ||
564 | } | 619 | } | ... | ... |
comsat/biff.rc
0 → 100644
1 | # The default biffrc file for GNU Mailutils comsatd utility. | ||
2 | # Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | echo "Mail to \a$u@$h\a\n---\n\ | ||
18 | From: $H{from}\n\ | ||
19 | Subject: $H{Subject}\n\ | ||
20 | ---\n\ | ||
21 | $B(,5)\n\ | ||
22 | ---" |
comsat/biffrc.sed
0 → 100644
1 | # This file is part of GNU Mailutils. | ||
2 | # Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | # | ||
4 | # GNU Mailutils is free software; you can redistribute it and/or | ||
5 | # modify it under the terms of the GNU General Public License as | ||
6 | # published by the Free Software Foundation; either version 3, or (at | ||
7 | # your option) any later version. | ||
8 | # | ||
9 | # GNU Mailutils is distributed in the hope that it will be useful, but | ||
10 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | # General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | # Provide leading quote | ||
18 | 1i\ | ||
19 | "\\ | ||
20 | |||
21 | # Provide trailing quote | ||
22 | $a\ | ||
23 | " | ||
24 | |||
25 | # Remove empty lines and comments | ||
26 | /#/d | ||
27 | /^ *$/d | ||
28 | # Escape quotes and backslashes | ||
29 | s/["\]/\\&/g | ||
30 | # Add newline and continuation character at the end of each line | ||
31 | s/$/\\n\\/ | ||
32 | # End | ||
33 |
... | @@ -46,6 +46,7 @@ BIFFTEST([default commands],[comsatd00], | ... | @@ -46,6 +46,7 @@ BIFFTEST([default commands],[comsatd00], |
46 | MUT_MBCOPY($abs_top_srcdir/testsuite/spool/teaparty.mbox, mailbox) | 46 | MUT_MBCOPY($abs_top_srcdir/testsuite/spool/teaparty.mbox, mailbox) |
47 | cat > biff.rc <<EOT | 47 | cat > biff.rc <<EOT |
48 | tty $cwd/output | 48 | tty $cwd/output |
49 | default | ||
49 | EOT | 50 | EOT |
50 | chmod 600 biff.rc | 51 | chmod 600 biff.rc |
51 | > $cwd/output | 52 | > $cwd/output |
... | @@ -69,6 +70,7 @@ BIFFTEST([non-zero qid],[comsatd01], | ... | @@ -69,6 +70,7 @@ BIFFTEST([non-zero qid],[comsatd01], |
69 | MUT_MBCOPY($abs_top_srcdir/testsuite/spool/teaparty.mbox, mailbox) | 70 | MUT_MBCOPY($abs_top_srcdir/testsuite/spool/teaparty.mbox, mailbox) |
70 | cat > biff.rc <<EOT | 71 | cat > biff.rc <<EOT |
71 | tty $cwd/output | 72 | tty $cwd/output |
73 | default | ||
72 | EOT | 74 | EOT |
73 | chmod 600 biff.rc | 75 | chmod 600 biff.rc |
74 | > $cwd/output | 76 | > $cwd/output |
... | @@ -93,6 +95,7 @@ BIFFTEST([maildir qid],[comsatd02], | ... | @@ -93,6 +95,7 @@ BIFFTEST([maildir qid],[comsatd02], |
93 | MUT_MBCOPY($abs_top_srcdir/testsuite/maildir/teaparty, mailbox) | 95 | MUT_MBCOPY($abs_top_srcdir/testsuite/maildir/teaparty, mailbox) |
94 | cat > biff.rc <<EOT | 96 | cat > biff.rc <<EOT |
95 | tty $cwd/output | 97 | tty $cwd/output |
98 | default | ||
96 | EOT | 99 | EOT |
97 | chmod 600 biff.rc | 100 | chmod 600 biff.rc |
98 | > $cwd/output | 101 | > $cwd/output |
... | @@ -116,6 +119,7 @@ BIFFTEST([MH qid],[comsatd03], | ... | @@ -116,6 +119,7 @@ BIFFTEST([MH qid],[comsatd03], |
116 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/teaparty, mailbox) | 119 | MUT_MBCOPY($abs_top_srcdir/testsuite/mh/teaparty, mailbox) |
117 | cat > biff.rc <<EOT | 120 | cat > biff.rc <<EOT |
118 | tty $cwd/output | 121 | tty $cwd/output |
122 | default | ||
119 | EOT | 123 | EOT |
120 | chmod 600 biff.rc | 124 | chmod 600 biff.rc |
121 | > $cwd/output | 125 | > $cwd/output | ... | ... |
-
Please register or sign in to post a comment