summaryrefslogtreecommitdiff
path: root/alpine/init.c
diff options
context:
space:
mode:
authorEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
committerEduardo Chappa <echappa@gmx.com>2013-02-03 00:59:38 -0700
commit094ca96844842928810f14844413109fc6cdd890 (patch)
treee60efbb980f38ba9308ccb4fb2b77b87bbc115f3 /alpine/init.c
downloadalpine-094ca96844842928810f14844413109fc6cdd890.tar.xz
Initial Alpine Version
Diffstat (limited to 'alpine/init.c')
-rw-r--r--alpine/init.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/alpine/init.c b/alpine/init.c
new file mode 100644
index 00000000..27c58cbf
--- /dev/null
+++ b/alpine/init.c
@@ -0,0 +1,396 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: init.c 101 2006-08-10 22:53:04Z mikes@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006-2007 University of Washington
+ * Copyright 2013 Eduardo Chappa
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+/*======================================================================
+ init.c
+
+ Session initiation support routines
+
+ ====*/
+
+
+#include "headers.h"
+
+#include "../pith/init.h"
+#include "../pith/conf.h"
+#include "../pith/status.h"
+#include "../pith/folder.h"
+#include "../pith/context.h"
+
+#include "init.h"
+
+
+/* these are used to report folder directory creation problems */
+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.";
+
+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.";
+
+CONF_TXT_T init_md_create[] = "Creating subdirectory \"%s\" where Alpine will store its mail folders.";
+
+
+/*
+ * Internal prototypes
+ */
+void display_init_err(char *, int);
+char *context_string(char *);
+int prune_folders(CONTEXT_S *, char *, int, char *, unsigned);
+int prune_move_folder(char *, char *, CONTEXT_S *);
+void delete_old_mail(struct sm_folder *, CONTEXT_S *, char *);
+
+
+
+/*----------------------------------------------------------------------
+ Make sure the alpine folders directory exists, with proper folders
+
+ Args: ps -- alpine structure to get mail directory and contexts from
+
+ Result: returns 0 if it exists or it is created and all is well
+ 1 if it is missing and can't be created.
+ ----*/
+int
+init_mail_dir(struct pine *ps)
+{
+
+/* MAIL_LIST: can we use imap4 CREATE? */
+ /*
+ * We don't really care if mail_dir exists if it isn't
+ * part of the first folder collection specified. If this
+ * is the case, it must have been created external to us, so
+ * just move one...
+ */
+ if(ps->VAR_FOLDER_SPEC && ps->VAR_FOLDER_SPEC[0]){
+ char *p = context_string(ps->VAR_FOLDER_SPEC[0]);
+ int rv = strncmp(p, ps->VAR_MAIL_DIRECTORY,
+ strlen(ps->VAR_MAIL_DIRECTORY));
+ fs_give((void **)&p);
+ if(rv)
+ return(0);
+ }
+
+ switch(is_writable_dir(ps->folders_dir)){
+ case 0:
+ /* --- all is well --- */
+ return(0);
+
+ case 1:
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, init_md_exists, ps->folders_dir);
+ display_init_err(tmp_20k_buf, 1);
+ return(-1);
+
+ case 2:
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, init_md_file, ps->folders_dir);
+ display_init_err(tmp_20k_buf, 1);
+ return(-1);
+
+ case 3:
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, init_md_create, ps->folders_dir);
+ display_init_err(tmp_20k_buf, 0);
+#ifndef _WINDOWS
+ sleep(4);
+#endif
+ if(create_mail_dir(ps->folders_dir) < 0){
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Error creating subdirectory \"%s\" : %s",
+ ps->folders_dir, error_description(errno));
+ display_init_err(tmp_20k_buf, 1);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+
+/*----------------------------------------------------------------------
+ Make sure the default save folders exist in the default
+ save context.
+ ----*/
+void
+display_init_err(char *s, int err)
+{
+#ifdef _WINDOWS
+ mswin_messagebox(s, err);
+#else
+ int n = 0;
+
+ if(err)
+ fputc(BELL, stdout);
+
+ for(; *s; s++)
+ if(++n > 60 && isspace((unsigned char)*s)){
+ n = 0;
+ fputc('\n', stdout);
+ while(*(s+1) && isspace((unsigned char)*(s+1)))
+ s++;
+ }
+ else
+ fputc(*s, stdout);
+
+ fputc('\n', stdout);
+#endif
+}
+
+
+/*
+ * Return malloc'd string containing only the context specifier given
+ * a string containing the raw pinerc entry
+ */
+char *
+context_string(char *s)
+{
+ CONTEXT_S *t = new_context(s, NULL);
+ char *rv = NULL;
+
+ if(t){
+ /*
+ * Take what we want from context, then free the rest...
+ */
+ rv = t->context;
+ t->context = NULL; /* don't free it! */
+ free_context(&t);
+ }
+
+ return(rv ? rv : cpystr(""));
+}
+
+
+
+/*----------------------------------------------------------------------
+ Rename the current sent-mail folder to sent-mail for last month
+
+ open up sent-mail and get date of very first message
+ if date is last month rename and...
+ if files from 3 months ago exist ask if they should be deleted and...
+ if files from previous months and yes ask about them, too.
+ ----------------------------------------------------------------------*/
+int
+expire_sent_mail(void)
+{
+ int cur_month, ok = 1;
+ time_t now;
+ char tmp[50], **p;
+ struct tm *tm_now;
+ CONTEXT_S *prune_cntxt;
+
+ dprint((5, "==== expire_mail called ====\n"));
+
+ if(!check_prune_time(&now, &tm_now))
+ return 0;
+
+ cur_month = (1900 + tm_now->tm_year) * 12 + tm_now->tm_mon;
+ dprint((5, "Current month %d\n", cur_month));
+
+ /*
+ * locate the default save context...
+ */
+ if(!(prune_cntxt = default_save_context(ps_global->context_list)))
+ prune_cntxt = ps_global->context_list;
+
+ /*
+ * Since fcc's and read-mail can be an IMAP mailbox, be sure to only
+ * try expiring a list if it's an ambiguous name associated with some
+ * collection...
+ *
+ * If sentmail set outside a context, then pruning is up to the
+ * user...
+ */
+ if(prune_cntxt){
+ if(ps_global->VAR_DEFAULT_FCC && *ps_global->VAR_DEFAULT_FCC
+ && context_isambig(ps_global->VAR_DEFAULT_FCC))
+ ok = prune_folders(prune_cntxt, ps_global->VAR_DEFAULT_FCC,
+ cur_month, " SENT",
+ ps_global->pruning_rule);
+
+ if(ok && ps_global->VAR_READ_MESSAGE_FOLDER
+ && *ps_global->VAR_READ_MESSAGE_FOLDER
+ && context_isambig(ps_global->VAR_READ_MESSAGE_FOLDER))
+ ok = prune_folders(prune_cntxt, ps_global->VAR_READ_MESSAGE_FOLDER,
+ cur_month, " READ",
+ ps_global->pruning_rule);
+ }
+
+ /*
+ * Within the default prune context,
+ * prune back the folders with the given name
+ */
+ if(ok && prune_cntxt && (p = ps_global->VAR_PRUNED_FOLDERS))
+ for(; ok && *p; p++)
+ if(**p && context_isambig(*p))
+ ok = prune_folders(prune_cntxt, *p, cur_month, "",
+ ps_global->pruning_rule);
+
+ /*
+ * Mark that we're done for this month...
+ */
+ if(ok){
+ ps_global->last_expire_year = tm_now->tm_year;
+ ps_global->last_expire_month = tm_now->tm_mon;
+ snprintf(tmp, sizeof(tmp), "%d.%d", ps_global->last_expire_year,
+ ps_global->last_expire_month + 1);
+ set_variable(V_LAST_TIME_PRUNE_QUESTION, tmp, 1, 1, Main);
+ }
+
+ return(1);
+}
+
+
+/*----------------------------------------------------------------------
+ Offer to delete old sent-mail folders
+
+ Args: sml -- The list of sent-mail folders
+
+ ----*/
+int
+prune_folders(CONTEXT_S *prune_cntxt, char *folder_base, int cur_month,
+ char *type, unsigned int pr)
+{
+ char path2[MAXPATH+1], prompt[128], tmp[21];
+ int month_to_use, exists;
+ struct sm_folder *mail_list, *sm;
+
+ mail_list = get_mail_list(prune_cntxt, folder_base);
+ free_folder_list(prune_cntxt);
+
+#ifdef DEBUG
+ for(sm = mail_list; sm != NULL && sm->name != NULL; sm++)
+ dprint((5,"Old sent-mail: %5d %s\n", sm->month_num,
+ sm->name[0] ? sm->name : "?"));
+#endif
+
+ for(sm = mail_list; sm != NULL && sm->name != NULL; sm++)
+ if(sm->month_num == cur_month - 1)
+ break; /* matched a month */
+
+ month_to_use = (sm == NULL || sm->name == NULL) ? cur_month - 1 : 0;
+
+ dprint((5, "Month_to_use : %d\n", month_to_use));
+
+ if(month_to_use == 0 || pr == PRUNE_NO_AND_ASK || pr == PRUNE_NO_AND_NO)
+ goto delete_old;
+
+ strncpy(path2, folder_base, sizeof(path2)-1);
+ path2[sizeof(path2)-1] = '\0';
+
+ if(F_ON(F_PRUNE_USES_ISO,ps_global)){ /* sent-mail-yyyy-mm */
+ snprintf(path2 + strlen(path2), sizeof(path2)-strlen(path2), "-%4.4d-%2.2d", month_to_use/12,
+ month_to_use % 12 + 1);
+ }
+ else{
+ strncpy(tmp, month_abbrev((month_to_use % 12)+1), 20);
+ tmp[sizeof(tmp)-1] = '\0';
+ lcase((unsigned char *) tmp);
+#ifdef DOS
+ if(*prune_cntxt->context != '{'){
+ int i;
+
+ i = strlen(path2);
+ snprintf(path2 + (size_t)((i > 4) ? 4 : i),
+ sizeof(path2)- ((i > 4) ? 4 : i),
+ "%2.2d%2.2d", (month_to_use % 12) + 1,
+ ((month_to_use / 12) - 1900) % 100);
+ }
+ else
+#endif
+ snprintf(path2 + strlen(path2), sizeof(path2)-strlen(path2), "-%.20s-%d", tmp, month_to_use/12);
+ }
+
+ Writechar(BELL, 0);
+ snprintf(prompt, sizeof(prompt), "Move current \"%.50s\" to \"%.50s\"", folder_base, path2);
+ if((exists = folder_exists(prune_cntxt, folder_base)) == FEX_ERROR){
+ dprint((5, "prune_folders: Error testing existence\n"));
+ return(0);
+ }
+ else if(exists == FEX_NOENT){ /* doesn't exist */
+ dprint((5, "prune_folders: nothing to prune <%s %s>\n",
+ prune_cntxt->context ? prune_cntxt->context : "?",
+ folder_base ? folder_base : "?"));
+ goto delete_old;
+ }
+ else if(!(exists & FEX_ISFILE)
+ || pr == PRUNE_NO_AND_ASK || pr == PRUNE_NO_AND_NO
+ || ((pr == PRUNE_ASK_AND_ASK || pr == PRUNE_ASK_AND_NO) &&
+ want_to(prompt, 'n', 0, h_wt_expire, WT_FLUSH_IN) == 'n')){
+ dprint((5, "User declines renaming %s\n",
+ ps_global->VAR_DEFAULT_FCC ? ps_global->VAR_DEFAULT_FCC : "?"));
+ goto delete_old;
+ }
+
+ prune_move_folder(folder_base, path2, prune_cntxt);
+
+ delete_old:
+ if(pr == PRUNE_ASK_AND_ASK || pr == PRUNE_YES_AND_ASK
+ || pr == PRUNE_NO_AND_ASK)
+ delete_old_mail(mail_list, prune_cntxt, type);
+
+ if((sm = mail_list) != NULL){
+ while(sm->name){
+ fs_give((void **)&(sm->name));
+ sm++;
+ }
+
+ fs_give((void **)&mail_list);
+ }
+
+ return(1);
+}
+
+
+/*----------------------------------------------------------------------
+ Offer to delete old sent-mail folders
+
+ Args: sml -- The list of sent-mail folders
+ fcc_cntxt -- context to delete list of folders in
+ type -- label indicating type of folders being deleted
+
+ ----*/
+void
+delete_old_mail(struct sm_folder *sml, CONTEXT_S *fcc_cntxt, char *type)
+{
+ char prompt[150];
+ struct sm_folder *sm;
+
+ for(sm = sml; sm != NULL && sm->name != NULL; sm++){
+ if(sm->name[0] == '\0') /* can't happen */
+ continue;
+
+ snprintf(prompt, sizeof(prompt),
+ "To save disk space, delete old%.10s mail folder \"%.30s\" ",
+ type, sm->name);
+ if(want_to(prompt, 'n', 0, h_wt_delete_old, WT_FLUSH_IN) == 'y'){
+
+ if(!context_delete(fcc_cntxt, NULL, sm->name)){
+ q_status_message1(SM_ORDER,
+ 3, 3, "Error deleting \"%s\".", sm->name);
+ dprint((1, "Error context_deleting %s in %s\n", sm->name,
+ (fcc_cntxt && fcc_cntxt->context)
+ ? fcc_cntxt->context : "<null>"));
+ }
+ else{
+ int index;
+
+ if((index = folder_index(sm->name, fcc_cntxt, FI_FOLDER)) >= 0)
+ folder_delete(index, FOLDERS(fcc_cntxt));
+ }
+ }else{
+ /* break;*/ /* skip out of the whole thing when he says no */
+ /* Decided to keep asking anyway */
+ }
+ }
+}
+
+
+