#module NEWSSETSHOW "V5.6"

/*
**++
**  FACILITY:
**
**      NEWSSETSHOW
**
**  ABSTRACT:
**
**      Support the SET and SHOW command to set/display newsgroup attributes.
**
**  AUTHOR:
**
**      Geoff Huston
**
**  COPYRIGHT:
**
**      Copyright © 1988
**
**  MODIFICATION HISTORY:
**
**      V5.6    11-Nov-1988     GIH
**          Add support for restricted newsgroups
**
**--
**/

#include "newsinclude.h"
#include "newsdefine.h"
#include "newsextern.h"

/*
 * update_newsitm
 *
 * Assumes the contents of newsitm have been altered - this procedure
 * updates the master item file.
 */

static update_newsitm(g,i)
    int g,i;
{

    itmrab.rab$l_kbf = &(ga[g]->grp_ia[i].itm_num);
    itmrab.rab$b_krf = 0;
    itmrab.rab$b_ksz = 4;
    itmrab.rab$l_rop = RAB$M_WAT;
    itmrab.rab$b_rac = RAB$C_KEY;
    if (sys$find(&itmrab) & 1) {
        itmrab.rab$l_rbf = &(ga[g]->grp_ia[i]);
        itmrab.rab$w_rsz = sizeof newsitm;
        sys$update(&itmrab);
        }
}

/*
 * update_newsgrp
 *
 * Assumes the contents of newsgrp have been altered - this procedure
 * updates the master newsgroup file.
 */

update_newsgrp(g)
{
    grprab.rab$l_kbf = &(ga[g]->grp_num);
    grprab.rab$b_krf = 1;
    grprab.rab$b_ksz = 2;
    grprab.rab$l_rop = RAB$M_WAT;
    grprab.rab$b_rac = RAB$C_KEY;
    if (sys$find(&grprab) & 1) {
        grprab.rab$l_rbf = ga[g];
        grprab.rab$w_rsz = sizeof newsgrp;
        sys$update(&grprab);
        }
}

/*
 *  set_show_item
 *
 *  Common routine to set/show item attributes
 */

static set_show_item(setshow)
    int setshow;
{
    char s[132],
         hold[132],
         credate[11],
         deldate[11],
         delstr[20],
         holdstr[30];

    short s_len = 0,
          hold_len;
    unsigned short hold_val;
    $DESCRIPTOR(s_dsc,s);
    $DESCRIPTOR(hold_dsc,hold);

    if ((setshow) && (no_priv())) {
        err_line("\tError: Set Item - No priv\n");
        return(0);
        }

    cli$get_value(c$dsc("NEWSITEM"),&s_dsc,&s_len);
    s[s_len] = '\0';
    if (setshow) {
        cli$get_value(c$dsc("HOLD"),&hold_dsc,&hold_len);
        hold[hold_len] = '\0';
        if (!hold_len) hold_len = 0;
        if (!strcmp(hold,"*")) hold_val = ~0;
        else if (sscanf(hold,"%hd",&hold_val) != 1) {
            err_line("\tError: Set Item - /HOLD value not an integer\n");
            return(0);
            }
        }

    if (!curr_g) {
        err_line("\tError: Set/Show Item - No Newsgroup selected\n");
        return(0);
        }
    if (!*s) {
        if (curr_i <= 0) {
            err_line("\tError: Set/Show Item - No current item\n");
            return(0);
            }
        }
    else if (setshow && !strcmp(s,"*")) {
        int i;
        if (!ga[curr_g]->grp_count) {
            err_line("\tError: Set/Show Item - Newsgroup is empty\n");
            return(0);
            }
        set_level(2);
        for (i = 1 ; i <= ga[curr_g]->grp_count; ++i) {
            ga[curr_g]->grp_ia[i].itm_life = hold_val;
            update_newsitm(curr_g,i);
            }
        sprintf(hold,"\tItem *, Hold: %d\n",hold_val);
        err_line(hold);
        return(0);
        }
    else {
        if (!item_find(s)) {
            sprintf(hold,"\tError: Set/Show Item - Item %s not located\n",s);
            err_line(hold);
            return(0);
            }
        }

    if (setshow) {
        ga[curr_g]->grp_ia[curr_i].itm_life = hold_val;
        update_newsitm(curr_g,curr_i);
        }

    strcpy(credate,gendate(ga[curr_g]->grp_ia[curr_i].itm_date));
    *delstr = '\0';
    if (ga[curr_g]->grp_ia[curr_i].itm_life) {
        if (ga[curr_g]->grp_ia[curr_i].itm_life == 65535) strcpy(holdstr,"Perm");
        else {
            sprintf(holdstr,"%u",ga[curr_g]->grp_ia[curr_i].itm_life);
            strcpy(deldate,gendate(ga[curr_g]->grp_ia[curr_i].itm_date + (ga[curr_g]->grp_ia[curr_i].itm_life * 86400)));
            sprintf(delstr,"Del: %s, ",deldate);
            }
        }
    else {
        if (ga[curr_g]->grp_itmlife) {
            if (ga[curr_g]->grp_itmlife == 65535) strcpy(holdstr,"[Perm]");
            else {
                sprintf(holdstr,"[%u]",ga[curr_g]->grp_itmlife);
                strcpy(deldate,gendate(ga[curr_g]->grp_ia[curr_i].itm_date + (ga[curr_g]->grp_itmlife * 86400)));
                sprintf(delstr,"Del: %s, ",deldate);
                }
            }
        else {
            if (!ga[0]->grp_itmlife) ga[0]->grp_itmlife = EXP_TIME;
            if (ga[0]->grp_itmlife == 65535) strcpy(holdstr,"[Perm]");
            else {
                sprintf(holdstr,"[%u]",ga[0]->grp_itmlife);
                strcpy(deldate,gendate(ga[curr_g]->grp_ia[curr_i].itm_date + (ga[0]->grp_itmlife * 86400)));
                sprintf(delstr,"Del: %s, ",deldate);
                }
            }
        }
    sprintf(hold,"\tItem %u, Cre: %s, %sHold: %s, Size: %u\n",ga[curr_g]->grp_ia[curr_i].itm_num,credate,delstr,holdstr,ga[curr_g]->grp_ia[curr_i].itm_size);
    err_line(hold);
    return(0);
}

/*
 *  set_show_newsgroup
 *
 *  Common routine to set/show newsgroup attributes
 */

set_show_newsgroup(setshow)
    int setshow;
{
    int hold_pres = 0,
        itemhold_pres = 0,
        local_pres = 0,
        g,
        old_lev,
        mod_pres = 0,
        filehold_pres = 0,
        server_pres = 0,
        keep_pres = 0,
        protocol_pres = 0,
        protocol_val = 0,
        wild_group = 0,
        cur_time,
        glob_iexp_val,
        glob_iexp_time,
        server_call = 0,
        restrict_pres = 0,
        write_pres = 0;
    char s[132],
         hold[132],
         itemhold[132],
         filehold[132],
         delstr[132],
         oldsub[SUBJLEN],
         mod[132],
         mod_add[132],
         mod_prompt[132],
         srv[132],
         protocol[132],
         restrict[132];
    unsigned short s_len,
                   hold_len,
                   itemhold_len,
                   filehold_len,
                   filehold_val,
                   hold_val,
                   itemhold_val,
                   mod_len,
                   srv_len,
                   protocol_len,
                   restrict_len;
    short int s_zero = 0;
    $DESCRIPTOR(s_dsc,s);
    $DESCRIPTOR(hold_dsc,hold);
    $DESCRIPTOR(itemhold_dsc,itemhold);
    $DESCRIPTOR(filehold_dsc,filehold);
    $DESCRIPTOR(mod_dsc,mod);
    $DESCRIPTOR(srv_dsc,srv);
    $DESCRIPTOR(protocol_dsc,protocol);
    $DESCRIPTOR(restrict_dsc,restrict);

    if ((setshow) && (no_priv())) {
        err_line("\tError: Set Newsgroup - No priv\n");
        return(0);
        }

    clear_gl();
    old_lev = news_context;
    cli$get_value(c$dsc("GROUP"),&s_dsc,&s_len);
    s[s_len] = '\0';

    if (setshow) {
        if ((status = cli$present(c$dsc("RESTRICT"))) & 1) {
            while (cli$get_value(c$dsc("RESTRICT"),&restrict_dsc,&restrict_len) & 1) {
                if (toupper(*restrict == 'M')) {
                    restrict_pres = 1;
                    break;
                    }
                }
            }
        else if (status == CLI$_NEGATED) {
            while (cli$get_value(c$dsc("RESTRICT"),&restrict_dsc,&restrict_len) & 1) {
                if (toupper(*restrict == 'M')) {
                    restrict_pres = -1;
                    break;
                    }
                }
            }
        if ((status = cli$present(c$dsc("WRITE"))) & 1) write_pres = 1;
        else if (status == CLI$_NEGATED) write_pres = -1;
        if (cli$present(c$dsc("HOLD")) & 1) {
            ++hold_pres;
            cli$get_value(c$dsc("HOLD"),&hold_dsc,&hold_len);
            hold[hold_len] = '\0';
            if (!hold_len) hold_len = 0;
            if (!strcmp(hold,"*")) hold_val = ~0;
            else if (sscanf(hold,"%hd",&hold_val) != 1) {
                err_line("\tError: Set Newsgroup - /HOLD=val not an integer\n");
                return(0);
                }
            }
        if (cli$present(c$dsc("ITEMHOLD")) & 1) {
            ++itemhold_pres;
            cli$get_value(c$dsc("ITEMHOLD"),&itemhold_dsc,&itemhold_len);
            itemhold[itemhold_len] = '\0';
            if (!itemhold_len) itemhold_len = 0;
            if (!strcmp(itemhold,"*")) itemhold_val = ~0;
            else if (sscanf(itemhold,"%hd",&itemhold_val) != 1) {
                err_line("\tError: Set Newsgroup - /ITEMHOLD=val not an integer\n");
                return(0);
                }
            }
        if (cli$present(c$dsc("FILEHOLD")) & 1) {
            filehold_pres = 1;
            if (!(cli$get_value(c$dsc("FILEHOLD"),&filehold_dsc,&filehold_len) & 1)) filehold_val = ga[0]->grp_loccoplife;
            else {
                filehold[filehold_len] = '\0';
                if (sscanf(filehold,"%hd",&filehold_val) != 1) {
                    err_line("\tError: Set Newsgroup - /FILEHOLD=val not an integer\n");
                    filehold_pres = 0;
                    }
                }
            }
        if (cli$present(c$dsc("PROTOCOL")) & 1) {
            protocol_pres = 1;
            if (!(cli$get_value(c$dsc("PROTOCOL"),&protocol_dsc,&protocol_len) & 1)) protocol_val = 0;
            else {
                protocol[protocol_len] = '\0';
                if (!protocol_len) protocol_val = 0;
                else if (!strncmp(protocol,"CMUTCP",protocol_len))
                    protocol_val= 1;
                else if (!strncmp(protocol,"WINTCP",protocol_len))
                    protocol_val= 2;
                else if (!strncmp(protocol,"TCP",protocol_len))
#ifdef TWG
                    protocol_val= 2;
#else
                    protocol_val= 1;
#endif
                else protocol_val = 0;
                }
            }
        if ((status = cli$present(c$dsc("MODERATOR"))) & 1) mod_pres = 1;
        else if (status == CLI$_NEGATED) mod_pres = -1;
        if ((status = cli$present(c$dsc("LOCAL"))) & 1) local_pres = 1;
        else if (status == CLI$_NEGATED) local_pres = -1;
        if ((status = cli$present(c$dsc("SERVER"))) & 1) {
            server_pres = 1;
            srv_len = 0;
            if (cli$get_value(c$dsc("SERVER"),&srv_dsc,&srv_len) & 1) srv[srv_len] = '\0';
            if (!srv_len) get_input_dflt(&srv_dsc,c$dsc("SERVER Node: "),&srv_len,( *(ga[0]->grp_server) ? c$dsc(ga[0]->grp_server) : 0),0);
            if (!srv_len) server_pres = -1;
            if (srv_len > 6) srv_len = 6;
            srv[srv_len] = '\0';
            }
        else if (status == CLI$_NEGATED) server_pres = -1;
        if ((status = cli$present(c$dsc("KEEPREQUEST"))) & 1) keep_pres = 1;
        else if (status == CLI$_NEGATED) keep_pres = -1;
        }

    if ((!*s) || (!(strcmp,s,"."))) {
        if (!curr_g) {
            err_line("\tError: Set/Show Newsgroup - No Newsgroup specified\n");
            return(0);
            }
        else g = curr_g;
        }
    else if (!strcmp(s_to_lower(s),"default")) {
        g = 0;
        strcpy(s,"Default Newsgroup");
        }
    else if (setshow && (strchr(s,'*') || strchr(s,'%'))) {
        wild_group = 1;
        util_cvrt(s,s);
        g = 1;
        err_line("\tModifying all matching newsgroups to supplied parameters\n");
        }
    else {
        util_cvrt(s,s);
        if (!(g = ga_exact_name(s))) {
            sprintf(hold,"\tError: Set/Show Newsgroup - %s not located\n",s);
            err_line(hold);
            return(0);
            }
        }

    time(&cur_time);
    glob_iexp_val = (ga[0]->grp_itmlife ? ga[0]->grp_itmlife : EXP_TIME);
    glob_iexp_time = cur_time - (glob_iexp_val * 84600);

    if (setshow) {
        for (;;) {
            int grp_iexp_time;

            if (wild_group) {
                while (!wild_match(ga[g]->grp_name,s) && (++g <= ga_size));
                if (g > ga_size) break;
                }
            if (hold_pres) ga[g]->grp_life = hold_val;
            if (itemhold_pres) ga[g]->grp_itmlife = itemhold_val;
            if (filehold_pres) ga[g]->grp_loccoplife = filehold_val;
            if (protocol_pres) ga[g]->grp_srvproto = protocol_val;
            if (keep_pres > 0) ga[g]->grp_holdcop = 1;
            else if (keep_pres < 0) ga[g]->grp_holdcop = 0;
            if (restrict_pres > 0) {
                do_set_restrict(g);
                ga[g]->grp_local |= NEWS_RESTRICT_SET;
                }
            else if (restrict_pres < 0) {
                do_set_norestrict(g);
                ga[g]->grp_local &= ~NEWS_RESTRICT_SET;
                }
            if (write_pres > 0) {
                ga[g]->grp_local &= ~NEWS_NOWRITE_SET;
                }
            else if (write_pres < 0) {
                ga[g]->grp_local |= NEWS_NOWRITE_SET;
                }
            if (server_pres) {
                if (server_pres < 0) {
                    if (*(ga[g]->grp_server)) noserver_add(ga[g]->grp_num);
                    *(ga[g]->grp_server) = '\0';
                    }
                else strncpy(ga[g]->grp_server,srv,8);
                }
            if (g && (protocol_pres || server_pres) && *(ga[g]->grp_server)) {
                if (ga[g]->grp_itmlife) grp_iexp_time = cur_time - (ga[g]->grp_itmlife * 84600);
                else grp_iexp_time = glob_iexp_time;
                ++server_call;
                add_check_id(ga[g]->grp_name,0,ga[g]->grp_num,ga[g]->grp_server,grp_iexp_time,ga[g]->grp_srvproto);
                }
            if ((mod_pres) && g) {
                if ((mod_pres < 0) && ga[g]->grp_moderator) ga[g]->grp_moderator = 0;
                else {
                    strcpy(mod_add,moderator_address(ga[g]->grp_name));
                    mod_len = 0;
                    if (cli$get_value(c$dsc("MODERATOR"),&mod_dsc,&mod_len) & 1) {
                        mod[mod_len] = '\0';
                        strcpy(mod_add,mod);
                        }
                    sprintf(mod_prompt,"Moderator for %s: ",ga[g]->grp_name);
                    get_input_dflt(&mod_dsc,c$dsc(mod_prompt),&mod_len,c$dsc(mod_add),0);
                    if ((!mod_len) && ga[g]->grp_moderator) ga[g]->grp_moderator = 0;
                    else {
                        mod[mod_len] = '\0';
                        s_to_lower(mod);
                        strcpy(mod_add,moderator_address(ga[g]->grp_name));
                        if (strcmp(mod,mod_add)) add_moderator(ga[g]->grp_name,mod);
                        ga[g]->grp_moderator = 1;
                        }
                    }
                }
            if (local_pres > 0) ga[g]->grp_local |= 1;
            else if (local_pres < 0) ga[g]->grp_local &= ~1;
            update_newsgrp(g);
            if (!wild_group) break;
            if (++g > ga_size) break;
            }
        }

    if (server_call) {
        server_check(1,1);
        clear_gl();
        }
    noserver_skim();
    if (wild_group) return(0);

    hold_val = ga[g]->grp_life;
    *itemhold = '\0';
    if (ga[g]->grp_itmlife == 65535) strcpy(itemhold,"Perm");
    else if (ga[g]->grp_itmlife) sprintf(itemhold,"%u",ga[g]->grp_itmlife);
    *hold = '\0';
    if (ga[g]->grp_life == 65535) strcpy(hold,"Perm");
    else if (ga[g]->grp_life) sprintf(hold,"%u",ga[g]->grp_life);
    if ((!((*hold) && (*itemhold))) && (g)) {
        if (!*itemhold) {
            if (ga[0]->grp_itmlife == 65535) strcpy(itemhold,"[Perm]");
            else if (ga[0]->grp_itmlife) sprintf(itemhold,"[%u]",ga[0]->grp_itmlife);
            }
        if (!*hold) {
            if (ga[0]->grp_life == 65535) strcpy(hold,"[Perm]");
            else if (ga[0]->grp_life) sprintf(hold,"[%u]",ga[0]->grp_life);
            hold_val = ga[0]->grp_life;
            }
        }
    if (!*itemhold) sprintf(itemhold,"[%u]",EXP_TIME);
    if (!*hold) {
        sprintf(hold,"[%u]",GRP_TIME);
        hold_val = GRP_TIME;
        }
    if (ga[g]->grp_count) sprintf(delstr," #: %u",ga[g]->grp_count);
    else if (hold_val != 65535) sprintf(delstr," Del: %s",gendate(ga[g]->grp_entdate + (hold_val * 86400)));
    else *delstr = '\0';
    sprintf(s,"%s Itm:%s Grp:%s%s",ga[g]->grp_name,itemhold,hold,delstr);
    if (ga[g]->grp_moderator) {
        strcat(s," Mod:");
        strcat(s,moderator_address(ga[g]->grp_name));
        }
    if (ga[g]->grp_local & 1) strcat(s," L");
    if (*(ga[g]->grp_server)) {
        strcat(s," [Srv: ");
        if (ga[g]->grp_srvproto == 1) strcat(s,"@");
        strcat(s,ga[g]->grp_server);
        if (ga[g]->grp_srvproto != 1) strcat(s,"::");
        if (!ga[g]->grp_holdcop) strcat(s," Nohold]");
        else sprintf(&s[strlen(s)]," Hold: %d]",ga[g]->grp_loccoplife);
        }
    strcat(s,"\n");
    err_line(s);
    return(0);
}

/*
 *  do_show_item
 *
 *  Show item attributes
 */

do_show_item()
{
    return(set_show_item(0));
}

/*
 *  do_set_item
 *
 *  Set item attributes
 */

do_set_item()
{
    return(set_show_item(1));
}

/*
 *  do_show_newsgroup
 *
 *  Set newsgroup attributes
 */

do_show_newsgroup()
{
    return(set_show_newsgroup(0));
}

/*
 *  do_set_newsgroup
 *
 *  Set newsgroup attributes
 */

do_set_newsgroup()
{
    return(set_show_newsgroup(1));
}

ismember(ng,user)
    char *ng, *user;
{
    FILE *fpr;
    char il[256], cu[256],
         *cp, *ap, *op;
    int retval = 0;

    sprintf(itm_fname,Access_template,util_dir(ng));
    sysprv();
    if (!(fpr = fopen(itm_fname,"r"))) return(nosysprv(),0);
    while (fgets(il,256,fpr)) {
        if (*il == '#') continue;
        if (cp = strchr(il,' ')) *cp = '\0';
        if (ap = strchr(il,'@')) *ap = '\0';
        if (op = strchr(il,':')) *op = '\0';
        strcpy(cu,il);
        if (cp) *cp = ' ';
        if (ap) *ap = '@';
        if (op) *op = ':';
        s_to_lower(cu);
        if (!strcmp(cu,user)) {
            retval = 1;
            break;
            }
        }
    fclose(fpr);
    nosysprv();
    return(retval);
}

do_add_member()
{
    FILE *fpr, *fpw;
    char uv[256], username[132], mailstr[256], nodelist[256], privstr[256],
         *c, *cp, *ap, *op;
    short ul;
    $DESCRIPTOR(ud,uv);

    if (!curr_g)
        return(err_line("\tAdd Member: No current newsgroup selected\n"),0);

    if (no_priv() && !(ga[curr_g]->grp_local & NEWS_MOD_ACCESS))
        return(err_line("\tAdd Member: No Privs for this command\n"),0);

    *mailstr = *privstr = *nodelist = '\0';

    if (!(cli$get_value(c$dsc("USERNAME"),&ud,&ul) & 1)) return(0);
    if (!ul) return(0);
    uv[ul] = '\0';
    s_to_lower(uv);
    if ((c = strchr(uv,':')) && (*(c + 1) == ':')) {
        *c = '\0';
        sprintf(nodelist,"@%s",uv);
        strcpy(username,c+2);
        }
    else if (c = strchr(uv,'@')) {
        strcpy(nodelist,c);
        *c = '\0';
        strcpy(username,uv);
        }
    else strcpy(username,uv);

    if (cli$get_value(c$dsc("MAIL"),&ud,&ul) & 1) {
        uv[ul] = '\0';
        sprintf(mailstr," MAIL:%s",uv);
        }
    while (cli$get_value(c$dsc("NODES"),&ud,&ul) & 1) {
        uv[ul] = '\0';
        s_to_lower(uv);
        if (*nodelist) strcat(nodelist," ");
        strcat(nodelist,"@");
        strcat(nodelist,uv);
        }

    while (cli$get_value(c$dsc("PRIVILEGES"),&ud,&ul) & 1) {
        uv[ul] = '\0';
        s_to_lower(uv);
        if (!strncmp(uv,"moderate",ul)) strcpy(uv,"MODERATE");
        else if (!strncmp(uv,"create_keywords",ul)) strcpy(uv,"CREATE_KEYWORDS");
        else if (!strncmp(uv,"nowrite",ul)) strcpy(uv,"NOWRITE");
        else if (!strncmp(uv,"write",ul)) strcpy(uv,"WRITE");
        strcat(privstr," ");
        strcat(privstr,uv);
        }

    sprintf(itm_fname,Access_template,util_dir(ga[curr_g]->grp_name));
    sysprv();
    if (!(fpr = fopen(itm_fname,"r"))) {
        sprintf(err_oline,"\tAdd Member: Newsgroup %s is NOT a restricted newsgroup\n",ga[curr_g]->grp_name);
        err_line(err_oline);
        return(nosysprv(),0);
        }
    fpw = fopen(itm_fname,"w");
    fprintf(fpw,"%s%s%s%s\n",username,nodelist,privstr,mailstr);
    while (fgets(mailstr,256,fpr)) {
        if (*mailstr == '#') {
            fputs(mailstr,fpw);
            continue;
            }
        if (cp = strchr(mailstr,' ')) *cp = '\0';
        if (ap = strchr(mailstr,'@')) *ap = '\0';
        if (op = strchr(mailstr,':')) *op = '\0';
        strcpy(uv,mailstr);
        if (cp) *cp = ' ';
        if (ap) *ap = '@';
        if (op) *op = ':';
        s_to_lower(uv);
        if (!strcmp(uv,username)) continue;
        fputs(mailstr,fpw);
        }
    fclose(fpr);
    fclose(fpw);
    strcat(itm_fname,";-1");
    while (!delete(itm_fname)) ;
    nosysprv();
    err_line("\tAdd Member: Entry added\n");
    return(0);
}

do_delete_member()
{
    FILE *fpr, *fpw;
    char uv[256], il[256], cu[132],
         *cp, *ap, *op;
    short ul;
    $DESCRIPTOR(ud,uv);


    if (!curr_g)
        return(err_line("\tAdd Member: No current newsgroup selected\n"),0);

    if (no_priv() && !(ga[curr_g]->grp_local & NEWS_MOD_ACCESS))
        return(err_line("\tAdd Member: No Privs for this command\n"),0);

    if (!(cli$get_value(c$dsc("USERNAME"),&ud,&ul) & 1)) return(0);
    if (!ul) return(0);
    uv[ul] = '\0';
    s_to_lower(uv);

    if (!ismember(ga[curr_g]->grp_name,uv)) {
        sprintf(err_oline,"\tDelete Member: Username %s is not a member of %s\n",uv,ga[curr_g]->grp_name);
        err_line(err_oline);
        return(0);
        }

    sprintf(itm_fname,Access_template,util_dir(ga[curr_g]->grp_name));

    sysprv();
    if (!(fpr = fopen(itm_fname,"r"))) {
        sprintf(err_oline,"\tDelete Member: Newsgroup %s is NOT a restricted newsgroup\n",ga[curr_g]->grp_name);
        err_line(err_oline);
        return(nosysprv(),0);
        }
    fpw = fopen(itm_fname,"w");
    while (fgets(il,256,fpr)) {
        if (*il == '#') {
            fputs(il,fpw);
            continue;
            }
        if (cp = strchr(il,' ')) *cp = '\0';
        if (ap = strchr(il,'@')) *ap = '\0';
        if (op = strchr(il,':')) *op = '\0';
        strcpy(cu,il);
        if (cp) *cp = ' ';
        if (ap) *ap = '@';
        if (op) *op = ':';
        s_to_lower(cu);
        if (!strcmp(cu,uv)) continue;
        fputs(il,fpw);
        }
    fclose(fpr);
    fclose(fpw);
    strcat(itm_fname,";-1");
    while (!delete(itm_fname)) ;
    nosysprv();
    err_line("\tDelete Member: Entry deleted\n");
    return(0);
}

do_modify_member()
{
    FILE *fpr, *fpw;
    char uv[256], username[132], mailstr[256], nodelist[256], privstr[256],
         newname[132], il[256],
         *c, *cp, *ap, *op;
    short ul;
    $DESCRIPTOR(ud,uv);

    if (!curr_g)
        return(err_line("\tModify Member: No current newsgroup selected\n"),0);

    if (no_priv() && !(ga[curr_g]->grp_local & NEWS_MOD_ACCESS))
        return(err_line("\tModify Member: No Privs for this command\n"),0);

    *mailstr = *privstr = *nodelist = '\0';

    if (!(cli$get_value(c$dsc("USERNAME"),&ud,&ul) & 1)) return(0);
    if (!ul) return(0);
    uv[ul] = '\0';
    s_to_lower(uv);
    strcpy(username,uv);
    strcpy(newname,uv);

    if (cli$get_value(c$dsc("NAME"),&ud,&ul) & 1) {
        if ((c = strchr(uv,':')) && (*(c + 1) == ':')) {
            *c = '\0';
            sprintf(nodelist,"@%s",uv);
            strcpy(newname,c+2);
            }
        else if (c = strchr(uv,'@')) {
            strcpy(nodelist,c);
            *c = '\0';
            strcpy(newname,uv);
            }
        else strcpy(newname,uv);
        }

    if (cli$get_value(c$dsc("MAIL"),&ud,&ul) & 1) {
        uv[ul] = '\0';
        sprintf(mailstr," MAIL:%s",uv);
        }
    while (cli$get_value(c$dsc("NODES"),&ud,&ul) & 1) {
        uv[ul] = '\0';
        s_to_lower(uv);
        if (*nodelist) strcat(nodelist," ");
        strcat(nodelist,"@");
        strcat(nodelist,uv);
        }

    while (cli$get_value(c$dsc("PRIVILEGES"),&ud,&ul) & 1) {
        uv[ul] = '\0';
        s_to_lower(uv);
        strcat(privstr," ");
        strcat(privstr,uv);
        }

    if (!ismember(ga[curr_g]->grp_name,username)) {
        sprintf(err_oline,"\tModify Member: Username %s is not a member of %s\n",uv,ga[curr_g]->grp_name);
        err_line(err_oline);
        return(0);
        }

    sprintf(itm_fname,Access_template,util_dir(ga[curr_g]->grp_name));
    sysprv();
    if (!(fpr = fopen(itm_fname,"r"))) {
        sprintf(err_oline,"\tModify Member: Newsgroup %s is NOT a restricted newsgroup\n",ga[curr_g]->grp_name);
        err_line(err_oline);
        return(nosysprv(),0);
        }
    fpw = fopen(itm_fname,"w");
    while (fgets(il,256,fpr)) {
        if (*il == '#') {
            fputs(il,fpw);
            continue;
            }
        if (cp = strchr(il,' ')) *cp = '\0';
        if (ap = strchr(il,'@')) *ap = '\0';
        if (op = strchr(il,':')) *op = '\0';
        strcpy(uv,mailstr);
        if (cp) *cp = ' ';
        if (ap) *ap = '@';
        if (op) *op = ':';
        s_to_lower(uv);
        if (!strcmp(uv,username)) {
            int i;

            s_to_lower(il);
            fprintf(fpw,"%s",newname);

            if (op) *op = '\0';
            if ((!*nodelist) && (ap)) {
                while (ap) {
                    while (*ap && !isspace(*ap)) {
                        fputc(*ap,fpw);
                        ap++;
                        }
                    ap = strchr(ap,'@');
                    }
                }
            else if (*nodelist) fputs(nodelist,fpw);
            if (op) *op = ':';

            if (!*privstr) {
                if (substrcmp(cp," write ")) fprintf(fpw," WRITE ");
                else if (substrcmp(cp," nowrite ")) fprintf(fpw," NOWRITE ");
                if (substrcmp(cp," moderate ")) fprintf(fpw," MODERATE ");
                if (substrcmp(cp," create_keywords ")) fprintf(fpw," CREATE_KEYWORDS ");
                }
            else fputs(privstr,fpw);

            if ((!*mailstr) && (i = substrcmp(il," mail:"))) {
                fputc(' ',fpw);
                while (!isspace(cp[i])) {
                    fputc(cp[i],fpw);
                    ++i;
                    }
                }
            else if (*mailstr) fputs(mailstr,fpw);
            fputc('\n',fpw);
            }
        else fputs(il,fpw);
        }
    fclose(fpr);
    fclose(fpw);
    strcat(itm_fname,";-1");
    while (!delete(itm_fname)) ;
    nosysprv();
    err_line("\tModify Member: Entry modified\n");
    return(0);
}

do_show_member()
{
    char uv[256], ml[256], il[256], rl[256], us[256],
         *cp, *ap, *op;
    short ul;
    int all = 0,
        mod = 0,
        displayed = 0;
    FILE *fpr;
    $DESCRIPTOR(ud,uv);

    all = (cli$present(c$dsc("ALL")) & 1);
    mod = (cli$present(c$dsc("MODERATOR")) & 1);
    if (!all) {
        if (!(cli$get_value(c$dsc("USERNAME"),&ud,&ul) & 1)) {
            ul = 0;
            if (mod) all = 1;
            else if (!(get_input(&ud,c$dsc("Username :"),&ul) & 1)) return(0);
            }
        uv[ul] = '\0';
        s_to_lower(uv);
        }

    if (!curr_g)
        return(err_line("\tShow Member: No current newsgroup selected\n"),0);

    *ml = '\0';
    if (ga[curr_g]->grp_moderator) {
        sprintf(ml,"Mail_Address: %s",moderator_address(ga[curr_g]->grp_name));
        }

    sprintf(itm_fname,Access_template,util_dir(ga[curr_g]->grp_name));
    sysprv();
    if (!(fpr = fopen(itm_fname,"r"))) {
        sprintf(err_oline,"\tShow Member: Newsgroup %s is NOT a restricted newsgroup\n",ga[curr_g]->grp_name);
        err_line(err_oline);
        return(nosysprv(),0);
        }
    nosysprv();

    while (fgets(il,256,fpr)) {
        if (*il == '#') continue;
        strcpy(rl,il);
        s_to_lower(rl);
        if (cp = strchr(rl,' ')) *cp = '\0';
        if (ap = strchr(rl,'@')) *ap = '\0';
        if (op = strchr(rl,':')) *op = '\0';
        strcpy(us,rl);
        if (cp) *cp = ' ';
        if (ap) *ap = '@';
        if (op) *op = ':';
        if (all || !strcmp(us,uv)) {
            if (mod) {
                if (!substrcmp(cp," moderator ")) continue;
                }
            if (!displayed) {
                start_header();
                sprintf(err_oline,"Membership of Newsgroup %s",ga[curr_g]->grp_name);
                put_line(err_oline,0);
                put_line("",0);
                end_header();
                displayed = 1;
                if (*ml) put_line(ml,0);
                }
            put_line(il,0);
            }
        }
    sysprv();
    fclose(fpr);
    nosysprv();
    if (displayed) put_line("",1);
    else err_line("\tNo such Member in this newsgroup\n");
    return(0);
}

do_show_moderator()
{
    int displayed = 0;
    char rl[256], il[256], ml[256];
    FILE *fpr;

    *ml = '\0';
    if (!curr_g)
        return(err_line("\tShow Moderator: No current newsgroup selected\n"),0);

    if (ga[curr_g]->grp_moderator) {
        sprintf(ml,"Mail_Address: %s",moderator_address(ga[curr_g]->grp_name));
        start_header();
        sprintf(err_oline,"Moderators of Newsgroup %s",ga[curr_g]->grp_name);
        put_line(err_oline,0);
        put_line("",0);
        end_header();
        displayed = 1;
        put_line(ml,0);
        }

    sprintf(itm_fname,Access_template,util_dir(ga[curr_g]->grp_name));
    sysprv();
    if (!(fpr = fopen(itm_fname,"r"))) {
        sprintf(err_oline,"\tShow Moderator: Newsgroup %s is NOT a restricted newsgroup\n",ga[curr_g]->grp_name);
        err_line(err_oline);
        return(nosysprv(),0);
        }
    nosysprv();

    while (fgets(il,256,fpr)) {
        if (*il == '#') continue;
        strcpy(rl,il);
        s_to_lower(rl);
        if (!substrcmp(rl," moderator ")) continue;
        if (!displayed) {
            start_header();
            sprintf(err_oline,"Moderators of Newsgroup %s",ga[curr_g]->grp_name);
            put_line(err_oline,0);
            put_line("",0);
            end_header();
            displayed = 1;
            }
        put_line(il,0);
        }
    sysprv();
    fclose(fpr);
    nosysprv();
    if (displayed) put_line("",1);
    else err_line("\tNo such Member in this newsgroup\n");
    return(0);
}

do_set_restrict(g)
    int g;
{
    struct FAB resfab;
    struct XABPRO respro;
    FILE *fpr;

    sprintf(itm_fname,Access_template,util_dir(ga[curr_g]->grp_name));
    sysprv();
    if (fpr = fopen(itm_fname,"r")) {
        fclose(fpr);
        nosysprv();
        err_line("\tSet Newsgroup/Restrict=Members: Newsgroup is already restricted\n");
        return(0);
        }

    /* open the index newsgroup descriptor file for full access */
    resfab = cc$rms_fab;
    resfab.fab$b_fac = FAB$M_GET | FAB$M_PUT | FAB$M_UPD | FAB$M_DEL ;
    resfab.fab$l_fna = itm_fname;
    resfab.fab$b_fns = strlen(resfab.fab$l_fna);
    resfab.fab$l_fop = FAB$M_CIF;
    resfab.fab$w_mrs = 2000;
    resfab.fab$b_rat = FAB$M_CR;
    resfab.fab$b_rfm = FAB$C_VAR;
    resfab.fab$l_xab = &respro;

    respro = cc$rms_xabpro;
    respro.xab$w_pro = 0xEE00;
    if (!(sys$create(&resfab) & 1)) {
        nosysprv();
        err_line("\tSet Newsgroup/Restrict=Members: Cannot create member file\n");
        return(0);
        }
    sys$close(&resfab);
    nosysprv();
    err_line("\tSet Newsgroup/Restrict=Members: Created new member file\n");
    return(1);
}
do_set_norestrict(g)
    int g;
{
    FILE *fpr;

    sprintf(itm_fname,Access_template,util_dir(ga[curr_g]->grp_name));
    sysprv();
    if (fpr = fopen(itm_fname,"r")) {
        fclose(fpr);
        while (!delete(itm_fname));
        nosysprv();
        return(1);
        }
    return(0);
}

check_access(g)
    int g;
{
    char acline[256], cknode[132],
         *cp, *ap, *op;
    FILE *fpd;

    ga[g]->grp_local |= NEWS_ACCESS_CHECKED;
    sprintf(itm_fname,Access_template,util_dir(ga[g]->grp_name));
    sysprv();
    if (fpd = fopen(itm_fname,"r")) {
        if (!(ga[g]->grp_local & NEWS_NOWRITE_SET))  ga[g]->grp_local |= NEWS_WRITE_ACCESS;
        while (fgets(acline,256,fpd)) {
            if (*acline == '#') continue;
            if (cp = strchr(acline,'\n')) *cp = ' ';
            s_to_lower(acline);
            if (cp = strchr(acline,' ')) *cp = '\0';
            if (ap = strchr(acline,'@')) *ap = '\0';
            if (op = strchr(acline,':')) *op = '\0';
            if (!strcmp(acline,usr_username) || wild_match(usr_username,acline) || idmatch(acline)) {
                if (cp) *cp = ' ';
                if (ap) *ap = '@';
                if (strchr(acline,'@')) {
                    sprintf(cknode,"@%s ",usr_nodename);
                    if (!substrcmp(cp,cknode)) continue;
                    }
                if (substrcmp(cp," write ")) ga[g]->grp_local |= NEWS_WRITE_ACCESS;
                if (substrcmp(cp," nowrite ")) ga[g]->grp_local &= ~NEWS_WRITE_ACCESS;
                if (substrcmp(cp," moderator ")) ga[g]->grp_local |= (NEWS_MOD_USER | NEWS_WRITE_ACCESS);
                }
            }
        fclose(fpd);
        }
    nosysprv();
}

do_set_mod()
{
    int g;
    for (g = 1; g <= ga_size; ++g) {
        if (!(ga[g]->grp_local & NEWS_ACCESS_CHECKED)) check_access(g);
        if (ga[g]->grp_local & NEWS_MOD_USER) ga[g]->grp_local |= NEWS_MOD_ACCESS;
        }
    return(0);
}

do_set_nomod()
{
    int g;

    for (g = 1; g <= ga_size; ++g) ga[g]->grp_local &= ~NEWS_MOD_ACCESS;
    return(0);
}
