Commit 835ee6b0 835ee6b03a098d8566e9b9ba2c22ab2403d41cba by Sergey Poznyakoff

comsat: improve tty handling, add testsuite.

* comsat/action.c (need_crlf, _open_tty, open_tty): Moved from comsat.c
(open_default_tty): New function.
(run_user_action): Take device name as first argument.
Reuse wordsplit memory.
* comsat/comsat.c (notify_user): Update invocation of run_user_action.
* comsat/comsat.h (open_tty): Remove prototype.
(run_user_action): Change signature.
* configure.ac: Add comsat tests.
* comsat/Makefile.am (SUBDIRS): Add tests.
* comsat/tests/.gitignore: New file.
* comsat/tests/Makefile.am: New file.
* comsat/tests/atlocal.in: New file.
* comsat/tests/testsuite.at: New file.
1 parent 2cbe825e
......@@ -16,7 +16,7 @@
## along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
INCLUDES = @MU_APP_COMMON_INCLUDES@
SUBDIRS = . tests
sbin_PROGRAMS = comsatd
comsatd_SOURCES = action.c comsat.c comsat.h
......
......@@ -325,12 +325,129 @@ open_rc (const char *filename, mu_stream_t tty)
return stream;
}
static int
need_crlf (mu_stream_t str)
{
#if defined(OPOST) && defined(ONLCR)
mu_transport_t trans[2];
struct termios tbuf;
if (mu_stream_ioctl (str, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans))
return 1; /* suppose we do need it */
if (tcgetattr ((int)trans[0], &tbuf) == 0 &&
(tbuf.c_oflag & OPOST) && (tbuf.c_oflag & ONLCR))
return 0;
else
return 1;
#else
return 1; /* Just in case */
#endif
}
static mu_stream_t
_open_tty (const char *device, int argc, char **argv)
{
mu_stream_t dev, base_dev, prev_stream;
int status;
status = mu_file_stream_create (&dev, device, MU_STREAM_WRITE);
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)
{
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)
{
argc--;
argv++;
}
}
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));
}
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);
}
void
run_user_action (mu_stream_t tty, mu_message_t msg)
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);
if (!tty)
return;
input = open_rc (biffrc, tty);
if (input)
{
......@@ -340,6 +457,8 @@ run_user_action (mu_stream_t tty, mu_message_t msg)
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);
......@@ -350,16 +469,15 @@ run_user_action (mu_stream_t tty, mu_message_t msg)
}
else
locus.mu_file = rcname;
locus.mu_line = 1;
locus.mu_col = 0;
ws.ws_comment = "#";
wsflags = MU_WRDSF_DEFFLAGS | MU_WRDSF_COMMENT;
while (mu_stream_getline (input, &stmt, &size, &n) == 0 && n > 0)
{
struct mu_wordsplit ws;
ws.ws_comment = "#";
if (mu_wordsplit (stmt, &ws,
MU_WRDSF_DEFFLAGS | MU_WRDSF_COMMENT) == 0
&& ws.ws_wordc)
if (mu_wordsplit (stmt, &ws, wsflags) == 0 && ws.ws_wordc)
{
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_LOCUS, &locus);
......@@ -428,11 +546,12 @@ run_user_action (mu_stream_t tty, mu_message_t msg)
}
}
}
mu_wordsplit_free (&ws);
wsflags |= MU_WRDSF_REUSE;
/* FIXME: line number is incorrect if .biffrc contains
escaped newlines */
locus.mu_line++;
}
mu_wordsplit_free (&ws);
mu_stream_destroy (&input);
mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL);
......@@ -441,4 +560,5 @@ run_user_action (mu_stream_t tty, mu_message_t msg)
if (nact == 0)
echo_string (tty, expand_line (default_action, msg));
mu_stream_destroy (&tty);
}
......
......@@ -365,131 +365,19 @@ comsat_connection (int fd, struct sockaddr *sa, int salen,
return 0;
}
static int
need_crlf (mu_stream_t str)
{
#if defined(OPOST) && defined(ONLCR)
mu_transport_t trans[2];
struct termios tbuf;
if (mu_stream_ioctl (str, MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, trans))
return 1; /* suppose we do need it */
if (tcgetattr ((int)trans[0], &tbuf) == 0 &&
(tbuf.c_oflag & OPOST) && (tbuf.c_oflag & ONLCR))
return 0;
else
return 1;
#else
return 1; /* Just in case */
#endif
}
static mu_stream_t
_open_tty (const char *device, int argc, char **argv)
{
mu_stream_t dev, base_dev, prev_stream;
int status;
status = mu_file_stream_create (&dev, device, MU_STREAM_WRITE);
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)
{
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)
{
argc--;
argv++;
}
}
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));
}
else
dev = _open_tty (device, argc, argv);
return dev;
}
/* NOTE: Do not bother to free allocated memory, as the program exits
immediately after executing this */
static void
notify_user (const char *user, const char *device, const char *path,
mu_message_qid_t qid)
{
mu_stream_t dev;
mu_mailbox_t mbox = NULL;
mu_message_t msg;
static char *default_filters[] = { "7bit", "+", "?CRLF", NULL };
int status;
if (change_user (user))
return;
dev = open_tty (device, MU_ARRAY_SIZE (default_filters) - 1,
default_filters);
if (!dev)
return;
if (!path)
{
path = mailbox_path (user);
......@@ -514,8 +402,7 @@ notify_user (const char *user, const char *device, const char *path,
return; /* FIXME: Notify the user, anyway */
}
run_user_action (dev, msg);
mu_stream_destroy (&dev);
run_user_action (device, msg);
}
/* Search utmp for the local user */
......@@ -683,7 +570,7 @@ main (int argc, char **argv)
}
}
if (biffrc[0] == '.')
if (biffrc[0] == '.' && biffrc[1] == '/')
{
char *cwd = mu_getcwd ();
biffrc = mu_make_file_name (cwd, biffrc);
......
......@@ -79,6 +79,5 @@ extern char *hostname;
extern struct daemon_param daemon_param;
extern char *biffrc;
void run_user_action (mu_stream_t str, mu_message_t msg);
mu_stream_t open_tty (const char *device, int argc, char **argv);
void run_user_action (const char *device, mu_message_t msg);
......
atconfig
atlocal
package.m4
status.mf
testsuite
testsuite.dir
testsuite.log
# This file is part of GNU Mailutils.
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# GNU Mailutils is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3, or (at
# your option) any later version.
#
# 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/>.
EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4
DISTCLEANFILES = atconfig $(check_SCRIPTS)
MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
## ------------ ##
## package.m4. ##
## ------------ ##
$(srcdir)/package.m4: $(top_srcdir)/configure.ac
$(AM_V_GEN){ \
echo '# Signature of the current package.'; \
echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \
echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \
echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \
echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \
echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \
} >$(srcdir)/package.m4
#
## ------------ ##
## Test suite. ##
## ------------ ##
TESTSUITE_AT = testsuite.at
TESTSUITE = $(srcdir)/testsuite
M4=m4
AUTOTEST = $(AUTOM4TE) --language=autotest
$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(top_srcdir)/testsuite/testsuite.inc
$(AM_V_GEN)$(AUTOTEST) -I $(srcdir) -I $(top_srcdir)/testsuite testsuite.at -o $@.tmp
$(AM_V_at)mv $@.tmp $@
atconfig: $(top_builddir)/config.status
cd $(top_builddir) && ./config.status tests/$@
clean-local:
@test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean
check-local: atconfig atlocal $(TESTSUITE)
@$(SHELL) $(TESTSUITE)
# Run the test suite on the *installed* tree.
#installcheck-local:
# $(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin
# @configure_input@ -*- shell-script -*-
# Configurable variable values for Mailutils test suite.
# Copyright (C) 2004, 2010 Free Software Foundation, Inc.
PATH=@abs_builddir@:@abs_top_builddir@/comsat:$top_srcdir:$srcdir:$PATH
# This file is part of GNU Mailutils. -*- Autotest -*-
# Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
#
# GNU Mailutils is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3, or (at
# your option) any later version.
#
# 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/>.
m4_include([testsuite.inc])
dnl ------------------------------------------------------------
dnl mailbox for comsatd
m4_pushdef([BIFF_MBOX],[`pwd`/mailbox])
dnl ------------------------------------------------------------
dnl comsatcmd
m4_pushdef([comsatcmd],[comsatd --no-site --no-user --file ./biff.rc dnl
--set logging.syslog=no --test])
dnl ------------------------------------------------------------
dnl BIFFTEST(DESCR, KW, DATA, CMDLINE, [STDOUT = `'], [STDERR = `'])
dnl
m4_pushdef([BIFFTEST],[
AT_SETUP([comsatd: $1])
AT_KEYWORDS([comsatd $2])
$3
AT_CHECK([$4],[0],[$5],[$6])
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
EOT
chmod 600 biff.rc
> $cwd/output
],
[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
EOT
chmod 600 biff.rc
> $cwd/output
],
[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
EOT
chmod 600 biff.rc
> $cwd/output
],
[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
EOT
chmod 600 biff.rc
> $cwd/output
],
[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
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
cat output
],
[You have mail from March Hare <hare@wonder.land>, regarding Invitation
])
m4_popdef([BIFFTEST])
m4_popdef([comsatcmd])
m4_popdef([BIFF_MBOX])
......@@ -1212,6 +1212,7 @@ AC_CONFIG_TESTDIR(messages/tests)
AC_CONFIG_TESTDIR(readmsg/tests)
AC_CONFIG_TESTDIR(sieve/tests)
AC_CONFIG_TESTDIR(mh/tests)
AC_CONFIG_TESTDIR(comsat/tests)
AC_CONFIG_FILES([libmailutils/tests/Makefile
libmailutils/tests/atlocal
......@@ -1219,6 +1220,8 @@ AC_CONFIG_FILES([libmailutils/tests/Makefile
libmu_compat/tests/atlocal
testsuite/Makefile
testsuite/atlocal
comsat/tests/Makefile
comsat/tests/atlocal
frm/tests/Makefile
frm/tests/atlocal
maidag/tests/Makefile
......