repl.c 5.67 KB
/* GNU mailutils - a suite of utilities for electronic mail
   Copyright (C) 2002 Free Software Foundation, Inc.

   This program 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.

   This program 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 this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* MH reply command */

#include <mh.h>

const char *argp_program_version = "reply (" PACKAGE_STRING ")";
static char doc[] = "GNU MH reply";
static char args_doc[] = "[+folder] [msg]";

#define ARG_NOEDIT      1
#define ARG_FCC         2
#define ARG_FILTER      3
#define ARG_INPLACE     4
#define ARG_QUERY       5  
#define ARG_WHATNOWPROC 6
#define ARG_NOWHATNOWPROC 7
#define ARG_NODRAFTFOLDER 8

/* GNU options */
static struct argp_option options[] = {
  {"annotate", 'a', "BOOL", OPTION_ARG_OPTIONAL,
   "Add Replied: header to the message being replied to"},
  {"draftfolder", 'd', "FOLDER", 0,
   "Invoke the draftfolder facility"},
  {"draftmessage" , 'm', "MSG", 0,
   "Invoke the draftmessage facility"},
  {"cc",       'c', "{all|to|cc|me}", 0,
   "Specify whom to place on the Cc: list of the reply"},
  {"nocc",     'n', "{all|to|cc|me}", 0,
   "Specify whom to remove from the Cc: list of the reply"},
  {"folder",  'f', "FOLDER", 0, "Specify folder to operate upon"},
  {"editor",  'e', "PROG", 0, "Set the editor program to use"},
  {"noedit", ARG_NOEDIT, 0, 0, "Suppress the initial edit"},
  {"fcc",    ARG_FCC, "FOLDER", 0, "Set the folder to receive Fcc's."},
  {"filter", ARG_FILTER, "PROG", 0,
   "Set the filter program to preprocess the body of the message being replied"},
  {"form",   'F', "FILE", 0, "Read format from given file"},
  {"inplace", ARG_INPLACE, "BOOL", 0, "Annotate the message in place"},
  {"query", ARG_QUERY, "BOOL", 0, "Query for addresses to place in To: and Cc: lists"},
  {"width", 'w', "NUMBER", 0, "Set output width"},
  {"whatnowproc", ARG_WHATNOWPROC, "PROG", 0,
   "Set the relacement for whatnow program"},
  { "\nUse -help switch to obtain the list of traditional MH options. ", 0, 0, OPTION_DOC, "" },
  { 0 }
};

/* Traditional MH options */
struct mh_option mh_option[] = {
  {"annotate", 1, 'a', MH_OPT_BOOL },
  {"cc", 1, 'c', MH_OPT_ARG, "all/to/cc/me"},
  {"nocc", 3, 'n', MH_OPT_ARG, "all/to/cc/me"},
  {"form",    4,  'F', MH_OPT_ARG, "formatfile"},
  {"width",   1,  'w', MH_OPT_ARG, "number"},
  {"draftfolder", 6, 'd', MH_OPT_ARG, "folder"},
  {"nodraftfolder", 3, ARG_NODRAFTFOLDER, },
  {"editor", 1, 'e', MH_OPT_ARG, "program"},
  {"noedit", 3, ARG_NOEDIT, },
  {"fcc", 1, ARG_FCC, MH_OPT_ARG, "folder"},
  {"filter", 2, ARG_FILTER, MH_OPT_ARG, "program"},
  {"inplace", 1, ARG_INPLACE, MH_OPT_BOOL },
  {"query", 1, ARG_QUERY, MH_OPT_BOOL },
  {"whatnowproc", 2, ARG_WHATNOWPROC, MH_OPT_ARG, "program"},
  {"nowhatnowproc", 3, ARG_NOWHATNOWPROC },
  { 0 }
};

static char *format_str =
"%(lit)%(formataddr %<{reply-to}%?{from}%?{sender}%?{return-path}%>)"
"%<(nonnull)%(void(width))%(putaddr To: )\\n%>"
"%(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))"
"%<(nonnull)%(void(width))%(putaddr cc: )\\n%>"
"%<{fcc}Fcc: %{fcc}\\n%>"
"%<{subject}Subject: Re: %{subject}\\n%>"
"%<{date}In-reply-to: Your message of \""
"%<(nodate{date})%{date}%|%(pretty{date})%>.\"%<{message-id}\n"
"             %{message-id}%>\\n%>"
"--------\n";

static mh_format_t format;
static int width = 80;
static char *draft_file;
static mh_msgset_t msgset;
static mailbox_t mbox;

static int
opt_handler (int key, char *arg, void *unused)
{
  switch (key)
    {
    case '+':
    case 'f': 
      current_folder = arg;
      break;

    case 'F':
      mh_read_formfile (arg, &format_str);
      break;

    case 'w':
      width = strtoul (arg, NULL, 0);
      if (!width)
	{
	  mh_error ("Invalid width");
	  exit (1);
	}
      break;

    case 'a':
    case 'd':
    case 'm':
    case 'c':
    case 'n':
    case 'e':
    case ARG_NOEDIT:
    case ARG_FCC:
    case ARG_FILTER:
    case ARG_INPLACE:
    case ARG_QUERY:
    case ARG_WHATNOWPROC:
      mh_error ("option is not yet implemented");
      exit (1);
      
    default:
      return 1;
    }
  return 0;
}

void
make_draft ()
{
  int rc;
  message_t msg;
  FILE *fp;
  char buffer[1024];
#define bufsize sizeof(buffer)

  /* FIXME: first check if the draft exists */
  fp = fopen (draft_file, "w+");
  if (!fp)
    {
      mh_error ("cannot open draft file %s: %s",
		draft_file, strerror (errno));
      exit (1);
    }
  
  rc = mailbox_get_message (mbox, msgset.list[0], &msg);
  if (rc)
    {
      mh_error ("cannot read message %lu: %s",
		(unsigned long) msgset.list[0],
		mu_errstring (rc));
      exit (1);
    }
  
  mh_format (&format, msg, msgset.list[0], buffer, bufsize);
  fprintf (fp, "%s", buffer);
  fclose (fp);
}

int
main (int argc, char **argv)
{
  int index;
  
  mh_argp_parse (argc, argv, options, mh_option, args_doc, doc,
		 opt_handler, NULL, &index);
  if (mh_format_parse (format_str, &format))
    {
      mh_error ("Bad format string");
      exit (1);
    }

  mbox = mh_open_folder (current_folder, 0);
  mh_msgset_parse (mbox, &msgset, argc - index, argv + index, "cur");
  if (msgset.count != 1)
    {
      mh_error ("only one message at a time!");
      return 1;
    }

  draft_file = mh_expand_name ("draft", 0);
  
  make_draft ();
  
  return 0;
}