📄 unix.c
字号:
/* ======================================================================== * Copyright 1988-2008 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * * ======================================================================== *//* * Program: UNIX mail routines * * Author: Mark Crispin * UW Technology * University of Washington * Seattle, WA 98195 * Internet: MRC@Washington.EDU * * Date: 20 December 1989 * Last Edited: 27 March 2008 *//* DEDICATION * * This file is dedicated to my dog, Unix, also known as Yun-chan and * Unix J. Terwilliker Jehosophat Aloysius Monstrosity Animal Beast. Unix * passed away at the age of 11 1/2 on September 14, 1996, 12:18 PM PDT, after * a two-month bout with cirrhosis of the liver. * * He was a dear friend, and I miss him terribly. * * Lift a leg, Yunie. Luv ya forever!!!! */#include <stdio.h>#include <ctype.h>#include <errno.h>extern int errno; /* just in case */#include <signal.h>#include "mail.h"#include "osdep.h"#include <time.h>#include <sys/stat.h>#include "unix.h"#include "pseudo.h"#include "fdstring.h"#include "misc.h"#include "dummy.h"/* UNIX I/O stream local data */typedef struct unix_local { unsigned int dirty : 1; /* disk copy needs updating */ unsigned int ddirty : 1; /* double-dirty, ping becomes checkpoint */ unsigned int pseudo : 1; /* uses a pseudo message */ unsigned int appending : 1; /* don't mark new messages as old */ int fd; /* mailbox file descriptor */ int ld; /* lock file descriptor */ char *lname; /* lock file name */ off_t filesize; /* file size parsed */ time_t filetime; /* last file time */ time_t lastsnarf; /* last snarf time (for mbox driver) */ unsigned char *buf; /* temporary buffer */ unsigned long buflen; /* current size of temporary buffer */ unsigned long uid; /* current text uid */ SIZEDTEXT text; /* current text */ unsigned long textlen; /* current text length */ char *line; /* returned line */ char *linebuf; /* line readin buffer */ unsigned long linebuflen; /* current line readin buffer length */} UNIXLOCAL;/* Convenient access to local data */#define LOCAL ((UNIXLOCAL *) stream->local)/* UNIX protected file structure */typedef struct unix_file { MAILSTREAM *stream; /* current stream */ off_t curpos; /* current file position */ off_t protect; /* protected position */ off_t filepos; /* current last written file position */ char *buf; /* overflow buffer */ size_t buflen; /* current overflow buffer length */ char *bufpos; /* current buffer position */} UNIXFILE;/* Function prototypes */DRIVER *unix_valid (char *name);long unix_isvalid_fd (int fd);void *unix_parameters (long function,void *value);void unix_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);void unix_list (MAILSTREAM *stream,char *ref,char *pat);void unix_lsub (MAILSTREAM *stream,char *ref,char *pat);long unix_create (MAILSTREAM *stream,char *mailbox);long unix_delete (MAILSTREAM *stream,char *mailbox);long unix_rename (MAILSTREAM *stream,char *old,char *newname);MAILSTREAM *unix_open (MAILSTREAM *stream);void unix_close (MAILSTREAM *stream,long options);char *unix_header (MAILSTREAM *stream,unsigned long msgno, unsigned long *length,long flags);long unix_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);char *unix_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, unsigned long *length,long flags);void unix_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt);long unix_ping (MAILSTREAM *stream);void unix_check (MAILSTREAM *stream);long unix_expunge (MAILSTREAM *stream,char *sequence,long options);long unix_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);long unix_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);int unix_collect_msg (MAILSTREAM *stream,FILE *sf,char *flags,char *date, STRING *msg);int unix_append_msgs (MAILSTREAM *stream,FILE *sf,FILE *df,SEARCHSET *set);void unix_abort (MAILSTREAM *stream);char *unix_file (char *dst,char *name);int unix_lock (char *file,int flags,int mode,DOTLOCK *lock,int op);void unix_unlock (int fd,MAILSTREAM *stream,DOTLOCK *lock);int unix_parse (MAILSTREAM *stream,DOTLOCK *lock,int op);char *unix_mbxline (MAILSTREAM *stream,STRING *bs,unsigned long *size);unsigned long unix_pseudo (MAILSTREAM *stream,char *hdr);unsigned long unix_xstatus (MAILSTREAM *stream,char *status,MESSAGECACHE *elt, unsigned long uid,long flag);long unix_rewrite (MAILSTREAM *stream,unsigned long *nexp,DOTLOCK *lock, long flags);long unix_extend (MAILSTREAM *stream,unsigned long size);void unix_write (UNIXFILE *f,char *s,unsigned long i);void unix_phys_write (UNIXFILE *f,char *buf,size_t size);/* mbox mail routines *//* Function prototypes */DRIVER *mbox_valid (char *name);long mbox_create (MAILSTREAM *stream,char *mailbox);long mbox_delete (MAILSTREAM *stream,char *mailbox);long mbox_rename (MAILSTREAM *stream,char *old,char *newname);long mbox_status (MAILSTREAM *stream,char *mbx,long flags);MAILSTREAM *mbox_open (MAILSTREAM *stream);long mbox_ping (MAILSTREAM *stream);void mbox_check (MAILSTREAM *stream);long mbox_expunge (MAILSTREAM *stream,char *sequence,long options);long mbox_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);/* UNIX mail routines *//* Driver dispatch used by MAIL */DRIVER unixdriver = { "unix", /* driver name */ /* driver flags */ DR_LOCAL|DR_MAIL|DR_LOCKING|DR_NONEWMAILRONLY|DR_XPOINT, (DRIVER *) NIL, /* next driver */ unix_valid, /* mailbox is valid for us */ unix_parameters, /* manipulate parameters */ unix_scan, /* scan mailboxes */ unix_list, /* list mailboxes */ unix_lsub, /* list subscribed mailboxes */ NIL, /* subscribe to mailbox */ NIL, /* unsubscribe from mailbox */ unix_create, /* create mailbox */ unix_delete, /* delete mailbox */ unix_rename, /* rename mailbox */ mail_status_default, /* status of mailbox */ unix_open, /* open mailbox */ unix_close, /* close mailbox */ NIL, /* fetch message "fast" attributes */ NIL, /* fetch message flags */ NIL, /* fetch overview */ NIL, /* fetch message envelopes */ unix_header, /* fetch message header */ unix_text, /* fetch message text */ NIL, /* fetch partial message text */ NIL, /* unique identifier */ NIL, /* message number */ NIL, /* modify flags */ unix_flagmsg, /* per-message modify flags */ NIL, /* search for message based on criteria */ NIL, /* sort messages */ NIL, /* thread messages */ unix_ping, /* ping mailbox to see if still alive */ unix_check, /* check for new messages */ unix_expunge, /* expunge deleted messages */ unix_copy, /* copy messages to another mailbox */ unix_append, /* append string message to mailbox */ NIL /* garbage collect stream */}; /* prototype stream */MAILSTREAM unixproto = {&unixdriver}; /* driver parameters */static long unix_fromwidget = T;/* UNIX mail validate mailbox * Accepts: mailbox name * Returns: our driver if name is valid, NIL otherwise */DRIVER *unix_valid (char *name){ int fd; DRIVER *ret = NIL; char *t,file[MAILTMPLEN]; struct stat sbuf; time_t tp[2]; errno = EINVAL; /* assume invalid argument */ /* must be non-empty file */ if ((t = dummy_file (file,name)) && !stat (t,&sbuf)) { if (!sbuf.st_size)errno = 0;/* empty file */ else if ((fd = open (file,O_RDONLY,NIL)) >= 0) { /* OK if mailbox format good */ if (unix_isvalid_fd (fd)) ret = &unixdriver; else errno = -1; /* invalid format */ close (fd); /* close the file */ /* \Marked status? */ if ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) { tp[0] = sbuf.st_atime; /* yes, preserve atime and mtime */ tp[1] = sbuf.st_mtime; utime (file,tp); /* set the times */ } } } return ret; /* return what we should */}/* UNIX mail test for valid mailbox * Accepts: file descriptor * scratch buffer * Returns: T if valid, NIL otherwise */long unix_isvalid_fd (int fd){ int zn; int ret = NIL; char tmp[MAILTMPLEN],*s,*t,c = '\n'; memset (tmp,'\0',MAILTMPLEN); if (read (fd,tmp,MAILTMPLEN-1) >= 0) { for (s = tmp; (*s == '\r') || (*s == '\n') || (*s == ' ') || (*s == '\t');) c = *s++; if (c == '\n') VALID (s,t,ret,zn); } return ret; /* return what we should */}/* UNIX manipulate driver parameters * Accepts: function code * function-dependent value * Returns: function-dependent return value */void *unix_parameters (long function,void *value){ void *ret = NIL; switch ((int) function) { case GET_INBOXPATH: if (value) ret = dummy_file ((char *) value,"INBOX"); break; case SET_FROMWIDGET: unix_fromwidget = (long) value; case GET_FROMWIDGET: ret = (void *) unix_fromwidget; break; } return ret;}/* UNIX mail scan mailboxes * Accepts: mail stream * reference * pattern to search * string to scan */void unix_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents){ if (stream) dummy_scan (NIL,ref,pat,contents);}/* UNIX mail list mailboxes * Accepts: mail stream * reference * pattern to search */void unix_list (MAILSTREAM *stream,char *ref,char *pat){ if (stream) dummy_list (NIL,ref,pat);}/* UNIX mail list subscribed mailboxes * Accepts: mail stream * reference * pattern to search */void unix_lsub (MAILSTREAM *stream,char *ref,char *pat){ if (stream) dummy_lsub (NIL,ref,pat);}/* UNIX mail create mailbox * Accepts: MAIL stream * mailbox name to create * Returns: T on success, NIL on failure */long unix_create (MAILSTREAM *stream,char *mailbox){ char *s,mbx[MAILTMPLEN],tmp[MAILTMPLEN]; long ret = NIL; int i,fd; time_t ti = time (0); if (!(s = dummy_file (mbx,mailbox))) { sprintf (tmp,"Can't create %.80s: invalid name",mailbox); MM_LOG (tmp,ERROR); } /* create underlying file */ else if (dummy_create_path (stream,s,get_dir_protection (mailbox))) { /* done if dir-only or whiner */ if (((s = strrchr (s,'/')) && !s[1]) || mail_parameters (NIL,GET_USERHASNOLIFE,NIL)) ret = T; else if ((fd = open (mbx,O_WRONLY, (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL))) < 0) { sprintf (tmp,"Can't reopen mailbox node %.80s: %s",mbx,strerror (errno)); MM_LOG (tmp,ERROR); unlink (mbx); /* delete the file */ } else { /* initialize header */ memset (tmp,'\0',MAILTMPLEN); sprintf (tmp,"From %s %sDate: ",pseudo_from,ctime (&ti)); rfc822_fixed_date (s = tmp + strlen (tmp)); /* write the pseudo-header */ sprintf (s += strlen (s), "\nFrom: %s <%s@%s>\nSubject: %s\nX-IMAP: %010lu 0000000000", pseudo_name,pseudo_from,mylocalhost (),pseudo_subject, (unsigned long) ti); for (i = 0; i < NUSERFLAGS; ++i) if (default_user_flag (i)) sprintf (s += strlen (s)," %s",default_user_flag (i)); sprintf (s += strlen (s),"\nStatus: RO\n\n%s\n\n",pseudo_msg); if (write (fd,tmp,strlen (tmp)) > 0) ret = T; else { sprintf (tmp,"Can't initialize mailbox node %.80s: %s",mbx, strerror (errno)); MM_LOG (tmp,ERROR); unlink (mbx); /* delete the file */ } close (fd); /* close file */ } } /* set proper protections */ return ret ? set_mbx_protections (mailbox,mbx) : NIL;}/* UNIX mail delete mailbox * Accepts: MAIL stream * mailbox name to delete * Returns: T on success, NIL on failure */long unix_delete (MAILSTREAM *stream,char *mailbox){ return unix_rename (stream,mailbox,NIL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -