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