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

📄 tenex.c

📁 这是用C编写IMAP源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
 * Accepts: MAIL stream */void tenex_check (MAILSTREAM *stream){				/* mark that a check is desired */  if (LOCAL) LOCAL->mustcheck = T;  if (tenex_ping (stream)) MM_LOG ("Check completed",(long) NIL);}/* Tenex mail snarf messages from system inbox * Accepts: MAIL stream */void tenex_snarf (MAILSTREAM *stream){  unsigned long i = 0;  unsigned long j,r,hdrlen,txtlen;  struct stat sbuf;  char *hdr,*txt,lock[MAILTMPLEN],tmp[MAILTMPLEN];  MESSAGECACHE *elt;  MAILSTREAM *sysibx = NIL;  int ld;				/* give up if can't get exclusive permission */  if ((time (0) >= (LOCAL->lastsnarf +		    (long) mail_parameters (NIL,GET_SNARFINTERVAL,NIL))) &&      strcmp (sysinbox (),stream->mailbox) &&      ((ld = lockfd (LOCAL->fd,lock,LOCK_EX)) >= 0)) {    MM_CRITICAL (stream);	/* go critical */				/* sizes match and anything in sysinbox? */    if (!stat (sysinbox (),&sbuf) && sbuf.st_size &&	!fstat (LOCAL->fd,&sbuf) && (sbuf.st_size == LOCAL->filesize) && 	(sysibx = mail_open (sysibx,sysinbox (),OP_SILENT)) &&	(!sysibx->rdonly) && (r = sysibx->nmsgs)) {				/* yes, go to end of file in our mailbox */      lseek (LOCAL->fd,sbuf.st_size,L_SET);				/* for each message in sysibx mailbox */      while (r && (++i <= sysibx->nmsgs)) {				/* snarf message from system INBOX */	hdr = cpystr (mail_fetchheader_full(sysibx,i,NIL,&hdrlen,FT_INTERNAL));	txt = mail_fetchtext_full (sysibx,i,&txtlen,FT_INTERNAL|FT_PEEK);				/* if have a message */	if (j = hdrlen + txtlen) {				/* calculate header line */	  mail_date (LOCAL->buf,elt = mail_elt (sysibx,i));	  sprintf (LOCAL->buf + strlen (LOCAL->buf),		   ",%lu;0000000000%02o\n",j,(unsigned)		   ((fSEEN * elt->seen) + (fDELETED * elt->deleted) +		    (fFLAGGED * elt->flagged) + (fANSWERED * elt->answered) +		    (fDRAFT * elt->draft)));				/* copy message */	  if ((write (LOCAL->fd,LOCAL->buf,strlen (LOCAL->buf)) < 0) ||	      (write (LOCAL->fd,hdr,hdrlen) < 0) ||	      (write (LOCAL->fd,txt,txtlen) < 0)) r = 0;	}	fs_give ((void **) &hdr);      }				/* make sure all the updates take */      if (fsync (LOCAL->fd)) r = 0;      if (r) {			/* delete all the messages we copied */	if (r == 1) strcpy (tmp,"1");	else sprintf (tmp,"1:%lu",r);	mail_flag (sysibx,tmp,"\\Deleted",ST_SET);	mail_expunge (sysibx);	/* now expunge all those messages */      }      else {	sprintf (LOCAL->buf,"Can't copy new mail: %s",strerror (errno));	MM_LOG (LOCAL->buf,ERROR);	ftruncate (LOCAL->fd,sbuf.st_size);      }      fstat (LOCAL->fd,&sbuf);	/* yes, get current file size */      LOCAL->filetime = sbuf.st_mtime;    }    if (sysibx) mail_close (sysibx);    MM_NOCRITICAL (stream);	/* release critical */    unlockfd (ld,lock);		/* release exclusive parse/append permission */    LOCAL->lastsnarf = time (0);/* note time of last snarf */  }}/* Tenex mail expunge mailbox * Accepts: MAIL stream */void tenex_expunge (MAILSTREAM *stream){  time_t tp[2];  struct stat sbuf;  off_t pos = 0;  int ld;  unsigned long i = 1;  unsigned long j,k,m,recent;  unsigned long n = 0;  unsigned long delta = 0;  char lock[MAILTMPLEN];  MESSAGECACHE *elt;  blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);				/* do nothing if stream dead */  if (!tenex_ping (stream)) return;  if (stream->rdonly) {		/* won't do on readonly files! */    MM_LOG ("Expunge ignored on readonly mailbox",WARN);    return;  }  if (LOCAL->filetime && !LOCAL->shouldcheck) {    fstat (LOCAL->fd,&sbuf);	/* get current write time */    if (LOCAL->filetime < sbuf.st_mtime) LOCAL->shouldcheck = T;  }  /* The cretins who designed flock() created a window of vulnerability in   * upgrading locks from shared to exclusive or downgrading from exclusive   * to shared.  Rather than maintain the lock at shared status at a minimum,   * flock() actually *releases* the former lock.  Obviously they never talked   * to any database guys.  Fortunately, we have the parse/append permission   * lock.  If we require this lock before going exclusive on the mailbox,   * another process can not sneak in and steal the exclusive mailbox lock on   * us, because it will block on trying to get parse/append permission first.   */				/* get exclusive parse/append permission */  if ((ld = lockfd (LOCAL->fd,lock,LOCK_EX)) < 0) {    MM_LOG ("Unable to lock expunge mailbox",ERROR);    return;  }				/* make sure see any newly-arrived messages */  if (!tenex_parse (stream)) return;				/* get exclusive access */  if (flock (LOCAL->fd,LOCK_EX|LOCK_NB)) {    (*bn) (BLOCK_FILELOCK,NIL);    flock (LOCAL->fd,LOCK_SH);	/* recover previous lock */    (*bn) (BLOCK_NONE,NIL);    MM_LOG ("Can't expunge because mailbox is in use by another process",	      ERROR);    unlockfd (ld,lock);		/* release exclusive parse/append permission */    return;  }  MM_CRITICAL (stream);		/* go critical */  recent = stream->recent;	/* get recent now that pinged and locked */  while (i <= stream->nmsgs) {	/* for each message */    elt = tenex_elt (stream,i);	/* get cache element */				/* number of bytes to smash or preserve */    k = elt->private.special.text.size + tenex_size (stream,i);    if (elt->deleted) {		/* if deleted */      if (elt->recent) --recent;/* if recent, note one less recent message */      delta += k;		/* number of bytes to delete */      mail_expunged (stream,i);	/* notify upper levels */      n++;			/* count up one more expunged message */    }    else if (i++ && delta) {	/* preserved message */				/* first byte to preserve */      j = elt->private.special.offset;      do {			/* read from source position */	m = min (k,LOCAL->buflen);	lseek (LOCAL->fd,j,L_SET);	read (LOCAL->fd,LOCAL->buf,m);	pos = j - delta;	/* write to destination position */	lseek (LOCAL->fd,pos,L_SET);	while (T) {	  lseek (LOCAL->fd,pos,L_SET);	  if (write (LOCAL->fd,LOCAL->buf,m) > 0) break;	  MM_NOTIFY (stream,strerror (errno),WARN);	  MM_DISKERROR (stream,errno,T);	}	pos += m;		/* new position */	j += m;			/* next chunk, perhaps */      } while (k -= m);		/* until done */				/* note the new address of this text */      elt->private.special.offset -= delta;    }				/* preserved but no deleted messages */    else pos = elt->private.special.offset + k;  }  if (n) {			/* truncate file after last message */    if (pos != (LOCAL->filesize -= delta)) {      sprintf (LOCAL->buf,"Calculated size mismatch %lu != %lu, delta = %lu",	       (unsigned long) pos,(unsigned long) LOCAL->filesize,delta);      MM_LOG (LOCAL->buf,WARN);      LOCAL->filesize = pos;	/* fix it then */    }    ftruncate (LOCAL->fd,LOCAL->filesize);    sprintf (LOCAL->buf,"Expunged %lu messages",n);				/* output the news */    MM_LOG (LOCAL->buf,(long) NIL);  }  else MM_LOG ("No messages deleted, so no update needed",(long) NIL);  fsync (LOCAL->fd);		/* force disk update */  fstat (LOCAL->fd,&sbuf);	/* get new write time */  tp[1] = LOCAL->filetime = sbuf.st_mtime;  tp[0] = time (0);		/* reset atime to now */  utime (stream->mailbox,tp);  MM_NOCRITICAL (stream);	/* release critical */				/* notify upper level of new mailbox size */  mail_exists (stream,stream->nmsgs);  mail_recent (stream,recent);  (*bn) (BLOCK_FILELOCK,NIL);  flock (LOCAL->fd,LOCK_SH);	/* allow sharers again */  (*bn) (BLOCK_NONE,NIL);  unlockfd (ld,lock);		/* release exclusive parse/append permission */}/* Tenex mail copy message(s) * Accepts: MAIL stream *	    sequence *	    destination mailbox *	    copy options * Returns: T if success, NIL if failed */long tenex_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){  struct stat sbuf;  time_t tp[2];  MESSAGECACHE *elt;  unsigned long i,j,k;  long ret = LONGT;  int fd,ld;  char file[MAILTMPLEN],lock[MAILTMPLEN];  mailproxycopy_t pc =    (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL);				/* make sure valid mailbox */  if (!tenex_isvalid (mailbox,LOCAL->buf)) switch (errno) {  case ENOENT:			/* no such file? */    MM_NOTIFY (stream,"[TRYCREATE] Must create mailbox before copy",NIL);    return NIL;  case 0:			/* merely empty file? */    break;  case EINVAL:    if (pc) return (*pc) (stream,sequence,mailbox,options);    sprintf (LOCAL->buf,"Invalid Tenex-format mailbox name: %.80s",mailbox);    MM_LOG (LOCAL->buf,ERROR);    return NIL;  default:    if (pc) return (*pc) (stream,sequence,mailbox,options);    sprintf (LOCAL->buf,"Not a Tenex-format mailbox: %.80s",mailbox);    MM_LOG (LOCAL->buf,ERROR);    return NIL;  }  if (!((options & CP_UID) ? mail_uid_sequence (stream,sequence) :	mail_sequence (stream,sequence))) return NIL;				/* got file? */    if ((fd=open(tenex_file(file,mailbox),O_RDWR|O_CREAT,S_IREAD|S_IWRITE))<0) {    sprintf (LOCAL->buf,"Unable to open copy mailbox: %s",strerror (errno));    MM_LOG (LOCAL->buf,ERROR);    return NIL;  }  MM_CRITICAL (stream);		/* go critical */				/* get exclusive parse/append permission */  if ((ld = lockfd (fd,lock,LOCK_EX)) < 0) {    MM_LOG ("Unable to lock copy mailbox",ERROR);    MM_NOCRITICAL (stream);    return NIL;  }  fstat (fd,&sbuf);		/* get current file size */  lseek (fd,sbuf.st_size,L_SET);/* move to end of file */				/* for each requested message */  for (i = 1; ret && (i <= stream->nmsgs); i++)     if ((elt = mail_elt (stream,i))->sequence) {      lseek (LOCAL->fd,elt->private.special.offset,L_SET);				/* number of bytes to copy */      k = elt->private.special.text.size + tenex_size (stream,i);      do {			/* read from source position */	j = min (k,LOCAL->buflen);	read (LOCAL->fd,LOCAL->buf,j);	if (write (fd,LOCAL->buf,j) < 0) ret = NIL;      } while (ret && (k -= j));/* until done */    }				/* make sure all the updates take */  if (!(ret && (ret = !fsync (fd)))) {    sprintf (LOCAL->buf,"Unable to write message: %s",strerror (errno));    MM_LOG (LOCAL->buf,ERROR);    ftruncate (fd,sbuf.st_size);  }  if (ret) tp[0] = time (0) - 1;/* set atime to now-1 if successful copy */				/* else preserve \Marked status */  else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);  tp[1] = sbuf.st_mtime;	/* preserve mtime */  utime (file,tp);		/* set the times */  close (fd);			/* close the file */  unlockfd (ld,lock);		/* release exclusive parse/append permission */  MM_NOCRITICAL (stream);	/* release critical */				/* delete all requested messages */  if (ret && (options & CP_MOVE)) {    for (i = 1; i <= stream->nmsgs; i++)      if ((elt = tenex_elt (stream,i))->sequence) {	elt->deleted = T;	/* mark message deleted */				/* recalculate status */	tenex_update_status (stream,i,NIL);      }    if (!stream->rdonly) {	/* make sure the update takes */      fsync (LOCAL->fd);      fstat (LOCAL->fd,&sbuf);	/* get current write time */      tp[1] = LOCAL->filetime = sbuf.st_mtime;      tp[0] = time (0);		/* make sure atime remains greater */      utime (stream->mailbox,tp);    }  }  return ret;}/* Tenex mail append message from stringstruct * Accepts: MAIL stream *	    destination mailbox *	    append callback *	    data for callback * Returns: T if append successful, else NIL */long tenex_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){  struct stat sbuf;  int fd,ld,c;  char *flags,*date,tmp[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN];  time_t tp[2];  FILE *df;  MESSAGECACHE elt;  long f;  unsigned long i,j,uf,size;  STRING *message;  long ret = LONGT;				/* default stream to prototype */  if (!stream) stream = user_flags (&tenexproto);				/* make sure valid mailbox */  if (!tenex_isvalid (mailbox,tmp)) switch (errno) {  case ENOENT:			/* no such file? */    if (!compare_cstring (mailbox,"INBOX")) dummy_create (NIL,"mail.txt");    else {      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 TENEX-format mailbox name: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  default:    sprintf (tmp,"Not a TENEX-format mailbox: %.80s",mailbox);    MM_LOG (tmp,ERROR);    return NIL;  }				/* get first message */  if (!MM_APPEND (af) (stream,data,&flags,&date,&message)) return NIL;				/* open destination mailbox */  if (((fd = open (tenex_file (file,mailbox),O_WRONLY|O_APPEND|O_CREAT,		   S_IREAD|S_IWRITE)) < 0) || !(df = fdopen (fd,"ab"))) {    sprintf (tmp,"Can't open append mailbox: %s",strerror (errno));    MM_LOG (tmp,ERROR);    return NIL;  }				/* get parse/append permission */  if ((ld = lockfd (fd,lock,LOCK_EX)) < 0) {    MM_LOG ("Unable to lock append mailbox",ERROR);    close (fd);    return NIL;  }  MM_CRITICAL (stream);		/* go critical */  fstat (fd,&sbuf);		/* get current file size */  errno = 0;

⌨️ 快捷键说明

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