/* length=0 specifies ASCIIZ data */ int SMBCALL smb_getmsgidx_by_hash(smb_t* smb, smbmsg_t* msg, unsigned source ,unsigned flags, const void* data, size_t length) { int retval; size_t n; hash_t** hashes; hash_t found; if((hashes=(hash_t**)malloc(sizeof(hash_t*)*2))==NULL) return(SMB_ERR_MEM); if(length==0) hashes[0]=smb_hashstr(0,0,source,flags,data); else hashes[0]=smb_hash(0,0,source,flags,data,length); if(hashes[0]==NULL) return(SMB_ERR_MEM); hashes[1]=NULL; /* terminate list */ if((retval=smb_findhash(smb, hashes, &found, 1<<source, FALSE))==SMB_SUCCESS) { if(found.number==0) retval=SMB_FAILURE; /* use better error value here? */ else { msg->hdr.number=found.number; retval=smb_getmsgidx(smb, msg); } } FREE_LIST(hashes,n); return(retval); }
ulong first_msg() { smbmsg_t msg; msg.offset=0; msg.hdr.number=0; if(smb_getmsgidx(&smb,&msg)) /* Get first message index */ return(0); return(msg.idx.number); }
int sbbs_t::loadmsg(smbmsg_t *msg, ulong number) { char str[128]; int i; if(msg->idx.offset) { /* Load by offset if specified */ if((i=smb_lockmsghdr(&smb,msg))!=0) { errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); return(0); } i=smb_getmsghdr(&smb,msg); if(i==SMB_SUCCESS) { if(msg->hdr.number==number) return(1); /* Wrong offset */ smb_freemsgmem(msg); } smb_unlockmsghdr(&smb,msg); } msg->hdr.number=number; if((i=smb_getmsgidx(&smb,msg))!=SMB_SUCCESS) /* Message is deleted */ return(0); if((i=smb_lockmsghdr(&smb,msg))!=SMB_SUCCESS) { errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); return(0); } if((i=smb_getmsghdr(&smb,msg))!=SMB_SUCCESS) { sprintf(str,"(%06"PRIX32") #%"PRIu32"/%lu %s",msg->idx.offset,msg->idx.number ,number,smb.file); smb_unlockmsghdr(&smb,msg); errormsg(WHERE,ERR_READ,str,i,smb.last_error); return(0); } return(msg->total_hfields); }
time_t sbbs_t::getmsgtime(uint subnum, ulong ptr) { int i; smbmsg_t msg; idxrec_t lastidx; sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code); smb.retry_time=cfg.smb_retry_time; smb.subnum=subnum; if((i=smb_open(&smb))!=0) { errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); return(0); } if(!filelength(fileno(smb.sid_fp))) { /* Empty base */ smb_close(&smb); return(0); } msg.offset=0; msg.hdr.number=0; if(smb_getmsgidx(&smb,&msg)) { /* Get first message index */ smb_close(&smb); return(0); } if(!ptr || msg.idx.number>=ptr) { /* ptr is before first message */ smb_close(&smb); return(msg.idx.time); /* so return time of first msg */ } if(smb_getlastidx(&smb,&lastidx)) { /* Get last message index */ smb_close(&smb); return(0); } if(lastidx.number<ptr) { /* ptr is after last message */ smb_close(&smb); return(lastidx.time); /* so return time of last msg */ } msg.idx.time=0; msg.hdr.number=ptr; if(!smb_getmsgidx(&smb,&msg)) { smb_close(&smb); return(msg.idx.time); } if(ptr-msg.idx.number < lastidx.number-ptr) { msg.offset=0; msg.idx.number=0; while(msg.idx.number<ptr) { msg.hdr.number=0; if(smb_getmsgidx(&smb,&msg) || msg.idx.number>=ptr) break; msg.offset++; } smb_close(&smb); return(msg.idx.time); } ptr--; while(ptr) { msg.hdr.number=ptr; if(!smb_getmsgidx(&smb,&msg)) break; ptr--; } smb_close(&smb); return(msg.idx.time); }
void sbbs_t::readmail(uint usernumber, int which) { char str[256],str2[256],str3[256],done=0,domsg=1 ,*p,*tp,*sp,ch; char tmp[512]; int i,j; int error; int mismatches=0,act; long length,l,lm_mode; ulong last; bool replied; file_t fd; mail_t *mail; smbmsg_t msg; if(which==MAIL_SENT && useron.rest&FLAG('K')) { bputs(text[R_ReadSentMail]); return; } msg.total_hfields=0; /* init to NULL, cause not allocated yet */ fd.dir=cfg.total_dirs+1; /* temp dir for file attachments */ if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) { errormsg(WHERE,ERR_OPEN,"MAIL",i); return; } sprintf(smb.file,"%smail",cfg.data_dir); smb.retry_time=cfg.smb_retry_time; smb.subnum=INVALID_SUB; if((i=smb_open(&smb))!=0) { smb_stack(&smb,SMB_STACK_POP); errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); return; } if(cfg.sys_misc&SM_SYSVDELM && (SYSOP || cfg.sys_misc&SM_USRVDELM)) lm_mode=LM_INCDEL; else lm_mode=0; mail=loadmail(&smb,&smb.msgs,usernumber,which,lm_mode); if(!smb.msgs) { if(which==MAIL_SENT) bputs(text[NoMailSent]); else if(which==MAIL_ALL) bputs(text[NoMailOnSystem]); else bputs(text[NoMailWaiting]); smb_close(&smb); smb_stack(&smb,SMB_STACK_POP); return; } last=smb.status.last_msg; if(which==MAIL_SENT) act=NODE_RSML; else if(which==MAIL_ALL) act=NODE_SYSP; else act=NODE_RMAL; action=act; if(smb.msgs>1 && which!=MAIL_ALL) { if(which==MAIL_SENT) bputs(text[MailSentLstHdr]); else bputs(text[MailWaitingLstHdr]); for(smb.curmsg=0;smb.curmsg<smb.msgs && !msgabort();smb.curmsg++) { if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=mail[smb.curmsg].offset; if(!loadmsg(&msg,mail[smb.curmsg].number)) continue; smb_unlockmsghdr(&smb,&msg); bprintf(text[MailWaitingLstFmt],smb.curmsg+1 ,which==MAIL_SENT ? msg.to : (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP ? text[Anonymous] : msg.from ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R' : msg.hdr.attr&MSG_READ ? ' ' : msg.from_net.type || msg.to_net.type ? 'N':'*' ,msg.subj); smb_freemsgmem(&msg); msg.total_hfields=0; } ASYNC; if(!(sys_status&SS_ABORT)) { bprintf(text[StartWithN],1L); if((long)(smb.curmsg=getnum(smb.msgs))>0) smb.curmsg--; else if((long)smb.curmsg==-1) { free(mail); smb_close(&smb); smb_stack(&smb,SMB_STACK_POP); return; } } sys_status&=~SS_ABORT; } else { smb.curmsg=0; if(which==MAIL_ALL) domsg=0; } if(which==MAIL_SENT) { sprintf(str,"%s read sent mail",useron.alias); logline("E",str); } else if(which==MAIL_ALL) { sprintf(str,"%s read all mail",useron.alias); logline("S+",str); } else { sprintf(str,"%s read mail",useron.alias); logline("E",str); } if(useron.misc&RIP) { strcpy(str,which==MAIL_YOUR ? "mailread" : which==MAIL_ALL ? "allmail" : "sentmail"); menu(str); } while(online && !done) { action=act; if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=mail[smb.curmsg].offset; msg.idx.number=mail[smb.curmsg].number; msg.idx.to=mail[smb.curmsg].to; msg.idx.from=mail[smb.curmsg].from; msg.idx.subj=mail[smb.curmsg].subj; if((i=smb_locksmbhdr(&smb))!=0) { errormsg(WHERE,ERR_LOCK,smb.file,i); break; } if((i=smb_getstatus(&smb))!=0) { smb_unlocksmbhdr(&smb); errormsg(WHERE,ERR_READ,smb.file,i); break; } smb_unlocksmbhdr(&smb); if(smb.status.last_msg!=last) { /* New messages */ last=smb.status.last_msg; free(mail); mail=loadmail(&smb,&smb.msgs,usernumber,which,lm_mode); /* So re-load */ if(!smb.msgs) break; for(smb.curmsg=0;smb.curmsg<smb.msgs;smb.curmsg++) if(mail[smb.curmsg].number==msg.idx.number) break; if(smb.curmsg>=smb.msgs) smb.curmsg=(smb.msgs-1); continue; } if(!loadmsg(&msg,mail[smb.curmsg].number)) { /* Message header gone */ if(mismatches>5) { /* We can't do this too many times in a row */ errormsg(WHERE,ERR_CHK,"message number",mail[smb.curmsg].number); break; } free(mail); mail=loadmail(&smb,&smb.msgs,usernumber,which,lm_mode); if(!smb.msgs) break; if(smb.curmsg>(smb.msgs-1)) smb.curmsg=(smb.msgs-1); mismatches++; continue; } smb_unlockmsghdr(&smb,&msg); msg.idx.attr=msg.hdr.attr; mismatches=0; if(domsg && !(sys_status&SS_ABORT)) { show_msg(&msg ,msg.from_ext && msg.idx.from==1 && !msg.from_net.type ? 0:P_NOATCODES); if(msg.hdr.auxattr&MSG_FILEATTACH) { /* Attached file */ smb_getmsgidx(&smb,&msg); strcpy(str,msg.subj); /* filenames in title */ // strupr(str); tp=str; while(online) { p=strchr(tp,' '); if(p) *p=0; sp=strrchr(tp,'/'); /* sp is slash pointer */ if(!sp) sp=strrchr(tp,'\\'); if(sp) tp=sp+1; padfname(tp,fd.name); sprintf(str2,"%sfile/%04u.in/%s" /* str2 is path/fname */ ,cfg.data_dir,msg.idx.to,tp); length=flength(str2); if(length<1) bputs(text[FileNotFound]); else if(!(useron.exempt&FLAG('T')) && cur_cps && !SYSOP && length/(long)cur_cps>(time_t)timeleft) bputs(text[NotEnoughTimeToDl]); else { sprintf(str3,text[DownloadAttachedFileQ] ,tp,ultoac(length,tmp)); if(length>0L && yesno(str3)) { #if 0 /* no such thing as local logon */ if(online==ON_LOCAL) { bputs(text[EnterPath]); if(getstr(str3,60,K_LINE)) { backslashcolon(str3); sprintf(tmp,"%s%s",str3,tp); if(!mv(str2,tmp,which!=MAIL_YOUR)) { logon_dlb+=length; logon_dls++; useron.dls=(ushort)adjustuserrec(&cfg,useron.number ,U_DLS,5,1); useron.dlb=adjustuserrec(&cfg,useron.number ,U_DLB,10,length); bprintf(text[FileNBytesSent] ,fd.name,ultoac(length,tmp)); } } } else #endif { /* Remote User */ xfer_prot_menu(XFER_DOWNLOAD); mnemonics(text[ProtocolOrQuit]); strcpy(str3,"Q"); for(i=0;i<cfg.total_prots;i++) if(cfg.prot[i]->dlcmd[0] && chk_ar(cfg.prot[i]->ar,&useron)) { sprintf(tmp,"%c",cfg.prot[i]->mnemonic); strcat(str3,tmp); } ch=(char)getkeys(str3,0); for(i=0;i<cfg.total_prots;i++) if(cfg.prot[i]->dlcmd[0] && ch==cfg.prot[i]->mnemonic && chk_ar(cfg.prot[i]->ar,&useron)) break; if(i<cfg.total_prots) { error=protocol(cfg.prot[i],XFER_DOWNLOAD,str2,nulstr,false); if(checkprotresult(cfg.prot[i],error,&fd)) { if(which==MAIL_YOUR) remove(str2); logon_dlb+=length; /* Update stats */ logon_dls++; useron.dls=(ushort)adjustuserrec(&cfg,useron.number ,U_DLS,5,1); useron.dlb=adjustuserrec(&cfg,useron.number ,U_DLB,10,length); bprintf(text[FileNBytesSent] ,fd.name,ultoac(length,tmp)); sprintf(str3 ,"%s downloaded attached file: %s" ,useron.alias ,fd.name); logline("D-",str3); } autohangup(); } } } } if(!p) break; tp=p+1; while(*tp==' ') tp++; } sprintf(str,"%sfile/%04u.in",cfg.data_dir,usernumber); rmdir(str); } if(which==MAIL_YOUR && !(msg.hdr.attr&MSG_READ)) { mail[smb.curmsg].attr|=MSG_READ; if(thisnode.status==NODE_INUSE) telluser(&msg); if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=0; /* Search by number */ if(smb_locksmbhdr(&smb)==SMB_SUCCESS) { /* Lock the entire base */ if(loadmsg(&msg,msg.idx.number)) { msg.hdr.attr|=MSG_READ; msg.idx.attr=msg.hdr.attr; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i); smb_unlockmsghdr(&smb,&msg); } smb_unlocksmbhdr(&smb); } if(!msg.total_hfields) { /* unsuccessful reload */ domsg=0; continue; } } } else domsg=1; if(useron.misc&WIP) { strcpy(str,which==MAIL_YOUR ? "mailread" : which==MAIL_ALL ? "allmail" : "sentmail"); menu(str); } ASYNC; if(which==MAIL_SENT) bprintf(text[ReadingSentMail],smb.curmsg+1,smb.msgs); else if(which==MAIL_ALL) bprintf(text[ReadingAllMail],smb.curmsg+1,smb.msgs); else bprintf(text[ReadingMail],smb.curmsg+1,smb.msgs); sprintf(str,"ADFLNQRT?<>[]{}-+"); if(SYSOP) strcat(str,"CUSPH"); if(which!=MAIL_YOUR) strcat(str,"E"); l=getkeys(str,smb.msgs); if(l&0x80000000L) { if(l==-1) /* ctrl-c */ break; smb.curmsg=(l&~0x80000000L)-1; continue; } switch(l) { case 'A': /* Auto-reply to last piece */ case 'R': if(l==(cfg.sys_misc&SM_RA_EMU ? 'A' : 'R')) /* re-read last message */ break; if(which==MAIL_SENT) break; if((msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP) { bputs(text[CantReplyToAnonMsg]); break; } quotemsg(&msg,1); if(msg.from_net.addr==NULL) SAFECOPY(str,msg.from); else if(msg.from_net.type==NET_FIDO) /* FidoNet type */ SAFEPRINTF2(str,"%s@%s",msg.from ,smb_faddrtoa((faddr_t *)msg.from_net.addr,tmp)); else if(msg.from_net.type==NET_INTERNET) { if(msg.replyto_net.type==NET_INTERNET) SAFECOPY(str,(char *)msg.replyto_net.addr); else SAFECOPY(str,(char *)msg.from_net.addr); } else SAFEPRINTF2(str,"%s@%s",msg.from,(char*)msg.from_net.addr); SAFECOPY(str2,str); bputs(text[Email]); if(!getstr(str,64,K_EDIT|K_AUTODEL)) break; msg.hdr.number=msg.idx.number; smb_getmsgidx(&smb,&msg); if(!stricmp(str2,str)) /* Reply to sender */ sprintf(str2,text[Regarding],msg.subj); else /* Reply to other */ sprintf(str2,text[RegardingByOn],msg.subj,msg.from ,timestr((time_t *)&msg.hdr.when_written.time)); p=strrchr(str,'@'); if(p) { /* name @addr */ replied=netmail(str,msg.subj,WM_QUOTE); sprintf(str2,text[DeleteMailQ],msg.from); } else { if(!msg.from_net.type && !stricmp(str,msg.from)) replied=email(msg.idx.from,str2,msg.subj,WM_EMAIL|WM_QUOTE); else if(!stricmp(str,"SYSOP")) replied=email(1,str2,msg.subj,WM_EMAIL|WM_QUOTE); else if((i=finduser(str))!=0) replied=email(i,str2,msg.subj,WM_EMAIL|WM_QUOTE); else replied=false; sprintf(str2,text[DeleteMailQ],msg.from); } if(replied==true && !(msg.hdr.attr&MSG_REPLIED)) { if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=0; if(smb_locksmbhdr(&smb)==SMB_SUCCESS) { /* Lock the entire base */ if(loadmsg(&msg,msg.idx.number)) { msg.hdr.attr|=MSG_REPLIED; msg.idx.attr=msg.hdr.attr; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i); smb_unlockmsghdr(&smb,&msg); } smb_unlocksmbhdr(&smb); } } if(msg.hdr.attr&MSG_DELETE || !yesno(str2)) { if(smb.curmsg<smb.msgs-1) smb.curmsg++; else done=1; break; } /* Case 'D': must follow! */ case 'D': /* Delete last piece (toggle) */ if(msg.hdr.attr&MSG_PERMANENT) { bputs("\r\nPermanent message.\r\n"); domsg=0; break; } if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=0; if(smb_locksmbhdr(&smb)==SMB_SUCCESS) { /* Lock the entire base */ if(loadmsg(&msg,msg.idx.number)) { msg.hdr.attr^=MSG_DELETE; msg.idx.attr=msg.hdr.attr; // mail[smb.curmsg].attr=msg.hdr.attr; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i); smb_unlockmsghdr(&smb,&msg); } smb_unlocksmbhdr(&smb); } if(smb.curmsg<smb.msgs-1) smb.curmsg++; else done=1; break; case 'F': /* Forward last piece */ domsg=0; bputs(text[ForwardMailTo]); if(!getstr(str,LEN_ALIAS,cfg.uq&UQ_NOUPRLWR ? K_NONE:K_UPRLWR)) break; i=finduser(str); if(!i) break; domsg=1; if(smb.curmsg<smb.msgs-1) smb.curmsg++; else done=1; smb_getmsgidx(&smb,&msg); forwardmail(&msg,i); if(msg.hdr.attr&MSG_PERMANENT) break; sprintf(str2,text[DeleteMailQ],msg.from); if(!yesno(str2)) break; if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=0; if(smb_locksmbhdr(&smb)==SMB_SUCCESS) { /* Lock the entire base */ if(loadmsg(&msg,msg.idx.number)) { msg.hdr.attr|=MSG_DELETE; msg.idx.attr=msg.hdr.attr; // mail[smb.curmsg].attr=msg.hdr.attr; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i); smb_unlockmsghdr(&smb,&msg); } smb_unlocksmbhdr(&smb); } break; case 'H': domsg=0; msghdr(&msg); break; case 'L': /* List mail */ domsg=0; bprintf(text[StartWithN],(long)smb.curmsg+1); if((i=getnum(smb.msgs))>0) i--; else if(i==-1) break; else i=smb.curmsg; if(which==MAIL_SENT) bputs(text[MailSentLstHdr]); else if(which==MAIL_ALL) bputs(text[MailOnSystemLstHdr]); else bputs(text[MailWaitingLstHdr]); for(;i<smb.msgs && !msgabort();i++) { if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=mail[i].offset; if(!loadmsg(&msg,mail[i].number)) continue; smb_unlockmsghdr(&smb,&msg); if(which==MAIL_ALL) bprintf(text[MailOnSystemLstFmt] ,i+1,msg.from,msg.to ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R' : msg.hdr.attr&MSG_READ ? ' ' : msg.from_net.type || msg.to_net.type ? 'N':'*' ,msg.subj); else bprintf(text[MailWaitingLstFmt],i+1 ,which==MAIL_SENT ? msg.to : (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP ? text[Anonymous] : msg.from ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R' : msg.hdr.attr&MSG_READ ? ' ' : msg.from_net.type || msg.to_net.type ? 'N':'*' ,msg.subj); smb_freemsgmem(&msg); msg.total_hfields=0; } break; case 'Q': done=1; break; case 'C': /* Change attributes of last piece */ i=chmsgattr(msg.hdr.attr); if(msg.hdr.attr==i) break; if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=0; if(smb_locksmbhdr(&smb)==SMB_SUCCESS) { /* Lock the entire base */ if(loadmsg(&msg,msg.idx.number)) { msg.hdr.attr=msg.idx.attr=(ushort)i; if((i=smb_putmsg(&smb,&msg))!=0) errormsg(WHERE,ERR_WRITE,smb.file,i); smb_unlockmsghdr(&smb,&msg); } smb_unlocksmbhdr(&smb); } break; case '>': for(i=smb.curmsg+1;i<smb.msgs;i++) if(mail[i].subj==msg.idx.subj) break; if(i<smb.msgs) smb.curmsg=i; else domsg=0; break; case '<': /* Search Title backward */ for(i=smb.curmsg-1;i>-1;i--) if(mail[i].subj==msg.idx.subj) break; if(i>-1) smb.curmsg=i; else domsg=0; break; case '}': /* Search Author forward */ strcpy(str,msg.from); for(i=smb.curmsg+1;i<smb.msgs;i++) if(mail[i].from==msg.idx.from) break; if(i<smb.msgs) smb.curmsg=i; else domsg=0; break; case 'N': /* Got to next un-read message */ for(i=smb.curmsg+1;i<smb.msgs;i++) if(!(mail[i].attr&MSG_READ)) break; if(i<smb.msgs) smb.curmsg=i; else domsg=0; break; case '{': /* Search Author backward */ strcpy(str,msg.from); for(i=smb.curmsg-1;i>-1;i--) if(mail[i].from==msg.idx.from) break; if(i>-1) smb.curmsg=i; else domsg=0; break; case ']': /* Search To User forward */ strcpy(str,msg.to); for(i=smb.curmsg+1;i<smb.msgs;i++) if(mail[i].to==msg.idx.to) break; if(i<smb.msgs) smb.curmsg=i; else domsg=0; break; case '[': /* Search To User backward */ strcpy(str,msg.to); for(i=smb.curmsg-1;i>-1;i--) if(mail[i].to==msg.idx.to) break; if(i>-1) smb.curmsg=i; else domsg=0; break; case 0: case '+': if(smb.curmsg<smb.msgs-1) smb.curmsg++; else done=1; break; case '-': if(smb.curmsg>0) smb.curmsg--; break; case 'S': domsg=0; /* if(!yesno(text[SaveMsgToFile])) break; */ bputs(text[FileToWriteTo]); if(getstr(str,40,K_LINE)) msgtotxt(&msg,str,1,1); break; case 'E': editmsg(&msg,INVALID_SUB); break; case 'T': domsg=0; i=smb.curmsg; if(i) i++; j=i+10; if(j>smb.msgs) j=smb.msgs; if(which==MAIL_SENT) bputs(text[MailSentLstHdr]); else if(which==MAIL_ALL) bputs(text[MailOnSystemLstHdr]); else bputs(text[MailWaitingLstHdr]); for(;i<j;i++) { if(msg.total_hfields) smb_freemsgmem(&msg); msg.total_hfields=0; msg.idx.offset=mail[i].offset; if(!loadmsg(&msg,mail[i].number)) continue; smb_unlockmsghdr(&smb,&msg); if(which==MAIL_ALL) bprintf(text[MailOnSystemLstFmt] ,i+1,msg.from,msg.to ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R' : msg.hdr.attr&MSG_READ ? ' ' : msg.from_net.type || msg.to_net.type ? 'N':'*' ,msg.subj); else bprintf(text[MailWaitingLstFmt],i+1 ,which==MAIL_SENT ? msg.to : (msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP ? text[Anonymous] : msg.from ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_REPLIED ? 'R' : msg.hdr.attr&MSG_READ ? ' ' : msg.from_net.type || msg.to_net.type ? 'N':'*' ,msg.subj); smb_freemsgmem(&msg); msg.total_hfields=0; } smb.curmsg=(i-1); break; case 'U': /* user edit */ msg.hdr.number=msg.idx.number; smb_getmsgidx(&smb,&msg); useredit(which==MAIL_SENT ? msg.idx.to : msg.idx.from); break; case 'P': /* Purge author and all mail to/from */ if(noyes(text[AreYouSureQ])) break; msg.hdr.number=msg.idx.number; smb_getmsgidx(&smb,&msg); purgeuser(msg.idx.from); if(smb.curmsg<smb.msgs-1) smb.curmsg++; break; case '?': strcpy(str,which==MAIL_YOUR ? "mailread" : which==MAIL_ALL ? "allmail" : "sentmail"); menu(str); if(SYSOP && which==MAIL_SENT) menu("syssmail"); else if(SYSOP && which==MAIL_YOUR) menu("sysmailr"); /* Sysop Mail Read */ domsg=0; break; } } if(msg.total_hfields) smb_freemsgmem(&msg); if(smb.msgs) free(mail); /***************************************/ /* Delete messages marked for deletion */ /***************************************/ if(cfg.sys_misc&SM_DELEMAIL) { if((i=smb_locksmbhdr(&smb))!=0) /* Lock the base, so nobody */ errormsg(WHERE,ERR_LOCK,smb.file,i); /* messes with the index */ else delmail(usernumber,which); } smb_close(&smb); smb_stack(&smb,SMB_STACK_POP); }
void maint(void) { int i; ulong l,m,n,f,flagged=0; time_t now; smbmsg_t msg; idxrec_t *idx; printf("Maintaining %s\r\n",smb.file); now=time(NULL); i=smb_locksmbhdr(&smb); if(i) { fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n" ,beep,i,smb.last_error); return; } i=smb_getstatus(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n" ,beep,i,smb.last_error); return; } if(smb_open_hash(&smb) == SMB_SUCCESS) { ulong max_hashes=0; printf("Maintaining %s hash file\r\n", smb.file); if((smb.status.attr&(SMB_EMAIL|SMB_NOHASH)) == 0) { max_hashes = smb.status.max_msgs; if(smb.status.max_crcs > max_hashes) max_hashes = smb.status.max_crcs; } if(!max_hashes) { CHSIZE_FP(smb.hash_fp,0); } else if(filelength(fileno(smb.hash_fp)) > (long)(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t))) { if(fseek(smb.hash_fp, -((long)(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t))), SEEK_END) == 0) { hash_t* hashes = malloc(max_hashes * SMB_HASH_SOURCE_TYPES * sizeof(hash_t)); if(hashes != NULL) { if(fread(hashes, sizeof(hash_t), max_hashes * SMB_HASH_SOURCE_TYPES, smb.hash_fp) == max_hashes * SMB_HASH_SOURCE_TYPES) { CHSIZE_FP(smb.hash_fp,0); rewind(smb.hash_fp); fwrite(hashes, sizeof(hash_t), max_hashes * SMB_HASH_SOURCE_TYPES, smb.hash_fp); } free(hashes); } } } smb_close_hash(&smb); } if(!smb.status.total_msgs) { smb_unlocksmbhdr(&smb); printf("Empty\n"); return; } printf("Loading index...\n"); if((idx=(idxrec_t *)malloc(sizeof(idxrec_t)*smb.status.total_msgs)) ==NULL) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!Error allocating %u bytes of memory\n" ,beep,sizeof(idxrec_t)*smb.status.total_msgs); return; } fseek(smb.sid_fp,0L,SEEK_SET); for(l=0;l<smb.status.total_msgs;l++) { printf("%lu of %"PRIu32"\r" ,l+1,smb.status.total_msgs); if(!fread(&idx[l],1,sizeof(idxrec_t),smb.sid_fp)) break; } printf("\nDone.\n\n"); printf("Scanning for pre-flagged messages...\n"); for(m=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&MSG_DELETE) flagged++; } printf("\r100%% (%lu pre-flagged for deletion)\n",flagged); if(smb.status.max_age) { printf("Scanning for messages more than %u days old...\n" ,smb.status.max_age); for(m=f=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; if((ulong)now>idx[m].time && (now-idx[m].time)/(24L*60L*60L) >smb.status.max_age) { f++; flagged++; idx[m].attr|=MSG_DELETE; } } /* mark for deletion */ printf("\r100%% (%lu flagged for deletion due to age)\n",f); } printf("Scanning for read messages to be killed...\n"); for(m=f=0;m<l;m++) { printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0); if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) { f++; flagged++; idx[m].attr|=MSG_DELETE; } } printf("\r100%% (%lu flagged for deletion due to read status)\n",f); if(smb.status.max_msgs && l-flagged>smb.status.max_msgs) { printf("Flagging excess messages for deletion...\n"); for(m=n=0,f=flagged;l-flagged>smb.status.max_msgs && m<l;m++) { if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE)) continue; printf("%lu of %lu\r",++n,(l-f)-smb.status.max_msgs); flagged++; idx[m].attr|=MSG_DELETE; } /* mark for deletion */ printf("\nDone.\n\n"); } if(!flagged) { /* No messages to delete */ free(idx); smb_unlocksmbhdr(&smb); return; } if(!(mode&NOANALYSIS)) { printf("Freeing allocated header and data blocks for deleted messages...\n"); if(!(smb.status.attr&SMB_HYPERALLOC)) { i=smb_open_da(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_open_da returned %d: %s\n" ,beep,i,smb.last_error); bail(1); } i=smb_open_ha(&smb); if(i) { smb_unlocksmbhdr(&smb); fprintf(errfp,"\n%s!smb_open_ha returned %d: %s\n" ,beep,i,smb.last_error); bail(1); } } for(m=n=0;m<l;m++) { if(idx[m].attr&MSG_DELETE) { printf("%lu of %lu\r",++n,flagged); msg.idx=idx[m]; msg.hdr.number=msg.idx.number; if((i=smb_getmsgidx(&smb,&msg))!=0) { fprintf(errfp,"\n%s!smb_getmsgidx returned %d: %s\n" ,beep,i,smb.last_error); continue; } i=smb_lockmsghdr(&smb,&msg); if(i) { fprintf(errfp,"\n%s!smb_lockmsghdr returned %d: %s\n" ,beep,i,smb.last_error); break; } if((i=smb_getmsghdr(&smb,&msg))!=0) { smb_unlockmsghdr(&smb,&msg); fprintf(errfp,"\n%s!smb_getmsghdr returned %d: %s\n" ,beep,i,smb.last_error); break; } msg.hdr.attr|=MSG_DELETE; /* mark header as deleted */ if((i=smb_putmsg(&smb,&msg))!=0) { smb_freemsgmem(&msg); smb_unlockmsghdr(&smb,&msg); fprintf(errfp,"\n%s!smb_putmsg returned %d: %s\n" ,beep,i,smb.last_error); break; } smb_unlockmsghdr(&smb,&msg); if((i=smb_freemsg(&smb,&msg))!=0) { smb_freemsgmem(&msg); fprintf(errfp,"\n%s!smb_freemsg returned %d: %s\n" ,beep,i,smb.last_error); break; } smb_freemsgmem(&msg); } } if(!(smb.status.attr&SMB_HYPERALLOC)) { smb_close_ha(&smb); smb_close_da(&smb); } printf("\nDone.\n\n"); } printf("Re-writing index...\n"); rewind(smb.sid_fp); CHSIZE_FP(smb.sid_fp,0); for(m=n=0;m<l;m++) { if(idx[m].attr&MSG_DELETE) continue; printf("%lu of %lu\r",++n,l-flagged); fwrite(&idx[m],sizeof(idxrec_t),1,smb.sid_fp); } printf("\nDone.\n\n"); fflush(smb.sid_fp); free(idx); smb.status.total_msgs-=flagged; smb_putstatus(&smb); smb_unlocksmbhdr(&smb); }
ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, uint subnum , int conf, FILE* hdrs) { char str[512],from[512],to[512],ch=0,tear=0,tearwatch=0,*buf,*p; char asc; char msgid[256]; char tmp[512]; long l,size=0,offset; int i; ushort hfield_type; struct tm tm; smbmsg_t remsg; time_t tt; offset=(long)ftell(qwk_fp); if(hdrs!=NULL) { fprintf(hdrs,"[%lx]\n",offset); /* Message-IDs */ fprintf(hdrs,"Message-ID: %s\n",get_msgid(&cfg,subnum,msg,msgid,sizeof(msgid))); if(msg->reply_id!=NULL) fprintf(hdrs,"In-Reply-To: %s\n",msg->reply_id); /* Time/Date/Zone info */ fprintf(hdrs,"WhenWritten: %-20s %04hx\n" ,xpDateTime_to_isoDateTimeStr( time_to_xpDateTime(msg->hdr.when_written.time,smb_tzutc(msg->hdr.when_written.zone)) ,/* separators: */"","","", /* precision: */0 ,str,sizeof(str)) ,msg->hdr.when_written.zone ); fprintf(hdrs,"WhenImported: %-20s %04hx\n" ,xpDateTime_to_isoDateTimeStr( time_to_xpDateTime(msg->hdr.when_imported.time,smb_tzutc(msg->hdr.when_imported.zone)) ,/* separators: */"","","", /* precision: */0 ,str,sizeof(str)) ,msg->hdr.when_imported.zone ); fprintf(hdrs,"WhenExported: %-20s %04hx\n" ,xpDateTime_to_isoDateTimeStr( xpDateTime_now() ,/* separators: */"","","", /* precision: */0 ,str,sizeof(str)) ,sys_timezone(&cfg) ); fprintf(hdrs,"ExportedFrom: %s %s %"PRIu32"\n" ,cfg.sys_id ,subnum==INVALID_SUB ? "mail":cfg.sub[subnum]->code ,msg->hdr.number ); /* SENDER */ fprintf(hdrs,"%s: %s\n",smb_hfieldtype(SENDER),msg->from); if(msg->from_net.type) fprintf(hdrs,"%s: %s\n",smb_hfieldtype(SENDERNETADDR),smb_netaddrstr(&msg->from_net,tmp)); if((p=(char*)smb_get_hfield(msg,hfield_type=SENDERIPADDR,NULL))!=NULL) fprintf(hdrs,"%s: %s\n",smb_hfieldtype(hfield_type),p); if((p=(char*)smb_get_hfield(msg,hfield_type=SENDERHOSTNAME,NULL))!=NULL) fprintf(hdrs,"%s: %s\n",smb_hfieldtype(hfield_type),p); if((p=(char*)smb_get_hfield(msg,hfield_type=SENDERPROTOCOL,NULL))!=NULL) fprintf(hdrs,"%s: %s\n",smb_hfieldtype(hfield_type),p); if(msg->from_org!=NULL) fprintf(hdrs,"Organization: %s\n",msg->from_org); else if(msg->from_net.type==NET_NONE) fprintf(hdrs,"Organization: %s\n",cfg.sys_name); /* Reply-To */ if((p=(char*)smb_get_hfield(msg,RFC822REPLYTO,NULL))==NULL) { if(msg->replyto_net.type==NET_INTERNET) p=(char*)msg->replyto_net.addr; else if(msg->replyto!=NULL) p=msg->replyto; } if(p!=NULL) fprintf(hdrs,"Reply-To: %s\n",p); /* use original RFC822 header field */ /* SUBJECT */ fprintf(hdrs,"%s: %s\n",smb_hfieldtype(SUBJECT),msg->subj); /* RECIPIENT */ fprintf(hdrs,"%s: %s\n",smb_hfieldtype(RECIPIENT),msg->to); if(msg->to_net.type) fprintf(hdrs,"%s: %s\n",smb_hfieldtype(RECIPIENTNETADDR),smb_netaddrstr(&msg->to_net,tmp)); /* FidoNet */ if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOAREA,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOSEENBY,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOPATH,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOMSGID,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOREPLYID,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOPID,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOFLAGS,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=FIDOTID,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); /* Synchronet */ if((p=(char*)smb_get_hfield(msg,hfield_type=SMB_EDITOR,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); /* USENET */ if((p=(char*)smb_get_hfield(msg,hfield_type=USENETPATH,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); if((p=(char*)smb_get_hfield(msg,hfield_type=USENETNEWSGROUPS,NULL))!=NULL) fprintf(hdrs,"%s: %s\n", smb_hfieldtype(hfield_type), p); /* RFC822 header fields: */ for(i=0;i<msg->total_hfields;i++) if(msg->hfield[i].type==RFC822HEADER) fprintf(hdrs,"%s\n",truncsp_lines((char*)msg->hfield_dat[i])); /* Blank line: */ fprintf(hdrs,"\n"); } fprintf(qwk_fp,"%*s",QWK_BLOCK_LEN,""); /* Init header to space */ /* QWKE compatible kludges */ SAFECOPY(from,msg->from); if(msg->from_net.addr && (uint)subnum==INVALID_SUB && !(mode&QM_TO_QNET)) { if(msg->from_net.type==NET_FIDO) sprintf(from,"%.128s@%.128s" ,msg->from,smb_faddrtoa((faddr_t *)msg->from_net.addr,tmp)); else if(msg->from_net.type==NET_INTERNET || strchr((char*)msg->from_net.addr,'@')!=NULL) sprintf(from,"%.128s",(char*)msg->from_net.addr); else sprintf(from,"%.128s@%.128s",msg->from,(char*)msg->from_net.addr); } if(msg->hdr.attr&MSG_ANONYMOUS && !SYSOP) SAFECOPY(from,text[Anonymous]); else if((subnum==INVALID_SUB || (useron.qwk&QWK_EXT)) && strlen(from) > QWK_HFIELD_LEN) { size+=fprintf(qwk_fp,"From: %.128s%c", from, QWK_NEWLINE); SAFECOPY(from,msg->from); } SAFECOPY(to,msg->to); if(msg->to_net.addr && (uint)subnum==INVALID_SUB) { if(msg->to_net.type==NET_FIDO) sprintf(to,"%.128s@%s",msg->to,smb_faddrtoa((faddr_t *)msg->to_net.addr,tmp)); else if(msg->to_net.type==NET_INTERNET) sprintf(to,"%.128s",(char*)msg->to_net.addr); else if(msg->to_net.type==NET_QWK) { if(mode&QM_TO_QNET) { p=strchr((char *)msg->to_net.addr,'/'); if(p) { /* Another hop */ p++; SAFECOPY(to,"NETMAIL"); size+=fprintf(qwk_fp,"%.128s@%.128s%c",msg->to,p,QWK_NEWLINE); } else sprintf(to,"%.128s",msg->to); } else sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr); } else sprintf(to,"%.128s@%.128s",msg->to,(char*)msg->to_net.addr); } if((subnum==INVALID_SUB || (useron.qwk&QWK_EXT)) && strlen(to) > QWK_HFIELD_LEN) { size+=fprintf(qwk_fp,"To: %.128s%c", to, QWK_NEWLINE); if(msg->to_net.type==NET_QWK) SAFECOPY(to,"NETMAIL"); else SAFECOPY(to,msg->to); } if((useron.qwk&QWK_EXT) && strlen(msg->subj) > QWK_HFIELD_LEN) size+=fprintf(qwk_fp,"Subject: %.128s%c", msg->subj, QWK_NEWLINE); if(msg->from_net.type==NET_QWK && mode&QM_VIA && !msg->forwarded) size+=fprintf(qwk_fp,"@VIA: %s%c" ,(char*)msg->from_net.addr,QWK_NEWLINE); if(mode&QM_MSGID && (uint)subnum!=INVALID_SUB) { size+=fprintf(qwk_fp,"@MSGID: %s%c" ,get_msgid(&cfg,subnum,msg,msgid,sizeof(msgid)),QWK_NEWLINE); if(msg->reply_id) { SAFECOPY(tmp,msg->reply_id); truncstr(tmp," "); size+=fprintf(qwk_fp,"@REPLY: %s%c" ,tmp,QWK_NEWLINE); } else if(msg->hdr.thread_back) { memset(&remsg,0,sizeof(remsg)); remsg.hdr.number=msg->hdr.thread_back; if(smb_getmsgidx(&smb, &remsg)) size+=fprintf(qwk_fp,"@REPLY: <%s>%c",smb.last_error,QWK_NEWLINE); else size+=fprintf(qwk_fp,"@REPLY: %s%c" ,get_msgid(&cfg,subnum,&remsg,msgid,sizeof(msgid)) ,QWK_NEWLINE); } } if(msg->hdr.when_written.zone && mode&QM_TZ) size+=fprintf(qwk_fp,"@TZ: %04hx%c",msg->hdr.when_written.zone,QWK_NEWLINE); if(msg->replyto!=NULL && mode&QM_REPLYTO) size+=fprintf(qwk_fp,"@REPLYTO: %s%c" ,msg->replyto,QWK_NEWLINE); p=0; for(i=0;i<msg->total_hfields;i++) { if(msg->hfield[i].type==SENDER) p=(char *)msg->hfield_dat[i]; if(msg->hfield[i].type==FORWARDED && p) { size+=fprintf(qwk_fp,"Forwarded from %s on %s%c",p ,timestr(*(time32_t *)msg->hfield_dat[i]) ,QWK_NEWLINE); } } buf=smb_getmsgtxt(&smb,msg,GETMSGTXT_ALL); if(!buf) return(0); for(l=0;buf[l];l++) { ch=buf[l]; if(ch=='\n') { if(tear) tear++; /* Count LFs after tearline */ if(tear>3) /* more than two LFs after the tear */ tear=0; if(tearwatch==4) { /* watch for LF---LF */ tear=1; tearwatch=0; } else if(!tearwatch) tearwatch=1; else tearwatch=0; if(l && buf[l-1]=='\r') /* Replace CRLF with funky char */ ch=QWK_NEWLINE; /* but leave sole LF (soft-NL) alone */ fputc(ch,qwk_fp); size++; continue; } if(ch=='\r') { /* Ignore CRs */ if(tearwatch<4) /* LF---CRLF is okay */ tearwatch=0; /* LF-CR- is not okay */ continue; } if(ch==' ' && tearwatch==4) { /* watch for "LF--- " */ tear=1; tearwatch=0; } if(ch=='-') { /* watch for "LF---" */ if(l==0 || (tearwatch && tearwatch<4)) tearwatch++; else tearwatch=0; } else tearwatch=0; if((uint)subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_ASCII) { if(ch<' ' && ch!=1) ch='.'; else if((uchar)ch>0x7f) ch=exascii_to_ascii_char(ch); } if(ch==QWK_NEWLINE) /* funky char */ ch='*'; if(ch==CTRL_A) { ch=buf[++l]; if(ch==0 || toupper(ch)=='Z') /* EOF */ break; if((asc=ctrl_a_to_ascii_char(ch)) != 0) { fputc(asc,qwk_fp); size++; continue; } if(mode&A_EXPAND) { str[0]=0; switch(toupper(ch)) { case 'W': SAFECOPY(str,ansi(LIGHTGRAY)); break; case 'K': SAFECOPY(str,ansi(BLACK)); break; case 'H': SAFECOPY(str,ansi(HIGH)); break; case 'I': SAFECOPY(str,ansi(BLINK)); break; case '-': case '_': case 'N': /* Normal */ SAFECOPY(str,ansi(ANSI_NORMAL)); break; case 'R': SAFECOPY(str,ansi(RED)); break; case 'G': SAFECOPY(str,ansi(GREEN)); break; case 'B': SAFECOPY(str,ansi(BLUE)); break; case 'C': SAFECOPY(str,ansi(CYAN)); break; case 'M': SAFECOPY(str,ansi(MAGENTA)); break; case 'Y': /* Yellow */ SAFECOPY(str,ansi(BROWN)); break; case '0': SAFECOPY(str,ansi(BG_BLACK)); break; case '1': SAFECOPY(str,ansi(BG_RED)); break; case '2': SAFECOPY(str,ansi(BG_GREEN)); break; case '3': SAFECOPY(str,ansi(BG_BROWN)); break; case '4': SAFECOPY(str,ansi(BG_BLUE)); break; case '5': SAFECOPY(str,ansi(BG_MAGENTA)); break; case '6': SAFECOPY(str,ansi(BG_CYAN)); break; case '7': SAFECOPY(str,ansi(BG_LIGHTGRAY)); break; } if(str[0]) size+=fwrite(str,sizeof(char),strlen(str),qwk_fp); continue; } /* End Expand */ if(mode&A_LEAVE && valid_ctrl_a_code(ch)) { fputc(CTRL_A,qwk_fp); fputc(ch,qwk_fp); size+=2L; } continue; } /* End of Ctrl-A shit */ fputc(ch,qwk_fp); size++; } free(buf); if(ch!=QWK_NEWLINE) { fputc(QWK_NEWLINE,qwk_fp); /* make sure it ends in CRLF */ size++; } if(mode&QM_TAGLINE && !(cfg.sub[subnum]->misc&SUB_NOTAG)) { if(!tear) /* no tear line */ SAFEPRINTF(str,"\1n---%c",QWK_NEWLINE); /* so add one */ else SAFECOPY(str,"\1n"); if(cfg.sub[subnum]->misc&SUB_ASCII) ch='*'; else ch='þ'; safe_snprintf(tmp,sizeof(tmp)," %c \1g%.10s\1n %c %.127s%c" ,ch,VERSION_NOTICE,ch,cfg.sub[subnum]->tagline,QWK_NEWLINE); strcat(str,tmp); if(!(mode&A_LEAVE)) remove_ctrl_a(str,str); size+=fwrite(str,sizeof(char),strlen(str),qwk_fp); } while(size%QWK_BLOCK_LEN) { /* Pad with spaces */ size++; fputc(' ',qwk_fp); } tt=msg->hdr.when_written.time; if(localtime_r(&tt,&tm)==NULL) memset(&tm,0,sizeof(tm)); safe_snprintf(tmp,sizeof(tmp),"%02u-%02u-%02u%02u:%02u" ,tm.tm_mon+1,tm.tm_mday,TM_YEAR(tm.tm_year) ,tm.tm_hour,tm.tm_min); if(msg->hdr.attr&MSG_PRIVATE) { if(msg->hdr.attr&MSG_READ) ch='*'; /* private, read */ else ch='+'; /* private, unread */ } else { if(msg->hdr.attr&MSG_READ) ch='-'; /* public, read */ else ch=' '; /* public, unread */ } safe_snprintf(str,sizeof(str),"%c%-7lu%-13.13s%-25.25s" "%-25.25s%-25.25s%12s%-8lu%-6lu\xe1%c%c%c%c%c" ,ch /* message status flag */ ,mode&QM_REP ? (ulong)conf /* conference or */ : msg->hdr.number&MAX_MSGNUM /* message number */ ,tmp /* date and time */ ,to /* To: */ ,from /* From: */ ,msg->subj /* Subject */ ,nulstr /* Password */ ,msg->hdr.thread_back&MAX_MSGNUM /* Message Re: Number */ ,(size/QWK_BLOCK_LEN)+1 /* Number of blocks */ ,(char)conf&0xff /* Conference number lo byte */ ,(ushort)conf>>8 /* hi byte */ ,' ' /* not used */ ,' ' /* not used */ ,useron.rest&FLAG('Q') ? '*' : ' ' /* Net tag line */ ); fseek(qwk_fp,offset,SEEK_SET); fwrite(str,QWK_BLOCK_LEN,1,qwk_fp); fseek(qwk_fp,size,SEEK_CUR); return(size); }