/* Copyright (c) 1996, Ruslan R. Laishev (@RRL) */ #include "nntp.h" int lib$signal (); char *MsgDBname = "nntp$msg.db"; char *GrpDBname = "nntp$grp.db"; char *SuckDBname= "nntp$suck.db"; char *FeedDBname= "nntp$feed.db"; /* */ struct FAB Msgfab; struct XABKEY MsgGrp; struct XABKEY MsgId; char *MsgGrp$_knm = "News Groups ID + # Article "; char *MsgId$_knm = "Message ID "; /* */ struct FAB Grpfab; struct XABKEY GrpName; char *GrpName$_knm = "News Groups ID "; /* */ struct FAB Suckfab; struct XABKEY Suck; char *Suck$_knm = "Suck_Host_IP ',' News Groups ID "; /* */ struct FAB Feedfab; struct XABKEY Feed; char *Feed$_knm = "Feed_Host_IP ',' 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; /* * 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; status = sys$create (&Msgfab); } return (NNTP_LOG_ERR("MsgDBopen:$open/$create",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:$open/$create",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$v_mse = 1; /* multistream */ Suckfab.fab$l_fna = SuckDBname; 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:$open/$create",status)); } int FeedDBopen (void) { long status; /* * FAB$ */ Feedfab = cc$rms_fab; Feedfab.fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_UPD | FAB$M_DEL; Feedfab.fab$b_shr = FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD | FAB$M_SHRDEL; Feedfab.fab$v_mse = 1; /* multistream */ Feedfab.fab$l_fna = FeedDBname; Feedfab.fab$b_fns = strlen(FeedDBname); Feedfab.fab$w_mrs = Feed_MaxRec; Feedfab.fab$b_org = FAB$C_IDX; Feedfab.fab$b_rat = FAB$M_CR; Feedfab.fab$l_fop = FAB$M_CIF | FAB$M_CBT; Feedfab.fab$b_rfm = FAB$C_FIX; /* * XABKEY$FeedName: "194.220.60.71,comp.os.vms" */ Feed = cc$rms_xabkey; Feed.xab$b_ref = Feed$_ref; Feed.xab$b_dtp = XAB$C_STG; Feed.xab$b_flg = 0; Feed.xab$w_pos0= Feed$_pos; Feed.xab$b_siz0= Feed$_len; Feedfab.fab$l_xab = (char* ) &Feed; /* * Open or Create file (if need) */ status = sys$open (&Feedfab); if (! (status & 1)) { Feed.xab$l_knm = Feed$_knm; status = sys$create (&Feedfab); } return (NNTP_LOG_ERR("FeedDBopen:$open/$create",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_wat = 1; /* Wait if record is current locked, */ rabp->rab$b_tmo = 250; /* 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_wat = 1; /* Wait if record is currently locked */ rabp->rab$b_tmo = 250; /* 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); 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_stream",status)); } int FeedDBopen_stream (struct RAB *rabp) { long status; *rabp = cc$rms_rab; rabp->rab$l_fab = &Feedfab; 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 ("FeedDBopen_stream",status)); } /* *-------------------------------------------------------------------------------- * Close stream's */ int DBclose_stream (struct RAB *rabp) { long status; status = sys$flush(rabp); status = sys$free (rabp); status = sys$disconnect(rabp); return (NNTP_LOG_ERR ("DBclose_stream",status)); } /* *-------------------------------------------------------------------------------- * Close databases */ int DBclose (void) { long status; status = sys$close (&Msgfab); status = sys$close (&Grpfab); status = sys$close (&Suckfab); status = sys$close (&Feedfab); return (NNTP_LOG_ERR ("DBclose",status)); } /* *-------------------------------------------------------------------------------- */ int MsgDBfind_byId (struct RAB *mrabp,char *Id,int Idl) { long status; mrabp->rab$b_krf = MsgId$_ref; mrabp->rab$b_rac = RAB$C_KEY; mrabp->rab$l_kbf = Id; mrabp->rab$b_ksz = Idl; mrabp->rab$v_nlk = 1; status = sys$find (mrabp); if (! (status & 1)) { NNTP_LOG_ERR ("MsgDBfind_byId:$find",status); return -1; } return 0; } /* *-------------------------------------------------------------------------------- */ int MsgDBget_byId (struct RAB *mrabp, char *Id,char *Msg,int MsgL) { long status; mrabp->rab$b_krf = MsgId$_ref; mrabp->rab$b_rac = RAB$C_KEY; mrabp->rab$l_kbf = Id; mrabp->rab$b_ksz = strnlen(Id,MsgId$_len); mrabp->rab$l_rbf = Msg; mrabp->rab$w_rsz = MsgL; mrabp->rab$l_ubf = Msg; mrabp->rab$w_usz = MsgL; mrabp->rab$v_nlk = 1; status = sys$get (mrabp); if (! (status & 1)) { NNTP_LOG_ERR ("MsgDBget_byId:$get",status); return 0; } return (mrabp->rab$w_rsz - sizeof(MsgKey)); } /* *-------------------------------------------------------------------------------- */ int MsgDBget_byNum (struct RAB *mrabp, char *Grp,int n,char *Msg,int MsgL) { long status; MsgKey *mkeyp; int sz; mkeyp = (MsgKey *) Msg; sz = sprintf(mkeyp->Grp,"%.*s %011lu",GrpName$_len,Grp,n); mrabp->rab$b_krf = MsgGrp$_ref; mrabp->rab$b_rac = RAB$C_KEY; mrabp->rab$l_kbf = (char *)mkeyp->Grp; mrabp->rab$b_ksz = min (sz,MsgGrp$_len); mrabp->rab$l_rbf = Msg; mrabp->rab$w_rsz = MsgL; mrabp->rab$l_ubf = Msg; mrabp->rab$w_usz = MsgL; mrabp->rab$v_nlk = 1; status = sys$get (mrabp); if (! (status & 1)) { NNTP_LOG_ERR ("MsgDBget_byNum:$get",status); return 0; } if ( mkeyp->MsgId[0] == '>' ) { mkeyp->MsgId[0] = '<'; return ( MsgDBget_byId(mrabp,&mkeyp->MsgId[0],Msg,MsgL) ); } return (mrabp->rab$w_rsz - sizeof(MsgKey)); } /* *-------------------------------------------------------------------------------- */ int MsgDBdel (struct RAB *mrabp) { long status; MsgKey *mkeyp; int sz; status = sys$delete (mrabp); if (! (status & 1)) { return (NNTP_LOG_ERR ("MsgDBdel:$delete",status)); } return 0; } /* *-------------------------------------------------------------------------------- */ int GrpDBget (struct RAB *grabp,char *Grp,char *bufp,int lockf) { long status; 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 = bufp; grabp->rab$w_rsz = sizeof(GrpKey); grabp->rab$l_ubf = bufp; grabp->rab$w_usz = sizeof(GrpKey); grabp->rab$v_rlk = 1; grabp->rab$v_nlk = (lockf?0:1); status = sys$get (grabp); if (! (status & 1) ) { sys$free(grabp); return ( NNTP_LOG_ERR ("GrpDBget:$get",status) ); } return grabp->rab$w_rsz; } /* *-------------------------------------------------------------------------------- */ int GrpDBfree (struct RAB *grabp) { long status; status = sys$free (grabp); return ( NNTP_LOG_ERR ("GrpDBget:$get",status) ); } /* *-------------------------------------------------------------------------------- */ int GrpDBput (struct RAB *grabp,char *Grp,char *bufp) { long status; 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 = bufp; grabp->rab$w_rsz = sizeof(GrpKey); grabp->rab$l_ubf = bufp; grabp->rab$w_usz = sizeof(GrpKey); status = sys$put (grabp); sys$free (grabp); if (! (status & 1)) return ( NNTP_LOG_ERR ("GrpDBput:$put",status)); return grabp->rab$w_rsz; } /* *-------------------------------------------------------------------------------- */ int GrpDBget_seq (struct RAB *grabp,char *bufp,int flag) { long status; grabp->rab$b_krf = GrpName$_ref; grabp->rab$b_rac = RAB$C_SEQ; grabp->rab$l_rbf = bufp; grabp->rab$w_rsz = sizeof(GrpKey); grabp->rab$l_ubf = bufp; grabp->rab$w_usz = sizeof(GrpKey); grabp->rab$v_nlk = 1; if (!flag) { status = sys$rewind (grabp); if (! (status & 1)) { NNTP_LOG_ERR ("GrpDBget_seq:$rewind",status); return 0; } } status = sys$get (grabp); if (! (status & 1)) { NNTP_LOG_ERR ("GrpDBget_seq:$get",status); return 0; } return grabp->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)) { sys$free(grabp); return -1; } if ( 'n' == gkey.PostFlag ) { sys$free(grabp); 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; gkey.DateUp = 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$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(grabp); return 0; } /* *-------------------------------------------------------------------------------- */ int MsgDBget_byRange ( struct RAB *mrabp, char *Grp, int from, int to, char *Msg, int MsgL, char *LimKey, int *LimKeysz ) { long status; MsgKey *mkeyp = (MsgKey *)Msg; mrabp->rab$b_krf = MsgGrp$_ref; mrabp->rab$l_rbf = Msg; mrabp->rab$w_rsz = MsgL; mrabp->rab$l_ubf = Msg; mrabp->rab$w_usz = MsgL; mrabp->rab$v_nlk = 1; if ( !(*LimKey) ) { *LimKeysz = sprintf(LimKey,"%.*s %011lu",GrpName$_len,Grp,to); sprintf(Msg ,"%.*s %011lu",GrpName$_len,Grp,from); mrabp->rab$b_rac = RAB$C_KEY; mrabp->rab$b_krf = MsgGrp$_ref; mrabp->rab$l_kbf = Msg; mrabp->rab$b_ksz = min(*LimKeysz,MsgGrp$_len); status = sys$get (mrabp); if (! (status & 1)) { NNTP_LOG_ERR ("MsgDBget_byRange:$get0",status); return -1; } return (mrabp->rab$w_rsz - sizeof(MsgKey)); } mrabp->rab$b_rac = RAB$C_SEQ; mrabp->rab$v_lim = 1; mrabp->rab$l_kbf = LimKey; mrabp->rab$b_ksz = min (*LimKeysz,MsgGrp$_len); status = sys$get (mrabp); if (! (status & 1)) { NNTP_LOG_ERR ("MsgDBget_byRange:$get1",status); return 0; } return (mrabp->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:$get",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:$put",status); return 0; } return (rabp->rab$w_rsz); } /* *-------------------------------------------------------------------------------- */ int FeedDBget (struct RAB *rabp,char *key) { long status; rabp->rab$b_krf = Feed$_ref; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$l_kbf = key; rabp->rab$b_ksz = strnlen(key,Feed$_len); rabp->rab$l_rbf = key; rabp->rab$w_rsz = sizeof(FeedRec); rabp->rab$l_ubf = key; rabp->rab$w_usz = sizeof(FeedRec); status = sys$get (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("FeedDBget:$get",status); return 0; } return (rabp->rab$w_rsz); } /* *-------------------------------------------------------------------------------- */ int FeedDBput (struct RAB *rabp,char *key) { long status; rabp->rab$b_krf = Feed$_ref; rabp->rab$b_rac = RAB$C_KEY; rabp->rab$l_kbf = key; rabp->rab$b_ksz = strnlen(key,Feed$_len); rabp->rab$l_rbf = key; rabp->rab$w_rsz = sizeof(FeedRec); rabp->rab$l_ubf = key; rabp->rab$w_usz = sizeof(FeedRec); status = sys$put (rabp); if (! (status & 1)) { NNTP_LOG_ERR ("FeedDBput:$put",status); return 0; } return (rabp->rab$w_rsz); }