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

📄 mh.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 3 页
字号:
			   get_dir_protection ("INBOX"))) return T;    sprintf (tmp,"Can't open mailbox %.80s: no such mailbox",stream->mailbox);    mm_log (tmp,ERROR);    return NIL;  }  stream->silent = T;		/* don't pass up mm_exists() events yet */  if (sbuf.st_ctime != LOCAL->scantime) {    struct direct **names = NIL;    long nfiles = scandir (LOCAL->dir,&names,mh_select,mh_numsort);    if (nfiles < 0) nfiles = 0;	/* in case error */				/* note scanned now */    LOCAL->scantime = sbuf.st_ctime;				/* scan directory */    for (i = 0; i < nfiles; ++i) {				/* if newly seen, add to list */      if ((j = atoi (names[i]->d_name)) > old) {	mail_exists (stream,++nmsgs);	stream->uid_last = (elt = mail_elt (stream,nmsgs))->private.uid = j;	elt->valid = T;		/* note valid flags */	if (old) {		/* other than the first pass? */	  elt->recent = T;	/* yup, mark as recent */	  recent++;		/* bump recent count */	}	else {			/* see if already read */	  sprintf (tmp,"%s/%s",LOCAL->dir,names[i]->d_name);	  if (!stat (tmp,&sbuf) && (sbuf.st_atime > sbuf.st_mtime))	    elt->seen = T;	}      }      fs_give ((void **) &names[i]);    }				/* free directory */    if (s = (void *) names) fs_give ((void **) &s);  }				/* if INBOX, snarf from system INBOX  */  if (stream->inbox && strcmp (sysinbox (),stream->mailbox)) {    old = stream->uid_last;    mm_critical (stream);	/* go critical */				/* see if anything in system inbox */    if (!stat (sysinbox (),&sbuf) && sbuf.st_size &&	(sysibx = mail_open (sysibx,sysinbox (),OP_SILENT)) &&	!sysibx->rdonly && (r = sysibx->nmsgs)) {      for (i = 1; i <= r; ++i) {/* for each message in sysinbox mailbox */				/* build file name we will use */	sprintf (LOCAL->buf,"%s/%lu",LOCAL->dir,++old);				/* snarf message from Berkeley mailbox */	selt = mail_elt (sysibx,i);	if (((fd = open (LOCAL->buf,O_WRONLY|O_CREAT|O_EXCL,			 (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL)))	     >= 0) &&	    (s = mail_fetchheader_full (sysibx,i,NIL,&j,FT_INTERNAL)) &&	    (write (fd,s,j) == j) &&	    (s = mail_fetchtext_full (sysibx,i,&j,FT_INTERNAL|FT_PEEK)) &&	    (write (fd,s,j) == j) && !fsync (fd) && !close (fd)) {				/* swell the cache */	  mail_exists (stream,++nmsgs);	  stream->uid_last =	/* create new elt, note its file number */	    (elt = mail_elt (stream,nmsgs))->private.uid = old;	  recent++;		/* bump recent count */				/* set up initial flags and date */	  elt->valid = elt->recent = T;	  elt->seen = selt->seen;	  elt->deleted = selt->deleted;	  elt->flagged = selt->flagged;	  elt->answered = selt->answered;	  elt->draft = selt->draft;	  elt->day = selt->day;elt->month = selt->month;elt->year = selt->year;	  elt->hours = selt->hours;elt->minutes = selt->minutes;	  elt->seconds = selt->seconds;	  elt->zhours = selt->zhours; elt->zminutes = selt->zminutes;	  elt->zoccident = selt->zoccident;	  mh_setdate (LOCAL->buf,elt);	  sprintf (tmp,"%lu",i);/* delete it from the sysinbox */	  mail_flag (sysibx,tmp,"\\Deleted",ST_SET);	}	else {			/* failed to snarf */	  if (fd) {		/* did it ever get opened? */	    close (fd);		/* close descriptor */	    unlink (LOCAL->buf);/* flush this file */	  }	  sprintf (tmp,"Message copy to MH mailbox failed: %.80s",		   s,strerror (errno));	  mm_log (tmp,ERROR);	  r = 0;		/* stop the snarf in its tracks */	}      }				/* update scan time */      if (!stat (LOCAL->dir,&sbuf)) LOCAL->scantime = sbuf.st_ctime;            mail_expunge (sysibx);	/* now expunge all those messages */    }    if (sysibx) mail_close (sysibx);    mm_nocritical (stream);	/* release critical */  }  stream->silent = silent;	/* can pass up events now */  mail_exists (stream,nmsgs);	/* notify upper level of mailbox size */  mail_recent (stream,recent);  return T;			/* return that we are alive */}/* MH mail check mailbox * Accepts: MAIL stream */void mh_check (MAILSTREAM *stream){  /* Perhaps in the future this will preserve flags */  if (mh_ping (stream)) mm_log ("Check completed",(long) NIL);}/* MH mail expunge mailbox * Accepts: MAIL stream *	    sequence to expunge if non-NIL *	    expunge options * Returns: T, always */long mh_expunge (MAILSTREAM *stream,char *sequence,long options){  long ret;  MESSAGECACHE *elt;  unsigned long i = 1;  unsigned long n = 0;  unsigned long recent = stream->recent;  if (ret = sequence ? ((options & EX_UID) ?			mail_uid_sequence (stream,sequence) :			mail_sequence (stream,sequence)) : LONGT) {    mm_critical (stream);	/* go critical */    while (i <= stream->nmsgs) {/* for each message */      elt = mail_elt (stream,i);/* if deleted, need to trash it */      if (elt->deleted && (sequence ? elt->sequence : T)) {	sprintf (LOCAL->buf,"%s/%lu",LOCAL->dir,elt->private.uid);	if (unlink (LOCAL->buf)) {/* try to delete the message */	  sprintf (LOCAL->buf,"Expunge of message %lu failed, aborted: %s",i,		   strerror (errno));	  mm_log (LOCAL->buf,(long) NIL);	  break;	}				/* note uncached */	LOCAL->cachedtexts -= ((elt->private.msg.header.text.data ?				elt->private.msg.header.text.size : 0) +			       (elt->private.msg.text.text.data ?				elt->private.msg.text.text.size : 0));	mail_gc_msg (&elt->private.msg,GC_ENV | GC_TEXTS);				/* if recent, note one less recent message */	if (elt->recent) --recent;				/* notify upper levels */	mail_expunged (stream,i);	n++;			/* count up one more expunged message */      }      else i++;			/* otherwise try next message */    }    if (n) {			/* output the news if any expunged */      sprintf (LOCAL->buf,"Expunged %lu messages",n);      mm_log (LOCAL->buf,(long) NIL);    }    else mm_log ("No messages deleted, so no update needed",(long) NIL);    mm_nocritical (stream);	/* release critical */				/* notify upper level of new mailbox size */    mail_exists (stream,stream->nmsgs);    mail_recent (stream,recent);  }  return ret;}/* MH mail copy message(s) * Accepts: MAIL stream *	    sequence *	    destination mailbox *	    copy options * Returns: T if copy successful, else NIL */long mh_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){  FDDATA d;  STRING st;  MESSAGECACHE *elt;  struct stat sbuf;  int fd;  unsigned long i;  char flags[MAILTMPLEN],date[MAILTMPLEN];  appenduid_t au = (appenduid_t) mail_parameters (NIL,GET_APPENDUID,NIL);  long ret = NIL;				/* copy the messages */  if ((options & CP_UID) ? mail_uid_sequence (stream,sequence) :      mail_sequence (stream,sequence))    for (i = 1; i <= stream->nmsgs; i++)       if ((elt = mail_elt (stream,i))->sequence) {	sprintf (LOCAL->buf,"%s/%lu",LOCAL->dir,elt->private.uid);	if ((fd = open (LOCAL->buf,O_RDONLY,NIL)) < 0) return NIL;	fstat (fd,&sbuf);	/* get size of message */	if (!elt->day) {	/* set internaldate to file date if needed */	  struct tm *tm = gmtime (&sbuf.st_mtime);	  elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1;	  elt->year = tm->tm_year + 1900 - BASEYEAR;	  elt->hours = tm->tm_hour; elt->minutes = tm->tm_min;	  elt->seconds = tm->tm_sec;	  elt->zhours = 0; elt->zminutes = 0;	}	d.fd = fd;		/* set up file descriptor */	d.pos = 0;		/* start of file */	d.chunk = LOCAL->buf;	d.chunksize = CHUNKSIZE;				/* kludge; mh_append would just strip CRs */	INIT (&st,fd_string,&d,sbuf.st_size);				/* init flag string */	flags[0] = flags[1] = '\0';	if (elt->seen) strcat (flags," \\Seen");	if (elt->deleted) strcat (flags," \\Deleted");	if (elt->flagged) strcat (flags," \\Flagged");	if (elt->answered) strcat (flags," \\Answered");	if (elt->draft) strcat (flags," \\Draft");	flags[0] = '(';		/* open list */	strcat (flags,")");	/* close list */	mail_date (date,elt);	/* generate internal date */	if (au) mail_parameters (NIL,SET_APPENDUID,NIL);	if ((ret = mail_append_full (NIL,mailbox,flags,date,&st)) &&	    (options & CP_MOVE)) elt->deleted = T;	if (au) mail_parameters (NIL,SET_APPENDUID,(void *) au);	close (fd);      }  if (ret && mail_parameters (NIL,GET_COPYUID,NIL))    mm_log ("Can not return meaningful COPYUID with this mailbox format",WARN);  return ret;			/* return success */}/* MH mail append message from stringstruct * Accepts: MAIL stream *	    destination mailbox *	    append callback *	    data for callback * Returns: T if append successful, else NIL */long mh_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){  struct direct **names = NIL;  int fd;  char c,*flags,*date,*s,tmp[MAILTMPLEN];  STRING *message;  MESSAGECACHE elt;  FILE *df;  long i,size,last,nfiles;  long ret = LONGT;				/* default stream to prototype */  if (!stream) stream = &mhproto;				/* make sure valid mailbox */  if (!mh_isvalid (mailbox,tmp,NIL)) switch (errno) {  case ENOENT:			/* no such file? */    if (!((!compare_cstring (mailbox,MHINBOX) ||	   !compare_cstring (mailbox,"INBOX")) &&	  (mh_file (tmp,MHINBOX) &&	   dummy_create_path (stream,strcat (tmp,"/"),			      get_dir_protection (mailbox))))) {      mm_notify (stream,"[TRYCREATE] Must create mailbox before append",NIL);      return NIL;    }				/* falls through */  case 0:			/* merely empty file? */    break;  case EINVAL:    sprintf (tmp,"Invalid MH-format mailbox name: %.80s",mailbox);    mm_log (tmp,ERROR);    return NIL;  default:    sprintf (tmp,"Not a MH-format mailbox: %.80s",mailbox);    mm_log (tmp,ERROR);    return NIL;  }				/* get first message */  if (!(*af) (stream,data,&flags,&date,&message)) return NIL;  if ((nfiles = scandir (tmp,&names,mh_select,mh_numsort)) > 0) {				/* largest number */    last = atoi (names[nfiles-1]->d_name);        for (i = 0; i < nfiles; ++i) /* free directory */      fs_give ((void **) &names[i]);  }  else last = 0;		/* no messages here yet */  if (s = (void *) names) fs_give ((void **) &s);  mm_critical (stream);		/* go critical */  do {    if (!SIZE (message)) {	/* guard against zero-length */      mm_log ("Append of zero-length message",ERROR);      ret = NIL;      break;    }    if (date) {			/* want to preserve date? */				/* yes, parse date into an elt */      if (!mail_parse_date (&elt,date)) {	sprintf (tmp,"Bad date in append: %.80s",date);	mm_log (tmp,ERROR);	ret = NIL;	break;      }    }    mh_file (tmp,mailbox);	/* build file name we will use */    sprintf (tmp + strlen (tmp),"/%ld",++last);    if (((fd = open (tmp,O_WRONLY|O_CREAT|O_EXCL,		     (long)mail_parameters (NIL,GET_MBXPROTECTION,NIL))) < 0)||	!(df = fdopen (fd,"ab"))) {      sprintf (tmp,"Can't open append message: %s",strerror (errno));      mm_log (tmp,ERROR);      ret = NIL;      break;    }				/* copy the data w/o CR's */    for (size = 0,i = SIZE (message); i && ret; --i)      if (((c = SNX (message)) != '\015') && (putc (c,df) == EOF)) ret = NIL;				/* close the file */    if (!ret || fclose (df)) {      unlink (tmp);		/* delete message */      sprintf (tmp,"Message append failed: %s",strerror (errno));      mm_log (tmp,ERROR);      ret = NIL;    }    if (ret) {			/* set the date for this message */      if (date) mh_setdate (tmp,&elt);				/* get next message */      if (!(*af) (stream,data,&flags,&date,&message)) ret = NIL;    }  } while (ret && message);  mm_nocritical (stream);	/* release critical */  if (ret && mail_parameters (NIL,GET_APPENDUID,NIL))    mm_log ("Can not return meaningful APPENDUID with this mailbox format",	    WARN);  return ret;}/* Internal routines *//* MH file name selection test * Accepts: candidate directory entry * Returns: T to use file name, NIL to skip it */int mh_select (struct direct *name){  char c;  char *s = name->d_name;  while (c = *s++) if (!isdigit (c)) return NIL;  return T;}/* MH file name comparision * Accepts: first candidate directory entry *	    second candidate directory entry * Returns: negative if d1 < d2, 0 if d1 == d2, postive if d1 > d2 */int mh_numsort (const void *d1,const void *d2){  return atoi ((*(struct direct **) d1)->d_name) -    atoi ((*(struct direct **) d2)->d_name);}/* MH mail build file name * Accepts: destination string *          source * Returns: destination */char *mh_file (char *dst,char *name){  char *s;  char *path = mh_path (dst);  if (!path) fatal ("No mh path in mh_file()!");				/* INBOX becomes "inbox" in the MH path */  if (!compare_cstring (name,MHINBOX) || !compare_cstring (name,"INBOX"))    sprintf (dst,"%.900s/%.80s",path,MHINBOXDIR);				/* #mh names skip past prefix */  else if (*name == '#') sprintf (dst,"%.100s/%.900s",path,name + 4);  else mailboxfile (dst,name);	/* all other names */				/* tie off unnecessary trailing / */  if ((s = strrchr (dst,'/')) && !s[1] && (s[-1] == '/')) *s = '\0';  return dst;}/* MH canonicalize name * Accepts: buffer to write name *	    reference *	    pattern * Returns: T if success, NIL if failure */long mh_canonicalize (char *pattern,char *ref,char *pat){  unsigned long i;  char *s,tmp[MAILTMPLEN];  if (ref && *ref) {		/* have a reference */    strcpy (pattern,ref);	/* copy reference to pattern */				/* # overrides mailbox field in reference */    if (*pat == '#') strcpy (pattern,pat);				/* pattern starts, reference ends, with / */    else if ((*pat == '/') && (pattern[strlen (pattern) - 1] == '/'))      strcat (pattern,pat + 1);	/* append, omitting one of the period */    else strcat (pattern,pat);	/* anything else is just appended */  }  else strcpy (pattern,pat);	/* just have basic name */  if (mh_isvalid (pattern,tmp,T)) {				/* count wildcards */    for (i = 0, s = pattern; *s; *s++) if ((*s == '*') || (*s == '%')) ++i;				/* success if not too many */    if (i <= MAXWILDCARDS) return LONGT;    mm_log ("Excessive wildcards in LIST/LSUB",ERROR);  }  return NIL;}/* Set date for message * Accepts: file name *	    elt containing date */void mh_setdate (char *file,MESSAGECACHE *elt){  time_t tp[2];  tp[0] = time (0);		/* atime is now */  tp[1] = mail_longdate (elt);	/* modification time */  utime (file,tp);		/* set the times */}

⌨️ 快捷键说明

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