Commit 9e253b39 9e253b395de6ea7839b7f2b04b1a28892af514e7 by Sergey Poznyakoff

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.
1 parent 835ee6b0
...@@ -4,3 +4,4 @@ comsatd ...@@ -4,3 +4,4 @@ comsatd
4 .deps 4 .deps
5 .libs 5 .libs
6 .gdbinit 6 .gdbinit
7 biff.rc.h
......
...@@ -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 }
......
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 ---"
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
......