📄 unixnt.c
字号:
sprintf (tmp,"Mailbox %.80s is in use by another process",old); } /* lock out non c-client applications */ else if ((fd = unix_lock (file,O_BINARY|O_RDWR,S_IREAD|S_IWRITE,lockx, LOCK_EX)) < 0) sprintf (tmp,"Can't lock mailbox %.80s: %s",old,strerror (errno)); else { unix_unlock(fd,NIL,lockx);/* pacify evil NTFS */ if (newname) { /* want rename? */ /* found superior to destination name? */ if ((s = strrchr (tmp,'\\')) && (s != tmp) && ((tmp[1] != ':') || (s != tmp + 2))) { c = s[1]; /* remember character after delimiter */ *s = s[1] = '\0'; /* tie off name at delimiter */ /* name doesn't exist, create it */ if (stat (tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) { *s = '\\'; /* restore delimiter */ if (!dummy_create (stream,newname)) { flock (ld,LOCK_UN); close (ld); /* close c-client lock */ unlink (lock); /* and delete it */ mm_nocritical (stream); return NIL; /* couldn't create superior */ } } else *s = '\\'; /* restore delimiter */ s[1] = c; /* restore character after delimiter */ } if (rename (file,tmp)) sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %s",old,newname, strerror (errno)); else ret = T; /* set success */ } else if (unlink (file)) /* want delete */ sprintf (tmp,"Can't delete mailbox %.80s: %s",old,strerror (errno)); else ret = T; /* set success */ flock (ld,LOCK_UN); /* release c-client lock */ close (ld); /* close c-client lock */ unlink (lock); /* and delete it */ } } mm_nocritical (stream); /* no longer critical */ if (!ret) mm_log (tmp,ERROR); /* log error */ return ret; /* return success or failure */}/* UNIX mail open * Accepts: Stream to open * Returns: Stream on success, NIL on failure */MAILSTREAM *unix_open (MAILSTREAM *stream){ int fd; char tmp[MAILTMPLEN]; /* return prototype for OP_PROTOTYPE call */ if (!stream) return &unixproto; if (stream->local) fatal ("unix recycle stream"); stream->local = memset (fs_get (sizeof (UNIXLOCAL)),0,sizeof (UNIXLOCAL)); /* note if an INBOX or not */ stream->inbox = !compare_cstring (stream->mailbox,"INBOX"); /* canonicalize the stream mailbox name */ if (!dummy_file (tmp,stream->mailbox)) { sprintf (tmp,"Can't open - invalid name: %.80s",stream->mailbox); mm_log (tmp,ERROR); return NIL; } /* flush old name */ fs_give ((void **) &stream->mailbox); /* save canonical name */ stream->mailbox = cpystr (tmp); LOCAL->fd = LOCAL->ld = -1; /* no file or state locking yet */ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = CHUNKSIZE) + 1); LOCAL->text.data = (unsigned char *) fs_get (CHUNKSIZE); LOCAL->text.size = CHUNKSIZE - 1; LOCAL->linebuf = (char *) fs_get (CHUNKSIZE); LOCAL->linebuflen = CHUNKSIZE - 1; stream->sequence++; /* bump sequence number */ if (!stream->rdonly) { /* make lock for read/write access */ if ((fd = lockname (tmp,stream->mailbox,NIL)) < 0) mm_log ("Can't open mailbox lock, access is readonly",WARN); /* can get the lock? */ else if (flock (fd,LOCK_EX|LOCK_NB)) { if (!stream->silent) mm_log ("Mailbox is open by another process, access is readonly",WARN); close (fd); } else { /* got the lock, nobody else can alter state */ LOCAL->ld = fd; /* note lock's fd and name */ LOCAL->lname = cpystr (tmp); } } /* parse mailbox */ stream->nmsgs = stream->recent = 0; /* will we be able to get write access? */ if ((LOCAL->ld >= 0) && access (stream->mailbox,02) && (errno == EACCES)) { mm_log ("Can't get write access to mailbox, access is readonly",WARN); flock (LOCAL->ld,LOCK_UN); /* release the lock */ close (LOCAL->ld); /* close the lock file */ LOCAL->ld = -1; /* no more lock fd */ unlink (LOCAL->lname); /* delete it */ } /* reset UID validity */ stream->uid_validity = stream->uid_last = 0; if (stream->silent && !stream->rdonly && (LOCAL->ld < 0)) unix_abort (stream); /* abort if can't get RW silent stream */ /* parse mailbox */ else if (unix_parse (stream,tmp,LOCK_SH)) { unix_unlock (LOCAL->fd,stream,tmp); mail_unlock (stream); mm_nocritical (stream); /* done with critical */ } if (!LOCAL) return NIL; /* failure if stream died */ /* make sure upper level knows readonly */ stream->rdonly = (LOCAL->ld < 0); /* notify about empty mailbox */ if (!(stream->nmsgs || stream->silent)) mm_log ("Mailbox is empty",NIL); if (!stream->rdonly) { /* flags stick if readwrite */ stream->perm_seen = stream->perm_deleted = stream->perm_flagged = stream->perm_answered = stream->perm_draft = T; /* have permanent keywords */ stream->perm_user_flags = 0xffffffff; /* and maybe can create them too */ stream->kwd_create = stream->user_flags[NUSERFLAGS-1] ? NIL : T; } return stream; /* return stream alive to caller */}/* UNIX mail close * Accepts: MAIL stream * close options */void unix_close (MAILSTREAM *stream,long options){ int silent = stream->silent; stream->silent = T; /* go silent */ /* expunge if requested */ if (options & CL_EXPUNGE) unix_expunge (stream,NIL,NIL); /* else dump final checkpoint */ else if (LOCAL->dirty) unix_check (stream); stream->silent = silent; /* restore old silence state */ unix_abort (stream); /* now punt the file and local data */}/* UNIX mail fetch message header * Accepts: MAIL stream * message # to fetch * pointer to returned header text length * option flags * Returns: message header in RFC822 format */ /* lines to filter from header */static STRINGLIST *unix_hlines = NIL;char *unix_header (MAILSTREAM *stream,unsigned long msgno, unsigned long *length,long flags){ MESSAGECACHE *elt; unsigned char *s; *length = 0; /* default to empty */ if (flags & FT_UID) return "";/* UID call "impossible" */ elt = mail_elt (stream,msgno);/* get cache */ if (!unix_hlines) { /* once only code */ STRINGLIST *lines = unix_hlines = mail_newstringlist (); lines->text.size = strlen ((char *) (lines->text.data = (unsigned char *) "Status")); lines = lines->next = mail_newstringlist (); lines->text.size = strlen ((char *) (lines->text.data = (unsigned char *) "X-Status")); lines = lines->next = mail_newstringlist (); lines->text.size = strlen ((char *) (lines->text.data = (unsigned char *) "X-Keywords")); lines = lines->next = mail_newstringlist (); lines->text.size = strlen ((char *) (lines->text.data = (unsigned char *) "X-UID")); lines = lines->next = mail_newstringlist (); lines->text.size = strlen ((char *) (lines->text.data = (unsigned char *) "X-IMAP")); lines = lines->next = mail_newstringlist (); lines->text.size = strlen ((char *) (lines->text.data = (unsigned char *) "X-IMAPbase")); } /* go to header position */ lseek (LOCAL->fd,elt->private.special.offset + elt->private.msg.header.offset,L_SET); if (flags & FT_INTERNAL) { /* initial data OK? */ if (elt->private.msg.header.text.size > LOCAL->buflen) { fs_give ((void **) &LOCAL->buf); LOCAL->buf = (char *) fs_get ((LOCAL->buflen = elt->private.msg.header.text.size) + 1); } /* read message */ read (LOCAL->fd,LOCAL->buf,elt->private.msg.header.text.size); /* got text, tie off string */ LOCAL->buf[*length = elt->private.msg.header.text.size] = '\0'; } else { /* need to make a CRLF version */ read (LOCAL->fd,s = (char *) fs_get (elt->private.msg.header.text.size+1), elt->private.msg.header.text.size); /* tie off string, and convert to CRLF */ s[elt->private.msg.header.text.size] = '\0'; *length = unix_crlfcpy (&LOCAL->buf,&LOCAL->buflen,s, elt->private.msg.header.text.size); fs_give ((void **) &s); /* free readin buffer */ } *length = mail_filter (LOCAL->buf,*length,unix_hlines,FT_NOT); return LOCAL->buf; /* return processed copy */}/* UNIX mail fetch message text * Accepts: MAIL stream * message # to fetch * pointer to returned stringstruct * option flags * Returns: T on success, NIL if failure */long unix_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags){ char *s; unsigned long i; MESSAGECACHE *elt; /* UID call "impossible" */ if (flags & FT_UID) return NIL; elt = mail_elt (stream,msgno);/* get cache element */ /* if message not seen */ if (!(flags & FT_PEEK) && !elt->seen) { /* mark message seen and dirty */ elt->seen = elt->private.dirty = LOCAL->dirty = T; mm_flags (stream,msgno); } s = unix_text_work (stream,elt,&i,flags); INIT (bs,mail_string,s,i); /* set up stringstruct */ return T; /* success */}/* UNIX mail fetch message text worker routine * Accepts: MAIL stream * message cache element * pointer to returned header text length * option flags */char *unix_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, unsigned long *length,long flags){ FDDATA d; STRING bs; unsigned char c,*s,tmp[CHUNKSIZE]; /* go to text position */ lseek (LOCAL->fd,elt->private.special.offset + elt->private.msg.text.offset,L_SET); if (flags & FT_INTERNAL) { /* initial data OK? */ if (elt->private.msg.text.text.size > LOCAL->buflen) { fs_give ((void **) &LOCAL->buf); LOCAL->buf = (char *) fs_get ((LOCAL->buflen = elt->private.msg.text.text.size) + 1); } /* read message */ read (LOCAL->fd,LOCAL->buf,elt->private.msg.text.text.size); /* got text, tie off string */ LOCAL->buf[*length = elt->private.msg.text.text.size] = '\0'; return LOCAL->buf; } /* have it cached already? */ if (elt->private.uid != LOCAL->uid) { /* not cached, cache it now */ LOCAL->uid = elt->private.uid; /* is buffer big enough? */ if (elt->rfc822_size > LOCAL->text.size) { /* excessively conservative, but the right thing is too hard to do */ fs_give ((void **) &LOCAL->text.data); LOCAL->text.data = (unsigned char *) fs_get ((LOCAL->text.size = elt->rfc822_size) + 1); } d.fd = LOCAL->fd; /* yes, set up file descriptor */ d.pos = elt->private.special.offset + elt->private.msg.text.offset; d.chunk = tmp; /* initial buffer chunk */ d.chunksize = CHUNKSIZE; /* file chunk size */ INIT (&bs,fd_string,&d,elt->private.msg.text.text.size); for (s = (char *) LOCAL->text.data; SIZE (&bs);) switch (c = SNX (&bs)) { case '\r': /* carriage return seen */ *s++ = c; /* copy it and any succeeding LF */ if (SIZE (&bs) && (CHR (&bs) == '\n')) *s++ = SNX (&bs); break; case '\n': *s++ = '\r'; /* insert a CR */ default: *s++ = c; /* copy characters */ } *s = '\0'; /* tie off buffer */ /* calculate length of cached data */ LOCAL->textlen = s - LOCAL->text.data; } *length = LOCAL->textlen; /* return from cache */ return (char *) LOCAL->text.data;}/* UNIX per-message modify flag * Accepts: MAIL stream * message cache element */void unix_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt){ /* only after finishing */ if (elt->valid) elt->private.dirty = LOCAL->dirty = T;}/* UNIX mail ping mailbox * Accepts: MAIL stream * Returns: T if stream alive, else NIL */long unix_ping (MAILSTREAM *stream){ char lock[MAILTMPLEN]; struct stat sbuf; /* big no-op if not readwrite */ if (LOCAL && (LOCAL->ld >= 0) && !stream->lock) { if (stream->rdonly) { /* does he want to give up readwrite? */ /* checkpoint if we changed something */ if (LOCAL->dirty) unix_check (stream); flock (LOCAL->ld,LOCK_UN);/* release readwrite lock */ close (LOCAL->ld); /* close the readwrite lock file */ LOCAL->ld = -1; /* no more readwrite lock fd */ unlink (LOCAL->lname); /* delete the readwrite lock file */ } else { /* get current mailbox size */ if (LOCAL->fd >= 0) fstat (LOCAL->fd,&sbuf); else if (stat (stream->mailbox,&sbuf)) { sprintf (LOCAL->buf,"Mailbox stat failed, aborted: %s", strerror (errno)); MM_LOG (LOCAL->buf,ERROR); unix_abort (stream); return NIL; } /* parse if mailbox changed */ if ((LOCAL->ddirty || (sbuf.st_size != LOCAL->filesize)) && unix_parse (stream,lock,LOCK_EX)) { /* force checkpoint if double-dirty */ if (LOCAL->ddirty) unix_rewrite (stream,NIL,lock,NIL); /* unlock mailbox */ else unix_unlock (LOCAL->fd,stream,lock); mail_unlock (stream); /* and stream */ mm_nocritical (stream); /* done with critical */ } } } return LOCAL ? LONGT : NIL; /* return if still alive */}/* UNIX mail check mailbox * Accepts: MAIL stream */void unix_check (MAILSTREAM *stream){ char lock[MAILTMPLEN]; /* parse and lock mailbox */ if (LOCAL && (LOCAL->ld >= 0) && !stream->lock && unix_parse (stream,lock,LOCK_EX)) { /* any unsaved changes? */ if (LOCAL->dirty && unix_rewrite (stream,NIL,lock,NIL)) { if (!stream->silent) mm_log ("Checkpoint completed",NIL); } /* no checkpoint needed, just unlock */ else unix_unlock (LOCAL->fd,stream,lock); mail_unlock (stream); /* unlock the stream */ mm_nocritical (stream); /* done with critical */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -