1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: init.c 101 2006-08-10 22:53:04Z mikes@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2015 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 /*======================================================================
22 Session initiation support routines
29 #include "../pith/init.h"
30 #include "../pith/conf.h"
31 #include "../pith/status.h"
32 #include "../pith/folder.h"
33 #include "../pith/context.h"
38 /* these are used to report folder directory creation problems */
39 CONF_TXT_T init_md_exists
[] = "The \"%s\" subdirectory already exists, but it is not writable by Alpine so Alpine cannot run. Please correct the permissions and restart Alpine.";
41 CONF_TXT_T init_md_file
[] = "Alpine requires a directory called \"%s\" and usualy creates it. You already have a regular file by that name which means Alpine cannot create the directory. Please move or remove it and start Alpine again.";
43 CONF_TXT_T init_md_create
[] = "Creating subdirectory \"%s\" where Alpine will store its mail folders.";
49 void display_init_err(char *, int);
50 char *context_string(char *);
51 int prune_folders(CONTEXT_S
*, char *, int, char *, unsigned);
52 int prune_move_folder(char *, char *, CONTEXT_S
*);
53 void delete_old_mail(struct sm_folder
*, CONTEXT_S
*, char *);
57 /*----------------------------------------------------------------------
58 Make sure the alpine folders directory exists, with proper folders
60 Args: ps -- alpine structure to get mail directory and contexts from
62 Result: returns 0 if it exists or it is created and all is well
63 1 if it is missing and can't be created.
66 init_mail_dir(struct pine
*ps
)
69 /* MAIL_LIST: can we use imap4 CREATE? */
71 * We don't really care if mail_dir exists if it isn't
72 * part of the first folder collection specified. If this
73 * is the case, it must have been created external to us, so
76 if(ps
->VAR_FOLDER_SPEC
&& ps
->VAR_FOLDER_SPEC
[0]){
77 char *p
= context_string(ps
->VAR_FOLDER_SPEC
[0]);
78 int rv
= strncmp(p
, ps
->VAR_MAIL_DIRECTORY
,
79 strlen(ps
->VAR_MAIL_DIRECTORY
));
85 switch(is_writable_dir(ps
->folders_dir
)){
87 /* --- all is well --- */
91 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, init_md_exists
, ps
->folders_dir
);
92 display_init_err(tmp_20k_buf
, 1);
96 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, init_md_file
, ps
->folders_dir
);
97 display_init_err(tmp_20k_buf
, 1);
101 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, init_md_create
, ps
->folders_dir
);
102 display_init_err(tmp_20k_buf
, 0);
106 if(create_mail_dir(ps
->folders_dir
) < 0){
107 snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "Error creating subdirectory \"%s\" : %s",
108 ps
->folders_dir
, error_description(errno
));
109 display_init_err(tmp_20k_buf
, 1);
118 /*----------------------------------------------------------------------
119 Make sure the default save folders exist in the default
123 display_init_err(char *s
, int err
)
126 mswin_messagebox(s
, err
);
134 if(++n
> 60 && isspace((unsigned char)*s
)){
137 while(*(s
+1) && isspace((unsigned char)*(s
+1)))
149 * Return malloc'd string containing only the context specifier given
150 * a string containing the raw pinerc entry
153 context_string(char *s
)
155 CONTEXT_S
*t
= new_context(s
, NULL
);
160 * Take what we want from context, then free the rest...
163 t
->context
= NULL
; /* don't free it! */
167 return(rv
? rv
: cpystr(""));
172 /*----------------------------------------------------------------------
173 Rename the current sent-mail folder to sent-mail for last month
175 open up sent-mail and get date of very first message
176 if date is last month rename and...
177 if files from 3 months ago exist ask if they should be deleted and...
178 if files from previous months and yes ask about them, too.
179 ----------------------------------------------------------------------*/
181 expire_sent_mail(void)
183 int cur_month
, ok
= 1;
187 CONTEXT_S
*prune_cntxt
;
189 dprint((5, "==== expire_mail called ====\n"));
191 if(!check_prune_time(&now
, &tm_now
))
194 cur_month
= (1900 + tm_now
->tm_year
) * 12 + tm_now
->tm_mon
;
195 dprint((5, "Current month %d\n", cur_month
));
198 * locate the default save context...
200 if(!(prune_cntxt
= default_save_context(ps_global
->context_list
)))
201 prune_cntxt
= ps_global
->context_list
;
204 * Since fcc's and read-mail can be an IMAP mailbox, be sure to only
205 * try expiring a list if it's an ambiguous name associated with some
208 * If sentmail set outside a context, then pruning is up to the
212 if(ps_global
->VAR_DEFAULT_FCC
&& *ps_global
->VAR_DEFAULT_FCC
213 && context_isambig(ps_global
->VAR_DEFAULT_FCC
))
214 ok
= prune_folders(prune_cntxt
, ps_global
->VAR_DEFAULT_FCC
,
216 ps_global
->pruning_rule
);
218 if(ok
&& ps_global
->VAR_READ_MESSAGE_FOLDER
219 && *ps_global
->VAR_READ_MESSAGE_FOLDER
220 && context_isambig(ps_global
->VAR_READ_MESSAGE_FOLDER
))
221 ok
= prune_folders(prune_cntxt
, ps_global
->VAR_READ_MESSAGE_FOLDER
,
223 ps_global
->pruning_rule
);
227 * Within the default prune context,
228 * prune back the folders with the given name
230 if(ok
&& prune_cntxt
&& (p
= ps_global
->VAR_PRUNED_FOLDERS
))
232 if(**p
&& context_isambig(*p
))
233 ok
= prune_folders(prune_cntxt
, *p
, cur_month
, "",
234 ps_global
->pruning_rule
);
237 * Mark that we're done for this month...
240 ps_global
->last_expire_year
= tm_now
->tm_year
;
241 ps_global
->last_expire_month
= tm_now
->tm_mon
;
242 snprintf(tmp
, sizeof(tmp
), "%d.%d", ps_global
->last_expire_year
,
243 ps_global
->last_expire_month
+ 1);
244 set_variable(V_LAST_TIME_PRUNE_QUESTION
, tmp
, 1, 1, Main
);
251 /*----------------------------------------------------------------------
252 Offer to delete old sent-mail folders
254 Args: sml -- The list of sent-mail folders
258 prune_folders(CONTEXT_S
*prune_cntxt
, char *folder_base
, int cur_month
,
259 char *type
, unsigned int pr
)
261 char path2
[MAXPATH
+1], prompt
[128], tmp
[21];
262 int month_to_use
, exists
;
263 struct sm_folder
*mail_list
, *sm
;
265 mail_list
= get_mail_list(prune_cntxt
, folder_base
);
266 free_folder_list(prune_cntxt
);
269 for(sm
= mail_list
; sm
!= NULL
&& sm
->name
!= NULL
; sm
++)
270 dprint((5,"Old sent-mail: %5d %s\n", sm
->month_num
,
271 sm
->name
[0] ? sm
->name
: "?"));
274 for(sm
= mail_list
; sm
!= NULL
&& sm
->name
!= NULL
; sm
++)
275 if(sm
->month_num
== cur_month
- 1)
276 break; /* matched a month */
278 month_to_use
= (sm
== NULL
|| sm
->name
== NULL
) ? cur_month
- 1 : 0;
280 dprint((5, "Month_to_use : %d\n", month_to_use
));
282 if(month_to_use
== 0 || pr
== PRUNE_NO_AND_ASK
|| pr
== PRUNE_NO_AND_NO
)
285 strncpy(path2
, folder_base
, sizeof(path2
)-1);
286 path2
[sizeof(path2
)-1] = '\0';
288 if(F_ON(F_PRUNE_USES_ISO
,ps_global
)){ /* sent-mail-yyyy-mm */
289 snprintf(path2
+ strlen(path2
), sizeof(path2
)-strlen(path2
), "-%4.4d-%2.2d", month_to_use
/12,
290 month_to_use
% 12 + 1);
293 strncpy(tmp
, month_abbrev((month_to_use
% 12)+1), 20);
294 tmp
[sizeof(tmp
)-1] = '\0';
295 lcase((unsigned char *) tmp
);
297 if(*prune_cntxt
->context
!= '{'){
301 snprintf(path2
+ (size_t)((i
> 4) ? 4 : i
),
302 sizeof(path2
)- ((i
> 4) ? 4 : i
),
303 "%2.2d%2.2d", (month_to_use
% 12) + 1,
304 ((month_to_use
/ 12) - 1900) % 100);
308 snprintf(path2
+ strlen(path2
), sizeof(path2
)-strlen(path2
), "-%.20s-%d", tmp
, month_to_use
/12);
312 snprintf(prompt
, sizeof(prompt
), "Move current \"%.50s\" to \"%.50s\"", folder_base
, path2
);
313 if((exists
= folder_exists(prune_cntxt
, folder_base
)) == FEX_ERROR
){
314 dprint((5, "prune_folders: Error testing existence\n"));
317 else if(exists
== FEX_NOENT
){ /* doesn't exist */
318 dprint((5, "prune_folders: nothing to prune <%s %s>\n",
319 prune_cntxt
->context
? prune_cntxt
->context
: "?",
320 folder_base
? folder_base
: "?"));
323 else if(!(exists
& FEX_ISFILE
)
324 || pr
== PRUNE_NO_AND_ASK
|| pr
== PRUNE_NO_AND_NO
325 || ((pr
== PRUNE_ASK_AND_ASK
|| pr
== PRUNE_ASK_AND_NO
) &&
326 want_to(prompt
, 'n', 0, h_wt_expire
, WT_FLUSH_IN
) == 'n')){
327 dprint((5, "User declines renaming %s\n",
328 ps_global
->VAR_DEFAULT_FCC
? ps_global
->VAR_DEFAULT_FCC
: "?"));
332 prune_move_folder(folder_base
, path2
, prune_cntxt
);
335 if(pr
== PRUNE_ASK_AND_ASK
|| pr
== PRUNE_YES_AND_ASK
336 || pr
== PRUNE_NO_AND_ASK
)
337 delete_old_mail(mail_list
, prune_cntxt
, type
);
339 if((sm
= mail_list
) != NULL
){
341 fs_give((void **)&(sm
->name
));
345 fs_give((void **)&mail_list
);
352 /*----------------------------------------------------------------------
353 Offer to delete old sent-mail folders
355 Args: sml -- The list of sent-mail folders
356 fcc_cntxt -- context to delete list of folders in
357 type -- label indicating type of folders being deleted
361 delete_old_mail(struct sm_folder
*sml
, CONTEXT_S
*fcc_cntxt
, char *type
)
364 struct sm_folder
*sm
;
366 for(sm
= sml
; sm
!= NULL
&& sm
->name
!= NULL
; sm
++){
367 if(sm
->name
[0] == '\0') /* can't happen */
370 snprintf(prompt
, sizeof(prompt
),
371 "To save disk space, delete old%.10s mail folder \"%.30s\" ",
373 if(want_to(prompt
, 'n', 0, h_wt_delete_old
, WT_FLUSH_IN
) == 'y'){
375 if(!context_delete(fcc_cntxt
, NULL
, sm
->name
)){
376 q_status_message1(SM_ORDER
,
377 3, 3, "Error deleting \"%s\".", sm
->name
);
378 dprint((1, "Error context_deleting %s in %s\n", sm
->name
,
379 (fcc_cntxt
&& fcc_cntxt
->context
)
380 ? fcc_cntxt
->context
: "<null>"));
385 if((index
= folder_index(sm
->name
, fcc_cntxt
, FI_FOLDER
)) >= 0)
386 folder_delete(index
, FOLDERS(fcc_cntxt
));
389 /* break;*/ /* skip out of the whole thing when he says no */
390 /* Decided to keep asking anyway */