Fix UNIX mbox driver and mail utility.
The `mail' and `frm' utilities pass tests. * include/mailutils/stream.h (mu_stream_err): New proto. * libproto/mbox/mbox.c (_msg_stream_setup) (_msg_body_setup): Fix stream abridgement. (mbox_envelope_date, mbox_envelope_sender): Fix seek position. (uid_to_stream): Fix invocation of mu_stream_printf. (append_message_to_stream): Likewise. (mbox_expunge_unlocked): Rewind tempstr before copying its contents back to the mailbox. (mbox_expunge0): Open tempstr. * libproto/mbox/mbox0.h (_mbox_message)<header_from>: Rename to envel_from. <header_from_end>: Rename to envel_from_end. All uses changed. * libproto/mbox/mboxscan.c: Minor changes. * mail/decode.c: Use streamrefs. * mail/escape.c: Likewise. * mail/msgset.y: Likewise. * mail/pipe.c: Likewise. * mail/print.c: Likewise. * mail/top.c: Likewise. * mail/write.c: Likewise. * mail/send.c: Use streamrefs. (mail_send0): Reset env->header after assigning it to the message. * mailbox/body.c (_body_seek): Fix a typo which produced a recursive call. * mailbox/file_stream.c (fd_truncate): New function. (_mu_file_stream_create): Initialize str->stream.truncate. * mailbox/header.c (header_parse): Fix parsing of blurbs lacking terminating empty line. (header_seek): Fix boundary checks. Return new position in presult. * mailbox/message.c (string_find_eoh): Rewrite to handle \n\n split between two successive invocations. (_header_fill): Update the invocation of string_find_eoh. * mailbox/stream.c (mu_stream_destroy): Call mu_stream_close. (mu_stream_get_flags, mu_stream_set_flags) (mu_stream_clr_flags): Ignore internal bits. (mu_stream_err): New function. (mu_stream_close): Close the stream only if it is not used by anyone else. * mailbox/streamref.c (_streamref_read): Clear transport error if ESPIPE is returned. (_streamref_size): Take into account sp->end and sp->start. (mu_streamref_create_abridged): Set pointer to 0.
Showing
18 changed files
with
182 additions
and
115 deletions
... | @@ -65,6 +65,7 @@ void mu_stream_unref (mu_stream_t stream); | ... | @@ -65,6 +65,7 @@ void mu_stream_unref (mu_stream_t stream); |
65 | void mu_stream_destroy (mu_stream_t *pstream); | 65 | void mu_stream_destroy (mu_stream_t *pstream); |
66 | int mu_stream_open (mu_stream_t stream); | 66 | int mu_stream_open (mu_stream_t stream); |
67 | const char *mu_stream_strerror (mu_stream_t stream, int rc); | 67 | const char *mu_stream_strerror (mu_stream_t stream, int rc); |
68 | int mu_stream_err (mu_stream_t stream); | ||
68 | int mu_stream_last_error (mu_stream_t stream); | 69 | int mu_stream_last_error (mu_stream_t stream); |
69 | void mu_stream_clearerr (mu_stream_t stream); | 70 | void mu_stream_clearerr (mu_stream_t stream); |
70 | int mu_stream_eof (mu_stream_t stream); | 71 | int mu_stream_eof (mu_stream_t stream); | ... | ... |
... | @@ -259,7 +259,7 @@ static int | ... | @@ -259,7 +259,7 @@ static int |
259 | mbox_message_qid (mu_message_t msg, mu_message_qid_t *pqid) | 259 | mbox_message_qid (mu_message_t msg, mu_message_qid_t *pqid) |
260 | { | 260 | { |
261 | mbox_message_t mum = mu_message_get_owner (msg); | 261 | mbox_message_t mum = mu_message_get_owner (msg); |
262 | return mu_asprintf (pqid, "%lu", (unsigned long) mum->header_from); | 262 | return mu_asprintf (pqid, "%lu", (unsigned long) mum->envel_from); |
263 | } | 263 | } |
264 | 264 | ||
265 | 265 | ||
... | @@ -297,8 +297,8 @@ _msg_stream_setup (mu_message_t msg, mbox_message_t mum) | ... | @@ -297,8 +297,8 @@ _msg_stream_setup (mu_message_t msg, mbox_message_t mum) |
297 | 297 | ||
298 | status = mu_streamref_create_abridged (&stream, | 298 | status = mu_streamref_create_abridged (&stream, |
299 | mum->mud->mailbox->stream, | 299 | mum->mud->mailbox->stream, |
300 | mum->header_from_end + 1, | 300 | mum->envel_from_end, |
301 | mum->body); | 301 | mum->body_end); |
302 | if (status == 0) | 302 | if (status == 0) |
303 | status = mu_message_set_stream (msg, stream, mum); | 303 | status = mu_message_set_stream (msg, stream, mum); |
304 | return status; | 304 | return status; |
... | @@ -343,7 +343,7 @@ _msg_body_setup (mu_message_t msg, mbox_message_t mum) | ... | @@ -343,7 +343,7 @@ _msg_body_setup (mu_message_t msg, mbox_message_t mum) |
343 | status = mu_streamref_create_abridged (&stream, | 343 | status = mu_streamref_create_abridged (&stream, |
344 | mum->mud->mailbox->stream, | 344 | mum->mud->mailbox->stream, |
345 | mum->body, | 345 | mum->body, |
346 | mum->body_end); | 346 | mum->body_end - 1); |
347 | if (status) | 347 | if (status) |
348 | mu_body_destroy (&body, msg); | 348 | mu_body_destroy (&body, msg); |
349 | else | 349 | else |
... | @@ -373,7 +373,7 @@ mbox_envelope_date (mu_envelope_t envelope, char *buf, size_t len, | ... | @@ -373,7 +373,7 @@ mbox_envelope_date (mu_envelope_t envelope, char *buf, size_t len, |
373 | return EINVAL; | 373 | return EINVAL; |
374 | 374 | ||
375 | status = mu_stream_seek (mum->mud->mailbox->stream, | 375 | status = mu_stream_seek (mum->mud->mailbox->stream, |
376 | mum->header_from, MU_SEEK_SET, | 376 | mum->envel_from, MU_SEEK_SET, |
377 | NULL); | 377 | NULL); |
378 | if (status) | 378 | if (status) |
379 | return status; | 379 | return status; |
... | @@ -419,7 +419,7 @@ mbox_envelope_sender (mu_envelope_t envelope, char *buf, size_t len, | ... | @@ -419,7 +419,7 @@ mbox_envelope_sender (mu_envelope_t envelope, char *buf, size_t len, |
419 | return EINVAL; | 419 | return EINVAL; |
420 | 420 | ||
421 | status = mu_stream_seek (mum->mud->mailbox->stream, | 421 | status = mu_stream_seek (mum->mud->mailbox->stream, |
422 | mum->header_from, MU_SEEK_SET, | 422 | mum->envel_from, MU_SEEK_SET, |
423 | NULL); | 423 | NULL); |
424 | if (status) | 424 | if (status) |
425 | return status; | 425 | return status; |
... | @@ -1022,8 +1022,10 @@ uid_to_stream (mu_stream_t ostr, mu_message_t msg, mbox_data_t mud, int flags) | ... | @@ -1022,8 +1022,10 @@ uid_to_stream (mu_stream_t ostr, mu_message_t msg, mbox_data_t mud, int flags) |
1022 | else | 1022 | else |
1023 | uid = mud->uidnext++; | 1023 | uid = mud->uidnext++; |
1024 | 1024 | ||
1025 | return mu_stream_printf (ostr, "%s: %u\n", MU_HEADER_X_UID, | 1025 | mu_stream_printf (ostr, "%s: %u\n", MU_HEADER_X_UID, (unsigned) uid); |
1026 | (unsigned) uid); | 1026 | if (mu_stream_err (ostr)) |
1027 | return mu_stream_last_error (ostr); | ||
1028 | return 0; | ||
1027 | } | 1029 | } |
1028 | 1030 | ||
1029 | /* Append MSG to stream OSTR in its current position */ | 1031 | /* Append MSG to stream OSTR in its current position */ |
... | @@ -1048,12 +1050,14 @@ append_message_to_stream (mu_stream_t ostr, mu_message_t msg, | ... | @@ -1048,12 +1050,14 @@ append_message_to_stream (mu_stream_t ostr, mu_message_t msg, |
1048 | 1050 | ||
1049 | if (flags & MBOX_FIRSTMSG) | 1051 | if (flags & MBOX_FIRSTMSG) |
1050 | { | 1052 | { |
1051 | status = mu_stream_printf (ostr, "%s: %lu %u\n", | 1053 | /* FIXME: Perhaps printf should return error code, |
1054 | like the rest of stream functions. */ | ||
1055 | mu_stream_printf (ostr, "%s: %lu %u\n", | ||
1052 | MU_HEADER_X_IMAPBASE, | 1056 | MU_HEADER_X_IMAPBASE, |
1053 | (unsigned long) mud->uidvalidity, | 1057 | (unsigned long) mud->uidvalidity, |
1054 | (unsigned) mud->uidnext); | 1058 | (unsigned) mud->uidnext); |
1055 | if (status) | 1059 | if (mu_stream_err (ostr)) |
1056 | return status; | 1060 | return mu_stream_last_error (ostr); |
1057 | } | 1061 | } |
1058 | 1062 | ||
1059 | status = msg_attr_to_stream (ostr, msg); | 1063 | status = msg_attr_to_stream (ostr, msg); |
... | @@ -1165,7 +1169,7 @@ mbox_reset (mu_mailbox_t mailbox, size_t dirty, int remove_deleted) | ... | @@ -1165,7 +1169,7 @@ mbox_reset (mu_mailbox_t mailbox, size_t dirty, int remove_deleted) |
1165 | else | 1169 | else |
1166 | memset (mum, 0, sizeof (*mum)); | 1170 | memset (mum, 0, sizeof (*mum)); |
1167 | } | 1171 | } |
1168 | mum->header_from = mum->header_from_end = 0; | 1172 | mum->envel_from = mum->envel_from_end = 0; |
1169 | mum->body = mum->body_end = 0; | 1173 | mum->body = mum->body_end = 0; |
1170 | mum->header_lines = mum->body_lines = 0; | 1174 | mum->header_lines = mum->body_lines = 0; |
1171 | } | 1175 | } |
... | @@ -1187,7 +1191,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, | ... | @@ -1187,7 +1191,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, |
1187 | mu_off_t size; | 1191 | mu_off_t size; |
1188 | 1192 | ||
1189 | /* Set the marker position. */ | 1193 | /* Set the marker position. */ |
1190 | start_off = mud->umessages[dirty]->header_from; | 1194 | start_off = mud->umessages[dirty]->envel_from; |
1191 | 1195 | ||
1192 | for (i = dirty; i < mud->messages_count; i++) | 1196 | for (i = dirty; i < mud->messages_count; i++) |
1193 | { | 1197 | { |
... | @@ -1226,8 +1230,8 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, | ... | @@ -1226,8 +1230,8 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, |
1226 | status = mbox_get_message (mailbox, i + 1, &msg); | 1230 | status = mbox_get_message (mailbox, i + 1, &msg); |
1227 | if (status != 0) | 1231 | if (status != 0) |
1228 | { | 1232 | { |
1229 | mu_error (_("error expunging:%d: %s"), __LINE__, | 1233 | mu_error (_("%s:%d: error expunging: %s"), |
1230 | mu_strerror (status)); | 1234 | __FILE__, __LINE__, mu_strerror (status)); |
1231 | return status; | 1235 | return status; |
1232 | } | 1236 | } |
1233 | } | 1237 | } |
... | @@ -1235,8 +1239,8 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, | ... | @@ -1235,8 +1239,8 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, |
1235 | flags); | 1239 | flags); |
1236 | if (status != 0) | 1240 | if (status != 0) |
1237 | { | 1241 | { |
1238 | mu_error (_("error expunging:%d: %s"), __LINE__, | 1242 | mu_error (_("%s:%d: error expunging: %s"), |
1239 | mu_strerror (status)); | 1243 | __FILE__, __LINE__, mu_strerror (status)); |
1240 | return status; | 1244 | return status; |
1241 | } | 1245 | } |
1242 | /* Clear the dirty bits. */ | 1246 | /* Clear the dirty bits. */ |
... | @@ -1247,7 +1251,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, | ... | @@ -1247,7 +1251,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, |
1247 | { | 1251 | { |
1248 | /* Otherwise, copy bits from mailbox->stream as is. */ | 1252 | /* Otherwise, copy bits from mailbox->stream as is. */ |
1249 | 1253 | ||
1250 | status = mu_stream_seek (mailbox->stream, mum->header_from, | 1254 | status = mu_stream_seek (mailbox->stream, mum->envel_from, |
1251 | MU_SEEK_SET, NULL); | 1255 | MU_SEEK_SET, NULL); |
1252 | if (status) | 1256 | if (status) |
1253 | { | 1257 | { |
... | @@ -1257,7 +1261,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, | ... | @@ -1257,7 +1261,7 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, |
1257 | return status; | 1261 | return status; |
1258 | } | 1262 | } |
1259 | status = mu_stream_copy (tempstr, mailbox->stream, | 1263 | status = mu_stream_copy (tempstr, mailbox->stream, |
1260 | mum->body_end - mum->header_from); | 1264 | mum->body_end - mum->envel_from); |
1261 | if (status) | 1265 | if (status) |
1262 | { | 1266 | { |
1263 | mu_error (_("%s:%d: error copying: %s"), | 1267 | mu_error (_("%s:%d: error copying: %s"), |
... | @@ -1336,10 +1340,19 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, | ... | @@ -1336,10 +1340,19 @@ mbox_expunge_unlocked (mu_mailbox_t mailbox, size_t dirty, int remove_deleted, |
1336 | return status; | 1340 | return status; |
1337 | } | 1341 | } |
1338 | 1342 | ||
1343 | status = mu_stream_seek (tempstr, 0, MU_SEEK_SET, NULL); | ||
1344 | if (status) | ||
1345 | { | ||
1346 | mu_error (_("%s:%d: seek error: %s"), | ||
1347 | __FILE__, __LINE__, | ||
1348 | mu_stream_strerror (mailbox->stream, status)); | ||
1349 | return status; | ||
1350 | } | ||
1351 | |||
1339 | status = mu_stream_copy (mailbox->stream, tempstr, size); | 1352 | status = mu_stream_copy (mailbox->stream, tempstr, size); |
1340 | if (status) | 1353 | if (status) |
1341 | { | 1354 | { |
1342 | mu_error (_("%s:%d: error writing to temporary stream: %s"), | 1355 | mu_error (_("%s:%d: copying from the temporary stream: %s"), |
1343 | __FILE__, __LINE__, | 1356 | __FILE__, __LINE__, |
1344 | mu_strerror (status)); | 1357 | mu_strerror (status)); |
1345 | return status; | 1358 | return status; |
... | @@ -1395,6 +1408,9 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted) | ... | @@ -1395,6 +1408,9 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted) |
1395 | status = mu_temp_file_stream_create (&tempstr, NULL); | 1408 | status = mu_temp_file_stream_create (&tempstr, NULL); |
1396 | if (status == 0) | 1409 | if (status == 0) |
1397 | { | 1410 | { |
1411 | status = mu_stream_open (tempstr); | ||
1412 | if (status == 0) | ||
1413 | { | ||
1398 | sigset_t signalset; | 1414 | sigset_t signalset; |
1399 | #ifdef WITH_PTHREAD | 1415 | #ifdef WITH_PTHREAD |
1400 | int state; | 1416 | int state; |
... | @@ -1408,7 +1424,8 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted) | ... | @@ -1408,7 +1424,8 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted) |
1408 | sigaddset (&signalset, SIGWINCH); | 1424 | sigaddset (&signalset, SIGWINCH); |
1409 | sigprocmask (SIG_BLOCK, &signalset, 0); | 1425 | sigprocmask (SIG_BLOCK, &signalset, 0); |
1410 | 1426 | ||
1411 | status = mbox_expunge_unlocked (mailbox, dirty, remove_deleted, tempstr); | 1427 | status = mbox_expunge_unlocked (mailbox, dirty, remove_deleted, |
1428 | tempstr); | ||
1412 | 1429 | ||
1413 | #ifdef WITH_PTHREAD | 1430 | #ifdef WITH_PTHREAD |
1414 | pthread_setcancelstate (state, &state); | 1431 | pthread_setcancelstate (state, &state); |
... | @@ -1420,6 +1437,7 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted) | ... | @@ -1420,6 +1437,7 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted) |
1420 | if (status == 0) | 1437 | if (status == 0) |
1421 | mbox_reset (mailbox, dirty, remove_deleted); | 1438 | mbox_reset (mailbox, dirty, remove_deleted); |
1422 | } | 1439 | } |
1440 | } | ||
1423 | mu_locker_unlock (mailbox->locker); | 1441 | mu_locker_unlock (mailbox->locker); |
1424 | return status; | 1442 | return status; |
1425 | } | 1443 | } | ... | ... |
... | @@ -71,8 +71,8 @@ typedef struct _mbox_message *mbox_message_t; | ... | @@ -71,8 +71,8 @@ typedef struct _mbox_message *mbox_message_t; |
71 | struct _mbox_message | 71 | struct _mbox_message |
72 | { | 72 | { |
73 | /* Offset of the messages in the mailbox. */ | 73 | /* Offset of the messages in the mailbox. */ |
74 | mu_off_t header_from; /* Start of envelope (^From ) */ | 74 | mu_off_t envel_from; /* Start of envelope (^From ) */ |
75 | mu_off_t header_from_end; /* End of envelope (terminating \n) */ | 75 | mu_off_t envel_from_end; /* End of envelope (terminating \n) */ |
76 | mu_off_t body; /* Start of body */ | 76 | mu_off_t body; /* Start of body */ |
77 | mu_off_t body_end; /* End of body */ | 77 | mu_off_t body_end; /* End of body */ |
78 | 78 | ... | ... |
... | @@ -359,11 +359,10 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum, | ... | @@ -359,11 +359,10 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum, |
359 | } | 359 | } |
360 | /* Allocate_msgs will initialize mum. */ | 360 | /* Allocate_msgs will initialize mum. */ |
361 | ALLOCATE_MSGS (mailbox, mud); | 361 | ALLOCATE_MSGS (mailbox, mud); |
362 | mud->messages_count++; | 362 | mum = mud->umessages[mud->messages_count++]; |
363 | mum = mud->umessages[mud->messages_count - 1]; | ||
364 | mum->mud = mud; | 363 | mum->mud = mud; |
365 | mum->header_from = total - n; | 364 | mum->envel_from = total - n; |
366 | mum->header_from_end = total; | 365 | mum->envel_from_end = total; |
367 | mum->body_end = mum->body = 0; | 366 | mum->body_end = mum->body = 0; |
368 | mum->attr_flags = 0; | 367 | mum->attr_flags = 0; |
369 | lines = 0; | 368 | lines = 0; |
... | @@ -467,7 +466,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) | ... | @@ -467,7 +466,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) |
467 | { | 466 | { |
468 | mum = mud->umessages[msgno - 1]; | 467 | mum = mud->umessages[msgno - 1]; |
469 | if (mum) | 468 | if (mum) |
470 | total = mum->header_from; | 469 | total = mum->envel_from; |
471 | mud->messages_count = msgno - 1; | 470 | mud->messages_count = msgno - 1; |
472 | } | 471 | } |
473 | else | 472 | else | ... | ... |
... | @@ -116,8 +116,11 @@ display_headers (FILE *out, mu_message_t mesg, | ... | @@ -116,8 +116,11 @@ display_headers (FILE *out, mu_message_t mesg, |
116 | { | 116 | { |
117 | mu_stream_t stream = NULL; | 117 | mu_stream_t stream = NULL; |
118 | if (mu_message_get_header (mesg, &hdr) == 0 | 118 | if (mu_message_get_header (mesg, &hdr) == 0 |
119 | && mu_header_get_stream (hdr, &stream) == 0) | 119 | && mu_header_get_streamref (hdr, &stream) == 0) |
120 | { | ||
120 | print_stream (stream, out); | 121 | print_stream (stream, out); |
122 | mu_stream_destroy (&stream); | ||
123 | } | ||
121 | } | 124 | } |
122 | } | 125 | } |
123 | 126 | ||
... | @@ -254,10 +257,10 @@ display_submessage (struct mime_descend_closure *closure, void *data) | ... | @@ -254,10 +257,10 @@ display_submessage (struct mime_descend_closure *closure, void *data) |
254 | 257 | ||
255 | mu_message_get_body (closure->message, &body); | 258 | mu_message_get_body (closure->message, &body); |
256 | mu_message_get_header (closure->message, &hdr); | 259 | mu_message_get_header (closure->message, &hdr); |
257 | mu_body_get_stream (body, &b_stream); | 260 | mu_body_get_streamref (body, &b_stream); |
258 | 261 | ||
259 | /* Can we decode. */ | 262 | /* Can we decode. */ |
260 | if (mu_filter_create(&d_stream, b_stream, closure->encoding, | 263 | if (mu_filter_create (&d_stream, b_stream, closure->encoding, |
261 | MU_FILTER_DECODE, | 264 | MU_FILTER_DECODE, |
262 | MU_STREAM_READ|MU_STREAM_NO_CLOSE) == 0) | 265 | MU_STREAM_READ|MU_STREAM_NO_CLOSE) == 0) |
263 | stream = d_stream; | 266 | stream = d_stream; |
... | @@ -303,13 +306,13 @@ display_submessage (struct mime_descend_closure *closure, void *data) | ... | @@ -303,13 +306,13 @@ display_submessage (struct mime_descend_closure *closure, void *data) |
303 | if (out != ofile) | 306 | if (out != ofile) |
304 | pclose (out); | 307 | pclose (out); |
305 | } | 308 | } |
306 | if (d_stream) | 309 | mu_stream_destroy (&stream); |
307 | mu_stream_destroy (&d_stream); | ||
308 | } | 310 | } |
309 | 311 | ||
310 | return 0; | 312 | return 0; |
311 | } | 313 | } |
312 | 314 | ||
315 | /* FIXME: Try to use mu_stream_copy instead */ | ||
313 | static int | 316 | static int |
314 | print_stream (mu_stream_t stream, FILE *out) | 317 | print_stream (mu_stream_t stream, FILE *out) |
315 | { | 318 | { |
... | @@ -317,12 +320,6 @@ print_stream (mu_stream_t stream, FILE *out) | ... | @@ -317,12 +320,6 @@ print_stream (mu_stream_t stream, FILE *out) |
317 | size_t n = 0; | 320 | size_t n = 0; |
318 | int rc; | 321 | int rc; |
319 | 322 | ||
320 | rc = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | ||
321 | if (rc) | ||
322 | { | ||
323 | util_error (_("seek error: %s"), mu_stream_strerror (stream, rc)); | ||
324 | return rc; | ||
325 | } | ||
326 | while (mu_stream_read (stream, buffer, sizeof (buffer) - 1, &n) == 0 | 323 | while (mu_stream_read (stream, buffer, sizeof (buffer) - 1, &n) == 0 |
327 | && n != 0) | 324 | && n != 0) |
328 | { | 325 | { |
... | @@ -397,20 +394,18 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg) | ... | @@ -397,20 +394,18 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg) |
397 | { | 394 | { |
398 | /* Child process */ | 395 | /* Child process */ |
399 | int status; | 396 | int status; |
400 | mu_stream_t stream; | 397 | mu_stream_t stream = NULL; |
401 | 398 | ||
402 | do /* Fake loop to avoid gotos */ | 399 | do /* Fake loop to avoid gotos */ |
403 | { | 400 | { |
404 | mu_stream_t pstr; | 401 | mu_stream_t pstr; |
405 | char buffer[512]; | ||
406 | size_t n; | ||
407 | char *no_ask; | 402 | char *no_ask; |
408 | 403 | ||
409 | setenv ("METAMAIL_PAGER", getenv ("PAGER"), 0); | 404 | setenv ("METAMAIL_PAGER", getenv ("PAGER"), 0); |
410 | if (mailvar_get (&no_ask, "mimenoask", mailvar_type_string, 0)) | 405 | if (mailvar_get (&no_ask, "mimenoask", mailvar_type_string, 0)) |
411 | setenv ("MM_NOASK", no_ask, 1); | 406 | setenv ("MM_NOASK", no_ask, 1); |
412 | 407 | ||
413 | status = mu_message_get_stream (mesg, &stream); | 408 | status = mu_message_get_streamref (mesg, &stream); |
414 | if (status) | 409 | if (status) |
415 | { | 410 | { |
416 | mu_error ("mu_message_get_stream: %s", mu_strerror (status)); | 411 | mu_error ("mu_message_get_stream: %s", mu_strerror (status)); |
... | @@ -430,12 +425,7 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg) | ... | @@ -430,12 +425,7 @@ run_metamail (const char *mailcap_cmd, mu_message_t mesg) |
430 | mu_error ("mu_stream_open: %s", mu_strerror (status)); | 425 | mu_error ("mu_stream_open: %s", mu_strerror (status)); |
431 | break; | 426 | break; |
432 | } | 427 | } |
433 | mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | 428 | mu_stream_copy (pstr, stream, 0); |
434 | while (mu_stream_read (stream, buffer, sizeof buffer - 1, | ||
435 | &n) == 0 | ||
436 | && n > 0) | ||
437 | mu_stream_write (pstr, buffer, n, NULL); | ||
438 | |||
439 | mu_stream_close (pstr); | 429 | mu_stream_close (pstr); |
440 | mu_stream_destroy (&pstr); | 430 | mu_stream_destroy (&pstr); |
441 | exit (0); | 431 | exit (0); | ... | ... |
... | @@ -30,19 +30,21 @@ dump_headers (FILE *fp, compose_env_t *env) | ... | @@ -30,19 +30,21 @@ dump_headers (FILE *fp, compose_env_t *env) |
30 | size_t n; | 30 | size_t n; |
31 | int rc; | 31 | int rc; |
32 | 32 | ||
33 | mu_header_get_stream (env->header, &stream); | 33 | rc = mu_header_get_streamref (env->header, &stream); |
34 | rc = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | ||
35 | if (rc) | 34 | if (rc) |
36 | { | 35 | { |
37 | util_error (_("seek error: %s"), mu_stream_strerror (stream, rc)); | 36 | util_error ("mu_header_get_streamref: %s", |
37 | mu_stream_strerror (stream, rc)); | ||
38 | return; | 38 | return; |
39 | } | 39 | } |
40 | /* FIXME: Use mu_stream_copy */ | ||
40 | while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0 | 41 | while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0 |
41 | && n != 0) | 42 | && n != 0) |
42 | { | 43 | { |
43 | buffer[n] = 0; | 44 | buffer[n] = 0; |
44 | fprintf (fp, "%s", buffer); | 45 | fprintf (fp, "%s", buffer); |
45 | } | 46 | } |
47 | mu_stream_destroy (&stream); | ||
46 | } | 48 | } |
47 | 49 | ||
48 | #define STATE_INIT 0 | 50 | #define STATE_INIT 0 |
... | @@ -478,24 +480,25 @@ quote0 (msgset_t *mspec, mu_message_t mesg, void *data) | ... | @@ -478,24 +480,25 @@ quote0 (msgset_t *mspec, mu_message_t mesg, void *data) |
478 | } | 480 | } |
479 | fprintf (ofile, "%s\n", prefix); | 481 | fprintf (ofile, "%s\n", prefix); |
480 | mu_message_get_body (mesg, &body); | 482 | mu_message_get_body (mesg, &body); |
481 | mu_body_get_stream (body, &stream); | 483 | rc = mu_body_get_streamref (body, &stream); |
482 | } | 484 | } |
483 | else | 485 | else |
484 | mu_message_get_stream (mesg, &stream); | 486 | rc = mu_message_get_streamref (mesg, &stream); |
485 | 487 | ||
486 | rc = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | ||
487 | if (rc) | 488 | if (rc) |
488 | { | 489 | { |
489 | util_error (_("seek error: %s"), mu_stream_strerror (stream, rc)); | 490 | util_error (_("get_streamref error: %s"), mu_strerror (rc)); |
490 | return rc; | 491 | return rc; |
491 | } | 492 | } |
492 | 493 | ||
494 | /* FIXME: Use mu_stream_copy? */ | ||
493 | while (mu_stream_readline (stream, buffer, sizeof buffer - 1, &n) == 0 | 495 | while (mu_stream_readline (stream, buffer, sizeof buffer - 1, &n) == 0 |
494 | && n != 0) | 496 | && n != 0) |
495 | { | 497 | { |
496 | buffer[n] = '\0'; | 498 | buffer[n] = '\0'; |
497 | fprintf (ofile, "%s%s", prefix, buffer); | 499 | fprintf (ofile, "%s%s", prefix, buffer); |
498 | } | 500 | } |
501 | mu_stream_destroy (&stream); | ||
499 | return 0; | 502 | return 0; |
500 | } | 503 | } |
501 | 504 | ... | ... |
... | @@ -629,8 +629,7 @@ select_body (mu_message_t msg, void *closure) | ... | @@ -629,8 +629,7 @@ select_body (mu_message_t msg, void *closure) |
629 | mu_message_get_body (msg, &body); | 629 | mu_message_get_body (msg, &body); |
630 | mu_body_size (body, &size); | 630 | mu_body_size (body, &size); |
631 | mu_body_lines (body, &lines); | 631 | mu_body_lines (body, &lines); |
632 | mu_body_get_stream (body, &stream); | 632 | status = mu_body_get_streamref (body, &stream); |
633 | status = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | ||
634 | while (status == 0 | 633 | while (status == 0 |
635 | && mu_stream_readline (stream, buffer, sizeof(buffer)-1, &n) == 0 | 634 | && mu_stream_readline (stream, buffer, sizeof(buffer)-1, &n) == 0 |
636 | && n > 0) | 635 | && n > 0) |
... | @@ -643,7 +642,7 @@ select_body (mu_message_t msg, void *closure) | ... | @@ -643,7 +642,7 @@ select_body (mu_message_t msg, void *closure) |
643 | else | 642 | else |
644 | status = regexec (&re, buffer, 0, NULL, 0); | 643 | status = regexec (&re, buffer, 0, NULL, 0); |
645 | } | 644 | } |
646 | 645 | mu_stream_destroy (&stream); | |
647 | if (!noregex) | 646 | if (!noregex) |
648 | regfree (&re); | 647 | regfree (&re); |
649 | 648 | ... | ... |
... | @@ -49,14 +49,15 @@ mail_pipe (int argc, char **argv) | ... | @@ -49,14 +49,15 @@ mail_pipe (int argc, char **argv) |
49 | { | 49 | { |
50 | if (util_get_message (mbox, mp->msg_part[0], &msg) == 0) | 50 | if (util_get_message (mbox, mp->msg_part[0], &msg) == 0) |
51 | { | 51 | { |
52 | mu_message_get_stream (msg, &stream); | 52 | mu_message_get_streamref (msg, &stream); |
53 | mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | 53 | /* FIXME: Use mu_stream_copy */ |
54 | while (mu_stream_read (stream, buffer, sizeof (buffer) - 1, &n) == 0 | 54 | while (mu_stream_read (stream, buffer, sizeof (buffer) - 1, &n) == 0 |
55 | && n != 0) | 55 | && n != 0) |
56 | { | 56 | { |
57 | buffer[n] = '\0'; | 57 | buffer[n] = '\0'; |
58 | fprintf (tube, "%s", buffer); | 58 | fprintf (tube, "%s", buffer); |
59 | } | 59 | } |
60 | mu_stream_destroy (&stream); | ||
60 | if (mailvar_get (NULL, "page", mailvar_type_boolean, 0) == 0) | 61 | if (mailvar_get (NULL, "page", mailvar_type_boolean, 0) == 0) |
61 | fprintf (tube, "\f\n"); | 62 | fprintf (tube, "\f\n"); |
62 | } | 63 | } | ... | ... |
... | @@ -36,6 +36,7 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void *data) | ... | @@ -36,6 +36,7 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void *data) |
36 | size_t n = 0, lines = 0; | 36 | size_t n = 0, lines = 0; |
37 | FILE *out = ofile; | 37 | FILE *out = ofile; |
38 | int pagelines = util_get_crt (); | 38 | int pagelines = util_get_crt (); |
39 | int status; | ||
39 | 40 | ||
40 | mu_message_lines (mesg, &lines); | 41 | mu_message_lines (mesg, &lines); |
41 | if (mailvar_get (NULL, "showenvelope", mailvar_type_boolean, 0) == 0) | 42 | if (mailvar_get (NULL, "showenvelope", mailvar_type_boolean, 0) == 0) |
... | @@ -89,12 +90,18 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void *data) | ... | @@ -89,12 +90,18 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void *data) |
89 | } | 90 | } |
90 | fprintf (out, "\n"); | 91 | fprintf (out, "\n"); |
91 | mu_message_get_body (mesg, &body); | 92 | mu_message_get_body (mesg, &body); |
92 | mu_body_get_stream (body, &stream); | 93 | status = mu_body_get_streamref (body, &stream); |
93 | } | 94 | } |
94 | else | 95 | else |
95 | mu_message_get_stream (mesg, &stream); | 96 | status = mu_message_get_streamref (mesg, &stream); |
96 | 97 | ||
97 | mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | 98 | if (status) |
99 | { | ||
100 | mu_error (_("get_stream error: %s"), mu_strerror (status)); | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | /* FIXME: Use mu_stream_copy instead? */ | ||
98 | while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0 | 105 | while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0 |
99 | && n != 0) | 106 | && n != 0) |
100 | { | 107 | { |
... | @@ -106,6 +113,7 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void *data) | ... | @@ -106,6 +113,7 @@ mail_print_msg (msgset_t *mspec, mu_message_t mesg, void *data) |
106 | buffer[n] = '\0'; | 113 | buffer[n] = '\0'; |
107 | fprintf (out, "%s", buffer); | 114 | fprintf (out, "%s", buffer); |
108 | } | 115 | } |
116 | mu_stream_destroy (&stream); | ||
109 | if (out != ofile) | 117 | if (out != ofile) |
110 | pclose (out); | 118 | pclose (out); |
111 | 119 | ... | ... |
... | @@ -293,36 +293,37 @@ compose_header_get (compose_env_t * env, char *name, char *defval) | ... | @@ -293,36 +293,37 @@ compose_header_get (compose_env_t * env, char *name, char *defval) |
293 | } | 293 | } |
294 | 294 | ||
295 | void | 295 | void |
296 | compose_destroy (compose_env_t * env) | 296 | compose_destroy (compose_env_t *env) |
297 | { | 297 | { |
298 | mu_header_destroy (&env->header); | 298 | mu_header_destroy (&env->header); |
299 | free (env->outfiles); | 299 | free (env->outfiles); |
300 | } | 300 | } |
301 | 301 | ||
302 | /* FIXME: Can we use mu_stream_t instead of FILE? If so, | ||
303 | replace the loop with a call to mu_stream_copy. */ | ||
302 | static int | 304 | static int |
303 | fill_body (mu_message_t msg, FILE *file) | 305 | fill_body (mu_message_t msg, FILE *file) |
304 | { | 306 | { |
305 | mu_body_t body = NULL; | 307 | mu_body_t body = NULL; |
306 | mu_stream_t stream = NULL; | 308 | mu_stream_t stream = NULL; |
307 | off_t offset = 0; | ||
308 | char *buf = NULL; | 309 | char *buf = NULL; |
309 | size_t n = 0; | 310 | size_t n = 0; |
310 | mu_message_get_body (msg, &body); | 311 | mu_message_get_body (msg, &body); |
311 | mu_body_get_stream (body, &stream); | 312 | mu_body_get_streamref (body, &stream); |
313 | int nullbody = 1; | ||
312 | 314 | ||
313 | mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | ||
314 | offset = 0; | ||
315 | while (getline (&buf, &n, file) >= 0) | 315 | while (getline (&buf, &n, file) >= 0) |
316 | { | 316 | { |
317 | size_t len = strlen (buf); | 317 | size_t len = strlen (buf); |
318 | if (len) | ||
319 | nullbody = 0; | ||
318 | mu_stream_write (stream, buf, len, NULL); | 320 | mu_stream_write (stream, buf, len, NULL); |
319 | offset += len; | ||
320 | } | 321 | } |
321 | 322 | mu_stream_destroy (&stream); | |
322 | if (buf) | 323 | if (buf) |
323 | free (buf); | 324 | free (buf); |
324 | 325 | ||
325 | if (offset == 0) | 326 | if (nullbody) |
326 | { | 327 | { |
327 | if (mailvar_get (NULL, "nullbody", mailvar_type_boolean, 0) == 0) | 328 | if (mailvar_get (NULL, "nullbody", mailvar_type_boolean, 0) == 0) |
328 | { | 329 | { |
... | @@ -525,7 +526,6 @@ mail_send0 (compose_env_t * env, int save_to) | ... | @@ -525,7 +526,6 @@ mail_send0 (compose_env_t * env, int save_to) |
525 | int rc; | 526 | int rc; |
526 | 527 | ||
527 | mu_message_create (&msg, NULL); | 528 | mu_message_create (&msg, NULL); |
528 | mu_message_set_header (msg, env->header, NULL); | ||
529 | 529 | ||
530 | /* Fill the body. */ | 530 | /* Fill the body. */ |
531 | rc = fill_body (msg, file); | 531 | rc = fill_body (msg, file); |
... | @@ -599,6 +599,8 @@ mail_send0 (compose_env_t * env, int save_to) | ... | @@ -599,6 +599,8 @@ mail_send0 (compose_env_t * env, int save_to) |
599 | if (mailvar_get (&sendmail, "sendmail", | 599 | if (mailvar_get (&sendmail, "sendmail", |
600 | mailvar_type_string, 0) == 0) | 600 | mailvar_type_string, 0) == 0) |
601 | { | 601 | { |
602 | mu_message_set_header (msg, env->header, NULL); | ||
603 | env->header = NULL; | ||
602 | if (sendmail[0] == '/') | 604 | if (sendmail[0] == '/') |
603 | msg_to_pipe (sendmail, msg); | 605 | msg_to_pipe (sendmail, msg); |
604 | else | 606 | else |
... | @@ -669,14 +671,15 @@ msg_to_pipe (const char *cmd, mu_message_t msg) | ... | @@ -669,14 +671,15 @@ msg_to_pipe (const char *cmd, mu_message_t msg) |
669 | mu_stream_t stream = NULL; | 671 | mu_stream_t stream = NULL; |
670 | char buffer[512]; | 672 | char buffer[512]; |
671 | size_t n = 0; | 673 | size_t n = 0; |
672 | mu_message_get_stream (msg, &stream); | 674 | /* FIXME: Use mu_stream_copy */ |
673 | mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | 675 | mu_message_get_streamref (msg, &stream); |
674 | while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0 | 676 | while (mu_stream_read (stream, buffer, sizeof buffer - 1, &n) == 0 |
675 | && n != 0) | 677 | && n != 0) |
676 | { | 678 | { |
677 | buffer[n] = '\0'; | 679 | buffer[n] = '\0'; |
678 | fprintf (fp, "%s", buffer); | 680 | fprintf (fp, "%s", buffer); |
679 | } | 681 | } |
682 | mu_stream_destroy (&stream); | ||
680 | pclose (fp); | 683 | pclose (fp); |
681 | } | 684 | } |
682 | else | 685 | else | ... | ... |
... | @@ -35,8 +35,8 @@ top0 (msgset_t *mspec, mu_message_t msg, void *data) | ... | @@ -35,8 +35,8 @@ top0 (msgset_t *mspec, mu_message_t msg, void *data) |
35 | || lines < 0) | 35 | || lines < 0) |
36 | return 1; | 36 | return 1; |
37 | 37 | ||
38 | mu_message_get_stream (msg, &stream); | 38 | /* FIXME: Use mu_stream_copy */ |
39 | mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | 39 | mu_message_get_streamref (msg, &stream); |
40 | for (; lines > 0; lines--) | 40 | for (; lines > 0; lines--) |
41 | { | 41 | { |
42 | int status = mu_stream_readline (stream, buf, sizeof (buf), &n); | 42 | int status = mu_stream_readline (stream, buf, sizeof (buf), &n); |
... | @@ -44,6 +44,7 @@ top0 (msgset_t *mspec, mu_message_t msg, void *data) | ... | @@ -44,6 +44,7 @@ top0 (msgset_t *mspec, mu_message_t msg, void *data) |
44 | break; | 44 | break; |
45 | fprintf (ofile, "%s", buf); | 45 | fprintf (ofile, "%s", buf); |
46 | } | 46 | } |
47 | mu_stream_destroy (&stream); | ||
47 | set_cursor (mspec->msg_part[0]); | 48 | set_cursor (mspec->msg_part[0]); |
48 | 49 | ||
49 | util_mark_read (msg); | 50 | util_mark_read (msg); | ... | ... |
... | @@ -98,8 +98,8 @@ mail_write (int argc, char **argv) | ... | @@ -98,8 +98,8 @@ mail_write (int argc, char **argv) |
98 | mu_body_lines (bod, &size); | 98 | mu_body_lines (bod, &size); |
99 | total_lines += size; | 99 | total_lines += size; |
100 | 100 | ||
101 | mu_body_get_stream (bod, &stream); | 101 | /* FIXME: Use mu_stream_copy */ |
102 | mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | 102 | mu_body_get_streamref (bod, &stream); |
103 | /* should there be a separator? */ | 103 | /* should there be a separator? */ |
104 | while (mu_stream_read (stream, buffer, sizeof (buffer) - 1, &n) == 0 | 104 | while (mu_stream_read (stream, buffer, sizeof (buffer) - 1, &n) == 0 |
105 | && n != 0) | 105 | && n != 0) |
... | @@ -107,6 +107,7 @@ mail_write (int argc, char **argv) | ... | @@ -107,6 +107,7 @@ mail_write (int argc, char **argv) |
107 | buffer[n] = '\0'; | 107 | buffer[n] = '\0'; |
108 | fprintf (output, "%s", buffer); | 108 | fprintf (output, "%s", buffer); |
109 | } | 109 | } |
110 | mu_stream_destroy (&stream); | ||
110 | 111 | ||
111 | /* mark as saved. */ | 112 | /* mark as saved. */ |
112 | 113 | ... | ... |
... | @@ -285,7 +285,7 @@ _body_seek (mu_stream_t stream, mu_off_t off, int whence, mu_off_t *presult) | ... | @@ -285,7 +285,7 @@ _body_seek (mu_stream_t stream, mu_off_t off, int whence, mu_off_t *presult) |
285 | { | 285 | { |
286 | struct _mu_body_stream *str = (struct _mu_body_stream*) stream; | 286 | struct _mu_body_stream *str = (struct _mu_body_stream*) stream; |
287 | mu_body_t body = str->body; | 287 | mu_body_t body = str->body; |
288 | return mu_stream_seek (body->stream, off, whence, presult); | 288 | return mu_stream_seek (body->fstream, off, whence, presult); |
289 | } | 289 | } |
290 | 290 | ||
291 | static const char * | 291 | static const char * | ... | ... |
... | @@ -221,6 +221,15 @@ fd_wait (mu_stream_t stream, int *pflags, struct timeval *tvp) | ... | @@ -221,6 +221,15 @@ fd_wait (mu_stream_t stream, int *pflags, struct timeval *tvp) |
221 | } | 221 | } |
222 | 222 | ||
223 | int | 223 | int |
224 | fd_truncate (mu_stream_t stream, mu_off_t size) | ||
225 | { | ||
226 | struct _mu_file_stream *fstr = (struct _mu_file_stream *) stream; | ||
227 | if (ftruncate (fstr->fd, size)) | ||
228 | return errno; | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | int | ||
224 | _mu_file_stream_create (mu_stream_t *pstream, size_t size, | 233 | _mu_file_stream_create (mu_stream_t *pstream, size_t size, |
225 | char *filename, int flags) | 234 | char *filename, int flags) |
226 | { | 235 | { |
... | @@ -239,6 +248,7 @@ _mu_file_stream_create (mu_stream_t *pstream, size_t size, | ... | @@ -239,6 +248,7 @@ _mu_file_stream_create (mu_stream_t *pstream, size_t size, |
239 | str->stream.size = fd_size; | 248 | str->stream.size = fd_size; |
240 | str->stream.ctl = fd_ioctl; | 249 | str->stream.ctl = fd_ioctl; |
241 | str->stream.wait = fd_wait; | 250 | str->stream.wait = fd_wait; |
251 | str->stream.truncate = fd_truncate; | ||
242 | str->stream.error_string = fd_error_string; | 252 | str->stream.error_string = fd_error_string; |
243 | 253 | ||
244 | str->filename = filename; | 254 | str->filename = filename; | ... | ... |
... | @@ -329,7 +329,7 @@ header_parse (mu_header_t header, const char *blurb, int len) | ... | @@ -329,7 +329,7 @@ header_parse (mu_header_t header, const char *blurb, int len) |
329 | *[ (' ' | '\t') field-value '\r' '\n' ] | 329 | *[ (' ' | '\t') field-value '\r' '\n' ] |
330 | */ | 330 | */ |
331 | /* First loop goes through the blurb */ | 331 | /* First loop goes through the blurb */ |
332 | for (header_start = blurb; ; header_start = ++header_end) | 332 | for (header_start = blurb; len > 0; header_start = ++header_end) |
333 | { | 333 | { |
334 | const char *fn, *fn_end, *fv, *fv_end; | 334 | const char *fn, *fn_end, *fv, *fv_end; |
335 | struct mu_hdrent *ent; | 335 | struct mu_hdrent *ent; |
... | @@ -340,7 +340,7 @@ header_parse (mu_header_t header, const char *blurb, int len) | ... | @@ -340,7 +340,7 @@ header_parse (mu_header_t header, const char *blurb, int len) |
340 | break; | 340 | break; |
341 | 341 | ||
342 | /* Second loop extract one header field. */ | 342 | /* Second loop extract one header field. */ |
343 | for (header_start2 = header_start; ;header_start2 = ++header_end) | 343 | for (header_start2 = header_start; len; header_start2 = ++header_end) |
344 | { | 344 | { |
345 | header_end = memchr (header_start2, '\n', len); | 345 | header_end = memchr (header_start2, '\n', len); |
346 | if (header_end == NULL) | 346 | if (header_end == NULL) |
... | @@ -348,21 +348,14 @@ header_parse (mu_header_t header, const char *blurb, int len) | ... | @@ -348,21 +348,14 @@ header_parse (mu_header_t header, const char *blurb, int len) |
348 | else | 348 | else |
349 | { | 349 | { |
350 | len -= (header_end - header_start2 + 1); | 350 | len -= (header_end - header_start2 + 1); |
351 | if (len < 0) | 351 | if (!len |
352 | { | 352 | || (header_end[1] != ' ' |
353 | header_end = NULL; | 353 | && header_end[1] != '\t')) |
354 | break; | ||
355 | } | ||
356 | if (header_end[1] != ' ' | ||
357 | && header_end[1] != '\t') | ||
358 | break; /* New header break the inner for. */ | 354 | break; /* New header break the inner for. */ |
359 | } | 355 | } |
360 | /* *header_end = ' '; smash LF ? NO */ | 356 | /* *header_end = ' '; smash LF ? NO */ |
361 | } | 357 | } |
362 | 358 | ||
363 | if (header_end == NULL) | ||
364 | break; /* FIXME: Bail out. */ | ||
365 | |||
366 | /* Now save the header in the data structure. */ | 359 | /* Now save the header in the data structure. */ |
367 | 360 | ||
368 | /* Treats unix "From " specially. FIXME: Should we? */ | 361 | /* Treats unix "From " specially. FIXME: Should we? */ |
... | @@ -956,9 +949,10 @@ header_seek (mu_stream_t str, mu_off_t off, int whence, mu_off_t *presult) | ... | @@ -956,9 +949,10 @@ header_seek (mu_stream_t str, mu_off_t off, int whence, mu_off_t *presult) |
956 | break; | 949 | break; |
957 | } | 950 | } |
958 | 951 | ||
959 | if (off < 0 || off >= hstr->hdr->size) | 952 | if (off < 0 || off > hstr->hdr->size) |
960 | return ESPIPE; | 953 | return ESPIPE; |
961 | hstr->off = off; | 954 | hstr->off = off; |
955 | *presult = off; | ||
962 | return 0; | 956 | return 0; |
963 | } | 957 | } |
964 | 958 | ... | ... |
... | @@ -270,21 +270,35 @@ _message_stream_create (mu_stream_t *pmsg, mu_message_t msg, int flags) | ... | @@ -270,21 +270,35 @@ _message_stream_create (mu_stream_t *pmsg, mu_message_t msg, int flags) |
270 | } | 270 | } |
271 | 271 | ||
272 | 272 | ||
273 | enum eoh_state | ||
274 | { | ||
275 | eoh_no, | ||
276 | eoh_maybe, | ||
277 | eoh_yes | ||
278 | }; | ||
279 | |||
273 | /* Message header stuff */ | 280 | /* Message header stuff */ |
274 | static int | 281 | static enum eoh_state |
275 | string_find_eoh (const char *str, size_t len, size_t *ppos) | 282 | string_find_eoh (enum eoh_state eoh, const char *str, size_t len, |
283 | size_t *ppos) | ||
276 | { | 284 | { |
277 | size_t pos; | 285 | size_t pos; |
278 | int eoh = 0; | ||
279 | 286 | ||
280 | for (pos = 0; pos < len-1; pos++) | 287 | if (eoh == eoh_maybe && *str == '\n') |
281 | if (str[pos] == '\n' && str[pos+1] == '\n') | ||
282 | { | 288 | { |
283 | eoh = 1; | 289 | *ppos = 0; |
284 | break; | 290 | return eoh_yes; |
291 | } | ||
292 | |||
293 | for (pos = 0; pos < len - 1; pos++) | ||
294 | if (str[pos] == '\n' && str[pos + 1] == '\n') | ||
295 | { | ||
296 | *ppos = pos + 1; | ||
297 | return eoh_yes; | ||
285 | } | 298 | } |
299 | |||
286 | *ppos = pos + 1; | 300 | *ppos = pos + 1; |
287 | return eoh; | 301 | return str[pos] == '\n' ? eoh_maybe : eoh_no; |
288 | } | 302 | } |
289 | 303 | ||
290 | #define MIN_HEADER_BUF_SIZE 2048 | 304 | #define MIN_HEADER_BUF_SIZE 2048 |
... | @@ -297,17 +311,21 @@ _header_fill (mu_stream_t stream, char **pbuf, size_t *plen) | ... | @@ -297,17 +311,21 @@ _header_fill (mu_stream_t stream, char **pbuf, size_t *plen) |
297 | size_t bufsize = 0; | 311 | size_t bufsize = 0; |
298 | char inbuf[MIN_HEADER_BUF_SIZE]; | 312 | char inbuf[MIN_HEADER_BUF_SIZE]; |
299 | size_t nread; | 313 | size_t nread; |
314 | enum eoh_state eoh = eoh_no; | ||
300 | 315 | ||
301 | status = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); | 316 | status = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL); |
302 | if (status) | 317 | if (status) |
303 | return status; | 318 | return status; |
304 | 319 | ||
305 | while ((status = mu_stream_read (stream, inbuf, sizeof (inbuf), &nread)) | 320 | while (eoh != eoh_yes |
306 | == 0 && nread) | 321 | && (status = mu_stream_read (stream, inbuf, sizeof (inbuf), &nread)) |
322 | == 0 | ||
323 | && nread) | ||
307 | { | 324 | { |
308 | char *nbuf; | 325 | char *nbuf; |
309 | size_t len; | 326 | size_t len; |
310 | int eoh = string_find_eoh (inbuf, nread, &len); | 327 | |
328 | eoh = string_find_eoh (eoh, inbuf, nread, &len); | ||
311 | 329 | ||
312 | nbuf = realloc (buffer, bufsize + len); | 330 | nbuf = realloc (buffer, bufsize + len); |
313 | if (!nbuf) | 331 | if (!nbuf) |
... | @@ -318,8 +336,6 @@ _header_fill (mu_stream_t stream, char **pbuf, size_t *plen) | ... | @@ -318,8 +336,6 @@ _header_fill (mu_stream_t stream, char **pbuf, size_t *plen) |
318 | memcpy (nbuf + bufsize, inbuf, len); | 336 | memcpy (nbuf + bufsize, inbuf, len); |
319 | buffer = nbuf; | 337 | buffer = nbuf; |
320 | bufsize += len; | 338 | bufsize += len; |
321 | if (eoh) | ||
322 | break; | ||
323 | } | 339 | } |
324 | 340 | ||
325 | if (status) | 341 | if (status) | ... | ... |
... | @@ -53,7 +53,7 @@ _stream_seterror (struct _mu_stream *stream, int code, int perm) | ... | @@ -53,7 +53,7 @@ _stream_seterror (struct _mu_stream *stream, int code, int perm) |
53 | #define _stream_cleareof(s) ((s)->flags &= ~_MU_STR_EOF) | 53 | #define _stream_cleareof(s) ((s)->flags &= ~_MU_STR_EOF) |
54 | #define _stream_advance_buffer(s,n) ((s)->cur += n, (s)->level -= n) | 54 | #define _stream_advance_buffer(s,n) ((s)->cur += n, (s)->level -= n) |
55 | #define _stream_buffer_offset(s) ((s)->cur - (s)->buffer) | 55 | #define _stream_buffer_offset(s) ((s)->cur - (s)->buffer) |
56 | #define _stream_orig_level(s) ((s)->level + _stream_buffer_offset(s)) | 56 | #define _stream_orig_level(s) ((s)->level + _stream_buffer_offset (s)) |
57 | 57 | ||
58 | static int | 58 | static int |
59 | _stream_fill_buffer (struct _mu_stream *stream) | 59 | _stream_fill_buffer (struct _mu_stream *stream) |
... | @@ -202,6 +202,7 @@ mu_stream_destroy (mu_stream_t *pstream) | ... | @@ -202,6 +202,7 @@ mu_stream_destroy (mu_stream_t *pstream) |
202 | mu_stream_t str = *pstream; | 202 | mu_stream_t str = *pstream; |
203 | if (str && (str->ref_count == 0 || --str->ref_count == 0)) | 203 | if (str && (str->ref_count == 0 || --str->ref_count == 0)) |
204 | { | 204 | { |
205 | mu_stream_close (str); | ||
205 | if (str->done) | 206 | if (str->done) |
206 | str->done (str); | 207 | str->done (str); |
207 | free (str); | 208 | free (str); |
... | @@ -213,7 +214,7 @@ mu_stream_destroy (mu_stream_t *pstream) | ... | @@ -213,7 +214,7 @@ mu_stream_destroy (mu_stream_t *pstream) |
213 | void | 214 | void |
214 | mu_stream_get_flags (mu_stream_t str, int *pflags) | 215 | mu_stream_get_flags (mu_stream_t str, int *pflags) |
215 | { | 216 | { |
216 | *pflags = str->flags; | 217 | *pflags = str->flags & ~_MU_STR_INTERN_MASK; |
217 | } | 218 | } |
218 | 219 | ||
219 | void | 220 | void |
... | @@ -252,6 +253,12 @@ mu_stream_strerror (mu_stream_t stream, int rc) | ... | @@ -252,6 +253,12 @@ mu_stream_strerror (mu_stream_t stream, int rc) |
252 | } | 253 | } |
253 | 254 | ||
254 | int | 255 | int |
256 | mu_stream_err (mu_stream_t stream) | ||
257 | { | ||
258 | return stream->flags & _MU_STR_ERR; | ||
259 | } | ||
260 | |||
261 | int | ||
255 | mu_stream_last_error (mu_stream_t stream) | 262 | mu_stream_last_error (mu_stream_t stream) |
256 | { | 263 | { |
257 | return stream->last_err; | 264 | return stream->last_err; |
... | @@ -700,6 +707,9 @@ mu_stream_close (mu_stream_t stream) | ... | @@ -700,6 +707,9 @@ mu_stream_close (mu_stream_t stream) |
700 | if (!stream) | 707 | if (!stream) |
701 | return EINVAL; | 708 | return EINVAL; |
702 | mu_stream_flush (stream); | 709 | mu_stream_flush (stream); |
710 | /* Do close the stream only if it is not used by anyone else */ | ||
711 | if (stream->ref_count > 1) | ||
712 | return 0; | ||
703 | if (stream->close) | 713 | if (stream->close) |
704 | rc = stream->close (stream); | 714 | rc = stream->close (stream); |
705 | return rc; | 715 | return rc; |
... | @@ -785,7 +795,7 @@ mu_stream_set_flags (mu_stream_t stream, int fl) | ... | @@ -785,7 +795,7 @@ mu_stream_set_flags (mu_stream_t stream, int fl) |
785 | { | 795 | { |
786 | if (stream == NULL) | 796 | if (stream == NULL) |
787 | return EINVAL; | 797 | return EINVAL; |
788 | stream->flags |= fl; | 798 | stream->flags |= (fl & ~_MU_STR_INTERN_MASK); |
789 | return 0; | 799 | return 0; |
790 | } | 800 | } |
791 | 801 | ||
... | @@ -794,7 +804,7 @@ mu_stream_clr_flags (mu_stream_t stream, int fl) | ... | @@ -794,7 +804,7 @@ mu_stream_clr_flags (mu_stream_t stream, int fl) |
794 | { | 804 | { |
795 | if (stream == NULL) | 805 | if (stream == NULL) |
796 | return EINVAL; | 806 | return EINVAL; |
797 | stream->flags &= ~fl; | 807 | stream->flags &= ~(fl & ~_MU_STR_INTERN_MASK); |
798 | return 0; | 808 | return 0; |
799 | } | 809 | } |
800 | 810 | ... | ... |
... | @@ -62,7 +62,7 @@ _streamref_read (struct _mu_stream *str, char *buf, size_t bufsize, | ... | @@ -62,7 +62,7 @@ _streamref_read (struct _mu_stream *str, char *buf, size_t bufsize, |
62 | else if (rc == ESPIPE) | 62 | else if (rc == ESPIPE) |
63 | { | 63 | { |
64 | *pnread = 0; | 64 | *pnread = 0; |
65 | str->flags |= _MU_STR_EOF; | 65 | mu_stream_clearerr (sp->transport); |
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
68 | return streamref_return (sp, rc); | 68 | return streamref_return (sp, rc); |
... | @@ -170,7 +170,21 @@ static int | ... | @@ -170,7 +170,21 @@ static int |
170 | _streamref_size (struct _mu_stream *str, mu_off_t *psize) | 170 | _streamref_size (struct _mu_stream *str, mu_off_t *psize) |
171 | { | 171 | { |
172 | struct _mu_streamref *sp = (struct _mu_streamref *)str; | 172 | struct _mu_streamref *sp = (struct _mu_streamref *)str; |
173 | return streamref_return (sp, mu_stream_size (sp->transport, psize)); | 173 | mu_off_t size; |
174 | int rc = 0; | ||
175 | |||
176 | if (sp->end) | ||
177 | size = sp->end - sp->start + 1; | ||
178 | else | ||
179 | { | ||
180 | rc = mu_stream_size (sp->transport, &size); | ||
181 | if (rc) | ||
182 | return streamref_return (sp, rc); | ||
183 | size -= sp->start; | ||
184 | } | ||
185 | if (rc == 0) | ||
186 | *psize = size; | ||
187 | return rc; | ||
174 | } | 188 | } |
175 | 189 | ||
176 | static int | 190 | static int |
... | @@ -240,12 +254,11 @@ mu_streamref_create_abridged (mu_stream_t *pref, mu_stream_t str, | ... | @@ -240,12 +254,11 @@ mu_streamref_create_abridged (mu_stream_t *pref, mu_stream_t str, |
240 | int flags; | 254 | int flags; |
241 | struct _mu_streamref *sp; | 255 | struct _mu_streamref *sp; |
242 | 256 | ||
243 | rc = mu_stream_seek (str, 0, MU_SEEK_CUR, &off); | 257 | rc = mu_stream_seek (str, 0, MU_SEEK_SET, &off); |
244 | if (rc) | 258 | if (rc) |
245 | return rc; | 259 | return rc; |
246 | mu_stream_get_flags (str, &flags); | 260 | mu_stream_get_flags (str, &flags); |
247 | sp = (struct _mu_streamref *) _mu_stream_create (sizeof (*sp), | 261 | sp = (struct _mu_streamref *) _mu_stream_create (sizeof (*sp), flags); |
248 | flags | MU_STREAM_NO_CLOSE); | ||
249 | if (!sp) | 262 | if (!sp) |
250 | return ENOMEM; | 263 | return ENOMEM; |
251 | mu_stream_ref (str); | 264 | mu_stream_ref (str); | ... | ... |
-
Please register or sign in to post a comment