Commit 4ad8290a 4ad8290ab5e7796b9c0bcf0a64ad4e41fd7527db by Sergey Poznyakoff

Added to the repository

1 parent bb5c8d24
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 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 2, 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Functions shared between comp and forw utilities */
#include <mh.h>
#include <sys/types.h>
#include <sys/stat.h>
static char *default_format_str =
"To:\n"
"cc:\n"
"Subject:\n"
"--------\n";
void
mh_comp_draft (char *formfile, char *defformfile, char *draftfile)
{
char *s = NULL;
if (formfile)
{
s = mh_expand_name (MHLIBDIR, formfile, 0);
if (mh_file_copy (s, draftfile) == 0)
exit (1);
}
else
{
s = mh_expand_name (MHLIBDIR, defformfile, 0);
if (access (s, R_OK) == 0)
{
if (mh_file_copy (s, draftfile) == 0)
exit (1);
}
else
{
int rc;
stream_t stream;
if ((rc = file_stream_create (&stream,
draftfile,
MU_STREAM_WRITE|MU_STREAM_CREAT)) != 0
|| (rc = stream_open (stream)))
{
mh_error (_("cannot open output file \"%s\": %s"),
draftfile, mu_strerror (rc));
exit (1);
}
rc = stream_sequential_write (stream,
default_format_str,
strlen (default_format_str));
stream_close (stream);
stream_destroy (&stream, stream_get_owner (stream));
if (rc)
{
mh_error (_("error writing to \"%s\": %s"),
draftfile, mu_strerror (rc));
exit (1);
}
}
}
free (s);
}
int
check_draft_disposition (struct mh_whatnow_env *wh, int use_draft)
{
struct stat st;
int disp = DISP_REPLACE;
/* First check if the draft exists */
if (stat (wh->draftfile, &st) == 0)
{
if (use_draft)
disp = DISP_USE;
else
{
printf (_("Draft \"%s\" exists (%lu bytes).\n"),
wh->draftfile, (unsigned long) st.st_size);
disp = mh_disposition (wh->draftfile);
}
}
return disp;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 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 2, 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* MH forw command */
#include <mh.h>
const char *argp_program_version = "forw (" PACKAGE_STRING ")";
static char doc[] = N_("GNU MH forw\v"
"Options marked with `*' are not yet implemented.\n"
"Use -help to obtain the list of traditional MH options.");
static char args_doc[] = "[msgs]";
/* GNU options */
static struct argp_option options[] = {
{"annotate", ARG_ANNOTATE, N_("BOOL"), OPTION_ARG_OPTIONAL,
N_("* Add Replied: header to the message being replied to")},
{"build", ARG_BUILD, 0, 0,
N_("Build the draft and quit immediately.")},
{"draftfolder", ARG_DRAFTFOLDER, N_("FOLDER"), 0,
N_("Specify the folder for message drafts")},
{"nodraftfolder", ARG_NODRAFTFOLDER, 0, 0,
N_("Undo the effect of the last --draftfolder option")},
{"draftmessage" , ARG_DRAFTMESSAGE, N_("MSG"), 0,
N_("Invoke the draftmessage facility")},
{"folder", ARG_FOLDER, N_("FOLDER"), 0,
N_("Specify folder to operate upon")},
{"editor", ARG_EDITOR, N_("PROG"), 0,
N_("Set the editor program to use")},
{"noedit", ARG_NOEDIT, 0, 0,
N_("Suppress the initial edit")},
{"format", ARG_FORMAT, N_("BOOL"), 0,
N_("Format messages")},
{"noformat", ARG_NOFORMAT, NULL, 0,
N_("Undo the effect of the last --format option") },
{"form", ARG_FORM, N_("FILE"), 0,
N_("Read format from given file")},
{"filter", ARG_FILTER, N_("FILE"), 0,
N_("Use filter FILE to preprocess the body of the message") },
{"nofilter", ARG_NOFILTER, NULL, 0,
N_("Undo the effect of the last --filter option") },
{"inplace", ARG_INPLACE, N_("BOOL"), OPTION_ARG_OPTIONAL,
N_("* Annotate the message in place")},
{"noinplace", ARG_NOINPLACE, 0, OPTION_HIDDEN, "" },
{"mime", ARG_MIME, N_("BOOL"), OPTION_ARG_OPTIONAL,
N_("* Use MIME encapsulation") },
{"nomime", ARG_NOMIME, NULL, OPTION_HIDDEN, "" },
{"width", ARG_WIDTH, N_("NUMBER"), 0, N_("Set output width")},
{"whatnowproc", ARG_WHATNOWPROC, N_("PROG"), 0,
N_("* Set the replacement for whatnow program")},
{"nowhatnowproc", ARG_NOWHATNOWPROC, NULL, 0,
N_("* Ignore whatnowproc variable. Use standard `whatnow' shell instead.")},
{"use", ARG_USE, N_("BOOL"), OPTION_ARG_OPTIONAL,
N_("Use draft file preserved after the last session") },
{NULL},
};
/* Traditional MH options */
struct mh_option mh_option[] = {
{"annotate", 1, MH_OPT_BOOL },
{"build", 1, },
{"form", 4, MH_OPT_ARG, "formatfile"},
{"format", 5, MH_OPT_ARG, "string"},
{"draftfolder", 6, MH_OPT_ARG, "folder"},
{"nodraftfolder", 3 },
{"draftmessage", 6, },
{"editor", 1, MH_OPT_ARG, "program"},
{"noedit", 3, },
{"filter", 2, MH_OPT_ARG, "program"},
{"inplace", 1, MH_OPT_BOOL },
{"whatnowproc", 2, MH_OPT_ARG, "program"},
{"nowhatnowproc", 3 },
{"mime", 2, MH_OPT_BOOL, NULL},
{NULL}
};
static char *formfile;
struct mh_whatnow_env wh_env = { 0 };
static int initial_edit = 1;
static char *mhl_filter = NULL; /* --filter flag */
static int build_only = 0; /* --build flag */
static int do_format = 0; /* --format flag */
static int mime_encap = 0; /* --mime flag */
static int use_draft = 0; /* --use flag */
static int width = 80; /* --width flag */
static mh_msgset_t msgset;
static mailbox_t mbox;
static int
opt_handler (int key, char *arg, void *unused, struct argp_state *state)
{
switch (key)
{
case ARG_BUILD:
build_only = 1;
break;
case ARG_DRAFTFOLDER:
wh_env.draftfolder = arg;
break;
case ARG_DRAFTMESSAGE:
wh_env.draftmessage = arg;
break;
case ARG_USE:
use_draft = is_true (arg);
break;
case ARG_WIDTH:
width = strtoul (arg, NULL, 0);
if (!width)
{
argp_error (state, _("Invalid width"));
exit (1);
}
break;
case ARG_EDITOR:
wh_env.editor = arg;
break;
case ARG_FOLDER:
current_folder = arg;
break;
case ARG_FORM:
formfile = arg;
break;
case ARG_FORMAT:
do_format = is_true (arg);
break;
case ARG_NOFORMAT:
do_format = 0;
break;
case ARG_FILTER:
mhl_filter = arg;
break;
case ARG_MIME:
mime_encap = is_true (arg);
break;
case ARG_NOMIME:
mime_encap = 0;
break;
case ARG_ANNOTATE:
case ARG_INPLACE:
case ARG_WHATNOWPROC:
case ARG_NOWHATNOWPROC:
argp_error (state, _("option is not yet implemented"));
exit (1);
default:
return 1;
}
return 0;
}
struct format_data {
int num;
stream_t stream;
list_t format;
};
static int
msg_copy (message_t msg, stream_t ostream)
{
stream_t istream;
int rc;
size_t n;
char buf[512];
rc = message_get_stream (msg, &istream);
if (rc)
return rc;
stream_seek (istream, 0, SEEK_SET);
while (rc == 0
&& stream_sequential_read (istream, buf, sizeof buf, &n) == 0
&& n > 0)
rc = stream_sequential_write (ostream, buf, n);
return rc;
}
void
format_message (mailbox_t mbox, message_t msg, size_t num, void *data)
{
struct format_data *fp = data;
char *s;
int rc;
if (fp->num)
{
asprintf (&s, "\n------- Message %d\n", fp->num++);
rc = stream_sequential_write (fp->stream, s, strlen (s));
free (s);
}
if (fp->format)
rc = mhl_format_run (fp->format, width, 0, 0, 0, msg, fp->stream);
else
rc = msg_copy (msg, fp->stream);
}
void
finish_draft ()
{
int rc;
stream_t stream;
list_t format = NULL;
struct format_data fd;
char *str;
if (!mhl_filter)
{
char *s = mh_expand_name (MHLIBDIR, "mhl.forward", 0);
if (access (s, R_OK) == 0)
mhl_filter = "mhl.forward";
free (s);
}
if (mhl_filter)
{
char *s = mh_expand_name (MHLIBDIR, mhl_filter, 0);
format = mhl_format_compile (s);
if (!format)
exit (1);
free (s);
}
if ((rc = file_stream_create (&stream,
wh_env.file,
MU_STREAM_WRITE|MU_STREAM_CREAT)) != 0
|| (rc = stream_open (stream)))
{
mh_error (_("cannot open output file \"%s\": %s"),
wh_env.file, mu_strerror (rc));
exit (1);
}
stream_seek (stream, 0, SEEK_END);
str = "\n------- ";
rc = stream_sequential_write (stream, str, strlen (str));
if (msgset.count == 1)
{
fd.num = 0;
str = _("Forwarded message\n");
}
else
{
fd.num = 1;
str = _("Forwarded messages\n");
}
rc = stream_sequential_write (stream, str, strlen (str));
fd.stream = stream;
fd.format = format;
rc = mh_iterate (mbox, &msgset, format_message, &fd);
str = "\n------- ";
rc = stream_sequential_write (stream, str, strlen (str));
if (msgset.count == 1)
str = _("End of Forwarded message");
else
str = _("End of Forwarded messages");
rc = stream_sequential_write (stream, str, strlen (str));
stream_close (stream);
stream_destroy (&stream, stream_get_owner (stream));
}
int
main (int argc, char **argv)
{
int index;
/* Native Language Support */
mu_init_nls ();
mh_argp_parse (argc, argv, 0, options, mh_option, args_doc, doc,
opt_handler, NULL, &index);
argc -= index;
argv += index;
mbox = mh_open_folder (current_folder, 0);
mh_msgset_parse (mbox, &msgset, argc, argv, "cur");
if (!wh_env.draftfolder)
wh_env.draftfolder = mh_global_profile_get ("Draft-Folder",
mu_path_folder_dir);
wh_env.file = mh_expand_name (wh_env.draftfolder, "forw", 0);
if (!wh_env.draftfile)
wh_env.draftfile = mh_expand_name (wh_env.draftfolder, "draft", 0);
switch (build_only ?
DISP_REPLACE : check_draft_disposition (&wh_env, use_draft))
{
case DISP_QUIT:
exit (0);
case DISP_USE:
unlink (wh_env.file);
rename (wh_env.draftfile, wh_env.file);
break;
case DISP_REPLACE:
unlink (wh_env.draftfile);
mh_comp_draft (formfile, "forwcomps", wh_env.file);
finish_draft ();
}
/* Exit immediately if --build is given */
if (build_only)
{
rename (wh_env.file, wh_env.draftfile);
return 0;
}
return mh_whatnow (&wh_env, initial_edit);
}