📄 tmail.c
字号:
deliver_safely (ds,&st,mailbox,path,duid,tmp) : fail ("unable to resolve INBOX path",EX_CANTCREAT); /* dummy, empty imputed append path exist? */ if (ibxpath (ds = default_proto (T),&mailbox,path) && !lstat (path,&sbuf) && !sbuf.st_size) return deliver_safely (ds,&st,mailbox,path,duid,tmp); /* impute path that we will create */ if (!ibxpath (ds = format ? (format->open) (NIL) : default_proto (NIL), &mailbox,path)) return fail ("unable to resolve INBOX",EX_CANTCREAT); } /* black box, must create, get create proto */ else if (lstat (path,&sbuf)) ds = default_proto (NIL); else { /* black box, existing file */ /* empty file, get append prototype */ if (!sbuf.st_size) ds = default_proto (T); /* non-empty, get prototype from its data */ else if (!(ds = mail_open (NIL,"INBOX",OP_PROTOTYPE))) fatal ("no INBOX prototype"); /* error if unknown format */ if (!strcmp (ds->dtb->name,"phile")) return fail ("unknown format INBOX",EX_UNAVAILABLE); /* otherwise can deliver to it */ return deliver_safely (ds,&st,mailbox,path,duid,tmp); } sprintf (tmp,"attempting to create mailbox %.80s path %.80s",mailbox,path); mm_dlog (tmp); /* supplicate to the Evil One */ if (!path_create (ds,path)) return fail ("can't create INBOX",EX_CANTCREAT); sprintf (tmp,"created %.80s",path); mm_dlog (tmp); /* deliver the message */ return deliver_safely (ds,&st,mailbox,path,duid,tmp);}/* Resolve INBOX from driver prototype into mailbox name and filesystem path * Accepts: driver prototype * pointer to mailbox name string pointer * buffer to return mailbox path * Returns: T if success, NIL if error */long ibxpath (MAILSTREAM *ds,char **mailbox,char *path){ char *s,tmp[MAILTMPLEN]; long ret = T; if (!ds) ret = NIL; else if (!strcmp (ds->dtb->name,"unix") || !strcmp (ds->dtb->name,"mmdf")) strcpy (path,sysinbox ()); /* use system INBOX for unix and MMDF */ else if (!strcmp (ds->dtb->name,"tenex")) ret = (mailboxfile (path,"mail.txt") == path) ? T : NIL; else if (!strcmp (ds->dtb->name,"mtx")) ret = (mailboxfile (path,"INBOX.MTX") == path) ? T : NIL; else if (!strcmp (ds->dtb->name,"mbox")) ret = (mailboxfile (path,"mbox") == path) ? T : NIL; /* better not be a namespace driver */ else if (ds->dtb->flags & DR_NAMESPACE) return NIL; /* INBOX in home directory */ else ret = ((mailboxfile (path,"&&&&&") == path) && (s = strstr (path,"&&&&&")) && strcpy (s,"INBOX")) ? T : NIL; if (ret) { /* don't bother if lossage */ sprintf (tmp,"#driver.%s/INBOX",ds->dtb->name); *mailbox = cpystr (tmp); /* name of INBOX in this namespace */ } return ret;}/* Deliver safely * Accepts: prototype stream to force mailbox format * stringstruct of message temporary file * mailbox name * filesystem path name * user id * scratch buffer for messages * Returns: NIL if success, else error code */int deliver_safely (MAILSTREAM *prt,STRING *st,char *mailbox,char *path, uid_t uid,char *tmp){ struct stat sbuf; int i = delivery_unsafe (path,uid,&sbuf,tmp); if (i) return i; /* give up now if delivery unsafe */ /* directory, not file */ if ((sbuf.st_mode & S_IFMT) == S_IFDIR) { if (sbuf.st_mode & 0001) { /* listable directories may be worrisome */ sprintf (tmp,"WARNING: directory %.80s is listable",path); mm_log (tmp,WARN); } } else { /* file, not directory */ if (sbuf.st_nlink != 1) { /* multiple links may be worrisome */ sprintf (tmp,"WARNING: multiple links to file %.80s",path); mm_log (tmp,WARN); } if (sbuf.st_mode & 0111) { /* executable files may be worrisome */ sprintf (tmp,"WARNING: file %.80s is executable",path); mm_log (tmp,WARN); } } if (sbuf.st_mode & 0002) { /* public-write files may be worrisome */ sprintf (tmp,"WARNING: file %.80s is publicly-writable",path); mm_log (tmp,WARN); } if (sbuf.st_mode & 0004) { /* public-write files may be worrisome */ sprintf (tmp,"WARNING: file %.80s is publicly-readable",path); mm_log (tmp,WARN); } /* check site-written quota procedure */ if (!tmail_quota (st,path,uid,tmp,sender,precedence)) return fail (tmp,-1); /* so far, so good */ sprintf (tmp,"%s appending to %.80s (%s %.80s)", prt ? prt->dtb->name : "default",mailbox, ((sbuf.st_mode & S_IFMT) == S_IFDIR) ? "directory" : "file",path); mm_dlog (tmp); /* do the append now! */ if (!mail_append (prt,mailbox,st)) { sprintf (tmp,"message delivery failed to %.80s",path); return fail (tmp,EX_CANTCREAT); } /* note success */ sprintf (tmp,"delivered to %.80s",path); mm_log (tmp,NIL); /* make sure nothing evil this way comes */ return delivery_unsafe (path,uid,&sbuf,tmp);}/* Verify that delivery is safe * Accepts: path name * user id * stat buffer * scratch buffer for messages * Returns: NIL if delivery is safe, error code if unsafe */int delivery_unsafe (char *path,uid_t uid,struct stat *sbuf,char *tmp){ u_short type; sprintf (tmp,"Verifying safe delivery to %.80s by UID %ld",path,(long) uid); mm_dlog (tmp); /* prepare message just in case */ sprintf (tmp,"delivery to %.80s unsafe: ",path); /* unsafe if can't get its status */ if (lstat (path,sbuf)) strcat (tmp,strerror (errno)); else if (sbuf->st_uid != uid) /* unsafe if UID does not match */ sprintf (tmp + strlen (tmp),"uid mismatch (%ld != %ld)", (long) sbuf->st_uid,(long) uid); /* check file type */ else switch (sbuf->st_mode & S_IFMT) { case S_IFDIR: /* directory is always OK */ return NIL; case S_IFREG: /* file is unsafe if setuid */ if (sbuf->st_mode & S_ISUID) strcat (tmp,"setuid file"); /* or setgid */ else if (sbuf->st_mode & S_ISGID) strcat (tmp,"setgid file"); else return NIL; /* otherwise safe */ break; case S_IFCHR: strcat (tmp,"character special"); break; case S_IFBLK: strcat (tmp,"block special"); break; case S_IFLNK: strcat (tmp,"symbolic link"); break; case S_IFSOCK: strcat (tmp,"socket"); break; default: sprintf (tmp + strlen (tmp),"file type %07o",(unsigned int) type); } return fail (tmp,EX_CANTCREAT);}/* Report an error * Accepts: string to output */int fail (char *string,int code){ mm_log (string,ERROR); /* pass up the string */ switch (code) {#if T case EX_USAGE: case EX_OSERR: case EX_SOFTWARE: case EX_NOUSER: case EX_CANTCREAT: case EX_UNAVAILABLE: code = EX_TEMPFAIL; /* coerce these to TEMPFAIL */#endif break; case -1: /* quota failure... */ code = EX_CANTCREAT; /* ...really returns this code */ break; default: break; } return code; /* error code to return */}/* Get user name from username+mailbox specifier * Accepts: username/mailbox specifier * pointer to return location for mailbox specifier * Returns: user name, mailbox specifier value NIL if INBOX, patches out + */char *getusername (char *s,char **t){ if (*t = strchr (s,'+')) { /* have a mailbox specifier? */ *(*t)++ = '\0'; /* yes, tie off user name */ /* user+ and user+INBOX same as user */ if (!**t || !compare_cstring ((unsigned char *) *t,"INBOX")) *t = NIL; } return s; /* return user name */}/* Co-routines from MAIL library *//* Message matches a search * Accepts: MAIL stream * message number */void mm_searched (MAILSTREAM *stream,unsigned long msgno){ fatal ("mm_searched() call");}/* Message exists (i.e. there are that many messages in the mailbox) * Accepts: MAIL stream * message number */void mm_exists (MAILSTREAM *stream,unsigned long number){ fatal ("mm_exists() call");}/* Message expunged * Accepts: MAIL stream * message number */void mm_expunged (MAILSTREAM *stream,unsigned long number){ fatal ("mm_expunged() call");}/* Message flags update seen * Accepts: MAIL stream * message number */void mm_flags (MAILSTREAM *stream,unsigned long number){}/* Mailbox found * Accepts: MAIL stream * delimiter * mailbox name * mailbox attributes */void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes){ fatal ("mm_list() call");}/* Subscribed mailbox found * Accepts: MAIL stream * delimiter * mailbox name * mailbox attributes */void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes){ fatal ("mm_lsub() call");}/* Mailbox status * Accepts: MAIL stream * mailbox name * mailbox status */void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status){ fatal ("mm_status() call");}/* Notification event * Accepts: MAIL stream * string to log * error flag */void mm_notify (MAILSTREAM *stream,char *string,long errflg){ char tmp[MAILTMPLEN]; tmp[11] = '\0'; /* see if TRYCREATE */ if (!strcmp (ucase (strncpy (tmp,string,11)),"[TRYCREATE]")) trycreate = T; mm_log (string,errflg); /* just do mm_log action */}/* Log an event for the user to see * Accepts: string to log * error flag */void mm_log (char *string,long errflg){ if (trycreate)mm_dlog(string);/* debug logging only if trycreate in effect */ else { /* ordinary logging */ fprintf (stderr,"%s\n",string); switch (errflg) { case NIL: /* no error */ syslog (LOG_INFO,"%s",string); break; case PARSE: /* parsing problem */ case WARN: /* warning */ syslog (LOG_WARNING,"%s",string); break; case ERROR: /* error */ default: syslog (LOG_ERR,"%s",string); break; } }}/* Log an event to debugging telemetry * Accepts: string to log */void mm_dlog (char *string){ if (debug) fprintf (stderr,"%s\n",string); syslog (LOG_DEBUG,"%s",string);}/* Get user name and password for this host * Accepts: parse of network mailbox name * where to return user name * where to return password * trial count */void mm_login (NETMBX *mb,char *username,char *password,long trial){ fatal ("mm_login() call");}/* About to enter critical code * Accepts: stream */void mm_critical (MAILSTREAM *stream){ critical = T; /* note in critical code */}/* About to exit critical code * Accepts: stream */void mm_nocritical (MAILSTREAM *stream){ critical = NIL; /* note not in critical code */}/* Disk error found * Accepts: stream * system error code * flag indicating that mailbox may be clobbered * Returns: T if user wants to abort */long mm_diskerror (MAILSTREAM *stream,long errcode,long serious){ return T;}/* Log a fatal error event * Accepts: string to log */void mm_fatal (char *string){ printf ("?%s\n",string); /* shouldn't happen normally */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -