/* Copyright (c) 1996, Ruslan R. Laishev (@RRL) */ #include "nntp.h" #include "nntp_rms.h" #include "nntp_log.h" #include "nntp_lib.h" int lib$signal (); char *MsgDBname = "nntp$msg.db"; char *GrpDBname = "nntp$grp.db"; char *SuckDBname= "nntp$suck.db"; /* */ struct FAB Msgfab; struct XABKEY MsgGrp; struct XABKEY MsgId; struct XABKEY MsgDate; char *MsgGrp$_knm = "News Groups ID + Date/Time "; char *MsgId$_knm = "Message ID "; char *MsgDate$_knm = "Message Date/Time "; /* */ struct FAB Grpfab; struct XABKEY GrpName; char *GrpName$_knm = "News Groups ID "; /* */ struct FAB Suckfab; struct XABKEY Suck; char *Suck$_knm = "Suck Host + News Groups ID "; /* *-------------------------------------------------------------------------------- */ int MsgDBopen (void) { long status; /* * FAB$ */ Msgfab = cc$rms_fab; Msgfab.fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_UPD | FAB$M_DEL; Msgfab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD | FAB$M_SHRDEL; /* read/write sharing */ Msgfab.fab$l_fna = MsgDBname; Msgfab.fab$v_mse = 1; /* multistream */ Msgfab.fab$b_fns = strlen(MsgDBname); Msgfab.fab$w_mrs = Msg_MaxRec; /* record size */ Msgfab.fab$b_org = FAB$C_IDX; Msgfab.fab$b_rat = FAB$M_CR; /* implied carriage return */ Msgfab.fab$l_fop = FAB$M_CIF | FAB$M_CBT; Msgfab.fab$b_rfm = FAB$C_VAR; /* * XABKEY$MsgGrp: comp.os.vms,vmsnet.test... + Date/Time in ASCII format */ MsgGrp = cc$rms_xabkey; MsgGrp.xab$b_ref = MsgGrp$_ref; MsgGrp.xab$b_dtp = XAB$C_STG; MsgGrp.xab$b_flg = XAB$M_DUP; MsgGrp.xab$w_pos0= MsgGrp$_pos; MsgGrp.xab$b_siz0= MsgGrp$_len; Msgfab.fab$l_xab = (char* ) &MsgGrp; /* * XABKEY$MsgId: <4358asdfd@petrobank.spb.su>... */ MsgId = cc$rms_xabkey; MsgId.xab$b_ref = MsgId$_ref; MsgId.xab$b_dtp = XAB$C_STG; MsgId.xab$b_flg = XAB$M_DUP; MsgId.xab$w_pos0= MsgId$_pos; MsgId.xab$b_siz0= MsgId$_len; MsgGrp.xab$l_nxt = (char *) &MsgId; /* * XABKEY$MsgDate: Message Date/Time in time_t format */ MsgDate = cc$rms_xabkey; MsgDate.xab$b_ref = MsgDate$_ref; MsgDate.xab$b_dtp = XAB$C_BN4; MsgDate.xab$b_flg = XAB$M_DUP; MsgDate.xab$w_pos0= MsgDate$_pos; MsgDate.xab$b_siz0= MsgDate$_len; MsgId.xab$l_nxt = (char *) &MsgDate; /* * Open or Create file (if need) */ status = sys$open (&Msgfab); if (! (status & 1)) { MsgGrp.xab$l_knm = MsgGrp$_knm; MsgId.xab$l_knm = MsgId$_knm; MsgDate.xab$l_knm = MsgDate$_knm; status = sys$create (&Msgfab); } return (NNTP_LOG_ERR("MsgDBopen",status)); } int GrpDBopen (void) { long status; /* * FAB$ */ Grpfab = cc$rms_fab; Grpfab.fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_UPD | FAB$M_DEL; Grpfab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD | FAB$M_SHRDEL; /* read/write sharing */ Grpfab.fab$l_fna = GrpDBname; Grpfab.fab$v_mse = 1; /* multistream */ Grpfab.fab$b_fns = strlen(GrpDBname); Grpfab.fab$w_mrs = Grp_MaxRec; /* record size */ Grpfab.fab$b_org = FAB$C_IDX; Grpfab.fab$b_rat = FAB$M_CR; /* implied carriage return */ Grpfab.fab$l_fop = FAB$M_CIF | FAB$M_CBT; Grpfab.fab$b_rfm = FAB$C_FIX; /* * XABKEY$GrpName: comp.os.vms,vmsnet.test... */ GrpName = cc$rms_xabkey; GrpName.xab$b_ref = GrpName$_ref; GrpName.xab$b_dtp = XAB$C_STG; GrpName.xab$b_flg = 0; GrpName.xab$w_pos0= GrpName$_pos; GrpName.xab$b_siz0= GrpName$_len; Grpfab.fab$l_xab = (char* ) &GrpName; /* * Open or Create file (if need) */ status = sys$open (&Grpfab); if (! (status & 1)) { GrpName.xab$l_knm = GrpName$_knm; status = sys$create (&Grpfab); } return (NNTP_LOG_ERR("GrpDBopen",status)); } int SuckDBopen (void) { long status; /* * FAB$ */ Suckfab = cc$rms_fab; Suckfab.fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_UPD | FAB$M_DEL; Suckfab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD | FAB$M_SHRDEL; Suckfab.fab$l_fna = SuckDBname; Suckfab.fab$v_mse = 1; /* multistream */ Suckfab.fab$b_fns = strlen(SuckDBname); Suckfab.fab$w_mrs = Suck_MaxRec; Suckfab.fab$b_org = FAB$C_IDX; Suckfab.fab$b_rat = FAB$M_CR; Suckfab.fab$l_fop = FAB$M_CIF | FAB$M_CBT; Suckfab.fab$b_rfm = FAB$C_FIX; /* * XABKEY$SuckName: "194.220.60.71,comp.os.vms" */ Suck = cc$rms_xabkey; Suck.xab$b_ref = Suck$_ref; Suck.xab$b_dtp = XAB$C_STG; Suck.xab$b_flg = 0; Suck.xab$w_pos0= Suck$_pos; Suck.xab$b_siz0= Suck$_len; Suckfab.fab$l_xab = (char* ) &Suck; /* * Open or Create file (if need) */ status = sys$open (&Suckfab); if (! (status & 1)) { Suck.xab$l_knm = Suck$_knm; status = sys$create (&Suckfab); } return (NNTP_LOG_ERR("SuckDBopen",status)); } /* *-------------------------------------------------------------------------------- * Allocate RAB & buffers, open stream's */ int MsgDBopen_stream (struct RAB *rabp) { long status; *rabp = cc$rms_rab; rabp->rab$l_fab = &Msgfab; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$v_wbh = 1; rabp->rab$v_rah = 1; rabp->rab$v_wat = 1; /* Wait if record is current locked, */ rabp->rab$b_tmo = 120; /* 120 second before return */ rabp->rab$b_mbf = 8; /* Number of buffers for the one stream */ status = sys$connect (rabp); rabp->rab$v_nlk = 1; return (NNTP_LOG_ERR ("MsgDBopen_stream",status)); } int GrpDBopen_stream (struct RAB *rabp) { long status; *rabp = cc$rms_rab; rabp->rab$l_fab = &Grpfab; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$v_wbh = 1; rabp->rab$v_rah = 1; rabp->rab$v_wat = 1; /* Wait if record is currently locked */ rabp->rab$b_tmo = 120; /* 120 second before return */ rabp->rab$v_uif = 1; /* Update if record (primary key) exist */ rabp->rab$b_mbf = 4; /* Number of buffers for the one stream */ status = sys$connect (rabp); rabp->rab$v_nlk = 1; return (NNTP_LOG_ERR ("GrpDBopen_stream",status)); } int SuckDBopen_stream (struct RAB *rabp) { long status; *rabp = cc$rms_rab; rabp->rab$l_fab = &Suckfab; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$v_uif = 1; /* Update if record (primary key) exist */ status = sys$connect (rabp); rabp->rab$v_nlk = 1; return (NNTP_LOG_ERR ("SuckDBopen",status)); } /* *-------------------------------------------------------------------------------- * Close stream's */ int DBclose_stream (struct RAB *rabp) { long status; status = sys$flush(rabp); status = sys$disconnect(rabp); return (NNTP_LOG_ERR ("DBclose_stream",status)); } /* *-------------------------------------------------------------------------------- * Close databases */ int DBclose (void) { long status; status = sys$close (&Msgfab); return (NNTP_LOG_ERR ("DBclose",status)); } /* *-------------------------------------------------------------------------------- */ int MsgDBfind_byId (struct RAB *rabp,char *Id,int Idl) { long status; rabp->rab$b_krf = MsgId$_ref; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$l_kbf = Id; rabp->rab$b_ksz = Idl; rabp->rab$v_nlk = 1; status = sys$find (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("MsgDBfind_byId",status); return -1; } return 0; } /* *-------------------------------------------------------------------------------- */ int MsgDBget_byId (struct RAB *rabp, char *Id,char *Msg,int MsgL) { long status; rabp->rab$b_krf = MsgId$_ref; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$l_kbf = Id; rabp->rab$b_ksz = strnlen(Id,MsgId$_len); rabp->rab$l_rbf = Msg; rabp->rab$w_rsz = MsgL; rabp->rab$l_ubf = Msg; rabp->rab$w_usz = MsgL; rabp->rab$v_nlk = 1; status = sys$get (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("MsgDBget_byId",status); return 0; } return (rabp->rab$w_rsz - sizeof(MsgKey)); } /* *-------------------------------------------------------------------------------- */ int MsgDBget_byNum (struct RAB *rabp, char *Grp,int n,char *Msg,int MsgL) { long status; MsgKey *Keyp; Keyp = (MsgKey *) Msg; sprintf(Keyp->Grp,"%.*s %011lu",GrpName$_len,Grp,n); rabp->rab$b_krf = MsgGrp$_ref; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$l_kbf = (char *)Keyp->Grp; rabp->rab$b_ksz = strnlen(Keyp->Grp,MsgGrp$_len); rabp->rab$l_rbf = Msg; rabp->rab$w_rsz = MsgL; rabp->rab$l_ubf = Msg; rabp->rab$w_usz = MsgL; rabp->rab$v_nlk = 1; status = sys$get (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("MsgDBget_byNum",status); return 0; } if ( Keyp->MsgId[0] == '>' ) { Keyp->MsgId[0] = '<'; return ( MsgDBget_byId(rabp,&Keyp->MsgId[0],Msg,MsgL) ); } return (rabp->rab$w_rsz - sizeof(MsgKey)); } /* *-------------------------------------------------------------------------------- */ int GrpDBget (struct RAB *rabp,char *Grp,char *bufp,int lockf) { long status; rabp->rab$b_krf = GrpName$_ref; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$l_kbf = Grp; rabp->rab$b_ksz = strnlen(Grp,GrpName$_len); rabp->rab$l_rbf = bufp; rabp->rab$w_rsz = sizeof(GrpKey); rabp->rab$l_ubf = bufp; rabp->rab$w_usz = sizeof(GrpKey); rabp->rab$v_nlk = (lockf?0:1); status = sys$get (rabp); if (! (status & 1)) { sys$free(rabp); return ( NNTP_LOG_ERR ("GrpDBget",status)); } return rabp->rab$w_rsz; } /* *-------------------------------------------------------------------------------- */ int GrpDBput (struct RAB *rabp,char *Grp,char *bufp) { long status; rabp->rab$b_krf = GrpName$_ref; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$l_kbf = Grp; rabp->rab$b_ksz = strnlen(Grp,GrpName$_len); rabp->rab$l_rbf = bufp; rabp->rab$w_rsz = sizeof(GrpKey); rabp->rab$l_ubf = bufp; rabp->rab$w_usz = sizeof(GrpKey); rabp->rab$v_nlk = 1; status = sys$put (rabp); if (! (status & 1)) return ( NNTP_LOG_ERR ("GrpDBput",status)); return rabp->rab$w_rsz; } /* *-------------------------------------------------------------------------------- */ int GrpDBget_seq (struct RAB *rabp,char *bufp,int flag) { long status; rabp->rab$b_krf = GrpName$_ref; rabp->rab$b_rac = RAB$C_SEQ; rabp->rab$l_rbf = bufp; rabp->rab$w_rsz = sizeof(GrpKey); rabp->rab$l_ubf = bufp; rabp->rab$w_usz = sizeof(GrpKey); rabp->rab$v_nlk = 1; if (!flag) { status = sys$rewind (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("GrpDBget_seq:$rewind",status); return 0; } } status = sys$get (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("GrpDBget_seq:$get",status); return 0; } return rabp->rab$w_rsz; } /* *-------------------------------------------------------------------------------- */ int DBins (struct RAB *grabp,struct RAB *mrabp,char *Grp, time_t Date,char *Msg,int MsgL) { long status; MsgKey *mkeyp =(MsgKey *) Msg ; GrpKey gkey; grabp->rab$b_krf = GrpName$_ref; grabp->rab$b_rac = RAB$C_KEY; grabp->rab$l_kbf = Grp; grabp->rab$b_ksz = strnlen(Grp,GrpName$_len); grabp->rab$l_rbf = (char *)&gkey; grabp->rab$w_rsz = sizeof(GrpKey); grabp->rab$l_ubf = (char *)&gkey; grabp->rab$w_usz = sizeof(GrpKey); grabp->rab$v_nlk = 0; status = sys$get (grabp); if (! (status & 1)) return -1; if ( !gkey.PostFlag ) return -1; gkey.DateCr = (gkey.DateCr == 0?Date:gkey.DateCr); gkey.First = (gkey.First == 0?1:gkey.First); gkey.Last++; mrabp->rab$b_krf = MsgId$_ref; mrabp->rab$b_rac = RAB$C_KEY; mrabp->rab$l_kbf = (char *)&mkeyp->MsgId; mrabp->rab$b_ksz = strnlen(mkeyp->MsgId,MsgId$_len); status = sys$find (mrabp); memset(&mkeyp->Grp[0],0,sizeof(mkeyp->Grp)); sprintf(mkeyp->Grp,"%.*s %011lu",GrpName$_len,Grp,gkey.Last); mrabp->rab$l_rbf = Msg; mrabp->rab$w_rsz = sizeof(MsgKey)+MsgL; mrabp->rab$l_ubf = Msg; mrabp->rab$w_usz = sizeof(MsgKey)+MsgL; mkeyp->Date = Date; if ( status != RMS$_RNF ) { NNTP_LOG(LOGW,"MessageID already exist-Change MsgId key"); mkeyp->MsgId[0] = '>'; mrabp->rab$w_rsz = sizeof(MsgKey); status = sys$find (mrabp); if ( status != RMS$_RNF ) { NNTP_LOG(LOGW,"MessageID already exist-Ignore"); status = sys$free(mrabp); status = sys$free(grabp); return 0; } } status = sys$put (mrabp); if (! (status & 1)) { NNTP_LOG_ERR ("DBins:$put(mrabp)",status); } else { status = sys$put (grabp); if (! (status & 1)) { NNTP_LOG_ERR ("DBins:$put(grabp)",status); } } status = sys$free(mrabp); status = sys$free(grabp); return 0; } /* *-------------------------------------------------------------------------------- */ int MsgDBget_byRange (struct RAB *rabp, char *Grp,int from,int to,char *Msg,int MsgL, char *LimKey) { long status; MsgKey *mkeyp = (MsgKey *)Msg; rabp->rab$b_krf = MsgGrp$_ref; rabp->rab$l_rbf = Msg; rabp->rab$w_rsz = MsgL; rabp->rab$l_ubf = Msg; rabp->rab$w_usz = MsgL; rabp->rab$v_nlk = 1; if ( !(*LimKey) ) { sprintf(LimKey,"%.*s %011lu",GrpName$_len,Grp,to); sprintf(Msg ,"%.*s %011lu",GrpName$_len,Grp,from); rabp->rab$b_rac = RAB$C_KEY; rabp->rab$b_krf = MsgGrp$_ref; rabp->rab$l_kbf = Msg; rabp->rab$b_ksz = strnlen(LimKey,MsgGrp$_len); status = sys$get (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("MsgDBget_byRange:$get0",status); return -1; } return (rabp->rab$w_rsz - sizeof(MsgKey)); } rabp->rab$b_rac = RAB$C_SEQ; rabp->rab$v_lim = 1; rabp->rab$l_kbf = LimKey; rabp->rab$b_ksz = strnlen(LimKey,MsgGrp$_len); status = sys$get (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("MsgDBget_byRange:$get1",status); return 0; } return (rabp->rab$w_rsz - sizeof(MsgKey)); } /* *-------------------------------------------------------------------------------- */ int SuckDBget (struct RAB *rabp,char *key) { long status; rabp->rab$b_krf = Suck$_ref; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$l_kbf = key; rabp->rab$b_ksz = strnlen(key,Suck$_len); rabp->rab$l_rbf = key; rabp->rab$w_rsz = sizeof(SuckRec); rabp->rab$l_ubf = key; rabp->rab$w_usz = sizeof(SuckRec); status = sys$get (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("SuckDBget",status); return 0; } return (rabp->rab$w_rsz); } /* *-------------------------------------------------------------------------------- */ int SuckDBput (struct RAB *rabp,char *key) { long status; rabp->rab$b_krf = Suck$_ref; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$l_kbf = key; rabp->rab$b_ksz = strnlen(key,Suck$_len); rabp->rab$l_rbf = key; rabp->rab$w_rsz = sizeof(SuckRec); rabp->rab$l_ubf = key; rabp->rab$w_usz = sizeof(SuckRec); status = sys$put (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("SuckDBput",status); return 0; } return (rabp->rab$w_rsz); }