📄 news.c
字号:
/* ======================================================================== * Copyright 1988-2007 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: News routines * * Author: Mark Crispin * Networks and Distributed Computing * Computing & Communications * University of Washington * Administration Building, AG-44 * Seattle, WA 98195 * Internet: MRC@CAC.Washington.EDU * * Date: 4 September 1991 * Last Edited: 30 January 2007 */#include <stdio.h>#include <ctype.h>#include <errno.h>extern int errno; /* just in case */#include "mail.h"#include "osdep.h"#include <sys/stat.h>#include <sys/time.h>#include "misc.h"#include "newsrc.h"#include "fdstring.h"/* news_load_message() flags */#define NLM_HEADER 0x1 /* load message text */#define NLM_TEXT 0x2 /* load message text *//* NEWS I/O stream local data */ typedef struct news_local { unsigned int dirty : 1; /* disk copy of .newsrc needs updating */ char *dir; /* spool directory name */ char *name; /* local mailbox name */ unsigned char buf[CHUNKSIZE]; /* scratch buffer */ unsigned long cachedtexts; /* total size of all cached texts */} NEWSLOCAL;/* Convenient access to local data */#define LOCAL ((NEWSLOCAL *) stream->local)/* Function prototypes */DRIVER *news_valid (char *name);DRIVER *news_isvalid (char *name,char *mbx);void *news_parameters (long function,void *value);void news_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents);void news_list (MAILSTREAM *stream,char *ref,char *pat);void news_lsub (MAILSTREAM *stream,char *ref,char *pat);long news_canonicalize (char *ref,char *pat,char *pattern);long news_subscribe (MAILSTREAM *stream,char *mailbox);long news_unsubscribe (MAILSTREAM *stream,char *mailbox);long news_create (MAILSTREAM *stream,char *mailbox);long news_delete (MAILSTREAM *stream,char *mailbox);long news_rename (MAILSTREAM *stream,char *old,char *newname);MAILSTREAM *news_open (MAILSTREAM *stream);int news_select (struct direct *name);int news_numsort (const void *d1,const void *d2);void news_close (MAILSTREAM *stream,long options);void news_fast (MAILSTREAM *stream,char *sequence,long flags);void news_flags (MAILSTREAM *stream,char *sequence,long flags);void news_load_message (MAILSTREAM *stream,unsigned long msgno,long flags);char *news_header (MAILSTREAM *stream,unsigned long msgno, unsigned long *length,long flags);long news_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);void news_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt);long news_ping (MAILSTREAM *stream);void news_check (MAILSTREAM *stream);long news_expunge (MAILSTREAM *stream,char *sequence,long options);long news_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);long news_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);/* News routines *//* Driver dispatch used by MAIL */DRIVER newsdriver = { "news", /* driver name */ /* driver flags */ DR_NEWS|DR_READONLY|DR_NOFAST|DR_NAMESPACE|DR_NONEWMAIL|DR_DIRFMT, (DRIVER *) NIL, /* next driver */ news_valid, /* mailbox is valid for us */ news_parameters, /* manipulate parameters */ news_scan, /* scan mailboxes */ news_list, /* find mailboxes */ news_lsub, /* find subscribed mailboxes */ news_subscribe, /* subscribe to mailbox */ news_unsubscribe, /* unsubscribe from mailbox */ news_create, /* create mailbox */ news_delete, /* delete mailbox */ news_rename, /* rename mailbox */ mail_status_default, /* status of mailbox */ news_open, /* open mailbox */ news_close, /* close mailbox */ news_fast, /* fetch message "fast" attributes */ news_flags, /* fetch message flags */ NIL, /* fetch overview */ NIL, /* fetch message envelopes */ news_header, /* fetch message header */ news_text, /* fetch message body */ NIL, /* fetch partial message text */ NIL, /* unique identifier */ NIL, /* message number */ NIL, /* modify flags */ news_flagmsg, /* per-message modify flags */ NIL, /* search for message based on criteria */ NIL, /* sort messages */ NIL, /* thread messages */ news_ping, /* ping mailbox to see if still alive */ news_check, /* check for new messages */ news_expunge, /* expunge deleted messages */ news_copy, /* copy messages to another mailbox */ news_append, /* append string message to mailbox */ NIL /* garbage collect stream */}; /* prototype stream */MAILSTREAM newsproto = {&newsdriver};/* News validate mailbox * Accepts: mailbox name * Returns: our driver if name is valid, NIL otherwise */DRIVER *news_valid (char *name){ int fd; char *s,*t,*u; struct stat sbuf; if ((name[0] == '#') && (name[1] == 'n') && (name[2] == 'e') && (name[3] == 'w') && (name[4] == 's') && (name[5] == '.') && !strchr (name,'/') && !stat ((char *) mail_parameters (NIL,GET_NEWSSPOOL,NIL),&sbuf) && ((fd = open ((char *) mail_parameters (NIL,GET_NEWSACTIVE,NIL),O_RDONLY, NIL)) >= 0)) { fstat (fd,&sbuf); /* get size of active file */ /* slurp in active file */ read (fd,t = s = (char *) fs_get (sbuf.st_size+1),sbuf.st_size); s[sbuf.st_size] = '\0'; /* tie off file */ close (fd); /* flush file */ while (*t && (u = strchr (t,' '))) { *u++ = '\0'; /* tie off at end of name */ if (!strcmp (name+6,t)) { fs_give ((void **) &s); /* flush data */ return &newsdriver; } t = 1 + strchr (u,'\n'); /* next line */ } fs_give ((void **) &s); /* flush data */ } return NIL; /* return status */}/* News manipulate driver parameters * Accepts: function code * function-dependent value * Returns: function-dependent return value */void *news_parameters (long function,void *value){ return (function == GET_NEWSRC) ? env_parameters (function,value) : NIL;}/* News scan mailboxes * Accepts: mail stream * reference * pattern to search * string to scan */void news_scan (MAILSTREAM *stream,char *ref,char *pat,char *contents){ char tmp[MAILTMPLEN]; if (news_canonicalize (ref,pat,tmp)) mm_log ("Scan not valid for news mailboxes",ERROR);}/* News find list of newsgroups * Accepts: mail stream * reference * pattern to search */void news_list (MAILSTREAM *stream,char *ref,char *pat){ int fd; int i; char *s,*t,*u,*r,pattern[MAILTMPLEN],name[MAILTMPLEN]; struct stat sbuf; if (!pat || !*pat) { /* empty pattern? */ if (news_canonicalize (ref,"*",pattern)) { /* tie off name at root */ if (s = strchr (pattern,'.')) *++s = '\0'; else pattern[0] = '\0'; mm_list (stream,'.',pattern,LATT_NOSELECT); } } else if (news_canonicalize (ref,pat,pattern) && !stat ((char *) mail_parameters (NIL,GET_NEWSSPOOL,NIL),&sbuf) && ((fd = open ((char *) mail_parameters (NIL,GET_NEWSACTIVE,NIL), O_RDONLY,NIL)) >= 0)) { fstat (fd,&sbuf); /* get file size and read data */ read (fd,s = (char *) fs_get (sbuf.st_size + 1),sbuf.st_size); close (fd); /* close file */ s[sbuf.st_size] = '\0'; /* tie off string */ strcpy (name,"#news."); /* write initial prefix */ i = strlen (pattern); /* length of pattern */ if (pattern[--i] != '%') i = 0; if (t = strtok_r (s,"\n",&r)) do if (u = strchr (t,' ')) { *u = '\0'; /* tie off at end of name */ strcpy (name + 6,t); /* make full form of name */ if (pmatch_full (name,pattern,'.')) mm_list (stream,'.',name,NIL); else if (i && (u = strchr (name + i,'.'))) { *u = '\0'; /* tie off at delimiter, see if matches */ if (pmatch_full (name,pattern,'.')) mm_list (stream,'.',name,LATT_NOSELECT); } } while (t = strtok_r (NIL,"\n",&r)); fs_give ((void **) &s); }}/* News find list of subscribed newsgroups * Accepts: mail stream * reference * pattern to search */void news_lsub (MAILSTREAM *stream,char *ref,char *pat){ char pattern[MAILTMPLEN]; /* return data from newsrc */ if (news_canonicalize (ref,pat,pattern)) newsrc_lsub (stream,pattern);}/* News canonicalize newsgroup name * Accepts: reference * pattern * returned single pattern * Returns: T on success, NIL on failure */long news_canonicalize (char *ref,char *pat,char *pattern){ unsigned long i; char *s; if (ref && *ref) { /* have a reference */ strcpy (pattern,ref); /* copy reference to pattern */ /* # overrides mailbox field in reference */ if (*pat == '#') strcpy (pattern,pat); /* pattern starts, reference ends, with . */ else if ((*pat == '.') && (pattern[strlen (pattern) - 1] == '.')) strcat (pattern,pat + 1); /* append, omitting one of the period */ else strcat (pattern,pat); /* anything else is just appended */ } else strcpy (pattern,pat); /* just have basic name */ if ((pattern[0] == '#') && (pattern[1] == 'n') && (pattern[2] == 'e') && (pattern[3] == 'w') && (pattern[4] == 's') && (pattern[5] == '.') && !strchr (pattern,'/')) { /* count wildcards */ for (i = 0, s = pattern; *s; *s++) if ((*s == '*') || (*s == '%')) ++i; /* success if not too many */ if (i <= MAXWILDCARDS) return LONGT; MM_LOG ("Excessive wildcards in LIST/LSUB",ERROR); } return NIL;}/* News subscribe to mailbox * Accepts: mail stream * mailbox to add to subscription list * Returns: T on success, NIL on failure */long news_subscribe (MAILSTREAM *stream,char *mailbox){ return news_valid (mailbox) ? newsrc_update (stream,mailbox+6,':') : NIL;}/* NEWS unsubscribe to mailbox * Accepts: mail stream * mailbox to delete from subscription list * Returns: T on success, NIL on failure */long news_unsubscribe (MAILSTREAM *stream,char *mailbox){ return news_valid (mailbox) ? newsrc_update (stream,mailbox+6,'!') : NIL;}/* News create mailbox * Accepts: mail stream * mailbox name to create * Returns: T on success, NIL on failure */long news_create (MAILSTREAM *stream,char *mailbox){ return NIL; /* never valid for News */}/* News delete mailbox * mailbox name to delete * Returns: T on success, NIL on failure */long news_delete (MAILSTREAM *stream,char *mailbox){ return NIL; /* never valid for News */}/* News rename mailbox * Accepts: mail stream * old mailbox name * new mailbox name * Returns: T on success, NIL on failure */long news_rename (MAILSTREAM *stream,char *old,char *newname){ return NIL; /* never valid for News */}/* News open * Accepts: stream to open * Returns: stream on success, NIL on failure */MAILSTREAM *news_open (MAILSTREAM *stream){ long i,nmsgs; char *s,tmp[MAILTMPLEN]; struct direct **names = NIL; /* return prototype for OP_PROTOTYPE call */ if (!stream) return &newsproto; if (stream->local) fatal ("news recycle stream"); /* build directory name */ sprintf (s = tmp,"%s/%s",(char *) mail_parameters (NIL,GET_NEWSSPOOL,NIL), stream->mailbox + 6); while (s = strchr (s,'.')) *s = '/'; /* scan directory */ if ((nmsgs = scandir (tmp,&names,news_select,news_numsort)) >= 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -