/*
**++
**  FACILITY:
**      NEWSDEFINE.H
**
**  ABSTRACT:
**      Common NEWS constant definitions.
**
**  AUTHOR:
**      Geoff Huston
**
**  COPYRIGHT:
**      Copyright © 1988,1989,1990,1991
**
**  Modification History:
**    6.1b5  Charles Bailey  bailey@genetics.upenn.edu
**      - 'unseenitems' changed to 'unreaditems' throughout
**    6.1b7  15-May-1993  Charles Bailey  bailey@genetics.upenn.edu
**      - added IDMAP struct and NEWS_[M|V]_ITMIDSSET for message-ID handling
**    6.1b7  Charles Bailey  bailey@genetics.upenn.edu
**      - added NEWS_GRPFIL_RSZ preprocessor symbol
**    6.1b9  25-May-1994  Pat Rankin  rankin@eql.caltech.edu
**	- move globalvalue NEWS$_xxx and NNTP$_xxx to new file "newsmsg.h"
**	  and `globalref news_msg_hook' to newsrtl.c.
**    6.1b9   4-Jun-1994  Dick Munroe munroe@dmc.com
**	- added estimated article count.
**    6.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
**    6.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)
**    6.1b9  19-Sep-1994     Mark Martinec   mark.martinec@ijs.si
**	- define the ANSI and traditional form of macro  news_assert
**	  to assure proper conversion to string of the first parameter
**    6.1b9   6-Oct-1994     Mark Martinec   mark.martinec@ijs.si
**	- rearanged the order of fields in structures: itms, grps and sys_entry
**	  to naturally align structure members
**    6.1b9  15-Jan-1995  Charles Bailey  bailey@genetics.upenn.edu
**	- added grp_funread to grp struct
**    6.1b10  5-Sep-1996     Mark Martinec   mark.martinec@ijs.si
**      - make two separate structures for newsgroup:
**	  * GRP  is used for in-memory structure;
**	  * GRPF is used for file I/O and exactly corresponds
**	         to a record in NEWS.GROUPS file.
**	  This change is reflected in many modules but only documented here.
**	  The main reason for this was to significantly reduce page faulting
**	  when the number of newsgroups is very high. For a single loop e.g.
**	  to set a flag for each group (say 10000 groups), it was necessary
**	  to page through 10000*524/512 = 10k pages and now this is reduced
**	  to 10000*160/512 = 3k pages, which has a far better chance of
**	  staying in the process' working set. Also virtual memory is somewhat
**	  reduced since space for blanks in the newsgroup title, notice
**	  and NNTP server node is not allocated. The in-memory structures
**	  now have a more optimal memory alignment for AXP.
**	  Routines for conversion of in-memory <--> i/o structures are provided
**	  (see: cnvgroup_inmemory_to_filerec,
**	        cnvgroup_filerec_to_inmemory, new_group).
**    6.1b10  9-Sep-1996     Mark Martinec   mark.martinec@ijs.si
**	- add field grp_firstnum (lowest article number) to the group record;
**        It appears that this field was updated in the file even though
**	  the comments claimed that it is in the memory-only region of the
**	  group structure. NNTP server uses this info for the clients.
**	  It is updated by the skim procedure (plus at some other locations).
**      NOTE: the location of this field in the file record is now changed
**	  (to avoid having a field in the middle of the filler).
**	  This introduces inconsistency with the upgrade, but the SKIM phase
**	  will recalculate this value, so this should not be a problem.
**	V6.1b10 09-DEC-1996	Mark Pizzolato	mark@infocomm.com
**	- Changed the definition of "establish_handler" when working under
**	  DEC C, to properly cast the argument function type to return
**	  unsigned int.  It seems that recent changes to the signal.h 
**	  include file uses a typedefed prototype which is incompatible.
**	V6.1b11  7-May-1997	Mark Martinec   mark.martinec@ijs.si
**      - all modules: 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, and ANU in a NNTP client mode
**        may access groups with longer names than local database
**        would accomodate.
**      - grp_name field in the GRP structure is now dynamically allocated
**	  to save on virtual memory by storing only the actual title sizes
**	
**--
**/

#ifndef _NEWSDEFINE_H

#define _NEWSDEFINE_H

#include "newssite.h"
#include <stdio.h>

#ifdef __DECC
#pragma member_alignment save
#endif

#ifdef	__GNUC__
		/* GNU CC settings */
/*
 * Can't use VAXC$ESTABLISH() with v1.x (actually 2.2 or higher is needed
 * to use it, but there's no way to test the minor version number).
 * If using 2.0 or 2.1, then compile with /define="GNUC_HANDLER_HACK".
 */
#if __GNUC__ < 2
#define GNUC_HANDLER_HACK 1
#define C$_LONGJMP 0x0035C05C	/* from module C$ERRNO in VAXCRTL */
#endif
#endif

#ifndef GNUC_HANDLER_HACK
#define GNUC_HANDLER_HACK 0
#endif

/*
 *  PROTOTYPES is something that says whether we can define functions with
 *  argument prototypes, as allowed by ANSI C.
 */

#ifdef vaxc
/* note: viable for VAX C v2.3 and later; not for v2.2 or earlier */
#define PROTOTYPES	1
#endif

#ifndef	PROTOTYPES
#ifdef	__STDC__
#define	PROTOTYPES	1
#else
#define	PROTOTYPES	0
#endif
#endif

/* can we use globalref, globaldef and globalvalue ? */
#if defined(vaxc) || defined(__DECC)
#define NOGLOBALREF	0
#else
#define NOGLOBALREF	1
#endif

#define MAXQUALLEN      132

#define IO_SIZE         512             /* various string sizes */
#define FILE_SIZE       256
#define NODE_SIZE       256
#define NGRP_SIZE       256

#ifdef module_name
static const char module_name_str[] = module_name;
#else
static const char *module_name_str = NULL;
#endif

/* how should condition handler react on signals of severity
   levels ERROR or SEVERE, after reporting signal condition first: */
#define ON_ERROR_ABORT    0  /* abort program execution */
#define ON_ERROR_UNWIND   1  /* unwind to main loop (cont. with next command) */
#define ON_ERROR_CONTINUE 2  /* return to the point of failure and continue   */

#if GNUC_HANDLER_HACK
#  define establish_handler(handler) lib$establish(handler)
#elif defined(__DECC) /* avoid 'int' vs 'unsigned int' conflict in return type*/
#  define establish_handler(handler) \
     VAXC$ESTABLISH((unsigned int(*)(void *,void *))handler)
#else
#  define establish_handler(handler) VAXC$ESTABLISH(handler)
#endif

#ifdef __STDC__
#define news_assert(expr) \
  ( (expr) ? 1 : (news_assert_routine(#expr,module_name_str,__LINE__,0),0) )
#define news_assert_nonfatal(expr) \
  ( (expr) ? 1 : (news_assert_routine(#expr,module_name_str,__LINE__,1),0) )
#else
#define news_assert(expr) \
  ( (expr) ? 1 : (news_assert_routine("expr",module_name_str,__LINE__,0),0) )
#define news_assert_nonfatal(expr) \
  ( (expr) ? 1 : (news_assert_routine("expr",module_name_str,__LINE__,1),0) )
#endif

/* c$cks and _c$cks are appropriate for reporting status with facility=system */
#define  c$cks(s)  c$cks_routine(s,module_name_str,__LINE__)
#define _c$cks(s)  (((status=(s)) & 1) ? 1 : (cks_routine(status,module_name_str,__LINE__),0))
  /* _c$cks(x) is equivalent to _ck_sys(0,0,x) and to _ck_sys(SS$_NORMAL,0,x);
   * _c$cks is much like _ck_sys, but for historic reasons kept the old name
   * and for reduced code length has its own routine with less parameters.
   */
/**/
/* _ck_sys reports a user status plus an optional system condition code */
#define _ck_sys(user_status,user_value,s)  (((status = (s)) & 1) ? 1 : \
  (report_sys_error_routine(user_status,user_value,status,module_name_str,__LINE__),0))
/**/
/* checks on C RTL operations: */
#define report_cio_error(user_status,file_ptr) \
  report_cio_error_routine(user_status,file_ptr,0,module_name_str,__LINE__)
#define _ck_open_r(file_ptr,file_name) \
  (((file_ptr) && !ferror(file_ptr)) ? 1 : \
   (report_cio_error_routine(NEWS$_OPNFAIL,file_ptr,file_name,module_name_str,__LINE__),0))
#define _ck_open_w(file_ptr,file_name) \
  (((file_ptr) && !ferror(file_ptr)) ? 1 : \
   (report_cio_error_routine(NEWS$_CREFAIL,file_ptr,file_name,module_name_str,__LINE__),0))
#define _ck_open_a(file_ptr,file_name) \
  (((file_ptr) && !ferror(file_ptr)) ? 1 : \
   (report_cio_error_routine(NEWS$_APPFAIL,file_ptr,file_name,module_name_str,__LINE__),0))
#define _ck_close(file_ptr) \
  ((!errno) ? 1 : /* close sets *file_ptr=NULL, ferror must not be called */  \
   (report_cio_error_routine(NEWS$_CLOFAIL,file_ptr,0,module_name_str,__LINE__),0))
#define _ck_seek(file_ptr) \
  (((file_ptr) && !ferror(file_ptr)) ? 1 : \
   (report_cio_error_routine(NEWS$_FNDFAIL,file_ptr,0,module_name_str,__LINE__),0))
#define _ck_get(file_ptr) \
  (((file_ptr) && !ferror(file_ptr)) ? 1 : \
   (report_cio_error_routine(NEWS$_GETFAIL,file_ptr,0,module_name_str,__LINE__),0))
#define _ck_put(file_ptr) \
  (((file_ptr) && !ferror(file_ptr)) ? 1 : \
   (report_cio_error_routine(NEWS$_PUTFAIL,file_ptr,0,module_name_str,__LINE__),0))
#define _ck_delete(file_name) \
  ((!errno) ? 1 : /* file_ptr not available, ferror must not be called */  \
   (report_cio_error_routine(NEWS$_REMFAIL,0,file_name,module_name_str,__LINE__),0))
#define _ck_rename(old_file_name,new_file_name) \
  ((!errno) ? 1 : /* file_ptr not available, ferror must not be called */  \
   (report_cio_error_routine(NEWS$_RENFAIL,0,old_file_name,module_name_str,__LINE__),0))
/**/
/* checks on RMS operations: */
#define report_rms_error(user_status,rms_status,fabrab) \
  report_rms_error_routine(user_status,rms_status,fabrab,module_name_str,__LINE__)
#define sys_open(fab)	(((status=sys$open(fab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_OPNFAIL,status,fab,module_name_str,__LINE__),0))
/* sys_open_nofnf differs from sys_open in that it does not signal RMS$_FNF */
#define sys_open_nofnf(fab) (((status=sys$open(fab)) & 1) ? 1 : \
  ((status==RMS$_FNF?0:report_rms_error_routine(NEWS$_OPNFAIL,status,fab,module_name_str,__LINE__)),0))
#define sys_create(fab)	(((status=sys$create(fab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_CREFAIL,status,fab,module_name_str,__LINE__),0))
#define sys_close(fab)	(((status=sys$close(fab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_CLOFAIL,status,fab,module_name_str,__LINE__),0))
#define sys_connect(rab) (((status=sys$connect(rab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_CONFAIL,status,rab,module_name_str,__LINE__),0))
#define sys_rewind(rab)	(((status=sys$rewind(rab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_REWFAIL,status,rab,module_name_str,__LINE__),0))
#define sys_get(rab)	(((status=sys$get(rab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_GETFAIL,status,rab,module_name_str,__LINE__),0))
/* sys_get_noeof differs from sys_get in that it does not signal EOF */
#define sys_get_noeof(rab) (((status=sys$get(rab)) & 1) ? 1 : \
  ((status==RMS$_EOF?0:report_rms_error_routine(NEWS$_GETFAIL,status,rab,module_name_str,__LINE__)),0))
/* sys_get_nornf differs from sys_get in that it does not signal EOF or RNF */
#define sys_get_nornf(rab) (((status=sys$get(rab)) & 1) ? 1 : \
  ((status==RMS$_RNF||status==RMS$_EOF?0:report_rms_error_routine(NEWS$_GETFAIL,status,rab,module_name_str,__LINE__)),0))
#define sys_put(rab)	(((status=sys$put(rab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_PUTFAIL,status,rab,module_name_str,__LINE__),0))
/* sys_put_nodup differs from sys_put in that it does not signal RMS$_DUP */
#define sys_put_nodup(rab) (((status=sys$put(rab)) & 1) ? 1 : \
  ((status==RMS$_DUP?0:report_rms_error_routine(NEWS$_PUTFAIL,status,rab,module_name_str,__LINE__)),0))
#define sys_find(rab)	(((status=sys$find(rab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_FNDFAIL,status,rab,module_name_str,__LINE__),0))
#define sys_find_nornf(rab) (((status=sys$find(rab)) & 1) ? 1 : \
  ((status==RMS$_RNF||status==RMS$_EOF?0:report_rms_error_routine(NEWS$_FNDFAIL,status,rab,module_name_str,__LINE__)),0))
#define sys_update(rab)	(((status=sys$update(rab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_UPDFAIL,status,rab,module_name_str,__LINE__),0))
#define sys_delete(rab)	(((status=sys$delete(rab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_DELFAIL,status,rab,module_name_str,__LINE__),0))
#define sys_free(rab)	(((status=sys$free(rab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_FREEFAIL,status,rab,module_name_str,__LINE__),0))
#define sys_free_nornl(rab) (((status=sys$free(rab)) & 1) ? 1 : \
  ((status==RMS$_RNL?0:report_rms_error_routine(NEWS$_FREEFAIL,status,rab,module_name_str,__LINE__)),0))
#define sys_read(rab)	(((status=sys$read(rab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_RDFAIL,status,rab,module_name_str,__LINE__),0))
/* sys_read_noeof differs from sys_read in that it does not signal EOF */
#define sys_read_noeof(rab) (((status=sys$read(rab)) & 1) ? 1 : \
  ((status==RMS$_EOF?0:report_rms_error_routine(NEWS$_RDFAIL,status,rab,module_name_str,__LINE__)),0))
#define sys_write(rab)	(((status=sys$write(rab)) & 1) ? 1 : \
  (report_rms_error_routine(NEWS$_WRFAIL,status,rab,module_name_str,__LINE__),0))

#if SIMPLE_MALLOC
#define news_malloc_raw(size)		malloc(size)
#define news_calloc_raw(n,csize)	calloc(n,csize)
#define news_realloc_raw(oldp,newsize)	realloc(oldp,newsize)
#define news_free_raw(ptr)		free(ptr)
#define news_free(ptr)			news_free_raw(ptr)
#else
#define news_free(ptr)			news_free_raw(ptr)
#endif

#ifdef vaxc
#define c$ac(v)		&(v)
#else
#define c$ac(v)		c$rfi(v)
#endif

#if (defined(__DECC) || defined(__DECCXX)) && !defined(__ALPHA)
#  define set_errno(v)		(cma$tis_errno_set_value(v))
#  define set_vaxc_errno(v)	(vaxc$errno = (v))
#else
#  define set_errno(v)		(errno = (v))
#  define set_vaxc_errno(v)	(vaxc$errno = (v))
#endif

#define max(a,b)        (((a) > (b)) ? (a) : (b))
#define min(a,b)        (((a) > (b)) ? (b) : (a))
#define	empty_string(s)	(*(s) == '\0')


#define DAY_SECS        86400

#define HLP$V_PROMPT    0

#define DIR_ALL         0
#define DIR_DATE        1
#define DIR_NEW         2
#define DIR_REGISTER    3
#define DIR_UNREGISTER  4

#define HELP_FILE       "NEWS_ROOT:NEWS.HLB"

#define ALIAS_FILE      "NEWS_MANAGER:NEWS.ALIASES"
#define ADDRESS_FILE    "NEWS_MANAGER:NEWS_ADDRESS.CNF"
#define MAILPATHS_FILE  "NEWS_MANAGER:MAILPATHS"
#define SYS_FILE        "NEWS_MANAGER:NEWS.SYS"
#define SYSD_FILE       "NEWS_MANAGER:NEWS.SYSD"
#define DIST_FILE       "NEWS_MANAGER:NEWS.DISTRIBUTION"
#define DISTRIBUTIONS_FILE	"NEWS_MANAGER:NEWS.DISTRIBUTIONS"
#define POSTCC_FILE     "NEWS_MANAGER:NEWS_POST.CC"
#define PGPCALL_FILE    "NEWS_MANAGER:PGPCALL.COM"

#define NNTP_ACCESS_FILE    "NEWS_ROOT:NNTP_ACCESS.NEWS"

#define HIST_FILE       "NEWS_ROOT:HISTORY.V60"

#define HIST_OFF       "NEWS_ROOT:HISTORY.OFF"
#define HIST_VAL        45

#define User_file       "SYS$LOGIN:NEWSRC"
#define Itm_files       "NEWS_DEVICE:[000000...]*.ITM;*"
#define Itm_template    "NEWS_DEVICE:[%s]%d.ITM"
#define Itm_device	"NEWS_DEVICE:"
#define Itmg_template   "NEWS_DEVICE:[%s]*.ITM;*"
#define Grp_template    "NEWS_DEVICE:[%s]"
#define Dir_template    "NEWS_DEVICE:[000000.%s^DIR"
#define Access_template "NEWS_DEVICE:[%s]ACCESS.NEWS"
#define News_ini        "NEWS_INI"

#define DISP_BUF_SIZE   2000

#define GRPNAMELEN 	100 /* Max length of newsgroup name (in memory,
                               '\0'-terminated, limits group names
                               in the NNTP client mode). This limit applies
                               mostly to temporary buffers. Space for keeping
                               all titles is allocated dynamically as needed  */

#define GRPNAMELEN_F	50  /* length of newsgroup name in the groups file
                               (not necessarily '\0'-terminated)

                               Requirement:  GRPNAMELEN >= GRPNAMELEN_F+1 .

                               NOTE: set to 50 if you want to avoid converting
                                     an existing NEWS.GROUPS file;  set to a
                                     larger value (recommended 80) to support
                                     longer group names in the local database */

#define SUBJLEN 	50  /* max length of article title (subject) */
#define IDLEN           60
#define FROMLEN		60

/*
 * newsitem file: record structure
 */

#define ITM_FILENAME   "NEWS_ROOT:NEWS.ITEMS"

#ifdef __DECC
#pragma nomember_alignment  /* no member alignment - this is a file record */
#endif
typedef struct {
    unsigned int itm_num;           /* newsitem index [key 0, b 1-4] 4   4 */
    unsigned int itm_grp;           /* newsgroup index[key 0, b 5-8] 4   8 */
                                    /*                [key 1, seg 1]       */
    char itm_id[IDLEN];             /* item id        [key 1, seg 0]60  68 */
    unsigned int itm_recvdate;      /* recvdate                      4  72 */
    unsigned int itm_lines;         /* lines                         4  76 */
    char itm_title[SUBJLEN];        /* title                        50 126 */
    unsigned int itm_cachedate;     /* server - cache entry date     4 130 */
    unsigned short itm_life;        /* retention period              2 132 */
    unsigned int itm_flags;         /* item flags                    4 136 */
    unsigned int itm_cid;           /* conversation id [key 2, b1-4] 4 140 */
    unsigned int itm_postdate;      /* posted date                   4 144 */
    char itm_from[FROMLEN];         /* poster                       60 204 */  
    } ITM, *ITM_PTR;

/*
 * itm_flags - bit definitions
 */

#define NEWS_M_NEW              1       /* new item */
#define NEWS_M_UNREAD           2       /* unread item */
#define NEWS_M_XPOST		4	/* local xposting to another newsgroup*/
#define NEWS_M_MAILITEM		8
#define NEWS_M_MAILMARK		16
#define NEWS_M_MAILREPLIED	32
#define NEWS_M_NOACCESS		64
#define NEWS_M_LINESVALID	128

#define NEWS_V_NEW              0
#define NEWS_V_UNREAD           1
#define NEWS_V_XPOST		2
#define NEWS_V_MAILITEM		3
#define NEWS_V_MAILMARK		4
#define NEWS_V_MAILREPLIED	5
#define NEWS_V_NOACCESS		6
#define NEWS_V_LINESVALID	7

/*
 * linked list element for message-IDs of articles which have not yet been
 * retrieved from nntp server.
 */

#ifdef __DECC
#pragma member_alignment
#endif
typedef struct idmap_element {
    unsigned int itm_num;           /* server's item number          4   4 */
    char id[IDLEN];                 /* item id                      60  60 */
    struct idmap_element *f_link;   /* forward link                  4  64 */
    struct idmap_element *b_link;   /* back link                     4  68 */
    } IDMAP, *IDMAP_PTR;

/*
 * newsgroup file: record structure
 */

#define GRP_FILENAME   "NEWS_ROOT:NEWS.GROUPS"

/* This is the size of the records in the News.Groups file. */
#define NEWS_GRPFIL_RSZ 512  /* should be equal to the sizeof(GRPF) */

#ifdef __DECC
#pragma member_alignment  /* member alignment - this is a memory structure *only* */
#endif
/* This structure contains info from the NEWS.GROUPS file record
   plus other dynamic information. Mapping to GRP structure is
   field-by-field to allow for different alignments.  */
typedef struct {
    unsigned int grp_num;           /* newsgroup index [key 1]       4 */
    unsigned int grp_topnum;        /* highest item number used      4 */
    unsigned int grp_count;         /* item count                    4 */
    unsigned int grp_credate;       /* date created (unixtime)       4 */
    unsigned int grp_entdate;       /* last entry date (unixtime)    4 */
    unsigned int grp_flags;         /* newsgroup flags               4 */
    unsigned int grp_firstnum;	    /* lowest article number         4 */
    unsigned short grp_life;        /* newsgroup hold time (days)    2 */
    unsigned short grp_itmlife;     /* item retention time (days)    2 */
    unsigned short grp_srvcache;    /* NNTP client cache time        2 */
    char grp_srvproto;              /* NNTP transport protocol       1 */
    char grp_filler1;               /* alignment filler              1 */
       /* End of area that maps field-by-field to the file record. */
    char *grp_name;                 /* newsgroup name  [key 0]         */
    unsigned char grp_displaystk;/* used by unseenstack (in-memory only) 1 */
    char grp_filler2;               /* alignment filler              1 */
       /* The following three pointers point to dynamically allocated strings;
          the actual file record contains these three strings in-place.*/
    char *grp_srvnode;              /* NNTP server node              4 */
    char *grp_topic;                /* group topic line              4 */
    char *grp_notice;               /* group notice line             4 */
       /* The remainder of the record has no correspondence in the file */
    int grp_reg;                    /* registered level              4 */
    unsigned int grp_unread;        /* unread count                  4 */
    ITM_PTR grp_ia;                 /* item array                    4 */
    unsigned int grp_iasize;        /* item array size               4 */
    int grp_iavd;                   /* item virtual display          4 */
    int grp_iavdsize;               /* item virtual disp size        4 */
    int grp_iapaste;                /* item display paste pos        4 */
    unsigned int grp_c_itm;         /* item current index            4 */
    int grp_display_indx;           /* group display position        4 */
    char *grp_reg_text;             /* register test pointer         4 */
    unsigned int grp_topreadnum;    /* top read number               4 */
    IDMAP_PTR grp_idhead;           /* head of ID list               4 */
    IDMAP_PTR grp_idtail;           /* end of ID list                4 */
    unsigned int grp_funread;       /* lowest unread article number  4 */
#if ARBITRON
    int arb_readtime;  /* when was the group read for the last time  4 */
#endif
    } GRP, *GRP_PTR;

#ifdef __DECC
#pragma nomember_alignment  /* no member alignment - this is a file record */
#endif
/* file records in file NEWS.GROUPS map *exactly* to this structure */
typedef struct {
    char grp_name[GRPNAMELEN_F];    /* newsgroup name  [key 0]      50  50 */
                /* grp_name field is '\0'-filled, but filler size may be 0 */
    unsigned int grp_num;           /* newsgroup index [key 1]       4  54 */
    unsigned int grp_topnum;        /* highest item number used      4  58 */
    unsigned int grp_count;         /* item count                    4  62 */
    unsigned int grp_credate;       /* date created (unixtime)       4  66 */
    unsigned int grp_entdate;       /* last entry date (unixtime)    4  70 */
    unsigned short grp_life;        /* newsgroup hold time (days)    2  72 */
    unsigned short grp_itmlife;     /* item retention time (days)    2  74 */
    unsigned short grp_srvcache;    /* NNTP client cache time        2  76 */
    unsigned int grp_flags;         /* newsgroup flags               4  80 */
    char grp_srvproto;              /* NNTP transport protocol       1  81 */
    char grp_srvnode[132];          /* NNTP server node            132 213 */
    char grp_topic[125];            /* group topic line            125 338 */
    char grp_notice[125];           /* group notice line           125 463 */
    unsigned int grp_firstnum;	    /* lowest article number         4 467 */
    char grp_filler[NEWS_GRPFIL_RSZ-417-GRPNAMELEN_F]; /* filler     ? 512 */
    } GRPF, *GRPF_PTR;

/*
 * grp_flags - bit definitions
 */

#define NEWS_M_LOCAL            1       /* non-network newsgroup */
#define NEWS_M_WRITE_ACCESS     2       /* user post access */
#define NEWS_M_MOD_ACCESS       4       /* user moderator access enabled */
#define NEWS_M_MOD_USER         8       /* user moderator */
#define NEWS_M_NOWRITE_SET      16      /* newsgroup is set nowrite */
#define NEWS_M_RESTRICT_SET     32      /* newsgroup is set restricted */
#define NEWS_M_ACCESS_CHECKED   64      /* access file checked ? */
#define NEWS_M_NNTPSRV          128     /* NNTP server defined */
#define NEWS_M_NNTPCACHE        256     /* NNTP server cache enabled */
#define NEWS_M_MAILMODERATE     512     /* newsgroup is moderated */
#define NEWS_M_OLDGROUP        1024     /* newsgroup is moderated */
#define NEWS_M_NOAPPROVAL      2048	/* moderated newsgroup - no approval */
#define NEWS_M_MAILLIST	       4096	/* this is a mailing list */
#define NEWS_M_MAILGROUP       8192	/* this is a vms mail folder */
#define NEWS_M_NEWSKIP	      16384
#define NEWS_M_IGNEXP	      32768	/* ignore expiry headers */
#define NEWS_M_NOSTORE	      65536	/* dont store item texts locally */
#define NEWS_M_UNSEENSTACK   131072
#define NEWS_M_UNREADITEMS   262144
#define NEWS_M_NONDEFDISPLAY 524288
#define NEWS_M_ORDERBYSUBJECT 1048576
#define NEWS_M_READTHISSESSION 2097152
#define NEWS_M_NNTPSRVBYNUM    4194304
#define NEWS_M_ITMIDSSET       8388608

#define NEWS_V_LOCAL            0
#define NEWS_V_WRITE_ACCESS     1
#define NEWS_V_MOD_ACCESS       2
#define NEWS_V_MOD_USER         3
#define NEWS_V_NOWRITE_SET      4
#define NEWS_V_RESTRICT_SET     5
#define NEWS_V_ACCESS_CHECKED   6
#define NEWS_V_NNTPSRV          7
#define NEWS_V_NNTPCACHE        8
#define NEWS_V_MAILMODERATE     9
#define NEWS_V_OLDGROUP        10
#define NEWS_V_NOAPPROVAL      11
#define NEWS_V_MAILLIST	       12
#define NEWS_V_MAILGROUP       13
#define NEWS_V_NEWSKIP	       14
#define NEWS_V_IGNEXP		15
#define NEWS_V_NOSTORE		16
#define NEWS_V_UNSEENSTACK	17
#define NEWS_V_UNREADITEMS	18
#define NEWS_V_NONDEFDISPLAY    19
#define NEWS_V_ORDERBYSUBJECT   20
#define NEWS_V_READTHISSESSION  21
#define NEWS_V_NNTPSRVBYNUM     22
#define NEWS_V_ITMIDSSET        23

#ifdef __DECC
#pragma member_alignment
#endif
struct itms {
        struct itms *itmsnext;
        int itmdate,
            itmsize;
        int itmvalid;
        char itmid[IDLEN];
        char itmtitle[SUBJLEN];
        char itmfrom[FROMLEN];
        };

#ifdef __DECC
#pragma member_alignment
#endif
struct grps {
        struct grps *grpsnext;
        struct itms *ids,
                    *idr;
        unsigned int itmgrp;
        int nproto;
        int grptime;
        char grpname[GRPNAMELEN];
        char grpnode[132];
        };

#ifdef __DECC
#pragma member_alignment
#endif
typedef struct its {
    int ngrp;
    int fitm, litm;
    } NOTE_RANGE;

#ifdef __DECC
#pragma member_alignment
#endif
typedef struct dptt {
  int do_header,
      usr_line,
      gets_size,
      text_lines,
      text_cline,
      text_displayed,
      disp_size,
      shdid,
      sdid,
      sdid_paste,
      sdid_home,
      sdid_line,
      sdid_baseline,
      sdid_dsize,
      sdid_current,
      sheader_line,
      target_paste,
      fdepth,
      str_found,
      str_searching,
      str_case_sensitive,
      str_length,
      str_line,
      str_col,
      display_code;
  char header_line[500],
       str_target[512];
  struct stat dispf_stat;
  } DPT, *DPTR;

/* From NEWSFILES.C -	Tim Cook, 12 Feb 1990 */
#ifdef __DECC
#pragma nomember_alignment
#endif
struct rms_file {
  struct FAB f;
  struct RAB r;
  struct XABPRO p;
  };

/* From NEWSRC.C -	Tim Cook, 12 Feb 1990 */
#ifdef __DECC
#pragma member_alignment
#endif
struct marks {
    int m_type;
    char *m_tag;
    unsigned int *m_grps;
    unsigned int *m_itms;
    int m_size;
    int m_malloc;
    char *k_grp_name;
    char *k_itm_title;
    char *k_itm_from;
    char *k_itm_header;
    int k_test_from;
    int k_test_header;
    int k_test;
    struct marks *m_next;
    };

#define NHEADERS 22     /* number of different header lines recognized by ANU */
#define OHEADERS 18     /* first OHEADERS header lines from the list
                           of known header types are stored and forwarded
                           mostly unmodified, the remaining ones
                           require special handling */
#define PATH          0
#define NEWSGROUPS    1
#define SUBJECT       2
#define MESSAGE_ID    3
#define FROM          4
#define DATE          5
#define REPLY_TO      6
#define SENDER        7
#define FOLLOWUP_TO   8
#define EXPIRES       9
#define REFERENCES    10
#define CONTROL       11
#define DISTRIBUTION  12
#define ORGANIZATION  13
#define KEYWORDS      14
#define SUMMARY       15
#define APPROVED      16
#define SUPERSEDES    17
#define LINES         18
#define XREF          19
#define RELAY_VERSION 20
#define X_PGP_SIG     21

#ifndef NNTP_CLIENT
#define NNTP_CLIENT	1
#endif

#ifndef NNTP_CLIENT_ONLY
#define NNTP_CLIENT_ONLY	0
#endif

#if NNTP_CLIENT_ONLY
#define NNTP_CLIENT	1
#endif

#define OUTER_LOOP	0
#define I_DISPLAY_LOOP	1
#define T_DISPLAY_LOOP	2

#define MAXTARGETS	10		/* maximum nuymber of ANDed search target strings */
#define MAXIDLEN	1023		/* maximum size of a message-id string */
#define SEARCH_FORWARD	1		/* search-direction forward (default) */
#define SEARCH_BACKWARD 2		/* search-direction backward */

#ifdef __DECC
#pragma nomember_alignment   /* no member alignment - this is a VMS structure */
#endif
struct	dsc$descriptor_const_s
{
	unsigned short	dsc$w_length;	/* length of data item in bytes,
					     or if dsc$b_dtype is DSC$K_DTYPE_V, bits,
					     or if dsc$b_dtype is DSC$K_DTYPE_P, digits (4 bits each) */
	unsigned char	dsc$b_dtype;	/* data type code */
	unsigned char	dsc$b_class;	/* descriptor class code = DSC$K_CLASS_S */
	const char	*dsc$a_pointer;	/* address of first byte of data storage */
};

#define $DESCRIPTOR_CONST(name,string) \
  struct dsc$descriptor_const_s name = { sizeof(string)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S, string }

#ifdef __DECC
#pragma nomember_alignment   /* no member alignment - this is a VMS structure */
#endif
typedef struct IOSB_TYPE {		/* I/O status block type */
		 unsigned short	status;
		 unsigned short	count;
		 unsigned short	terminator;
		 unsigned short	term_count;
		 } IOSB_DEF;

#ifdef __DECC
#pragma member_alignment
#endif
typedef struct dir_class {		/* class structure */
    char *c_name;
    unsigned int *c_nums;
    int c_size;
    int c_malloc;
    struct dir_class *c_next;
    } DIR_CLASS, *DIR_CLASS_PTR;

#ifdef __DECC
#pragma member_alignment
#endif
typedef struct als {
  char *ngname;
  char *alias_name;
  struct als *a_next;
  } ALIAS, *ALIAS_PTR;

#ifdef __DECC
#pragma member_alignment
#endif
typedef struct sys_filter {
    char *sys_filtnam;
    struct sys_filter *sys_fnext;
    } SYS_FILTER_T, NAME_LIST;

#ifdef __DECC
#pragma member_alignment
#endif
typedef struct sys_entry {
    char *sys_nodename;
    SYS_FILTER_T *sys_no;
    SYS_FILTER_T *sys_f;
    SYS_FILTER_T *sys_d;
    char *sys_type;
    char *sys_file;
    int sys_batch_size;
    int sys_estimated_article_count ;
    int sys_article_count;
    int sys_article_bytes;
    int sys_id_count;		/* IHAVE ID's */
    FILE *sys_fp;
    struct sys_entry *sys_enext;
    struct stat sys_statb;
    int sys_index_file;
    struct FAB  sys_idxfab;
    struct RAB  sys_idxrab;
    struct XABKEY  sys_idxkey_1;
    struct XABPRO  sys_idxpro_1;
    struct {
       time_t t;
       char idx_id[MAXIDLEN+1];
       }  sys_newsidx;
    } SYS_ENTRY_T;

#ifdef __DECC
#pragma member_alignment
#endif
typedef struct dist_entry {
    char *from_name;
    SYS_FILTER_T *to_names;
    struct dist_entry *next;
    } DIST_ENTRY_T;
				/* Add definition of TCP modules */
#ifdef UCX
#define UCX	1
#endif

#ifdef CMU
#define CMU	1
#endif

#ifdef TWG
#define TWG	1
#endif

#ifdef MULTINET
#define MULTINET 1
#endif

#ifdef MULTINET
#define __TYPES_OFF_T
#define __TYPES_DEV_T
#endif

/*----- NEWSADD/NEWSCONTROL Control: message parse routines exit status values */

#define CTLOK			1
#define CTLOKNOCHG		3

#define NOSCRATCHFILE	 	2
#define NORETURNADDRESS	 	4
#define NEWGROUPERROR	 	6
#define NONEWSGROUPFIELD 	8
#define NONAPPROVEDCONTROL	10
#define LOCALNEWSGROUP		12
#define NORMNEWSGROUP		14
#define NOACCESSINFILE		16
#define NOSENDERADDRESS		18
#define BADFORMAT		20
#define NOTTOME			22
#define NOREMOTESYS		24
#define UNKCTL			26

/*----- NEWSADD/NEWSCONTROL Control: switch flag definitions */
/* flags to enable immediate execution of control messages of the type: */
#define EXECUTE_CONTROL_CHECKGROUPS	1
#define EXECUTE_CONTROL_NEWGROUP	2
#define EXECUTE_CONTROL_RMGROUP		4

/* the following two flags are only modifiers to EXECUTE_CONTROL_RMGROUP    *
 * and setting them does not activate execution of rmgroup control messages */
#define EXECUTE_CONTROL_RMGROUP_DELETE	8
#define EXECUTE_CONTROL_RMGROUP_LOCAL	16

/*----- NEWSADD Parser output codes */

#define SCAN1OK			1

#define NOPATH		        2
#define NOGROUPS		4
#define NOSUBJ			8
#define NOID			16
#define NOFROM			32
#define NODATE			64
#define BADID			128

#define	NOFILENAME		 2
#define NOREADACCESS		 4
#define NOSCRFILEACCESS		 6
#define BADHD_STARTSPACE	 8
#define BADHD_NOCOLON		10
#define BADHD_NOTAKEYWORD	12
#define BADHD_REPEATEDKEYWORD	14
#define EMPTYINFILE		16
#define NOLOCALNEWSGROUPS	18
#define JUNKED			20
#define KNOWNID			22
#define NOTLOCALLYACCEPTED	24

/*--------- NEWSPROFILE flag settings */

#define PROFILE_AUTO       	1
#define PROFILE_CLASS       	2
#define PROFILE_EDIT        	4
#define PROFILE_PERSNAME    	8
#define PROFILE_PRINT       	16
#define PROFILE_DIRECTORY   	32
#define PROFILE_NEWREGISTER 	64
#define PROFILE_SCANSIZE	128
#define PROFILE_SIGNATURE	256
#define PROFILE_LOCSIGNATURE	512
#define PROFILE_ORGANIZATION	1024
#define PROFILE_KEYDEFS		2048
#define PROFILE_SEARCH		4096
#define PROFILE_DISPLAY		8192
#define PROFILE_LINEEDIT	16384
#define PROFILE_BROADCAST	32768
#define PROFILE_UNSEENSTACK	65536		/* bit 16 */
#define PROFILE_UNREADITEMS	131072
#define PROFILE_RCREG		262144
#define PROFILE_SHOWDIRS	524288
#define PROFILE_FASTLOAD	1048576
#define PROFILE_REPLYTO		2097152
#define PROFILE_VIEW            4194304
#define PROFILE_DOTNEWSRC       8388608

#define PROFILE_UNSEEN      1
#define PROFILE_DIR         2

#define SHOW_CLASSES		1
#define SHOW_ALIASES		2
#define DIR_ITEMS		3
#define DIR_GROUPS		4
#define SHOW_SYS		5
#define SHOW_ITEM		6
#define SHOW_FILE		7
#define SHOW_NOTE		8
#define SHOW_MAILPROFILE	9
#define SHOW_PROFILE		10
#define SHOW_MESSAGES		11
#define SHOW_NEWSGROUP		12
#define SHOW_SUPERVISOR		13
#define SHOW_MODERATOR		14
#define SHOW_MEMBER		15
#define SHOW_ENTRY		16
#define SHOW_MARK		17

#define DECNET		0
#define CMUTCP		1
#define WINTCP		2
#define MULTINETTCP	3
#define UCXTCP		4
#define EXOSTCP		5
#define TCPWARETCP	6

#ifdef __DECC
#pragma member_alignment restore
#endif

/* condition codes from the module NEWSMSG.MSG */
#include "newsmsg.h"

#endif	/* _NEWSDEFINE_H */
