]> git.llucax.com Git - software/mutt-debian.git/blob - editmsg.c
fix index weirdness if mailbox is emptied while inside the pager (Closes: 375530)
[software/mutt-debian.git] / editmsg.c
1 /*
2  * Copyright (C) 1999-2002 Thomas Roessler <roessler@does-not-exist.org>
3  * 
4  *     This program is free software; you can redistribute it
5  *     and/or modify it under the terms of the GNU General Public
6  *     License as published by the Free Software Foundation; either
7  *     version 2 of the License, or (at your option) any later
8  *     version.
9  * 
10  *     This program is distributed in the hope that it will be
11  *     useful, but WITHOUT ANY WARRANTY; without even the implied
12  *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13  *     PURPOSE.  See the GNU General Public License for more
14  *     details.
15  * 
16  *     You should have received a copy of the GNU General Public
17  *     License along with this program; if not, write to the Free
18  *     Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *     Boston, MA  02110-1301, USA.
20  */ 
21
22 /* simple, editor-based message editing */
23
24 #if HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include "mutt.h"
29 #include "copy.h"
30 #include "mailbox.h"
31 #include "mx.h"
32
33 #include <sys/stat.h>
34 #include <errno.h>
35
36 #include <time.h>
37
38 /*
39  * return value:
40  * 
41  * 1    message not modified
42  * 0    message edited successfully
43  * -1   error
44  */
45
46 static int edit_one_message (CONTEXT *ctx, HEADER *cur)
47 {
48   char tmp[_POSIX_PATH_MAX];
49   char buff[STRING];
50   int omagic;
51   int oerrno;
52   int rc;
53
54   unsigned short o_read;
55   unsigned short o_old;
56
57   int of, cf;
58   
59   CONTEXT tmpctx;
60   MESSAGE *msg;
61
62   FILE *fp = NULL;
63
64   struct stat sb;
65   time_t mtime = 0;
66   
67   mutt_mktemp (tmp);
68
69   omagic = DefaultMagic;
70   DefaultMagic = M_MBOX;
71
72   rc = (mx_open_mailbox (tmp, M_NEWFOLDER, &tmpctx) == NULL) ? -1 : 0;
73
74   DefaultMagic = omagic;
75
76   if (rc == -1)
77   {
78     mutt_error (_("could not create temporary folder: %s"), strerror (errno));
79     return -1;
80   }
81
82   rc = mutt_append_message (&tmpctx, ctx, cur, 0, CH_NOLEN |
83         ((ctx->magic == M_MBOX || ctx->magic == M_MMDF) ? 0 : CH_NOSTATUS));
84   oerrno = errno;
85
86   mx_close_mailbox (&tmpctx, NULL);
87
88   if (rc == -1)
89   {
90     mutt_error (_("could not write temporary mail folder: %s"), strerror (oerrno));
91     goto bail;
92   }
93
94   if ((rc = stat (tmp, &sb)) == -1)
95   {
96     mutt_error (_("Can't stat %s: %s"), tmp, strerror (errno));
97     goto bail;
98   }
99
100   /*
101    * 2002-09-05 me@sigpipe.org
102    * The file the user is going to edit is not a real mbox, so we need to
103    * truncate the last newline in the temp file, which is logically part of
104    * the message separator, and not the body of the message.  If we fail to
105    * remove it, the message will grow by one line each time the user edits
106    * the message.
107    */
108   if (sb.st_size != 0 && truncate (tmp, sb.st_size - 1) == -1)
109   {
110     mutt_error (_("could not truncate temporary mail folder: %s"),
111                 strerror (errno));
112     goto bail;
113   }
114
115   mtime = mutt_decrease_mtime (tmp, &sb);
116
117   mutt_edit_file (NONULL(Editor), tmp);
118
119   if ((rc = stat (tmp, &sb)) == -1)
120   {
121     mutt_error (_("Can't stat %s: %s"), tmp, strerror (errno));
122     goto bail;
123   }
124   
125   if (sb.st_size == 0)
126   {
127     mutt_message (_("Message file is empty!"));
128     rc = 1;
129     goto bail;
130   }
131
132   if (sb.st_mtime == mtime)
133   {
134     mutt_message (_("Message not modified!"));
135     rc = 1;
136     goto bail;
137   }
138
139   if ((fp = fopen (tmp, "r")) == NULL)
140   {
141     rc = -1;
142     mutt_error (_("Can't open message file: %s"), strerror (errno));
143     goto bail;
144   }
145
146   if (mx_open_mailbox (ctx->path, M_APPEND, &tmpctx) == NULL)
147   {
148     rc = -1;
149     mutt_error (_("Can't append to folder: %s"), strerror (errno));
150     goto bail;
151   }
152
153   of = 0;
154   cf = ((tmpctx.magic == M_MBOX || tmpctx.magic == M_MMDF) ? 0 : CH_NOSTATUS);
155   
156   if (fgets (buff, sizeof (buff), fp) && is_from (buff, NULL, 0, NULL))
157   {
158     if (tmpctx.magic == M_MBOX || tmpctx.magic == M_MMDF)
159       cf = CH_FROM | CH_FORCE_FROM;
160   }
161   else
162     of = M_ADD_FROM;
163
164   /* 
165    * XXX - we have to play games with the message flags to avoid
166    * problematic behaviour with maildir folders.
167    *
168    */
169
170   o_read = cur->read; o_old = cur->old;
171   cur->read = cur->old = 0;
172   msg = mx_open_new_message (&tmpctx, cur, of);
173   cur->read = o_read; cur->old = o_old;
174
175   if (msg == NULL)
176   {
177     mutt_error (_("Can't append to folder: %s"), strerror (errno));
178     mx_close_mailbox (&tmpctx, NULL);
179     goto bail;
180   }
181
182   if ((rc = mutt_copy_hdr (fp, msg->fp, 0, sb.st_size, CH_NOLEN | cf, NULL)) == 0)
183   {
184     fputc ('\n', msg->fp);
185     rc = mutt_copy_stream (fp, msg->fp);
186   }
187
188   rc = mx_commit_message (msg, &tmpctx);
189   mx_close_message (&msg);
190   
191   mx_close_mailbox (&tmpctx, NULL);
192   
193   bail:
194   if (fp) fclose (fp);
195
196   if (rc >= 0)
197     unlink (tmp);
198
199   if (rc == 0)
200   {
201     mutt_set_flag (Context, cur, M_DELETE, 1);
202     mutt_set_flag (Context, cur, M_READ, 1);
203
204     if (option (OPTDELETEUNTAG))
205       mutt_set_flag (Context, cur, M_TAG, 0);
206   }
207   else if (rc == -1)
208     mutt_message (_("Error. Preserving temporary file: %s"), tmp);
209
210     
211   return rc;
212 }
213
214 int mutt_edit_message (CONTEXT *ctx, HEADER *hdr)
215 {
216   int i, j;
217
218   if (hdr)
219     return edit_one_message (ctx, hdr);
220
221   
222   for (i = 0; i < ctx->vcount; i++)
223   {
224     j = ctx->v2r[i];
225     if (ctx->hdrs[j]->tagged)
226     {
227       if (edit_one_message (ctx, ctx->hdrs[j]) == -1)
228         return -1;
229     }
230   }
231
232   return 0;
233 }