1
#if !defined(lint) && !defined(DOS)
2
static char rcsid[] = "$Id: imap.c 394 2007-01-25 20:29:45Z hubert@u.washington.edu $";
6
* ========================================================================
7
* Copyright 2006 University of Washington
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
13
* http://www.apache.org/licenses/LICENSE-2.0
15
* ========================================================================
18
#include "../pith/headers.h"
19
#include "../pith/imap.h"
20
#include "../pith/msgno.h"
21
#include "../pith/state.h"
22
#include "../pith/flag.h"
23
#include "../pith/status.h"
24
#include "../pith/conftype.h"
25
#include "../pith/context.h"
26
#include "../pith/thread.h"
27
#include "../pith/mailview.h"
28
#include "../pith/mailpart.h"
29
#include "../pith/mailindx.h"
30
#include "../pith/save.h"
31
#include "../pith/util.h"
32
#include "../pith/stream.h"
38
long imap_seq_exec(MAILSTREAM *, char *, long (*)(MAILSTREAM *, long, void *), void *);
39
long imap_seq_exec_append(MAILSTREAM *, long, void *);
44
* Exported globals setup by searching functions to tell mm_searched
45
* where to put message numbers that matched the search criteria,
46
* and to allow mm_searched to return number of matches.
48
MAILSTREAM *mm_search_stream;
49
long mm_search_count = 0L;
50
MAILSTATUS mm_status_result;
52
MM_LIST_S *mm_list_info;
54
MMLOGIN_S *mm_login_list = NULL;
55
MMLOGIN_S *cert_failure_list = NULL;
58
* Instead of storing cached passwords in free storage, store them in this
59
* private space. This makes it easier and more reliable when we want
60
* to zero this space out. We only store passwords here (char *) so we
61
* don't need to worry about alignment.
63
static char private_store[1024];
65
static int critical_depth = 0;
68
RETSIGTYPE (*hold_int)(int);
72
RETSIGTYPE (*hold_term)(int);
76
RETSIGTYPE (*hold_hup)(int);
80
RETSIGTYPE (*hold_usr2)(int);
85
/*----------------------------------------------------------------------
86
receive notification that search found something
88
Input: mail stream and message number of located item
90
Result: nothing, not used by pine
93
mm_searched(MAILSTREAM *stream, long unsigned int rawno)
97
if(rawno > 0L && stream && rawno <= stream->nmsgs
98
&& (mc = mail_elt(stream, rawno))){
100
if(stream == mm_search_stream)
106
/*----------------------------------------------------------------------
107
receive notification of new mail from imap daemon
109
Args: stream -- The stream the message count report is for.
110
number -- The number of messages now in folder.
112
Result: Sets value in pine state indicating new mailbox size
114
Called when the number of messages in the mailbox goes up. This
115
may also be called as a result of an expunge. It increments the
116
new_mail_count based on a the difference between the current idea of
117
the maximum number of messages and what mm_exists claims. The new mail
118
notification is done in newmail.c
120
Only worry about the cases when the number grows, as mm_expunged
125
mm_exists(MAILSTREAM *stream, long unsigned int number)
127
long new_this_call, n;
128
int exbits = 0, lflags = 0;
132
if(ps_global->debug_imap > 1 || ps_global->debugmem)
133
dprint((3, "=== mm_exists(%lu,%s) called ===\n", number,
134
!stream ? "(no stream)" : !stream->mailbox ? "(null)" : stream->mailbox));
137
msgmap = sp_msgmap(stream);
141
if(mn_get_nmsgs(msgmap) != (long) number){
142
sp_set_mail_box_changed(stream, 1);
143
/* titlebar will be affected */
144
if(ps_global->mail_stream == stream)
145
ps_global->mangled_header = 1;
148
if(mn_get_nmsgs(msgmap) < (long) number){
149
new_this_call = (long) number - mn_get_nmsgs(msgmap);
150
sp_set_new_mail_count(stream,
151
sp_new_mail_count(stream) + new_this_call);
152
if(ps_global->mail_stream != stream)
153
sp_set_recent_since_visited(stream,
154
sp_recent_since_visited(stream) + new_this_call);
156
mn_add_raw(msgmap, new_this_call);
159
* Set local "recent" and "hidden" bits...
161
for(n = 0; n < new_this_call; n++, number--){
162
if(msgno_exceptions(stream, number, "0", &exbits, FALSE))
163
exbits |= MSG_EX_RECENT;
165
exbits = MSG_EX_RECENT;
167
msgno_exceptions(stream, number, "0", &exbits, TRUE);
169
if(SORT_IS_THREADED(msgmap))
173
* If we're zoomed, then hide this message too since
174
* it couldn't have possibly been selected yet...
176
lflags |= (any_lflagged(msgmap, MN_HIDE) ? MN_HIDE : 0);
178
set_lflag(stream, msgmap, mn_get_total(msgmap) - n, lflags, 1);
184
/*----------------------------------------------------------------------
185
Receive notification from IMAP that a single message has been expunged
187
Args: stream -- The stream/folder the message is expunged from
188
rawno -- The raw message number that was expunged
190
mm_expunged is always called on an expunge. Simply remove all
191
reference to the expunged message, shifting internal mappings as
195
mm_expunged(MAILSTREAM *stream, long unsigned int rawno)
203
if(ps_global->debug_imap > 1 || ps_global->debugmem)
204
dprint((3, "mm_expunged(%s,%lu)\n",
212
msgmap = sp_msgmap(stream);
216
if(ps_global->mail_stream == stream)
219
if(i = mn_raw2m(msgmap, (long) rawno)){
220
dprint((7, "mm_expunged: rawno=%lu msgno=%ld nmsgs=%ld max_msgno=%ld flagged_exld=%ld\n", rawno, i, mn_get_nmsgs(msgmap), mn_get_total(msgmap), msgmap->flagged_exld));
222
sp_set_mail_box_changed(stream, 1);
223
sp_set_expunge_count(stream, sp_expunge_count(stream) + 1);
226
reset_check_point(stream);
227
ps_global->mangled_header = 1;
229
/* flush invalid cache entries */
230
while(i <= mn_get_total(msgmap))
231
clear_index_cache_ent(stream, i++, 0);
233
/* let app know what happened */
234
mm_expunged_current(rawno);
239
"mm_expunged: rawno=%lu was excluded, flagged_exld was %d\n",
240
rawno, msgmap->flagged_exld));
241
dprint((7, " nmsgs=%ld max_msgno=%ld\n",
242
mn_get_nmsgs(msgmap), mn_get_total(msgmap)));
243
if(rawno > 0L && rawno <= stream->nmsgs)
244
mc = mail_elt(stream, rawno);
247
dprint((7, " cannot get mail_elt(%lu)\n",
251
dprint((7, " mail_elt(%lu)->spare2=%d\n",
252
rawno, (int) (mc->spare2)));
256
if(SORT_IS_THREADED(msgmap)
258
|| ps_global->thread_disp_style != THREAD_NONE)){
262
* When we're sorting with a threaded method an expunged
263
* message may cause the rest of the sort to be wrong. This
264
* isn't so bad if we're just looking at the index. However,
265
* it also causes the thread tree (PINETHRD_S) to become
266
* invalid, so if we're using a threading view we need to
267
* sort in order to fix the tree and to protect fetch_thread().
269
sp_set_need_to_rethread(stream, 1);
272
* If we expunged the current message which was a member of the
273
* viewed thread, and the adjustment to current will take us
274
* out of that thread, fix it if we can, by backing current up
275
* into the thread. We'd like to just check after mn_flush_raw
276
* below but the problem is that the elts won't change until
277
* after we return from mm_expunged. So we have to manually
278
* check the other messages for CHID2 flags instead of thinking
279
* that we can expunge the current message and then check. It won't
280
* work because the elt will still refer to the expunged message.
282
if(sp_viewing_a_thread(stream)
283
&& get_lflag(stream, NULL, rawno, MN_CHID2)
284
&& mn_total_cur(msgmap) == 1
285
&& mn_is_cur(msgmap, mn_raw2m(msgmap, (long) rawno))
286
&& (cur = mn_get_cur(msgmap)) > 1L
287
&& cur < mn_get_total(msgmap)
288
&& !get_lflag(stream, msgmap, cur + 1L, MN_CHID2)
289
&& get_lflag(stream, msgmap, cur - 1L, MN_CHID2))
290
mn_set_cur(msgmap, cur - 1L);
294
* Keep on top of our special flag counts.
296
* NOTE: This is allowed since mail_expunged releases
297
* data for this message after the callback.
299
if(rawno > 0L && rawno <= stream->nmsgs && (mc = mail_elt(stream, rawno))){
301
msgmap->flagged_hid--;
304
msgmap->flagged_exld--;
307
msgmap->flagged_tmp--;
310
msgmap->flagged_chid--;
313
msgmap->flagged_chid2--;
316
msgmap->flagged_coll--;
319
msgmap->flagged_stmp--;
322
msgmap->flagged_usor--;
324
if(mc->spare || mc->spare4)
325
msgmap->flagged_invisible--;
327
free_pine_elt(&mc->sparep);
331
* if it's in the sort array, flush it, otherwise
332
* decrement raw sequence numbers greater than "rawno"
334
mn_flush_raw(msgmap, (long) rawno);
339
mm_flags(MAILSTREAM *stream, long unsigned int rawno)
342
* The idea here is to clean up any data pine might have cached
343
* that has anything to do with the indicated message number.
345
if(stream == ps_global->mail_stream){
349
if(scores_are_used(SCOREUSE_GET) & SCOREUSE_STATEDEP)
350
clear_msg_score(stream, rawno);
352
msgno = mn_raw2m(sp_msgmap(stream), (long) rawno);
354
/* if in thread index */
356
if((thrd = fetch_thread(stream, rawno))
358
&& (thrd = fetch_thread(stream, thrd->top))
360
&& (t = mn_raw2m(sp_msgmap(stream), thrd->rawno)))
361
clear_index_cache_ent(stream, t, 0);
363
else if(THREADING()){
365
clear_index_cache_ent(stream, msgno, 0);
368
* If a parent is collapsed, clear that parent's
371
if((thrd = fetch_thread(stream, rawno)) && thrd->parent){
372
thrd = fetch_thread(stream, thrd->parent);
374
if(get_lflag(stream, NULL, thrd->rawno, MN_COLL)
375
&& (t = mn_raw2m(sp_msgmap(stream), (long) thrd->rawno)))
376
clear_index_cache_ent(stream, t, 0);
379
thrd = fetch_thread(stream, thrd->parent);
386
clear_index_cache_ent(stream, msgno, 0);
388
if(msgno && mn_is_cur(sp_msgmap(stream), msgno))
389
ps_global->mangled_header = 1;
393
* We count up flag changes here. The
394
* dont_count_flagchanges variable tries to prevent us from
395
* counting when we're just fetching flags.
397
if(!(ps_global->dont_count_flagchanges
398
&& stream == ps_global->mail_stream)){
401
check_point_change(stream);
403
/* we also note flag changes for filtering purposes */
404
if(msgno_exceptions(stream, rawno, "0", &exbits, FALSE))
405
exbits |= MSG_EX_STATECHG;
407
exbits = MSG_EX_STATECHG;
409
msgno_exceptions(stream, rawno, "0", &exbits, TRUE);
415
mm_list(MAILSTREAM *stream, int delimiter, char *mailbox, long int attributes)
418
if(ps_global->debug_imap > 2 || ps_global->debugmem)
419
dprint((5, "mm_list \"%s\": delim: '%c', %s%s%s%s%s%s\n",
420
mailbox ? mailbox : "?", delimiter ? delimiter : 'X',
421
(attributes & LATT_NOINFERIORS) ? ", no inferiors" : "",
422
(attributes & LATT_NOSELECT) ? ", no select" : "",
423
(attributes & LATT_MARKED) ? ", marked" : "",
424
(attributes & LATT_UNMARKED) ? ", unmarked" : "",
425
(attributes & LATT_HASCHILDREN) ? ", has children" : "",
426
(attributes & LATT_HASNOCHILDREN) ? ", has no children" : ""));
429
if(!mm_list_info->stream || stream == mm_list_info->stream)
430
(*mm_list_info->filter)(stream, mailbox, delimiter,
431
attributes, mm_list_info->data,
432
mm_list_info->options);
437
mm_lsub(MAILSTREAM *stream, int delimiter, char *mailbox, long int attributes)
440
if(ps_global->debug_imap > 2 || ps_global->debugmem)
441
dprint((5, "LSUB \"%s\": delim: '%c', %s%s%s%s%s%s\n",
442
mailbox ? mailbox : "?", delimiter ? delimiter : 'X',
443
(attributes & LATT_NOINFERIORS) ? ", no inferiors" : "",
444
(attributes & LATT_NOSELECT) ? ", no select" : "",
445
(attributes & LATT_MARKED) ? ", marked" : "",
446
(attributes & LATT_UNMARKED) ? ", unmarked" : "",
447
(attributes & LATT_HASCHILDREN) ? ", has children" : "",
448
(attributes & LATT_HASNOCHILDREN) ? ", has no children" : ""));
451
if(!mm_list_info->stream || stream == mm_list_info->stream)
452
(*mm_list_info->filter)(stream, mailbox, delimiter,
453
attributes, mm_list_info->data,
454
mm_list_info->options);
459
mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status)
462
* We implement mail_status for the #move namespace by adding a wrapper
463
* routine, pine_mail_status. It may have to call the real mail_status
464
* twice for #move folders and combine the results. It sets
465
* pine_cached_status to point to a local status variable to store the
466
* intermediate results.
468
if(pine_cached_status != NULL)
469
*pine_cached_status = *status;
471
mm_status_result = *status;
475
if(pine_cached_status)
477
"mm_status: Preliminary pass for #move\n"));
479
dprint((2, "mm_status: Mailbox \"%s\"",
480
mailbox ? mailbox : "?"));
481
if(status->flags & SA_MESSAGES)
482
dprint((2, ", %lu messages", status->messages));
484
if(status->flags & SA_RECENT)
485
dprint((2, ", %lu recent", status->recent));
487
if(status->flags & SA_UNSEEN)
488
dprint((2, ", %lu unseen", status->unseen));
490
if(status->flags & SA_UIDVALIDITY)
491
dprint((2, ", %lu UID validity", status->uidvalidity));
493
if(status->flags & SA_UIDNEXT)
494
dprint((2, ", %lu next UID", status->uidnext));
502
/*----------------------------------------------------------------------
503
Write imap debugging information into log file
505
Args: strings -- the string for the debug file
507
Result: message written to the debug log file
510
mm_dlog(char *string)
512
char *p, *q = NULL, save, *continued;
516
mswin_imaptelemetry(string);
522
/* because string can be really long and we don't want to lose any of it */
530
continued = "(Continuation line) ";
533
if(strlen(p) > 63000){
541
dprint(((ps_global->debug_imap >= 4 && debug < 4) ? debug : 4,
542
"IMAP DEBUG %s%s: %s\n",
543
continued ? continued : "",
544
debug_time(1, ps_global->debug_timestamp), p ? p : "?"));
552
/*----------------------------------------------------------------------
553
Ignore signals when imap is running through critical code
555
Args: stream -- The stream on which critical operation is proceeding
559
mm_critical(MAILSTREAM *stream)
561
stream = stream; /* For compiler complaints that this isn't used */
563
if(++critical_depth == 1){
566
hold_hup = signal(SIGHUP, SIG_IGN);
569
hold_usr2 = signal(SIGUSR2, SIG_IGN);
572
hold_int = signal(SIGINT, SIG_IGN);
575
hold_term = signal(SIGTERM, SIG_IGN);
579
dprint((9, "IMAP critical (depth now %d) on %s\n",
581
(stream && stream->mailbox) ? stream->mailbox : "<no folder>" ));
585
/*----------------------------------------------------------------------
586
Reset signals after critical imap code
589
mm_nocritical(MAILSTREAM *stream)
591
stream = stream; /* For compiler complaints that this isn't used */
593
if(--critical_depth == 0){
596
(void)signal(SIGHUP, hold_hup);
599
(void)signal(SIGUSR2, hold_usr2);
602
(void)signal(SIGINT, hold_int);
605
(void)signal(SIGTERM, hold_term);
609
critical_depth = MAX(critical_depth, 0);
611
dprint((9, "Done with IMAP critical (depth now %d) on %s\n",
613
(stream && stream->mailbox) ? stream->mailbox : "<no folder>" ));
618
mm_fatal(char *message)
625
imap_referral(MAILSTREAM *stream, char *ref, long int code)
629
if(ref && !struncmp(ref, "imap://", 7)){
631
imapuid_t uid_val, uid;
634
rv = url_imap_folder(ref, &folder, &uid, &uid_val, NULL, 1);
638
if((rv & URL_IMAP_IMAILBOXLIST) && (rv & URL_IMAP_ISERVERONLY))
639
buf = cpystr(folder);
648
case REFUNSUBSCRIBE :
652
if(rv & URL_IMAP_IMESSAGELIST)
653
buf = cpystr(folder);
662
fs_give((void **) &folder);
670
imap_proxycopy(MAILSTREAM *stream, char *sequence, char *mailbox, long int flags)
674
args.folder = mailbox;
677
return(imap_seq_exec(stream, sequence, imap_seq_exec_append, &args));
682
imap_seq_exec(MAILSTREAM *stream, char *sequence,
683
long int (*func)(MAILSTREAM *, long int, void *),
689
while (*sequence) { /* while there is something to parse */
690
if (*sequence == '*') { /* maximum message */
691
if(!(i = stream->nmsgs)){
692
mm_log ("No messages, so no maximum message number",ERROR);
696
sequence++; /* skip past * */
698
else if (!(i = strtoul ((const char *) sequence,&sequence,10))
699
|| (i > stream->nmsgs)){
700
mm_log ("Sequence invalid",ERROR);
704
switch (*sequence) { /* see what the delimiter is */
705
case ':': /* sequence range */
706
if (*++sequence == '*') { /* maximum message */
707
if (stream->nmsgs) j = stream->nmsgs;
709
mm_log ("No messages, so no maximum message number",ERROR);
713
sequence++; /* skip past * */
715
/* parse end of range */
716
else if (!(j = strtoul ((const char *) sequence,&sequence,10)) ||
717
(j > stream->nmsgs)) {
718
mm_log ("Sequence range invalid",ERROR);
722
if (*sequence && *sequence++ != ',') {
723
mm_log ("Sequence range syntax error",ERROR);
727
if (i > j) { /* swap the range if backwards */
732
if(!(*func)(stream, i++, args))
736
case ',': /* single message */
737
++sequence; /* skip the delimiter, fall into end case */
738
case '\0': /* end of sequence */
739
if(!(*func)(stream, i, args))
743
default: /* anything else is a syntax error! */
744
mm_log ("Sequence syntax error",ERROR);
749
return T; /* successfully parsed sequence */
754
imap_seq_exec_append(MAILSTREAM *stream, long int msgno, void *args)
756
char *save_folder, flags[64], date[64];
757
CONTEXT_S *cntxt = NULL;
760
MAILSTREAM *save_stream;
761
SE_APP_S *sa = (SE_APP_S *) args;
765
save_folder = (strucmp(sa->folder, ps_global->inbox_name) == 0)
766
? ps_global->VAR_INBOX_PATH : sa->folder;
768
save_stream = save_msg_stream(cntxt, save_folder, &our_stream);
770
if(so = so_get(CharStar, NULL, WRITE_ACCESS)){
771
/* store flags before the fetch so UNSEEN bit isn't flipped */
772
mc = (msgno > 0L && stream && msgno <= stream->nmsgs)
773
? mail_elt(stream, msgno) : NULL;
775
flag_string(mc, F_ANS|F_FLAG|F_SEEN, flags, sizeof(flags));
781
rv = save_fetch_append(stream, msgno, NULL,
782
save_stream, save_folder, NULL,
783
mc ? mc->rfc822_size : 0L, flags, date, so);
784
if(rv < 0 || sp_expunge_count(stream)){
785
cmd_cancelled("Attached message Save");
788
/* else whatever broke in save_fetch_append shoulda bitched */
793
dprint((1, "Can't allocate store for save: %s\n",
794
error_description(errno)));
795
q_status_message(SM_ORDER | SM_DING, 3, 4,
796
"Problem creating space for message text.");
800
mail_close(save_stream);
807
/*----------------------------------------------------------------------
808
Get login and password from user for IMAP login
810
Args: mb -- The mail box property struct
811
user -- Buffer to return the user name in
812
passwd -- Buffer to return the passwd in
813
trial -- The trial number or number of attempts to login
814
user is at least size NETMAXUSER
815
passwd is apparently at least MAILTMPLEN, but mrc has asked us to
816
use a max size of about 100 instead
818
Result: username and password passed back to imap
821
mm_login(NETMBX *mb, char *user, char *pwd, long int trial)
823
mm_login_work(mb, user, pwd, trial, NULL, NULL);
827
/*----------------------------------------------------------------------
828
Exported method to retrieve logged in user name associated with stream
830
Args: host -- host to find associated login name with.
835
cached_user_name(char *host)
840
if((l = mm_login_list) && host)
842
for(h = l->hosts; h; h = h->next)
843
if(!strucmp(host, h->name))
852
imap_same_host(STRLIST_S *hl1, STRLIST_S *hl2)
856
for( ; hl1; hl1 = hl1->next)
857
for(lp = hl2; lp; lp = lp->next)
858
if(!strucmp(hl1->name, lp->name))
866
* For convenience, we use the same m_list structure (but a different
867
* instance) for storing a list of hosts we've asked the user about when
868
* SSL validation fails. If this function returns TRUE, that means we
869
* have previously asked the user about this host. Ok_novalidate == 1 means
870
* the user said yes, it was ok. Ok_novalidate == 0 means the user
871
* said no. Warned means we warned them already.
874
imap_get_ssl(MMLOGIN_S *m_list, STRLIST_S *hostlist, int *ok_novalidate, int *warned)
878
for(l = m_list; l; l = l->next)
879
if(imap_same_host(l->hosts, hostlist)){
881
*ok_novalidate = l->ok_novalidate;
894
* Just trying to guess the username the user might want to use on this
895
* host, the user will confirm.
898
imap_get_user(MMLOGIN_S *m_list, STRLIST_S *hostlist)
902
for(l = m_list; l; l = l->next)
903
if(imap_same_host(l->hosts, hostlist))
911
* If we have a matching hostname, username, and altflag in our cache,
912
* attempt to login with the password from the cache.
915
imap_get_passwd(MMLOGIN_S *m_list, char *passwd, char *user, STRLIST_S *hostlist, int altflag)
920
"imap_get_passwd: checking user=%s alt=%d host=%s%s%s\n",
921
user ? user : "(null)",
923
hostlist->name ? hostlist->name : "",
924
(hostlist->next && hostlist->next->name) ? ", " : "",
925
(hostlist->next && hostlist->next->name) ? hostlist->next->name
927
for(l = m_list; l; l = l->next)
928
if(imap_same_host(l->hosts, hostlist)
930
&& !strcmp(user, l->user)
931
&& l->altflag == altflag){
933
strncpy(passwd, l->passwd, NETMAXPASSWD);
934
passwd[NETMAXPASSWD-1] = '\0';
936
dprint((9, "imap_get_passwd: match\n"));
937
dprint((10, "imap_get_passwd: trying passwd=\"%s\"\n",
938
passwd ? passwd : "?"));
942
dprint((9, "imap_get_passwd: no match\n"));
949
imap_set_passwd(MMLOGIN_S **l, char *passwd, char *user, STRLIST_S *hostlist,
950
int altflag, int ok_novalidate, int warned)
955
dprint((9, "imap_set_passwd\n"));
956
for(; *l; l = &(*l)->next)
957
if(imap_same_host((*l)->hosts, hostlist)
958
&& !strcmp(user, (*l)->user)
959
&& altflag == (*l)->altflag)
960
if(strcmp(passwd, (*l)->passwd) ||
961
(*l)->ok_novalidate != ok_novalidate ||
962
(*l)->warned != warned)
968
*l = (MMLOGIN_S *)fs_get(sizeof(MMLOGIN_S));
969
memset(*l, 0, sizeof(MMLOGIN_S));
972
len = strlen(passwd);
973
if(!(*l)->passwd || strlen((*l)->passwd) < len)
974
(*l)->passwd = ps_get(len+1);
976
strncpy((*l)->passwd, passwd, len+1);
978
(*l)->altflag = altflag;
979
(*l)->ok_novalidate = ok_novalidate;
980
(*l)->warned = warned;
983
(*l)->user = cpystr(user);
985
dprint((9, "imap_set_passwd: user=%s altflag=%d\n",
986
(*l)->user ? (*l)->user : "?",
989
for( ; hostlist; hostlist = hostlist->next){
990
for(listp = &(*l)->hosts;
991
*listp && strucmp((*listp)->name, hostlist->name);
992
listp = &(*listp)->next)
996
*listp = (STRLIST_S *)fs_get(sizeof(STRLIST_S));
997
(*listp)->name = cpystr(hostlist->name);
998
dprint((9, "imap_set_passwd: host=%s\n",
999
(*listp)->name ? (*listp)->name : "?"));
1000
(*listp)->next = NULL;
1004
dprint((10, "imap_set_passwd: passwd=\"%s\"\n",
1005
passwd ? passwd : "?"));
1011
imap_flush_passwd_cache(int dumpcache)
1013
memset((void *)private_store, 0, sizeof(private_store));
1018
while(l = mm_login_list){
1019
mm_login_list = mm_login_list->next;
1021
fs_give((void **) &l->user);
1023
free_strlist(&l->hosts);
1025
fs_give((void **) &l);
1028
while(l = cert_failure_list){
1029
cert_failure_list = cert_failure_list->next;
1031
fs_give((void **) &l->user);
1033
free_strlist(&l->hosts);
1035
fs_give((void **) &l);
1042
* Mimics fs_get except it only works for char * (no alignment hacks), it
1043
* stores in a static array so it is easy to zero it out (that's the whole
1044
* purpose), allocations always happen at the end (no free).
1045
* If we go past array limit, we don't break, we just use free storage.
1046
* Should be awfully rare, though.
1051
static char *last = private_store;
1054
/* there is enough space */
1055
if(size <= sizeof(private_store) - (last - private_store)){
1061
"Out of password caching space in private_store\n"));
1063
"Using free storage instead\n"));
1064
block = fs_get(size);