📄 news.c
字号:
mail_exists (stream,nmsgs); /* notify upper level that messages exist */ stream->local = fs_get (sizeof (NEWSLOCAL)); LOCAL->dirty = NIL; /* no update to .newsrc needed yet */ LOCAL->dir = cpystr (tmp); /* copy directory name for later */ LOCAL->name = cpystr (stream->mailbox + 6); for (i = 0; i < nmsgs; ++i) { stream->uid_last = mail_elt (stream,i+1)->private.uid = atoi (names[i]->d_name); fs_give ((void **) &names[i]); } s = (void *) names; /* stupid language */ fs_give ((void **) &s); /* free directory */ LOCAL->cachedtexts = 0; /* no cached texts */ stream->sequence++; /* bump sequence number */ stream->rdonly = stream->perm_deleted = T; /* UIDs are always valid */ stream->uid_validity = 0xbeefface; /* read .newsrc entries */ mail_recent (stream,newsrc_read (LOCAL->name,stream)); /* notify if empty newsgroup */ if (!(stream->nmsgs || stream->silent)) { sprintf (tmp,"Newsgroup %s is empty",LOCAL->name); mm_log (tmp,WARN); } } else mm_log ("Unable to scan newsgroup spool directory",ERROR); return LOCAL ? stream : NIL; /* if stream is alive, return to caller */}/* News file name selection test * Accepts: candidate directory entry * Returns: T to use file name, NIL to skip it */int news_select (struct direct *name){ char c; char *s = name->d_name; while (c = *s++) if (!isdigit (c)) return NIL; return T;}/* News file name comparision * Accepts: first candidate directory entry * second candidate directory entry * Returns: negative if d1 < d2, 0 if d1 == d2, postive if d1 > d2 */int news_numsort (const void *d1,const void *d2){ return atoi ((*(struct direct **) d1)->d_name) - atoi ((*(struct direct **) d2)->d_name);}/* News close * Accepts: MAIL stream * option flags */void news_close (MAILSTREAM *stream,long options){ if (LOCAL) { /* only if a file is open */ news_check (stream); /* dump final checkpoint */ if (LOCAL->dir) fs_give ((void **) &LOCAL->dir); if (LOCAL->name) fs_give ((void **) &LOCAL->name); /* nuke the local data */ fs_give ((void **) &stream->local); stream->dtb = NIL; /* log out the DTB */ }}/* News fetch fast information * Accepts: MAIL stream * sequence * option flags */void news_fast (MAILSTREAM *stream,char *sequence,long flags){ MESSAGECACHE *elt; unsigned long i; /* set up metadata for all messages */ if (stream && LOCAL && ((flags & FT_UID) ? mail_uid_sequence (stream,sequence) : mail_sequence (stream,sequence))) for (i = 1; i <= stream->nmsgs; i++) if ((elt = mail_elt (stream,i))->sequence && !(elt->day && elt->rfc822_size)) news_load_message (stream,i,NIL);}/* News fetch flags * Accepts: MAIL stream * sequence * option flags */void news_flags (MAILSTREAM *stream,char *sequence,long flags){ unsigned long i; if ((flags & FT_UID) ? /* validate all elts */ mail_uid_sequence (stream,sequence) : mail_sequence (stream,sequence)) for (i = 1; i <= stream->nmsgs; i++) mail_elt (stream,i)->valid = T;}/* News load message into cache * Accepts: MAIL stream * message # * option flags */void news_load_message (MAILSTREAM *stream,unsigned long msgno,long flags){ unsigned long i,j,nlseen; int fd; unsigned char c,*t; struct stat sbuf; MESSAGECACHE *elt; FDDATA d; STRING bs; elt = mail_elt (stream,msgno);/* get elt */ /* build message file name */ sprintf (LOCAL->buf,"%s/%lu",LOCAL->dir,elt->private.uid); /* anything we need not currently cached? */ if ((!elt->day || !elt->rfc822_size || ((flags & NLM_HEADER) && !elt->private.msg.header.text.data) || ((flags & NLM_TEXT) && !elt->private.msg.text.text.data)) && ((fd = open (LOCAL->buf,O_RDONLY,NIL)) >= 0)) { fstat (fd,&sbuf); /* get file metadata */ d.fd = fd; /* set up file descriptor */ d.pos = 0; /* start of file */ d.chunk = LOCAL->buf; d.chunksize = CHUNKSIZE; INIT (&bs,fd_string,&d,sbuf.st_size); if (!elt->day) { /* set internaldate to file date */ struct tm *tm = gmtime (&sbuf.st_mtime); elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1; elt->year = tm->tm_year + 1900 - BASEYEAR; elt->hours = tm->tm_hour; elt->minutes = tm->tm_min; elt->seconds = tm->tm_sec; elt->zhours = 0; elt->zminutes = 0; } if (!elt->rfc822_size) { /* know message size yet? */ for (i = 0, j = SIZE (&bs), nlseen = 0; j--; ) switch (SNX (&bs)) { case '\015': /* unlikely carriage return */ if (!j || (CHR (&bs) != '\012')) { i++; /* ugh, raw CR */ nlseen = NIL; break; } SNX (&bs); /* eat the line feed, drop in */ case '\012': /* line feed? */ i += 2; /* count a CRLF */ /* header size known yet? */ if (!elt->private.msg.header.text.size && nlseen) { /* note position in file */ elt->private.special.text.size = GETPOS (&bs); /* and CRLF-adjusted size */ elt->private.msg.header.text.size = i; } nlseen = T; /* note newline seen */ break; default: /* ordinary chararacter */ i++; nlseen = NIL; break; } SETPOS (&bs,0); /* restore old position */ elt->rfc822_size = i; /* note that we have size now */ /* header is entire message if no delimiter */ if (!elt->private.msg.header.text.size) elt->private.msg.header.text.size = elt->rfc822_size; /* text is remainder of message */ elt->private.msg.text.text.size = elt->rfc822_size - elt->private.msg.header.text.size; } /* need to load cache with message data? */ if (((flags & NLM_HEADER) && !elt->private.msg.header.text.data) || ((flags & NLM_TEXT) && !elt->private.msg.text.text.data)) { /* purge cache if too big */ if (LOCAL->cachedtexts > max (stream->nmsgs * 4096,2097152)) { /* just can't keep that much */ mail_gc (stream,GC_TEXTS); LOCAL->cachedtexts = 0; } if ((flags & NLM_HEADER) && !elt->private.msg.header.text.data) { t = elt->private.msg.header.text.data = (unsigned char *) fs_get (elt->private.msg.header.text.size + 1); LOCAL->cachedtexts += elt->private.msg.header.text.size; /* read in message header */ for (i = 0; i <= elt->private.msg.header.text.size; i++) switch (c = SNX (&bs)) { case '\015': /* unlikely carriage return */ *t++ = c; if ((CHR (&bs) == '\012')) *t++ = SNX (&bs); break; case '\012': /* line feed? */ *t++ = '\015'; default: *t++ = c; break; } *t = '\0'; /* tie off string */ } if ((flags & NLM_TEXT) && !elt->private.msg.text.text.data) { t = elt->private.msg.text.text.data = (unsigned char *) fs_get (elt->private.msg.text.text.size + 1); SETPOS (&bs,elt->private.msg.header.text.size); LOCAL->cachedtexts += elt->private.msg.text.text.size; /* read in message text */ for (i = 0; i <= elt->private.msg.text.text.size; i++) switch (c = SNX (&bs)) { case '\015': /* unlikely carriage return */ *t++ = c; if ((CHR (&bs) == '\012')) *t++ = SNX (&bs); break; case '\012': /* line feed? */ *t++ = '\015'; default: *t++ = c; break; } *t = '\0'; /* tie off string */ } } close (fd); /* flush message file */ }}/* News fetch message header * Accepts: MAIL stream * message # to fetch * pointer to returned header text length * option flags * Returns: message header in RFC822 format */char *news_header (MAILSTREAM *stream,unsigned long msgno, unsigned long *length,long flags){ MESSAGECACHE *elt; *length = 0; /* default to empty */ if (flags & FT_UID) return "";/* UID call "impossible" */ elt = mail_elt (stream,msgno);/* get elt */ if (!elt->private.msg.header.text.data) news_load_message (stream,msgno,NLM_HEADER); *length = elt->private.msg.header.text.size; return (char *) elt->private.msg.header.text.data;}/* News fetch message text (body only) * Accepts: MAIL stream * message # to fetch * pointer to returned stringstruct * option flags * Returns: T on success, NIL on failure */long news_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags){ MESSAGECACHE *elt; /* UID call "impossible" */ if (flags & FT_UID) return NIL; elt = mail_elt (stream,msgno);/* get elt */ /* snarf message if don't have it yet */ if (!elt->private.msg.text.text.data) { news_load_message (stream,msgno,NLM_TEXT); if (!elt->private.msg.text.text.data) return NIL; } if (!(flags & FT_PEEK)) { /* mark as seen */ mail_elt (stream,msgno)->seen = T; mm_flags (stream,msgno); } INIT (bs,mail_string,elt->private.msg.text.text.data, elt->private.msg.text.text.size); return T;}/* News per-message modify flag * Accepts: MAIL stream * message cache element */void news_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt){ if (!LOCAL->dirty) { /* only bother checking if not dirty yet */ if (elt->valid) { /* if done, see if deleted changed */ if (elt->sequence != elt->deleted) LOCAL->dirty = T; elt->sequence = T; /* leave the sequence set */ } /* note current setting of deleted flag */ else elt->sequence = elt->deleted; }}/* News ping mailbox * Accepts: MAIL stream * Returns: T if stream alive, else NIL */long news_ping (MAILSTREAM *stream){ return T; /* always alive */}/* News check mailbox * Accepts: MAIL stream */void news_check (MAILSTREAM *stream){ /* never do if no updates */ if (LOCAL->dirty) newsrc_write (LOCAL->name,stream); LOCAL->dirty = NIL;}/* News expunge mailbox * Accepts: MAIL stream * sequence to expunge if non-NIL * expunge options * Returns: T if success, NIL if failure */long news_expunge (MAILSTREAM *stream,char *sequence,long options){ if (!stream->silent) mm_log ("Expunge ignored on readonly mailbox",NIL); return LONGT;}/* News copy message(s) * Accepts: MAIL stream * sequence * destination mailbox * option flags * Returns: T if copy successful, else NIL */long news_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){ mailproxycopy_t pc = (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL); if (pc) return (*pc) (stream,sequence,mailbox,options); mm_log ("Copy not valid for News",ERROR); return NIL;}/* News append message from stringstruct * Accepts: MAIL stream * destination mailbox * append callback function * data for callback * Returns: T if append successful, else NIL */long news_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){ mm_log ("Append not valid for news",ERROR); return NIL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -