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

📄 unix.c

📁 Vovida 社区开源的 SIP 协议源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  unsigned long i,j,k,m;  char *s,*t,*te,p1[CHUNK];  char *ret = "";				/* flush old buffer */  if (LOCAL->line) fs_give ((void **) &LOCAL->line);				/* if buffer needs refreshing */  if (!bs->cursize) SETPOS (bs,GETPOS (bs));  if (SIZE (bs)) {		/* find newline */				/* end of fast scan */    te = (t = (s = bs->curpos) + bs->cursize) - 12;    while (s < te) if ((*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||		       (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||		       (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||		       (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n')) {      --s;			/* back up */      break;			/* exit loop */    }				/* final character-at-a-time scan */    while ((s < t) && (*s != '\n')) ++s;				/* difficult case if line spans buffer */    if ((i = s - bs->curpos) == bs->cursize) {      memcpy (p1,bs->curpos,i);	/* remember what we have so far */				/* load next buffer */      SETPOS (bs,k = GETPOS (bs) + i);				/* end of fast scan */      te = (t = (s = bs->curpos) + bs->cursize) - 12;				/* fast scan in overlap buffer */      while (s < te) if ((*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||			 (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||			 (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n') ||			 (*s++ == '\n') || (*s++ == '\n') || (*s++ == '\n')) {	--s;			/* back up */	break;			/* exit loop */      }				/* final character-at-a-time scan */      while ((s < t) && (*s != '\n')) ++s;				/* huge line? */      if ((j = s - bs->curpos) == bs->cursize) {	SETPOS (bs,GETPOS (bs) + j);				/* look for end of line (s-l-o-w!!) */	for (m = SIZE (bs); m && (SNX (bs) != '\n'); --m,++j);	SETPOS (bs,k);		/* go back to where it started */      }				/* got size of data, make buffer for return */      ret = LOCAL->line = (char *) fs_get (i + j + 2);      memcpy (ret,p1,i);	/* copy first chunk */      while (j) {		/* copy remainder */	if (!bs->cursize) SETPOS (bs,GETPOS (bs));	memcpy (ret + i,bs->curpos,k = min (j,bs->cursize));	i += k;			/* account for this much read in */	j -= k;	bs->curpos += k;	/* increment new position */	bs->cursize -= k;	/* eat that many bytes */      }      if (!bs->cursize) SETPOS (bs,GETPOS (bs));      if (SIZE (bs)) SNX (bs);	/* skip over newline if one seen */      ret[i++] = '\n';		/* make sure newline at end */      ret[i] = '\0';		/* makes debugging easier */    }    else {			/* this is easy */      ret = bs->curpos;		/* string it at this position */      bs->curpos += ++i;	/* increment new position */      bs->cursize -= i;		/* eat that many bytes */    }    *size = i;			/* return that to user */  }  else *size = 0;		/* end of data, return empty */  return ret;}/* UNIX make pseudo-header * Accepts: MAIL stream *	    buffer to write pseudo-header * Returns: length of pseudo-header */unsigned long unix_pseudo (MAILSTREAM *stream,char *hdr){  int i;  char *s,tmp[MAILTMPLEN];  time_t now = time (0);  rfc822_fixed_date (tmp);  sprintf (hdr,"From %s %.24s\nDate: %s\nFrom: %s <%s@%.80s>\nSubject: %s\nMessage-ID: <%lu@%.80s>\nX-IMAP: %010lu %010lu",	   pseudo_from,ctime (&now),	   tmp,pseudo_name,pseudo_from,mylocalhost (),pseudo_subject,	   (unsigned long) now,mylocalhost (),stream->uid_validity,	   stream->uid_last);  for (s = hdr + strlen (hdr),i = 0; i < NUSERFLAGS; ++i)    if (stream->user_flags[i])      sprintf (s += strlen (s)," %s",stream->user_flags[i]);  sprintf (s += strlen (s),"\nStatus: RO\n\n%s\n\n",pseudo_msg);  return strlen (hdr);		/* return header length */}/* UNIX make status string * Accepts: MAIL stream *	    destination string to write *	    message cache entry *	    non-zero flag to write UID (.LT. 0 to write UID base info too) * Returns: length of string */unsigned long unix_xstatus (MAILSTREAM *stream,char *status,MESSAGECACHE *elt,			    long flag){  char *t,stack[64];  char *s = status;  unsigned long n;  int pad = 50;  /* This used to use sprintf(), but thanks to certain cretinous C libraries     with horribly slow implementations of sprintf() I had to change it to this     mess.  At least it should be fast. */				/* need to write X-IMAPbase: header? */  if ((flag < 0) && !stream->uid_nosticky) {    *s++ = 'X'; *s++ = '-'; *s++ = 'I'; *s++ = 'M'; *s++ = 'A'; *s++ = 'P';    *s++ = 'b'; *s++ = 'a'; *s++ = 's'; *s++ = 'e'; *s++ = ':'; *s++ = ' ';    t = stack;    n = stream->uid_validity;	/* push UID validity digits on the stack */    do *t++ = (char) (n % 10) + '0';    while (n /= 10);				/* pop UID validity digits from stack */    while (t > stack) *s++ = *--t;    *s++ = ' ';    n = stream->uid_last;	/* push UID last digits on the stack */    do *t++ = (char) (n % 10) + '0';    while (n /= 10);				/* pop UID last digits from stack */    while (t > stack) *s++ = *--t;    for (n = 0; n < NUSERFLAGS; ++n) if (t = stream->user_flags[n])      for (*s++ = ' '; *t; *s++ = *t++);    *s++ = '\n';    pad += 30;			/* increased padding if have IMAPbase */  }  *s++ = 'S'; *s++ = 't'; *s++ = 'a'; *s++ = 't'; *s++ = 'u'; *s++ = 's';  *s++ = ':'; *s++ = ' ';  if (elt->seen) *s++ = 'R';  *s++ = 'O'; *s++ = '\n';  *s++ = 'X'; *s++ = '-'; *s++ = 'S'; *s++ = 't'; *s++ = 'a'; *s++ = 't';  *s++ = 'u'; *s++ = 's'; *s++ = ':'; *s++ = ' ';  if (elt->deleted) *s++ = 'D';  if (elt->flagged) *s++ = 'F';  if (elt->answered) *s++ = 'A';  if (elt->draft) *s++ = 'T';  *s++ = '\n';  if (!stream->uid_nosticky) {	/* cretins with no life can't use this */    *s++ = 'X'; *s++ = '-'; *s++ = 'K'; *s++ = 'e'; *s++ = 'y'; *s++ = 'w';    *s++ = 'o'; *s++ = 'r'; *s++ = 'd'; *s++ = 's'; *s++ = ':';    if (n = elt->user_flags) do {      *s++ = ' ';      for (t = stream->user_flags[find_rightmost_bit (&n)]; *t; *s++ = *t++);    } while (n);    n = s - status;		/* get size of stuff so far */				/* pad X-Keywords to make size constant */    if (n < pad) for (n = pad - n; n > 0; --n) *s++ = ' ';    *s++ = '\n';    if (flag) {			/* want to include UID? */      t = stack;      n = elt->private.uid;	/* push UID digits on the stack */      do *t++ = (char) (n % 10) + '0';      while (n /= 10);      *s++ = 'X'; *s++ = '-'; *s++ = 'U'; *s++ = 'I'; *s++ = 'D'; *s++ = ':';      *s++ = ' ';				/* pop UID from stack */      while (t > stack) *s++ = *--t;      *s++ = '\n';    }  }  *s++ = '\n'; *s = '\0';	/* end of extended message status */  return s - status;		/* return size of resulting string */}/* Rewrite mailbox file * Accepts: MAIL stream, must be critical and locked *	    return pointer to number of expunged messages if want expunge *	    lock file name * Returns: T if success and mailbox unlocked, NIL if failure */#define OVERFLOWBUFLEN 8192	/* initial overflow buffer length */long unix_rewrite (MAILSTREAM *stream,unsigned long *nexp,DOTLOCK *lock){  MESSAGECACHE *elt;  UNIXFILE f;  char *s;  time_t tp[2];  long ret,flag;  unsigned long i,j;  unsigned long recent = stream->recent;  unsigned long size = LOCAL->pseudo ? unix_pseudo (stream,LOCAL->buf) : 0;  if (nexp) *nexp = 0;		/* initially nothing expunged */				/* calculate size of mailbox after rewrite */  for (i = 1,flag = LOCAL->pseudo ? 1 : -1; i <= stream->nmsgs; i++)    if (!(elt = mail_elt (stream,i))->deleted || !nexp) {				/* add RFC822 size of this message */      size += elt->private.special.text.size + elt->private.data +	unix_xstatus (stream,LOCAL->buf,elt,flag) +	  elt->private.msg.text.text.size + 1;      flag = 1;			/* only count X-IMAPbase once */    }				/* extend the file as necessary */  if (ret = unix_extend (stream,size)) {    /* Set up buffered I/O file structure     * curpos	current position being written through buffering     * filepos	current position being written physically to the disk     * bufpos	current position being written in the buffer     * protect	current maximum position that can be written to the disk     *		before buffering is forced     * The code tries to buffer so that that disk is written in multiples of     * OVERBLOWBUFLEN bytes.     */    f.stream = stream;		/* note mail stream */    f.curpos = f.filepos = 0;	/* start of file */    f.protect = stream->nmsgs ?	/* initial protection pointer */    mail_elt (stream,1)->private.special.offset : 8192;    f.bufpos = f.buf = (char *) fs_get (f.buflen = OVERFLOWBUFLEN);    if (LOCAL->pseudo)		/* update pseudo-header */      unix_write (&f,LOCAL->buf,unix_pseudo (stream,LOCAL->buf));				/* loop through all messages */    for (i = 1,flag = LOCAL->pseudo ? 1 : -1; i <= stream->nmsgs;) {      elt = mail_elt (stream,i);/* get cache */      if (nexp && elt->deleted){/* expunge this message? */				/* one less recent message */	if (elt->recent) --recent;	mail_expunged(stream,i);/* notify upper levels */	++*nexp;		/* count up one more expunged message */      }      else {			/* preserve this message */	i++;			/* advance to next message */	if ((flag < 0) ||	/* need to rewrite message? */	    (elt->private.dirty || (f.curpos != elt->private.special.offset) ||	     (elt->private.msg.header.text.size !=	      (elt->private.data +	       unix_xstatus (stream,LOCAL->buf,elt,flag))))) {	  unsigned long newoffset = f.curpos;				/* yes, seek to internal header */	  lseek (LOCAL->fd,elt->private.special.offset,L_SET);	  read (LOCAL->fd,LOCAL->buf,elt->private.special.text.size);				/* see if need to squeeze out a CR */	  if (LOCAL->buf[elt->private.special.text.size - 2] == '\r') {	    LOCAL->buf[--elt->private.special.text.size - 1] = '\n';	    --size;		/* squeezed out a CR from PC */	  }				/* protection pointer moves to RFC822 header */	  f.protect = elt->private.special.offset +	    elt->private.msg.header.offset;				/* write internal header */	  unix_write (&f,LOCAL->buf,elt->private.special.text.size);				/* get RFC822 header */	  s = unix_header (stream,elt->msgno,&j,FT_INTERNAL);				/* in case this got decremented */	  elt->private.msg.header.offset = elt->private.special.text.size;				/* header size, sans trailing newline */	  if ((j < 2) || (s[j - 2] == '\n')) j--;	  if (j != elt->private.data) fatal ("header size inconsistent");				/* protection pointer moves to RFC822 text */	  f.protect = elt->private.special.offset +	    elt->private.msg.text.offset;	  unix_write (&f,s,j);	/* write RFC822 header */				/* write status and UID */	  unix_write (&f,LOCAL->buf,		      j = unix_xstatus (stream,LOCAL->buf,elt,flag));	  flag = 1;		/* only write X-IMAPbase once */				/* new file header size */	  elt->private.msg.header.text.size = elt->private.data + j;				/* did text move? */	  if (f.curpos != f.protect) {				/* get message text */	    s = unix_text_work (stream,elt,&j,FT_INTERNAL);				/* this can happen if CRs were squeezed */	    if (j < elt->private.msg.text.text.size) {				/* so fix up counts */	      size -= elt->private.msg.text.text.size - j;	      elt->private.msg.text.text.size = j;	    }				/* can't happen it says here */	    else if (j > elt->private.msg.text.text.size)	      fatal ("text size inconsistent");				/* new text offset, status/UID may change it */	    elt->private.msg.text.offset = f.curpos - newoffset;				/* protection pointer moves to next message */	    f.protect = (i <= stream->nmsgs) ?	      mail_elt (stream,i)->private.special.offset : (f.curpos + j + 1);	    unix_write (&f,s,j);/* write text */				/* write trailing newline */	    unix_write (&f,"\n",1);	  }	  else {		/* tie off header and status */	    unix_write (&f,NIL,NIL);	    f.curpos = f.protect =/* restart everything at end of message */	      f.filepos += elt->private.msg.text.text.size + 1;	  }				/* new internal header offset */	  elt->private.special.offset = newoffset;	  elt->private.dirty =NIL;/* message is now clean */	}	else {			/* no need to rewrite this message */				/* tie off previous message if needed */	  unix_write (&f,NIL,NIL);	  f.curpos = f.protect =/* restart everything at end of message */	    f.filepos += elt->private.special.text.size +	      elt->private.msg.header.text.size +		elt->private.msg.text.text.size + 1;	}      }    }    unix_write (&f,NIL,NIL);	/* tie off final message */    if (size != f.filepos) fatal ("file size inconsistent");    fs_give ((void **) &f.buf);	/* free buffer */				/* make sure tied off */    ftruncate (LOCAL->fd,LOCAL->filesize = size);    fsync (LOCAL->fd);		/* make sure the updates take */    if (size && (flag < 0)) fatal ("lost UID base information");    LOCAL->dirty = NIL;		/* no longer dirty */  				/* notify upper level of new mailbox sizes */    mail_exists (stream,stream->nmsgs);    mail_recent (stream,recent);				/* set atime to now, mtime a second earlier */    tp[1] = (tp[0] = time (0)) - 1;				/* set the times, note change */    if (!utime (stream->mailbox,tp)) LOCAL->filetime = tp[1];    close (LOCAL->fd);		/* close and reopen file */    if ((LOCAL->fd = open (stream->mailbox,O_RDWR,NIL)) < 0) {      sprintf (LOCAL->buf,"Mailbox open failed, aborted: %s",strerror (errno));      mm_log (LOCAL->buf,ERROR);      unix_abort (stream);    }    dotlock_unlock (lock);	/* flush the lock file */  }  return ret;			/* return state from algorithm */}/* Extend UNIX mailbox file * Accepts: MAIL stream *	    new desired size * Return: T if success, else NIL */long unix_extend (MAILSTREAM *stream,unsigned long size){  unsigned long i = (size > LOCAL->filesize) ? size - LOCAL->filesize : 0;  if (i) {			/* does the mailbox need to grow? */    if (i > LOCAL->buflen) {	/* make sure have enough space */				/* this user won the lottery all right */      fs_give ((void **) &LOCAL->buf);      LOCAL->buf = (char *) fs_get ((LOCAL->buflen = i) + 1);    }    memset (LOCAL->buf,'\0',i);	/* get a block of nulls */    while (T) {			/* until write successful or punt */      lseek (LOCAL->fd,LOCAL->filesize,L_SET);      if ((write (LOCAL->fd,LOCAL->buf,i) >= 0) && !fsync (LOCAL->fd)) break;      else {	long e = errno;		/* note error before doing ftruncate */	ftruncate (LOCAL->fd,LOCAL->filesize);	if (mm_diskerror (stream,e,NIL)) {	  fsync (LOCAL->fd);	/* user chose to punt */	  sprintf (LOCAL->buf,"Unable to extend mailbox: %s",strerror (e));	  mm_log (LOCAL->buf,ERROR);	  return NIL;	}      }    }  }  return LONGT;}/* Write data to buffered file * Accepts: buffered file pointer *	    file data or NIL to indicate "flush buffer" *	    date size (ignored for "flu

⌨️ 快捷键说明

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