#module NEWSSITE "V5.6"

/*
**++
**  FACILITY:
**
**      NEWSSITE
**
**  ABSTRACT:
**
**      This module contains two areas of functionality: firstly startup
**      code which checks for the existence of various logical names before
**      linking to the local news database, and secondly the filters which
**      implement the local and remote news item acceptance conditions.
**
**  AUTHOR:
**
**      Geoff Huston
**
**  COPYRIGHT:
**
**      Copyright © 1988
**
**  MODIFICATION HISTORY:
**
**      V5.5    7-Oct-1988      GIH
**        - Added definitions for VMS V5.0 mail file for correct extract of
**          personal mail name
**        - Added logical name NEWS_NONETPOST to prevent holders of such
**          an identifier posting into non /local newsgroups
**        - Added logical name NEWS_NETPOST to explicitly allow holders of such
**          an identifier (and no others) posting into non /local newsgroups
**      V5.6    11-Nov-1988     GIH
**        - Change identifier routines to more efficient algorithms
**--
**/

#include "newsinclude.h"
#include "newsdefine.h"
#include "newsextern.h"
#include "v5maildef.h"

#include lnmdef
#include psldef
#include syidef

#define MAIL_DAT_NAME     "VMSMAIL"
#define MAIL_DAT_DEFAULT  "SYS$SYSTEM:.DAT"



int vms_major = 0,
    vms_minor = 0,
    held_ids[100];

static int mgr_priv = -1,
           post_priv = -1,
           post_id,
           nopost_id;

static char mgrid[256],
            nopostid[256],
            postid[256],
            version[4];

static struct itv {
    short bl;
    short code;
    int *ba;
    short *rl;
    } ver_item[]= {{4,SYI$_VERSION,&version,0}, {0,0,0,0}};

/*
 *  site_get_env
 *
 * read site specific logical name values  - note this code uses the C RTL
 * call getenv to perform the logical name translation where possible, for
 * simplicity. Where specific mode logical names are translated sys$trnlnm is
 * used
 */

site_get_env()
{
    char *p,
         *gotenv,
         exec_mode = MODE,
         prefix[] = "SYS$SCRATCH",
         translate_value[256];
    unsigned int trnlist[4];
    unsigned short len;
    struct crelnm_record {
        short bl;
        short ic;
        char *ba;
        short *rl;
        int enditm;
        } scritm;

    sys$getsyiw(0,0,0,ver_item,0,0,0);
    sscanf(version,"V%d.%d",&vms_major,&vms_minor);
    strcpy(Post_file,"SYS$SCRATCH:POST_NEWS.TMP");
    strcat(Mail_file,"SYS$SCRATCH:MAIL_NEWS.TMP");
    strcpy(Extract_file,"SYS$LOGIN:NEWS.LIS");

    if (!getenv(prefix)) {
        strcpy(prefix,"SYS$LOGIN");
        if (!(gotenv = getenv(prefix))) {
            printf("SYS$LOGIN not defined (?) - exiting NEWS\n");
            exit(1);
            }
        scritm.bl = strlen(gotenv);
        scritm.ic = LNM$_STRING;
        scritm.ba = gotenv;
        scritm.rl = &len;
        scritm.enditm = 0;
        c$cks(sys$crelnm(0,c$dsc("LNM$JOB"),c$dsc("SYS$SCRATCH"),0,&scritm));
        }
    if (gotenv = getenv("NEWSRC")) strcpy(news_register,gotenv);
    else if (gotenv = getenv("NEWS_REGISTER")) strcpy(news_register,gotenv);
    else strcpy(news_register,User_file);
    strcpy(news_register_d,news_register);
    strcat(news_register_d,";-1");

    if (!(gotenv = getenv("NEWS_EDIT"))) *Editor = '\0';
    else s_to_lower(strcpy(Editor,gotenv));
    if (!strcmp(Editor,"callable_tpu")) *Editor = '\0';
    else if (!strcmp(Editor,"callable_edt")) strcpy(Editor,"edt");

    if (!(gotenv = getenv("NEWS_VIEW"))) *Viewer = '\0';
    else s_to_lower(strcpy(Viewer,gotenv));
    if (!strcmp(Viewer,"callable_tpu")) *Viewer = '\0';
    else if (!strcmp(Viewer,"callable_edt")) strcpy(Viewer,"edt");

    if (!(gotenv = getenv("NEWS_ORGANISATION"))) {
        if (!(gotenv = getenv("NEWS_ORGANIZATION"))) strcpy(Organisation_name,"VAX/VMS NEWS V6.0");
        else strcpy(Organisation_name,gotenv);
        }
    else strcpy(Organisation_name,gotenv);

    /*    Set up item list for exec mode logical names */

    trnlist[0] = (LNM$_STRING << 16) + LNM$C_NAMLENGTH;
    trnlist[1] = translate_value;
    trnlist[2] = &len;
    trnlist[3] = 0;


    if (!(sys$trnlnm(0,c$dsc(LOG_TABLE),c$dsc("NEWS_ROOT"),&exec_mode,&trnlist) & 1)) {
        printf("NEWS_ROOT not properly defined - exiting\n");
        exit(1);
        }

    if (!(sys$trnlnm(0,c$dsc(LOG_TABLE),c$dsc("NEWS_DEVICE"),&exec_mode,&trnlist) & 1)) {
        printf("NEWS_DEVICE not properly defined - exiting\n");
        exit(1);
        }

    if (!(sys$trnlnm(0,c$dsc(LOG_TABLE),c$dsc("NEWS_ADDRESS"),&exec_mode,&trnlist) & 1)) {
        printf("NEWS_ADDRESS not defined - exiting\n");
        exit(1);
        }
    else {
        translate_value[len] = '\0';
        s_to_lower(strcpy(Node_address,translate_value));
        }

    if (!(sys$trnlnm(0,c$dsc(LOG_TABLE),c$dsc("NEWS_NODE"),&exec_mode,&trnlist) & 1)) {
        printf("NEWS_NODE not defined - exiting\n");
        exit(1);
        }
    else {
        translate_value[len] = '\0';
        s_to_lower(strcpy(usr_nodename,translate_value));
        }

    if (!(sys$trnlnm(0,c$dsc(LOG_TABLE),c$dsc("NEWS_MANAGER"),&exec_mode,&trnlist) & 1)) {
        printf("NEWS_MANAGER not defined - exiting\n");
        exit(1);
        }
    else {
        translate_value[len] = '\0';
        strcpy(newsmgr_dir,translate_value);
        }

    if (!(sys$trnlnm(0,c$dsc(LOG_TABLE),c$dsc("NEWS_TIMEZONE"),&exec_mode,&trnlist) & 1)) {
        strcpy(news_timezone,"GMT");
        }
    else {
        char *cp;

        translate_value[len] = '\0';
        strcpy(news_timezone,translate_value);
        cp = news_timezone;
        while (*cp) { *cp = toupper(*cp); ++cp; }
        }

    trnlist[1] = mgrid;
    if (sys$trnlnm(0,c$dsc(LOG_TABLE),c$dsc("NEWS_MGR_ID"),&exec_mode,&trnlist) & 1) mgrid[len] = '\0';
    else {
        printf("NEWS_MGR_ID not defined - exiting\n");
        exit(1);
        }

    trnlist[1] = nopostid;
    nopost_id = 0;
    if (sys$trnlnm(0,c$dsc(LOG_TABLE),c$dsc("NEWS_NONETPOST"),&exec_mode,
            &trnlist) & 1) {
        nopostid[len] = '\0';
        if (!(sys$asctoid(c$dsc(nopostid),&nopost_id,0) & 1)) nopost_id = 0;
        }
    else *nopostid = '\0';

    trnlist[1] = postid;
    post_id = 0;
    if (sys$trnlnm(0,c$dsc(LOG_TABLE),c$dsc("NEWS_NETPOST"),&exec_mode,
            &trnlist) & 1) {
        postid[len] = '\0';
        if (!(sys$asctoid(c$dsc(postid),&post_id,0) & 1)) post_id = 0;
        }
    else *postid = '\0';

    strcpy(usr_username,getenv("USER"));

    *usr_persname = '\0';
    mail_flags = 0;
    *mail_queue = '\0';
    *mail_form = '\0';
    *mail_editor = '\0';
    if (!get_v5mailprofile()) get_v4mailprofile();
    if (gotenv = getenv("NEWS_PERSONALNAME")) strcpy(usr_username,gotenv);
    s_to_lower(usr_username);
    sysprv();
    sys_readsys();
    nosysprv();
    init_transform();
}

/*
 *  no_priv
 *
 *  Return 1 if the user is not an authorised news manager - check the
 *  list of held identifiers
 */

no_priv()
{
    int mgr_id,
        id,
        contxt = 0,
        lstatus,
        idindx;
    unsigned int holder[2];

    if (mgr_priv != -1) return(mgr_priv);
    if (!(sys$asctoid(c$dsc(mgrid),&mgr_id,0) & 1)) return(mgr_priv = 1);
    holder[0] = (getgid() << 16) + getuid();
    holder[1] = 0;
    idindx = 0;
    mgr_priv = 1;
    while ((lstatus = sys$find_held(holder,&id,0,&contxt)) & 1) {
        held_ids[idindx++] = id;
        if (id == mgr_id) mgr_priv = 0;
        }
    held_ids[idindx] = 0;
    sys$finish_rdb(&contxt);
    return(mgr_priv);
}

idmatch(identifier)
    char *identifier;
{
    int try_id,
        i = 0;

    s_to_upper(identifier);
    if (!(sys$asctoid(c$dsc(identifier),&try_id,0) & 1)) return(0);
    while (held_ids[i]) {
        if (held_ids[i] == try_id) return(1);
        ++i;
        }
    return(0);
}

/*
 *  nout_priv
 *
 *  Return 1 if the user is not authorised to post to net newsgroups
 */

nout_priv()
{
    int i = 0;

    if (post_priv != -1) return(post_priv);
    if (no_priv) {
        while (held_ids[i]) {
            if (held_ids[i] == post_id) return(post_priv = 0);
            if (held_ids[i] = nopost_id) return(post_priv = 1);
            ++i;
            }
        if (post_id) post_priv = 1;
        else post_priv = 0;
        }
    else return(post_priv = 0);
}

/*
 *  NEWS.SYS and NEWS.DISTRIBUTION file handling routines
 *
 *  The following structures hold memory maps of these files
 */

static struct sys_filter {
    char *sys_filtnam;
    struct sys_filter *sys_fnext;
    } *local_filter = 0;

static struct sys_entry {
    char *sys_nodename;
    struct sys_filter *sys_f;
    char *sys_type;
    char *sys_file;
    struct sys_entry *sys_enext;
    } *sysfile = 0;

static struct net_dist {
    char *from_name;
    struct sys_filter *to_names;
    struct net_dist *next;
    } *distfile = 0;

static int net_read = 0;

/*
 *  scan
 *
 *  Read a news.sys line of the form "node:filter:format:file^xmitformat"
 *  and store in local structure
 */

static scan(s)
    char *s;
{
    struct sys_entry *tmp, *t1 = sysfile;
    struct sys_filter *fmp, *f1;
    char node[36],
         filters[512],
         type[30],
         file[256],
         *cp1,
         *cp2,
         filtname[50];

    *node = *filters = *type = *file = '\0';

    sscanf(s,"%[^:]:%[^:]:%[^:]:%s",node,filters,type,file);
    if (*node) {
        tmp = malloc(sizeof *tmp);
        strcpy((tmp->sys_nodename = malloc(strlen(node) + 1)),s_to_lower(node));
        tmp->sys_f = 0;
        cp1 = file;
        if (cp2 = strchr(file,'^')) {
            *cp2++ = '\0';
            if (tolower(*type) != 'n') strcpy(type,cp2);
            }
        if (!*type) strcpy(type,"b");
        strcpy((tmp->sys_type = malloc(strlen(type) + 1)),s_to_lower(type));
        while (cp1 = strchr(cp1,'/')) *cp1++ = ':';
        strcpy((tmp->sys_file = malloc(strlen(file) + 1)),s_to_lower(file));
        cp1 = filters;
        do {
            if (cp2 = strchr(cp1,',')) *cp2++ = '\0';
            util_cvrt(filtname,cp1);
            fmp = malloc(sizeof *fmp);
            strcpy((fmp->sys_filtnam = malloc(strlen(filtname) + 1)),filtname);
            fmp->sys_fnext = 0;
            if (!tmp->sys_f) tmp->sys_f = f1 = fmp;
            else {
                f1->sys_fnext = fmp;
                f1 = fmp;
                }
            cp1 = cp2;
            } while (cp1);
        tmp->sys_enext = 0;
        if (!sysfile) sysfile = tmp;
        else {
            while (t1->sys_enext) t1 = t1->sys_enext;
            t1->sys_enext = tmp;
            }
        if (!strcmp(usr_nodename,node)) local_filter = tmp->sys_f;
        }
}

/*
 *  sys_readsys
 *
 *  Read the news.sys file, and pass all reconstructed lines to scan
 */

sys_readsys()
{
    FILE *fp;
    char sysname[256],
         inline[512],
         cur_line[1024];
    int next_cont = 0;

    strcpy(sysname,newsmgr_dir);
    strcat(sysname,"NEWS.SYS");
    sysprv();
    if (!(fp = fopen(sysname,"r"))) {
        printf("\tNO NEWS.SYS file defined\n");
        nosysprv();
        return(0);
        }
    nosysprv();
    *cur_line = '\0';
    while (fgets(inline,510,fp)) {
        if (*inline == '#') continue;
        if (inline[strlen(inline) - 1] == '\n') inline[strlen(inline) - 1] = '\0';
        strip(inline,strlen(inline));
        strcat(cur_line,inline);
        if (inline[strlen(inline) - 1] == '\\') cur_line[strlen(cur_line) - 1] = '\0';
        else {
            scan(cur_line);
            *cur_line = '\0';
            }
        }
    fclose(fp);
}

/*
 *  net_scan
 *
 *  Read a news.distribution line of the form   node node,node,...
 *  and store in local structure
 */

static net_scan(s)
    char *s;
{
    char *cp1,
         *cp2;
    struct sys_filter *fmp, *f1;
    struct net_dist *tmp, *t1 = distfile;

    if (!(cp1 = strchr(s,' '))) return;
    *cp1++ = '\0';
    while (*cp1 == ' ') cp1++;
    tmp = malloc(sizeof *tmp);
    strcpy((tmp->from_name = malloc(strlen(s) + 1)),s_to_lower(s));
    tmp->to_names = 0;
    do {
        if (cp2 = strchr(cp1,',')) *cp2++ = '\0';
        fmp = malloc(sizeof *fmp);
        strcpy((fmp->sys_filtnam = malloc(strlen(cp1) + 1)),s_to_lower(cp1));
        fmp->sys_fnext = 0;
        if (!tmp->to_names) tmp->to_names = f1 = fmp;
        else {
            f1->sys_fnext = fmp;
            f1 = fmp;
            }
        cp1 = cp2;
        } while (cp1);
    tmp->next = 0;
    if (!distfile) distfile = tmp;
    else {
        while (t1->next) t1 = t1->next;
        t1->next = tmp;
        }
}

/*
 *  net_readsys
 *
 *  Read the news.distribution file, and pass all reconstructed lines to
 *  net_scan.
 */

net_readsys()
{
    FILE *fp;
    char sysname[256],
         inline[512],
         cur_line[1024];
    int next_cont = 0;

    ++net_read;
    strcpy(sysname,newsmgr_dir);
    strcat(sysname,"NEWS.DISTRIBUTION");
    sysprv();
    if (!(fp = fopen(sysname,"r"))) {
        nosysprv();
        return(0);
        }
    nosysprv();
    *cur_line = '\0';
    while (fgets(inline,510,fp)) {
        if (*inline == '#') continue;
        if (inline[strlen(inline) - 1] == '\n') inline[strlen(inline) - 1] = '\0';
        strip(inline,strlen(inline));
        strcat(cur_line,inline);
        if (inline[strlen(inline) - 1] == '\\') cur_line[strlen(cur_line) - 1] = '\0';
        else {
            net_scan(cur_line);
            *cur_line = '\0';
            }
        }
    fclose(fp);
}

/*
 *  test_accept
 *
 *  Test if the newsgroup groups and distribution dist is accepted
 *  using the filter f
 */

static test_accept(groups,dist,f)
    char *groups,
         *dist;
    struct sys_filter *f;
{
    char *cp1,
         *cp2,
         locname[132],
         wname[132],
         line[512];
    int accept = 0;
    struct sys_filter *f_sav = f;

    strcpy(line,groups);
    cp1 = line;

    if (!f) return(1);
    do {
        if (cp2 = strchr(cp1,',')) *cp2++ = '\0';
        util_cvrt(locname,cp1);
        f = f_sav;
        while (f) {
            if (*f->sys_filtnam == '!') {
                if (!strcmp(locname,f->sys_filtnam + 1)) return(0);
                else {
                    strcpy(wname,f->sys_filtnam + 1);
                    strcat(wname,".*");
                    if (wild_match(locname,wname)) return(0);
                    }
                }
            else {
                if (!strcmp(locname,f->sys_filtnam)) accept = 1;
                else {
                    strcpy(wname,f->sys_filtnam);
                    strcat(wname,".*");
                    if (wild_match(locname,wname)) accept = 1;
                    }
                }
            f = f->sys_fnext;
            }
        cp1 = cp2;
        } while ((!accept) && (cp1));

    if (!accept) return(0);
    if ((!dist) || (!*dist)) return(accept);

    accept = 0;
    strcpy(line,dist);
    if (!strcmp(line,"all")) return(1);
    cp1 = line;
    do {
        if (cp2 = strchr(cp1,',')) *cp2++ = '\0';
        util_cvrt(locname,cp1);
        f = f_sav;
        while ((!accept) && (f)) {
            if (*f->sys_filtnam == '!') {
                if (!strcmp(locname,f->sys_filtnam + 1)) return(0);
                else {
                    strcpy(wname,f->sys_filtnam + 1);
                    strcat(wname,".*");
                    if (wild_match(locname,wname)) return(0);
                    }
                }
            else {
                if (!strcmp(locname,f->sys_filtnam)) accept = 1;
                else {
                    strcpy(wname,f->sys_filtnam);
                    strcat(wname,".*");
                    if (wild_match(locname,wname)) accept = 1;
                    }
                }
            f = f->sys_fnext;
            }
        cp1 = cp2;
        } while ((!accept) && (cp1));
    return(accept);
}

/*
 *  sys_local_accept
 *
 *  Determine is newsgroups dist, distribution dist is accepted by the
 *  host node's filter
 */

sys_local_accept(groups,dist)
    char *groups,
         *dist;
{
    return(test_accept(groups,dist,local_filter));
}

/*
 *  sys_accept_group
 *
 *  Determine if the newsgroup group is accepted by the host node's filter
 */

sys_accept_group(group)
    char *group;
{
    int accept = 0;
    char wname[132];
    struct sys_filter *f = local_filter;

    if (!f) return(1);
    while (f) {
        if (*f->sys_filtnam == '!') {
            if (!strcmp(group,f->sys_filtnam + 1)) return(0);
            else {
                strcpy(wname,f->sys_filtnam + 1);
                strcat(wname,".*");
                if (wild_match(group,wname)) return(0);
                }
            }
        else {
            if (!strcmp(group,f->sys_filtnam)) accept = 1;
            else {
                strcpy(wname,f->sys_filtnam);
                strcat(wname,".*");
                if (wild_match(group,wname)) accept = 1;
                }
            }
        f = f->sys_fnext;
        }
    return(accept);
}

/*
 *  sys_looping
 *
 *  Determine if the incoming net item has been seen on this node
 *  already - check the path value
 */

sys_looping(path)
    char *path;
{
    char lname[64];

    sprintf(lname,"*!%s!*",usr_nodename);
    if (wild_match(path,lname)) return(0);
    *(lname+1) = ' ';
    if (wild_match(path,lname)) return(0);
    return(1);
}

/*
 *  sys_remote_send
 *
 *  Determine if a news item should be sent to an adjacent net site
 */

sys_remote_send(path,groups,dist,file,id,net)
    char *path,
         *groups,
         *dist,
         *file,
         *id;
    int net;
{
    int b_size = 0;
    char tmp_name[256],
         lname[64],
         from_n[32],
         rbuf[512],
         *xbuf,
         *b;
    struct sys_entry *s = sysfile;
    struct net_dist *f = distfile;
    struct sys_filter *netdist;
    struct stat app_file,
                inp_file;
    FILE *fpo,
         *fpi;

    *from_n = *tmp_name = '\0';
    if (stat(file,&inp_file)) return;
    if (net) {
        if (!net_read) net_readsys();
        if (!distfile) return;
        else f = distfile;
        if (b = strchr(path,'!')) {
            *b = '\0';
            if (*path == ' ') strcpy(from_n,path+1);
            else strcpy(from_n,path);
            *b = '!';
            }
        else return;
        while ((f) && (strcmp(f->from_name,from_n)))
            f = f->next;
        if (!f) return;
        if (!f->to_names) return;
        }

    if (!s) return;
    do {
        if (net) {
            netdist = f->to_names;
            while ((netdist) && (strcmp(netdist->sys_filtnam,s->sys_nodename)))
                netdist = netdist->sys_fnext;
            if (!netdist) continue;
            }
        sprintf(lname,"*!%s!*",s->sys_nodename);
        if (wild_match(path,lname)) continue;
        *(lname+1) = ' ';
        if (wild_match(path,lname)) continue;
        if (test_accept(groups,dist,s->sys_f)) {
            int n_char = 0;

            if (*s->sys_type == 'n') {
                sysprv();
                fpo = fopen(s->sys_file,"a","rfm=var","rat=cr");
                nosysprv();
                fprintf(fpo,"%s\n",id);
                fclose(fpo);
                }
            else {
                if (!*tmp_name) {
                    sysprv();
                    if (!(fpi = fopen(file,"r"))) {
                        nosysprv();
                        continue;
                        }
                    sprintf(tmp_name,"%sSEND_%X.TMP",newsmgr_dir,time(0));
                    if (!(fpo = fopen(tmp_name,"w"))) {
                        fclose(fpi);
                        *tmp_name = '\0';
                        nosysprv();
                        continue;
                    }
                    b_size = 0;
                    while (fgets(rbuf,512,fpi)) {
                        b_size += strlen(rbuf);
                        fputs(rbuf,fpo);
                        }
                    fclose(fpi);
                    fclose(fpo);
                    }
                else sysprv();
                if (!(fpi = fopen(tmp_name,"r"))) {
                    nosysprv();
                    continue;
                    }
                nosysprv();

                n_char = (*(s->sys_type + 1) == 'n');
                if (*s->sys_type != 'b') {
                    sysprv();
                    fpo = fopen(s->sys_file,"w","rfm=var","rat=cr");
                    nosysprv();
                    }
                else {
                    sysprv();
                    if (!stat(s->sys_file,&app_file)) {
                        if ((app_file.st_size + inp_file.st_size) > NEWS_BATCH_SIZE)
                            fpo = fopen(s->sys_file,"w","rfm=var","rat=cr");
                        else fpo = fopen(s->sys_file,"a");
                        }
                    else fpo = fopen(s->sys_file,"w","rfm=var","rat=cr");
                    nosysprv();
                    if (!fpo) {
                        fclose(fpi);
                        continue;
                        }
                    if (n_char) fprintf(fpo,"N");
                    fprintf(fpo,"#! rnews %d\n",b_size);
                    }
                xbuf = rbuf;
                if (n_char) *xbuf++ = 'N';
                while (fgets(xbuf,510,fpi)) fputs(rbuf,fpo);
                fclose(fpo);
                fclose(fpi);
                }
            }
        } while (s = s->sys_enext);
    if (*tmp_name) {
        sysprv();
        while (!delete(tmp_name));
        nosysprv();
        }
}

/*
 *  first_time
 *
 *  First time code - print out little license message
 */

first_time()
{
    char sysname[132],
         inpline[132];
    int line;
    FILE *fpw;

    strcpy(sysname,newsmgr_dir);
    strcat(sysname,"000README.NEWS_LICENSE");
    sysprv();
    if (!(fpw = fopen(sysname,"w"))) {
        printf("Cannot write file %s\n",sysname);
        sys$exit(1);
    }
    nosysprv();
    fputs("+-----------------------------------------------------------------------------+\n",fpw);
    fputs("|  NEWS, Copyright (c) Geoff Huston, 1987,1988                                |\n",fpw);
    fputs("|                                                                             |\n",fpw);
    fputs("| License is granted to run this software on one condition:                   |\n",fpw);
    fputs("|                                                                             |\n",fpw);
    fputs("|  The Licensee registers with the copyright holder the details of the        |\n",fpw);
    fputs("|  systems which are running NEWS. In doing so I will also endeavour to notify|\n",fpw);
    fputs("|  you of new versions and bug fixes. It is a condition of the license that   |\n",fpw);
    fputs("|  the following letter is mailed to:                                         |\n",fpw);
    fputs("|                                                                             |\n",fpw);
    fputs("|       Geoff Huston                                                          |\n",fpw);
    fputs("|       Computer Services Centre                                              |\n",fpw);
    fputs("|       Australian National University                                        |\n",fpw);
    fputs("|       GPO Box 4, Canberra, ACT   2601                                       |\n",fpw);
    fputs("|       AUSTRALIA                                                             |\n",fpw);
    fputs("|                                                                             |\n",fpw);
    fputs("|  or the letter may be e-mailed to:                                          |\n",fpw);
    fputs("|                                                                             |\n",fpw);
    fputs("|   ACSnet,CSNET:       gih900@csc.anu.oz                                     |\n",fpw);
    fputs("|   INTERNET: gih900%csc.anu.oz@uunet.uu.net                                  |\n",fpw);
    fputs("|   UUCP: {uunet,ubc-cs,nttlab,mcvax,ukc}!munnari!csc.anu.oz!gih900           |\n",fpw);
    fputs("|                                                                             |\n",fpw);
    fputs("|  NO CHARGE is made for this license.                                        |\n",fpw);
    fputs("|                                                                             |\n",fpw);
    fputs("| +--------------------------------------------------------------------------+|\n",fpw);
    fputs("| |======== VMS News - Release V5.6 =========================================||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| |   Please license the following system to run VMS NEWS:                   ||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| |     ORGANISATION: _______________________________________________        ||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| |     ADDRESS: ____________________________________________________        ||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| |              ____________________________________________________        ||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| |              ____________________________________________________        ||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| |              ____________________________________________________        ||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| |     CONTACT: ____________________________________________________        ||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| |     E-MAIL:  ____________________________________________________        ||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| |              ____________________________________________________        ||\n",fpw);
    fputs("| |                                                                          ||\n",fpw);
    fputs("| +--------------------------------------------------------------------------+|\n",fpw);
    fputs("|                                                                             |\n",fpw);
    fputs("| Permission is given to make and distribute copies of this software provided |\n",fpw);
    fputs("| 1: the author headers in all the source files are preserved                 |\n",fpw);
    fputs("| 2: that any further distribution of this software is free (except for a     |\n",fpw);
    fputs("|    nominal shipping change which may be applied).                           |\n",fpw);
    fputs("| 3: This file is included in all distributed copies of NEWS.                 |\n",fpw);
    fputs("|                                                                             |\n",fpw);
    fputs("| Permission is given to modify the sources in any way, provided:             |\n",fpw);
    fputs("| 1: the author headers are preserved on the source files                     |\n",fpw);
    fputs("| 2: the source files contain a header stating who changed the source         |\n",fpw);
    fputs("|    and the date of the change                                               |\n",fpw);
    fputs("|                                                                             |\n",fpw);
    fputs("| NOTE : This software is distributed free of any license charges on the      |\n",fpw);
    fputs("|    understanding that no warranty is implied with this software, nor is any |\n",fpw);
    fputs("|    liability incurred by the owner of the original copyright nor by any     |\n",fpw);
    fputs("|    person who has modified the file(s), nor any by person who permits a copy|\n",fpw);
    fputs("|    of the software to be made                                               |\n",fpw);
    fputs("+-----------------------------------------------------------------------------+\n",fpw);
    fclose(fpw);
    line = 1;
    printf("\tVMS NEWS V5.5 - LICENCE\n");
    gets(inpline);
    if (fpw = fopen(sysname,"r")) {
        while (fgets(inpline,132,fpw)) {
            printf("%s",inpline);
            if (++line > 22) {
                printf("(<return> to continue)");
                gets(inpline);
                line = 0;
                }
            }
        fclose(fpw);
        }
    printf("\tNEWS - LICENCE conditions:\n<<This message has been saved as %s>>\n\n",sysname);
    printf("(<return> to continue)");
    gets(inpline);
    printf("\n");
}

get_v5mailprofile()
{
    int i,
        j;
    char username_buf[32],
         *rv;
    MAIL_PROFILE vmsmail_profile;
    MAIL_ITEM_PTR vmsmail_item;
    struct FAB vmsmail_fab;
    struct RAB vmsmail_rab;

    j = strlen(usr_username);
    for (i = 0; i < 31 ; ++i) {
        if (i >= j) username_buf[i] =' ';
        else username_buf[i] = toupper(usr_username[i]);
        }

    j = 0;
    vmsmail_fab = cc$rms_fab;
    vmsmail_fab.fab$b_fac = FAB$M_GET;
    vmsmail_fab.fab$l_fna = MAIL_PRO_NAME;
    vmsmail_fab.fab$b_fns = strlen(vmsmail_fab.fab$l_fna);
    vmsmail_fab.fab$l_dna = MAIL_PRO_DEFAULT;
    vmsmail_fab.fab$b_dns = strlen(vmsmail_fab.fab$l_dna);
    vmsmail_fab.fab$b_shr = FAB$M_SHRPUT | FAB$M_SHRGET | FAB$M_SHRDEL | FAB$M_SHRUPD;

    vmsmail_rab = cc$rms_rab;
    vmsmail_rab.rab$l_fab = &vmsmail_fab;
    vmsmail_rab.rab$l_rop = RAB$M_NLK | RAB$M_RRL;
    vmsmail_rab.rab$b_krf = 0;
    vmsmail_rab.rab$l_kbf = username_buf;
    vmsmail_rab.rab$b_ksz = MAIL_PROKEY_SIZE;
    vmsmail_rab.rab$b_rac = RAB$C_KEY;
    vmsmail_rab.rab$w_usz = MAIL_PROREC_SIZE;
    vmsmail_rab.rab$l_ubf = &vmsmail_profile;

    sysprv();
    if ((sys$open(&vmsmail_fab) & 1) && (sys$connect(&vmsmail_rab) & 1)
            && (sys$get(&vmsmail_rab) & 1)) {
        j = 1;
        for (vmsmail_item = &vmsmail_profile.mail_pfields;
                vmsmail_item < vmsmail_rab.rab$l_rbf + vmsmail_rab.rab$w_rsz;
                i = vmsmail_item,i += 4 + vmsmail_item->mail_icount, vmsmail_item = i) {

            switch (vmsmail_item->mail_itype) {
                case MAIL_K_FLAGS:
                    i = &(vmsmail_item->mail_item_data);
                    mail_flags = *((unsigned short *) i);
                    continue;
                case MAIL_K_PERSNAME:
                    strncpy(usr_persname,&(vmsmail_item->mail_item_data),vmsmail_item->mail_icount);
                    usr_persname[vmsmail_item->mail_icount] = '\0';
                    break;
                case MAIL_K_EDITOR:
                    strncpy(mail_editor,&(vmsmail_item->mail_item_data),vmsmail_item->mail_icount);
                    mail_editor[vmsmail_item->mail_icount] = '\0';
                    break;
                case MAIL_K_QUEUE:
                    strncpy(mail_queue,&(vmsmail_item->mail_item_data),vmsmail_item->mail_icount);
                    mail_queue[vmsmail_item->mail_icount] = '\0';
                    break;
                case MAIL_K_FORM:
                    strncpy(mail_form,&(vmsmail_item->mail_item_data),vmsmail_item->mail_icount);
                    mail_form[vmsmail_item->mail_icount] = '\0';
                    break;
                default:
                    continue;
                }
            }
        }
    sys$close(&vmsmail_fab);
    nosysprv();
    return(j);
}

get_v4mailprofile()
{
    struct FAB vmsmail_fab;
    struct RAB vmsmail_rab;
    char mail_data_area[1000],
         *p;

    vmsmail_fab = cc$rms_fab;
    vmsmail_fab.fab$b_fac = FAB$M_GET;
    vmsmail_fab.fab$l_fna = MAIL_DAT_NAME;
    vmsmail_fab.fab$b_fns = strlen(vmsmail_fab.fab$l_fna);
    vmsmail_fab.fab$l_dna = MAIL_DAT_DEFAULT;
    vmsmail_fab.fab$b_dns = strlen(vmsmail_fab.fab$l_dna);
    vmsmail_fab.fab$b_shr = FAB$M_SHRPUT | FAB$M_SHRGET | FAB$M_SHRDEL | FAB$M_SHRUPD;

    vmsmail_rab = cc$rms_rab;
    vmsmail_rab.rab$l_fab = &vmsmail_fab;
    vmsmail_rab.rab$l_rop = RAB$M_NLK | RAB$M_RRL;
    vmsmail_rab.rab$b_krf = 0;
    vmsmail_rab.rab$l_kbf = usr_username;
    vmsmail_rab.rab$b_ksz = strlen(usr_username);
    vmsmail_rab.rab$b_rac = RAB$C_KEY;
    vmsmail_rab.rab$w_usz = 1000;
    vmsmail_rab.rab$l_ubf = mail_data_area;

    sysprv();
    if ((sys$open(&vmsmail_fab) & 1) && (sys$connect(&vmsmail_rab) & 1)
            && (sys$get(&vmsmail_rab) & 1)) {
        p = &mail_data_area[68];
        if (mail_data_area[67]) p += mail_data_area[67];
        if (mail_data_area[66]) {
            strncpy(usr_persname,p,mail_data_area[66]);
            usr_persname[mail_data_area[66]] = '\0';
            }
        }
    sys$close(&vmsmail_fab);
    nosysprv();
}

/*--------------------------------------------------------------

VMS V5.0 callable mail interface code - commented out at present

int no_in_list[2] = {0,0},
    no_out_list[2] = {0,0};

unsigned short autopurge_len,
               captive_len,
               cc_prompt_len,
               copy_forward_len,
               copy_reply_len,
               copy_send_len,
               forwarding_len,
               form_len,
               full_directory_len,
               new_messages_len,
               personal_name_len,
               queue_len,
               sub_directory_len;

int autopurge,
    captive,
    cc_prompt,
    copy_forward,
    copy_reply,
    copy_send;

char forwarding[256],
     form[256],
     full_directory[256],
     personal_name[256],
     queue[256],
     sub_directory[256];

short new_messages;

struct mail_item {
    unsigned short bl;
    unsigned short ic;
    int *ba;
    unsigned short *rl;
    } user_profile_list[] = {{4,MAIL$_USER_AUTOPURGE,&autopurge,&autopurge_len},
                             {4,MAIL$_USER_CAPTIVE,&captive,&captive_len},
                             {4,MAIL$_USER_CC_PROMPT,&cc_prompt,&cc_prompt_len},
                             {4,MAIL$_USER_COPY_FORWARD,&copy_forward,&copy_forward_len},
                             {4,MAIL$_USER_COPY_REPLY,&copy_reply,&copy_reply_len},
                             {4,MAIL$_USER_COPY_SEND,&copy_send,&copy_send_len},
                             {255,MAIL$_USER_FORWARDING,forwarding,&forwarding_len},
                             {255,MAIL$_USER_FORM,form,&form_len},
                             {255,MAIL$_USER_FULL_DIRECTORY,full_directory,&full_directory_len},
                             {2,MAIL$_USER_NEW_MESSAGES,&new_messages,&new_messages_len},
                             {255,MAIL$_USER_PERSONAL_NAME,personal_name,&personal_name_len},
                             {255,MAIL$_USER_QUEUE,queue,&queue_len},
                             {255,MAIL$_USER_SUB_DIRECTORY,sub_directory,&sub_directory_len},
                             {0,0,0,0}};

call_mail_profile()
{
    int context;

    if ((status = mail$user_begin(&context,no_in_list,no_out_list)) & 1) {
        status = mail$user_get_info(&context,no_in_list,user_profile_list);
        forwarding[forwarding_len] = '\0';
        form[form_len] = '\0';
        full_directory[full_directory_len] = '\0';
        personal_name[personal_name_len] = '\0';
        queue[queue_len] = '\0;
        sub_directory[sub_directory_len] = '\0';
        }
    mail$user_end(&context,no_in_list,no_out_list);
    return(status & 1)
}
--------------------------------------------------------*/
