Commit ac08a857 ac08a8575ae8ea3b85180bd05464a48768f398ee by Sergey Poznyakoff

comsat: Use mu streams instead of stdio

* comsat/action.c (action_beep, echo_string)
(action_echo, action_exec): Take mu_stream_t as first argument.
(open_rc): Take mu_stream_t as tty, return mu_stream_t as well.
Install the linecon filter.
(run_user_action): Take mu_stream_t as first arg.  Pass it to all
invoked actions.
* comsat/comsat.c (get_newline_str): Remove.
(need_crlf): New function.
(notify_user): Use mu_stream_t instead of FILE.
Install a 7bit filter and CRLF filter (if the device requires it).
* comsat/comsat.h: Include mailutils/filter.h.
(run_user_action): Change signature.
1 parent c2b48051
......@@ -17,7 +17,7 @@
#include "comsat.h"
#include <mailutils/io.h>
#include <mailutils/filter.h>
#include <mailutils/argcv.h>
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
#include <obstack.h>
......@@ -188,65 +188,46 @@ const char *default_action =
"$B(,5)\n"
"---\n";
/* Take care to clear eighth bit, so we won't upset some stupid terminals */
#define LB(c) ((c)&0x7f)
static void
action_beep (FILE *tty)
action_beep (mu_stream_t tty)
{
fprintf (tty, "\a\a");
mu_stream_write (tty, "\a\a", 2, NULL);
mu_stream_flush (tty);
}
static void
echo_string (FILE *tty, const char *cr, char *str)
echo_string (mu_stream_t tty, char *str)
{
if (!str)
return;
for (; *str; str++)
{
if (*str == '\n')
fprintf (tty, "%s", cr);
else
{
char c = LB (*str);
putc (c, tty);
}
}
fflush (tty);
mu_stream_write (tty, str, strlen (str), NULL);
}
static void
action_echo (FILE *tty, const char *cr, int omit_newline,
int argc, char **argv)
action_echo (mu_stream_t tty, int omit_newline, int argc, char **argv)
{
int i;
if (omit_newline)
{
argc--;
argv++;
}
for (i = 0;;)
{
echo_string (tty, cr, argv[i]);
echo_string (tty, argv[i]);
if (++i < argc)
echo_string (tty, cr, " ");
echo_string (tty, " ");
else
{
if (!omit_newline)
echo_string (tty, cr, "\n");
break;
}
break;
}
if (!omit_newline)
echo_string (tty, "\n");
}
static void
action_exec (FILE *tty, int argc, char **argv)
action_exec (mu_stream_t tty, int argc, char **argv)
{
pid_t pid;
mu_stream_t pstream;
struct stat stb;
char *command;
int status;
if (argc == 0)
{
mu_diag_output (MU_DIAG_ERROR, _("no arguments for exec"));
......@@ -272,22 +253,30 @@ action_exec (FILE *tty, int argc, char **argv)
return;
}
pid = fork ();
if (pid == 0)
/* FIXME: Redirect stderr to out */
/* FIXME: need this:
status = mu_prog_stream_create_argv (&pstream, argv[0], argv,
MU_STREAM_READ);
*/
status = mu_argcv_join (argc, argv, " ", mu_argcv_escape_no, &command);
if (status)
{
close (1);
close (2);
dup2 (fileno (tty), 1);
dup2 (fileno (tty), 2);
fclose (tty);
execv (argv[0], argv);
mu_diag_output (MU_DIAG_ERROR, _("cannot execute %s: %s"), argv[0], strerror (errno));
exit (0);
mu_diag_funcall (MU_DIAG_ERROR, "mu_argcv_join", NULL, status);
return;
}
status = mu_prog_stream_create (&pstream, command, MU_STREAM_READ);
if (status)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_prog_stream_create_argv", argv[0],
status);
return;
}
mu_stream_copy (tty, pstream, 0, NULL);
mu_stream_destroy (&pstream);
}
static mu_stream_t
open_rc (const char *filename, FILE *tty)
open_rc (const char *filename, mu_stream_t tty)
{
struct stat stb;
struct passwd *pw = getpwnam (username);
......@@ -307,8 +296,8 @@ open_rc (const char *filename, FILE *tty)
}
if ((stb.st_mode & 0777) != 0600)
{
fprintf (tty, "%s\r\n",
_("Warning: your .biffrc has wrong permissions"));
mu_stream_printf (tty, "%s\n",
_("Warning: your .biffrc has wrong permissions"));
mu_diag_output (MU_DIAG_NOTICE, _("%s's %s has wrong permissions"),
username, filename);
return NULL;
......@@ -319,8 +308,8 @@ open_rc (const char *filename, FILE *tty)
{
if (rc != ENOENT)
{
fprintf (tty, _("Cannot open .biffrc file: %s\r\n"),
mu_strerror (rc));
mu_stream_printf (tty, _("Cannot open .biffrc file: %s\n"),
mu_strerror (rc));
mu_diag_output (MU_DIAG_NOTICE, _("cannot open %s for %s: %s"),
filename, username, mu_strerror (rc));
}
......@@ -331,8 +320,9 @@ open_rc (const char *filename, FILE *tty)
mu_stream_unref (input);
if (rc)
{
fprintf (tty, _("Cannot create filter for your .biffrc file: %s\r\n"),
mu_strerror (rc));
mu_stream_printf (tty,
_("Cannot create filter for your .biffrc file: %s\n"),
mu_strerror (rc));
mu_diag_output (MU_DIAG_NOTICE,
_("cannot create filter for file %s of %s: %s"),
filename, username, mu_strerror (rc));
......@@ -342,7 +332,7 @@ open_rc (const char *filename, FILE *tty)
}
void
run_user_action (FILE *tty, const char *cr, mu_message_t msg)
run_user_action (mu_stream_t tty, mu_message_t msg)
{
mu_stream_t input;
int nact = 0;
......@@ -403,8 +393,14 @@ run_user_action (FILE *tty, const char *cr, mu_message_t msg)
if (strcmp (ws.ws_wordv[0], "echo") == 0)
{
action_echo (tty, cr, n_option,
ws.ws_wordc - 1, ws.ws_wordv + 1);
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)
......@@ -414,9 +410,9 @@ run_user_action (FILE *tty, const char *cr, mu_message_t msg)
}
else
{
fprintf (tty, _(".biffrc:%d: unknown keyword"),
locus.mu_line);
fprintf (tty, "\r\n");
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;
......@@ -424,6 +420,8 @@ run_user_action (FILE *tty, const char *cr, mu_message_t msg)
}
}
mu_wordsplit_free (&ws);
/* FIXME: line number is incorrect if .biffrc contains
escaped newlines */
locus.mu_line++;
}
mu_stream_destroy (&input);
......@@ -433,5 +431,5 @@ run_user_action (FILE *tty, const char *cr, mu_message_t msg)
}
if (nact == 0)
echo_string (tty, cr, expand_line (default_action, msg));
echo_string (tty, expand_line (default_action, msg));
}
......
......@@ -358,19 +358,22 @@ comsat_connection (int fd, struct sockaddr *sa, int salen,
return 0;
}
static const char *
get_newline_str (FILE *fp)
static int
need_crlf (mu_stream_t str)
{
#if defined(OPOST) && defined(ONLCR)
mu_transport_t trans[2];
struct termios tbuf;
tcgetattr (fileno (fp), &tbuf);
if ((tbuf.c_oflag & OPOST) && (tbuf.c_oflag & ONLCR))
return "\n";
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 "\r\n";
return 1;
#else
return "\r\n"; /* Just in case */
return 1; /* Just in case */
#endif
}
......@@ -380,21 +383,43 @@ static void
notify_user (const char *user, const char *device, const char *path,
mu_message_qid_t qid)
{
FILE *fp;
const char *cr;
mu_stream_t out, dev;
mu_mailbox_t mbox = NULL;
mu_message_t msg;
int status;
if (change_user (user))
return;
if ((fp = fopen (device, "w")) == NULL)
status = mu_file_stream_create (&dev, device, MU_STREAM_WRITE);
if (status)
{
mu_error (_("cannot open device %s: %s"), device, mu_strerror (errno));
mu_error (_("cannot open device %s: %s"), device, mu_strerror (status));
return;
}
cr = get_newline_str (fp);
mu_stream_set_buffer (dev, mu_buffer_line, 0);
status = mu_filter_create (&out, dev, "7bit", MU_FILTER_ENCODE,
MU_STREAM_WRITE);
mu_stream_unref (dev);
if (status)
{
mu_error (_("cannot create 7bit filter: %s"), mu_strerror (status));
return;
}
if (need_crlf (out))
{
mu_stream_t str;
status = mu_filter_create (&str, out, "CRLF", MU_FILTER_ENCODE,
MU_STREAM_WRITE);
mu_stream_unref (out);
if (status)
{
mu_error (_("cannot create crlf filter: %s"), mu_strerror (status));
return;
}
out = str;
}
if (!path)
{
......@@ -403,8 +428,9 @@ notify_user (const char *user, const char *device, const char *path,
return;
}
if ((status = mu_mailbox_create (&mbox, path)) != 0
|| (status = mu_mailbox_open (mbox, MU_STREAM_READ|MU_STREAM_QACCESS)) != 0)
if ((status = mu_mailbox_create (&mbox, path)) != 0 ||
(status = mu_mailbox_open (mbox,
MU_STREAM_READ|MU_STREAM_QACCESS)) != 0)
{
mu_error (_("cannot open mailbox %s: %s"),
path, mu_strerror (status));
......@@ -419,8 +445,8 @@ notify_user (const char *user, const char *device, const char *path,
return; /* FIXME: Notify the user, anyway */
}
run_user_action (fp, cr, msg);
fclose (fp);
run_user_action (out, msg);
mu_stream_destroy (&out);
}
/* Search utmp for the local user */
......
......@@ -60,6 +60,7 @@
#include <mailutils/acl.h>
#include <mailutils/server.h>
#include <mailutils/cctype.h>
#include <mailutils/filter.h>
#ifndef INADDR_NONE
# define INADDR_NONE -1
......@@ -77,5 +78,5 @@ extern const char *username;
extern char *hostname;
extern struct daemon_param daemon_param;
void run_user_action (FILE *tty, const char *cr, mu_message_t msg);
void run_user_action (mu_stream_t str, mu_message_t msg);
......