/*
**++
**  FACILITY:
**      NEWGRPFILE
**
**  ABSTRACT:
**      This is a standalone image which performs a record-by-record copy of
**	the news group indexed file while obeying all RMS interlocks.
**
**	The program attempts to gain exclusive access to the file by taking
**	out the relevant system lock, or failing that by opening up a stop
**	file. This is an attempt to gain exclusive access to the file for the
**	duration of the record copy operation. Even if exclusive access is
**	not obtained, the program will press on and do the copy after waiting
**	for a maximum of 20 minutes for everyone to shut down.
**
**  AUTHOR:
**      Geoff Huston
**
**  COPYRIGHT:
**      Copyright © 1990
**
**  Modification History:
**	6.1b7	15-Jun-1993	Charles Bailey  bailey@genetics.upenn.edu
**	  - set record size in grprab to NEWS_GRPFIL_RSZ, not sizeof newsgrp,
**	    since newsgrp struct contains volatile data not needed in file
**      6.1b8   12-Oct-1993     Charles Lane    lane@duphy4.physics.drexel.edu
**        - clear NEWS_M_NEWSKIP flag while processing group entry
**	V6.1b9	17-Aug-1994     Mark Martinec   mark.martinec@ijs.si
**	  - code cleanup to make it compile under gcc 2.6.0 with full
**	    warnings reporting turned on - with no or very few harmless warnings
**	V6.1b9	17-Sep-1994     Mark Martinec   mark.martinec@ijs.si
**	  - code cleanup to preserve the read-only nature of string literals
**	    (strategically placed 'const' attribute to string parameters)
**	V6.1b10 09-DEC-1996	Mark Pizzolato	mark@infocomm.com
**	  - minor declaration cleanup to get warningless compile under 
**	    DEC C V5.3 on VAX
**	V6.1b11  7-May-1997	Mark Martinec   mark.martinec@ijs.si
**	  - decouple group name size (new constant GRPNAMELEN)
**	    from the size of item titles (SUBJLEN)
**	  - decouple the in-memory grp_name size (GRPNAMELEN) from the
**	    size of the groups file record field (GRPNAMELEN_F).
**	    Now the file record may contain group name which is
**	    not '\0'-terminated, thus gaining one character
**	    in the group name length
**--
*/

#ifdef vaxc
#module NEWGRPFILE "V6.1"
#endif

#define _NEWGRPFILE_C

/* Cause variable declarations for things declared in NEWSVARIABLES.H */
#define _NEWS_MAIN_PROGRAM

#include "newsinclude.h"
#include "newsextern.h"


int main(void)
{
  int status, incount = 0, outcount = 0;
  char prgfname[256];
  struct FAB grpfab, grpfab_1;
  struct RAB grprab, grprab_1;
  struct XABKEY xabkey_1, xabkey_2;
  struct XABPRO xabpro_1;
  GRPF newsgrp;

  if (!((status = acquire_exclusive_lock(20*60)) & 1)) {
    printf("Unable to acquire Exclusive Access to the News System:\n%s\n",
	    strerror(EVMSERR, status));
    printf("Continuing . . .\n");
    }
  grpfab = cc$rms_fab;
  grpfab.fab$b_fac = FAB$M_GET ;
  grpfab.fab$l_fna = (char *) GRP_FILENAME;
  grpfab.fab$b_fns = strlen(grpfab.fab$l_fna);
  grpfab.fab$b_shr = FAB$M_SHRDEL | FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD;

  grprab = cc$rms_rab;
  grprab.rab$l_fab = &grpfab;
  grprab.rab$l_ubf = (char *) &newsgrp;
  grprab.rab$w_usz = NEWS_GRPFIL_RSZ;
  grprab.rab$l_rbf = (char *) &newsgrp;
  grprab.rab$w_rsz = NEWS_GRPFIL_RSZ;

  if (!((status = sys$open(&grpfab)) & 1)) exit(status);
  if (!((status = sys$connect(&grprab)) & 1)) exit(status);

  grpfab_1 = cc$rms_fab;
  grpfab_1.fab$l_alq = 7*grpfab.fab$l_alq/8; /* use 87% of original allocation*/
  grpfab_1.fab$b_bks = 3;
  grpfab_1.fab$w_deq = grpfab.fab$l_alq/16;        /* and a 6% extension size */
  grpfab_1.fab$b_fac = FAB$M_PUT;
  grpfab_1.fab$l_fna = (char *) "NEWS_ROOT:NEWS.GROUPS_WRK";
  grpfab_1.fab$b_fns = strlen(grpfab_1.fab$l_fna);
  grpfab_1.fab$l_fop = FAB$M_CIF | FAB$M_CTG;
  grpfab_1.fab$w_mrs = NEWS_GRPFIL_RSZ;
  grpfab_1.fab$b_org = FAB$C_IDX;
  grpfab_1.fab$b_rat = FAB$M_CR;
  grpfab_1.fab$b_rfm = FAB$C_FIX;
  grpfab_1.fab$b_shr = FAB$M_SHRDEL | FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD;
  grpfab_1.fab$l_xab = (char *) &xabkey_1;

  xabkey_1 = cc$rms_xabkey;
  xabkey_1.xab$b_dtp = XAB$C_STG;
  xabkey_1.xab$b_flg = 0;
  xabkey_1.xab$w_pos0 = (char *) &newsgrp.grp_name - (char *) &newsgrp;
  xabkey_1.xab$b_ref = 0;
  xabkey_1.xab$b_siz0 = GRPNAMELEN_F;
  xabkey_1.xab$l_nxt = (char *) &xabkey_2;

  xabkey_2 = cc$rms_xabkey;
  xabkey_2.xab$b_dtp = XAB$C_BN4;
  xabkey_2.xab$b_flg = 0;
  xabkey_2.xab$w_pos0 = (char *) &newsgrp.grp_num - (char *) &newsgrp;
  xabkey_2.xab$b_ref = 1;
  xabkey_2.xab$b_siz0 = 4;
  xabkey_2.xab$l_nxt = (char *) &xabpro_1;

  xabpro_1 = cc$rms_xabpro;
  xabpro_1.xab$w_pro = 0xEE00;

  grprab_1 = cc$rms_rab;
  grprab_1.rab$l_fab = &grpfab_1;
  grprab_1.rab$b_krf = 0;
  grprab_1.rab$b_ksz = GRPNAMELEN_F;
  grprab_1.rab$l_ubf = (char *) &newsgrp;
  grprab_1.rab$w_usz = NEWS_GRPFIL_RSZ;
  grprab_1.rab$l_rbf = (char *) &newsgrp;
  grprab_1.rab$w_rsz = NEWS_GRPFIL_RSZ;

  if (!((status = sys$create(&grpfab_1)) & 1)) {
    printf("Cannot create %s with %ld contiguous blocks - using best try\n",
      grpfab_1.fab$l_fna,grpfab_1.fab$l_alq);
    grpfab_1.fab$l_fop &= ~FAB$M_CTG;
    grpfab_1.fab$l_fop |= FAB$M_CBT;
    if (!((status = sys$create(&grpfab_1)) & 1)) exit(status);
    }
  if (!((status = sys$connect(&grprab_1)) & 1)) exit(status);

  grprab.rab$l_rop = RAB$M_WAT;
  grprab.rab$b_rac = RAB$C_SEQ;
  grprab.rab$b_krf = 0;
  grprab.rab$b_ksz = GRPNAMELEN_F;

  grprab_1.rab$l_rop = RAB$M_WAT;
  grprab_1.rab$b_rac = RAB$C_SEQ;
  grprab_1.rab$b_krf = 0;
  grprab_1.rab$b_ksz = GRPNAMELEN_F;

  if (!((status = sys$rewind(&grprab)) & 1)) exit(status);

  printf("\n");
  for (;;) {
    if ((status = sys$get(&grprab)) == RMS$_EOF) {
      printf("End of file reached, %d records read, %d records written\n",incount, outcount);
      _c$cks(sys$close(&grpfab));
      _c$cks(sys$close(&grpfab_1));
      printf("Renaming newly created NEWS_ROOT:NEWS.GROUPS_WRK to NEWS.GROUPS");
      rename("NEWS_ROOT:NEWS.GROUPS_WRK", GRP_FILENAME);
      strcpy(prgfname,GRP_FILENAME);
      strcat(prgfname,";-1");
      while (!delete(prgfname));
      exit(1);
      }
    else if (!(status & 1)) {
      printf("ERROR FROM RMS - code returned was %X\n", status);
      printf("Group file copy terminated before Input EOF\n");
      printf("      %d records read, %d records written to NEWS_ROOT:NEWS.GROUPS_WRK\n",incount, outcount);
      exit(status);
      }
    printf("\t%.*s (#%d)\n",GRPNAMELEN_F,newsgrp.grp_name,newsgrp.grp_num);
    newsgrp.grp_flags &= ~NEWS_M_NEWSKIP;
    ++incount;
    if ((status = sys$put(&grprab_1)) & 1) ++outcount;
    else printf("\n$PUT call error: %X\n",status);
    }
}
