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

📄 unix.c

📁 Vovida 社区开源的 SIP 协议源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  MESSAGECACHE *elt;  long ret = T;  mailproxycopy_t pc =    (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL);  if (!((options & CP_UID) ? mail_uid_sequence (stream,sequence) :	mail_sequence (stream,sequence))) return NIL;				/* make sure valid mailbox */  if (!unix_valid (mailbox)) 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 UNIX-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 UNIX-format mailbox: %.80s",mailbox);    mm_log (LOCAL->buf,ERROR);    return NIL;  }  LOCAL->buf[0] = '\0';  mm_critical (stream);		/* go critical */  if ((fd = unix_lock (dummy_file (file,mailbox),O_WRONLY|O_APPEND|O_CREAT,		       S_IREAD|S_IWRITE,&lock,LOCK_EX)) < 0) {    mm_nocritical (stream);	/* done with critical */    sprintf (LOCAL->buf,"Can't open destination mailbox: %s",strerror (errno));    mm_log (LOCAL->buf,ERROR);	/* log the error */    return NIL;			/* failed */  }  fstat (fd,&sbuf);		/* get current file size */				/* write all requested messages to mailbox */  for (i = 1; ret && (i <= stream->nmsgs); i++)    if ((elt = mail_elt (stream,i))->sequence) {      lseek (LOCAL->fd,elt->private.special.offset,L_SET);      read (LOCAL->fd,LOCAL->buf,elt->private.special.text.size);      if (write (fd,LOCAL->buf,elt->private.special.text.size) < 0) ret = NIL;      else {			/* internal header succeeded */	s = unix_header (stream,i,&j,FT_INTERNAL);				/* header size, sans trailing newline */	if (j && (s[j - 2] == '\n')) j--;	if (write (fd,s,j) < 0) ret = NIL;	else {			/* message header succeeded */	  j = unix_xstatus (stream,LOCAL->buf,elt,NIL);	  if (write (fd,LOCAL->buf,j) < 0) ret = NIL;	  else {		/* message status succeeded */	    s = unix_text_work (stream,elt,&j,FT_INTERNAL);	    if ((write (fd,s,j) < 0) || (write (fd,"\n",1) < 0)) ret = NIL;	  }	}      }    }  if (!ret || fsync (fd)) {	/* force out the update */    sprintf (LOCAL->buf,"Message copy failed: %s",strerror (errno));    ftruncate (fd,sbuf.st_size);    ret = NIL;  }  tp[0] = sbuf.st_atime;	/* preserve atime */  tp[1] = time (0);		/* set mtime to now */  utime (file,tp);		/* set the times */  unix_unlock (fd,NIL,&lock);	/* unlock and close mailbox */  mm_nocritical (stream);	/* release critical */				/* log the error */  if (!ret) mm_log (LOCAL->buf,ERROR);				/* delete if requested message */  else if (options & CP_MOVE) for (i = 1; i <= stream->nmsgs; i++)    if ((elt = mail_elt (stream,i))->sequence)      elt->deleted = elt->private.dirty = LOCAL->dirty = T;  return ret;}/* UNIX mail append message from stringstruct * Accepts: MAIL stream *	    destination mailbox *	    append callback *	    data for callback * Returns: T if append successful, else NIL */#define BUFLEN 8*MAILTMPLENlong unix_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){  struct stat sbuf;  int fd;  unsigned long i,j;  char *flags,*date,buf[BUFLEN],tmp[MAILTMPLEN],file[MAILTMPLEN];  time_t tp[2];  FILE *sf,*df;  MESSAGECACHE elt;  DOTLOCK lock;  STRING *message;  long ret = LONGT;				/* default stream to prototype */  if (!stream) stream = user_flags (&unixproto);				/* make sure valid mailbox */  if (!unix_valid (mailbox)) switch (errno) {  case ENOENT:			/* no such file? */    if (((mailbox[0] == 'I') || (mailbox[0] == 'i')) &&	((mailbox[1] == 'N') || (mailbox[1] == 'n')) &&	((mailbox[2] == 'B') || (mailbox[2] == 'b')) &&	((mailbox[3] == 'O') || (mailbox[3] == 'o')) &&	((mailbox[4] == 'X') || (mailbox[4] == 'x')) && !mailbox[5])      unix_create (NIL,"INBOX");    else {      mm_notify (stream,"[TRYCREATE] Must create mailbox before append",NIL);      return NIL;    }				/* falls through */  case 0:			/* INBOX ENOENT or empty file? */    break;  case EINVAL:    sprintf (tmp,"Invalid UNIX-format mailbox name: %.80s",mailbox);    mm_log (tmp,ERROR);    return NIL;  default:    sprintf (tmp,"Not a UNIX-format mailbox: %.80s",mailbox);    mm_log (tmp,ERROR);    return NIL;  }				/* get first message */  if (!(*af) (stream,data,&flags,&date,&message)) return NIL;  if (!(sf = tmpfile ())) {	/* must have scratch file */    sprintf (tmp,"Unable to create scratch file: %.80s",strerror (errno));    mm_log (tmp,ERROR);  }  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 (!unix_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 ((*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 = unix_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[0] = sbuf.st_atime;	/* preserve atime */				/* make sure append wins */  if (i || (fflush (df) == EOF)) {    sprintf (buf,"Message append failed: %s",strerror (errno));    mm_log (buf,ERROR);    ftruncate (fd,sbuf.st_size);    tp[1] = sbuf.st_mtime;	/* preserve mtime */    ret = NIL;			/* return error */  }  else tp[1] = time (0);	/* set mtime to now */  utime (file,tp);		/* set the times */  unix_unlock (fd,NIL,&lock);	/* unlock and close mailbox */  fclose (df);			/* note that unix_unlock() released the fd */  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 unix_append_msg (MAILSTREAM *stream,FILE *sf,char *flags,char *date,		     STRING *msg){  int ti,zn,c;  unsigned long i,uf;  char *x,tmp[MAILTMPLEN];  long f = mail_parse_flags (stream,flags,&uf);				/* build initial header */  if ((fprintf (sf,"From %s@%s %sStatus: ",		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 */				/* possible delimiter if line starts with F */    if ((c = 0xff & SNX (msg)) == 'F') {				/* copy line to buffer */      for (i = 1,tmp[0] = c; SIZE (msg) && (c != '\n') && (i < MAILTMPLEN);)	if (((c = 0xff & SNX (msg)) != '\r') || !(SIZE (msg)) ||	    (CHR (msg) != '\n')) tmp[i++] = c;      if ((i > 4) && (tmp[1] == 'r') && (tmp[2] == 'o') && (tmp[3] == 'm') &&	  (tmp[4] == ' ')) {	/* possible "From " line? */				/* yes, see if need to write a widget */	if (!(ti = unix_fromwidget || (c != '\n'))) VALID (tmp,x,ti,zn);	if (ti && (putc ('>',sf) == EOF)) return NIL;      }				/* write buffered text */      if (fwrite (tmp,1,i,sf) != i) return NIL;      if (c == '\n') continue;	/* all done if got a complete line */    }				/* copy line, toss out CR from CRLF */    do if (((c == '\r') && SIZE (msg) && ((c = 0xff & SNX (msg)) != '\n') &&	    (putc ('\r',sf) == EOF)) || (putc (c,sf) == EOF)) return NIL;    while ((c != '\n') && SIZE (msg) && ((c = 0xff & SNX (msg)) ? c : T));  }				/* write trailing newline and return */  return (putc ('\n',sf) == EOF) ? NIL : T;}/* Internal routines *//* UNIX mail abort stream * Accepts: MAIL stream */void unix_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->line) fs_give ((void **) &LOCAL->line);				/* nuke the local data */    fs_give ((void **) &stream->local);    stream->dtb = NIL;		/* log out the DTB */  }}/* UNIX 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 unix_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;}/* UNIX unlock and close mailbox * Accepts: file descriptor *	    (optional) mailbox stream to check atime/mtime *	    (optional) lock file name */void unix_unlock (int fd,MAILSTREAM *stream,DOTLOCK *lock){  struct stat sbuf;  time_t tp[2];  fstat (fd,&sbuf);		/* get file times */				/* if stream and csh would think new mail */  if (stream && (sbuf.st_atime <= sbuf.st_mtime)) {    tp[0] = time (0);		/* set atime to now */				/* set mtime to (now - 1) if necessary */    tp[1] = tp[0] > sbuf.st_mtime ? sbuf.st_mtime : tp[0] - 1;				/* set the times, note change */    if (!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 */}/* UNIX 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 unix_parse (MAILSTREAM *stream,DOTLOCK *lock,int op){  int zn;  unsigned long i,j,k,m;  char c,*s,*t,*u,tmp[MAILTMPLEN],date[30];  int ti = 0,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 = unix_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);    unix_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 */    unix_unlock (LOCAL->fd,stream,lock);

⌨️ 快捷键说明

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