imapext-2007
diff src/osdep/nt/dummynt.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/nt/dummynt.c Mon Sep 14 15:17:45 2009 +0900 1.3 @@ -0,0 +1,724 @@ 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 for NT 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: 24 May 1993 1.29 + * Last Edited: 1 June 2007 1.30 + */ 1.31 + 1.32 + 1.33 +#include <ctype.h> 1.34 +#include <stdio.h> 1.35 +#include <errno.h> 1.36 +#include <fcntl.h> 1.37 +#include <direct.h> 1.38 +#include "mail.h" 1.39 +#include "osdep.h" 1.40 +#include <sys\stat.h> 1.41 +#include <dos.h> 1.42 +#include "dummy.h" 1.43 +#include "misc.h" 1.44 + 1.45 +/* Function prototypes */ 1.46 + 1.47 +DRIVER *dummy_valid (char *name); 1.48 +void *dummy_parameters (long function,void *value); 1.49 +void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents, 1.50 + long level); 1.51 +long dummy_listed (MAILSTREAM *stream,char delimiter,char *name, 1.52 + long attributes,char *contents); 1.53 +long dummy_subscribe (MAILSTREAM *stream,char *mailbox); 1.54 +MAILSTREAM *dummy_open (MAILSTREAM *stream); 1.55 +void dummy_close (MAILSTREAM *stream,long options); 1.56 +long dummy_ping (MAILSTREAM *stream); 1.57 +void dummy_check (MAILSTREAM *stream); 1.58 +long dummy_expunge (MAILSTREAM *stream,char *sequence,long options); 1.59 +long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options); 1.60 +long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data); 1.61 + 1.62 +/* Dummy routines */ 1.63 + 1.64 + 1.65 +/* Driver dispatch used by MAIL */ 1.66 + 1.67 +DRIVER dummydriver = { 1.68 + "dummy", /* driver name */ 1.69 + DR_LOCAL|DR_MAIL, /* driver flags */ 1.70 + (DRIVER *) NIL, /* next driver */ 1.71 + dummy_valid, /* mailbox is valid for us */ 1.72 + dummy_parameters, /* manipulate parameters */ 1.73 + dummy_scan, /* scan mailboxes */ 1.74 + dummy_list, /* list mailboxes */ 1.75 + dummy_lsub, /* list subscribed mailboxes */ 1.76 + dummy_subscribe, /* subscribe to mailbox */ 1.77 + NIL, /* unsubscribe from mailbox */ 1.78 + dummy_create, /* create mailbox */ 1.79 + dummy_delete, /* delete mailbox */ 1.80 + dummy_rename, /* rename mailbox */ 1.81 + mail_status_default, /* status of mailbox */ 1.82 + dummy_open, /* open mailbox */ 1.83 + dummy_close, /* close mailbox */ 1.84 + NIL, /* fetch message "fast" attributes */ 1.85 + NIL, /* fetch message flags */ 1.86 + NIL, /* fetch overview */ 1.87 + NIL, /* fetch message structure */ 1.88 + NIL, /* fetch header */ 1.89 + NIL, /* fetch text */ 1.90 + NIL, /* fetch message data */ 1.91 + NIL, /* unique identifier */ 1.92 + NIL, /* message number from UID */ 1.93 + NIL, /* modify flags */ 1.94 + NIL, /* per-message modify flags */ 1.95 + NIL, /* search for message based on criteria */ 1.96 + NIL, /* sort messages */ 1.97 + NIL, /* thread messages */ 1.98 + dummy_ping, /* ping mailbox to see if still alive */ 1.99 + dummy_check, /* check for new messages */ 1.100 + dummy_expunge, /* expunge deleted messages */ 1.101 + dummy_copy, /* copy messages to another mailbox */ 1.102 + dummy_append, /* append string message to mailbox */ 1.103 + NIL /* garbage collect stream */ 1.104 +}; 1.105 + 1.106 + 1.107 + /* prototype stream */ 1.108 +MAILSTREAM dummyproto = {&dummydriver}; 1.109 + 1.110 +/* Dummy validate mailbox 1.111 + * Accepts: mailbox name 1.112 + * Returns: our driver if name is valid, NIL otherwise 1.113 + */ 1.114 + 1.115 +DRIVER *dummy_valid (char *name) 1.116 +{ 1.117 + char *s,*t,tmp[MAILTMPLEN]; 1.118 + struct stat sbuf; 1.119 + /* must be valid local mailbox */ 1.120 + if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) { 1.121 + /* indeterminate INBOX */ 1.122 + if (!*s) return &dummydriver; 1.123 + /* remove trailing \ */ 1.124 + if ((t = strrchr (s,'\\')) && !t[1]) *t = '\0'; 1.125 + if (!stat (s,&sbuf)) switch (sbuf.st_mode & S_IFMT) { 1.126 + case S_IFREG: /* file */ 1.127 + case S_IFDIR: /* future use */ 1.128 + return &dummydriver; 1.129 + } 1.130 + } 1.131 + return NIL; 1.132 +} 1.133 + 1.134 + 1.135 +/* Dummy manipulate driver parameters 1.136 + * Accepts: function code 1.137 + * function-dependent value 1.138 + * Returns: function-dependent return value 1.139 + */ 1.140 + 1.141 +void *dummy_parameters (long function,void *value) 1.142 +{ 1.143 + return NIL; 1.144 +} 1.145 + 1.146 +/* Dummy scan mailboxes 1.147 + * Accepts: mail stream 1.148 + * reference 1.149 + * pattern to search 1.150 + * string to scan 1.151 + */ 1.152 + 1.153 +void dummy_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents) 1.154 +{ 1.155 + char *s,test[MAILTMPLEN],file[MAILTMPLEN]; 1.156 + long i = 0; 1.157 + if (!pat || !*pat) { /* empty pattern? */ 1.158 + if (dummy_canonicalize (test,ref,"*")) { 1.159 + /* tie off name at root */ 1.160 + if (s = strchr (test,'\\')) *++s = '\0'; 1.161 + else test[0] = '\0'; 1.162 + dummy_listed (stream,'\\',test,LATT_NOSELECT,NIL); 1.163 + } 1.164 + } 1.165 + /* get canonical form of name */ 1.166 + else if (dummy_canonicalize (test,ref,pat)) { 1.167 + /* found any wildcards? */ 1.168 + if (s = strpbrk (test,"%*")) { 1.169 + /* yes, copy name up to that point */ 1.170 + strncpy (file,test,(size_t) (i = s - test)); 1.171 + file[i] = '\0'; /* tie off */ 1.172 + } 1.173 + else strcpy (file,test); /* use just that name then */ 1.174 + /* find directory name */ 1.175 + if (s = strrchr (file,'\\')) { 1.176 + *++s = '\0'; /* found, tie off at that point */ 1.177 + s = file; 1.178 + } 1.179 + /* silly case */ 1.180 + else if (file[0] == '#') s = file; 1.181 + /* do the work */ 1.182 + dummy_list_work (stream,s,test,contents,0); 1.183 + if (pmatch ("INBOX",test)) /* always an INBOX */ 1.184 + dummy_listed (stream,NIL,"INBOX",LATT_NOINFERIORS,contents); 1.185 + } 1.186 +} 1.187 + 1.188 +/* Dummy list mailboxes 1.189 + * Accepts: mail stream 1.190 + * reference 1.191 + * pattern to search 1.192 + */ 1.193 + 1.194 +void dummy_list (MAILSTREAM *stream,char *ref,char *pat) 1.195 +{ 1.196 + dummy_scan (stream,ref,pat,NIL); 1.197 +} 1.198 + 1.199 + 1.200 +/* Dummy list subscribed mailboxes 1.201 + * Accepts: mail stream 1.202 + * reference 1.203 + * pattern to search 1.204 + */ 1.205 + 1.206 +void dummy_lsub (MAILSTREAM *stream,char *ref,char *pat) 1.207 +{ 1.208 + void *sdb = NIL; 1.209 + char *s,*t,test[MAILTMPLEN]; 1.210 + int showuppers = pat[strlen (pat) - 1] == '%'; 1.211 + /* get canonical form of name */ 1.212 + if (dummy_canonicalize (test,ref,pat) && (s = sm_read (&sdb))) do 1.213 + if (*s != '{') { 1.214 + if (pmatch_full (s,test,'\\')) { 1.215 + if (pmatch (s,"INBOX")) mm_lsub (stream,NIL,s,LATT_NOINFERIORS); 1.216 + else mm_lsub (stream,'\\',s,NIL); 1.217 + } 1.218 + else while (showuppers && (t = strrchr (s,'\\'))) { 1.219 + *t = '\0'; /* tie off the name */ 1.220 + if (pmatch_full (s,test,'\\')) mm_lsub (stream,'\\',s,LATT_NOSELECT); 1.221 + } 1.222 + } 1.223 + while (s = sm_read (&sdb)); /* until no more subscriptions */ 1.224 +} 1.225 + 1.226 + 1.227 +/* Dummy subscribe to mailbox 1.228 + * Accepts: mail stream 1.229 + * mailbox to add to subscription list 1.230 + * Returns: T on success, NIL on failure 1.231 + */ 1.232 + 1.233 +long dummy_subscribe (MAILSTREAM *stream,char *mailbox) 1.234 +{ 1.235 + char *s,tmp[MAILTMPLEN]; 1.236 + struct stat sbuf; 1.237 + /* must be valid local mailbox */ 1.238 + if ((s = mailboxfile (tmp,mailbox)) && *s && !stat (s,&sbuf) && 1.239 + ((sbuf.st_mode & S_IFMT) == S_IFREG)) return sm_subscribe (mailbox); 1.240 + sprintf (tmp,"Can't subscribe %.80s: not a mailbox",mailbox); 1.241 + mm_log (tmp,ERROR); 1.242 + return NIL; 1.243 +} 1.244 + 1.245 +/* Dummy list mailboxes worker routine 1.246 + * Accepts: mail stream 1.247 + * directory name to search 1.248 + * search pattern 1.249 + * string to scan 1.250 + * search level 1.251 + */ 1.252 + 1.253 +void dummy_list_work (MAILSTREAM *stream,char *dir,char *pat,char *contents, 1.254 + long level) 1.255 +{ 1.256 + struct _finddata_t f; 1.257 + struct stat sbuf; 1.258 + long fhandle; 1.259 + char tmp[MAILTMPLEN]; 1.260 + size_t len = 0; 1.261 + /* punt if bogus name */ 1.262 + if (!mailboxdir (tmp,dir,NIL)) return; 1.263 + /* make directory wildcard */ 1.264 + strcat (tmp,(tmp[strlen (tmp) -1] == '\\') ? "*.*" : "\\*.*"); 1.265 + /* do nothing if can't open directory */ 1.266 + if ((fhandle = _findfirst (tmp,&f)) >= 0) { 1.267 + /* list it if at top-level */ 1.268 + if (!level && dir && pmatch_full (dir,pat,'\\')) 1.269 + dummy_listed (stream,'\\',dir,LATT_NOSELECT,contents); 1.270 + /* scan directory */ 1.271 + if (!dir || dir[(len = strlen (dir)) - 1] == '\\') do 1.272 + if (((f.name[0] != '.') || 1.273 + (f.name[1] && ((f.name[1] != '.') || f.name[2]))) && 1.274 + ((len + strlen (f.name)) <= NETMAXMBX)) { 1.275 + /* see if name is useful */ 1.276 + if (dir) sprintf (tmp,"%s%s",dir,f.name); 1.277 + else strcpy (tmp,f.name); 1.278 + /* make sure useful and can get info */ 1.279 + if ((pmatch_full (tmp,pat,'\\') || 1.280 + pmatch_full (strcat (tmp,"\\"),pat,'\\') || 1.281 + dmatch (tmp,pat,'\\')) && 1.282 + mailboxdir (tmp,dir,f.name) && tmp[0] && !stat (tmp,&sbuf)) { 1.283 + /* now make name we'd return */ 1.284 + if (dir) sprintf (tmp,"%s%s",dir,f.name); 1.285 + else strcpy (tmp,f.name); 1.286 + /* only interested in file type */ 1.287 + switch (sbuf.st_mode & S_IFMT) { 1.288 + case S_IFDIR: /* directory? */ 1.289 + if (pmatch_full (tmp,pat,'\\')) { 1.290 + if (!dummy_listed (stream,'\\',tmp,LATT_NOSELECT,contents))break; 1.291 + strcat (tmp,"\\");/* set up for dmatch call */ 1.292 + } 1.293 + /* try again with trailing \ */ 1.294 + else if (pmatch_full (strcat (tmp,"\\"),pat,'\\') && 1.295 + !dummy_listed (stream,'\\',tmp,LATT_NOSELECT,contents)) 1.296 + break; 1.297 + if (dmatch (tmp,pat,'\\') && 1.298 + (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL))) 1.299 + dummy_list_work (stream,tmp,pat,contents,level+1); 1.300 + break; 1.301 + case S_IFREG: /* ordinary name */ 1.302 + if (pmatch_full (tmp,pat,'\\') && !pmatch ("INBOX",tmp)) 1.303 + dummy_listed (stream,'\\',tmp,LATT_NOINFERIORS,contents); 1.304 + break; 1.305 + } 1.306 + } 1.307 + } 1.308 + while (!_findnext (fhandle,&f)); 1.309 + _findclose(fhandle); 1.310 + } 1.311 +} 1.312 + 1.313 +/* Mailbox found 1.314 + * Accepts: hierarchy delimiter 1.315 + * mailbox name 1.316 + * attributes 1.317 + * contents to search before calling mm_list() 1.318 + * Returns: T, always 1.319 + */ 1.320 + 1.321 +#define BUFSIZE 4*MAILTMPLEN 1.322 + 1.323 +long dummy_listed (MAILSTREAM *stream,char delimiter,char *name, 1.324 + long attributes,char *contents) 1.325 +{ 1.326 + struct stat sbuf; 1.327 + struct _finddata_t f; 1.328 + int fd,nochild; 1.329 + long fhandle,csiz,ssiz,bsiz; 1.330 + char *s,*buf,tmp[MAILTMPLEN]; 1.331 + /* if not \NoInferiors */ 1.332 + if (!(attributes & LATT_NOINFERIORS) && mailboxdir (tmp,name,NIL) && 1.333 + strcat (tmp,(tmp[strlen (tmp) -1] == '\\') ? "*.*" : "\\*.*") && 1.334 + ((fhandle = _findfirst (tmp,&f)) >= 0)) { 1.335 + nochild = T; 1.336 + do if ((f.name[0] != '.') || (f.name[1] && ((f.name[1] != '.') || 1.337 + f.name[2]))) nochild = NIL; 1.338 + while (nochild && !_findnext (fhandle,&f)); 1.339 + attributes |= nochild ? LATT_HASNOCHILDREN : LATT_HASCHILDREN; 1.340 + _findclose (fhandle); /* all done, flush directory */ 1.341 + } 1.342 + if (contents) { /* want to search contents? */ 1.343 + /* forget it if can't select or open */ 1.344 + if ((attributes & LATT_NOSELECT) || !(csiz = strlen (contents)) || 1.345 + !(s = dummy_file (tmp,name)) || stat (s,&sbuf) || 1.346 + (csiz > sbuf.st_size) || ((fd = open (tmp,O_RDONLY,NIL)) < 0)) 1.347 + return T; 1.348 + /* get buffer including slop */ 1.349 + buf = (char *) fs_get (BUFSIZE + (ssiz = 4 * ((csiz / 4) + 1)) + 1); 1.350 + memset (buf,'\0',ssiz); /* no slop area the first time */ 1.351 + while (sbuf.st_size) { /* until end of file */ 1.352 + read (fd,buf+ssiz,bsiz = min (sbuf.st_size,BUFSIZE)); 1.353 + if (search ((unsigned char *) buf,bsiz+ssiz, 1.354 + (unsigned char *) contents,csiz)) break; 1.355 + memcpy (buf,buf+BUFSIZE,ssiz); 1.356 + sbuf.st_size -= bsiz; /* note that we read that much */ 1.357 + } 1.358 + fs_give ((void **) &buf); /* flush buffer */ 1.359 + close (fd); /* finished with file */ 1.360 + if (!sbuf.st_size) return T;/* not found */ 1.361 + } 1.362 + /* notify main program */ 1.363 + mm_list (stream,delimiter,name,attributes); 1.364 + return T; 1.365 +} 1.366 + 1.367 +/* Dummy create mailbox 1.368 + * Accepts: mail stream 1.369 + * mailbox name to create 1.370 + * Returns: T on success, NIL on failure 1.371 + */ 1.372 + 1.373 +long dummy_create (MAILSTREAM *stream,char *mailbox) 1.374 +{ 1.375 + char tmp[MAILTMPLEN]; 1.376 + if (compare_cstring (mailbox,"INBOX") && dummy_file (tmp,mailbox)) 1.377 + return dummy_create_path (stream,tmp,NIL); 1.378 + sprintf (tmp,"Can't create %.80s: invalid name",mailbox); 1.379 + mm_log (tmp,ERROR); 1.380 + return NIL; 1.381 +} 1.382 + 1.383 + 1.384 +/* Dummy create path 1.385 + * Accepts: mail stream 1.386 + * path name to create 1.387 + * directory mode 1.388 + * Returns: T on success, NIL on failure 1.389 + */ 1.390 + 1.391 +long dummy_create_path (MAILSTREAM *stream,char *path,long dirmode) 1.392 +{ 1.393 + struct stat sbuf; 1.394 + char c,*s,tmp[MAILTMPLEN]; 1.395 + int fd; 1.396 + long ret = NIL; 1.397 + char *t = strrchr (path,'\\'); 1.398 + char *pt = (path[1] == ':') ? path + 2 : path; 1.399 + int wantdir = t && !t[1]; 1.400 + if (wantdir) *t = '\0'; /* flush trailing delimiter for directory */ 1.401 + /* found superior to this name? */ 1.402 + if ((s = strrchr (pt,'\\')) && (s != pt)) { 1.403 + strncpy (tmp,path,(size_t) (s - path)); 1.404 + tmp[s - path] = '\0'; /* make directory name for stat */ 1.405 + c = *++s; /* tie off in case need to recurse */ 1.406 + *s = '\0'; 1.407 + /* name doesn't exist, create it */ 1.408 + if ((stat (tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) && 1.409 + !dummy_create_path (stream,path,dirmode)) return NIL; 1.410 + *s = c; /* restore full name */ 1.411 + } 1.412 + if (wantdir) { /* want to create directory? */ 1.413 + ret = !mkdir (path); 1.414 + *t = '\\'; /* restore directory delimiter */ 1.415 + } 1.416 + /* create file */ 1.417 + else if ((fd = open (path,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) >= 0) 1.418 + ret = !close (fd); /* close file */ 1.419 + if (!ret) { /* error? */ 1.420 + sprintf (tmp,"Can't create mailbox node %.80s: %.80s",path, 1.421 + strerror (errno)); 1.422 + mm_log (tmp,ERROR); 1.423 + } 1.424 + return ret; /* return status */ 1.425 +} 1.426 + 1.427 +/* Dummy delete mailbox 1.428 + * Accepts: mail stream 1.429 + * mailbox name to delete 1.430 + * Returns: T on success, NIL on failure 1.431 + */ 1.432 + 1.433 +long dummy_delete (MAILSTREAM *stream,char *mailbox) 1.434 +{ 1.435 + struct stat sbuf; 1.436 + char *s,tmp[MAILTMPLEN]; 1.437 + if (!(s = dummy_file (tmp,mailbox))) { 1.438 + sprintf (tmp,"Can't delete - invalid name: %.80s",s); 1.439 + mm_log (tmp,ERROR); 1.440 + } 1.441 + /* no trailing \ */ 1.442 + if ((s = strrchr (tmp,'\\')) && !s[1]) *s = '\0'; 1.443 + if (stat (tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) == S_IFDIR) ? 1.444 + rmdir (tmp) : unlink (tmp)) { 1.445 + sprintf (tmp,"Can't delete mailbox %.80s: %.80s",mailbox,strerror (errno)); 1.446 + mm_log (tmp,ERROR); 1.447 + return NIL; 1.448 + } 1.449 + return T; /* return success */ 1.450 +} 1.451 + 1.452 + 1.453 +/* Mail rename mailbox 1.454 + * Accepts: mail stream 1.455 + * old mailbox name 1.456 + * new mailbox name 1.457 + * Returns: T on success, NIL on failure 1.458 + */ 1.459 + 1.460 +long dummy_rename (MAILSTREAM *stream,char *old,char *newname) 1.461 +{ 1.462 + struct stat sbuf; 1.463 + char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN]; 1.464 + long ret = NIL; 1.465 + /* no trailing \ allowed */ 1.466 + if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) || 1.467 + stat (oldname,&sbuf) || ((s = strrchr (s,'\\')) && !s[1] && 1.468 + ((sbuf.st_mode & S_IFMT) != S_IFDIR))) { 1.469 + sprintf (mbx,"Can't rename %.80s to %.80s: invalid name",old,newname); 1.470 + mm_log (mbx,ERROR); 1.471 + return NIL; 1.472 + } 1.473 + if (s) { /* found a directory delimiter? */ 1.474 + if (!s[1]) *s = '\0'; /* ignore trailing delimiter */ 1.475 + /* found superior to destination name? */ 1.476 + else if ((s != mbx) && ((mbx[1] != ':') || (s != mbx + 2))) { 1.477 + c = s[1]; /* remember character after delimiter */ 1.478 + *s = s[1] = '\0'; /* tie off name at delimiter */ 1.479 + /* name doesn't exist, create it */ 1.480 + if (stat (mbx,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) { 1.481 + *s = '\\'; /* restore delimiter */ 1.482 + if (!dummy_create (stream,mbx)) return NIL; 1.483 + } 1.484 + else *s = '\\'; /* restore delimiter */ 1.485 + s[1] = c; /* restore character after delimiter */ 1.486 + } 1.487 + } 1.488 + /* rename of non-ex INBOX creates dest */ 1.489 + if (!compare_cstring (old,"INBOX") && stat (oldname,&sbuf)) 1.490 + return dummy_create (NIL,mbx); 1.491 + if (rename (oldname,mbx)) { 1.492 + sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %.80s",old,newname, 1.493 + strerror (errno)); 1.494 + mm_log (tmp,ERROR); 1.495 + return NIL; 1.496 + } 1.497 + return LONGT; /* return success */ 1.498 +} 1.499 + 1.500 +/* Dummy open 1.501 + * Accepts: stream to open 1.502 + * Returns: stream on success, NIL on failure 1.503 + */ 1.504 + 1.505 +MAILSTREAM *dummy_open (MAILSTREAM *stream) 1.506 +{ 1.507 + int fd; 1.508 + char err[MAILTMPLEN],tmp[MAILTMPLEN]; 1.509 + struct stat sbuf; 1.510 + /* OP_PROTOTYPE call */ 1.511 + if (!stream) return &dummyproto; 1.512 + err[0] = '\0'; /* no error message yet */ 1.513 + /* can we open the file? */ 1.514 + if (!dummy_file (tmp,stream->mailbox)) 1.515 + sprintf (err,"Can't open this name: %.80s",stream->mailbox); 1.516 + else if ((fd = open (tmp,O_RDONLY,NIL)) < 0) { 1.517 + /* no, error unless INBOX */ 1.518 + if (compare_cstring (stream->mailbox,"INBOX")) 1.519 + sprintf (err,"%.80s: %.80s",strerror (errno),stream->mailbox); 1.520 + } 1.521 + else { /* file had better be empty then */ 1.522 + fstat (fd,&sbuf); /* sniff at its size */ 1.523 + close (fd); 1.524 + if (sbuf.st_size) /* bogus format if non-empty */ 1.525 + sprintf (err,"%.80s (file %.80s) is not in valid mailbox format", 1.526 + stream->mailbox,tmp); 1.527 + } 1.528 + if (err[0]) { /* if an error happened */ 1.529 + mm_log (err,stream->silent ? WARN : ERROR); 1.530 + return NIL; 1.531 + } 1.532 + else if (!stream->silent) { /* only if silence not requested */ 1.533 + mail_exists (stream,0); /* say there are 0 messages */ 1.534 + mail_recent (stream,0); /* and certainly no recent ones! */ 1.535 + stream->uid_validity = (unsigned long) time (0); 1.536 + } 1.537 + stream->inbox = T; /* note that it's an INBOX */ 1.538 + return stream; /* return success */ 1.539 +} 1.540 + 1.541 + 1.542 +/* Dummy close 1.543 + * Accepts: MAIL stream 1.544 + * options 1.545 + */ 1.546 + 1.547 +void dummy_close (MAILSTREAM *stream,long options) 1.548 +{ 1.549 + /* return silently */ 1.550 +} 1.551 + 1.552 +/* Dummy ping mailbox 1.553 + * Accepts: MAIL stream 1.554 + * Returns: T if stream alive, else NIL 1.555 + */ 1.556 + 1.557 +long dummy_ping (MAILSTREAM *stream) 1.558 +{ 1.559 + MAILSTREAM *test; 1.560 + /* time to do another test? */ 1.561 + if (time (0) >= ((time_t) (stream->gensym + 30))) { 1.562 + /* has mailbox format changed? */ 1.563 + if ((test = mail_open (NIL,stream->mailbox,OP_PROTOTYPE)) && 1.564 + (test->dtb != stream->dtb) && 1.565 + (test = mail_open (NIL,stream->mailbox,NIL))) { 1.566 + /* preserve some resources */ 1.567 + test->original_mailbox = stream->original_mailbox; 1.568 + stream->original_mailbox = NIL; 1.569 + test->sparep = stream->sparep; 1.570 + stream->sparep = NIL; 1.571 + test->sequence = stream->sequence; 1.572 + mail_close ((MAILSTREAM *) /* flush resources used by dummy stream */ 1.573 + memcpy (fs_get (sizeof (MAILSTREAM)),stream, 1.574 + sizeof (MAILSTREAM))); 1.575 + /* swap the streams */ 1.576 + memcpy (stream,test,sizeof (MAILSTREAM)); 1.577 + fs_give ((void **) &test);/* flush test now that copied */ 1.578 + /* make sure application knows */ 1.579 + mail_exists (stream,stream->recent = stream->nmsgs); 1.580 + } 1.581 + /* still hasn't changed */ 1.582 + else stream->gensym = (unsigned long) time (0); 1.583 + } 1.584 + return T; 1.585 +} 1.586 + 1.587 + 1.588 +/* Dummy check mailbox 1.589 + * Accepts: MAIL stream 1.590 + * No-op for readonly files, since read/writer can expunge it from under us! 1.591 + */ 1.592 + 1.593 +void dummy_check (MAILSTREAM *stream) 1.594 +{ 1.595 + dummy_ping (stream); /* invoke ping */ 1.596 +} 1.597 + 1.598 + 1.599 +/* Dummy expunge mailbox 1.600 + * Accepts: MAIL stream 1.601 + * sequence to expunge if non-NIL 1.602 + * expunge options 1.603 + * Returns: T, always 1.604 + */ 1.605 + 1.606 +long dummy_expunge (MAILSTREAM *stream,char *sequence,long options) 1.607 +{ 1.608 + return LONGT; 1.609 +} 1.610 + 1.611 +/* Dummy copy message(s) 1.612 + * Accepts: MAIL stream 1.613 + * sequence 1.614 + * destination mailbox 1.615 + * options 1.616 + * Returns: T if copy successful, else NIL 1.617 + */ 1.618 + 1.619 +long dummy_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options) 1.620 +{ 1.621 + if ((options & CP_UID) ? mail_uid_sequence (stream,sequence) : 1.622 + mail_sequence (stream,sequence)) fatal ("Impossible dummy_copy"); 1.623 + return NIL; 1.624 +} 1.625 + 1.626 + 1.627 +/* Dummy append message string 1.628 + * Accepts: mail stream 1.629 + * destination mailbox 1.630 + * append callback function 1.631 + * data for callback 1.632 + * Returns: T on success, NIL on failure 1.633 + */ 1.634 + 1.635 +long dummy_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data) 1.636 +{ 1.637 + struct stat sbuf; 1.638 + int fd = -1; 1.639 + int e; 1.640 + char tmp[MAILTMPLEN]; 1.641 + MAILSTREAM *ts = default_proto (T); 1.642 + if (compare_cstring (mailbox,"INBOX") && dummy_file (tmp,mailbox) && 1.643 + ((fd = open (tmp,O_RDONLY,NIL)) < 0)) { 1.644 + if ((e = errno) == ENOENT) /* failed, was it no such file? */ 1.645 + mm_notify (stream,"[TRYCREATE] Must create mailbox before append", 1.646 + (long) NIL); 1.647 + sprintf (tmp,"%.80s: %.80s",strerror (e),mailbox); 1.648 + mm_log (tmp,ERROR); /* pass up error */ 1.649 + return NIL; /* always fails */ 1.650 + } 1.651 + if (fd >= 0) { /* found file? */ 1.652 + fstat (fd,&sbuf); /* get its size */ 1.653 + close (fd); /* toss out the fd */ 1.654 + if (sbuf.st_size) ts = NIL; /* non-empty file? */ 1.655 + } 1.656 + if (ts) return (*ts->dtb->append) (stream,mailbox,af,data); 1.657 + sprintf (tmp,"Indeterminate mailbox format: %.80s",mailbox); 1.658 + mm_log (tmp,ERROR); 1.659 + return NIL; 1.660 +} 1.661 + 1.662 +/* Dummy mail generate file string 1.663 + * Accepts: temporary buffer to write into 1.664 + * mailbox name string 1.665 + * Returns: local file string or NIL if failure 1.666 + */ 1.667 + 1.668 +char *dummy_file (char *dst,char *name) 1.669 +{ 1.670 + char *s = mailboxfile (dst,name); 1.671 + /* return our standard inbox */ 1.672 + return (s && !*s) ? strcpy (dst,sysinbox ()) : s; 1.673 +} 1.674 + 1.675 + 1.676 +/* Dummy canonicalize name 1.677 + * Accepts: buffer to write name 1.678 + * reference 1.679 + * pattern 1.680 + * Returns: T if success, NIL if failure 1.681 + */ 1.682 + 1.683 +long dummy_canonicalize (char *tmp,char *ref,char *pat) 1.684 +{ 1.685 + unsigned long i; 1.686 + char *s,dev[4]; 1.687 + /* initially no device */ 1.688 + dev[0] = dev[1] = dev[2] = dev[3] = '\0'; 1.689 + if (ref) switch (*ref) { /* preliminary reference check */ 1.690 + case '{': /* remote names not allowed */ 1.691 + return NIL; /* disallowed */ 1.692 + case '\0': /* empty reference string */ 1.693 + break; 1.694 + default: /* all other names */ 1.695 + if (ref[1] == ':') { /* start with device name? */ 1.696 + dev[0] = *ref++; dev[1] = *ref++; 1.697 + } 1.698 + break; 1.699 + } 1.700 + if (pat[1] == ':') { /* device name in pattern? */ 1.701 + dev[0] = *pat++; dev[1] = *pat++; 1.702 + ref = NIL; /* ignore reference */ 1.703 + } 1.704 + switch (*pat) { 1.705 + case '#': /* namespace names */ 1.706 + if (mailboxfile (tmp,pat)) strcpy (tmp,pat); 1.707 + else return NIL; /* unknown namespace */ 1.708 + break; 1.709 + case '{': /* remote names not allowed */ 1.710 + return NIL; 1.711 + case '\\': /* rooted name */ 1.712 + ref = NIL; /* ignore reference */ 1.713 + break; 1.714 + } 1.715 + /* make sure device names are rooted */ 1.716 + if (dev[0] && (*(ref ? ref : pat) != '\\')) dev[2] = '\\'; 1.717 + /* build name */ 1.718 + sprintf (tmp,"%s%s%s",dev,ref ? ref : "",pat); 1.719 + ucase (tmp); /* force upper case */ 1.720 + /* count wildcards */ 1.721 + for (i = 0, s = tmp; *s; *s++) if ((*s == '*') || (*s == '%')) ++i; 1.722 + if (i > MAXWILDCARDS) { /* ridiculous wildcarding? */ 1.723 + MM_LOG ("Excessive wildcards in LIST/LSUB",ERROR); 1.724 + return NIL; 1.725 + } 1.726 + return T; 1.727 +}