~ubuntu-branches/debian/lenny/alpine/lenny

« back to all changes in this revision

Viewing changes to imap/src/osdep/amiga/dummy.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
/* ========================================================================
 
2
 * Copyright 1988-2006 University of Washington
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * 
 
11
 * ========================================================================
 
12
 */
 
13
 
 
14
/*
 
15
 * Program:     Dummy routines
 
16
 *
 
17
 * Author:      Mark Crispin
 
18
 *              Networks and Distributed Computing
 
19
 *              Computing & Communications
 
20
 *              University of Washington
 
21
 *              Administration Building, AG-44
 
22
 *              Seattle, WA  98195
 
23
 *              Internet: MRC@CAC.Washington.EDU
 
24
 *
 
25
 * Date:        9 May 1991
 
26
 * Last Edited: 17 October 2006
 
27
 */
 
28
 
 
29
 
 
30
#include <stdio.h>
 
31
#include <ctype.h>
 
32
#include <errno.h>
 
33
extern int errno;               /* just in case */
 
34
#include "mail.h"
 
35
#include "osdep.h"
 
36
#include <pwd.h>
 
37
#include <sys/stat.h>
 
38
#include "dummy.h"
 
39
#include "misc.h"
 
40
 
 
41
/* Function prototypes */
 
42
 
 
43
DRIVER *dummy_valid (char *name);
 
44
void *dummy_parameters (long function,void *value);
 
45
void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents,
 
46
                      long level);
 
47
long dummy_listed (MAILSTREAM *stream,char delimiter,char *name,
 
48
                   long attributes,char *contents);
 
49
long dummy_subscribe (MAILSTREAM *stream,char *mailbox);
 
50
MAILSTREAM *dummy_open (MAILSTREAM *stream);
 
51
void dummy_close (MAILSTREAM *stream,long options);
 
52
long dummy_ping (MAILSTREAM *stream);
 
53
void dummy_check (MAILSTREAM *stream);
 
54
long dummy_expunge (MAILSTREAM *stream,char *sequence,long options);
 
55
long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
 
56
long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);
 
57
 
 
58
/* Dummy routines */
 
59
 
 
60
 
 
61
/* Driver dispatch used by MAIL */
 
62
 
 
63
DRIVER dummydriver = {
 
64
  "dummy",                      /* driver name */
 
65
  DR_LOCAL|DR_MAIL,             /* driver flags */
 
66
  (DRIVER *) NIL,               /* next driver */
 
67
  dummy_valid,                  /* mailbox is valid for us */
 
68
  dummy_parameters,             /* manipulate parameters */
 
69
  dummy_scan,                   /* scan mailboxes */
 
70
  dummy_list,                   /* list mailboxes */
 
71
  dummy_lsub,                   /* list subscribed mailboxes */
 
72
  dummy_subscribe,              /* subscribe to mailbox */
 
73
  NIL,                          /* unsubscribe from mailbox */
 
74
  dummy_create,                 /* create mailbox */
 
75
  dummy_delete,                 /* delete mailbox */
 
76
  dummy_rename,                 /* rename mailbox */
 
77
  mail_status_default,          /* status of mailbox */
 
78
  dummy_open,                   /* open mailbox */
 
79
  dummy_close,                  /* close mailbox */
 
80
  NIL,                          /* fetch message "fast" attributes */
 
81
  NIL,                          /* fetch message flags */
 
82
  NIL,                          /* fetch overview */
 
83
  NIL,                          /* fetch message structure */
 
84
  NIL,                          /* fetch header */
 
85
  NIL,                          /* fetch text */
 
86
  NIL,                          /* fetch message data */
 
87
  NIL,                          /* unique identifier */
 
88
  NIL,                          /* message number from UID */
 
89
  NIL,                          /* modify flags */
 
90
  NIL,                          /* per-message modify flags */
 
91
  NIL,                          /* search for message based on criteria */
 
92
  NIL,                          /* sort messages */
 
93
  NIL,                          /* thread messages */
 
94
  dummy_ping,                   /* ping mailbox to see if still alive */
 
95
  dummy_check,                  /* check for new messages */
 
96
  dummy_expunge,                /* expunge deleted messages */
 
97
  dummy_copy,                   /* copy messages to another mailbox */
 
98
  dummy_append,                 /* append string message to mailbox */
 
99
  NIL                           /* garbage collect stream */
 
100
};
 
101
 
 
102
                                /* prototype stream */
 
103
MAILSTREAM dummyproto = {&dummydriver};
 
104
 
 
105
/* Dummy validate mailbox
 
106
 * Accepts: mailbox name
 
107
 * Returns: our driver if name is valid, NIL otherwise
 
108
 */
 
109
 
 
110
DRIVER *dummy_valid (char *name)
 
111
{
 
112
  char *s,tmp[MAILTMPLEN];
 
113
  struct stat sbuf;
 
114
                                /* must be valid local mailbox */
 
115
  if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) {
 
116
                                /* indeterminate clearbox INBOX */
 
117
    if (!*s) return &dummydriver;
 
118
    else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) {
 
119
    case S_IFREG:
 
120
    case S_IFDIR:
 
121
      return &dummydriver;
 
122
    }
 
123
                                /* blackbox INBOX does not exist yet */
 
124
    else if (!compare_cstring (name,"INBOX")) return &dummydriver;
 
125
  }
 
126
  return NIL;
 
127
}
 
128
 
 
129
 
 
130
/* Dummy manipulate driver parameters
 
131
 * Accepts: function code
 
132
 *          function-dependent value
 
133
 * Returns: function-dependent return value
 
134
 */
 
135
 
 
136
void *dummy_parameters (long function,void *value)
 
137
{
 
138
  void *ret = NIL;
 
139
  switch ((int) function) {
 
140
  case GET_INBOXPATH:
 
141
    if (value) ret = dummy_file ((char *) value,"INBOX");
 
142
    break;
 
143
  }
 
144
  return ret;
 
145
}
 
146
 
 
147
/* Dummy scan mailboxes
 
148
 * Accepts: mail stream
 
149
 *          reference
 
150
 *          pattern to search
 
151
 *          string to scan
 
152
 */
 
153
 
 
154
void dummy_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents)
 
155
{
 
156
  DRIVER *drivers;
 
157
  char *s,test[MAILTMPLEN],file[MAILTMPLEN];
 
158
  long i;
 
159
  if (!pat || !*pat) {          /* empty pattern? */
 
160
    if (dummy_canonicalize (test,ref,"*")) {
 
161
                                /* tie off name at root */
 
162
      if (s = strchr (test,'/')) *++s = '\0';
 
163
      else test[0] = '\0';
 
164
      dummy_listed (stream,'/',test,LATT_NOSELECT,NIL);
 
165
    }
 
166
  }
 
167
                                /* get canonical form of name */
 
168
  else if (dummy_canonicalize (test,ref,pat)) {
 
169
                                /* found any wildcards? */
 
170
    if (s = strpbrk (test,"%*")) {
 
171
                                /* yes, copy name up to that point */
 
172
      strncpy (file,test,i = s - test);
 
173
      file[i] = '\0';           /* tie off */
 
174
    }
 
175
    else strcpy (file,test);    /* use just that name then */
 
176
    if (s = strrchr (file,'/')){/* find directory name */
 
177
      *++s = '\0';              /* found, tie off at that point */
 
178
      s = file;
 
179
    }
 
180
                                /* silly case */
 
181
    else if ((file[0] == '~') || (file[0] == '#')) s = file;
 
182
                                /* do the work */
 
183
    dummy_list_work (stream,s,test,contents,0);
 
184
                                /* always an INBOX */
 
185
    if (pmatch ("INBOX",ucase (test))) {
 
186
                                /* done if have a dirfmt INBOX */
 
187
      for (drivers = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL);
 
188
           drivers && !(!(drivers->flags & DR_DISABLE) &&
 
189
                        (drivers->flags & DR_DIRFMT) &&
 
190
                        (*drivers->valid) ("INBOX")); drivers = drivers->next);
 
191
                                /* list INBOX appropriately */
 
192
      dummy_listed (stream,drivers ? '/' : NIL,"INBOX",
 
193
                    drivers ? NIL : LATT_NOINFERIORS,contents);
 
194
    }
 
195
  }
 
196
}
 
197
 
 
198
 
 
199
/* Dummy list mailboxes
 
200
 * Accepts: mail stream
 
201
 *          reference
 
202
 *          pattern to search
 
203
 */
 
204
 
 
205
void dummy_list (MAILSTREAM *stream,char *ref,char *pat)
 
206
{
 
207
  dummy_scan (stream,ref,pat,NIL);
 
208
}
 
209
 
 
210
/* Dummy list subscribed mailboxes
 
211
 * Accepts: mail stream
 
212
 *          reference
 
213
 *          pattern to search
 
214
 */
 
215
 
 
216
void dummy_lsub (MAILSTREAM *stream,char *ref,char *pat)
 
217
{
 
218
  void *sdb = NIL;
 
219
  char *s,*t,test[MAILTMPLEN],tmp[MAILTMPLEN];
 
220
  int showuppers = pat[strlen (pat) - 1] == '%';
 
221
                                /* get canonical form of name */
 
222
  if (dummy_canonicalize (test,ref,pat) && (s = sm_read (&sdb))) do
 
223
    if (*s != '{') {
 
224
      if (!compare_cstring (s,"INBOX") &&
 
225
          pmatch ("INBOX",ucase (strcpy (tmp,test))))
 
226
        mm_lsub (stream,NIL,s,LATT_NOINFERIORS);
 
227
      else if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,NIL);
 
228
      else while (showuppers && (t = strrchr (s,'/'))) {
 
229
        *t = '\0';              /* tie off the name */
 
230
        if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,LATT_NOSELECT);
 
231
      }
 
232
    }
 
233
  while (s = sm_read (&sdb));   /* until no more subscriptions */
 
234
}
 
235
 
 
236
 
 
237
/* Dummy subscribe to mailbox
 
238
 * Accepts: mail stream
 
239
 *          mailbox to add to subscription list
 
240
 * Returns: T on success, NIL on failure
 
241
 */
 
242
 
 
243
long dummy_subscribe (MAILSTREAM *stream,char *mailbox)
 
244
{
 
245
  char *s,tmp[MAILTMPLEN];
 
246
  struct stat sbuf;
 
247
                                /* must be valid local mailbox */
 
248
  if ((s = mailboxfile (tmp,mailbox)) && *s && !stat (s,&sbuf) &&
 
249
      ((sbuf.st_mode & S_IFMT) == S_IFREG)) return sm_subscribe (mailbox);
 
250
  sprintf (tmp,"Can't subscribe %.80s: not a mailbox",mailbox);
 
251
  MM_LOG (tmp,ERROR);
 
252
  return NIL;
 
253
}
 
254
 
 
255
/* Dummy list mailboxes worker routine
 
256
 * Accepts: mail stream
 
257
 *          directory name to search
 
258
 *          search pattern
 
259
 *          string to scan
 
260
 *          search level
 
261
 */
 
262
 
 
263
void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents,
 
264
                      long level)
 
265
{
 
266
  DRIVER *drivers;
 
267
  dirfmttest_t dt;
 
268
  DIR *dp;
 
269
  struct direct *d;
 
270
  struct stat sbuf;
 
271
  char tmp[MAILTMPLEN],path[MAILTMPLEN];
 
272
  size_t len = 0;
 
273
                                /* punt if bogus name */
 
274
  if (!mailboxdir (tmp,dir,NIL)) return;
 
275
  if (dp = opendir (tmp)) {     /* do nothing if can't open directory */
 
276
                                /* see if a non-namespace directory format */
 
277
    for (drivers = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL), dt = NIL;
 
278
         dir && !dt && drivers; drivers = drivers->next)
 
279
      if (!(drivers->flags & DR_DISABLE) && (drivers->flags & DR_DIRFMT) &&
 
280
          (*drivers->valid) (dir))
 
281
        dt = mail_parameters ((*drivers->open) (NIL),GET_DIRFMTTEST,NIL);
 
282
                                /* list it if at top-level */
 
283
    if (!level && dir && pmatch_full (dir,pat,'/') && !pmatch (dir,"INBOX"))
 
284
      dummy_listed (stream,'/',dir,dt ? NIL : LATT_NOSELECT,contents);
 
285
 
 
286
                                /* scan directory, ignore . and .. */
 
287
    if (!dir || dir[(len = strlen (dir)) - 1] == '/') while (d = readdir (dp))
 
288
      if ((!(dt && (*dt) (d->d_name))) &&
 
289
          ((d->d_name[0] != '.') ||
 
290
           (((int) mail_parameters (NIL,GET_HIDEDOTFILES,NIL)) ? NIL :
 
291
            (d->d_name[1] && (((d->d_name[1] != '.') || d->d_name[2]))))) &&
 
292
          ((len + strlen (d->d_name)) <= NETMAXMBX)) {
 
293
                                /* see if name is useful */
 
294
        if (dir) sprintf (tmp,"%s%s",dir,d->d_name);
 
295
        else strcpy (tmp,d->d_name);
 
296
                                /* make sure useful and can get info */
 
297
        if ((pmatch_full (strcpy (path,tmp),pat,'/') ||
 
298
             pmatch_full (strcat (path,"/"),pat,'/') || dmatch (path,pat,'/')) &&
 
299
            mailboxdir (path,dir,"x") && (len = strlen (path)) &&
 
300
            strcpy (path+len-1,d->d_name) && !stat (path,&sbuf)) {
 
301
                                /* only interested in file type */
 
302
          switch (sbuf.st_mode & S_IFMT) {
 
303
          case S_IFDIR:         /* directory? */
 
304
                                /* form with trailing / */
 
305
            sprintf (path,"%s/",tmp);
 
306
                                /* skip listing if INBOX */
 
307
            if (!pmatch (tmp,"INBOX")) {
 
308
              if (pmatch_full (tmp,pat,'/')) {
 
309
                if (!dummy_listed (stream,'/',tmp,LATT_NOSELECT,contents))
 
310
                  break;
 
311
              }
 
312
                                /* try again with trailing / */
 
313
              else if (pmatch_full (path,pat,'/') &&
 
314
                       !dummy_listed (stream,'/',tmp,LATT_NOSELECT,contents))
 
315
                break;
 
316
            }
 
317
            if (dmatch (path,pat,'/') &&
 
318
                (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL)))
 
319
              dummy_list_work (stream,path,pat,contents,level+1);
 
320
            break;
 
321
          case S_IFREG:         /* ordinary name */
 
322
            /* Must use ctime for systems that don't update mtime properly */
 
323
            if (pmatch_full (tmp,pat,'/') && compare_cstring (tmp,"INBOX"))
 
324
              dummy_listed (stream,'/',tmp,LATT_NOINFERIORS +
 
325
                            ((sbuf.st_size && (sbuf.st_atime < sbuf.st_ctime))?
 
326
                             LATT_MARKED : LATT_UNMARKED),contents);
 
327
            break;
 
328
          }
 
329
        }
 
330
      }
 
331
    closedir (dp);              /* all done, flush directory */
 
332
  }
 
333
}
 
334
 
 
335
/* Scan file for contents
 
336
 * Accepts: driver to use
 
337
 *          file name
 
338
 *          desired contents
 
339
 *          length of contents
 
340
 *          size of file
 
341
 * Returns: NIL if contents not found, T if found
 
342
 */
 
343
 
 
344
long scan_contents (DRIVER *dtb,char *name,char *contents,
 
345
                    unsigned long csiz,unsigned long fsiz)
 
346
{
 
347
  scancontents_t sc = dtb ?
 
348
    (scancontents_t) (*dtb->parameters) (GET_SCANCONTENTS,NIL) : NIL;
 
349
  return (*(sc ? sc : dummy_scan_contents)) (name,contents,csiz,fsiz);
 
350
}
 
351
 
 
352
 
 
353
/* Scan file for contents
 
354
 * Accepts: file name
 
355
 *          desired contents
 
356
 *          length of contents
 
357
 *          size of file
 
358
 * Returns: NIL if contents not found, T if found
 
359
 */
 
360
 
 
361
#define BUFSIZE 4*MAILTMPLEN
 
362
 
 
363
long dummy_scan_contents (char *name,char *contents,unsigned long csiz,
 
364
                          unsigned long fsiz)
 
365
{
 
366
  int fd;
 
367
  unsigned long ssiz,bsiz;
 
368
  char *buf;
 
369
                                /* forget it if can't select or open */
 
370
  if ((fd = open (name,O_RDONLY,NIL)) >= 0) {
 
371
                                /* get buffer including slop */    
 
372
    buf = (char *) fs_get (BUFSIZE + (ssiz = 4 * ((csiz / 4) + 1)) + 1);
 
373
    memset (buf,'\0',ssiz);     /* no slop area the first time */
 
374
    while (fsiz) {              /* until end of file */
 
375
      read (fd,buf+ssiz,bsiz = min (fsiz,BUFSIZE));
 
376
      if (search ((unsigned char *) buf,bsiz+ssiz,
 
377
                  (unsigned char *) contents,csiz)) break;
 
378
      memcpy (buf,buf+BUFSIZE,ssiz);
 
379
      fsiz -= bsiz;             /* note that we read that much */
 
380
    }
 
381
    fs_give ((void **) &buf);   /* flush buffer */
 
382
    close (fd);                 /* finished with file */
 
383
    if (fsiz) return T;         /* found */
 
384
  }
 
385
  return NIL;                   /* not found */
 
386
}
 
387
 
 
388
/* Mailbox found
 
389
 * Accepts: MAIL stream
 
390
 *          hierarchy delimiter
 
391
 *          mailbox name
 
392
 *          attributes
 
393
 *          contents to search before calling mm_list()
 
394
 * Returns: NIL if should abort hierarchy search, else T (currently always)
 
395
 */
 
396
 
 
397
long dummy_listed (MAILSTREAM *stream,char delimiter,char *name,
 
398
                   long attributes,char *contents)
 
399
{
 
400
  DRIVER *d = NIL;
 
401
  unsigned long csiz;
 
402
  struct stat sbuf;
 
403
  char *s,tmp[MAILTMPLEN];
 
404
                                /* don't \NoSelect dir if it has a driver */
 
405
  if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) &&
 
406
      (d != &dummydriver)) attributes &= ~LATT_NOSELECT;
 
407
  if (!contents ||              /* notify main program */
 
408
      (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) &&
 
409
       (s = mailboxfile (tmp,name)) &&
 
410
       (*s || (s = mail_parameters (NIL,GET_INBOXPATH,tmp))) &&
 
411
       !stat (s,&sbuf) && (d || (csiz <= sbuf.st_size)) &&
 
412
       SAFE_SCAN_CONTENTS (d,tmp,contents,csiz,sbuf.st_size)))
 
413
    mm_list (stream,delimiter,name,attributes);
 
414
  return T;
 
415
}
 
416
 
 
417
/* Dummy create mailbox
 
418
 * Accepts: mail stream
 
419
 *          mailbox name to create
 
420
 * Returns: T on success, NIL on failure
 
421
 */
 
422
 
 
423
long dummy_create (MAILSTREAM *stream,char *mailbox)
 
424
{
 
425
  char *s,tmp[MAILTMPLEN];
 
426
  long ret = NIL;
 
427
                                /* validate name */
 
428
  if (!(compare_cstring (mailbox,"INBOX") && (s = dummy_file (tmp,mailbox)))) {
 
429
    sprintf (tmp,"Can't create %.80s: invalid name",mailbox);
 
430
    MM_LOG (tmp,ERROR);
 
431
  }
 
432
                                /* create the name, done if made directory */
 
433
  else if ((ret = dummy_create_path (stream,tmp,get_dir_protection(mailbox)))&&
 
434
           (s = strrchr (s,'/')) && !s[1]) return T;
 
435
  return ret ? set_mbx_protections (mailbox,tmp) : NIL;
 
436
}
 
437
 
 
438
/* Dummy create path
 
439
 * Accepts: mail stream
 
440
 *          path name to create
 
441
 *          directory mode
 
442
 * Returns: T on success, NIL on failure
 
443
 */
 
444
 
 
445
long dummy_create_path (MAILSTREAM *stream,char *path,long dirmode)
 
446
{
 
447
  struct stat sbuf;
 
448
  char c,*s,tmp[MAILTMPLEN];
 
449
  int fd;
 
450
  long ret = NIL;
 
451
  char *t = strrchr (path,'/');
 
452
  int wantdir = t && !t[1];
 
453
  int mask = umask (0);
 
454
  if (wantdir) *t = '\0';       /* flush trailing delimiter for directory */
 
455
  if (s = strrchr (path,'/')) { /* found superior to this name? */
 
456
    c = *++s;                   /* remember first character of inferior */
 
457
    *s = '\0';                  /* tie off to get just superior */
 
458
                                /* name doesn't exist, create it */
 
459
    if ((stat (path,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&
 
460
        !dummy_create_path (stream,path,dirmode)) {
 
461
      umask (mask);             /* restore mask */
 
462
      return NIL;
 
463
    }
 
464
    *s = c;                     /* restore full name */
 
465
  }
 
466
  if (wantdir) {                /* want to create directory? */
 
467
    ret = !mkdir (path,(int) dirmode);
 
468
    *t = '/';                   /* restore directory delimiter */
 
469
  }
 
470
                                /* create file */
 
471
  else if ((fd = open (path,O_WRONLY|O_CREAT|O_EXCL,
 
472
                       (int) mail_parameters(NIL,GET_MBXPROTECTION,NIL))) >= 0)
 
473
    ret = !close (fd);
 
474
  if (!ret) {                   /* error? */
 
475
    sprintf (tmp,"Can't create mailbox node %.80s: %.80s",path,strerror (errno));
 
476
    MM_LOG (tmp,ERROR);
 
477
  }
 
478
  umask (mask);                 /* restore mask */
 
479
  return ret;                   /* return status */
 
480
}
 
481
 
 
482
/* Dummy delete mailbox
 
483
 * Accepts: mail stream
 
484
 *          mailbox name to delete
 
485
 * Returns: T on success, NIL on failure
 
486
 */
 
487
 
 
488
long dummy_delete (MAILSTREAM *stream,char *mailbox)
 
489
{
 
490
  struct stat sbuf;
 
491
  char *s,tmp[MAILTMPLEN];
 
492
  if (!(s = dummy_file (tmp,mailbox))) {
 
493
    sprintf (tmp,"Can't delete - invalid name: %.80s",s);
 
494
    MM_LOG (tmp,ERROR);
 
495
  }
 
496
                                /* no trailing / (workaround BSD kernel bug) */
 
497
  if ((s = strrchr (tmp,'/')) && !s[1]) *s = '\0';
 
498
  if (stat (tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) == S_IFDIR) ?
 
499
      rmdir (tmp) : unlink (tmp)) {
 
500
    sprintf (tmp,"Can't delete mailbox %.80s: %.80s",mailbox,strerror (errno));
 
501
    MM_LOG (tmp,ERROR);
 
502
    return NIL;
 
503
  }
 
504
  return T;                     /* return success */
 
505
}
 
506
 
 
507
/* Mail rename mailbox
 
508
 * Accepts: mail stream
 
509
 *          old mailbox name
 
510
 *          new mailbox name
 
511
 * Returns: T on success, NIL on failure
 
512
 */
 
513
 
 
514
long dummy_rename (MAILSTREAM *stream,char *old,char *newname)
 
515
{
 
516
  struct stat sbuf;
 
517
  char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN];
 
518
                                /* no trailing / allowed */
 
519
  if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) ||
 
520
      stat (oldname,&sbuf) || ((s = strrchr (s,'/')) && !s[1] &&
 
521
                               ((sbuf.st_mode & S_IFMT) != S_IFDIR))) {
 
522
    sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",old,newname);
 
523
    MM_LOG (mbx,ERROR);
 
524
    return NIL;
 
525
  }
 
526
  if (s) {                      /* found a directory delimiter? */
 
527
    if (!s[1]) *s = '\0';       /* ignore trailing delimiter */
 
528
    else {                      /* found superior to destination name? */
 
529
      c = *++s;                 /* remember first character of inferior */
 
530
      *s = '\0';                /* tie off to get just superior */
 
531
                                /* name doesn't exist, create it */
 
532
      if ((stat (mbx,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&
 
533
          !dummy_create (stream,mbx)) return NIL;
 
534
      *s = c;                   /* restore full name */
 
535
    }
 
536
  }
 
537
                                /* rename of non-ex INBOX creates dest */
 
538
  if (!compare_cstring (old,"INBOX") && stat (oldname,&sbuf))
 
539
    return dummy_create (NIL,mbx);
 
540
  if (rename (oldname,mbx)) {
 
541
    sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",old,newname,
 
542
             strerror (errno));
 
543
    MM_LOG (tmp,ERROR);
 
544
    return NIL;
 
545
  }
 
546
  return T;                     /* return success */
 
547
}
 
548
 
 
549
/* Dummy open
 
550
 * Accepts: stream to open
 
551
 * Returns: stream on success, NIL on failure
 
552
 */
 
553
 
 
554
MAILSTREAM *dummy_open (MAILSTREAM *stream)
 
555
{
 
556
  int fd;
 
557
  char err[MAILTMPLEN],tmp[MAILTMPLEN];
 
558
  struct stat sbuf;
 
559
                                /* OP_PROTOTYPE call */
 
560
  if (!stream) return &dummyproto;
 
561
  err[0] = '\0';                /* no error message yet */
 
562
                                /* can we open the file? */
 
563
  if (!dummy_file (tmp,stream->mailbox))
 
564
    sprintf (err,"Can't open this name: %.80s",stream->mailbox);
 
565
  else if ((fd = open (tmp,O_RDONLY,NIL)) < 0) {
 
566
                                /* no, error unless INBOX */
 
567
    if (compare_cstring (stream->mailbox,"INBOX"))
 
568
      sprintf (err,"%.80s: %.80s",strerror (errno),stream->mailbox);
 
569
  }
 
570
  else {                        /* file had better be empty then */
 
571
    fstat (fd,&sbuf);           /* sniff at its size */
 
572
    close (fd);
 
573
    if ((sbuf.st_mode & S_IFMT) != S_IFREG)
 
574
      sprintf (err,"Can't open %.80s: not a selectable mailbox",
 
575
               stream->mailbox);
 
576
    else if (sbuf.st_size)      /* bogus format if non-empty */
 
577
      sprintf (err,"Can't open %.80s (file %.80s): not in valid mailbox format",
 
578
               stream->mailbox,tmp);
 
579
  }
 
580
  if (err[0]) {                 /* if an error happened */
 
581
    MM_LOG (err,stream->silent ? WARN : ERROR);
 
582
    return NIL;
 
583
  }
 
584
  else if (!stream->silent) {   /* only if silence not requested */
 
585
    mail_exists (stream,0);     /* say there are 0 messages */
 
586
    mail_recent (stream,0);     /* and certainly no recent ones! */
 
587
    stream->uid_validity = time (0);
 
588
  }
 
589
  stream->inbox = T;            /* note that it's an INBOX */
 
590
  return stream;                /* return success */
 
591
}
 
592
 
 
593
 
 
594
/* Dummy close
 
595
 * Accepts: MAIL stream
 
596
 *          options
 
597
 */
 
598
 
 
599
void dummy_close (MAILSTREAM *stream,long options)
 
600
{
 
601
                                /* return silently */
 
602
}
 
603
 
 
604
/* Dummy ping mailbox
 
605
 * Accepts: MAIL stream
 
606
 * Returns: T if stream alive, else NIL
 
607
 */
 
608
 
 
609
long dummy_ping (MAILSTREAM *stream)
 
610
{
 
611
  MAILSTREAM *test;
 
612
  if (time (0) >=               /* time to do another test? */
 
613
      ((time_t) (stream->gensym +
 
614
                 (long) mail_parameters (NIL,GET_SNARFINTERVAL,NIL)))) {
 
615
                                /* has mailbox format changed? */
 
616
    if ((test = mail_open (NIL,stream->mailbox,OP_PROTOTYPE)) &&
 
617
        (test->dtb != stream->dtb) &&
 
618
        (test = mail_open (NIL,stream->mailbox,NIL))) {
 
619
                                /* preserve some resources */
 
620
      test->original_mailbox = stream->original_mailbox;
 
621
      stream->original_mailbox = NIL;
 
622
      test->sparep = stream->sparep;
 
623
      stream->sparep = NIL;
 
624
      test->sequence = stream->sequence;
 
625
      mail_close ((MAILSTREAM *) /* flush resources used by dummy stream */
 
626
                  memcpy (fs_get (sizeof (MAILSTREAM)),stream,
 
627
                          sizeof (MAILSTREAM)));
 
628
                                /* swap the streams */
 
629
      memcpy (stream,test,sizeof (MAILSTREAM));
 
630
      fs_give ((void **) &test);/* flush test now that copied */
 
631
                                /* make sure application knows */
 
632
      mail_exists (stream,stream->recent = stream->nmsgs);
 
633
    }
 
634
                                /* still hasn't changed */
 
635
    else stream->gensym = time (0);
 
636
  }
 
637
  return T;
 
638
}
 
639
 
 
640
 
 
641
/* Dummy check mailbox
 
642
 * Accepts: MAIL stream
 
643
 * No-op for readonly files, since read/writer can expunge it from under us!
 
644
 */
 
645
 
 
646
void dummy_check (MAILSTREAM *stream)
 
647
{
 
648
  dummy_ping (stream);          /* invoke ping */
 
649
}
 
650
 
 
651
 
 
652
/* Dummy expunge mailbox
 
653
 * Accepts: MAIL stream
 
654
 *          sequence to expunge if non-NIL
 
655
 *          expunge options
 
656
 * Returns: T, always
 
657
 */
 
658
 
 
659
long dummy_expunge (MAILSTREAM *stream,char *sequence,long options)
 
660
{
 
661
  return LONGT;
 
662
}
 
663
 
 
664
/* Dummy copy message(s)
 
665
 * Accepts: MAIL stream
 
666
 *          sequence
 
667
 *          destination mailbox
 
668
 *          options
 
669
 * Returns: T if copy successful, else NIL
 
670
 */
 
671
 
 
672
long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
 
673
{
 
674
  if ((options & CP_UID) ? mail_uid_sequence (stream,sequence) :
 
675
      mail_sequence (stream,sequence)) fatal ("Impossible dummy_copy");
 
676
  return NIL;
 
677
}
 
678
 
 
679
 
 
680
/* Dummy append message string
 
681
 * Accepts: mail stream
 
682
 *          destination mailbox
 
683
 *          append callback function
 
684
 *          data for callback
 
685
 * Returns: T on success, NIL on failure
 
686
 */
 
687
 
 
688
long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
 
689
{
 
690
  struct stat sbuf;
 
691
  int fd = -1;
 
692
  int e;
 
693
  char tmp[MAILTMPLEN];
 
694
  MAILSTREAM *ts = default_proto (T);
 
695
  if (compare_cstring (mailbox,"INBOX") && dummy_file (tmp,mailbox) &&
 
696
      ((fd = open (tmp,O_RDONLY,NIL)) < 0)) {
 
697
    if ((e = errno) == ENOENT)  /* failed, was it no such file? */
 
698
      MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before append",NIL);
 
699
    sprintf (tmp,"%.80s: %.80s",strerror (e),mailbox);
 
700
    MM_LOG (tmp,ERROR);         /* pass up error */
 
701
    return NIL;                 /* always fails */
 
702
  }
 
703
  if (fd >= 0) {                /* found file? */
 
704
    fstat (fd,&sbuf);           /* get its size */
 
705
    close (fd);                 /* toss out the fd */
 
706
    if (sbuf.st_size) ts = NIL; /* non-empty file? */
 
707
  }
 
708
  if (ts) return (*ts->dtb->append) (stream,mailbox,af,data);
 
709
  sprintf (tmp,"Indeterminate mailbox format: %.80s",mailbox);
 
710
  MM_LOG (tmp,ERROR);
 
711
  return NIL;
 
712
}
 
713
 
 
714
/* Dummy mail generate file string
 
715
 * Accepts: temporary buffer to write into
 
716
 *          mailbox name string
 
717
 * Returns: local file string or NIL if failure
 
718
 */
 
719
 
 
720
char *dummy_file (char *dst,char *name)
 
721
{
 
722
  char *s = mailboxfile (dst,name);
 
723
                                /* return our standard inbox */
 
724
  return (s && !*s) ? strcpy (dst,sysinbox ()) : s;
 
725
}
 
726
 
 
727
 
 
728
/* Dummy canonicalize name
 
729
 * Accepts: buffer to write name
 
730
 *          reference
 
731
 *          pattern
 
732
 * Returns: T if success, NIL if failure
 
733
 */
 
734
 
 
735
long dummy_canonicalize (char *tmp,char *ref,char *pat)
 
736
{
 
737
  unsigned long i;
 
738
  char *s;
 
739
  if (ref) {                    /* preliminary reference check */
 
740
    if (*ref == '{') return NIL;/* remote reference not allowed */
 
741
    else if (!*ref) ref = NIL;  /* treat empty reference as no reference */
 
742
  }
 
743
  switch (*pat) {
 
744
  case '#':                     /* namespace name */
 
745
    if (mailboxfile (tmp,pat)) strcpy (tmp,pat);
 
746
    else return NIL;            /* unknown namespace */
 
747
    break;
 
748
  case '{':                     /* remote names not allowed */
 
749
    return NIL;
 
750
  case '/':                     /* rooted name */
 
751
  case '~':                     /* home directory name */
 
752
    if (!ref || (*ref != '#')) {/* non-namespace reference? */
 
753
      strcpy (tmp,pat);         /* yes, ignore */
 
754
      break;
 
755
    }
 
756
                                /* fall through */
 
757
  default:                      /* apply reference for all other names */
 
758
    if (!ref) strcpy (tmp,pat); /* just copy if no namespace */
 
759
    else if ((*ref != '#') || mailboxfile (tmp,ref)) {
 
760
                                /* wants root of name? */
 
761
      if (*pat == '/') strcpy (strchr (strcpy (tmp,ref),'/'),pat);
 
762
                                /* otherwise just append */
 
763
      else sprintf (tmp,"%s%s",ref,pat);
 
764
    }
 
765
    else return NIL;            /* unknown namespace */
 
766
  }
 
767
                                /* count wildcards */
 
768
  for (i = 0, s = tmp; *s; *s++) if ((*s == '*') || (*s == '%')) ++i;
 
769
  if (i > MAXWILDCARDS) {       /* ridiculous wildcarding? */
 
770
    MM_LOG ("Excessive wildcards in LIST/LSUB",ERROR);
 
771
    return NIL;
 
772
  }
 
773
  return T;
 
774
}