From:	AITGW::"ake%DAYTON.SAIC.COM@VM1.NoDak.EDU" "Earle Ake"  7-AUG-1991 01:32:08.00
To:	Multiple recipients of list ANU-NEWS <ANU-NEWS@NDSUVM1>
CC:	
Subj:	Rebuild_Item_File V1.1 fixes Geoff's original posting

Received: by AITGW.DECnet (utk-mail11 v1.5) ; Wed, 7 Aug 91 01:28:57 EDT
Received: from vm1.NoDak.edu by aitgw.ge.com (5.61/GE Gateway 1.3)
	id AA14339; Wed, 7 Aug 91 01:27:18 -0400
Message-Id: <9108070527.AA14339@aitgw.ge.com>
Received: from NDSUVM1.BITNET by VM1.NoDak.EDU (IBM VM SMTP R1.2.1MX) with BSMTP id 2105; Wed, 07 Aug 91 00:25:36 CDT
Received: from NDSUVM1.BITNET by NDSUVM1.BITNET (Mailer R2.07) with BSMTP id
 5659; Wed, 07 Aug 91 00:25:33 CDT
Date:         Wed, 7 Aug 1991 01:02:56 GMT
Reply-To: Earle Ake <ake%DAYTON.SAIC.COM@VM1.NoDak.EDU>
Sender: ANU-NEWS Discussion <ANU-NEWS@VM1.NoDak.EDU>
From: Earle Ake <ake%DAYTON.SAIC.COM@VM1.NoDak.EDU>
Subject:      Rebuild_Item_File V1.1 fixes Geoff's original posting
To: Multiple recipients of list ANU-NEWS <ANU-NEWS@NDSUVM1>
 
In article <1991Apr25.001057.1@sao.aarnet.edu.au>, gih900@sao.aarnet.edu.au writ
es:
> In article <1991Apr20.104639.1@sao.aarnet.edu.au>, gih900@sao.aarnet.edu.au wr
ites:
>>> Now, a question:  Why can't there be an utility that simplies rebuild the
>>> index file from scratch?  For example, you can get the post (add) date from
>>> the date of the file, and the titles and all that can come from reading the
>>> inside of the item file.  We could give the program a file specification to
>>> scan, such as NEWS_DEVICE:[*...]*.ITM.  It should matches the original
>>> index file (before corruption, of course) pretty darn close, if not exactly
>>> the same.  Thanks.  (Don't laugh, I don't know how the internals of
>>> ANU-NEWS works, so, there!) :-)
>>
>> Why not?
>>
>> NO _technical_ reason - just my available time (unless of course someone else
>> has been bitten by this hard enough to want to write it themselves).
>>
> OK - I got interested in this and ended up writing it - the following will rea
d
> the stored headers and reconstruct the item file:...
>
> Geoff
 
        I finally had a need to use the program and found some errors in it.
The following are fixed in my version:
 
        1) A printf statement didn't print out the line count as it was
running correctly.  A missing ", item_count" was the culprit.
 
        2) If the item-files parameter 2 on the command line was specified,
the first character was accidently chopped off.  The file specification
news_device:[*...]*.itm became ews_device:[*...]*.itm.  The problem was an
un-needed ++argv[2] for some reason.
 
        3) If an error had occured such as a duplicate record encountered, the
program immediately failed.  The problem I had was this was the reason I was
rebuilding the item file in the first place!  I now report an error and
continue.  Only the first occurance of a unique message-id is entered into the
news.items file anyway.
 
        4) I also print out more information if a bad record is encountered
letting the user know what happened.  Before you would get:
 
 
        PUT returned VMS error:
%RMS-F-DUP, duplicate key detected (DUP not set)
 
 
Now you get:
 
 
Error adding: <comp.mail.misc:3376> <1170@dumbcat.sf.ca.us>
        PUT returned VMS error:
%RMS-F-DUP, duplicate key detected (DUP not set)
 
 
        5) A coding error caused the creation date of every article to be
today's date.  The stat() function returns a '0' for success and the code was
assuming a '1' for success.
 
        6) To try to speed up the creation of the news.items file I have added
an allocation of 150, a default allocation of 150, and a global buffer count of
50 to the item file when opened.
 
        7) I have also included a command procedure to delete the duplicate
items from the news_device:[*...] directory structure.  The input is the name
of the logfile from the rebuild_item_file run.
 
 
-Earle Ake
_____________________________________________________________________________
             ____ ____    ___
Earle Ake   /___ /___/ / /     Science Applications International Corporation
           ____//   / / /__                 Dayton, Ohio
-----------------------------------------------------------------------------
Internet: ake@dayton.saic.com        uucp: dayvb!ake         SPAN: 28284::ake
 
 
$! ------------------ CUT HERE -----------------------
$ v='f$verify(f$trnlnm("SHARE_VERIFY"))'
$!
$! This archive created by VMS_SHARE Version 7.2-007  22-FEB-1990
$!   On  6-AUG-1991 20:59:20.68   By user AKE (Earle Ake - SAIC (513) 429-6500)
$!
$! This VMS_SHARE Written by:
$!    Andy Harper, Kings College London UK
$!
$! Acknowledgements to:
$!    James Gray       - Original VMS_SHARE
$!    Michael Bednarek - Original Concept and implementation
$!
$! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER
$! AND EXECUTE AS A COMMAND PROCEDURE  (  @name  )
$!
$! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING:
$!       1. AAAREADME.TXT;2
$!       2. REBUILD_ITEM_FILE.C;77
$!       3. REBUILD_ITEM_FILE-DELETE.COM;12
$!
$set="set"
$set symbol/scope=(nolocal,noglobal)
$f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID"))
$e="write sys$error  ""%UNPACK"", "
$w="write sys$output ""%UNPACK"", "
$ if f$trnlnm("SHARE_LOG") then $ w = "!"
$ ve=f$getsyi("version")
$ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START
$ e "-E-OLDVER, Must run at least VMS 4.4"
$ v=f$verify(v)
$ exit 44
$UNPACK: SUBROUTINE ! P1=filename, P2=checksum
$ if f$search(P1) .eqs. "" then $ goto file_absent
$ e "-W-EXISTS, File ''P1' exists. Skipped."
$ delete 'f'*
$ exit
$file_absent:
$ if f$parse(P1) .nes. "" then $ goto dirok
$ dn=f$parse(P1,,,"DIRECTORY")
$ w "-I-CREDIR, Creating directory ''dn'."
$ create/dir 'dn'
$ if $status then $ goto dirok
$ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped."
$ delete 'f'*
$ exit
$dirok:
$ w "-I-PROCESS, Processing file ''P1'."
$ if .not. f$verify() then $ define/user sys$output nl:
$ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1'
PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET(
SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:=
CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b));
LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION(
BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1);
IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE;
MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1;
ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")=
1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF";
POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r);
ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1;
COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE,
"output_file"));ENDPROCEDURE;Unpacker;QUIT;
$ delete/nolog 'f'*
$ CHECKSUM 'P1'
$ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT
$ e "-E-CHKSMFAIL, Checksum of ''P1' failed."
$ ENDSUBROUTINE
$START:
$ create 'f'
X6-Aug-1991 V1.1 of REBUILD_ITEM_FILE.C
X
X`09I finally had a need to use the program and found some errors in it.
XThe following are fixed in my version:
X
X`091) A printf statement didn't print out the line count as it was
Xrunning correctly.  A missing ", item_count" was the culprit.
X
X`092) If the item-files parameter 2 on the command line was specified,
Xthe first character was accidently chopped off.  The file specification
Xnews_device:`5B*...`5D*.itm became ews_device:`5B*...`5D*.itm.  The problem
V was an
Xun-needed ++argv`5B2`5D for some reason.
X
X`093) If an error had occured such as a duplicate record encountered, the
Xprogram immediately failed.  The problem I had was this was the reason I was
Xrebuilding the item file in the first place!  I now report an error and
Xcontinue.  Only the first occurance of a unique message-id is entered into t
Vhe
Xnews.items file anyway.
X
X`094) I also print out more information if a bad record is encountered
Xletting the user know what happened.  Before you would get:
X
X
X`09PUT returned VMS error:
X%RMS-F-DUP, duplicate key detected (DUP not set)
X
X
XNow you get:
X
X
XError adding: <comp.mail.misc:3376> <1170@dumbcat.sf.ca.us>
X`09PUT returned VMS error:
X%RMS-F-DUP, duplicate key detected (DUP not set)
X
X
X`095) A coding error caused the creation date of every article to be
Xtoday's date.  The stat() function returns a '0' for success and the code wa
Vs
Xassuming a '1' for success.
X
X`096) To try to speed up the creation of the news.items file I have added
Xan allocation of 150, a default allocation of 150, and a global buffer count
V of
X50 to the item file when opened.
X
X`097) I have also included a command procedure to delete the duplicate
Xitems from the news_device:`5B*...`5D directory structure.  The input is the
V name
Xof the logfile from the rebuild_item_file run.
X
X
X-Earle Ake
XInternet: ake@dayton.saic.com
XSPAN 28284::ake
$ CALL UNPACK AAAREADME.TXT;2 476398789
$ create 'f'
X/*
X**++
X**  FACILITY:
X**      REBUILD_ITEM_FILE
X**
X**  ABSTRACT:
X**      This program does a salvage on the news database.
X**
X**`09The program reads the headers of all locally stored item files, and
X**`09attempts to reconstruct the file news_root:news.items based on the
X**`09local files.
X**  USAGE:
X**      Rebuild_Item_File `5Bindex-file`5D `5Bitem-files`5D
X**
X**`09defaults are:
X**
X**`09index-file`09NEWS_ROOT:NEWS.ITEMS
X**`09item-files`09NEWS_DEVICE:`5B000000...`5D*.ITM;*
X**
X**  AUTHOR:
X**      Geoff Huston
X**
X**  COPYRIGHT:
X**      Copyright, Geoff Huston `A9 1991
X**
X**  VERSION:
X**`09V1.0`0924/4/91`09`09gh
X**`09V1.1`096-Aug-1991`09efa
X**`09 - Correct some initial coding mistakes.  Print more information if a
X**`09   duplicate message-id encountered.  Continue on if duplicate
X**`09   message-id encountered.  Try to speed up routine by adding default
X**`09   allocation, allocation, and buffer count parameters.  Fixed parsing
X**`09   of second parameter where first character was getting dropped.  Fixe
Vd
X**`09   bug where all articles had today's date as creation date in
X**`09   news.items file created.
X**--
X**/
X`0C
X#module RBLDITMFILE "V1.1"
X
X#define _REBUILD_ITEM_FILE_C
X
X#include <ctype.h>
X#include <descrip.h>
X#include <rms.h>
X#include <stdio.h>
X#include <time.h>
X#include "newsdefine.h"
X
X#define IOSIZE 512
X
Xstruct FAB grpfab, itmfab;
Xstruct RAB grprab, itmrab;
Xstruct XABKEY xabkey_1, xabkey_2;
Xstruct XABPRO xabpro_1;
X
XGRP newsgrp;
XITM newsitm;
X
Xvoid open_group_file();
Xvoid open_index_file(char *);
Xvoid scan_files(char *);
Xvoid fill_newsitm(char *);
Xchar *util_undir(char *);
Xvoid util_cvrt(char *, char *);
Xvoid strip(char *, int);
Xvoid util_idcpy(char *, char *);
Xvoid util_fromcpy(char *, char *);
Xvoid util_subjcpy(char *, char *);
Xint cvt_date(int *);
Xint cvt_date_val(char *);
Xint gmt_to_local(int);
Xint local_to_gmt(int);
Xint parse_usenet_date(char *);
Xint substrcmp(char *, char *);
Xvoid strip_compress_lower(char *);
Xvoid close_index_file();
Xvoid close_group_file();
X
X`0C
Xmain(argc, argv)
X  int argc;
X  char *argv`5B`5D;
X`7B
X  char *itemfiles = Itm_files;
X  char *item_index = ITM_FILENAME;
X
X  if (argc > 3) `7B
X    printf("Usage: Rebuild_Item_File `5Bindex-file`5D `5Bitem-files`5D\n");
X    exit(1);
X    `7D
X  if (--argc) `7B
X    item_index = argv`5B1`5D;
X    if (--argc) itemfiles = argv`5B2`5D;
X    `7D
X  open_group_file();
X  open_index_file(item_index);
X  scan_files(itemfiles);
X  close_index_file();
X  close_group_file();
X`7D
X`0C
Xvoid open_group_file()
X`7B
X  int status;
X
X  grpfab = cc$rms_fab;
X  grpfab.fab$b_fac = FAB$M_GET ;
X  grpfab.fab$l_fna = GRP_FILENAME;
X  grpfab.fab$b_fns = strlen(grpfab.fab$l_fna);
X  grpfab.fab$b_shr = FAB$M_SHRDEL `7C FAB$M_SHRGET `7C FAB$M_SHRPUT `7C FAB$
VM_SHRUPD;
X
X  grprab = cc$rms_rab;
X  grprab.rab$l_fab = &grpfab;
X  grprab.rab$l_rbf = grprab.rab$l_ubf = (char *) &newsgrp;
X  grprab.rab$w_rsz = grprab.rab$w_usz = sizeof newsgrp;
X
X  if (!((status = sys$open(&grpfab)) & 1)) `7B
X    printf("VMS error - cannot open news_root:news.groups\n");
X    exit(status);
X    `7D
X  if (!((status = sys$connect(&grprab)) & 1)) `7B
X    printf("VMS error - cannot connect to news_root:news.groups\n");
X    exit(status);
X    `7D
X`7D
X`0C
Xvoid open_index_file(file_name)
X  char *file_name;
X`7B
X  int status;
X
X  itmfab = cc$rms_fab;
X  itmfab.fab$b_bks = 3;`09`09`09/* bucket size`09`09`09*/
X  itmfab.fab$l_alq = 150;`09`09/* allocation quantity`09`09*/
X  itmfab.fab$w_deq = 150;`09`09/* default allocation quantity`09*/
X  itmfab.fab$w_gbc = 50;`09`09/* Global buffer count`09`09*/
X  itmfab.fab$b_fac = FAB$M_PUT ;`09/* file access`09`09`09*/
X  itmfab.fab$l_fna = file_name;
X  itmfab.fab$b_fns = strlen(itmfab.fab$l_fna);
X  itmfab.fab$l_fop = FAB$M_CIF;
X  itmfab.fab$w_mrs = sizeof newsitm;
X  itmfab.fab$b_org = FAB$C_IDX;
X  itmfab.fab$b_rat = FAB$M_CR;
X  itmfab.fab$b_rfm = FAB$C_FIX;
X  itmfab.fab$b_shr = FAB$M_SHRDEL `7C FAB$M_SHRGET `7C FAB$M_SHRPUT `7C FAB$
VM_SHRUPD;
X  itmfab.fab$l_xab = (char *) &xabkey_1;
X
X  xabkey_1 = cc$rms_xabkey;
X  xabkey_1.xab$b_dtp = XAB$C_BN8;
X  xabkey_1.xab$b_flg = 0;
X  xabkey_1.xab$w_pos0 = (char *) &newsitm.itm_num - (char *) &newsitm;
X  xabkey_1.xab$b_ref = 0;
X  xabkey_1.xab$b_siz0 = 8;
X  xabkey_1.xab$l_nxt = (char *) &xabkey_2;
X
X  xabkey_2 = cc$rms_xabkey;
X  xabkey_2.xab$b_dtp = XAB$C_STG;
X  xabkey_2.xab$b_flg = 0;
X  xabkey_2.xab$w_pos0 = (char *) &newsitm.itm_id - (char *) &newsitm;
X  xabkey_2.xab$w_pos1 = (char *) &newsitm.itm_grp - (char *) &newsitm;
X  xabkey_2.xab$b_ref = 1;
X  xabkey_2.xab$b_siz0 = IDLEN;
X  xabkey_2.xab$b_siz1 = 4;
X  xabkey_2.xab$l_nxt = (char *) &xabpro_1;
X
X  xabpro_1 = cc$rms_xabpro;
X  xabpro_1.xab$w_pro = 0xEE00;
X
X  itmrab = cc$rms_rab;
X  itmrab.rab$l_fab = &itmfab;
X  itmrab.rab$b_krf = 0;
X  itmrab.rab$b_ksz = 8;
X  itmrab.rab$l_rbf = itmrab.rab$l_ubf = (char *) &newsitm;
X  itmrab.rab$w_rsz = itmrab.rab$w_usz = sizeof newsitm;
X
X  if (!((status = sys$create(&itmfab)) & 1)) `7B
X    printf("VMS error - cannot create %s\n",file_name);
X    exit(status);
X    `7D
X  if (!((status = sys$connect(&itmrab)) & 1)) `7B
X    printf("VMS error - cannot connect to %s\n",file_name);
X    exit(status);
X    `7D
X`7D
X`0C
Xvoid scan_files(itm_files)
X  char *itm_files;
X`7B
X  int context = 0, status, version, no_grp, item_count = 0;
X  unsigned int itm_key`5B2`5D;
X  char fnam`5B257`5D, grp`5B257`5D, lstgrp`5B257`5D, inline`5BIOSIZE`5D, *s,
V *sf, *p;
X  FILE *fpr;
X  struct dsc$descriptor itm_dsc;
X  struct stat sbuffer;
X  $DESCRIPTOR(fnam_dsc,fnam);
X
X  itm_dsc.dsc$w_length = strlen(itm_files);
X  itm_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
X  itm_dsc.dsc$b_class = DSC$K_CLASS_S;
X  itm_dsc.dsc$a_pointer = itm_files;
X
X  grprab.rab$l_kbf = grp;
X  grprab.rab$b_ksz = SUBJLEN;
X  grprab.rab$b_krf = 0;
X  grprab.rab$l_rop = RAB$M_RRL `7C RAB$M_NLK ;
X  grprab.rab$b_rac = RAB$C_KEY;
X
X  itmrab.rab$l_kbf = (char *) itm_key;
X  itmrab.rab$b_krf = 0;
X  itmrab.rab$b_ksz = 8;
X  itmrab.rab$l_rop = RAB$M_RRL `7C RAB$M_NLK ;
X  itmrab.rab$b_rac = RAB$C_KEY;
X
X  printf("Scanning Item files: %s:\n",itm_files);
X
X  *lstgrp = '\0';
X  while ((status = lib$find_file(&itm_dsc,&fnam_dsc,&context,0,0,0,0)) & 1)
V `7B
X    fnam`5B256`5D = '\0';
X
X    if (!(++item_count % 100)) printf("%d\r",item_count);
X    `20
X    if (s = strchr(fnam,' ')) *s = '\0';
X    if (!(sf = strrchr(fnam,':'))) continue;
X    if (!(sf = strrchr(fnam,'`5B'))) continue;
X    ++sf;
X    if (!(p = strchr(sf,'`5D'))) continue;
X    *p = ' ';
X    if (*sf == '0') `7B
X      if (!(sf = strchr(sf,'.'))) continue;
X      sf++;
X      `7D
X    if (sscanf(sf,"%s %d.ITM;%d",grp,&itm_key`5B0`5D,&version) != 3) `7B
X      *p = '`5D';
X      printf("\tUnrecognized news item file - ?%s?\n",fnam);
X      continue;
X      `7D
X    *p = '`5D';
X    strcpy(grp,util_undir(grp));
X    util_cvrt(grp,grp);
X
X    if (strcmp(grp,lstgrp)) `7B
X      util_cvrt(lstgrp,grp);
X      if (!(sys$get(&grprab) & 1)) `7B
X        printf("\tCannot match directory to groupname - %s\n",lstgrp);
X        no_grp = 1;
X        `7D
X      else `7B
X        no_grp = 0;
X        itm_key`5B1`5D = newsgrp.grp_num;
X        `7D
X      `7D
X    if (no_grp) continue;
X
X    newsitm.itm_num = itm_key`5B0`5D;
X    newsitm.itm_grp = itm_key`5B1`5D;
X    sprintf(inline,"<%d:%d>",newsgrp.grp_num,newsitm.itm_num);
X    util_idcpy(newsitm.itm_id,inline);
X    time(&newsitm.itm_recvdate);
X    newsitm.itm_postdate = newsitm.itm_recvdate;
X    newsitm.itm_lines = 0;
X    newsitm.itm_title`5B0`5D = '\0';
X    newsitm.itm_from`5B0`5D = '\0';
X    newsitm.itm_cachedate = newsitm.itm_life = newsitm.itm_flags = newsitm.i
Vtm_cid = 0;
X
X    if (!(sys$get(&itmrab) & 1)) `7B
X      fpr = fopen(fnam,"r");
X      while (fgets(inline,IOSIZE,fpr)) `7B
X        if (*inline == '\n') break;
X`09fill_newsitm(inline);
X`09`7D
X      fclose(fpr);
X
X      if (stat(fnam,&sbuffer) == 0) newsitm.itm_recvdate = sbuffer.st_ctime;
X      if (!((status = sys$put(&itmrab)) & 1)) `7B
X        printf("\nError adding: ");
X        printf("<%s:%d> ",grp,newsitm.itm_num);
X        printf("%s\n", newsitm.itm_id);
X        printf("\tPUT returned VMS error:\n");
X        if ((status & 0x000fffff) == 0x000184ec)
X          printf("%%RMS-F-DUP, duplicate key detected (DUP not set)\n");
X        else
X          lib$signal(status);
X        `7D
X      `7D
X    `7D
X  lib$find_file_end(&context);
X  printf("\n\nAdded %d news articles.\n", item_count);
X`7D
X`0C
Xvoid fill_newsitm(header_line)
X  char *header_line;
X`7B
X  char *cp;
X  if (cp = strchr(header_line,'\n')) *cp = '\0';
X  if (!strncmp(header_line,"From:",5)) `7B
X    cp = &header_line`5B6`5D;
X    while (isspace(*cp)) ++cp;
X    util_fromcpy(newsitm.itm_from,cp);
X    `7D
X  else if (!strncmp(header_line,"Subject:",8)) `7B
X    cp = &header_line`5B8`5D;
X    while (isspace(*cp)) ++cp;
X    util_subjcpy(newsitm.itm_title,cp);
X    `7D
X  else if (!strncmp(header_line,"Date:",5)) `7B
X    int tmp;
X    cp = &header_line`5B6`5D;
X    while (isspace(*cp)) ++cp;
X    if (tmp = parse_usenet_date(cp)) newsitm.itm_postdate = tmp;
X    `7D
X  else if (!strncmp(header_line,"Lines:",5)) `7B
X    if (sscanf(header_line,"Lines: %d",&newsitm.itm_lines) == 1)
X      newsitm.itm_flags `7C= NEWS_M_LINESVALID;
X    `7D
X  else if (!strncmp(header_line,"Message-ID:",11)) `7B
X    cp = &header_line`5B12`5D;
X    while (isspace(*cp)) ++cp;
X    util_idcpy(newsitm.itm_id,cp);
X    `7D
X`7D
X`0C
X/*
X *  util_undir
X *
X *  Convert a directory name to a newsgroup string
X */
X
Xchar *util_undir(input)
X  char *input;
X`7B
X  static char undir_result`5BSUBJLEN`5D;
X  char *p = undir_result,
X       *in = input;
X
X  while (*in) `7B
X    if (*in == '_') `7B
X      in++;
X      if (*in < 'A') *p++ = (*in - '0') + ':';
X      else if (*in < 'P') *p++ = (*in - 'A') + '!';
X      else if (*in < 'V') *p++ = (*in - 'P') + '`5B';
X      else *p++ = (*in - 'V') + '`7B';
X      `7D
X    else *p++ = tolower(*in);
X    in++;
X    `7D
X  *p = '\0';
X  return(undir_result);
X`7D
X`0C
X/*
X *  util_cvrt
X *
X *  Convert a string into standard newsgroup format
X */
X
Xvoid util_cvrt(result, input)
X    char *result,
X         *input;
X`7B
X  char *p = result,
X       *in = input;
X  int i;
X
X  while ((*in) && (*in == ' ')) in++;
X  strncpy(result,in,SUBJLEN);
X  result`5BSUBJLEN - 1`5D = '\0';
X  strip(result,strlen(result));
X  while (*p) `7B
X    if (isgraph(*p)) *p = tolower(*p);
X    else *p = '_';
X    p++;
X    `7D
X  i = strlen(result);
X  while (i < SUBJLEN) result`5Bi++`5D = '\0';
X`7D
X`0C
X/*
X *  strip
X *
X *  remove trailing blanks
X */
X
Xvoid strip(p,n)
X  char *p;
X  int n;
X`7B
X  do `7B
X    n--;
X    `7D while ((n > 0) && (p`5Bn`5D == ' '));
X  p`5Bn+1`5D = '\0';
X`7D
X`0C
X/*
X *  util_idcpy
X *
X *  block copy (including padding nulls)
X */
X
Xvoid util_idcpy(result,input)
X  char *result,
X       *input;
X`7B
X  int i = 0, j = 0;
X
X  while (i < IDLEN) result`5Bi++`5D = input`5Bj`5D ? input `5Bj++`5D : input
V`5Bj`5D;
X  result`5B--i`5D = '\0';
X`7D
X/*
X *  util_fromcpy
X *
X *  block copy (including padding nulls)
X */
X
Xvoid util_fromcpy(result,input)
X  char *result,
X       *input;
X`7B
X  int i = 0, j = 0;
X
X  while (i < FROMLEN) result`5Bi++`5D = input`5Bj`5D ? input `5Bj++`5D : inp
Vut`5Bj`5D;
X  result`5B--i`5D = '\0';
X`7D
X`0C
X/*
X *  util_subjcpy
X *
X *  block copy (including padding nulls)
X */
X
Xvoid util_subjcpy(result,input)
X  char *result,
X       *input;
X`7B
X  int i = 0, j = 0;
X
X  while (i < SUBJLEN) result`5Bi++`5D = input`5Bj`5D ? input `5Bj++`5D : inp
Vut`5Bj`5D;
X  result`5B--i`5D = '\0';
X`7D
X`0C
X/*
X *  cvt_date_val
X *
X *  Convert from VMS date format to unix integer date value
X */
X
Xint cvt_date(vdate)
X  int *vdate;
X`7B
X  int offset`5B2`5D = `7B0X4BEB4000, 0X007C9567`7D,
X      adjtim`5B2`5D,
X      divisor = 10000000,
X      udate;
X
X  if (vdate`5B1`5D < 0) `7B
X    int now`5B2`5D,
X        then`5B2`5D,
X        len = 2;
X
X    sys$gettim(now);
X    lib$subx(now,vdate,then, &len);
X    *vdate = *then;
X    *(vdate + 1) = *(then + 1);
X    `7D
X  lib$subx(vdate, offset, adjtim, c$ac(2));
X  lib$ediv(&divisor, adjtim, &udate, vdate);
X  return(udate);
X`7D
X`0C
Xint cvt_date_val(str)
X    char *str;
X`7B
X  char locstr`5B132`5D,
X       *l = locstr,
X       *p = str;
X  time_t ctime;
X  struct tm *stm;
X  int vdate`5B2`5D;
X  unsigned short ngroup_len = 0;
X  $DESCRIPTOR(locstr_dsc,locstr);
X
X
X  do `7B
X    *l++ = toupper(*p++);
X    `7D while (*p);
X  *l = '\0';
X
X  if (!strcmp(locstr,"TODAY")) `7B
X    time(&ctime);
X    stm = localtime(&ctime);
X    return(ctime - (stm->tm_sec + (stm->tm_min * 60) + (stm->tm_hour * 3600)
V));
X    `7D
X  if (!strcmp(locstr,"YESTERDAY")) `7B
X    time(&ctime);
X    stm = localtime(&ctime);
X    return(ctime - (stm->tm_sec + (stm->tm_min * 60) + (stm->tm_hour * 3600)
V + DAY_SECS));
X    `7D
X  if (!strcmp(locstr,"TOMORROW")) `7B
X    time(&ctime);
X    stm = localtime(&ctime);
X    return(ctime - (stm->tm_sec + (stm->tm_min * 60) + (stm->tm_hour * 3600)
V) + DAY_SECS);
X    `7D
X  locstr_dsc.dsc$w_length = strlen(locstr);
X  if (!(sys$bintim(&locstr_dsc,vdate) & 1)) return(0);
X  else return(cvt_date(vdate));
X`7D
X`0C
X/*
X *  parse_usenet_date
X *
X *  Convert a Unix date string to a time value.
X */
X
Xstatic int gmt_offset_set = 0,
X    gmt_offset = 0;
X
Xint gmt_to_local(filt_date)
X  int filt_date;
X`7B
X  char *cp,
X       news_gmt_offset`5B256`5D;
X  int sign = 1,
X      hr,mn,se;
X
X  if (!gmt_offset_set) `7B
X    if (cp = getenv("NEWS_GMT_OFFSET")) `7B
X      strcpy(news_gmt_offset,cp);
X      strip_compress_lower(news_gmt_offset);
X      cp = news_gmt_offset;
X      if (*cp == '-') `7B
X        sign = -1;
X        ++cp;
X        `7D
X      else if (*cp == '+') ++cp;
X      hr = mn = se = 0;
X      if (sscanf(cp,"%d:%d:%d",&hr,&mn,&se) > 0) `7B
X        gmt_offset = (60 * 60 * hr) + (60 * mn) + se;
X        gmt_offset *= sign;
X        `7D
X      `7D
X    else gmt_offset_set = 1;
X    `7D
X  return(filt_date + gmt_offset);
X`7D
X
Xint local_to_gmt(local_date)
X  int local_date;
X`7B
X  if (!gmt_offset_set) gmt_to_local(0);
X  return(local_date - gmt_offset);
X`7D
X`0C
Xint parse_usenet_date(s)
X  char *s;
X`7B
X  char *cp, mon`5B80`5D, pdate`5B15`5D;
X  int dom = 0, yr = 0, hr = 0, mn = 0, sc = 0, cvttime;
X
X  if (!s `7C`7C !*s) return(0);
X  if (cp = strchr(s,',')) s = ++cp;
X  while (isspace(*s)) s++;
X  *mon = '\0';
X  if (isdigit(*s)) `7B
X    sscanf(s,"%d %s %d %d:%d:%d",&dom,mon,&yr,&hr,&mn,&sc);
X    yr += 1900;
X    `7D
X  else sscanf(s,"%*s %s %d %d:%d:%d %d",mon,&dom,&hr,&mn,&sc,&yr);
X
X  if (!dom `7C`7C !yr `7C`7C !*(cp = mon)) return(0);
X  if ((dom <= 0) `7C`7C (dom >= 32)) return(0);
X  if ((yr < 1989) `7C`7C (yr > 2020)) return(0);
X  if (strlen(mon) > 10) return(0);
X  if ((hr < 0) `7C`7C (hr > 23)) return(0);
X  if ((mn < 0) `7C`7C (mn > 59)) return(0);
X  if ((sc < 0) `7C`7C (sc > 59)) return(0);
X
X  while (*cp) `7B *cp = toupper(*cp); ++cp; `7D
X  sprintf(pdate,"%d-%s-%d %d:%d:%d",dom,mon,yr,hr,mn,sc);
X  if ((cvttime = cvt_date_val(pdate)) && substrcmp(s,"GMT"))
X    return(gmt_to_local(cvttime));
X  return(cvttime);
X`7D
X/*
X *  substrcmp
X *
X *  return 1 if the second arg is a substring of the first arg
X */
X
Xint substrcmp(s,sub)
X  char *s,
X       *sub;
X`7B
X  char *cp = s;
X  int i, bl = strlen(sub), sl = strlen(s);
X
X  for (i = 0; i <= (sl - bl); ++i)
X    if (!strncmp(&s`5Bi`5D,sub,bl)) return(i+1);
X  return(0);
X`7D
X`0C
X/*
X *  strip_compress_lower
X *
X *  Strip off leading and trailing blanks, convert all whitespace to a singl
Ve
X *  space, and convert all alphas to lower case.
X */
X
Xvoid strip_compress_lower(s)
X  char *s;
X`7B
X  char *start = s,
X       *r = s;
X
X  while (*s) `7B
X    if (isgraph(*s)) *r++ =tolower(*s);
X    else if ((r > start) && (*(r-1) != ' ')) *r++ = ' ';
X    s++;
X    `7D
X  if ((r > start) && (*(r-1) == ' ')) --r;
X  *r = '\0';
X`7D
X`0C
Xvoid close_index_file()
X`7B
X  sys$close(&itmfab);
X`7D
X`0C
Xvoid close_group_file()
X`7B
X  sys$close(&grpfab);
X`7D
$ CALL UNPACK REBUILD_ITEM_FILE.C;77 1014693411
$ create 'f'
X$ inquire/nopunctuation file "Enter rebuild_item_file logfile name: "
X$ open/read input1 'file
X$!
X$ loop:
X$   read/end=closeit input1 line
X$   if f$extract(0,14,line) .eqs. "Error adding: "
X$   then
X$     line = line - f$extract(0,14,line)
X$     p1 = f$locate("<",line)
X$     p2 = f$locate(":",line)
X$     p3 = f$locate(">",line)
X$     newsgroup = f$extract(p1+1,p2-p1-1,line)
X$     itemnum = f$extract(p2+1,p3-p2-1,line)
X$     write sys$output "$ delete/log news_device:`5B''newsgroup'`5D''itemnum
V'.itm;0"
X$     delete/log news_device:`5B'newsgroup'`5D'itemnum'.itm;0
X$   endif
X$   goto loop
X$!
X$ closeit:
X$   close input1
X$   exit
$ CALL UNPACK REBUILD_ITEM_FILE-DELETE.COM;12 39740327
$ v=f$verify(v)
$ EXIT
