/*
**++
**  FACILITY:
**      NEWSCONFIGS
**
**  ABSTRACT:
**      Manage NEWS configuration files
**
**  AUTHOR:
**      Geoff Huston
**
**  COPYRIGHT:
**      Copyright, Geoff Huston © 1988,1989,1990,1991,1992
**
**  MODIFICATION HISTORY:
**	V6.1b9	17-Aug-1994     Mark Martinec   mark.martinec@ijs.si
**	  - code cleanup to make it compile under gcc 2.6.0 with full
**	    warnings reporting turned on - with no or very few harmless warnings
**	V6.1b9	17-Sep-1994     Mark Martinec   mark.martinec@ijs.si
**	  - code cleanup to preserve the read-only nature of string literals
**	    (strategically placed 'const' attribute to string parameters)
**	V6.1b11 14-Apr-1997	Mark Martinec   mark.martinec@ijs.si
**	  - replace several calls to strcpy/strcat with safer strnncpy/strnncat
**	  - replace pattern strcpy(news_malloc(strlen(x)+1),x) with news_strdup
**	  - replace pattern strcat(err_oline,x) with err_oline_cat(x)
**	  - change %s to %.<n>s in sprintf to guard against overwriting buffer
**--
**/

#ifdef vaxc
#module NEWSCONFIGS "V6.2"
#endif

#define _NEWSCONFIGS_C
#define module_name "NEWSCONFIGS"

#include "newsinclude.h"
#include "newsextern.h"

char newsg[256];

static int dsaliases()
{
  ALIAS_PTR tmp;

  if (!aliases_list) {
    err_line("SHOW ALIASES - no local aliases defined");
    return(0);
    }

  start_header(T_DISPLAY_LOOP,SHOW_ALIASES);
  put_line("NEWS  - Local Newsgroup Alias list",0,T_DISPLAY_LOOP);
  put_line("",0,T_DISPLAY_LOOP);
  end_header(T_DISPLAY_LOOP);

  for (tmp=aliases_list; tmp; tmp=tmp->a_next) {
    if ( wild_match(tmp->ngname,newsg) ) {
      err_oline[0] = '\0';   err_oline_cat(tmp->ngname);
      err_oline_cat(" -> "); err_oline_cat(tmp->alias_name);
      put_line(err_oline,0,T_DISPLAY_LOOP);
      }
    }
  put_line("",1,T_DISPLAY_LOOP);
  return(0);
}

int do_show_aliases()
{
  $DESCRIPTOR(newsg_d,newsg);
  unsigned short len = 0;

  if (cli$get_value(c$dsc("NEWSGROUP"),&newsg_d,&len) & 1) newsg[len] = '\0';
  else *newsg = '\0';
  if (!*newsg) strcpy(newsg,"*");
  strip_compress_lower(newsg);

  if (nntp_client) return(0);

  if (!read_aliases() && (textptr.display_code != SHOW_ALIASES)) {
    err_line("SHOW ALIASES - no local aliases defined");
    return(0);
    }
  return(unwind_display(I_DISPLAY_LOOP,dsaliases));
}

static int daalias(mod)
  int mod;
{
  int status;
  ALIAS_PTR tmp;
  char alias[256], alias_list[512], *cp;
  unsigned short len = 0;
  int alias_list_l;
  $DESCRIPTOR(newsg_d,newsg);
  $DESCRIPTOR(alias_d,alias);

  if (nntp_client) return(0);
  if (no_priv()) {
    err_line("Error: Set Item - No priv");
    return(0);
    }

  if (cli$get_value(c$dsc("NEWSGROUP"),&newsg_d,&len) & 1) newsg[len] = '\0';
  else *newsg = '\0';
  if (!*newsg) {
    if (!(get_input(&newsg_d,c$dsc("ALIAS Newsgroup: "),&len) & 1)) return(0);
    newsg[len] = '\0';
    }
  strip_compress_lower(newsg);
  if (!*newsg) return(0);

  if (cli$get_value(c$dsc("ALIAS"),&alias_d,&len) & 1) {
    *alias_list = '\0'; alias_list_l = 0;
    do {
      alias[len] = '\0';
      strip_compress_lower(alias);
      if (*alias) {
        if (*alias_list)
          strnncat(alias_list,sizeof(alias_list),alias_list_l, ",",1, &alias_list_l);
        strnncat(alias_list,sizeof(alias_list),alias_list_l, alias,len, &alias_list_l);
        }
      } while (cli$get_value(c$dsc("ALIAS"),&alias_d,&len) & 1);
    }
  else { *alias_list = '\0'; alias_list_l = 0; }
  if (!*alias_list) {
    sprintf(err_oline,"ALIAS %.256s (to): ",newsg);
    if (!(get_input(&alias_d,c$dscl(&err_oline_d),&len) & 1)) return(0);
    alias[len] = '\0';
    strnncpy(alias_list,sizeof(alias_list), alias,len, &alias_list_l);
    }
  strip_compress_lower(alias_list);
  if (!*alias_list) return(0);

  for (tmp=read_aliases(); tmp; tmp=tmp->a_next) {
    if (!strcmp(tmp->ngname,newsg)) {
      if (!mod) {
        sprintf(err_oline,"Alias for %.200s (-> %.200s) already defined",
                tmp->ngname,tmp->alias_name);
        err_line(err_oline);
        status = get_input(&alias_d,c$dsc("Replace this alias? [y]"),&len);
        clear_err_line();
        if ((!(status & 1)) || (len && (tolower(*alias) != 'y'))) return(0);
        }
      news_free(tmp->alias_name);
      tmp->alias_name = news_strdup(alias_list,alias_list_l);
      break;
      }
    }
  if (!tmp) {
    tmp = news_malloc(sizeof *tmp);
    tmp->alias_name = news_strdup(alias_list,alias_list_l);
    tmp->ngname = news_strdup(newsg,-1);
    tmp->a_next = aliases_list;
    aliases_list = tmp;
    }

  sysprv();
  if ((fp = fopen(ALIAS_FILE,"w")) != 0) {
    for (tmp=aliases_list; tmp; tmp=tmp->a_next)
      fprintf(fp,"%s %s\n",tmp->ngname,tmp->alias_name);
    fgetname(fp,alias);
    fclose(fp);

    if ((cp = strchr(alias,';')) != 0) {
      strcpy(cp,";-1");
      delete_file_versions(alias);
      }
    }
  nosysprv();

  return(do_show_aliases());
}

int do_add_alias()
{
  return(daalias(0));
}

int do_mod_alias()
{
  return(daalias(1));
}

int do_delete_alias()
{
  int status;
  ALIAS_PTR tmp;
  char alias[256], *cp;
  unsigned short len = 0;
  int conf;
  $DESCRIPTOR(newsg_d,newsg);
  $DESCRIPTOR(alias_d,alias);

  if (nntp_client) return(0);
  if (no_priv()) {
    err_line("Error: Set Item - No priv");
    return(0);
    }

  conf = (cli$present(c$dsc("CONFIRM")) != CLI$_NEGATED);
  
  if (cli$get_value(c$dsc("NEWSGROUP"),&newsg_d,&len) & 1) newsg[len] = '\0';
  else *newsg = '\0';
  if (!*newsg) {
    if (!(get_input(&newsg_d,c$dsc("Delete Alias for Newsgroup: "),&len) & 1)) return(0);
    newsg[len] = '\0';
    }
  strip_compress_lower(newsg);
  if (!*newsg) return(0);

  for (tmp=read_aliases(); tmp; tmp=tmp->a_next) {
    if (!strcmp(tmp->ngname,newsg)) {
      if (conf) {
        sprintf(err_oline,"Alias for %.200s is %.200s",
                tmp->ngname,tmp->alias_name);
        err_line(err_oline);
        status = get_input(&alias_d,c$dsc("Delete alias? [y]"),&len);
        clear_err_line();
        if ((!(status & 1)) || (len && (tolower(*alias) != 'y')))
          return(0);
        }
      break;
      }
    }

  if (!tmp) {
    strcpy(err_oline,"No Alias defined for "); err_oline_cat(newsg);
    err_line(err_oline);
    return(0);
    }

  if (tmp == aliases_list) aliases_list = tmp->a_next;
  else {
    ALIAS_PTR p;
    for (p=aliases_list; p->a_next != tmp; p=p->a_next) {}
    p->a_next = tmp->a_next;
    }

  news_free(tmp->ngname);
  news_free(tmp->alias_name);
  news_free(tmp);

  sysprv();

  if (!aliases_list)
    delete_file_versions(ALIAS_FILE);
  else {
    if ((fp = fopen(ALIAS_FILE,"w")) != 0) {
      for (tmp=aliases_list; tmp; tmp=tmp->a_next)
        fprintf(fp,"%s %s\n",tmp->ngname,tmp->alias_name);
      fgetname(fp,alias);
      fclose(fp);

      if ((cp = strchr(alias,';')) != 0) {
        strcpy(cp,";-1");
        delete_file_versions(alias);
        }
      }
    }

  nosysprv();

  return(do_show_aliases());
}

static void out_list(c,f)
  const char *c;
  const SYS_FILTER_T *f;
{
  if (!f) return;
  strcpy(err_oline,"    "); err_oline_cat(c); err_oline_cat(": ");
  while (f) {
    err_oline_cat(f->sys_filtnam);
    f = f->sys_fnext;
    if (!f) put_line(err_oline,0,T_DISPLAY_LOOP);
    else {
      err_oline_cat(",");
      if ((strlen(err_oline) + strlen(f->sys_filtnam) + 2) > devcol) {
        put_line(err_oline,0,T_DISPLAY_LOOP);
        strcpy(err_oline,"        ");
        }
      }
    }
}

    
static int dssys()
{
  SYS_ENTRY_T *tmp;
  char *cp;

  if (!sysfile) {
    err_line("SHOW SYS - no local aliases defined");
    return(0);
    }

  start_header(T_DISPLAY_LOOP,SHOW_SYS);
  put_line("NEWS - System Configuration (NEWS.SYS)",0,T_DISPLAY_LOOP);
  end_header(T_DISPLAY_LOOP);

  for (tmp=sysfile; tmp; tmp=tmp->sys_enext) {
    put_line("",0,T_DISPLAY_LOOP);
    strcpy(err_oline,"Node: "); err_oline_cat(tmp->sys_nodename);
    if (local_filter == tmp->sys_f) err_oline_cat(" (LOCAL NODE)");
    put_line(err_oline,0,T_DISPLAY_LOOP);
    if (tmp->sys_no) out_list("Path Filter",tmp->sys_no);
    if (tmp->sys_f) out_list("Newsgroups Accepted",tmp->sys_f);
    else put_line("    Newsgroups Accepted: *",0,T_DISPLAY_LOOP);
    if (tmp->sys_f == tmp->sys_d) 
      put_line("    Distributions Accepted: => Newsgroups",0,T_DISPLAY_LOOP);
    else if (tmp->sys_d) out_list("Distributions Accepted",tmp->sys_d);
    else put_line("    Distributions Accepted: *",0,T_DISPLAY_LOOP);
    if (tmp->sys_type && *(tmp->sys_type)) {
      strcpy(err_oline,"    Flags: "); err_oline_cat(tmp->sys_type);    
      cp = tmp->sys_type;
      if (*cp == 'b') {
        err_oline_cat("   (Batch-File");
        if (*(cp + 1) == 'n') err_oline_cat(", N-wrapped");
        err_oline_cat(")");
        }
      else if (*cp == 'm') {
        err_oline_cat("   (Message-File");
        if (*(cp + 1) == 'n') err_oline_cat(", N-wrapped");
        err_oline_cat(")");
        }
      else if (*cp == 'n') {
        err_oline_cat("   (Message-ID-File");
        if (*(cp + 1) == 'x') err_oline_cat(", Indexed-Access");
        err_oline_cat(")");
        }
      else if (*cp == 'f') {
        err_oline_cat("   (File-Specification-List-Batch-File");
        if (*(cp + 1) == 'c') err_oline_cat(", File-Size-Included");
        err_oline_cat(")");
        }
      put_line(err_oline,0,T_DISPLAY_LOOP);
      }
    if (tmp->sys_file && *(tmp->sys_file)) {
      strcpy(err_oline,"    Spool Area: "); err_oline_cat(tmp->sys_file);    
      put_line(err_oline,0,T_DISPLAY_LOOP);
      }
    }
  put_line("",1,T_DISPLAY_LOOP);
  return(0);
}

int do_show_sys()
{
  if (nntp_client) return(0);

  if (!readsys() && (textptr.display_code != SHOW_SYS)) {
    err_line("SHOW SYS - no local sys config file located");
    return(0);
    }
  return(unwind_display(I_DISPLAY_LOOP,dssys));
}
