Commit 0c013ac5 0c013ac57ef780d2d6f2a9b389b1c754b5c29033 by Sergey Poznyakoff

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.
1 parent f900b3b0
...@@ -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);
......