~ubuntu-branches/debian/stretch/alpine/stretch

« back to all changes in this revision

Viewing changes to alpine/init.c

  • Committer: Bazaar Package Importer
  • Author(s): Asheesh Laroia
  • Date: 2007-02-17 13:17:42 UTC
  • Revision ID: james.westby@ubuntu.com-20070217131742-99x5c6cpg1pbkdhw
Tags: upstream-0.82+dfsg
ImportĀ upstreamĀ versionĀ 0.82+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#if !defined(lint) && !defined(DOS)
 
2
static char rcsid[] = "$Id: init.c 101 2006-08-10 22:53:04Z mikes@u.washington.edu $";
 
3
#endif
 
4
 
 
5
/*
 
6
 * ========================================================================
 
7
 * Copyright 2006 University of Washington
 
8
 *
 
9
 * Licensed under the Apache License, Version 2.0 (the "License");
 
10
 * you may not use this file except in compliance with the License.
 
11
 * You may obtain a copy of the License at
 
12
 *
 
13
 *     http://www.apache.org/licenses/LICENSE-2.0
 
14
 *
 
15
 * ========================================================================
 
16
 */
 
17
 
 
18
/*======================================================================
 
19
     init.c
 
20
 
 
21
  Session initiation support routines
 
22
 
 
23
 ====*/
 
24
 
 
25
 
 
26
#include "headers.h"
 
27
 
 
28
#include "../pith/init.h"
 
29
#include "../pith/conf.h"
 
30
#include "../pith/status.h"
 
31
#include "../pith/folder.h"
 
32
#include "../pith/context.h"
 
33
 
 
34
#include "init.h"
 
35
 
 
36
 
 
37
/* these are used to report folder directory creation problems */
 
38
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.";
 
39
 
 
40
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.";
 
41
 
 
42
CONF_TXT_T init_md_create[] =   "Creating subdirectory \"%s\" where Alpine will store its mail folders.";
 
43
 
 
44
 
 
45
/*
 
46
 * Internal prototypes
 
47
 */
 
48
void     display_init_err(char *, int);
 
49
char    *context_string(char *);
 
50
int      prune_folders(CONTEXT_S *, char *, int, char *, unsigned);
 
51
int      prune_move_folder(char *, char *, CONTEXT_S *);
 
52
void     delete_old_mail(struct sm_folder *, CONTEXT_S *, char *);
 
53
 
 
54
 
 
55
 
 
56
/*----------------------------------------------------------------------
 
57
    Make sure the alpine folders directory exists, with proper folders
 
58
 
 
59
   Args: ps -- alpine structure to get mail directory and contexts from
 
60
 
 
61
  Result: returns 0 if it exists or it is created and all is well
 
62
                  1 if it is missing and can't be created.
 
63
  ----*/
 
64
init_mail_dir(struct pine *ps)
 
65
{
 
66
 
 
67
/* MAIL_LIST: can we use imap4 CREATE? */
 
68
    /*
 
69
     * We don't really care if mail_dir exists if it isn't 
 
70
     * part of the first folder collection specified.  If this
 
71
     * is the case, it must have been created external to us, so
 
72
     * just move one...
 
73
     */
 
74
    if(ps->VAR_FOLDER_SPEC && ps->VAR_FOLDER_SPEC[0]){
 
75
        char *p  = context_string(ps->VAR_FOLDER_SPEC[0]);
 
76
        int   rv = strncmp(p, ps->VAR_MAIL_DIRECTORY,
 
77
                           strlen(ps->VAR_MAIL_DIRECTORY));
 
78
        fs_give((void **)&p);
 
79
        if(rv)
 
80
          return(0);
 
81
    }
 
82
 
 
83
    switch(is_writable_dir(ps->folders_dir)){
 
84
      case 0:
 
85
        /* --- all is well --- */
 
86
        return(0);
 
87
 
 
88
      case 1:
 
89
        snprintf(tmp_20k_buf, SIZEOF_20KBUF, init_md_exists, ps->folders_dir);
 
90
        display_init_err(tmp_20k_buf, 1);
 
91
        return(-1);
 
92
 
 
93
      case 2:
 
94
        snprintf(tmp_20k_buf, SIZEOF_20KBUF, init_md_file, ps->folders_dir);
 
95
        display_init_err(tmp_20k_buf, 1);
 
96
        return(-1);
 
97
 
 
98
      case 3:
 
99
        snprintf(tmp_20k_buf, SIZEOF_20KBUF, init_md_create, ps->folders_dir);
 
100
        display_init_err(tmp_20k_buf, 0);
 
101
#ifndef _WINDOWS
 
102
        sleep(4);
 
103
#endif
 
104
        if(create_mail_dir(ps->folders_dir) < 0){
 
105
            snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Error creating subdirectory \"%s\" : %s",
 
106
                    ps->folders_dir, error_description(errno));
 
107
            display_init_err(tmp_20k_buf, 1);
 
108
            return(-1);
 
109
        }
 
110
    }
 
111
 
 
112
    return(0);
 
113
}
 
114
 
 
115
 
 
116
/*----------------------------------------------------------------------
 
117
  Make sure the default save folders exist in the default
 
118
  save context.
 
119
  ----*/
 
120
void
 
121
display_init_err(char *s, int err)
 
122
{
 
123
#ifdef  _WINDOWS
 
124
    mswin_messagebox(s, err);
 
125
#else
 
126
    int n = 0;
 
127
 
 
128
    if(err)
 
129
      fputc(BELL, stdout);
 
130
 
 
131
    for(; *s; s++)
 
132
      if(++n > 60 && isspace((unsigned char)*s)){
 
133
          n = 0;
 
134
          fputc('\n', stdout);
 
135
          while(*(s+1) && isspace((unsigned char)*(s+1)))
 
136
            s++;
 
137
      }
 
138
      else
 
139
        fputc(*s, stdout);
 
140
 
 
141
    fputc('\n', stdout);
 
142
#endif
 
143
}
 
144
 
 
145
 
 
146
/*
 
147
 * Return malloc'd string containing only the context specifier given
 
148
 * a string containing the raw pinerc entry
 
149
 */
 
150
char *
 
151
context_string(char *s)
 
152
{
 
153
    CONTEXT_S *t = new_context(s, NULL);
 
154
    char      *rv = NULL;
 
155
 
 
156
    if(t){
 
157
        /*
 
158
         * Take what we want from context, then free the rest...
 
159
         */
 
160
        rv = t->context;
 
161
        t->context = NULL;                      /* don't free it! */
 
162
        free_context(&t);
 
163
    }
 
164
 
 
165
    return(rv ? rv : cpystr(""));
 
166
}
 
167
 
 
168
 
 
169
 
 
170
/*----------------------------------------------------------------------
 
171
      Rename the current sent-mail folder to sent-mail for last month
 
172
 
 
173
   open up sent-mail and get date of very first message
 
174
   if date is last month rename and...
 
175
       if files from 3 months ago exist ask if they should be deleted and...
 
176
           if files from previous months and yes ask about them, too.   
 
177
  ----------------------------------------------------------------------*/
 
178
int
 
179
expire_sent_mail(void)
 
180
{
 
181
    int          cur_month, ok = 1;
 
182
    time_t       now;
 
183
    char         tmp[50], **p;
 
184
    struct tm   *tm_now;
 
185
    CONTEXT_S   *prune_cntxt;
 
186
 
 
187
    dprint((5, "==== expire_mail called ====\n"));
 
188
 
 
189
    if(!check_prune_time(&now, &tm_now))
 
190
      return 0;
 
191
 
 
192
    cur_month = (1900 + tm_now->tm_year) * 12 + tm_now->tm_mon;
 
193
    dprint((5, "Current month %d\n", cur_month));
 
194
 
 
195
    /*
 
196
     * locate the default save context...
 
197
     */
 
198
    if(!(prune_cntxt = default_save_context(ps_global->context_list)))
 
199
      prune_cntxt = ps_global->context_list;
 
200
 
 
201
    /*
 
202
     * Since fcc's and read-mail can be an IMAP mailbox, be sure to only
 
203
     * try expiring a list if it's an ambiguous name associated with some
 
204
     * collection...
 
205
     *
 
206
     * If sentmail set outside a context, then pruning is up to the
 
207
     * user...
 
208
     */
 
209
    if(prune_cntxt){
 
210
        if(ps_global->VAR_DEFAULT_FCC && *ps_global->VAR_DEFAULT_FCC
 
211
           && context_isambig(ps_global->VAR_DEFAULT_FCC))
 
212
          ok = prune_folders(prune_cntxt, ps_global->VAR_DEFAULT_FCC,
 
213
                             cur_month, " SENT",
 
214
                             ps_global->pruning_rule);
 
215
 
 
216
        if(ok && ps_global->VAR_READ_MESSAGE_FOLDER 
 
217
           && *ps_global->VAR_READ_MESSAGE_FOLDER
 
218
           && context_isambig(ps_global->VAR_READ_MESSAGE_FOLDER))
 
219
          ok = prune_folders(prune_cntxt, ps_global->VAR_READ_MESSAGE_FOLDER,
 
220
                             cur_month, " READ",
 
221
                             ps_global->pruning_rule);
 
222
    }
 
223
 
 
224
    /*
 
225
     * Within the default prune context,
 
226
     * prune back the folders with the given name
 
227
     */
 
228
    if(ok && prune_cntxt && (p = ps_global->VAR_PRUNED_FOLDERS))
 
229
      for(; ok && *p; p++)
 
230
        if(**p && context_isambig(*p))
 
231
          ok = prune_folders(prune_cntxt, *p, cur_month, "",
 
232
                             ps_global->pruning_rule);
 
233
 
 
234
    /*
 
235
     * Mark that we're done for this month...
 
236
     */
 
237
    if(ok){
 
238
        ps_global->last_expire_year = tm_now->tm_year;
 
239
        ps_global->last_expire_month = tm_now->tm_mon;
 
240
        snprintf(tmp, sizeof(tmp), "%d.%d", ps_global->last_expire_year,
 
241
                ps_global->last_expire_month + 1);
 
242
        set_variable(V_LAST_TIME_PRUNE_QUESTION, tmp, 1, 1, Main);
 
243
    }
 
244
 
 
245
    return(1);
 
246
}
 
247
 
 
248
 
 
249
/*----------------------------------------------------------------------
 
250
     Offer to delete old sent-mail folders
 
251
 
 
252
  Args: sml -- The list of sent-mail folders
 
253
 
 
254
  ----*/
 
255
int
 
256
prune_folders(CONTEXT_S *prune_cntxt, char *folder_base, int cur_month,
 
257
              char *type, unsigned int pr)
 
258
{
 
259
    char         path2[MAXPATH+1],  prompt[128], tmp[21];
 
260
    char         ctmp[MAILTMPLEN];
 
261
    int          month_to_use, exists;
 
262
    struct sm_folder *mail_list, *sm;
 
263
 
 
264
    mail_list = get_mail_list(prune_cntxt, folder_base);
 
265
    free_folder_list(prune_cntxt);
 
266
 
 
267
#ifdef  DEBUG
 
268
    for(sm = mail_list; sm != NULL && sm->name[0] != '\0'; sm++)
 
269
      dprint((5,"Old sent-mail: %5d  %s\n", sm->month_num,
 
270
             sm->name ? sm->name : "?"));
 
271
#endif
 
272
 
 
273
    for(sm = mail_list; sm != NULL && sm->name[0] != '\0'; sm++)
 
274
      if(sm->month_num == cur_month - 1)
 
275
        break;  /* matched a month */
 
276
 
 
277
    month_to_use = (sm == NULL || sm->name[0] == '\0') ? cur_month - 1 : 0;
 
278
 
 
279
    dprint((5, "Month_to_use : %d\n", month_to_use));
 
280
 
 
281
    if(month_to_use == 0 || pr == PRUNE_NO_AND_ASK || pr == PRUNE_NO_AND_NO)
 
282
      goto delete_old;
 
283
 
 
284
    strncpy(path2, folder_base, sizeof(path2)-1);
 
285
    path2[sizeof(path2)-1] = '\0';
 
286
 
 
287
    if(F_ON(F_PRUNE_USES_ISO,ps_global)){             /* sent-mail-yyyy-mm */
 
288
        snprintf(path2 + strlen(path2), sizeof(path2)-strlen(path2), "-%04.4d-%02.2d", month_to_use/12,
 
289
                month_to_use % 12 + 1);
 
290
    }
 
291
    else{
 
292
        strncpy(tmp, month_abbrev((month_to_use % 12)+1), 20);
 
293
        tmp[sizeof(tmp)-1] = '\0';
 
294
        lcase((unsigned char *) tmp);
 
295
#ifdef  DOS
 
296
        if(*prune_cntxt->context != '{'){
 
297
          int i;
 
298
 
 
299
          i = strlen(path2);
 
300
          snprintf(path2 + (size_t)((i > 4) ? 4 : i),
 
301
                   sizeof(path2)- ((i > 4) ? 4 : i),
 
302
                  "%2.2d%2.2d", (month_to_use % 12) + 1,
 
303
                  ((month_to_use / 12) - 1900) % 100);
 
304
        }
 
305
        else
 
306
#endif
 
307
        snprintf(path2 + strlen(path2), sizeof(path2)-strlen(path2), "-%.20s-%d", tmp, month_to_use/12);
 
308
    }
 
309
 
 
310
    Writechar(BELL, 0);
 
311
    snprintf(prompt, sizeof(prompt), "Move current \"%.50s\" to \"%.50s\"", folder_base, path2);
 
312
    if((exists = folder_exists(prune_cntxt, folder_base)) == FEX_ERROR){
 
313
        dprint((5, "prune_folders: Error testing existence\n"));
 
314
        return(0);
 
315
    }
 
316
    else if(exists == FEX_NOENT){       /* doesn't exist */
 
317
        dprint((5, "prune_folders: nothing to prune <%s %s>\n",
 
318
                   prune_cntxt->context ? prune_cntxt->context : "?",
 
319
                   folder_base ? folder_base : "?"));
 
320
        goto delete_old;
 
321
    }
 
322
    else if(!(exists & FEX_ISFILE)
 
323
            || pr == PRUNE_NO_AND_ASK || pr == PRUNE_NO_AND_NO
 
324
            || ((pr == PRUNE_ASK_AND_ASK || pr == PRUNE_ASK_AND_NO) &&
 
325
                want_to(prompt, 'n', 0, h_wt_expire, WT_FLUSH_IN) == 'n')){
 
326
        dprint((5, "User declines renaming %s\n",
 
327
               ps_global->VAR_DEFAULT_FCC ? ps_global->VAR_DEFAULT_FCC : "?"));
 
328
        goto delete_old;
 
329
    }
 
330
 
 
331
    prune_move_folder(folder_base, path2, prune_cntxt);
 
332
 
 
333
  delete_old:
 
334
    if(pr == PRUNE_ASK_AND_ASK || pr == PRUNE_YES_AND_ASK
 
335
       || pr == PRUNE_NO_AND_ASK)
 
336
      delete_old_mail(mail_list, prune_cntxt, type);
 
337
 
 
338
    if(sm = mail_list){
 
339
        while(sm->name){
 
340
            fs_give((void **)&(sm->name));
 
341
            sm++;
 
342
        }
 
343
 
 
344
        fs_give((void **)&mail_list);
 
345
    }
 
346
 
 
347
    return(1);
 
348
}
 
349
 
 
350
 
 
351
/*----------------------------------------------------------------------
 
352
     Offer to delete old sent-mail folders
 
353
 
 
354
  Args: sml       -- The list of sent-mail folders
 
355
        fcc_cntxt -- context to delete list of folders in
 
356
        type      -- label indicating type of folders being deleted
 
357
 
 
358
  ----*/
 
359
void
 
360
delete_old_mail(struct sm_folder *sml, CONTEXT_S *fcc_cntxt, char *type)
 
361
{
 
362
    char  prompt[150];
 
363
    struct sm_folder *sm;
 
364
 
 
365
    for(sm = sml; sm != NULL && sm->name[0] != '\0'; sm++){
 
366
        snprintf(prompt, sizeof(prompt),
 
367
               "To save disk space, delete old%.10s mail folder \"%.30s\" ",
 
368
               type, sm->name);
 
369
        if(want_to(prompt, 'n', 0, h_wt_delete_old, WT_FLUSH_IN) == 'y'){
 
370
 
 
371
            if(!context_delete(fcc_cntxt, NULL, sm->name)){
 
372
                q_status_message1(SM_ORDER,
 
373
                                  3, 3, "Error deleting \"%.200s\".", sm->name);
 
374
                dprint((1, "Error context_deleting %s in %s\n",
 
375
                           sm->name ? sm->name : "?",
 
376
                           (fcc_cntxt && fcc_cntxt->context)
 
377
                                     ? fcc_cntxt->context : "<null>"));
 
378
            }
 
379
            else{
 
380
                int index;
 
381
 
 
382
                if((index = folder_index(sm->name, fcc_cntxt, FI_FOLDER)) >= 0)
 
383
                  folder_delete(index, FOLDERS(fcc_cntxt));
 
384
            }
 
385
        }else{
 
386
                /* break;*/ /* skip out of the whole thing when he says no */
 
387
                /* Decided to keep asking anyway */
 
388
        }
 
389
    }
 
390
}
 
391
 
 
392
 
 
393