Example #1
0
/* :comparator i;ascii-numeric */
static int
i_ascii_numeric_is (const char *pattern, const char *text)
{
  if (mu_isdigit (*pattern))
    {
      if (mu_isdigit (*text))
	return strtol (pattern, NULL, 10) == strtol (text, NULL, 10);
      else 
	return 0;
    }
  else if (mu_isdigit (*text))
    return 0;
  else
    return 1;
}
Example #2
0
static int
i_ascii_numeric_eq (const char *pattern, const char *text)
{
  if (mu_isdigit (*pattern))
    {
      if (mu_isdigit (*text))
	{
	  size_t a = strtoul (pattern, NULL, 10);
	  size_t b = strtoul (text, NULL, 10);
	  if (b > a)
	    return 1;
	  else if (b < a)
	    return -1;
	  return 0;
	}
      else 
	return 1;
    }
  else
    return 1;
}
Example #3
0
int
main (int argc, char **argv)
{
  int i;
  char *host = NULL;
  char *infile = NULL;
  char *port = NULL;
  int tls = 0;
  int raw = 1;
  int flags = 0;
  mu_stream_t stream;
  mu_smtp_t smtp;
  mu_stream_t instr;
  char *from = NULL;
  mu_list_t rcpt_list = NULL;
  mu_list_t meth_list = NULL;
  mu_list_t skiphdr_list = NULL;
  struct mu_sockaddr *sa;
  struct mu_sockaddr_hints hints;
  
  mu_set_program_name (argv[0]);
  mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
  
  if (argc < 2)
    usage ();

  memset (&hints, 0, sizeof (hints)); 
  hints.flags = MU_AH_DETECT_FAMILY;
  hints.port = 25;
  hints.protocol = IPPROTO_TCP;
  hints.socktype = SOCK_STREAM;

  MU_ASSERT (mu_smtp_create (&smtp));

  for (i = 1; i < argc; i++)
    {
      if (strncmp (argv[i], "port=", 5) == 0)
	port = argv[i] + 5;
      else if (strncmp (argv[i], "family=", 7) == 0)
	{
	  hints.flags &= ~MU_AH_DETECT_FAMILY;
	  switch (argv[i][7])
	    {
	    case '4':
	      hints.family = AF_INET;
	      break;
	    case '6':
	      hints.family = AF_INET6;
	      break;
	    default:
	      mu_error ("invalid family name: %s", argv[i]+7);
	      exit (1);
	    }
	}
      else if (strncmp (argv[i], "trace=", 6) == 0)
	{
	  char *arg = argv[i] + 6;

	  if (mu_isdigit (arg[0]))
	    mu_smtp_trace (smtp, atoi (argv[i] + 6) ?
			   MU_SMTP_TRACE_SET : MU_SMTP_TRACE_CLR);
	  else
	    {
	      mu_smtp_trace (smtp, MU_SMTP_TRACE_SET);
	      if (strcmp (arg, "secure") == 0)
		mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET,
				    MU_XSCRIPT_SECURE);
	      else if (strcmp (arg, "payload") == 0)
		mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET,
				    MU_XSCRIPT_PAYLOAD);
	    }
	}
      else if (strncmp (argv[i], "tls=", 4) == 0)
	tls = atoi (argv[i] + 4);
      else if (strncmp (argv[i], "domain=", 7) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN,
				      argv[i] + 7));
      else if (strncmp (argv[i], "user="******"pass="******"service=", 8) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_SERVICE,
				      argv[i] + 8));
      else if (strncmp (argv[i], "realm=", 6) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_REALM,
				      argv[i] + 6));
      else if (strncmp (argv[i], "host=", 5) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_HOST,
				      argv[i] + 5));
      else if (strncmp (argv[i], "url=", 4) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_URL,
				      argv[i] + 4));
      else if (strncmp (argv[i], "input=", 6) == 0)
	infile = argv[i] + 6;
      else if (strncmp (argv[i], "raw=", 4) == 0)
	raw = atoi (argv[i] + 4);
      else if (strncmp (argv[i], "rcpt=", 5) == 0)
	{
	  if (!rcpt_list)
	    MU_ASSERT (mu_list_create (&rcpt_list));
	  MU_ASSERT (mu_list_append (rcpt_list, argv[i] + 5));
	}
      else if (strncmp (argv[i], "from=", 5) == 0)
	from = argv[i] + 5;
      else if (strncmp (argv[i], "auth=", 5) == 0)
	update_list (&meth_list, argv[i] + 5);
      else if (strncmp (argv[i], "skiphdr=", 8) == 0)
	{
	  update_list (&skiphdr_list, argv[i] + 8);
	  raw = 0;
	}
      else if (host)
	{
	  mu_error ("server name already given: %s, new name %s?",
		    host, argv[i]);
	  exit (1);
	}
      else
	host = argv[i];
    }

  if (!host)
    usage ();

  if (!raw)
    flags = MU_STREAM_SEEK;
  if (infile)
    MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|flags));
  else
    MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, flags));
  
  host = argv[1];

  MU_ASSERT (mu_sockaddr_from_node (&sa, host, port, &hints));

  MU_ASSERT (mu_tcp_stream_create_from_sa (&stream, sa, NULL, MU_STREAM_RDWR));
  
  mu_smtp_set_carrier (smtp, stream);
  mu_stream_unref (stream);
  
  if (!from)
    {
      from = getenv ("USER");
      if (!from)
	{
	  mu_error ("cannot determine sender name");
	  exit (1);
	}
    }

  if (raw && !rcpt_list)
    {
      mu_error ("no recipients");
      exit (1);
    }
  
  MU_ASSERT (mu_smtp_open (smtp));
  MU_ASSERT (mu_smtp_ehlo (smtp));

  if (tls && mu_smtp_capa_test (smtp, "STARTTLS", NULL) == 0)
    {
      MU_ASSERT (mu_smtp_starttls (smtp));
      MU_ASSERT (mu_smtp_ehlo (smtp));
    }

  if (meth_list)
    {
      int status;
      
      MU_ASSERT (mu_smtp_add_auth_mech_list (smtp, meth_list));
      status = mu_smtp_auth (smtp);
      switch (status)
	{
	case 0:
	  MU_ASSERT (mu_smtp_ehlo (smtp));
	  break;
	  
	case ENOSYS:
	case MU_ERR_NOENT:
	  /* Ok, skip it */
	  break;

	default:
	  mu_error ("authentication failed: %s", mu_strerror (status));
	  exit (1);
	}
    }
  
  MU_ASSERT (mu_smtp_mail_basic (smtp, from, NULL));
  mu_list_foreach (rcpt_list, send_rcpt_command, smtp);
  
  if (raw)
    {
      /* Raw sending mode: send from the stream directly */
      MU_ASSERT (mu_smtp_send_stream (smtp, instr));
    }
  else
    {
      /* Message (standard) sending mode: send a MU message. */

      mu_message_t msg;
      mu_stream_t ostr, bstr;
      mu_header_t hdr;
      mu_iterator_t itr;
      mu_body_t body;

      if (skiphdr_list)
	mu_list_set_comparator (skiphdr_list, headercmp);
      
      MU_ASSERT (mu_stream_to_message (instr, &msg));
      mu_stream_unref (instr);
      MU_ASSERT (mu_smtp_data (smtp, &ostr));
      MU_ASSERT (mu_message_get_header (msg, &hdr));
      MU_ASSERT (mu_header_get_iterator (hdr, &itr));
      for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
	   mu_iterator_next (itr))
	{
	  const char *name;
	  void *value;

	  mu_iterator_current_kv (itr, (void*) &name, &value);
	  if (mu_list_locate (skiphdr_list, (void*) name, NULL) == 0)
	    continue;

	  mu_stream_printf (ostr, "%s: %s\n", name, (char*)value);
	}
      mu_iterator_destroy (&itr);
      MU_ASSERT (mu_stream_write (ostr, "\n", 1, NULL));
      
      MU_ASSERT (mu_message_get_body (msg, &body));
      MU_ASSERT (mu_body_get_streamref (body, &bstr));
      MU_ASSERT (mu_stream_copy (ostr, bstr, 0, NULL));
      mu_stream_destroy (&bstr);
      mu_stream_close (ostr);
      mu_stream_destroy (&ostr);
    }
  MU_ASSERT (mu_smtp_dot (smtp));
  MU_ASSERT (mu_smtp_quit (smtp));
  
  mu_smtp_destroy (&smtp);
  mu_stream_close (instr);
  mu_stream_destroy (&instr);
  return 0;
}
Example #4
0
/* Parse a message specification from (argc;argv). Returned msgset is
   not sorted nor optimised */
int
_mh_msgset_parse (mu_mailbox_t mbox, mh_msgset_t *msgset, int argc, char **argv)
{
  size_t msgcnt;
  size_t *msglist;
  size_t i, msgno;
  
  if (argc == 0)
    return 1;
  
  msgcnt = argc;
  msglist = calloc (msgcnt, sizeof(*msglist));
  for (i = 0, msgno = 0; i < argc; i++)
    {
      char *p = NULL, *q;
      size_t start, end;
      size_t msg_first, n;
      long num;
      char *arg = msgset_preproc (mbox, argv[i]);

      if (!mu_isdigit (arg[0]))
	{
	  int j;
	  mh_msgset_t m;
	  
	  if (expand_user_seq (mbox, &m, arg))
	    {
	      mu_error (_("message set %s does not exist"), arg);
	      exit (1);
	    }
	  _expand (&msgcnt, &msglist, m.count);
	  for (j = 0; j < m.count; j++)
	    msglist[msgno++] = m.list[j];
	  mh_msgset_free (&m);
	}
      else
	{
	  start = strtoul (arg, &p, 0);
	  switch (*p)
	    {
	    case 0:
	      n = mh_get_message (mbox, start, NULL);
	      if (!n)
		{
		  mu_error (_("message %lu does not exist"),
			    (unsigned long) start);
		  exit (1);
		}
	      msglist[msgno++] = n;
	      break;
	      
	    case '-':
	      end = strtoul (p+1, &p, 0);
	      if (*p)
		msgset_abort (argv[i]);
	      if (end < start)
		{
		  size_t t = start;
		  start = end;
		  end = t;
		}
	      _expand (&msgcnt, &msglist, end - start);
	      msg_first  = msgno;
	      for (; start <= end; start++)
		{
		  n = mh_get_message (mbox, start, NULL);
		  if (n)
		    msglist[msgno++] = n;
		}
	      if (msgno == msg_first)
		{
		  mu_error (_("no messages in range %s"), argv[i]);
		  exit (1);
		}
	      break;
	      
	    case ':':
	      num = strtoul (p+1, &q, 0);
	      if (*q)
		msgset_abort (argv[i]);
	      if (p[1] != '+' && p[1] != '-')
		{
		  if (strncmp (argv[i], "last:", 5) == 0
		      || strncmp (argv[i], "prev:", 5) == 0)
		    num = -num;
		}
	      end = start + num;
	      if (end < start)
		{
		  size_t t = start;
		  start = end + 1;
		  end = t;
		}
	      else
		end--;
	      _expand (&msgcnt, &msglist, end - start);
	      msg_first  = msgno;
	      for (; start <= end; start++)
		{
		  n = mh_get_message (mbox, start, NULL);
		  if (n)
		    msglist[msgno++] = n;
		}
	      if (msgno == msg_first)
		{
		  mu_error (_("no messages in range %s"), argv[i]);
		  exit (1);
		}
	      break;
	      
	    default:
	      msgset_abort (argv[i]);
	    }
	}
      free (arg);
    }

  msgset->count = msgno;
  msgset->list = msglist;
  return 0;
}
Example #5
0
struct header_segm *
compile_headline (const char *str)
{
  struct header_segm *head = NULL, *tail = NULL;
  char *text;
  int align;
  size_t width;
  
#define ALIGN_STRING (align == ALIGN_UNDEF ? ALIGN_LEFT : ALIGN_RIGHT)
#define ALIGN_NUMBER (align == ALIGN_UNDEF ? ALIGN_RIGHT : ALIGN_LEFT)
#define ATTACH(p)				\
  do						\
    {						\
      if (!head)				\
	head = p;				\
      else					\
	tail->next = p;				\
      tail = p;					\
    }						\
  while (0)
      
  while (*str)
    {
      struct header_segm *seg;
      size_t len;
      char *p = strchr (str, '%');
      if (!p)
	len = strlen (str);
      else
	len = p - str;
      if (len)
	{
	  text = xmalloc (len + 1);
	  memcpy (text, str, len);
	  text[len] = 0;
	  seg = new_header_segment (ALIGN_LEFT, 0, text, hdr_text);
	  ATTACH (seg);
	}
      if (!p)
	break;

      str = ++p;

      if (*str == '-')
	{
	  str++;
	  align = ALIGN_LEFT;
	}
      else if (*str == '+')
	{
	  str++;
	  align = ALIGN_RIGHT;
	}
      else
	align = ALIGN_UNDEF;
      
      if (mu_isdigit (*str))
	width = strtoul (str, (char**)&str, 10);
      else
	width = 0;

      switch (*str++)
	{
	case '%':
	  seg = new_header_segment (ALIGN_LEFT, 0, xstrdup ("%"), hdr_text);
	  break;
	  
	case 'a': /* Message attributes. */
	  seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_attr);
	  break;

	  /* FIXME: %c    The score of the message. */
	  
	case 'd': /* Message date */
	  seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_date);
	  break;
	  
	  /* FIXME: %e    The indenting level in threaded mode. */
	  
	case 'f': /* Message sender */
	  seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_from);
	  break;

	  /* FIXME: %i    The message thread structure. */
	  
	case 'l': /* The number of lines of the message */
	  seg = new_header_segment (ALIGN_NUMBER, width, NULL, hdr_lines);
	  break;
	  
	case 'm': /* Message number */
	  seg = new_header_segment (ALIGN_NUMBER, width, NULL, hdr_number);
	  break;
	  
	case 'o': /* The number of octets (bytes) in the message */
	  seg = new_header_segment (ALIGN_NUMBER, width, NULL, hdr_size);
	  break;
	  
	case 's': /* Message subject (if any) */
	  seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_subject);
	  break;

	case 'S': /* Message subject (if any) in double quotes */
	  seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_q_subject);
	  break;
	  
	  /* FIXME: %t    The position in threaded/sorted order. */
	  
	case '>': /* A `>' for the current message, otherwise ` ' */
	  seg = new_header_segment (ALIGN_STRING, width, xstrdup (">"), hdr_cur);
	  break;
	  
	case '<': /* A `<' for the current message, otherwise ` ' */
	  seg = new_header_segment (ALIGN_STRING, width, xstrdup ("<"), hdr_cur);
	  break;

	default:
	  mu_error (_("unknown escape: %%%c"), str[-1]);
	  len = str - p;
	  text = xmalloc (len);
	  memcpy (text, p, len-1);
	  text[len-1] = 0;
	  seg = new_header_segment (ALIGN_STRING, width, text, hdr_text);
	}
      ATTACH (seg);
    }
  return head;
#undef ALIGN_STRING
#undef ALIGN_NUMBER
#undef ATTACH
}