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