Blame view

readmsg/msglist.c 3.75 KB
1
/* GNU Mailutils -- a suite of utilities for electronic mail
2 3
   Copyright (C) 1999, 2000, 2001, 2005, 2007, 2009, 2010 Free Software
   Foundation, Inc.
4

5
   GNU Mailutils is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 3, or (at your option)
8 9
   any later version.

10
   GNU Mailutils is distributed in the hope that it will be useful,
11 12 13 14 15
   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
16
   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
17

Alain Magloire authored
18
#include "readmsg.h"
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

static int
addset (int **set, int *n, unsigned val)
{
  int *tmp;
  tmp = realloc (*set, (*n + 1) * sizeof (**set));
  if (tmp == NULL)
    {
      if (*set)
        free (*set);
      *n = 0;
      *set = NULL;
      return ENOMEM;
    }
  *set = tmp;
  (*set)[*n] = val;
  (*n)++;
  return 0;
}

39
static int
40
is_number (const char *s)
41
{
42
  int result = 1;
43
  if (*s == '\0')
44
    result = 0;
45 46
  for (; *s; s++)
    {
47
      if (!mu_isdigit ((unsigned char)*s))
48
	{
49
	  result = 0;
50 51 52
	  break;
	}
    }
53
  return result;
54 55 56 57 58
}

/*
  According to ELM readmsg(1):

59
  1. A lone ``*'' means select all messages in the mailbox.
60

61 62 63
  2. A list of message numbers may be specified.  Values of ``0'' and
  ``$'' in the list both mean the last message in the mailbox.  For
  example:
64 65 66

  readmsg 1 3 0

67 68
  extracts three messages from the folder: the first, the third, and
  the last.
69

70 71 72
  3. Finally, the selection may be some text to match.  This will
  select a mail message which exactly matches the specified text. For
  example,
73 74 75

  readmsg staff meeting

76 77 78 79 80
  extracts the message which contains the words ``staff meeting.''
  Note that it will not match a message containing ``Staff Meeting'' -
  the matching is case sensitive.  Normally only the first message
  which matches the pattern will be printed.  The -a option discussed
  in a moment changes this.
81 82
*/

83
int
84 85
msglist (mu_mailbox_t mbox, int show_all, int argc, char **argv,
	 int **set, int *n)
86
{
87 88 89
  int i = 0;
  size_t total = 0;

90
  mu_mailbox_messages_count (mbox, &total);
91 92 93

  for (i = 0; i < argc; i++)
    {
94
      /* 1. A lone ``*'' means select all messages in the mailbox. */
95
      if (!strcmp (argv[i], "*"))
96
	{
97 98 99 100 101
	  size_t j;
	  /* all messages */
	  for (j = 1; j <= total; j++)
	    addset (set, n, j);
	  j = argc + 1;
102
	}
103 104 105
      /* 2. A list of message numbers may be specified.  Values of
	 ``0'' and ``$'' in the list both mean the last message in the
	 mailbox. */
106
      else if (!strcmp (argv[i], "$") || !strcmp (argv[i], "0"))
107
	{
108
	  addset (set, n, total);
109
	}
110 111 112 113
      /* 3. Finally, the selection may be some text to match.  This
	 will select a mail message which exactly matches the
	 specified text. */
      else if (!is_number (argv[i]))
114
	{
115 116
	  size_t j;
	  int found = 0;
117 118
	  for (j = 1; j <= total; j++)
	    {
Sergey Poznyakoff authored
119
	      int status;
120 121
	      char buf[128];
	      size_t len = 0;
122 123
	      mu_message_t msg = NULL;
	      mu_stream_t stream = NULL;
124

125
	      mu_mailbox_get_message (mbox, j, &msg);
Sergey Poznyakoff authored
126 127 128 129 130
	      status = mu_message_get_streamref (msg, &stream);
	      if (status)
		mu_error (_("cannot read message: %s"),
			  mu_strerror (status));
	      else
131
		{
Sergey Poznyakoff authored
132 133
		  while (mu_stream_readline (stream, buf, sizeof buf, &len) == 0
			 && len > 0)
134
		    {
Sergey Poznyakoff authored
135 136 137 138 139 140
		      if (strstr (buf, argv[i]) != NULL)
			{
			  addset (set, n, j);
			  found = 1;
			  break;
			}
141
		    }
Sergey Poznyakoff authored
142
		  mu_stream_destroy (&stream);
143
		}
144 145
	      if (found && !show_all)
		break;
146 147
	    }
	}
148
      else if (mu_isdigit (argv[i][0]))
149 150 151 152 153 154 155 156
	{
	  /* single message */
	  addset (set, n, strtol (argv[i], NULL, 10));
	}
    }

  return 0;
}