Adding more comments, and in message_destroy make sure we
destroy all the objects attached to it.
Showing
4 changed files
with
181 additions
and
134 deletions
... | @@ -125,7 +125,7 @@ static int fill_buffer (bio_t bio, char *buffer, size_t buflen); | ... | @@ -125,7 +125,7 @@ static int fill_buffer (bio_t bio, char *buffer, size_t buflen); |
125 | filtering out the starting "." and return O(zero) when seeing the terminal | 125 | filtering out the starting "." and return O(zero) when seeing the terminal |
126 | octets ".\r\n". bio_readline () insists on having a _complete_ line .i.e | 126 | octets ".\r\n". bio_readline () insists on having a _complete_ line .i.e |
127 | a string terminated by \n, it will allocate/grow the working buffer as | 127 | a string terminated by \n, it will allocate/grow the working buffer as |
128 | needed. The '\r\n" termination is converted to '\n'. bio_destroy () | 128 | needed. The "\r\n" termination is converted to '\n'. bio_destroy () |
129 | does not close the stream but only free () the working buffer. */ | 129 | does not close the stream but only free () the working buffer. */ |
130 | struct _bio | 130 | struct _bio |
131 | { | 131 | { |
... | @@ -146,14 +146,14 @@ static int bio_read (bio_t); | ... | @@ -146,14 +146,14 @@ static int bio_read (bio_t); |
146 | static int bio_write (bio_t); | 146 | static int bio_write (bio_t); |
147 | 147 | ||
148 | 148 | ||
149 | /* This structure holds the info when for a pop_get_message() the | 149 | /* This structure holds the info for a pop_get_message(). The pop_message_t |
150 | pop_message_t type will serve as the owner of the message_t and contains | 150 | type, will serve as the owner of the message_t and contains the command to |
151 | the command to send to RETReive the specify message. The problem comes | 151 | send to "RETR"eive the specify message. The problem comes |
152 | from the header. If the POP server supports TOP, we can cleanly fetch | 152 | from the header. If the POP server supports TOP, we can cleanly fetch |
153 | the header. But otherwise we use the clumsy approach. .i.e for the header | 153 | the header. But otherwise we use the clumsy approach. .i.e for the header |
154 | we read 'til ^\n then discard the rest for the body we read after ^\n and | 154 | we read 'til ^\n then discard the rest, for the body we read after ^\n and |
155 | discard the beginning. This a waste, Pop was not conceive for this | 155 | discard the beginning. This a waste, Pop was not conceive for this |
156 | obviously. */ | 156 | obviously. */ |
157 | struct _pop_message | 157 | struct _pop_message |
158 | { | 158 | { |
159 | int inbody; | 159 | int inbody; |
... | @@ -171,7 +171,7 @@ struct _pop_message | ... | @@ -171,7 +171,7 @@ struct _pop_message |
171 | struct _pop_data | 171 | struct _pop_data |
172 | { | 172 | { |
173 | void *func; /* Indicate a command is in operation, busy. */ | 173 | void *func; /* Indicate a command is in operation, busy. */ |
174 | size_t id; /* Use in pop_expunge to indiate the message, if bailing out. */ | 174 | size_t id; /* Use in pop_expunge to hold the message num, if EAGAIN. */ |
175 | enum pop_state state; | 175 | enum pop_state state; |
176 | pop_message_t *pmessages; | 176 | pop_message_t *pmessages; |
177 | size_t pmessages_count; | 177 | size_t pmessages_count; |
... | @@ -183,7 +183,7 @@ struct _pop_data | ... | @@ -183,7 +183,7 @@ struct _pop_data |
183 | int flags; /* Flags of for the stream_t object. */ | 183 | int flags; /* Flags of for the stream_t object. */ |
184 | bio_t bio; /* Working I/O buffer. */ | 184 | bio_t bio; /* Working I/O buffer. */ |
185 | int is_updated; | 185 | int is_updated; |
186 | char *user; /* Temporary holders for user and passwd. */ | 186 | char *user; /* Temporary holders for user and passwd. */ |
187 | char *passwd; | 187 | char *passwd; |
188 | mailbox_t mbox; /* Back pointer. */ | 188 | mailbox_t mbox; /* Back pointer. */ |
189 | } ; | 189 | } ; |
... | @@ -209,7 +209,7 @@ do \ | ... | @@ -209,7 +209,7 @@ do \ |
209 | while (0) | 209 | while (0) |
210 | 210 | ||
211 | 211 | ||
212 | /* Parse the url, allocate mailbox_t etc .. */ | 212 | /* Parse the url, allocate mailbox_t, allocate pop internal structures. */ |
213 | static int | 213 | static int |
214 | pop_create (mailbox_t *pmbox, const char *name) | 214 | pop_create (mailbox_t *pmbox, const char *name) |
215 | { | 215 | { |
... | @@ -293,7 +293,7 @@ pop_create (mailbox_t *pmbox, const char *name) | ... | @@ -293,7 +293,7 @@ pop_create (mailbox_t *pmbox, const char *name) |
293 | return 0; /* Okdoke. */ | 293 | return 0; /* Okdoke. */ |
294 | } | 294 | } |
295 | 295 | ||
296 | /* Cleaning up all the ressources. */ | 296 | /* Cleaning up all the ressources associate with a pop mailbox. */ |
297 | static void | 297 | static void |
298 | pop_destroy (mailbox_t *pmbox) | 298 | pop_destroy (mailbox_t *pmbox) |
299 | { | 299 | { |
... | @@ -357,6 +357,7 @@ echo_on(void) | ... | @@ -357,6 +357,7 @@ echo_on(void) |
357 | tcsetattr (0, TCSANOW, &stored_settings); | 357 | tcsetattr (0, TCSANOW, &stored_settings); |
358 | } | 358 | } |
359 | 359 | ||
360 | /* User/pass authentication for pop. */ | ||
360 | static int | 361 | static int |
361 | pop_authenticate (auth_t auth, char **user, char **passwd) | 362 | pop_authenticate (auth_t auth, char **user, char **passwd) |
362 | { | 363 | { |
... | @@ -394,6 +395,9 @@ pop_authenticate (auth_t auth, char **user, char **passwd) | ... | @@ -394,6 +395,9 @@ pop_authenticate (auth_t auth, char **user, char **passwd) |
394 | return 0; | 395 | return 0; |
395 | } | 396 | } |
396 | 397 | ||
398 | /* Open the connection to the sever, ans send the authentication. | ||
399 | FIXME: Should also send the CAPA command to detect for example the suport | ||
400 | for POP, and DTRT(Do The Right Thing). */ | ||
397 | static int | 401 | static int |
398 | pop_open (mailbox_t mbox, int flags) | 402 | pop_open (mailbox_t mbox, int flags) |
399 | { | 403 | { |
... | @@ -481,7 +485,7 @@ pop_open (mailbox_t mbox, int flags) | ... | @@ -481,7 +485,7 @@ pop_open (mailbox_t mbox, int flags) |
481 | return EACCES; | 485 | return EACCES; |
482 | } | 486 | } |
483 | 487 | ||
484 | /* Fetch the the user/passwd from them. */ | 488 | /* Fetch the user/passwd from them. */ |
485 | auth_authenticate (mbox->auth, &mpd->user, &mpd->passwd); | 489 | auth_authenticate (mbox->auth, &mpd->user, &mpd->passwd); |
486 | 490 | ||
487 | bio->len = snprintf (bio->buffer, bio->maxlen, "USER %s\r\n", mpd->user); | 491 | bio->len = snprintf (bio->buffer, bio->maxlen, "USER %s\r\n", mpd->user); |
... | @@ -549,6 +553,7 @@ pop_open (mailbox_t mbox, int flags) | ... | @@ -549,6 +553,7 @@ pop_open (mailbox_t mbox, int flags) |
549 | return 0; | 553 | return 0; |
550 | } | 554 | } |
551 | 555 | ||
556 | /* Send the QUIT and close the socket. */ | ||
552 | static int | 557 | static int |
553 | pop_close (mailbox_t mbox) | 558 | pop_close (mailbox_t mbox) |
554 | { | 559 | { |
... | @@ -561,6 +566,7 @@ pop_close (mailbox_t mbox) | ... | @@ -561,6 +566,7 @@ pop_close (mailbox_t mbox) |
561 | if (mpd == NULL) | 566 | if (mpd == NULL) |
562 | return EINVAL; | 567 | return EINVAL; |
563 | 568 | ||
569 | /* Flag busy ? */ | ||
564 | if (mpd->func && mpd->func != func) | 570 | if (mpd->func && mpd->func != func) |
565 | return EBUSY; | 571 | return EBUSY; |
566 | 572 | ||
... | @@ -571,6 +577,7 @@ pop_close (mailbox_t mbox) | ... | @@ -571,6 +577,7 @@ pop_close (mailbox_t mbox) |
571 | switch (mpd->state) | 577 | switch (mpd->state) |
572 | { | 578 | { |
573 | case POP_NO_STATE: | 579 | case POP_NO_STATE: |
580 | /* Initiate the close. */ | ||
574 | bio->len = snprintf (bio->buffer, bio->maxlen, "QUIT\r\n"); | 581 | bio->len = snprintf (bio->buffer, bio->maxlen, "QUIT\r\n"); |
575 | bio->ptr = bio->buffer; | 582 | bio->ptr = bio->buffer; |
576 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 583 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
... | @@ -587,15 +594,15 @@ pop_close (mailbox_t mbox) | ... | @@ -587,15 +594,15 @@ pop_close (mailbox_t mbox) |
587 | status = bio_readline (bio); | 594 | status = bio_readline (bio); |
588 | CHECK_NON_RECOVERABLE (mpd, status); | 595 | CHECK_NON_RECOVERABLE (mpd, status); |
589 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); | 596 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_PROT, bio->buffer); |
590 | /* Now what ! and how can we tell them about errors ? So for now | 597 | /* Now what ! and how can we tell them about errors ? So far now |
591 | lets just be verbose about the error but close the connection | 598 | lets just be verbose about the error but close the connection |
592 | anyway. */ | 599 | anyway. */ |
593 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) | 600 | if (strncasecmp (bio->buffer, "+OK", 3) != 0) |
594 | fprintf (stderr, "pop_close: %s\n", bio->buffer); | 601 | fprintf (stderr, "pop_close: %s\n", bio->buffer); |
595 | |||
596 | stream_close (bio->stream); | 602 | stream_close (bio->stream); |
597 | bio->stream = NULL; | 603 | bio->stream = NULL; |
598 | break; | 604 | break; |
605 | |||
599 | default: | 606 | default: |
600 | /* | 607 | /* |
601 | fprintf (stderr, "pop_close unknow state"); | 608 | fprintf (stderr, "pop_close unknow state"); |
... | @@ -613,6 +620,7 @@ pop_close (mailbox_t mbox) | ... | @@ -613,6 +620,7 @@ pop_close (mailbox_t mbox) |
613 | free (mpd->pmessages[i]); | 620 | free (mpd->pmessages[i]); |
614 | } | 621 | } |
615 | } | 622 | } |
623 | /* And clear any residue. */ | ||
616 | free (mpd->pmessages); | 624 | free (mpd->pmessages); |
617 | mpd->pmessages = NULL; | 625 | mpd->pmessages = NULL; |
618 | mpd->pmessages_count = 0; | 626 | mpd->pmessages_count = 0; |
... | @@ -623,6 +631,7 @@ pop_close (mailbox_t mbox) | ... | @@ -623,6 +631,7 @@ pop_close (mailbox_t mbox) |
623 | return 0; | 631 | return 0; |
624 | } | 632 | } |
625 | 633 | ||
634 | /* Only build/setup the message_t structure for a mesgno. */ | ||
626 | static int | 635 | static int |
627 | pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | 636 | pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
628 | { | 637 | { |
... | @@ -651,25 +660,28 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -651,25 +660,28 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
651 | mpm = calloc (1, sizeof (*mpm)); | 660 | mpm = calloc (1, sizeof (*mpm)); |
652 | if (mpm == NULL) | 661 | if (mpm == NULL) |
653 | return ENOMEM; | 662 | return ENOMEM; |
654 | /* back pointer */ | 663 | |
664 | /* Back pointer. */ | ||
655 | mpm->mpd = mpd; | 665 | mpm->mpd = mpd; |
656 | mpm->num = msgno; | 666 | mpm->num = msgno; |
657 | 667 | ||
658 | /* Create the message. */ | 668 | /* Create the message. */ |
659 | { | 669 | { |
660 | message_t msg = NULL; | 670 | message_t msg = NULL; |
661 | stream_t is = NULL; | 671 | stream_t stream = NULL; |
662 | if ((status = message_create (&msg, mpm)) != 0 | 672 | if ((status = message_create (&msg, mpm)) != 0 |
663 | || (status = stream_create (&is, MU_STREAM_READ, mpm)) != 0) | 673 | || (status = stream_create (&stream, MU_STREAM_READ, mpm)) != 0) |
664 | { | 674 | { |
665 | message_destroy (&msg, mpm); | 675 | message_destroy (&msg, mpm); |
666 | stream_destroy (&is, mpm); | 676 | stream_destroy (&stream, mpm); |
667 | free (mpm); | 677 | free (mpm); |
668 | return status; | 678 | return status; |
669 | } | 679 | } |
670 | stream_set_read (is, pop_read_message, mpm); | 680 | stream_set_read (stream, pop_read_message, mpm); |
671 | message_set_stream (msg, is, mpm); | 681 | stream_set_fd (stream, pop_get_fd, mpm); |
672 | /* The message. */ | 682 | stream_set_flags (stream, MU_STREAM_READ, mpm); |
683 | message_set_stream (msg, stream, mpm); | ||
684 | /* Save The message. */ | ||
673 | mpm->message = msg; | 685 | mpm->message = msg; |
674 | } | 686 | } |
675 | 687 | ||
... | @@ -753,6 +765,7 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -753,6 +765,7 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
753 | return 0; | 765 | return 0; |
754 | } | 766 | } |
755 | 767 | ||
768 | /* How many messages we have. Done with STAT. */ | ||
756 | static int | 769 | static int |
757 | pop_messages_count (mailbox_t mbox, size_t *pcount) | 770 | pop_messages_count (mailbox_t mbox, size_t *pcount) |
758 | { | 771 | { |
... | @@ -764,6 +777,7 @@ pop_messages_count (mailbox_t mbox, size_t *pcount) | ... | @@ -764,6 +777,7 @@ pop_messages_count (mailbox_t mbox, size_t *pcount) |
764 | if (mpd == NULL) | 777 | if (mpd == NULL) |
765 | return EINVAL; | 778 | return EINVAL; |
766 | 779 | ||
780 | /* Do not send a STAT if we know the answer. */ | ||
767 | if (pop_is_updated (mbox)) | 781 | if (pop_is_updated (mbox)) |
768 | { | 782 | { |
769 | if (pcount) | 783 | if (pcount) |
... | @@ -771,6 +785,7 @@ pop_messages_count (mailbox_t mbox, size_t *pcount) | ... | @@ -771,6 +785,7 @@ pop_messages_count (mailbox_t mbox, size_t *pcount) |
771 | return 0; | 785 | return 0; |
772 | } | 786 | } |
773 | 787 | ||
788 | /* Flag busy. */ | ||
774 | if (mpd->func && mpd->func != func) | 789 | if (mpd->func && mpd->func != func) |
775 | return EBUSY; | 790 | return EBUSY; |
776 | 791 | ||
... | @@ -805,16 +820,20 @@ pop_messages_count (mailbox_t mbox, size_t *pcount) | ... | @@ -805,16 +820,20 @@ pop_messages_count (mailbox_t mbox, size_t *pcount) |
805 | break; | 820 | break; |
806 | } | 821 | } |
807 | 822 | ||
823 | /* Parse the answer. */ | ||
808 | status = sscanf (bio->buffer, "+OK %d %d", &(mpd->messages_count), | 824 | status = sscanf (bio->buffer, "+OK %d %d", &(mpd->messages_count), |
809 | &(mpd->size)); | 825 | &(mpd->size)); |
810 | 826 | ||
827 | /* Clear the state _after_ the scanf, since another thread could | ||
828 | start writing over bio->buffer. But We're not thread safe yet. */ | ||
811 | CLEAR_STATE (mpd); | 829 | CLEAR_STATE (mpd); |
812 | 830 | ||
813 | mpd->is_updated = 1; | ||
814 | if (pcount) | ||
815 | *pcount = mpd->messages_count; | ||
816 | if (status == EOF || status != 2) | 831 | if (status == EOF || status != 2) |
817 | return EIO; | 832 | return EIO; |
833 | |||
834 | if (pcount) | ||
835 | *pcount = mpd->messages_count; | ||
836 | mpd->is_updated = 1; | ||
818 | return 0; | 837 | return 0; |
819 | } | 838 | } |
820 | 839 | ||
... | @@ -829,6 +848,9 @@ pop_is_updated (mailbox_t mbox) | ... | @@ -829,6 +848,9 @@ pop_is_updated (mailbox_t mbox) |
829 | return mpd->is_updated; | 848 | return mpd->is_updated; |
830 | } | 849 | } |
831 | 850 | ||
851 | /* We do not send anything to the server since, no DELE command is sent but | ||
852 | the only the attribute flag is modified. | ||
853 | DELE is sent only when expunging. */ | ||
832 | static int | 854 | static int |
833 | pop_num_deleted (mailbox_t mbox, size_t *pnum) | 855 | pop_num_deleted (mailbox_t mbox, size_t *pnum) |
834 | { | 856 | { |
... | @@ -853,7 +875,8 @@ pop_num_deleted (mailbox_t mbox, size_t *pnum) | ... | @@ -853,7 +875,8 @@ pop_num_deleted (mailbox_t mbox, size_t *pnum) |
853 | return 0; | 875 | return 0; |
854 | } | 876 | } |
855 | 877 | ||
856 | /* We just simulated. */ | 878 | /* We just simulated. By sending a notification for the total msgno. */ |
879 | /* FIXME is message is set deleted should we sent a notif ? */ | ||
857 | static int | 880 | static int |
858 | pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | 881 | pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount) |
859 | { | 882 | { |
... | @@ -869,7 +892,7 @@ pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | ... | @@ -869,7 +892,7 @@ pop_scan (mailbox_t mbox, size_t msgno, size_t *pcount) |
869 | return 0; | 892 | return 0; |
870 | } | 893 | } |
871 | 894 | ||
872 | /* This were we actually sending the DELE command. */ | 895 | /* This were we actually send the DELE command. */ |
873 | static int | 896 | static int |
874 | pop_expunge (mailbox_t mbox) | 897 | pop_expunge (mailbox_t mbox) |
875 | { | 898 | { |
... | @@ -954,13 +977,13 @@ pop_expunge (mailbox_t mbox) | ... | @@ -954,13 +977,13 @@ pop_expunge (mailbox_t mbox) |
954 | mpd->id = 0; | 977 | mpd->id = 0; |
955 | mpd->func = NULL; | 978 | mpd->func = NULL; |
956 | mpd->state = POP_NO_STATE; | 979 | mpd->state = POP_NO_STATE; |
957 | /* Invalidate. But Really they should shutdown the challen POP protocol | 980 | /* Invalidate. But Really they should shutdown the channel POP protocol |
958 | is not meant for this like IMAP. */ | 981 | is not meant for this like IMAP. */ |
959 | mpd->is_updated = 0; | 982 | mpd->is_updated = 0; |
960 | return 0; | 983 | return 0; |
961 | } | 984 | } |
962 | 985 | ||
963 | /* Mailbox size ? */ | 986 | /* Mailbox size ? It is part of the STAT command */ |
964 | static int | 987 | static int |
965 | pop_size (mailbox_t mbox, off_t *psize) | 988 | pop_size (mailbox_t mbox, off_t *psize) |
966 | { | 989 | { |
... | @@ -999,6 +1022,10 @@ pop_body_lines (body_t body, size_t *plines) | ... | @@ -999,6 +1022,10 @@ pop_body_lines (body_t body, size_t *plines) |
999 | return 0; | 1022 | return 0; |
1000 | } | 1023 | } |
1001 | 1024 | ||
1025 | /* Pop does not have any command for this, We fake by reading the "Status: " | ||
1026 | header. But this is hackish some POP server(Qpopper) skip it. Also | ||
1027 | because we call header_get_value the function may return EAGAIN... | ||
1028 | uncool. */ | ||
1002 | static int | 1029 | static int |
1003 | pop_get_flags (attribute_t attr, int *pflags) | 1030 | pop_get_flags (attribute_t attr, int *pflags) |
1004 | { | 1031 | { |
... | @@ -1029,6 +1056,10 @@ pop_get_fd (stream_t stream, int *pfd) | ... | @@ -1029,6 +1056,10 @@ pop_get_fd (stream_t stream, int *pfd) |
1029 | return EINVAL; | 1056 | return EINVAL; |
1030 | } | 1057 | } |
1031 | 1058 | ||
1059 | /* Get the UIDL. Client should be prepare since it may fail. UIDL is | ||
1060 | optionnal for many POP server. | ||
1061 | FIXME: We should check this with CAPA and fall back to md5 scheme ? | ||
1062 | Or maybe check for "X-UIDL" a la Qpopper ? */ | ||
1032 | static int | 1063 | static int |
1033 | pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) | 1064 | pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) |
1034 | { | 1065 | { |
... | @@ -1104,6 +1135,9 @@ pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) | ... | @@ -1104,6 +1135,9 @@ pop_uidl (message_t msg, char *buffer, size_t buflen, size_t *pnwriten) |
1104 | return status; | 1135 | return status; |
1105 | } | 1136 | } |
1106 | 1137 | ||
1138 | /* How we retrieve the headers. If it fails we jump to the pop_retr() | ||
1139 | code .i.e send a RETR and skip the body, ugly. | ||
1140 | NOTE: offset is meaningless. */ | ||
1107 | static int | 1141 | static int |
1108 | pop_top (stream_t is, char *buffer, size_t buflen, | 1142 | pop_top (stream_t is, char *buffer, size_t buflen, |
1109 | off_t offset, size_t *pnread) | 1143 | off_t offset, size_t *pnread) |
... | @@ -1195,7 +1229,7 @@ pop_top (stream_t is, char *buffer, size_t buflen, | ... | @@ -1195,7 +1229,7 @@ pop_top (stream_t is, char *buffer, size_t buflen, |
1195 | } | 1229 | } |
1196 | break; | 1230 | break; |
1197 | default: | 1231 | default: |
1198 | /* Probabaly TOP was not supported so we fall back to RETR. */ | 1232 | /* Probabaly TOP was not supported so we have fall back to RETR. */ |
1199 | mpm->skip_header = 0; | 1233 | mpm->skip_header = 0; |
1200 | mpm->skip_body = 1; | 1234 | mpm->skip_body = 1; |
1201 | return pop_retr (mpm, buffer, buflen, offset, pnread); | 1235 | return pop_retr (mpm, buffer, buflen, offset, pnread); |
... | @@ -1210,6 +1244,7 @@ pop_top (stream_t is, char *buffer, size_t buflen, | ... | @@ -1210,6 +1244,7 @@ pop_top (stream_t is, char *buffer, size_t buflen, |
1210 | return 0; | 1244 | return 0; |
1211 | } | 1245 | } |
1212 | 1246 | ||
1247 | /* Stub to call pop_retr (). */ | ||
1213 | static int | 1248 | static int |
1214 | pop_read_header (stream_t is, char *buffer, size_t buflen, off_t offset, | 1249 | pop_read_header (stream_t is, char *buffer, size_t buflen, off_t offset, |
1215 | size_t *pnread) | 1250 | size_t *pnread) |
... | @@ -1230,6 +1265,7 @@ pop_read_header (stream_t is, char *buffer, size_t buflen, off_t offset, | ... | @@ -1230,6 +1265,7 @@ pop_read_header (stream_t is, char *buffer, size_t buflen, off_t offset, |
1230 | return pop_retr (mpm, buffer, buflen, offset, pnread); | 1265 | return pop_retr (mpm, buffer, buflen, offset, pnread); |
1231 | } | 1266 | } |
1232 | 1267 | ||
1268 | /* Stub to call pop_retr (). */ | ||
1233 | static int | 1269 | static int |
1234 | pop_read_body (stream_t is, char *buffer, size_t buflen, off_t offset, | 1270 | pop_read_body (stream_t is, char *buffer, size_t buflen, off_t offset, |
1235 | size_t *pnread) | 1271 | size_t *pnread) |
... | @@ -1250,6 +1286,7 @@ pop_read_body (stream_t is, char *buffer, size_t buflen, off_t offset, | ... | @@ -1250,6 +1286,7 @@ pop_read_body (stream_t is, char *buffer, size_t buflen, off_t offset, |
1250 | return pop_retr (mpm, buffer, buflen, offset, pnread); | 1286 | return pop_retr (mpm, buffer, buflen, offset, pnread); |
1251 | } | 1287 | } |
1252 | 1288 | ||
1289 | /* Stub to call pop_retr (). */ | ||
1253 | static int | 1290 | static int |
1254 | pop_read_message (stream_t is, char *buffer, size_t buflen, off_t offset, | 1291 | pop_read_message (stream_t is, char *buffer, size_t buflen, off_t offset, |
1255 | size_t *pnread) | 1292 | size_t *pnread) |
... | @@ -1270,6 +1307,7 @@ pop_read_message (stream_t is, char *buffer, size_t buflen, off_t offset, | ... | @@ -1270,6 +1307,7 @@ pop_read_message (stream_t is, char *buffer, size_t buflen, off_t offset, |
1270 | return pop_retr (mpm, buffer, buflen, offset, pnread); | 1307 | return pop_retr (mpm, buffer, buflen, offset, pnread); |
1271 | } | 1308 | } |
1272 | 1309 | ||
1310 | /* Little helper to fill the buffer without overflow. */ | ||
1273 | static int | 1311 | static int |
1274 | fill_buffer (bio_t bio, char *buffer, size_t buflen) | 1312 | fill_buffer (bio_t bio, char *buffer, size_t buflen) |
1275 | { | 1313 | { |
... | @@ -1293,6 +1331,7 @@ fill_buffer (bio_t bio, char *buffer, size_t buflen) | ... | @@ -1293,6 +1331,7 @@ fill_buffer (bio_t bio, char *buffer, size_t buflen) |
1293 | return nread; | 1331 | return nread; |
1294 | } | 1332 | } |
1295 | 1333 | ||
1334 | /* The heart of most funtions. Send the RETR and skip different parts. */ | ||
1296 | static int | 1335 | static int |
1297 | pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, | 1336 | pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, |
1298 | size_t *pnread) | 1337 | size_t *pnread) |
... | @@ -1340,7 +1379,7 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, | ... | @@ -1340,7 +1379,7 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, |
1340 | mpd->state = POP_RETR_RX_HDR; | 1379 | mpd->state = POP_RETR_RX_HDR; |
1341 | 1380 | ||
1342 | case POP_RETR_RX_HDR: | 1381 | case POP_RETR_RX_HDR: |
1343 | /* Skip the header. */ | 1382 | /* Skip/Take the header. */ |
1344 | while (!mpm->inbody) | 1383 | while (!mpm->inbody) |
1345 | { | 1384 | { |
1346 | /* Do we need to fill up. */ | 1385 | /* Do we need to fill up. */ |
... | @@ -1369,12 +1408,10 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, | ... | @@ -1369,12 +1408,10 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, |
1369 | break; | 1408 | break; |
1370 | } | 1409 | } |
1371 | } | 1410 | } |
1372 | /* Skip the newline. */ | ||
1373 | //bio_readline (bio); | ||
1374 | mpd->state = POP_RETR_RX_BODY; | 1411 | mpd->state = POP_RETR_RX_BODY; |
1375 | 1412 | ||
1376 | case POP_RETR_RX_BODY: | 1413 | case POP_RETR_RX_BODY: |
1377 | /* Start taking the body. */ | 1414 | /* Start/Take the body. */ |
1378 | { | 1415 | { |
1379 | while (mpm->inbody) | 1416 | while (mpm->inbody) |
1380 | { | 1417 | { |
... | @@ -1411,10 +1448,15 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, | ... | @@ -1411,10 +1448,15 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, |
1411 | } | 1448 | } |
1412 | } | 1449 | } |
1413 | mpd->state = POP_STATE_DONE; | 1450 | mpd->state = POP_STATE_DONE; |
1451 | /* Return here, because we want to return nread = 0 to notify the calle | ||
1452 | that we've finish. If we don't we will start over again by sending | ||
1453 | another RETR. hmm Is there a better way. */ | ||
1414 | return 0; | 1454 | return 0; |
1455 | |||
1415 | case POP_STATE_DONE: | 1456 | case POP_STATE_DONE: |
1416 | /* A convenient break, this is here so we can return 0 read on next | 1457 | /* A convenient break, this is here so we can return 0 read on next |
1417 | call meaning we're done. */ | 1458 | call meaning we're done. */ |
1459 | |||
1418 | default: | 1460 | default: |
1419 | /* fprintf (stderr, "pop_retr unknow state\n"); */ | 1461 | /* fprintf (stderr, "pop_retr unknow state\n"); */ |
1420 | break; | 1462 | break; |
... | @@ -1425,6 +1467,7 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, | ... | @@ -1425,6 +1467,7 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, |
1425 | return 0; | 1467 | return 0; |
1426 | } | 1468 | } |
1427 | 1469 | ||
1470 | /* Allocate buffer for I/O. */ | ||
1428 | static int | 1471 | static int |
1429 | bio_create (bio_t *pbio, stream_t stream) | 1472 | bio_create (bio_t *pbio, stream_t stream) |
1430 | { | 1473 | { |
... | @@ -1439,6 +1482,7 @@ bio_create (bio_t *pbio, stream_t stream) | ... | @@ -1439,6 +1482,7 @@ bio_create (bio_t *pbio, stream_t stream) |
1439 | return 0; | 1482 | return 0; |
1440 | } | 1483 | } |
1441 | 1484 | ||
1485 | /* Free() buffer but do not close the stream. */ | ||
1442 | static void | 1486 | static void |
1443 | bio_destroy (bio_t *pbio) | 1487 | bio_destroy (bio_t *pbio) |
1444 | { | 1488 | { |
... | @@ -1451,6 +1495,7 @@ bio_destroy (bio_t *pbio) | ... | @@ -1451,6 +1495,7 @@ bio_destroy (bio_t *pbio) |
1451 | } | 1495 | } |
1452 | } | 1496 | } |
1453 | 1497 | ||
1498 | /* Send as much data as possible. */ | ||
1454 | static int | 1499 | static int |
1455 | bio_write (bio_t bio) | 1500 | bio_write (bio_t bio) |
1456 | { | 1501 | { |
... | @@ -1470,6 +1515,7 @@ bio_write (bio_t bio) | ... | @@ -1470,6 +1515,7 @@ bio_write (bio_t bio) |
1470 | return 0; | 1515 | return 0; |
1471 | } | 1516 | } |
1472 | 1517 | ||
1518 | /* Read into the buffer. */ | ||
1473 | static int | 1519 | static int |
1474 | bio_read (bio_t bio) | 1520 | bio_read (bio_t bio) |
1475 | { | 1521 | { | ... | ... |
... | @@ -53,6 +53,12 @@ | ... | @@ -53,6 +53,12 @@ |
53 | #define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED) | 53 | #define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED) |
54 | #define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2) | 54 | #define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2) |
55 | 55 | ||
56 | struct _unix_message; | ||
57 | struct _unix_data; | ||
58 | |||
59 | typedef struct _unix_data* unix_data_t; | ||
60 | typedef struct _unix_message* unix_message_t; | ||
61 | |||
56 | static int unix_create (mailbox_t *pmbox, const char *name); | 62 | static int unix_create (mailbox_t *pmbox, const char *name); |
57 | static void unix_destroy (mailbox_t *pmbox); | 63 | static void unix_destroy (mailbox_t *pmbox); |
58 | 64 | ||
... | @@ -64,7 +70,7 @@ struct mailbox_registrar _mailbox_unix_registrar = | ... | @@ -64,7 +70,7 @@ struct mailbox_registrar _mailbox_unix_registrar = |
64 | 70 | ||
65 | /* Keep the position of where the header and body starts and ends. | 71 | /* Keep the position of where the header and body starts and ends. |
66 | old_flags is the "Status:" message. */ | 72 | old_flags is the "Status:" message. */ |
67 | typedef struct _unix_message | 73 | struct _unix_message |
68 | { | 74 | { |
69 | /* Offset of the parts of the messages in the mailbox. */ | 75 | /* Offset of the parts of the messages in the mailbox. */ |
70 | off_t header_from; | 76 | off_t header_from; |
... | @@ -90,7 +96,7 @@ typedef struct _unix_message | ... | @@ -90,7 +96,7 @@ typedef struct _unix_message |
90 | /* A message attach to it. */ | 96 | /* A message attach to it. */ |
91 | message_t message; | 97 | message_t message; |
92 | 98 | ||
93 | } *unix_message_t; | 99 | }; |
94 | 100 | ||
95 | /* The umessages is an array of pointers that contains umessages_count of | 101 | /* The umessages is an array of pointers that contains umessages_count of |
96 | unix_message_t*; umessages[umessages_count]. We do it this because | 102 | unix_message_t*; umessages[umessages_count]. We do it this because |
... | @@ -98,7 +104,7 @@ typedef struct _unix_message | ... | @@ -98,7 +104,7 @@ typedef struct _unix_message |
98 | the pointers someone has on the messages. Thanks to <Dave Inglis> for | 104 | the pointers someone has on the messages. Thanks to <Dave Inglis> for |
99 | pointing this out. The messages_count is the count number of messages | 105 | pointing this out. The messages_count is the count number of messages |
100 | parsed so far. */ | 106 | parsed so far. */ |
101 | typedef struct _unix_data | 107 | struct _unix_data |
102 | { | 108 | { |
103 | unix_message_t *umessages; | 109 | unix_message_t *umessages; |
104 | size_t umessages_count; | 110 | size_t umessages_count; |
... | @@ -118,8 +124,9 @@ typedef struct _unix_data | ... | @@ -118,8 +124,9 @@ typedef struct _unix_data |
118 | char *date; | 124 | char *date; |
119 | off_t off; | 125 | off_t off; |
120 | 126 | ||
121 | } *unix_data_t; | 127 | }; |
122 | 128 | ||
129 | /* Mailbox implementation. */ | ||
123 | static int unix_open (mailbox_t mbox, int flag); | 130 | static int unix_open (mailbox_t mbox, int flag); |
124 | static int unix_close (mailbox_t mbox); | 131 | static int unix_close (mailbox_t mbox); |
125 | static int unix_get_message (mailbox_t, size_t msgno, message_t *msg); | 132 | static int unix_get_message (mailbox_t, size_t msgno, message_t *msg); |
... | @@ -249,6 +256,7 @@ unix_create (mailbox_t *pmbox, const char *name) | ... | @@ -249,6 +256,7 @@ unix_create (mailbox_t *pmbox, const char *name) |
249 | return 0; /* okdoke */ | 256 | return 0; /* okdoke */ |
250 | } | 257 | } |
251 | 258 | ||
259 | /* Free all ressources associated with Unix mailbox. */ | ||
252 | static void | 260 | static void |
253 | unix_destroy (mailbox_t *pmbox) | 261 | unix_destroy (mailbox_t *pmbox) |
254 | { | 262 | { | ... | ... |
... | @@ -22,8 +22,7 @@ | ... | @@ -22,8 +22,7 @@ |
22 | /* Parsing. | 22 | /* Parsing. |
23 | * The approach is to detect the "From " as start of a | 23 | * The approach is to detect the "From " as start of a |
24 | * new message, give the position of the header and scan | 24 | * new message, give the position of the header and scan |
25 | * until "\n" then set header_end, set body position, if we have | 25 | * until "\n" then set header_end, set body position, |
26 | * a Content-Length field jump to the point if not | ||
27 | * scan until we it another "From " and set body_end. | 26 | * scan until we it another "From " and set body_end. |
28 | * | 27 | * |
29 | ************************************ | 28 | ************************************ |
... | @@ -187,7 +186,7 @@ do \ | ... | @@ -187,7 +186,7 @@ do \ |
187 | (buf[4] == 'U' || buf[4] == 'u') && \ | 186 | (buf[4] == 'U' || buf[4] == 'u') && \ |
188 | (buf[5] == 'S' || buf[5] == 's') && (buf[6] == ':')) | 187 | (buf[5] == 'S' || buf[5] == 's') && (buf[6] == ':')) |
189 | 188 | ||
190 | /* notification */ | 189 | /* Notification. */ |
191 | #define MAILBOX_NOTIFICATION(mbox,which,bailing) \ | 190 | #define MAILBOX_NOTIFICATION(mbox,which,bailing) \ |
192 | do \ | 191 | do \ |
193 | { \ | 192 | { \ |
... | @@ -201,7 +200,7 @@ do \ | ... | @@ -201,7 +200,7 @@ do \ |
201 | } \ | 200 | } \ |
202 | } while (0) | 201 | } while (0) |
203 | 202 | ||
204 | /* notifications ADD_MESG */ | 203 | /* Notifications ADD_MESG. */ |
205 | #define DISPATCH_ADD_MSG(mbox,mud) \ | 204 | #define DISPATCH_ADD_MSG(mbox,mud) \ |
206 | do \ | 205 | do \ |
207 | { \ | 206 | { \ |
... | @@ -218,17 +217,12 @@ do \ | ... | @@ -218,17 +217,12 @@ do \ |
218 | unix_ilock (mbox, MU_LOCKER_WRLOCK); \ | 217 | unix_ilock (mbox, MU_LOCKER_WRLOCK); \ |
219 | } while (0); | 218 | } while (0); |
220 | 219 | ||
221 | /* notification MBX_PROGRESS | 220 | /* Notification MBX_PROGRESS |
222 | * We do not want to fire up the progress notification | 221 | We do not want to fire up the progress notification every line, it will be |
223 | * every line, it will be too expensive, so we do it | 222 | too expensive, so we do it arbitrarely every 10 000 Lines. |
224 | * arbitrarely every 10 000 Lines. | 223 | FIXME: maybe this should be configurable. */ |
225 | * FIXME: maybe this should be configurable. | 224 | /* This is more tricky we can not leave the mum struct incomplete. So we |
226 | */ | 225 | only tell them about the complete messages. */ |
227 | /* | ||
228 | * This is more tricky we can not leave the mum | ||
229 | * struct incomplete. So we only tell them about | ||
230 | * the complete messages. | ||
231 | */ | ||
232 | #define DISPATCH_PROGRESS(mbox,mud) \ | 226 | #define DISPATCH_PROGRESS(mbox,mud) \ |
233 | do \ | 227 | do \ |
234 | { \ | 228 | { \ |
... | @@ -249,25 +243,7 @@ do \ | ... | @@ -249,25 +243,7 @@ do \ |
249 | } \ | 243 | } \ |
250 | } while (0) | 244 | } while (0) |
251 | 245 | ||
252 | #if 0 | 246 | /* Allocate slots for the new messages. */ |
253 | /* skip a function call, ?? do we gain that much */ | ||
254 | #define ATTRIBUTE_CREATE(attr, m, mbox) \ | ||
255 | do \ | ||
256 | { \ | ||
257 | attr = calloc (1, sizeof(*(attr))); \ | ||
258 | attr->owner = m; \ | ||
259 | if ((attr) == NULL) \ | ||
260 | { \ | ||
261 | unix_iunlock (mbox); \ | ||
262 | unix_unlock (mbox); \ | ||
263 | return ENOMEM; \ | ||
264 | } \ | ||
265 | } while (0) | ||
266 | #else | ||
267 | # define ATTRIBUTE_CREATE | ||
268 | #endif | ||
269 | |||
270 | /* allocate slots for the new messages */ | ||
271 | /* size_t num = 2 * ((mud)->messages_count) + 10; */ | 247 | /* size_t num = 2 * ((mud)->messages_count) + 10; */ |
272 | #define ALLOCATE_MSGS(mbox,mud) \ | 248 | #define ALLOCATE_MSGS(mbox,mud) \ |
273 | do \ | 249 | do \ |
... | @@ -303,7 +279,7 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -303,7 +279,7 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
303 | int inheader; | 279 | int inheader; |
304 | int inbody; | 280 | int inbody; |
305 | off_t total = 0; | 281 | off_t total = 0; |
306 | unix_data_t mud; | 282 | unix_data_t mud = mbox->data; |
307 | unix_message_t mum = NULL; | 283 | unix_message_t mum = NULL; |
308 | int status = 0; | 284 | int status = 0; |
309 | size_t lines; | 285 | size_t lines; |
... | @@ -313,21 +289,20 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -313,21 +289,20 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
313 | int zn, isfrom = 0; | 289 | int zn, isfrom = 0; |
314 | char *temp; | 290 | char *temp; |
315 | 291 | ||
316 | /* sanity */ | 292 | /* Sanity. */ |
317 | if (mbox == NULL || | 293 | if (mud == NULL) |
318 | (mud = (unix_data_t)mbox->data) == NULL) | ||
319 | return EINVAL; | 294 | return EINVAL; |
320 | 295 | ||
321 | /* save the timestamp and size */ | 296 | /* Save the timestamp and size. */ |
322 | status = stream_size (mbox->stream, &(mud->size)); | 297 | status = stream_size (mbox->stream, &(mud->size)); |
323 | if (status != 0) | 298 | if (status != 0) |
324 | return status; | 299 | return status; |
325 | 300 | ||
326 | /* grab the locks */ | 301 | /* Grab the locks. */ |
327 | unix_ilock (mbox, MU_LOCKER_WRLOCK); | 302 | unix_ilock (mbox, MU_LOCKER_WRLOCK); |
328 | unix_lock (mbox, MU_LOCKER_RDLOCK); | 303 | unix_lock (mbox, MU_LOCKER_RDLOCK); |
329 | 304 | ||
330 | /* seek to the starting point */ | 305 | /* Seek to the starting point. */ |
331 | if (mud->umessages && msgno > 0 && mud->messages_count > 0 | 306 | if (mud->umessages && msgno > 0 && mud->messages_count > 0 |
332 | && msgno <= mud->messages_count) | 307 | && msgno <= mud->messages_count) |
333 | { | 308 | { |
... | @@ -352,7 +327,7 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -352,7 +327,7 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
352 | VALID(buf, temp, isfrom, zn); | 327 | VALID(buf, temp, isfrom, zn); |
353 | isfrom = (isfrom) ? 1 : 0; | 328 | isfrom = (isfrom) ? 1 : 0; |
354 | 329 | ||
355 | /* which part of the message are we in ? */ | 330 | /* Which part of the message are we in ? */ |
356 | inheader = isfrom | ((!nl) & inheader); | 331 | inheader = isfrom | ((!nl) & inheader); |
357 | inbody = (!isfrom) & (!inheader); | 332 | inbody = (!isfrom) & (!inheader); |
358 | 333 | ||
... | @@ -360,10 +335,10 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -360,10 +335,10 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
360 | 335 | ||
361 | if (inheader) | 336 | if (inheader) |
362 | { | 337 | { |
363 | /* new message */ | 338 | /* New message. */ |
364 | if (isfrom) | 339 | if (isfrom) |
365 | { | 340 | { |
366 | /* signal the end of the body */ | 341 | /* Signal the end of the body. */ |
367 | if (mum && !mum->body_end) | 342 | if (mum && !mum->body_end) |
368 | { | 343 | { |
369 | mum->body_end = total - n - newline; | 344 | mum->body_end = total - n - newline; |
... | @@ -371,7 +346,7 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -371,7 +346,7 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
371 | if (do_notif) | 346 | if (do_notif) |
372 | DISPATCH_ADD_MSG(mbox, mud); | 347 | DISPATCH_ADD_MSG(mbox, mud); |
373 | } | 348 | } |
374 | /* allocate_msgs will initialize mum */ | 349 | /* Allocate_msgs will initialize mum. */ |
375 | ALLOCATE_MSGS(mbox, mud); | 350 | ALLOCATE_MSGS(mbox, mud); |
376 | mud->messages_count++; | 351 | mud->messages_count++; |
377 | mum = mud->umessages[mud->messages_count - 1]; | 352 | mum = mud->umessages[mud->messages_count - 1]; |
... | @@ -391,10 +366,10 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -391,10 +366,10 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
391 | } | 366 | } |
392 | } | 367 | } |
393 | 368 | ||
394 | /* body */ | 369 | /* Body. */ |
395 | if (inbody) | 370 | if (inbody) |
396 | { | 371 | { |
397 | /* set the body position */ | 372 | /* Set the body position. */ |
398 | if (mum && !mum->body) | 373 | if (mum && !mum->body) |
399 | { | 374 | { |
400 | mum->body = total - n + nl; | 375 | mum->body = total - n + nl; |
... | @@ -405,11 +380,11 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -405,11 +380,11 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
405 | 380 | ||
406 | newline = nl; | 381 | newline = nl; |
407 | 382 | ||
408 | /* every 50 mesgs update the lock, it should be every minute */ | 383 | /* Every 50 mesgs update the lock, it should be every minute. */ |
409 | if ((mud->messages_count % 50) == 0) | 384 | if ((mud->messages_count % 50) == 0) |
410 | unix_touchlock (mbox); | 385 | unix_touchlock (mbox); |
411 | 386 | ||
412 | /* ping them every 1000 lines */ | 387 | /* Ping them every 1000 lines. */ |
413 | if (do_notif) | 388 | if (do_notif) |
414 | if (((lines +1) % 1000) == 0) | 389 | if (((lines +1) % 1000) == 0) |
415 | DISPATCH_PROGRESS(mbox, mud); | 390 | DISPATCH_PROGRESS(mbox, mud); |
... | @@ -429,4 +404,3 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -429,4 +404,3 @@ unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) |
429 | *pcount = mud->messages_count; | 404 | *pcount = mud->messages_count; |
430 | return status; | 405 | return status; |
431 | } | 406 | } |
432 | ... | ... |
... | @@ -27,6 +27,7 @@ | ... | @@ -27,6 +27,7 @@ |
27 | #include <time.h> | 27 | #include <time.h> |
28 | #include <string.h> | 28 | #include <string.h> |
29 | 29 | ||
30 | /* FIXME: This should be part of the address_t object when implemented. */ | ||
30 | static int extract_addr(const char *s, size_t n, char **presult, | 31 | static int extract_addr(const char *s, size_t n, char **presult, |
31 | size_t *pnwrite); | 32 | size_t *pnwrite); |
32 | static int message_read (stream_t is, char *buf, size_t buflen, | 33 | static int message_read (stream_t is, char *buf, size_t buflen, |
... | @@ -35,6 +36,7 @@ static int message_write (stream_t os, const char *buf, size_t buflen, | ... | @@ -35,6 +36,7 @@ static int message_write (stream_t os, const char *buf, size_t buflen, |
35 | off_t off, size_t *pnwrite); | 36 | off_t off, size_t *pnwrite); |
36 | static int message_get_fd (stream_t stream, int *pfd); | 37 | static int message_get_fd (stream_t stream, int *pfd); |
37 | 38 | ||
39 | /* Allocate ressources for the message_t. */ | ||
38 | int | 40 | int |
39 | message_create (message_t *pmsg, void *owner) | 41 | message_create (message_t *pmsg, void *owner) |
40 | { | 42 | { |
... | @@ -59,31 +61,45 @@ message_destroy (message_t *pmsg, void *owner) | ... | @@ -59,31 +61,45 @@ message_destroy (message_t *pmsg, void *owner) |
59 | 61 | ||
60 | if (msg->owner == owner) | 62 | if (msg->owner == owner) |
61 | { | 63 | { |
62 | /* notify the listeners */ | 64 | /* Notify the listeners. */ |
65 | /* FIXME: to be removed since we do not supoort this event. */ | ||
63 | if (msg->event_num) | 66 | if (msg->event_num) |
64 | { | 67 | { |
65 | message_notification (msg, MU_EVT_MSG_DESTROY); | 68 | message_notification (msg, MU_EVT_MSG_DESTROY); |
66 | free (msg->event); | 69 | free (msg->event); |
67 | } | 70 | } |
68 | /* header */ | 71 | |
69 | header_destroy (&(msg->header), owner); | 72 | /* Header. */ |
70 | /* attribute */ | 73 | if (msg->header) |
71 | attribute_destroy (&(msg->attribute), owner); | 74 | header_destroy (&(msg->header), owner); |
72 | /* stream */ | 75 | if (msg->header) |
73 | stream_destroy (&(msg->stream), owner); | 76 | header_destroy (&(msg->header), msg); |
74 | 77 | ||
75 | /* if sometype of floating/temporary message */ | 78 | /* Attribute. */ |
76 | body_destroy (&(msg->body), owner); | 79 | if (msg->attribute) |
77 | /* notifications are done */ | 80 | attribute_destroy (&(msg->attribute), owner); |
78 | 81 | if (msg->attribute) | |
79 | /* check again for resurrection before free()ing | 82 | attribute_destroy (&(msg->attribute), msg); |
80 | * the memory maybe it was clone, if yes we can not | 83 | |
81 | * free the pointer. | 84 | /* Stream. */ |
82 | * | 85 | if (msg->stream) |
83 | */ | 86 | stream_destroy (&(msg->stream), owner); |
87 | if (msg->stream) | ||
88 | stream_destroy (&(msg->stream), msg); | ||
89 | |||
90 | /* Body. */ | ||
91 | if (msg->body) | ||
92 | body_destroy (&(msg->body), owner); | ||
93 | if (msg->body) | ||
94 | body_destroy (&(msg->body), msg); | ||
95 | |||
96 | /* Mime. */ | ||
97 | if (msg->mime) | ||
98 | mime_destroy (&(msg->mime)); | ||
99 | |||
84 | free (msg); | 100 | free (msg); |
85 | } | 101 | } |
86 | /* loose the link */ | 102 | /* Loose the link */ |
87 | *pmsg = NULL; | 103 | *pmsg = NULL; |
88 | } | 104 | } |
89 | } | 105 | } |
... | @@ -94,8 +110,8 @@ message_get_header (message_t msg, header_t *phdr) | ... | @@ -94,8 +110,8 @@ message_get_header (message_t msg, header_t *phdr) |
94 | if (msg == NULL || phdr == NULL) | 110 | if (msg == NULL || phdr == NULL) |
95 | return EINVAL; | 111 | return EINVAL; |
96 | 112 | ||
97 | /* is it a floating mesg */ | 113 | /* Is it a floating mesg */ |
98 | if (msg->header == NULL && msg->owner == NULL) | 114 | if (msg->header == NULL) |
99 | { | 115 | { |
100 | header_t header; | 116 | header_t header; |
101 | int status = header_create (&header, NULL, 0, msg); | 117 | int status = header_create (&header, NULL, 0, msg); |
... | @@ -114,8 +130,9 @@ message_set_header (message_t msg, header_t hdr, void *owner) | ... | @@ -114,8 +130,9 @@ message_set_header (message_t msg, header_t hdr, void *owner) |
114 | return EINVAL; | 130 | return EINVAL; |
115 | if (msg->owner != owner) | 131 | if (msg->owner != owner) |
116 | return EACCES; | 132 | return EACCES; |
117 | /* make sure we destoy the old if it was own by the mesg */ | 133 | /* Make sure we destoy the old if it was own by the mesg */ |
118 | header_destroy (&(msg->header), msg); | 134 | /* FIXME: I do not know if somebody has already a ref on this ? */ |
135 | /* header_destroy (&(msg->header), msg); */ | ||
119 | msg->header = hdr; | 136 | msg->header = hdr; |
120 | return 0; | 137 | return 0; |
121 | } | 138 | } |
... | @@ -126,7 +143,7 @@ message_get_body (message_t msg, body_t *pbody) | ... | @@ -126,7 +143,7 @@ message_get_body (message_t msg, body_t *pbody) |
126 | if (msg == NULL || pbody == NULL) | 143 | if (msg == NULL || pbody == NULL) |
127 | return EINVAL; | 144 | return EINVAL; |
128 | 145 | ||
129 | /* is it a floating mesg */ | 146 | /* Is it a floating mesg. */ |
130 | if (msg->body == NULL) | 147 | if (msg->body == NULL) |
131 | { | 148 | { |
132 | body_t body; | 149 | body_t body; |
... | @@ -146,8 +163,9 @@ message_set_body (message_t msg, body_t body, void *owner) | ... | @@ -146,8 +163,9 @@ message_set_body (message_t msg, body_t body, void *owner) |
146 | return EINVAL; | 163 | return EINVAL; |
147 | if (msg->owner != owner) | 164 | if (msg->owner != owner) |
148 | return EACCES; | 165 | return EACCES; |
149 | /* make sure we destoy the old if it was own by the mesg */ | 166 | /* Make sure we destoy the old if it was own by the mesg. */ |
150 | body_destroy (&(msg->body), msg); | 167 | /* FIXME: I do not know if somebody has already a ref on this ? */ |
168 | /* body_destroy (&(msg->body), msg); */ | ||
151 | msg->body = body; | 169 | msg->body = body; |
152 | return 0; | 170 | return 0; |
153 | } | 171 | } |
... | @@ -205,7 +223,7 @@ message_lines (message_t msg, size_t *plines) | ... | @@ -205,7 +223,7 @@ message_lines (message_t msg, size_t *plines) |
205 | size_t hlines, blines; | 223 | size_t hlines, blines; |
206 | if (msg == NULL) | 224 | if (msg == NULL) |
207 | return EINVAL; | 225 | return EINVAL; |
208 | /* Overload */ | 226 | /* Overload. */ |
209 | if (msg->_lines) | 227 | if (msg->_lines) |
210 | return msg->_lines (msg, plines); | 228 | return msg->_lines (msg, plines); |
211 | if (plines) | 229 | if (plines) |
... | @@ -272,11 +290,11 @@ message_from (message_t msg, char *buf, size_t len, size_t *pnwrite) | ... | @@ -272,11 +290,11 @@ message_from (message_t msg, char *buf, size_t len, size_t *pnwrite) |
272 | if (msg == NULL) | 290 | if (msg == NULL) |
273 | return EINVAL; | 291 | return EINVAL; |
274 | 292 | ||
275 | /* did they provide a way to get it */ | 293 | /* Did they provide a way to get it ? */ |
276 | if (msg->_from) | 294 | if (msg->_from) |
277 | return msg->_from (msg, buf, len, pnwrite); | 295 | return msg->_from (msg, buf, len, pnwrite); |
278 | 296 | ||
279 | /* can it be extracted from the From: */ | 297 | /* Can it be extracted from the From: */ |
280 | message_get_header (msg, &header); | 298 | message_get_header (msg, &header); |
281 | status = header_get_value (header, MU_HEADER_FROM, NULL, 0, &n); | 299 | status = header_get_value (header, MU_HEADER_FROM, NULL, 0, &n); |
282 | if (status == 0 && n != 0) | 300 | if (status == 0 && n != 0) |
... | @@ -335,14 +353,14 @@ message_received (message_t msg, char *buf, size_t len, size_t *pnwrite) | ... | @@ -335,14 +353,14 @@ message_received (message_t msg, char *buf, size_t len, size_t *pnwrite) |
335 | size_t n; | 353 | size_t n; |
336 | if (msg == NULL) | 354 | if (msg == NULL) |
337 | return EINVAL; | 355 | return EINVAL; |
338 | /* is it provided */ | 356 | /* Is it provided ? */ |
339 | if (msg->_received) | 357 | if (msg->_received) |
340 | return msg->_received (msg, buf, len, pnwrite); | 358 | return msg->_received (msg, buf, len, pnwrite); |
341 | 359 | ||
342 | /* FIXME: extract the time from "Date:" */ | 360 | /* FIXME: extract the time from "Date:". */ |
343 | 361 | ||
344 | /* catch all */ | 362 | /* Catch all. */ |
345 | /* FIXME: ctime() is not thread safe use strftime() */ | 363 | /* FIXME: ctime() is not thread safe use strftime(). */ |
346 | t = time (NULL); | 364 | t = time (NULL); |
347 | n = strlen (ctime (&t)); | 365 | n = strlen (ctime (&t)); |
348 | 366 | ||
... | @@ -406,7 +424,7 @@ message_get_uidl (message_t msg, char *buffer, size_t buflen, size_t *pwritten) | ... | @@ -406,7 +424,7 @@ message_get_uidl (message_t msg, char *buffer, size_t buflen, size_t *pwritten) |
406 | 424 | ||
407 | int | 425 | int |
408 | message_set_uidl (message_t msg, int (* _get_uidl) | 426 | message_set_uidl (message_t msg, int (* _get_uidl) |
409 | __P ((message_t msg, char *buffer, size_t buflen, size_t *pwritten)), void *owner) | 427 | __P ((message_t, char *, size_t, size_t *)), void *owner) |
410 | { | 428 | { |
411 | if (msg == NULL) | 429 | if (msg == NULL) |
412 | return EINVAL; | 430 | return EINVAL; |
... | @@ -527,7 +545,7 @@ message_register (message_t msg, size_t type, | ... | @@ -527,7 +545,7 @@ message_register (message_t msg, size_t type, |
527 | if (msg == NULL || action == NULL || type == 0) | 545 | if (msg == NULL || action == NULL || type == 0) |
528 | return EINVAL; | 546 | return EINVAL; |
529 | 547 | ||
530 | /* find a free spot */ | 548 | /* Find a free spot. */ |
531 | for (i = 0; i < msg->event_num; i++) | 549 | for (i = 0; i < msg->event_num; i++) |
532 | { | 550 | { |
533 | event = &(msg->event[i]); | 551 | event = &(msg->event[i]); |
... | @@ -633,7 +651,7 @@ message_write (stream_t os, const char *buf, size_t buflen, | ... | @@ -633,7 +651,7 @@ message_write (stream_t os, const char *buf, size_t buflen, |
633 | if (os == NULL || (msg = os->owner) == NULL) | 651 | if (os == NULL || (msg = os->owner) == NULL) |
634 | return EINVAL; | 652 | return EINVAL; |
635 | 653 | ||
636 | /* skip the obvious */ | 654 | /* Skip the obvious. */ |
637 | if (buf == NULL || *buf == '\0' || buflen == 0) | 655 | if (buf == NULL || *buf == '\0' || buflen == 0) |
638 | { | 656 | { |
639 | if (pnwrite) | 657 | if (pnwrite) |
... | @@ -649,7 +667,7 @@ message_write (stream_t os, const char *buf, size_t buflen, | ... | @@ -649,7 +667,7 @@ message_write (stream_t os, const char *buf, size_t buflen, |
649 | while (!msg->hdr_done && (nl = memchr (buf, '\n', buflen)) != NULL) | 667 | while (!msg->hdr_done && (nl = memchr (buf, '\n', buflen)) != NULL) |
650 | { | 668 | { |
651 | len = nl - buf + 1; | 669 | len = nl - buf + 1; |
652 | /* allocate more buffer to hold the header */ | 670 | /* Allocate more buffer to hold the header. */ |
653 | thdr = realloc (msg->hdr_buf, msg->hdr_buflen + len); | 671 | thdr = realloc (msg->hdr_buf, msg->hdr_buflen + len); |
654 | if (thdr == NULL) | 672 | if (thdr == NULL) |
655 | { | 673 | { |
... | @@ -662,8 +680,8 @@ message_write (stream_t os, const char *buf, size_t buflen, | ... | @@ -662,8 +680,8 @@ message_write (stream_t os, const char *buf, size_t buflen, |
662 | msg->hdr_buf = thdr; | 680 | msg->hdr_buf = thdr; |
663 | memcpy (msg->hdr_buf + msg->hdr_buflen, buf, len); | 681 | memcpy (msg->hdr_buf + msg->hdr_buflen, buf, len); |
664 | msg->hdr_buflen += len; | 682 | msg->hdr_buflen += len; |
665 | /* we detect an empty line .i.e "^\n$" this signal the end | 683 | /* We detect an empty line .i.e "^\n$" this signal the end of the |
666 | * of the header */ | 684 | header. */ |
667 | if (buf == nl) | 685 | if (buf == nl) |
668 | { | 686 | { |
669 | header_destroy (&(msg->header), msg); | 687 | header_destroy (&(msg->header), msg); |
... | @@ -683,7 +701,7 @@ message_write (stream_t os, const char *buf, size_t buflen, | ... | @@ -683,7 +701,7 @@ message_write (stream_t os, const char *buf, size_t buflen, |
683 | } | 701 | } |
684 | } | 702 | } |
685 | 703 | ||
686 | /* message header is not complete but was not a full line */ | 704 | /* Message header is not complete but was not a full line. */ |
687 | if (!msg->hdr_done && buflen > 0) | 705 | if (!msg->hdr_done && buflen > 0) |
688 | { | 706 | { |
689 | char *thdr = realloc (msg->hdr_buf, msg->hdr_buflen + buflen); | 707 | char *thdr = realloc (msg->hdr_buf, msg->hdr_buflen + buflen); |
... | @@ -700,7 +718,7 @@ message_write (stream_t os, const char *buf, size_t buflen, | ... | @@ -700,7 +718,7 @@ message_write (stream_t os, const char *buf, size_t buflen, |
700 | msg->hdr_buflen += buflen; | 718 | msg->hdr_buflen += buflen; |
701 | buflen = 0; | 719 | buflen = 0; |
702 | } | 720 | } |
703 | else if (buflen > 0) /* in the body */ | 721 | else if (buflen > 0) /* In the body. */ |
704 | { | 722 | { |
705 | stream_t bs; | 723 | stream_t bs; |
706 | body_t body; | 724 | body_t body; |
... | @@ -735,11 +753,12 @@ message_get_fd (stream_t stream, int *pfd) | ... | @@ -735,11 +753,12 @@ message_get_fd (stream_t stream, int *pfd) |
735 | if (stream == NULL || (msg = stream->owner) == NULL) | 753 | if (stream == NULL || (msg = stream->owner) == NULL) |
736 | return EINVAL; | 754 | return EINVAL; |
737 | 755 | ||
738 | /* Probably being lazy, then create a body for the stream */ | 756 | /* Probably being lazy, then create a body for the stream. */ |
739 | if (msg->body == NULL) | 757 | if (msg->body == NULL) |
740 | { | 758 | { |
741 | int status = body_create (&body, msg); | 759 | int status = body_create (&body, msg); |
742 | if (status != 0 ) | 760 | if (status != 0 ) |
761 | |||
743 | return status; | 762 | return status; |
744 | msg->body = body; | 763 | msg->body = body; |
745 | } | 764 | } |
... | @@ -758,7 +777,7 @@ extract_addr (const char *s, size_t n, char **presult, size_t *pnwrite) | ... | @@ -758,7 +777,7 @@ extract_addr (const char *s, size_t n, char **presult, size_t *pnwrite) |
758 | if (s == NULL || n == 0 || presult == NULL) | 777 | if (s == NULL || n == 0 || presult == NULL) |
759 | return EINVAL; | 778 | return EINVAL; |
760 | 779 | ||
761 | /* skip the double quotes */ | 780 | /* Skip the double quotes. */ |
762 | p = memchr (s, '\"', n); | 781 | p = memchr (s, '\"', n); |
763 | if (p != NULL) | 782 | if (p != NULL) |
764 | { | 783 | { |
... | @@ -775,7 +794,7 @@ extract_addr (const char *s, size_t n, char **presult, size_t *pnwrite) | ... | @@ -775,7 +794,7 @@ extract_addr (const char *s, size_t n, char **presult, size_t *pnwrite) |
775 | } | 794 | } |
776 | } | 795 | } |
777 | 796 | ||
778 | /* <name@hostname> ?? */ | 797 | /* <name@hostname> ?? */ |
779 | p = memchr (s, '<', n); | 798 | p = memchr (s, '<', n); |
780 | if (p != NULL) | 799 | if (p != NULL) |
781 | { | 800 | { |
... | @@ -785,7 +804,7 @@ extract_addr (const char *s, size_t n, char **presult, size_t *pnwrite) | ... | @@ -785,7 +804,7 @@ extract_addr (const char *s, size_t n, char **presult, size_t *pnwrite) |
785 | p2 = memchr (p, ' ', p1 - p); | 804 | p2 = memchr (p, ' ', p1 - p); |
786 | if (p2 == NULL) | 805 | if (p2 == NULL) |
787 | { | 806 | { |
788 | /* the NULL is already accounted for */ | 807 | /* The NULL is already accounted for. */ |
789 | *presult = calloc (1, p1 - p); | 808 | *presult = calloc (1, p1 - p); |
790 | if (*presult == NULL) | 809 | if (*presult == NULL) |
791 | return ENOMEM; | 810 | return ENOMEM; |
... | @@ -796,7 +815,7 @@ extract_addr (const char *s, size_t n, char **presult, size_t *pnwrite) | ... | @@ -796,7 +815,7 @@ extract_addr (const char *s, size_t n, char **presult, size_t *pnwrite) |
796 | } | 815 | } |
797 | } | 816 | } |
798 | } | 817 | } |
799 | /* name@domain */ | 818 | /* name@domain */ |
800 | p = memchr (s, '@', n); | 819 | p = memchr (s, '@', n); |
801 | if (p != NULL) | 820 | if (p != NULL) |
802 | { | 821 | { | ... | ... |
-
Please register or sign in to post a comment