summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2019-09-03 14:47:14 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2019-09-03 14:50:54 (GMT)
commit016c4a978a69cc8990b5aab6c88cbac6fda57203 (patch) (side-by-side diff)
treef451622ce35a0b64e52522aeef82bd3064faef06
parentddfa689bff19d877170add6fed3381f3d5b79a8e (diff)
downloadmailutils-016c4a978a69cc8990b5aab6c88cbac6fda57203.tar.gz
mailutils-016c4a978a69cc8990b5aab6c88cbac6fda57203.tar.bz2
comsatd: optional argument to the --test option supplies the name of the tty to use
* NEWS: Document changes. * comsat/action.c (open_default_tty): Remove. (open_tty): Examine the tty device (or file) and construct a suitable filter chain. Use append mode when opening it. * comsat/comsat.c: The --test option takes optional argument. * comsat/tests/testsuite.at: Use local file instead of the tty. * doc/texinfo/programs/comsatd.texi: Document changes.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--NEWS7
-rw-r--r--comsat/action.c156
-rw-r--r--comsat/comsat.c32
-rw-r--r--comsat/tests/testsuite.at62
-rw-r--r--doc/texinfo/programs/comsatd.texi28
5 files changed, 153 insertions, 132 deletions
diff --git a/NEWS b/NEWS
index 251f5a8..50eadb8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,37 +1,42 @@
-GNU mailutils NEWS -- history of user-visible changes. 2019-08-29
+GNU mailutils NEWS -- history of user-visible changes. 2019-09-03
Copyright (C) 2002-2019 Free Software Foundation, Inc.
See the end of file for copying conditions.
Please send mailutils bug reports to <bug-mailutils@gnu.org>.
Version 3.7.90 (git)
* Use of TLS in pop3d run from inetd
New global configuration statement "tls-mode" configures the TLS for
use in inetd mode.
The certificate and key files are configured by the global "tls"
compound statement.
Example configuration (pop3s server):
mode inetd;
tls-mode connection;
tls {
ssl-key-file /etc/ssl/key.pem;
ssl-certificate-file /etc/ssl/cert.pem;
}
+* comsatd --test
+
+The --test option takes optional argument: name of the tty or file to
+use for reporting.
+
Version 3.7 - 2019-06-21
* Support for the new mailbox format - dotmail
Dotmail is a replacement for traditional mbox format, proposed by
Kurt Hackenberg. A dotmail mailbox is a single disk file, where
messages are stored sequentially. Each message ends with a single
dot (similar to the format used in the SMTP DATA command). Any dot
appearing at the start of the line is doubled, to prevent it from
being interpreted as end of message marker.
diff --git a/comsat/action.c b/comsat/action.c
index c9703f2..b6799c4 100644
--- a/comsat/action.c
+++ b/comsat/action.c
@@ -167,138 +167,148 @@ expand_line (const char *str, mu_message_t msg)
}
}
mu_opool_append_char (pool, 0);
str = strdup (mu_opool_finish (pool, NULL));
mu_opool_destroy (&pool);
return (char *)str;
}
const char *default_action =
#include "biff.rc.h"
;
+/* Examine the tty to determine which filters to apply when printing
+ to it. On entry, STR is the opened stream, FLT points to an array
+ of char* with at least 3 slots, and NFLT to an integer number.
+ On success, populates FLT with the necessary filter chain, and stores
+ to *NFLT the number of used slots. On error, issues error message and
+ returns -1.
+ FLT and NFLT can be used as input to mu_filter_chain_create.
+ */
static int
-need_crlf (mu_stream_t str)
+study_tty (mu_stream_t str, char *flt[], int *nflt)
{
-#if defined(OPOST) && defined(ONLCR)
mu_transport_t trans[2];
- struct termios tbuf;
+ int fd;
+ struct stat st;
+ int rc;
- if (mu_stream_ioctl (str, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans))
- return 1; /* suppose we do need it */
- if (tcgetattr ((int) (intptr_t) trans[0], &tbuf) == 0 &&
- (tbuf.c_oflag & OPOST) && (tbuf.c_oflag & ONLCR))
- return 0;
- else
- return 1;
+ rc = mu_stream_ioctl (str, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_ioctl", NULL, rc);
+ return rc;
+ }
+
+ *nflt = 0;
+ fd = (int) (intptr_t) trans[0];
+ if (fstat (fd, &st) == 0)
+ {
+ switch (st.st_mode & S_IFMT)
+ {
+ case S_IFREG:
+ return 0;
+
+ case S_IFCHR:
+ flt[(*nflt)++] = "7BIT";
+#if defined(OPOST) && defined(ONLCR)
+ {
+ struct termios tbuf;
+
+ if (!(tcgetattr (fd, &tbuf) == 0
+ && (tbuf.c_oflag & OPOST) && (tbuf.c_oflag & ONLCR)))
+ {
+ flt[(*nflt)++] = "+";
+ flt[(*nflt)++] = "CRLF";
+ }
+ }
#else
- return 1; /* Just in case */
+ /* Just in case */
+ flt[(*nflt)++] = "+";
+ flt[(*nflt)++] = "CRLF";
#endif
+ break;
+
+ case S_IFSOCK:
+ return 0;
+
+ default:
+ /* FIXME: Perhaps an error? */
+ return 0;
+ }
+ }
+
+ return 0;
}
static mu_stream_t
_open_tty (const char *device, int argc, char **argv)
{
- mu_stream_t dev, base_dev, prev_stream;
+ mu_stream_t dev;
int status;
+ char *dfl_argv[4];
- status = mu_file_stream_create (&dev, device, MU_STREAM_WRITE);
+ status = mu_file_stream_create (&dev, device, MU_STREAM_APPEND|MU_STREAM_CREAT);
if (status)
{
mu_error (_("cannot open device %s: %s"),
device, mu_strerror (status));
return NULL;
}
mu_stream_set_buffer (dev, mu_buffer_line, 0);
- prev_stream = base_dev = dev;
- while (argc)
+ if (argc == 0)
{
- int i;
- int mode;
- int qmark;
- char *fltname;
-
- fltname = argv[0];
- if (fltname[0] == '?')
- {
- qmark = 1;
- fltname++;
- }
- else
- qmark = 0;
-
- if (fltname[0] == '~')
- {
- mode = MU_FILTER_DECODE;
- fltname++;
- }
- else
- {
- mode = MU_FILTER_ENCODE;
- }
-
- for (i = 1; i < argc; i++)
- if (strcmp (argv[i], "+") == 0)
- break;
-
- if (qmark == 0 || need_crlf (base_dev))
- {
- status = mu_filter_create_args (&dev, prev_stream, fltname,
- i, (const char **)argv,
- mode, MU_STREAM_WRITE);
- mu_stream_unref (prev_stream);
- if (status)
- {
- mu_error (_("cannot open filter stream: %s"),
- mu_strerror (status));
- return NULL;
- }
- prev_stream = dev;
- }
- argc -= i;
- argv += i;
- if (argc)
+ status = study_tty (dev, dfl_argv, &argc);
+ if (status)
+ return NULL;
+ argv = dfl_argv;
+ }
+
+ if (argc)
+ {
+ mu_stream_t str;
+ status = mu_filter_chain_create (&str, dev,
+ MU_FILTER_ENCODE, MU_STREAM_WRITE,
+ argc, argv);
+ mu_stream_unref (dev);
+ if (status)
{
- argc--;
- argv++;
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_filter_chain_create", device,
+ status);
+ return NULL;
}
+ dev = str;
}
return dev;
}
mu_stream_t
open_tty (const char *device, int argc, char **argv)
{
mu_stream_t dev;
if (!device || !*device || strcmp (device, "null") == 0)
{
int rc = mu_nullstream_create (&dev, MU_STREAM_WRITE);
if (rc)
- mu_error (_("cannot open null stream: %s"), mu_strerror (rc));
+ {
+ mu_error (_("cannot open null stream: %s"), mu_strerror (rc));
+ dev = NULL;
+ }
}
else
dev = _open_tty (device, argc, argv);
return dev;
}
-
-static mu_stream_t
-open_default_tty (const char *device)
-{
- static char *default_filters[] = { "7bit", "+", "?CRLF", NULL };
- return open_tty (device, MU_ARRAY_SIZE (default_filters) - 1,
- default_filters);
-}
-
struct biffrc_environ
{
mu_stream_t tty;
mu_stream_t logstr;
mu_message_t msg;
mu_stream_t input;
struct mu_locus_range locus;
int use_default;
char *errbuf;
size_t errsize;
};
@@ -602,25 +612,25 @@ eval_biffrc (struct biffrc_environ *env)
MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL);
mu_stream_ioctl (env->logstr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL);
}
void
run_user_action (const char *device, mu_message_t msg)
{
int rc, mode;
mu_stream_t stream;
struct biffrc_environ env;
- env.tty = open_default_tty (device);
+ env.tty = open_tty (device, 0, NULL);
if (!env.tty)
return;
env.msg = msg;
env.errbuf = NULL;
env.errsize = 0;
rc = mu_log_stream_create (&env.logstr, env.tty);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR,
_("cannot create log stream: %s"),
diff --git a/comsat/comsat.c b/comsat/comsat.c
index f317fa6..cee4745 100644
--- a/comsat/comsat.c
+++ b/comsat/comsat.c
@@ -9,24 +9,25 @@
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#include "comsat.h"
#include "mailutils/syslog.h"
#include "mailutils/cli.h"
#include "mailutils/sockaddr.h"
+#include "mailutils/alloc.h"
#ifndef PATH_DEV
# define PATH_DEV "/dev"
#endif
#ifndef PATH_TTY_PFX
# define PATH_TTY_PFX PATH_DEV
#endif
#ifdef HAVE_UTMP_H
# include <utmp.h>
#endif
@@ -50,35 +51,54 @@ typedef struct utmp UTMP;
# if HAVE_STRUCT_UTMP_UT_NAME
# define ut_user ut_name
# else
# error "Neither ut_user nor ut_name found in struct utmp. Please report."
# endif
# endif
#endif
#define MAX_TTY_SIZE (sizeof (PATH_TTY_PFX) + sizeof (((UTMP*)0)->ut_line))
const char *program_version = "comsatd (" PACKAGE_STRING ")";
-int test_mode;
+char *test_mode;
char *biffrc = BIFF_RC;
mu_m_server_t server;
static void
set_inetd_mode (struct mu_parseopt *po, struct mu_option *opt,
char const *arg)
{
mu_m_server_set_mode (server, MODE_INTERACTIVE);
}
-
+
+static void
+set_test_mode (struct mu_parseopt *po, struct mu_option *opt,
+ char const *arg)
+{
+ if (arg)
+ {
+ if (arg[0] != '/')
+ {
+ test_mode = mu_make_file_name (mu_getcwd (), arg);
+ if (!test_mode)
+ mu_alloc_die ();
+ }
+ else
+ test_mode = mu_strdup (arg);
+ }
+ else
+ test_mode = mu_strdup ("/dev/tty");
+}
+
static void
set_daemon_mode (struct mu_parseopt *po, struct mu_option *opt,
char const *arg)
{
mu_m_server_set_mode (server, MODE_DAEMON);
if (arg)
{
size_t max_children;
char *errmsg;
int rc = mu_str_to_c (arg, mu_c_size, &max_children, &errmsg);
if (rc)
{
@@ -88,27 +108,27 @@ set_daemon_mode (struct mu_parseopt *po, struct mu_option *opt,
mu_m_server_set_max_children (server, max_children);
}
}
static void
set_foreground (struct mu_parseopt *po, struct mu_option *opt,
char const *arg)
{
mu_m_server_set_foreground (server, 1);
}
static struct mu_option comsat_options[] = {
- { "test", 't', NULL, MU_OPTION_DEFAULT,
- N_("run in test mode"),
- mu_c_bool, &test_mode },
+ { "test", 't', N_("FILE"), MU_OPTION_ARG_OPTIONAL,
+ N_("run in test mode; use FILE as tty (default: /dev/tty)"),
+ mu_c_string, &test_mode, set_test_mode },
{ "foreground", 0, NULL, MU_OPTION_DEFAULT,
N_("remain in foreground"),
mu_c_bool, NULL, set_foreground },
{ "inetd", 'i', NULL, MU_OPTION_DEFAULT,
N_("run in inetd mode"),
mu_c_bool, NULL, set_inetd_mode },
{ "daemon", 'd', N_("NUMBER"), MU_OPTION_ARG_OPTIONAL,
N_("runs in daemon mode with a maximum of NUMBER children"),
mu_c_string, NULL, set_daemon_mode },
{ "file", 'f', N_("FILE"), MU_OPTION_DEFAULT,
N_("read FILE instead of .biffrc"),
mu_c_string, &biffrc },
@@ -596,25 +616,25 @@ main (int argc, char **argv)
{
char *cwd = mu_getcwd ();
biffrc = mu_make_file_name (cwd, biffrc);
if (!biffrc)
{
mu_error ("%s", mu_strerror (ENOMEM));
exit (1);
}
mu_normalize_path (biffrc);
free (cwd);
}
- notify_user (user, "/dev/tty", argv[0], argv[1]);
+ notify_user (user, test_mode, argv[0], argv[1]);
exit (0);
}
mu_stdstream_strerr_setup (mu_log_syslog ?
MU_STRERR_SYSLOG : MU_STRERR_STDERR);
if (mu_m_server_mode (server) == MODE_DAEMON)
{
if (save_argv[0][0] != '/')
mu_diag_output (MU_DIAG_NOTICE,
_("program name is not absolute; reloading will not "
"be possible"));
diff --git a/comsat/tests/testsuite.at b/comsat/tests/testsuite.at
index 45f3b1e..db2dbd0 100644
--- a/comsat/tests/testsuite.at
+++ b/comsat/tests/testsuite.at
@@ -14,170 +14,138 @@
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
m4_include([testsuite.inc])
dnl ------------------------------------------------------------
dnl mailbox for comsatd
m4_pushdef([BIFF_MBOX],[`pwd`/mailbox])
dnl ------------------------------------------------------------
dnl comsatcmd
m4_pushdef([comsatcmd],[comsatd --no-site-config --file ./biff.rc dnl
- --set logging.syslog=no --test])
+ --set logging.syslog=no --test=output])
dnl ------------------------------------------------------------
dnl BIFFTEST(DESCR, KW, DATA, CMDLINE, [STDOUT = `'], [STDERR = `'])
dnl
dnl NOTE: The test is skipped if run as root, because .biffrc is
dnl ignored for root (see open_rc() in action.c
dnl
m4_pushdef([BIFFTEST],[
AT_SETUP([comsatd: $1])
AT_KEYWORDS([comsatd $2])
+AT_CHECK([test -w / && AT_SKIP_TEST
+cwd=`pwd`
$3
-AT_CHECK([test -w / && AT_SKIP_TEST; $4],[0],[$5],[$6])
+],[0],[$4],[$5])
AT_CLEANUP])
AT_INIT
AT_TESTED([comsatd])
MUT_VERSION(comsatd)
BIFFTEST([default commands],[comsatd00],
-[cwd=`pwd`
+[
MUT_MBCOPY($abs_top_srcdir/testsuite/spool/teaparty.mbox, mailbox)
-cat > biff.rc <<EOT
-tty $cwd/output
-default
-EOT
-chmod 600 biff.rc
-> $cwd/output
-],
-[comsatcmd $cwd/mailbox 0
+comsatcmd $cwd/mailbox 0
sed '1s/^Mail to .*/Mail to test user/' output
],
[Mail to test user
---
From: March Hare <hare@wonder.land>
Subject: Invitation
---
Have some wine
---
])
BIFFTEST([non-zero qid],[comsatd01],
-[cwd=`pwd`
+[
MUT_MBCOPY($abs_top_srcdir/testsuite/spool/teaparty.mbox, mailbox)
-cat > biff.rc <<EOT
-tty $cwd/output
-default
-EOT
-chmod 600 biff.rc
-> $cwd/output
-],
-[comsatcmd $cwd/mailbox 9367
+comsatcmd $cwd/mailbox 9367
sed '1s/^Mail to .*/Mail to test user/' output
],
[Mail to test user
---
From: Alice <alice@wonder.land>
Subject: Funny watch (was Re: Watch)
---
What a funny watch! It tells the day of the
month, and doesn't tell what o'clock it is!
---
])
BIFFTEST([maildir qid],[comsatd02],
-[cwd=`pwd`
+[
MUT_MBCOPY($abs_top_srcdir/testsuite/maildir/teaparty, mailbox)
-cat > biff.rc <<EOT
-tty $cwd/output
-default
-EOT
-chmod 600 biff.rc
-> $cwd/output
-],
-[test "$MAILDIR_SUPPORT" = yes || AT_SKIP_TEST
+test "$MAILDIR_SUPPORT" = yes || AT_SKIP_TEST
comsatcmd maildir:$cwd/mailbox new/1284627340.M364969P3770Q81.Trurl
sed '1s/^Mail to .*/Mail to test user/' output
],
[Mail to test user
---
From: Alice <alice@wonder.land>
Subject: Re: Story
---
What did they draw?
---
])
BIFFTEST([MH qid],[comsatd03],
-[cwd=`pwd`
+[
MUT_MBCOPY($abs_top_srcdir/testsuite/mh/teaparty, mailbox)
-cat > biff.rc <<EOT
-tty $cwd/output
-default
-EOT
-chmod 600 biff.rc
-> $cwd/output
-],
-[test "$MH_SUPPORT" = yes || AT_SKIP_TEST
+test "$MH_SUPPORT" = yes || AT_SKIP_TEST
comsatcmd mh:$cwd/mailbox teaparty/58
sed '1s/^Mail to .*/Mail to test user/' output
],
[Mail to test user
---
From: March Hare <hare@wonder.land>
Subject: Request for a story (was Re: A guess)
---
Suppose we change the subject, I'm getting tired of this.
I vote the young lady tells us a story.
---
])
BIFFTEST([beep command],[comsatd04],
-[cwd=`pwd`
+[
MUT_MBCOPY($abs_top_srcdir/testsuite/spool/mbox1, mailbox)
cat > biff.rc <<EOT
-tty $cwd/output
beep
EOT
chmod 600 biff.rc
-> $cwd/output
-],
-[comsatcmd $cwd/mailbox 0
+comsatcmd $cwd/mailbox 0
cat output | tr '\a' A
],
[AA])
BIFFTEST([exec command],[comsatd05],
[cwd=`pwd`
MUT_MBCOPY($abs_top_srcdir/testsuite/spool/teaparty.mbox, mailbox)
AT_DATA([notifier],[#! /bin/sh
echo "You have mail from $1, regarding $2"
])
chmod +x notifier
cat > biff.rc <<EOT
-tty $cwd/output
exec $cwd/notifier '\$H{from}' '\$H{Subject}'
EOT
chmod 600 biff.rc
-> $cwd/output
-],
-[comsatcmd $cwd/mailbox 0
+comsatcmd $cwd/mailbox 0
cat output
],
[You have mail from March Hare <hare@wonder.land>, regarding Invitation
])
m4_popdef([BIFFTEST])
m4_popdef([comsatcmd])
m4_popdef([BIFF_MBOX])
diff --git a/doc/texinfo/programs/comsatd.texi b/doc/texinfo/programs/comsatd.texi
index 15cbd3d..07fa516 100644
--- a/doc/texinfo/programs/comsatd.texi
+++ b/doc/texinfo/programs/comsatd.texi
@@ -1,21 +1,22 @@
@c This is part of the GNU Mailutils manual.
@c Copyright (C) 1999-2019 Free Software Foundation, Inc.
@c See file mailutils.texi for copying conditions.
@comment *******************************************************************
@pindex comsatd
Comsatd is the server which receives reports of incoming mail and
-notifies users, wishing to get this service. It can be started
-either from @file{inetd.conf} or as a standalone daemon.
+notifies users about it. By default, it prints subject, sender
+name and email, followed by first five lines of each newly arrived message
+to the tty of the recipient user. Users can customize this behavior.
@menu
* Starting comsatd:: Invocation.
* Configuring comsatd:: Configuration of @command{comsatd}.
* dot.biffrc:: A per-user configuration file.
@end menu
@node Starting comsatd
@subsection Starting @command{comsatd}
@table @option
@item -d
@@ -24,34 +25,51 @@ Run as a standalone daemon.
@item -i
@itemx --inetd
The server is started from @file{/etc/inetd.conf} file:
@example
comsat dgram udp wait root /usr/sbin/comsatd \
comsatd -c /etc/comsat.conf
@end example
This is the default operation mode.
-@item -t
-@itemx --test
+@item -t[@var{file}]
+@itemx --test[=@var{file}]
Test mode. In this mode, @command{comsatd} takes two arguments:
@acronym{URL} of a mailbox and @acronym{QID} of the message from that
-mailbox, e.g.:
+mailbox and prints the notification to the current user tty
+(@file{/dev/tty}), or @var{file}, if it is supplied. If the
+@file{~/.biffrc} file exists, it will be used. For example:
@example
$ comsatd --test /var/mail/root 34589
@end example
+Notice, that @var{file} is an optional argument. When supplied, it
+should follow the short option form immediately, or the long option
+form after the equals sign, e.g.:
+
+@example
+$ comsatd --test=logfile /var/mail/root 34589
+@end example
+
+@noindent
+or
+
+@example
+$ comsatd -tlogfile /var/mail/root 34589
+@end example
+
@item --foreground
Don't detach from the controlling terminal, remain in foreground.
@end table
See also @ref{Common Options}.
@node Configuring comsatd
@subsection Configuring @command{comsatd}
Following configuration statements affect the behavior of
@command{comsatd}:

Return to:

Send suggestions and report system problems to the System administrator.