/*
**++
**  FACILITY:
**      NEWSV58_UPGRADE
**
**  ABSTRACT:
**      Convert the ITEM and NEWSGROUP files to V5.8 record format
**
**  AUTHOR:
**      Geoff Huston
**
**  COPYRIGHT:
**      Copyright © 1989,1990
**
**  VERSION HISTORY:
**	V6.1b8  22-Dec-1993	mark.martinec@ijs.si
**	   - convert calls to RMS to use new sys_* macros for error handling 
**	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)
**--
**/

#ifdef vaxc
#module NEWSV58_UPGRADE "V6.2"
#endif

#define _NEWSV58_UPGRADE_C
#define module_name "NEWSV58_UPGRADE"

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

#define OGroup_file      "NEWS_ROOT:NEWSGROUPS.V50"
#define OItem_file       "NEWS_ROOT:NEWSITEMS.V50"

#define GRPNAMELEN_F_V60 50  /* before V6.1 the size of group name was
                                fixed at 50 and always '\0'-terminated */

#ifdef __DECC
#pragma member_alignment save
#pragma nomember_alignment   /* no member alignment - file records! */
#endif
static struct {
    unsigned short oitm_num;
    unsigned short oitm_grp;
    char oitm_id[IDLEN];
    unsigned int oitm_recvdate;
    unsigned int oitm_size;
    unsigned short oitm_new;
    char oitm_title[SUBJLEN];
    unsigned short oitm_life;
    char oitm_unread;
    unsigned int oitm_locdate;
    } onewsitm;

static struct {
    char ogrp_name[GRPNAMELEN_F_V60];
    unsigned short ogrp_num;
    unsigned short ogrp_topnum;
    unsigned short ogrp_count;
    unsigned int ogrp_credate;
    unsigned int ogrp_entdate;
    unsigned short ogrp_life;
    unsigned short ogrp_itmlife;
    char ogrp_srvproto;
    unsigned char ogrp_reg;
    unsigned short ogrp_unread;
    int ogrp_ia;
    unsigned short ogrp_iasize;
    int ogrp_iavd;
    int ogrp_iavdsize;
    int ogrp_iapaste;
    unsigned short ogrp_c_itm;
    int ogrp_display_indx;
    char ogrp_moderator;
    char ogrp_local;
    char ogrp_server[8];
    char ogrp_holdcop;
    unsigned short ogrp_loccoplife;
    } onewsgrp;

typedef struct {
    unsigned int nitm_num;           /* newsitem index [key 0, b 1-4] 4   4 */
    unsigned int nitm_grp;           /* newsgroup index[key 0, b 5-8] 4   8 */
                                     /*                [key 1, seg 1]       */
    char nitm_id[IDLEN];             /* item id        [key 1, seg 0]60  68 */
    unsigned int nitm_recvdate;      /* date                          4  72 */
    unsigned int nitm_lines;         /* lines                         4  76 */
    char nitm_title[SUBJLEN];        /* title                        50 126 */
    unsigned int nitm_cachedate;     /* server - cache entry date     4 130 */
    unsigned short nitm_life;        /* retention period              4 134 */
    unsigned int nitm_flags;         /* item flags                    4 138 */
    unsigned int nitm_cid;           /* conversation id [key 2, b1-4] 4 142 */
    unsigned int nitm_cno;           /* conversation seq[key 2, b5-8] 4 146 */
    } V58ITM;

static GRPF   grpf_buffer;
static V58ITM itmf_buffer;

#ifdef __DECC
#pragma member_alignment restore
#endif

#ifdef _c$cks
#undef _c$cks
#endif
#define _c$cks(s)	(((stat58 = (s)) & 1) ? 1 : (lib$signal(stat58),0))

static int mcvtfiles()
{
    int status;
    int i;
    unsigned int cid = 0;
    struct FAB ogrpfab, grpfab, oitmfab, itmfab;
    struct RAB ogrprab, grprab, oitmrab, itmrab;
    struct XABKEY xabkey_g1,
		  xabkey_g2,
		  xabkey_1,
		  xabkey_2,
		  xabkey_3;
    struct XABPRO xabpro_g1,
                  xabpro_1;

    /* open the old index newsgroup descriptor file for read access */
    ogrpfab = cc$rms_fab;
    ogrpfab.fab$b_fac = FAB$M_GET;
    ogrpfab.fab$l_fna = (char *) OGroup_file;
    ogrpfab.fab$b_fns = strlen(ogrpfab.fab$l_fna);
    ogrpfab.fab$b_shr = FAB$M_SHRDEL | FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD;

    ogrprab = cc$rms_rab;
    ogrprab.rab$l_fab = &ogrpfab;
    ogrprab.rab$l_ubf = (char *) &onewsgrp;
    ogrprab.rab$w_usz = sizeof onewsgrp;
    ogrprab.rab$l_rbf = (char *) &onewsgrp;
    ogrprab.rab$w_rsz = sizeof onewsgrp;
    ogrprab.rab$b_rac = RAB$C_SEQ;

    if (!sys_open(&ogrpfab)) return(0);
    if (!sys_connect(&ogrprab)) return(0);

    grpfab = cc$rms_fab;
    grpfab.fab$b_bks = 3;
    grpfab.fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_UPD | FAB$M_DEL;
    grpfab.fab$l_fna = (char *) GRP_FILENAME;
    grpfab.fab$b_fns = strlen(grpfab.fab$l_fna);
    grpfab.fab$l_fop = FAB$M_CIF;
    grpfab.fab$w_mrs = sizeof grpf_buffer;
    grpfab.fab$b_org = FAB$C_IDX;
    grpfab.fab$b_rfm = FAB$C_FIX;
    grpfab.fab$b_shr = FAB$M_SHRDEL|FAB$M_SHRGET|FAB$M_SHRPUT|FAB$M_SHRUPD;
    grpfab.fab$l_xab = (char *) &xabkey_g1;

    xabkey_g1 = cc$rms_xabkey;
    xabkey_g1.xab$b_dtp = XAB$C_STG;
    xabkey_g1.xab$b_flg = 0;
    xabkey_g1.xab$w_pos0 = (char *)&grpf_buffer.grp_name - (char *)&grpf_buffer;
    xabkey_g1.xab$b_ref = 0;
    xabkey_g1.xab$b_siz0 = GRPNAMELEN_F_V60;
    xabkey_g1.xab$l_nxt = (char *) &xabkey_g2;

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

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

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

    sys_create(&grpfab);
    if (status == RMS$_CREATED) {

        sys_connect(&grprab);

        while (sys_get_nornf(&ogrprab)) {
            printf("Working on %.*s\n", GRPNAMELEN_F_V60,onewsgrp.ogrp_name);
            for (i = 0; i < GRPNAMELEN_F_V60; ++i)
                grpf_buffer.grp_name[i] = onewsgrp.ogrp_name[i];
            for (     ; i < GRPNAMELEN_F;     ++i)
                grpf_buffer.grp_name[i] = '\0';;
            grpf_buffer.grp_num         = onewsgrp.ogrp_num;
            grpf_buffer.grp_topnum      = onewsgrp.ogrp_topnum;
            grpf_buffer.grp_count       = onewsgrp.ogrp_count;
            grpf_buffer.grp_credate     = onewsgrp.ogrp_credate;
            grpf_buffer.grp_entdate     = onewsgrp.ogrp_entdate;
            grpf_buffer.grp_life        = onewsgrp.ogrp_life;
            grpf_buffer.grp_itmlife     = onewsgrp.ogrp_itmlife;
            grpf_buffer.grp_srvcache    = onewsgrp.ogrp_loccoplife;
            grpf_buffer.grp_flags       = onewsgrp.ogrp_local;
            grpf_buffer.grp_flags &= 0x7F;
            if (*(onewsgrp.ogrp_server)) grpf_buffer.grp_flags |= NEWS_M_NNTPSRV;
            if (onewsgrp.ogrp_holdcop) grpf_buffer.grp_flags |= NEWS_M_NNTPCACHE;
            if (onewsgrp.ogrp_moderator) grpf_buffer.grp_flags |= NEWS_M_MAILMODERATE;
            grpf_buffer.grp_srvproto = onewsgrp.ogrp_srvproto;
            strcpy(grpf_buffer.grp_srvnode,onewsgrp.ogrp_server);
            *(grpf_buffer.grp_topic) = '\0';
            *(grpf_buffer.grp_notice) = '\0';
            sys_put(&grprab);
            }
        }
    else printf("NEWS V5.8 newsgroup file has already been created\n");

    sys_close(&ogrpfab);
    sys_close(&grpfab);



    oitmfab = cc$rms_fab;
    oitmfab.fab$b_fac = FAB$M_GET;
    oitmfab.fab$l_fna = (char *) OItem_file;
    oitmfab.fab$b_fns = strlen(oitmfab.fab$l_fna);
    oitmfab.fab$b_shr = FAB$M_SHRDEL | FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD;

    oitmrab = cc$rms_rab;
    oitmrab.rab$l_fab = &oitmfab;
    oitmrab.rab$l_ubf = (char *) &onewsitm;
    oitmrab.rab$w_usz = sizeof onewsitm;
    oitmrab.rab$l_rbf = (char *) &onewsitm;
    oitmrab.rab$w_rsz = sizeof onewsitm;
    oitmrab.rab$b_rac = RAB$C_SEQ;

    if (!sys_open(&oitmfab)) return(0);
    if (!sys_connect(&oitmrab)) return(0);

    itmfab = cc$rms_fab;
    itmfab.fab$b_bks = 3;
    itmfab.fab$b_fac = FAB$M_PUT ;
    itmfab.fab$l_fna = (char *) ITM_FILENAME;
    itmfab.fab$b_fns = strlen(itmfab.fab$l_fna);
    itmfab.fab$l_fop = FAB$M_CIF;
    itmfab.fab$w_mrs = sizeof itmf_buffer;
    itmfab.fab$b_org = FAB$C_IDX;
    itmfab.fab$b_rfm = FAB$C_FIX;
    itmfab.fab$b_shr = FAB$M_SHRDEL | FAB$M_SHRGET | FAB$M_SHRPUT | FAB$M_SHRUPD;
    itmfab.fab$l_xab = (char *) &xabkey_1;

    xabkey_1 = cc$rms_xabkey;
    xabkey_1.xab$b_dtp = XAB$C_BN8;
    xabkey_1.xab$b_flg = 0;
    xabkey_1.xab$w_pos0 = (char *) &itmf_buffer.nitm_num - (char *) &itmf_buffer;
    xabkey_1.xab$b_ref = 0;
    xabkey_1.xab$b_siz0 = 8;
    xabkey_1.xab$l_nxt = (char *) &xabkey_2;

    xabkey_2 = cc$rms_xabkey;
    xabkey_2.xab$b_dtp = XAB$C_STG;
    xabkey_2.xab$b_flg = 0;
    xabkey_2.xab$w_pos0 = (char *) &itmf_buffer.nitm_id - (char *) &itmf_buffer;
    xabkey_2.xab$w_pos1 = (char *) &itmf_buffer.nitm_grp - (char *) &itmf_buffer;
    xabkey_2.xab$b_ref = 1;
    xabkey_2.xab$b_siz0 = IDLEN;
    xabkey_2.xab$b_siz1 = 4;
    xabkey_2.xab$l_nxt = (char *) &xabkey_3;

    xabkey_3 = cc$rms_xabkey;
    xabkey_3.xab$b_dtp = XAB$C_BN8;
    xabkey_3.xab$b_flg = XAB$M_DUP;
    xabkey_3.xab$w_pos0 = (char *) &itmf_buffer.nitm_cid - (char *) &itmf_buffer;
    xabkey_3.xab$b_ref = 2;
    xabkey_3.xab$b_siz0 = 8;
    xabkey_3.xab$l_nxt = (char *) &xabpro_1;

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

    itmrab = cc$rms_rab;
    itmrab.rab$l_fab = &itmfab;
    itmrab.rab$b_krf = 0;
    itmrab.rab$b_ksz = 4;
    itmrab.rab$l_ubf = (char *) &itmf_buffer;
    itmrab.rab$w_usz = sizeof itmf_buffer;
    itmrab.rab$l_rbf = (char *) &itmf_buffer;
    itmrab.rab$w_rsz = sizeof itmf_buffer;

    sys_create(&itmfab);
    if (status == RMS$_CREATED) {
        itmf_buffer.nitm_grp = 0;

        sys_connect(&itmrab);
        while (sys_get_nornf(&oitmrab)) {
            if (itmf_buffer.nitm_grp != onewsitm.oitm_grp)
                printf("Working on newsgroup #%d\n",onewsitm.oitm_grp);
            itmf_buffer.nitm_num = onewsitm.oitm_num;
            itmf_buffer.nitm_grp = onewsitm.oitm_grp;
            for (i = 0; i < IDLEN; ++i)
                itmf_buffer.nitm_id[i] = onewsitm.oitm_id[i];
            itmf_buffer.nitm_recvdate = onewsitm.oitm_recvdate;
            itmf_buffer.nitm_lines = onewsitm.oitm_size;
            for (i = 0; i < SUBJLEN; ++i)
                itmf_buffer.nitm_title[i] = onewsitm.oitm_title[i];
            itmf_buffer.nitm_cachedate = onewsitm.oitm_locdate;
            itmf_buffer.nitm_life = onewsitm.oitm_life;
            itmf_buffer.nitm_flags = 0;
            if (onewsitm.oitm_new) itmf_buffer.nitm_flags = NEWS_M_NEW;
            itmf_buffer.nitm_cid = 0;
            itmf_buffer.nitm_cno = ++cid;
            sys_put(&itmrab);
            }
        }
    else printf("NEWS V5.8 news item file has already been created\n");

    sys_close(&oitmfab);
    sys_close(&itmfab);
    return(1);
}

#ifdef	STANDALONE
int main()
#else
int v58_upgrade()
#endif
{
    struct stat sp;

    if (!stat(ITM_FILENAME,&sp)) return(0);
    if (stat(OItem_file,&sp)) return(1);

    printf("CONVERSION PROGRAM - NEWS V5.x to NEWS V5.8\n\n");
    printf("This program extends the newsgroup and news item index files\n");
    if (!mcvtfiles())
        printf("Error -cannot open files for conversion - check that this account has SYSPRV\n");
    else {
        printf("Once you have finished installing the NEWS V5.0 executable,\n");
        printf("you will also need to do the following:\n\n");
        printf("    - $ DELETE NEWS_ROOT:NEWSGROUPS.V50;*\n");
        printf("    - $ DELETE NEWS_ROOT:NEWSITEMS.V50;*\n");
        printf("    - in your NEWS housekeeping programs change all occurrances\n");
        printf("      of NEWS_ROOT:NEWSGROUPS.V50 to the new file name NEWS_ROOT:NEWS.GROUPS\n");
        printf("      and NEWS_ROOT:NEWSITEMS.V50 to the new file name NEWS_ROOT:NEWS.ITEMS\n");
        }
    exit(1);
    /*NOTREACHED*/
    return 1;
}
