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

📄 mmdf.c

📁 这是用C编写IMAP源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    MM_LOG (tmp,ERROR);    return NIL;  }				/* get first message */  if (!MM_APPEND (af) (stream,data,&flags,&date,&message)) return NIL;  if (!(sf = tmpfile ())) {	/* must have scratch file */    sprintf (tmp,".%lx.%lx",(unsigned long) time (0),(unsigned long)getpid ());    if (!stat (tmp,&sbuf) || !(sf = fopen (tmp,"wb+"))) {      sprintf (tmp,"Unable to create scratch file: %.80s",strerror (errno));      MM_LOG (tmp,ERROR);      return NIL;    }    unlink (tmp);  }  do {				/* parse date */    if (!date) rfc822_date (date = tmp);    if (!mail_parse_date (&elt,date)) {      sprintf (tmp,"Bad date in append: %.80s",date);      MM_LOG (tmp,ERROR);    }    else {			/* user wants to suppress time zones? */      if (mail_parameters (NIL,GET_NOTIMEZONES,NIL)) {	time_t when = mail_longdate (&elt);	date = ctime (&when);	/* use traditional date */      }				/* use POSIX-style date */      else date = mail_cdate (tmp,&elt);      if (!SIZE (message)) MM_LOG ("Append of zero-length message",ERROR);      else if (!mmdf_append_msg (stream,sf,flags,date,message)) {	sprintf (tmp,"Error writing scratch file: %.80s",strerror (errno));	MM_LOG (tmp,ERROR);      }				/* get next message */      else if (MM_APPEND (af) (stream,data,&flags,&date,&message)) continue;    }    fclose (sf);		/* punt scratch file */    return NIL;			/* give up */  } while (message);		/* until no more messages */  if (fflush (sf) || fstat (fileno (sf),&sbuf)) {    sprintf (tmp,"Error finishing scratch file: %.80s",strerror (errno));    MM_LOG (tmp,ERROR);    fclose (sf);		/* punt scratch file */    return NIL;			/* give up */  }  i = sbuf.st_size;		/* size of scratch file */  MM_CRITICAL (stream);	/* go critical */  if (((fd = mmdf_lock (dummy_file (file,mailbox),O_WRONLY|O_APPEND|O_CREAT,		       S_IREAD|S_IWRITE,&lock,LOCK_EX)) < 0) ||      !(df = fdopen (fd,"ab"))) {    MM_NOCRITICAL (stream);	/* done with critical */    sprintf (tmp,"Can't open append mailbox: %s",strerror (errno));    MM_LOG (tmp,ERROR);    return NIL;  }  fstat (fd,&sbuf);		/* get current file size */  rewind (sf);  for (; i && ((j = fread (buf,1,min ((long) BUFLEN,i),sf)) &&	       (fwrite (buf,1,j,df) == j)); i -= j);  fclose (sf);			/* done with scratch file */  tp[1] = time (0);		/* set mtime to now */				/* make sure append wins, fsync() necessary */  if (i || (fflush (df) == EOF) || fsync (fd)) {    sprintf (buf,"Message append failed: %s",strerror (errno));    MM_LOG (buf,ERROR);    ftruncate (fd,sbuf.st_size);    tp[0] =			/* preserve \Marked status */      ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?      sbuf.st_atime : tp[1];    ret = NIL;			/* return error */  }  else tp[0] = tp[1] - 1;	/* set atime to now-1 if successful copy */  utime (file,tp);		/* set the times */  mmdf_unlock (fd,NIL,&lock);	/* unlock and close mailbox */  fclose (df);  MM_NOCRITICAL (stream);	/* release critical */  return ret;}/* Write single message to append scratch file * Accepts: MAIL stream *	    scratch file *	    flags *	    message stringstruct * Returns: NIL if write error, else T */int mmdf_append_msg (MAILSTREAM *stream,FILE *sf,char *flags,char *date,		     STRING *msg){  unsigned long i,uf;  int c;  char tmp[MAILTMPLEN];  int hdrp = T;  long f = mail_parse_flags (stream,flags,&uf);				/* build initial header */  if ((fprintf (sf,"%sFrom %s@%s %sStatus: ",		mmdfhdr,myusername (),mylocalhost (),date) < 0) ||      (f&fSEEN && (putc ('R',sf) == EOF)) ||      (fputs ("\nX-Status: ",sf) == EOF) ||      (f&fDELETED && (putc ('D',sf) == EOF)) ||      (f&fFLAGGED && (putc ('F',sf) == EOF)) ||      (f&fANSWERED && (putc ('A',sf) == EOF)) ||      (f&fDRAFT && (putc ('T',sf) == EOF)) ||      (fputs ("\nX-Keywords:",sf) == EOF)) return NIL;  while (uf)			/* write user flags */    if (fprintf (sf," %s",stream->user_flags[find_rightmost_bit (&uf)]) < 0)      return NIL;				/* tie off flags */  if (putc ('\n',sf) == EOF) return NIL;  while (SIZE (msg)) {		/* copy text to scratch file */				/* disregard CRs */    while ((c = (SIZE (msg)) ? (c = 0xff & SNX (msg)) : '\n') == '\r');				/* see if line needs special treatment */    if (hdrp && ((c == 'S') || (c == 'X'))) {				/* copy line to buffer */      for (i = 1,tmp[0] = c; (c != '\n') && (i < MAILTMPLEN); )	if ((c = (SIZE (msg)) ? (0xff & SNX (msg)) : '\n') != '\r')	  tmp[i++] = c;				/* insert X- before metadata header */      if ((((i > 6) && (tmp[0] == 'S') && (tmp[1] == 't') &&	    (tmp[2] == 'a') && (tmp[3] == 't') && (tmp[4] == 'u') &&	    (tmp[5] == 's') && (tmp[6] == ':')) ||	   (((i > 5) && (tmp[0] == 'X') && (tmp[1] == '-')) &&	    (((tmp[2] == 'U') && (tmp[3] == 'I') && (tmp[4] == 'D') &&	      (tmp[5] == ':')) ||	     ((i > 6) && (tmp[2] == 'I') && (tmp[3] == 'M') &&	      (tmp[4] == 'A') && (tmp[5] == 'P') &&	      ((tmp[6] == ':') ||	       ((i > 10) && (tmp[6] == 'b') && (tmp[7] == 'a') &&		(tmp[8] == 's') && (tmp[9] == 'e') && (tmp[10] == ':')))) ||	     ((i > 8) && (tmp[2] == 'S') && (tmp[3] == 't') &&	      (tmp[4] == 'a') && (tmp[5] == 't') && (tmp[6] == 'u') &&	      (tmp[7] == 's') && (tmp[8] == ':')) ||	     ((i > 10) && (tmp[2] == 'K') && (tmp[3] == 'e') &&	      (tmp[4] == 'y') && (tmp[5] == 'w') && (tmp[6] == 'o') &&	      (tmp[7] == 'r') && (tmp[8] == 'd') && (tmp[9] == 's') &&	      (tmp[10] == ':'))))) && (fputs ("X-Original-",sf) == EOF))	return NIL;				/* write buffered text */      if (fwrite (tmp,1,i,sf) != i) return NIL;				/* set up to copy remainder of line */      if ((c != '\n') && SIZE (msg)) c = 0xff & SNX (msg);      else continue;		/* end of line or end of message */    }				/* check for end of header */    else if (hdrp && (c == '\n')) hdrp = NIL;    do switch (c) {		/* copy line */    case MMDFCHR:		/* flush CTRL/A */    case '\r':			/* and CR */      break;    default:			/* any other character */      if (putc (c,sf) == EOF) return NIL;    }    while ((c != '\n') && SIZE (msg) && ((c = 0xff & SNX (msg)) ? c : T));  }				/* write trailer and return */  return (fputs (mmdfhdr,sf) == EOF) ? NIL : T;}/* Internal routines *//* MMDF mail abort stream * Accepts: MAIL stream */void mmdf_abort (MAILSTREAM *stream){  if (LOCAL) {			/* only if a file is open */    if (LOCAL->fd >= 0) close (LOCAL->fd);    if (LOCAL->ld >= 0) {	/* have a mailbox lock? */      flock (LOCAL->ld,LOCK_UN);/* yes, release the lock */      close (LOCAL->ld);	/* close the lock file */      unlink (LOCAL->lname);	/* and delete it */    }    if (LOCAL->lname) fs_give ((void **) &LOCAL->lname);				/* free local text buffers */    if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);    if (LOCAL->text.data) fs_give ((void **) &LOCAL->text.data);    if (LOCAL->line) fs_give ((void **) &LOCAL->line);				/* nuke the local data */    fs_give ((void **) &stream->local);    stream->dtb = NIL;		/* log out the DTB */  }}/* MMDF open and lock mailbox * Accepts: file name to open/lock *	    file open mode *	    destination buffer for lock file name *	    type of locking operation (LOCK_SH or LOCK_EX) */int mmdf_lock (char *file,int flags,int mode,DOTLOCK *lock,int op){  int fd;  blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);  (*bn) (BLOCK_FILELOCK,NIL);				/* try locking the easy way */  if (dotlock_lock (file,lock,-1)) {				/* got dotlock file, easy open */    if ((fd = open (file,flags,mode)) >= 0) flock (fd,op);    else dotlock_unlock (lock);	/* open failed, free the dotlock */  }				/* no dot lock file, open file now */  else if ((fd = open (file,flags,mode)) >= 0) {				/* try paranoid way to make a dot lock file */    if (dotlock_lock (file,lock,fd)) {      close (fd);		/* get fresh fd in case of timing race */      if ((fd = open (file,flags,mode)) >= 0) flock (fd,op);      else dotlock_unlock (lock); /* open failed, free the dotlock */    }    else flock (fd,op);		/* paranoid way failed, just flock() it */  }  (*bn) (BLOCK_NONE,NIL);  return fd;}/* MMDF unlock and close mailbox * Accepts: file descriptor *	    (optional) mailbox stream to check atime/mtime *	    (optional) lock file name */void mmdf_unlock (int fd,MAILSTREAM *stream,DOTLOCK *lock){  if (stream) {			/* need to muck with times? */    struct stat sbuf;    time_t tp[2];    time_t now = time (0);    fstat (fd,&sbuf);		/* get file times */    if (LOCAL->ld >= 0) {	/* yes, readwrite session? */      tp[0] = now;		/* set atime to now */				/* set mtime to (now - 1) if necessary */      tp[1] = (now > sbuf.st_mtime) ? sbuf.st_mtime : now - 1;    }    else if (stream->recent) {	/* readonly with recent messages */      if ((sbuf.st_atime >= sbuf.st_mtime) ||	  (sbuf.st_atime >= sbuf.st_ctime))				/* keep past mtime, whack back atime */	tp[0] = (tp[1] = (sbuf.st_mtime < now) ? sbuf.st_mtime : now) - 1;      else now = 0;		/* no time change needed */    }				/* readonly with no recent messages */    else if ((sbuf.st_atime < sbuf.st_mtime) ||	     (sbuf.st_atime < sbuf.st_ctime)) {      tp[0] = now;		/* set atime to now */				/* set mtime to (now - 1) if necessary */      tp[1] = (now > sbuf.st_mtime) ? sbuf.st_mtime : now - 1;    }    else now = 0;		/* no time change needed */				/* set the times, note change */    if (now && !utime (stream->mailbox,tp)) LOCAL->filetime = tp[1];  }  flock (fd,LOCK_UN);		/* release flock'ers */  if (!stream) close (fd);	/* close the file if no stream */  dotlock_unlock (lock);	/* flush the lock file if any */}/* MMDF mail parse and lock mailbox * Accepts: MAIL stream *	    space to write lock file name *	    type of locking operation * Returns: T if parse OK, critical & mailbox is locked shared; NIL if failure */int mmdf_parse (MAILSTREAM *stream,DOTLOCK *lock,int op){  int ti,zn,m;  unsigned long i,j,k;  unsigned char c,*s,*t,*u,tmp[MAILTMPLEN],date[30];  int retain = T;  unsigned long nmsgs = stream->nmsgs;  unsigned long prevuid = nmsgs ? mail_elt (stream,nmsgs)->private.uid : 0;  unsigned long recent = stream->recent;  unsigned long oldnmsgs = stream->nmsgs;  short silent = stream->silent;  short pseudoseen = NIL;  struct stat sbuf;  STRING bs;  FDDATA d;  MESSAGECACHE *elt;  mail_lock (stream);		/* guard against recursion or pingers */				/* toss out previous descriptor */  if (LOCAL->fd >= 0) close (LOCAL->fd);  MM_CRITICAL (stream);		/* open and lock mailbox (shared OK) */  if ((LOCAL->fd = mmdf_lock (stream->mailbox,(LOCAL->ld >= 0) ?			      O_RDWR : O_RDONLY,NIL,lock,op)) < 0) {    sprintf (tmp,"Mailbox open failed, aborted: %s",strerror (errno));    MM_LOG (tmp,ERROR);    mmdf_abort (stream);    mail_unlock (stream);    MM_NOCRITICAL (stream);	/* done with critical */    return NIL;  }  fstat (LOCAL->fd,&sbuf);	/* get status */				/* validate change in size */  if (sbuf.st_size < LOCAL->filesize) {    sprintf (tmp,"Mailbox shrank from %lu to %lu bytes, aborted",	     (unsigned long) LOCAL->filesize,(unsigned long) sbuf.st_size);    MM_LOG (tmp,ERROR);		/* this is pretty bad */    mmdf_unlock (LOCAL->fd,stream,lock);    mmdf_abort (stream);    mail_unlock (stream);    MM_NOCRITICAL (stream);	/* done with critical */    return NIL;  }				/* new data? */  else if (i = sbuf.st_size - LOCAL->filesize) {    d.fd = LOCAL->fd;		/* yes, set up file descriptor */    d.pos = LOCAL->filesize;	/* get to that position in the file */    d.chunk = LOCAL->buf;	/* initial buffer chunk */    d.chunksize = CHUNK;	/* file chunk size */    INIT (&bs,fd_string,&d,i);	/* initialize stringstruct */				/* skip leading whitespace for broken MTAs */    while (((c = CHR (&bs)) == '\n') || (c == '\r') ||	   (c == ' ') || (c == '\t')) SNX (&bs);    if (SIZE (&bs)) {		/* read new data */				/* remember internal header position */      j = LOCAL->filesize + GETPOS (&bs);      s = mmdf_mbxline (stream,&bs,&i);      stream->silent = T;	/* quell main program new message events */      do {			/* read MMDF header */	if (!(i && ISMMDF (s))){/* see if valid MMDF header */	  sprintf (tmp,"Unexpected changes to mailbox (try restarting): %.20s",		   (char *) s);				/* see if we can back up to a line */	  if (i && (j > MMDFHDRLEN)) {	    SETPOS (&bs,j -= MMDFHDRLEN);				/* read previous line */	    s = mmdf_mbxline (stream,&bs,&i);				/* kill the error if it looks good */	    if (i && ISMMDF (s)) tmp[0] = '\0';	  }	  if (tmp[0]) {	    MM_LOG (tmp,ERROR);	    mmdf_unlock (LOCAL->fd,stream,lock);	    mmdf_abort (stream);	    mail_unlock (stream);	    MM_NOCRITICAL (stream);	    return NIL;	  }	}				/* instantiate first new message */	mail_exists (stream,++nmsgs);	(elt = mail_elt (stream,nmsgs))->valid = T;	recent++;		/* assume recent by default */	elt->recent = T;				/* note position/size of internal header */	elt->private.special.offset = j;	elt->private.special.text.size = i;	s = mmdf_mbxline (stream,&bs,&i);	ti = 0;			/* assume not a valid date */	zn = 0,t = NIL;	if (i) VALID (s,t,ti,zn);	if (ti) {		/* generate plausible IMAPish date string */				/* this is also part of header */	  elt->private.special.text.size += i;	  date[2] = date[6] = date[20] = '-'; date[11] = ' ';	  date[14] = date[17] = ':';				/* dd */	  date[0] = t[ti - 2]; date[1] = t[ti - 1];				/* mmm */	  date[3] = t[ti - 6]; date[4] = t[ti - 5]; date[5] = t[ti - 4];				/* hh */	  date[12] = t[ti + 1]; date[13] = t[ti + 2];				/* mm */	  date[15] = t[ti + 4]; date[16] = t[ti + 5];	  if (t[ti += 6]==':'){	/* ss */

⌨️ 快捷键说明

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