⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tenex.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 4 页
字号:
/* ======================================================================== * Copyright 1988-2007 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * *  * ======================================================================== *//* * Program:	Tenex mail routines * * Author:	Mark Crispin *		Networks and Distributed Computing *		Computing & Communications *		University of Washington *		Administration Building, AG-44 *		Seattle, WA  98195 *		Internet: MRC@CAC.Washington.EDU * * Date:	22 May 1990 * Last Edited:	11 October 2007 *//*				FILE TIME SEMANTICS * * The atime is the last read time of the file. * The mtime is the last flags update time of the file. * The ctime is the last write time of the file. * *				TEXT SIZE SEMANTICS * * Most of the text sizes are in internal (LF-only) form, except for the * msg.text size.  Beware. */#include <stdio.h>#include <ctype.h>#include <errno.h>extern int errno;		/* just in case */#include "mail.h"#include "osdep.h"#include <sys/stat.h>#include "misc.h"#include "dummy.h"/* TENEX I/O stream local data */	typedef struct tenex_local {  unsigned int shouldcheck: 1;	/* if ping should do a check instead */  unsigned int mustcheck: 1;	/* if ping must do a check instead */  int fd;			/* file descriptor for I/O */  off_t filesize;		/* file size parsed */  time_t filetime;		/* last file time */  time_t lastsnarf;		/* local snarf time */  unsigned char *buf;		/* temporary buffer */  unsigned long buflen;		/* current size of temporary buffer */  unsigned long uid;		/* current text uid */  SIZEDTEXT text;		/* current text */} TENEXLOCAL;/* Convenient access to local data */#define LOCAL ((TENEXLOCAL *) stream->local)/* Function prototypes */DRIVER *tenex_valid (char *name);int tenex_isvalid (char *name,char *tmp);void *tenex_parameters (long function,void *value);void tenex_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);void tenex_list (MAILSTREAM *stream,char *ref,char *pat);void tenex_lsub (MAILSTREAM *stream,char *ref,char *pat);long tenex_create (MAILSTREAM *stream,char *mailbox);long tenex_delete (MAILSTREAM *stream,char *mailbox);long tenex_rename (MAILSTREAM *stream,char *old,char *newname);long tenex_status (MAILSTREAM *stream,char *mbx,long flags);MAILSTREAM *tenex_open (MAILSTREAM *stream);void tenex_close (MAILSTREAM *stream,long options);void tenex_fast (MAILSTREAM *stream,char *sequence,long flags);void tenex_flags (MAILSTREAM *stream,char *sequence,long flags);char *tenex_header (MAILSTREAM *stream,unsigned long msgno,		    unsigned long *length,long flags);long tenex_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);void tenex_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags);void tenex_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt);long tenex_ping (MAILSTREAM *stream);void tenex_check (MAILSTREAM *stream);void tenex_snarf (MAILSTREAM *stream);long tenex_expunge (MAILSTREAM *stream,char *sequence,long options);long tenex_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);long tenex_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);unsigned long tenex_size (MAILSTREAM *stream,unsigned long m);char *tenex_file (char *dst,char *name);long tenex_parse (MAILSTREAM *stream);MESSAGECACHE *tenex_elt (MAILSTREAM *stream,unsigned long msgno);void tenex_read_flags (MAILSTREAM *stream,MESSAGECACHE *elt);void tenex_update_status (MAILSTREAM *stream,unsigned long msgno,			  long syncflag);unsigned long tenex_hdrpos (MAILSTREAM *stream,unsigned long msgno,			    unsigned long *size);/* Tenex mail routines *//* Driver dispatch used by MAIL */DRIVER tenexdriver = {  "tenex",			/* driver name */  DR_LOCAL|DR_MAIL|DR_NOSTICKY|DR_LOCKING,				/* driver flags */  (DRIVER *) NIL,		/* next driver */  tenex_valid,			/* mailbox is valid for us */  tenex_parameters,		/* manipulate parameters */  tenex_scan,			/* scan mailboxes */  tenex_list,			/* list mailboxes */  tenex_lsub,			/* list subscribed mailboxes */  NIL,				/* subscribe to mailbox */  NIL,				/* unsubscribe from mailbox */  dummy_create,			/* create mailbox */  tenex_delete,			/* delete mailbox */  tenex_rename,			/* rename mailbox */  tenex_status,			/* status of mailbox */  tenex_open,			/* open mailbox */  tenex_close,			/* close mailbox */  tenex_fast,			/* fetch message "fast" attributes */  tenex_flags,			/* fetch message flags */  NIL,				/* fetch overview */  NIL,				/* fetch message envelopes */  tenex_header,			/* fetch message header */  tenex_text,			/* fetch message body */  NIL,				/* fetch partial message text */  NIL,				/* unique identifier */  NIL,				/* message number */  tenex_flag,			/* modify flags */  tenex_flagmsg,		/* per-message modify flags */  NIL,				/* search for message based on criteria */  NIL,				/* sort messages */  NIL,				/* thread messages */  tenex_ping,			/* ping mailbox to see if still alive */  tenex_check,			/* check for new messages */  tenex_expunge,		/* expunge deleted messages */  tenex_copy,			/* copy messages to another mailbox */  tenex_append,			/* append string message to mailbox */  NIL				/* garbage collect stream */};				/* prototype stream */MAILSTREAM tenexproto = {&tenexdriver};/* Tenex mail validate mailbox * Accepts: mailbox name * Returns: our driver if name is valid, NIL otherwise */DRIVER *tenex_valid (char *name){  char tmp[MAILTMPLEN];  return tenex_isvalid (name,tmp) ? &tenexdriver : NIL;}/* Tenex mail test for valid mailbox * Accepts: mailbox name * Returns: T if valid, NIL otherwise */int tenex_isvalid (char *name,char *tmp){  int fd;  int ret = NIL;  char *s,file[MAILTMPLEN];  struct stat sbuf;  time_t tp[2];  errno = EINVAL;		/* assume invalid argument */				/* if file, get its status */  if ((s = tenex_file (file,name)) && !stat (s,&sbuf)) {    if (!sbuf.st_size) {	/* allow empty file if INBOX */      if ((s = mailboxfile (tmp,name)) && !*s) ret = T;      else errno = 0;		/* empty file */    }    else if ((fd = open (file,O_RDONLY,NIL)) >= 0) {      memset (tmp,'\0',MAILTMPLEN);      if ((read (fd,tmp,64) >= 0) && (s = strchr (tmp,'\012')) &&	  (s[-1] != '\015')) {	/* valid format? */	*s = '\0';		/* tie off header */				/* must begin with dd-mmm-yy" */	ret = (((tmp[2] == '-' && tmp[6] == '-') ||		(tmp[1] == '-' && tmp[5] == '-')) &&	       (s = strchr (tmp+18,',')) && strchr (s+2,';')) ? T : NIL;      }      else errno = -1;		/* bogus format */      close (fd);		/* close the file */				/* \Marked status? */      if (sbuf.st_ctime > sbuf.st_atime) {	tp[0] = sbuf.st_atime;	/* preserve atime and mtime */	tp[1] = sbuf.st_mtime;	utime (file,tp);	/* set the times */      }    }  }				/* in case INBOX but not tenex format */  else if ((errno == ENOENT) && !compare_cstring (name,"INBOX")) errno = -1;  return ret;			/* return what we should */}/* Tenex manipulate driver parameters * Accepts: function code *	    function-dependent value * Returns: function-dependent return value */void *tenex_parameters (long function,void *value){  void *ret = NIL;  switch ((int) function) {  case GET_INBOXPATH:    if (value) ret = tenex_file ((char *) value,"INBOX");    break;  }  return ret;}/* Tenex mail scan mailboxes * Accepts: mail stream *	    reference *	    pattern to search *	    string to scan */void tenex_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents){  if (stream) dummy_scan (NIL,ref,pat,contents);}/* Tenex mail list mailboxes * Accepts: mail stream *	    reference *	    pattern to search */void tenex_list (MAILSTREAM *stream,char *ref,char *pat){  if (stream) dummy_list (NIL,ref,pat);}/* Tenex mail list subscribed mailboxes * Accepts: mail stream *	    reference *	    pattern to search */void tenex_lsub (MAILSTREAM *stream,char *ref,char *pat){  if (stream) dummy_lsub (NIL,ref,pat);}/* Tenex mail delete mailbox * Accepts: MAIL stream *	    mailbox name to delete * Returns: T on success, NIL on failure */long tenex_delete (MAILSTREAM *stream,char *mailbox){  return tenex_rename (stream,mailbox,NIL);}/* Tenex mail rename mailbox * Accepts: MAIL stream *	    old mailbox name *	    new mailbox name (or NIL for delete) * Returns: T on success, NIL on failure */long tenex_rename (MAILSTREAM *stream,char *old,char *newname){  long ret = T;  char c,*s,tmp[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN];  int fd,ld;  struct stat sbuf;  if (!tenex_file (file,old) ||      (newname && (!((s = mailboxfile (tmp,newname)) && *s) ||		   ((s = strrchr (tmp,'/')) && !s[1])))) {    sprintf (tmp,newname ?	     "Can't rename mailbox %.80s to %.80s: invalid name" :	     "Can't delete mailbox %.80s: invalid name",	     old,newname);    MM_LOG (tmp,ERROR);    return NIL;  }  else if ((fd = open (file,O_RDWR,NIL)) < 0) {    sprintf (tmp,"Can't open mailbox %.80s: %s",old,strerror (errno));    MM_LOG (tmp,ERROR);    return NIL;  }				/* get exclusive parse/append permission */  if ((ld = lockfd (fd,lock,LOCK_EX)) < 0) {    MM_LOG ("Unable to lock rename mailbox",ERROR);    return NIL;  }				/* lock out other users */  if (flock (fd,LOCK_EX|LOCK_NB)) {    close (fd);			/* couldn't lock, give up on it then */    sprintf (tmp,"Mailbox %.80s is in use by another process",old);    MM_LOG (tmp,ERROR);    unlockfd (ld,lock);		/* release exclusive parse/append permission */    return NIL;  }  if (newname) {		/* want rename? */    if (s = strrchr (tmp,'/')) {/* found superior to destination name? */      c = *++s;			/* remember first character of inferior */      *s = '\0';		/* tie off to get just superior */				/* name doesn't exist, create it */      if ((stat (tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&	  !dummy_create_path (stream,tmp,get_dir_protection (newname)))	ret = NIL;      else *s = c;		/* restore full name */    }				/* rename the file */    if (ret && rename (file,tmp)) {      sprintf (tmp,"Can't rename mailbox %.80s to %.80s: %s",old,newname,	       strerror (errno));      MM_LOG (tmp,ERROR);      ret = NIL;		/* set failure */    }  }  else if (unlink (file)) {    sprintf (tmp,"Can't delete mailbox %.80s: %s",old,strerror (errno));    MM_LOG (tmp,ERROR);    ret = NIL;			/* set failure */  }  flock (fd,LOCK_UN);		/* release lock on the file */  close (fd);			/* close the file */  unlockfd (ld,lock);		/* release exclusive parse/append permission */				/* recreate file if renamed INBOX */  if (ret && !compare_cstring (old,"INBOX")) dummy_create (NIL,"mail.txt");  return ret;			/* return success */}/* Tenex Mail status * Accepts: mail stream *	    mailbox name *	    status flags * Returns: T on success, NIL on failure */long tenex_status (MAILSTREAM *stream,char *mbx,long flags){  MAILSTATUS status;  unsigned long i;  MAILSTREAM *tstream = NIL;  MAILSTREAM *systream = NIL;				/* make temporary stream (unless this mbx) */  if (!stream && !(stream = tstream =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -