bug-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [bug-mailutils] Illegal seek error


From: Sergey Poznyakoff
Subject: RE: [bug-mailutils] Illegal seek error
Date: Mon, 13 Jun 2005 17:27:29 +0300

References: <address@hidden>
X-Mailer: MH-E 7.4.3+cvs; GNU Mailutils 0.6.1; GNU Emacs 21.3.2

Melinda Chin <address@hidden> wrote:

> Do you have any suggestions to what maybe causing the illegal seek error
> to occur ?

Illegal seek on stream_readline can occur, for example, if its fourth argument
gets out of sync with mailutils internal counter. It is hard to say how
exactly it can happen in your code, but it is certain that it can. There
are too many inconsistencies. To name few of them:

1. You do

  message_size (part, &msize);
  [...]
  stream_readline (str, buf, 2046+msize, offset, &nbytes);

Note that msize is not the same as the size of the message part you
are about to read. You can obtain the exact size of this part by using
body_size().

2. In addition to the above

 result = stream_readline (str, buf, 2046+msize, offset, &nbytes);

attempts to read 2046 bytes more than the *entire message* contains,
whereas it is certain that the message part contains less still. That's
not that critical, but should be addressed anyway. 

3. This part:

          offset = 0;
          nbytes = 1;
          while (result  == 0 && nbytes)

is incorrect. You cannot assume any number of bytes to be read. Use `do
... while' construct instead.

I could probably give you a more precise diagnostics if I had more
information. Please find attached a program I was using to test your
code fragment. Hope this will help.

Regards,
Sergey

#include <mailutils/mailutils.h>

char * buf;
char * emailText;
/* this variable is defined in a header file included in the source file
   this function is defined in.
   In another function in another source file, I free memory and assign
   emailText to NULL. */

void
GetEmailBody(message_t msg,  int * valid_attachments)
{
  int ret, j;
  size_t msize, nlines, nparts, nsubparts;
  message_t part;
  header_t hdr;
  char type[256];
  char encoding[256];
  stream_t str;
  body_t body;
  int offset, ismulti;
  size_t nbytes;
  int indent = 0;
  int indent_level = 4;
  int result = 0;
  
  /* How many parts does the message has? */
  if ((ret = message_get_num_parts (msg, &nparts)) != 0)
    {
      fprintf (stderr, "message_get_num_parts - %s\n", mu_strerror (ret));
      exit (2);
    }

  /* Iterate through all the parts.
     Treat type "message/rfc822" differently, since it is a message of
     its own that can have other subparts(recursive). */
  for (j = 1; j <= nparts; j++)
    {
      if ((ret = message_get_part (msg, j, &part)) != 0)
        {
          fprintf (stderr, "mime_get_part - %s\n", mu_strerror (ret));
          exit (2);
        }
      if ((ret = message_size (part, &msize)) != 0)
        {
          fprintf (stderr, "message_size - %s\n", mu_strerror (ret));
          exit (2);
        }
      if ((ret = message_lines (part, &nlines)) != 0)
        {
          fprintf (stderr, "message_lines - %s\n", mu_strerror (ret));
          exit (2);
        }
      if ((ret = message_get_header (part, &hdr)) != 0)
        {
          fprintf (stderr, "message_get_header - %s\n", mu_strerror (ret));
          exit (2);
        }
      header_get_value (hdr, MU_HEADER_CONTENT_TYPE, type, sizeof (type),
                        NULL);
      printf ("%*.*sType of part %d = %s\n", indent, indent, "", j, type);
      printf ("%*.*sMessage part size - %lu/%lu\n", indent, indent, "",
              (unsigned long) msize, (unsigned long) nlines);
      encoding[0] = '\0';
      header_get_value (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING, encoding,
                        sizeof (encoding), NULL);
      ismulti = 0;
      if ((type[0]
           && strncasecmp (type, "message/rfc822", strlen (type)) == 0)
          || (message_is_multipart (part, &ismulti) == 0 && ismulti))
        {
          if (!ismulti)
            {
              ret = message_unencapsulate (part, &part, NULL);
              if (ret != 0)
                fprintf (stderr, "message_unencapsulate - %s\n",
                         mu_strerror (ret));
              break;
            }
          if ((ret = message_get_header (part, &hdr)) != 0)
            {
              fprintf (stderr, "message_get_header - %s\n",
                       mu_strerror (ret));
              exit (2);
            }
//          header_get_value (hdr, MU_HEADER_FROM, from, sizeof (from), NULL);
//          header_get_value (hdr, MU_HEADER_SUBJECT, subject, sizeof (subject),
//                            NULL);
//          printf ("%*.*sEncapsulated message : %s\t%s\n",
//                  indent, indent, "", from, subject);
          printf ("%*.*sBegin\n", indent, indent, "");
          if ((ret = message_get_num_parts (part, &nsubparts)) != 0)
            {
              fprintf (stderr, "mime_get_num_parts - %s\n",
                       mu_strerror (ret));
              exit (2);
            }

                  indent+=indent_level;
          GetEmailBody (part, valid_attachments);
          message_destroy (&part, NULL);
        }
      else if (type[0] == '\0'
               || (strncasecmp (type, "text/plain", strlen ("text/plain")) == 
0) )
        {
          printf ("%*.*sText Message\n", indent, indent, "");
          printf ("%*.*sBegin\n", indent, indent, "");
          result = message_get_body (part, &body);
          printf("\ngetting body, result = %d\n", result);

          
          
          
          msize += strlen(emailText);
          emailText = realloc(emailText, msize);
        
          
          buf = calloc(2046+msize, sizeof(char));
          
          result = body_get_stream (body, &str);
          printf("\ngetting stream, result = %d\n", result);

          filter_create (&str, str, encoding, 0, 0);
          offset = 0;
          nbytes = 1;
          while (result  == 0 && nbytes)
            {
              nbytes = 0;
              result = stream_readline (str, buf, 2046+msize, offset, &nbytes);
              printf("\nresult = %d, text = %s\n", result, buf);
              
              if (buf != NULL)
                {
                  printf("\nadding to textStream\n");
                  strcat(emailText, buf);
                }

              offset += nbytes;
            }

          free(buf);
          printf("\ndone getting text, result = %d\n", result);
                                
          stream_destroy (&str, NULL);
        }
      else
        {
          /* Save the attachements.  */
          char *fname = NULL;
          message_aget_attachment_name (part, &fname);
          if (fname == NULL)
            fname = mu_tempname (NULL);

          printf ("%*.*sAttachment - saving [%s]\n", indent, indent, "",
                  fname);
          printf ("%*.*sBegin\n", indent, indent, "");
          /*FIXME: What is the 'data' argument for? */
          message_save_attachment (part, NULL, NULL);
          free (fname);
        }
      printf ("\n%*.*sEnd\n", indent, indent, "");
    }
}

int
main(int argc, char **argv)
{
  list_t bookie = NULL;
  char *box = argv[1];
  mailbox_t mbox;
  int status;
  size_t i, count;

  emailText = strdup("text");
  
  mu_argp_init ("Melinda 1.0", NULL);

  if (!box)
    {
      mu_error("no mailbox specified");
      exit(1);
    }

  registrar_get_list (&bookie);
  list_append (bookie, path_record);
  list_append (bookie, mbox_record);
  
  status =  mailbox_create_default (&mbox, box);
  if (status != 0)
    {
      if (box)
        mu_error ("Could not create mailbox `%s': %s",
                  box, mu_strerror (status));
      else
        mu_error ("Could not create default mailbox: %s",
                  mu_strerror (status));
      return -1;
    }

  status =  mailbox_open (mbox, MU_STREAM_READ);
  if (status != 0)
    {
      mu_error ("Could not open mailbox `%s': %s",
                box, mu_strerror (status));
      return -1;
    }

  status = mailbox_messages_count (mbox, &count);
  if (status != 0)
    {
      mu_error ("Could not count messages in mailbox `%s': %s",
                box, mu_strerror (status));
      return -1;
    }

  for (i = 1; i <= count; i++)
    {
      int n;
      message_t msg;

      if (mailbox_get_message (mbox, 1, &msg) == 0)
        GetEmailBody (msg, &n);
    }
  
  mailbox_close (mbox);
  mailbox_destroy (&mbox);
  exit (0);
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]