imapext-2007
diff src/osdep/amiga/dummy.c @ 0:ada5e610ab86
imap-2007e
author | yuuji@gentei.org |
---|---|
date | Mon, 14 Sep 2009 15:17:45 +0900 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/osdep/amiga/dummy.c Mon Sep 14 15:17:45 2009 +0900 1.3 @@ -0,0 +1,809 @@ 1.4 +/* ======================================================================== 1.5 + * Copyright 1988-2007 University of Washington 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * 1.14 + * ======================================================================== 1.15 + */ 1.16 + 1.17 +/* 1.18 + * Program: Dummy routines 1.19 + * 1.20 + * Author: Mark Crispin 1.21 + * Networks and Distributed Computing 1.22 + * Computing & Communications 1.23 + * University of Washington 1.24 + * Administration Building, AG-44 1.25 + * Seattle, WA 98195 1.26 + * Internet: MRC@CAC.Washington.EDU 1.27 + * 1.28 + * Date: 9 May 1991 1.29 + * Last Edited: 1 June 2007 1.30 + */ 1.31 + 1.32 + 1.33 +#include <stdio.h> 1.34 +#include <ctype.h> 1.35 +#include <errno.h> 1.36 +extern int errno; /* just in case */ 1.37 +#include "mail.h" 1.38 +#include "osdep.h" 1.39 +#include <pwd.h> 1.40 +#include <sys/stat.h> 1.41 +#include "dummy.h" 1.42 +#include "misc.h" 1.43 + 1.44 +/* Function prototypes */ 1.45 + 1.46 +DRIVER *dummy_valid (char *name); 1.47 +void *dummy_parameters (long function,void *value); 1.48 +void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents, 1.49 + long level); 1.50 +long dummy_listed (MAILSTREAM *stream,char delimiter,char *name, 1.51 + long attributes,char *contents); 1.52 +long dummy_subscribe (MAILSTREAM *stream,char *mailbox); 1.53 +MAILSTREAM *dummy_open (MAILSTREAM *stream); 1.54 +void dummy_close (MAILSTREAM *stream,long options); 1.55 +long dummy_ping (MAILSTREAM *stream); 1.56 +void dummy_check (MAILSTREAM *stream); 1.57 +long dummy_expunge (MAILSTREAM *stream,char *sequence,long options); 1.58 +long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options); 1.59 +long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data); 1.60 + 1.61 +/* Dummy routines */ 1.62 + 1.63 + 1.64 +/* Driver dispatch used by MAIL */ 1.65 + 1.66 +DRIVER dummydriver = { 1.67 + "dummy", /* driver name */ 1.68 + DR_LOCAL|DR_MAIL, /* driver flags */ 1.69 + (DRIVER *) NIL, /* next driver */ 1.70 + dummy_valid, /* mailbox is valid for us */ 1.71 + dummy_parameters, /* manipulate parameters */ 1.72 + dummy_scan, /* scan mailboxes */ 1.73 + dummy_list, /* list mailboxes */ 1.74 + dummy_lsub, /* list subscribed mailboxes */ 1.75 + dummy_subscribe, /* subscribe to mailbox */ 1.76 + NIL, /* unsubscribe from mailbox */ 1.77 + dummy_create, /* create mailbox */ 1.78 + dummy_delete, /* delete mailbox */ 1.79 + dummy_rename, /* rename mailbox */ 1.80 + mail_status_default, /* status of mailbox */ 1.81 + dummy_open, /* open mailbox */ 1.82 + dummy_close, /* close mailbox */ 1.83 + NIL, /* fetch message "fast" attributes */ 1.84 + NIL, /* fetch message flags */ 1.85 + NIL, /* fetch overview */ 1.86 + NIL, /* fetch message structure */ 1.87 + NIL, /* fetch header */ 1.88 + NIL, /* fetch text */ 1.89 + NIL, /* fetch message data */ 1.90 + NIL, /* unique identifier */ 1.91 + NIL, /* message number from UID */ 1.92 + NIL, /* modify flags */ 1.93 + NIL, /* per-message modify flags */ 1.94 + NIL, /* search for message based on criteria */ 1.95 + NIL, /* sort messages */ 1.96 + NIL, /* thread messages */ 1.97 + dummy_ping, /* ping mailbox to see if still alive */ 1.98 + dummy_check, /* check for new messages */ 1.99 + dummy_expunge, /* expunge deleted messages */ 1.100 + dummy_copy, /* copy messages to another mailbox */ 1.101 + dummy_append, /* append string message to mailbox */ 1.102 + NIL /* garbage collect stream */ 1.103 +}; 1.104 + 1.105 + /* prototype stream */ 1.106 +MAILSTREAM dummyproto = {&dummydriver}; 1.107 + 1.108 +/* Dummy validate mailbox 1.109 + * Accepts: mailbox name 1.110 + * Returns: our driver if name is valid, NIL otherwise 1.111 + */ 1.112 + 1.113 +DRIVER *dummy_valid (char *name) 1.114 +{ 1.115 + char *s,tmp[MAILTMPLEN]; 1.116 + struct stat sbuf; 1.117 + /* must be valid local mailbox */ 1.118 + if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) { 1.119 + /* indeterminate clearbox INBOX */ 1.120 + if (!*s) return &dummydriver; 1.121 + else if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) { 1.122 + case S_IFREG: 1.123 + case S_IFDIR: 1.124 + return &dummydriver; 1.125 + } 1.126 + /* blackbox INBOX does not exist yet */ 1.127 + else if (!compare_cstring (name,"INBOX")) return &dummydriver; 1.128 + } 1.129 + return NIL; 1.130 +} 1.131 + 1.132 + 1.133 +/* Dummy manipulate driver parameters 1.134 + * Accepts: function code 1.135 + * function-dependent value 1.136 + * Returns: function-dependent return value 1.137 + */ 1.138 + 1.139 +void *dummy_parameters (long function,void *value) 1.140 +{ 1.141 + void *ret = NIL; 1.142 + switch ((int) function) { 1.143 + case GET_INBOXPATH: 1.144 + if (value) ret = dummy_file ((char *) value,"INBOX"); 1.145 + break; 1.146 + } 1.147 + return ret; 1.148 +} 1.149 + 1.150 +/* Dummy scan mailboxes 1.151 + * Accepts: mail stream 1.152 + * reference 1.153 + * pattern to search 1.154 + * string to scan 1.155 + */ 1.156 + 1.157 +void dummy_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents) 1.158 +{ 1.159 + DRIVER *drivers; 1.160 + char *s,test[MAILTMPLEN],file[MAILTMPLEN]; 1.161 + long i; 1.162 + if (!pat || !*pat) { /* empty pattern? */ 1.163 + if (dummy_canonicalize (test,ref,"*")) { 1.164 + /* tie off name at root */ 1.165 + if (s = strchr (test,'/')) *++s = '\0'; 1.166 + else test[0] = '\0'; 1.167 + dummy_listed (stream,'/',test,LATT_NOSELECT,NIL); 1.168 + } 1.169 + } 1.170 + /* get canonical form of name */ 1.171 + else if (dummy_canonicalize (test,ref,pat)) { 1.172 + /* found any wildcards? */ 1.173 + if (s = strpbrk (test,"%*")) { 1.174 + /* yes, copy name up to that point */ 1.175 + strncpy (file,test,i = s - test); 1.176 + file[i] = '\0'; /* tie off */ 1.177 + } 1.178 + else strcpy (file,test); /* use just that name then */ 1.179 + if (s = strrchr (file,'/')){/* find directory name */ 1.180 + *++s = '\0'; /* found, tie off at that point */ 1.181 + s = file; 1.182 + } 1.183 + /* silly case */ 1.184 + else if ((file[0] == '~') || (file[0] == '#')) s = file; 1.185 + /* do the work */ 1.186 + dummy_list_work (stream,s,test,contents,0); 1.187 + /* always an INBOX */ 1.188 + if (pmatch ("INBOX",ucase (test))) { 1.189 + /* done if have a dirfmt INBOX */ 1.190 + for (drivers = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL); 1.191 + drivers && !(!(drivers->flags & DR_DISABLE) && 1.192 + (drivers->flags & DR_DIRFMT) && 1.193 + (*drivers->valid) ("INBOX")); drivers = drivers->next); 1.194 + /* list INBOX appropriately */ 1.195 + dummy_listed (stream,drivers ? '/' : NIL,"INBOX", 1.196 + drivers ? NIL : LATT_NOINFERIORS,contents); 1.197 + } 1.198 + } 1.199 +} 1.200 + 1.201 + 1.202 +/* Dummy list mailboxes 1.203 + * Accepts: mail stream 1.204 + * reference 1.205 + * pattern to search 1.206 + */ 1.207 + 1.208 +void dummy_list (MAILSTREAM *stream,char *ref,char *pat) 1.209 +{ 1.210 + dummy_scan (stream,ref,pat,NIL); 1.211 +} 1.212 + 1.213 +/* Dummy list subscribed mailboxes 1.214 + * Accepts: mail stream 1.215 + * reference 1.216 + * pattern to search 1.217 + */ 1.218 + 1.219 +void dummy_lsub (MAILSTREAM *stream,char *ref,char *pat) 1.220 +{ 1.221 + void *sdb = NIL; 1.222 + char *s,*t,test[MAILTMPLEN],tmp[MAILTMPLEN]; 1.223 + int showuppers = pat[strlen (pat) - 1] == '%'; 1.224 + /* get canonical form of name */ 1.225 + if (dummy_canonicalize (test,ref,pat) && (s = sm_read (&sdb))) do 1.226 + if (*s != '{') { 1.227 + if (!compare_cstring (s,"INBOX") && 1.228 + pmatch ("INBOX",ucase (strcpy (tmp,test)))) 1.229 + mm_lsub (stream,NIL,s,LATT_NOINFERIORS); 1.230 + else if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,NIL); 1.231 + else while (showuppers && (t = strrchr (s,'/'))) { 1.232 + *t = '\0'; /* tie off the name */ 1.233 + if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,LATT_NOSELECT); 1.234 + } 1.235 + } 1.236 + while (s = sm_read (&sdb)); /* until no more subscriptions */ 1.237 +} 1.238 + 1.239 + 1.240 +/* Dummy subscribe to mailbox 1.241 + * Accepts: mail stream 1.242 + * mailbox to add to subscription list 1.243 + * Returns: T on success, NIL on failure 1.244 + */ 1.245 + 1.246 +long dummy_subscribe (MAILSTREAM *stream,char *mailbox) 1.247 +{ 1.248 + char *s,tmp[MAILTMPLEN]; 1.249 + struct stat sbuf; 1.250 + /* must be valid local mailbox */ 1.251 + if ((s = mailboxfile (tmp,mailbox)) && *s && !stat (s,&sbuf)) 1.252 + switch (sbuf.st_mode & S_IFMT) { 1.253 + case S_IFDIR: /* allow but snarl */ 1.254 + sprintf (tmp,"CLIENT BUG DETECTED: subscribe of non-mailbox directory %.80s", 1.255 + mailbox); 1.256 + MM_NOTIFY (stream,tmp,WARN); 1.257 + case S_IFREG: 1.258 + return sm_subscribe (mailbox); 1.259 + } 1.260 + sprintf (tmp,"Can't subscribe %.80s: not a mailbox",mailbox); 1.261 + MM_LOG (tmp,ERROR); 1.262 + return NIL; 1.263 +} 1.264 + 1.265 +/* Dummy list mailboxes worker routine 1.266 + * Accepts: mail stream 1.267 + * directory name to search 1.268 + * search pattern 1.269 + * string to scan 1.270 + * search level 1.271 + */ 1.272 + 1.273 +void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents, 1.274 + long level) 1.275 +{ 1.276 + DRIVER *drivers; 1.277 + dirfmttest_t dt; 1.278 + DIR *dp; 1.279 + struct direct *d; 1.280 + struct stat sbuf; 1.281 + char tmp[MAILTMPLEN],path[MAILTMPLEN]; 1.282 + size_t len = 0; 1.283 + /* punt if bogus name */ 1.284 + if (!mailboxdir (tmp,dir,NIL)) return; 1.285 + if (dp = opendir (tmp)) { /* do nothing if can't open directory */ 1.286 + /* see if a non-namespace directory format */ 1.287 + for (drivers = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL), dt = NIL; 1.288 + dir && !dt && drivers; drivers = drivers->next) 1.289 + if (!(drivers->flags & DR_DISABLE) && (drivers->flags & DR_DIRFMT) && 1.290 + (*drivers->valid) (dir)) 1.291 + dt = mail_parameters ((*drivers->open) (NIL),GET_DIRFMTTEST,NIL); 1.292 + /* list it if at top-level */ 1.293 + if (!level && dir && pmatch_full (dir,pat,'/') && !pmatch (dir,"INBOX")) 1.294 + dummy_listed (stream,'/',dir,dt ? NIL : LATT_NOSELECT,contents); 1.295 + 1.296 + /* scan directory, ignore . and .. */ 1.297 + if (!dir || dir[(len = strlen (dir)) - 1] == '/') while (d = readdir (dp)) 1.298 + if ((!(dt && (*dt) (d->d_name))) && 1.299 + ((d->d_name[0] != '.') || 1.300 + (((long) mail_parameters (NIL,GET_HIDEDOTFILES,NIL)) ? NIL : 1.301 + (d->d_name[1] && (((d->d_name[1] != '.') || d->d_name[2]))))) && 1.302 + ((len + strlen (d->d_name)) <= NETMAXMBX)) { 1.303 + /* see if name is useful */ 1.304 + if (dir) sprintf (tmp,"%s%s",dir,d->d_name); 1.305 + else strcpy (tmp,d->d_name); 1.306 + /* make sure useful and can get info */ 1.307 + if ((pmatch_full (strcpy (path,tmp),pat,'/') || 1.308 + pmatch_full (strcat (path,"/"),pat,'/') || 1.309 + dmatch (path,pat,'/')) && 1.310 + mailboxdir (path,dir,"x") && (len = strlen (path)) && 1.311 + strcpy (path+len-1,d->d_name) && !stat (path,&sbuf)) { 1.312 + /* only interested in file type */ 1.313 + switch (sbuf.st_mode & S_IFMT) { 1.314 + case S_IFDIR: /* directory? */ 1.315 + /* form with trailing / */ 1.316 + sprintf (path,"%s/",tmp); 1.317 + /* skip listing if INBOX */ 1.318 + if (!pmatch (tmp,"INBOX")) { 1.319 + if (pmatch_full (tmp,pat,'/')) { 1.320 + if (!dummy_listed (stream,'/',tmp,LATT_NOSELECT,contents)) 1.321 + break; 1.322 + } 1.323 + /* try again with trailing / */ 1.324 + else if (pmatch_full (path,pat,'/') && 1.325 + !dummy_listed (stream,'/',path,LATT_NOSELECT,contents)) 1.326 + break; 1.327 + } 1.328 + if (dmatch (path,pat,'/') && 1.329 + (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL))) 1.330 + dummy_list_work (stream,path,pat,contents,level+1); 1.331 + break; 1.332 + case S_IFREG: /* ordinary name */ 1.333 + /* Must use ctime for systems that don't update mtime properly */ 1.334 + if (pmatch_full (tmp,pat,'/') && compare_cstring (tmp,"INBOX")) 1.335 + dummy_listed (stream,'/',tmp,LATT_NOINFERIORS + 1.336 + ((sbuf.st_size && (sbuf.st_atime < sbuf.st_ctime))? 1.337 + LATT_MARKED : LATT_UNMARKED),contents); 1.338 + break; 1.339 + } 1.340 + } 1.341 + } 1.342 + closedir (dp); /* all done, flush directory */ 1.343 + } 1.344 +} 1.345 + 1.346 +/* Scan file for contents 1.347 + * Accepts: driver to use 1.348 + * file name 1.349 + * desired contents 1.350 + * length of contents 1.351 + * size of file 1.352 + * Returns: NIL if contents not found, T if found 1.353 + */ 1.354 + 1.355 +long scan_contents (DRIVER *dtb,char *name,char *contents, 1.356 + unsigned long csiz,unsigned long fsiz) 1.357 +{ 1.358 + scancontents_t sc = dtb ? 1.359 + (scancontents_t) (*dtb->parameters) (GET_SCANCONTENTS,NIL) : NIL; 1.360 + return (*(sc ? sc : dummy_scan_contents)) (name,contents,csiz,fsiz); 1.361 +} 1.362 + 1.363 + 1.364 +/* Scan file for contents 1.365 + * Accepts: file name 1.366 + * desired contents 1.367 + * length of contents 1.368 + * size of file 1.369 + * Returns: NIL if contents not found, T if found 1.370 + */ 1.371 + 1.372 +#define BUFSIZE 4*MAILTMPLEN 1.373 + 1.374 +long dummy_scan_contents (char *name,char *contents,unsigned long csiz, 1.375 + unsigned long fsiz) 1.376 +{ 1.377 + int fd; 1.378 + unsigned long ssiz,bsiz; 1.379 + char *buf; 1.380 + /* forget it if can't select or open */ 1.381 + if ((fd = open (name,O_RDONLY,NIL)) >= 0) { 1.382 + /* get buffer including slop */ 1.383 + buf = (char *) fs_get (BUFSIZE + (ssiz = 4 * ((csiz / 4) + 1)) + 1); 1.384 + memset (buf,'\0',ssiz); /* no slop area the first time */ 1.385 + while (fsiz) { /* until end of file */ 1.386 + read (fd,buf+ssiz,bsiz = min (fsiz,BUFSIZE)); 1.387 + if (search ((unsigned char *) buf,bsiz+ssiz, 1.388 + (unsigned char *) contents,csiz)) break; 1.389 + memcpy (buf,buf+BUFSIZE,ssiz); 1.390 + fsiz -= bsiz; /* note that we read that much */ 1.391 + } 1.392 + fs_give ((void **) &buf); /* flush buffer */ 1.393 + close (fd); /* finished with file */ 1.394 + if (fsiz) return T; /* found */ 1.395 + } 1.396 + return NIL; /* not found */ 1.397 +} 1.398 + 1.399 +/* Mailbox found 1.400 + * Accepts: MAIL stream 1.401 + * hierarchy delimiter 1.402 + * mailbox name 1.403 + * attributes 1.404 + * contents to search before calling mm_list() 1.405 + * Returns: NIL if should abort hierarchy search, else T (currently always) 1.406 + */ 1.407 + 1.408 +long dummy_listed (MAILSTREAM *stream,char delimiter,char *name, 1.409 + long attributes,char *contents) 1.410 +{ 1.411 + DRIVER *d; 1.412 + DIR *dp; 1.413 + struct direct *dr; 1.414 + dirfmttest_t dt; 1.415 + unsigned long csiz; 1.416 + struct stat sbuf; 1.417 + int nochild; 1.418 + char *s,tmp[MAILTMPLEN]; 1.419 + if (!(attributes & LATT_NOINFERIORS) && mailboxdir (tmp,name,NIL) && 1.420 + (dp = opendir (tmp))) { /* if not \NoInferiors */ 1.421 + /* locate dirfmttest if any */ 1.422 + for (d = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL), dt = NIL; 1.423 + !dt && d; d = d->next) 1.424 + if (!(d->flags & DR_DISABLE) && (d->flags & DR_DIRFMT) && 1.425 + (*d->valid) (name)) 1.426 + dt = mail_parameters ((*d->open) (NIL),GET_DIRFMTTEST,NIL); 1.427 + /* scan directory for children */ 1.428 + for (nochild = T; nochild && (dr = readdir (dp)); ) 1.429 + if ((!(dt && (*dt) (dr->d_name))) && 1.430 + ((dr->d_name[0] != '.') || 1.431 + (((long) mail_parameters (NIL,GET_HIDEDOTFILES,NIL)) ? NIL : 1.432 + (dr->d_name[1] && ((dr->d_name[1] != '.') || dr->d_name[2]))))) 1.433 + nochild = NIL; 1.434 + attributes |= nochild ? LATT_HASNOCHILDREN : LATT_HASCHILDREN; 1.435 + closedir (dp); /* all done, flush directory */ 1.436 + } 1.437 + d = NIL; /* don't \NoSelect dir if it has a driver */ 1.438 + if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) && 1.439 + (d != &dummydriver)) attributes &= ~LATT_NOSELECT; 1.440 + if (!contents || /* notify main program */ 1.441 + (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) && 1.442 + (s = mailboxfile (tmp,name)) && 1.443 + (*s || (s = mail_parameters (NIL,GET_INBOXPATH,tmp))) && 1.444 + !stat (s,&sbuf) && (d || (csiz <= sbuf.st_size)) && 1.445 + SAFE_SCAN_CONTENTS (d,tmp,contents,csiz,sbuf.st_size))) 1.446 + mm_list (stream,delimiter,name,attributes); 1.447 + return T; 1.448 +} 1.449 + 1.450 +/* Dummy create mailbox 1.451 + * Accepts: mail stream 1.452 + * mailbox name to create 1.453 + * Returns: T on success, NIL on failure 1.454 + */ 1.455 + 1.456 +long dummy_create (MAILSTREAM *stream,char *mailbox) 1.457 +{ 1.458 + char *s,tmp[MAILTMPLEN]; 1.459 + long ret = NIL; 1.460 + /* validate name */ 1.461 + if (!(compare_cstring (mailbox,"INBOX") && (s = dummy_file (tmp,mailbox)))) { 1.462 + sprintf (tmp,"Can't create %.80s: invalid name",mailbox); 1.463 + MM_LOG (tmp,ERROR); 1.464 + } 1.465 + /* create the name, done if made directory */ 1.466 + else if ((ret = dummy_create_path (stream,tmp,get_dir_protection(mailbox)))&& 1.467 + (s = strrchr (s,'/')) && !s[1]) return T; 1.468 + return ret ? set_mbx_protections (mailbox,tmp) : NIL; 1.469 +} 1.470 + 1.471 +/* Dummy create path 1.472 + * Accepts: mail stream 1.473 + * path name to create 1.474 + * directory mode 1.475 + * Returns: T on success, NIL on failure 1.476 + */ 1.477 + 1.478 +long dummy_create_path (MAILSTREAM *stream,char *path,long dirmode) 1.479 +{ 1.480 + struct stat sbuf; 1.481 + char c,*s,tmp[MAILTMPLEN]; 1.482 + int fd; 1.483 + long ret = NIL; 1.484 + char *t = strrchr (path,'/'); 1.485 + int wantdir = t && !t[1]; 1.486 + int mask = umask (0); 1.487 + if (wantdir) *t = '\0'; /* flush trailing delimiter for directory */ 1.488 + if (s = strrchr (path,'/')) { /* found superior to this name? */ 1.489 + c = *++s; /* remember first character of inferior */ 1.490 + *s = '\0'; /* tie off to get just superior */ 1.491 + /* name doesn't exist, create it */ 1.492 + if ((stat (path,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) && 1.493 + !dummy_create_path (stream,path,dirmode)) { 1.494 + umask (mask); /* restore mask */ 1.495 + return NIL; 1.496 + } 1.497 + *s = c; /* restore full name */ 1.498 + } 1.499 + if (wantdir) { /* want to create directory? */ 1.500 + ret = !mkdir (path,(int) dirmode); 1.501 + *t = '/'; /* restore directory delimiter */ 1.502 + } 1.503 + /* create file */ 1.504 + else if ((fd = open (path,O_WRONLY|O_CREAT|O_EXCL, 1.505 + (long) mail_parameters(NIL,GET_MBXPROTECTION,NIL))) >=0) 1.506 + ret = !close (fd); 1.507 + if (!ret) { /* error? */ 1.508 + sprintf (tmp,"Can't create mailbox node %.80s: %.80s",path,strerror (errno)); 1.509 + MM_LOG (tmp,ERROR); 1.510 + } 1.511 + umask (mask); /* restore mask */ 1.512 + return ret; /* return status */ 1.513 +} 1.514 + 1.515 +/* Dummy delete mailbox 1.516 + * Accepts: mail stream 1.517 + * mailbox name to delete 1.518 + * Returns: T on success, NIL on failure 1.519 + */ 1.520 + 1.521 +long dummy_delete (MAILSTREAM *stream,char *mailbox) 1.522 +{ 1.523 + struct stat sbuf; 1.524 + char *s,tmp[MAILTMPLEN]; 1.525 + if (!(s = dummy_file (tmp,mailbox))) { 1.526 + sprintf (tmp,"Can't delete - invalid name: %.80s",s); 1.527 + MM_LOG (tmp,ERROR); 1.528 + } 1.529 + /* no trailing / (workaround BSD kernel bug) */ 1.530 + if ((s = strrchr (tmp,'/')) && !s[1]) *s = '\0'; 1.531 + if (stat (tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) == S_IFDIR) ? 1.532 + rmdir (tmp) : unlink (tmp)) { 1.533 + sprintf (tmp,"Can't delete mailbox %.80s: %.80s",mailbox,strerror (errno)); 1.534 + MM_LOG (tmp,ERROR); 1.535 + return NIL; 1.536 + } 1.537 + return T; /* return success */ 1.538 +} 1.539 + 1.540 +/* Mail rename mailbox 1.541 + * Accepts: mail stream 1.542 + * old mailbox name 1.543 + * new mailbox name 1.544 + * Returns: T on success, NIL on failure 1.545 + */ 1.546 + 1.547 +long dummy_rename (MAILSTREAM *stream,char *old,char *newname) 1.548 +{ 1.549 + struct stat sbuf; 1.550 + char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN]; 1.551 + /* no trailing / allowed */ 1.552 + if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) || 1.553 + stat (oldname,&sbuf) || ((s = strrchr (s,'/')) && !s[1] && 1.554 + ((sbuf.st_mode & S_IFMT) != S_IFDIR))) { 1.555 + sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",old,newname); 1.556 + MM_LOG (mbx,ERROR); 1.557 + return NIL; 1.558 + } 1.559 + if (s) { /* found a directory delimiter? */ 1.560 + if (!s[1]) *s = '\0'; /* ignore trailing delimiter */ 1.561 + else { /* found superior to destination name? */ 1.562 + c = *++s; /* remember first character of inferior */ 1.563 + *s = '\0'; /* tie off to get just superior */ 1.564 + /* name doesn't exist, create it */ 1.565 + if ((stat (mbx,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) && 1.566 + !dummy_create (stream,mbx)) return NIL; 1.567 + *s = c; /* restore full name */ 1.568 + } 1.569 + } 1.570 + /* rename of non-ex INBOX creates dest */ 1.571 + if (!compare_cstring (old,"INBOX") && stat (oldname,&sbuf)) 1.572 + return dummy_create (NIL,mbx); 1.573 + if (rename (oldname,mbx)) { 1.574 + sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",old,newname, 1.575 + strerror (errno)); 1.576 + MM_LOG (tmp,ERROR); 1.577 + return NIL; 1.578 + } 1.579 + return T; /* return success */ 1.580 +} 1.581 + 1.582 +/* Dummy open 1.583 + * Accepts: stream to open 1.584 + * Returns: stream on success, NIL on failure 1.585 + */ 1.586 + 1.587 +MAILSTREAM *dummy_open (MAILSTREAM *stream) 1.588 +{ 1.589 + int fd; 1.590 + char err[MAILTMPLEN],tmp[MAILTMPLEN]; 1.591 + struct stat sbuf; 1.592 + /* OP_PROTOTYPE call */ 1.593 + if (!stream) return &dummyproto; 1.594 + err[0] = '\0'; /* no error message yet */ 1.595 + /* can we open the file? */ 1.596 + if (!dummy_file (tmp,stream->mailbox)) 1.597 + sprintf (err,"Can't open this name: %.80s",stream->mailbox); 1.598 + else if ((fd = open (tmp,O_RDONLY,NIL)) < 0) { 1.599 + /* no, error unless INBOX */ 1.600 + if (compare_cstring (stream->mailbox,"INBOX")) 1.601 + sprintf (err,"%.80s: %.80s",strerror (errno),stream->mailbox); 1.602 + } 1.603 + else { /* file had better be empty then */ 1.604 + fstat (fd,&sbuf); /* sniff at its size */ 1.605 + close (fd); 1.606 + if ((sbuf.st_mode & S_IFMT) != S_IFREG) 1.607 + sprintf (err,"Can't open %.80s: not a selectable mailbox", 1.608 + stream->mailbox); 1.609 + else if (sbuf.st_size) /* bogus format if non-empty */ 1.610 + sprintf (err,"Can't open %.80s (file %.80s): not in valid mailbox format", 1.611 + stream->mailbox,tmp); 1.612 + } 1.613 + if (err[0]) { /* if an error happened */ 1.614 + MM_LOG (err,stream->silent ? WARN : ERROR); 1.615 + return NIL; 1.616 + } 1.617 + else if (!stream->silent) { /* only if silence not requested */ 1.618 + mail_exists (stream,0); /* say there are 0 messages */ 1.619 + mail_recent (stream,0); /* and certainly no recent ones! */ 1.620 + stream->uid_validity = time (0); 1.621 + } 1.622 + stream->inbox = T; /* note that it's an INBOX */ 1.623 + return stream; /* return success */ 1.624 +} 1.625 + 1.626 + 1.627 +/* Dummy close 1.628 + * Accepts: MAIL stream 1.629 + * options 1.630 + */ 1.631 + 1.632 +void dummy_close (MAILSTREAM *stream,long options) 1.633 +{ 1.634 + /* return silently */ 1.635 +} 1.636 + 1.637 +/* Dummy ping mailbox 1.638 + * Accepts: MAIL stream 1.639 + * Returns: T if stream alive, else NIL 1.640 + */ 1.641 + 1.642 +long dummy_ping (MAILSTREAM *stream) 1.643 +{ 1.644 + MAILSTREAM *test; 1.645 + if (time (0) >= /* time to do another test? */ 1.646 + ((time_t) (stream->gensym + 1.647 + (long) mail_parameters (NIL,GET_SNARFINTERVAL,NIL)))) { 1.648 + /* has mailbox format changed? */ 1.649 + if ((test = mail_open (NIL,stream->mailbox,OP_PROTOTYPE)) && 1.650 + (test->dtb != stream->dtb) && 1.651 + (test = mail_open (NIL,stream->mailbox,NIL))) { 1.652 + /* preserve some resources */ 1.653 + test->original_mailbox = stream->original_mailbox; 1.654 + stream->original_mailbox = NIL; 1.655 + test->sparep = stream->sparep; 1.656 + stream->sparep = NIL; 1.657 + test->sequence = stream->sequence; 1.658 + mail_close ((MAILSTREAM *) /* flush resources used by dummy stream */ 1.659 + memcpy (fs_get (sizeof (MAILSTREAM)),stream, 1.660 + sizeof (MAILSTREAM))); 1.661 + /* swap the streams */ 1.662 + memcpy (stream,test,sizeof (MAILSTREAM)); 1.663 + fs_give ((void **) &test);/* flush test now that copied */ 1.664 + /* make sure application knows */ 1.665 + mail_exists (stream,stream->recent = stream->nmsgs); 1.666 + } 1.667 + /* still hasn't changed */ 1.668 + else stream->gensym = time (0); 1.669 + } 1.670 + return T; 1.671 +} 1.672 + 1.673 + 1.674 +/* Dummy check mailbox 1.675 + * Accepts: MAIL stream 1.676 + * No-op for readonly files, since read/writer can expunge it from under us! 1.677 + */ 1.678 + 1.679 +void dummy_check (MAILSTREAM *stream) 1.680 +{ 1.681 + dummy_ping (stream); /* invoke ping */ 1.682 +} 1.683 + 1.684 + 1.685 +/* Dummy expunge mailbox 1.686 + * Accepts: MAIL stream 1.687 + * sequence to expunge if non-NIL 1.688 + * expunge options 1.689 + * Returns: T, always 1.690 + */ 1.691 + 1.692 +long dummy_expunge (MAILSTREAM *stream,char *sequence,long options) 1.693 +{ 1.694 + return LONGT; 1.695 +} 1.696 + 1.697 +/* Dummy copy message(s) 1.698 + * Accepts: MAIL stream 1.699 + * sequence 1.700 + * destination mailbox 1.701 + * options 1.702 + * Returns: T if copy successful, else NIL 1.703 + */ 1.704 + 1.705 +long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options) 1.706 +{ 1.707 + if ((options & CP_UID) ? mail_uid_sequence (stream,sequence) : 1.708 + mail_sequence (stream,sequence)) fatal ("Impossible dummy_copy"); 1.709 + return NIL; 1.710 +} 1.711 + 1.712 + 1.713 +/* Dummy append message string 1.714 + * Accepts: mail stream 1.715 + * destination mailbox 1.716 + * append callback function 1.717 + * data for callback 1.718 + * Returns: T on success, NIL on failure 1.719 + */ 1.720 + 1.721 +long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data) 1.722 +{ 1.723 + struct stat sbuf; 1.724 + int fd = -1; 1.725 + int e; 1.726 + char tmp[MAILTMPLEN]; 1.727 + MAILSTREAM *ts = default_proto (T); 1.728 + /* append to INBOX? */ 1.729 + if (!compare_cstring (mailbox,"INBOX")) { 1.730 + /* yes, if no empty proto try creating */ 1.731 + if (!ts && !(*(ts = default_proto (NIL))->dtb->create) (ts,"INBOX")) 1.732 + ts = NIL; 1.733 + } 1.734 + else if (dummy_file (tmp,mailbox) && ((fd = open (tmp,O_RDONLY,NIL)) < 0)) { 1.735 + if ((e = errno) == ENOENT) /* failed, was it no such file? */ 1.736 + MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before append",NIL); 1.737 + sprintf (tmp,"%.80s: %.80s",strerror (e),mailbox); 1.738 + MM_LOG (tmp,ERROR); /* pass up error */ 1.739 + return NIL; /* always fails */ 1.740 + } 1.741 + else if (fd >= 0) { /* found file? */ 1.742 + fstat (fd,&sbuf); /* get its size */ 1.743 + close (fd); /* toss out the fd */ 1.744 + if (sbuf.st_size) ts = NIL; /* non-empty file? */ 1.745 + } 1.746 + if (ts) return (*ts->dtb->append) (stream,mailbox,af,data); 1.747 + sprintf (tmp,"Indeterminate mailbox format: %.80s",mailbox); 1.748 + MM_LOG (tmp,ERROR); 1.749 + return NIL; 1.750 +} 1.751 + 1.752 +/* Dummy mail generate file string 1.753 + * Accepts: temporary buffer to write into 1.754 + * mailbox name string 1.755 + * Returns: local file string or NIL if failure 1.756 + */ 1.757 + 1.758 +char *dummy_file (char *dst,char *name) 1.759 +{ 1.760 + char *s = mailboxfile (dst,name); 1.761 + /* return our standard inbox */ 1.762 + return (s && !*s) ? strcpy (dst,sysinbox ()) : s; 1.763 +} 1.764 + 1.765 + 1.766 +/* Dummy canonicalize name 1.767 + * Accepts: buffer to write name 1.768 + * reference 1.769 + * pattern 1.770 + * Returns: T if success, NIL if failure 1.771 + */ 1.772 + 1.773 +long dummy_canonicalize (char *tmp,char *ref,char *pat) 1.774 +{ 1.775 + unsigned long i; 1.776 + char *s; 1.777 + if (ref) { /* preliminary reference check */ 1.778 + if (*ref == '{') return NIL;/* remote reference not allowed */ 1.779 + else if (!*ref) ref = NIL; /* treat empty reference as no reference */ 1.780 + } 1.781 + switch (*pat) { 1.782 + case '#': /* namespace name */ 1.783 + if (mailboxfile (tmp,pat)) strcpy (tmp,pat); 1.784 + else return NIL; /* unknown namespace */ 1.785 + break; 1.786 + case '{': /* remote names not allowed */ 1.787 + return NIL; 1.788 + case '/': /* rooted name */ 1.789 + case '~': /* home directory name */ 1.790 + if (!ref || (*ref != '#')) {/* non-namespace reference? */ 1.791 + strcpy (tmp,pat); /* yes, ignore */ 1.792 + break; 1.793 + } 1.794 + /* fall through */ 1.795 + default: /* apply reference for all other names */ 1.796 + if (!ref) strcpy (tmp,pat); /* just copy if no namespace */ 1.797 + else if ((*ref != '#') || mailboxfile (tmp,ref)) { 1.798 + /* wants root of name? */ 1.799 + if (*pat == '/') strcpy (strchr (strcpy (tmp,ref),'/'),pat); 1.800 + /* otherwise just append */ 1.801 + else sprintf (tmp,"%s%s",ref,pat); 1.802 + } 1.803 + else return NIL; /* unknown namespace */ 1.804 + } 1.805 + /* count wildcards */ 1.806 + for (i = 0, s = tmp; *s; *s++) if ((*s == '*') || (*s == '%')) ++i; 1.807 + if (i > MAXWILDCARDS) { /* ridiculous wildcarding? */ 1.808 + MM_LOG ("Excessive wildcards in LIST/LSUB",ERROR); 1.809 + return NIL; 1.810 + } 1.811 + return T; 1.812 +}