/*


                              fc v1.01

                            25 June 1993

Allows other sites to change their  newsfeed without interaction of system
administrator. Method applied is email based, where commands are placed in
the body of the message. Written for AmigaUUCP V1.16.


Author Info:

Name:     Stefan G. Berg

Address:  523 Kerry Dr
          Bloomington, IN47408
          U.S.A.

Phone:    (812) 333-1963

Usenet:   sgberg@charon.bloomington.in.us
Internet: sgberg@ucs.indiana.edu
GEnie:    S.BERG5


*/





/* include statements */
/**********************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>





/* preprocessor definitions */
/****************************/

#define TRUE  1
#define FALSE 0
#define BUFSIZE 256
#define FC_CONFIG_VARNAME "FC_CONFIG"
#define DEFAULT_FC_CONFIG "UULIB:fc.config"
#define VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.+-_!*"
#define WILD_CHARS "*"





/* structure, type declarations and global definitions */
/*******************************************************/

typedef char boolean;
struct node {
  char *newsgroup;
  struct node *next;
};
struct head { /* contains info about system's feed file */
  struct node *add;         /* list of newsgroups to be added */
  struct node *remove;      /* list of newsgroups to be removed */
  struct node *old;         /* original list of changable newsgroups */
  struct node *add_last;       /* (next three) pointers to last element of above */
  struct node *remove_last;
  struct node *old_last;
  struct node *restricted;  /* list of unchangable newsgroups as given in configuration */
  struct node *fixed;       /* original list of unchangable newsgroups */
  char *site;               /* nodename of site which is being changed */
  boolean send;             /* flag for SEND command */
  boolean help;             /* flag for HELP command */
  boolean new;              /* flag for NEW command */
  boolean wildcards;        /* flag if wildcards are allowed */
};
struct node2 {
  char *from;               /* exact email address */
  char *site;               /* nodename */
  char *password;           /* password (optional) */
  boolean wildcards;        /* flag for wildcards */
  struct node2 *next;
};
struct head2 { /* contains info about systems listed in configuration file */
  struct node2 *names;
};
char buf1[BUFSIZE], buf2[BUFSIZE], buf3[BUFSIZE], buf4[BUFSIZE], buf5[BUFSIZE];
char *SYSFILE=NULL;
char *LOCALEMAIL=NULL;      /* email address for local system administrator */
char *TMPFILE=NULL;         /* temporary filename */
char *NEWSYSFILE=NULL;      /* temporary name of new Sys file */
char *BAKSYSFILE=NULL;      /* name of backup Sys file */
char *HELPFILE=NULL;        /* name of help file */
struct head2 usr_names;
struct head usr_input;
char *password;             /* contains password from Subject: header line */





/* version string */
/******************/
static char *VerString="$VER: fc 1.01 (25.6.93)";





/* function declarations */
/*************************/

          /* return the system name which does the request, get password
             and move stdout forward to start of message body */
char *scan_header(void);
          /* scan message body and fill structure containing user input */
boolean scan_msgbody(void);
          /* read in `system's entry in SYSFILE */
boolean scan_sysfile(FILE *sysfile, char *sysname);
          /* remove ADD and REMOVE instructions which cannot be executed */
boolean cleanup_input(void);
          /* make changes in sys record */
boolean change_sys(void);
          /* update SYSFILE */
boolean update_sysfile(FILE *sysfile, FILE *newsysfile, char *sysname);
          /* notify local and remote system about changes */
boolean notify(char *from_address, char *sysname);
          /* read configuration file */
boolean readcf(void);
          /* scan data from config file for system */
char *scan_config(char *from_address);
          /* verify if a newsgroup contains valid characters */
boolean check_newsgroup(char *newsgroup, boolean wildcards);
          /* check if a newsgroup is restricted */
boolean is_restricted(char *newsgroup);





/* main */
/********/

int main(int argc, char *argv[]) {

  FILE *sysfile, *newsysfile;
  char *from_address;
  char *sys_name;
  struct head *usr_input;

  if(!readcf())                        /* read contents of configuration file */
    exit(20);

  if((from_address=scan_header()) == NULL)             /* scan message header */
    exit(21);

  if(!scan_msgbody())                   /* read in commands from message body */
    exit(22);

  if((sys_name=scan_config(from_address)) == NULL)     /* find site in config */
    exit(23);

  sysfile = fopen(SYSFILE, "r");
  if(sysfile == NULL)
    exit(24);
  if(!scan_sysfile(sysfile, sys_name))           /* read contents of Sys file */
    exit(25);
  fclose(sysfile);

  if(!cleanup_input())                      /* verify that commands are valid */
    exit(26);

  if(!change_sys())         /* make changes to internal structure of Sys file */
    exit(27);

  sysfile = fopen(SYSFILE, "r");
  if(sysfile == NULL)
    exit(28);
  newsysfile = fopen(NEWSYSFILE, "w");
  if(newsysfile == NULL)
    exit(29);
  if(!update_sysfile(sysfile, newsysfile, sys_name))     /* write out changes */
    exit(30);
  fclose(sysfile);
  fclose(newsysfile);

  remove(BAKSYSFILE);              /* make Sys file current and create backup */
  if(rename(SYSFILE, BAKSYSFILE) != 0)
    exit(31);
  if(rename(NEWSYSFILE, SYSFILE) != 0)
    exit(32);

  if(!notify(from_address, sys_name))           /* notify sites about changes */
    exit(33);

  exit(0);

}





/* support functions */
/*********************/


/* return the system name which does the request, get password
   and move stdout forward to start of message body */
char *scan_header(void) {
  char *from_address;
  int i, len=0;
  char *tmp;

  /* scan for From: line */
  while( fgets(buf1,BUFSIZE,stdin)!=NULL && strncmp("From: ",buf1,6)!=0 )
    ;
  if(feof(stdin))
    return NULL;

  /* determine types of comments in system name */
  for(i=0; i<BUFSIZE && buf1[i]!=0 && buf1[i]!='<'; i++)
    ;
  if(buf1[i]!='<')
    i=4;
  else if(buf1[i]==0 || i>=BUFSIZE)
    return NULL;

  if(sscanf(&buf1[++i], "%s",buf2) != 1)
    return NULL;
  len=strlen(buf2);
  if(buf2[len-1] == '>')
    len--;

  /* get system name */
  from_address = (char *) malloc(len+1);
  if(from_address==NULL)
    return NULL;
  strncpy(from_address, buf2, len);
  from_address[len]=0;

  /* scan for Subject: line */
  while( fgets(buf1,BUFSIZE,stdin)!=NULL && strncmp("Subject: ",buf1,9)!=0 )
    ;
  if(feof(stdin))
    return NULL;

  if((i=sscanf(buf1, "%*s %s", buf2)) != 1)
    password = NULL;
  else {
    password = strdup(buf2);
    if(password == NULL)
      return NULL;
  }

  /* go to beginning of message body */
  while( fgets(buf1,BUFSIZE,stdin)!=NULL && buf1[0]!='\n' )
    ;

  return from_address;

}


/* scan message body and fill structure containing user input */
boolean scan_msgbody(void) {
  char command;
  boolean exists,end_flag=FALSE;
  struct node *tmp;
  int len;

  usr_input.add = NULL;
  usr_input.remove = NULL;
  usr_input.send = FALSE;
  usr_input.help = FALSE;
  usr_input.add_last = NULL;
  usr_input.remove_last = NULL;
  usr_input.old = NULL;
  usr_input.old_last = NULL;
  usr_input.site = NULL;
  usr_input.new = FALSE;
  usr_input.fixed = NULL;

  while( fgets(buf1,BUFSIZE,stdin)!=NULL && !end_flag ) {

    len = sscanf(buf1, "%s %s", buf2, buf3);

    switch(toupper(buf2[0])) {

    case 'A' : /* ADD */
      if( len==2 && check_newsgroup(buf3,TRUE) ) {
        exists = FALSE; /* test if newsgroup is already being added */
        tmp = usr_input.add;
        while( tmp!=NULL && !exists ) {
          if(stricmp(tmp->newsgroup,buf3) == 0)
            exists = TRUE;
          tmp = tmp->next;
        }

        if( !exists && !is_restricted(buf3) ) { /* add newsgroup to add-list */
          if(usr_input.add == NULL) { /* add to front */
            usr_input.add = malloc(sizeof(struct node));
            if(usr_input.add == NULL)
              return FALSE;
            usr_input.add_last = usr_input.add;
          } else { /* add to back */
            usr_input.add_last->next = malloc(sizeof(struct node));
            if(usr_input.add_last->next == NULL)
              return FALSE;
            usr_input.add_last = usr_input.add_last->next;
          }
          usr_input.add_last->next = NULL;
          usr_input.add_last->newsgroup = malloc(strlen(buf3)+1);
          if(usr_input.add_last->newsgroup == NULL)
            return FALSE;
          strcpy(usr_input.add_last->newsgroup, buf3);
        }
      }
      break;

    case 'R' : /* REMOVE */
      if( len==2 && check_newsgroup(buf3,TRUE) ) {
        exists = FALSE; /* test if newsgroup is already being removed */
        tmp = usr_input.remove;
        while( tmp!=NULL && !exists ) {
          if(stricmp(tmp->newsgroup,buf3) == 0)
            exists = TRUE;
          tmp = tmp->next;
        }
        if( !exists && !is_restricted(buf3) ) { /* add newsgroup to remove-list */
          if(usr_input.remove == NULL) {
            usr_input.remove = malloc(sizeof(struct node));
            if(usr_input.remove == NULL)
              return FALSE;
            usr_input.remove_last = usr_input.remove;
          } else {
            usr_input.remove_last->next = malloc(sizeof(struct node));
            if(usr_input.remove_last->next == NULL)
              return FALSE;
            usr_input.remove_last = usr_input.remove_last->next;
          }
          usr_input.remove_last->next = NULL;
          usr_input.remove_last->newsgroup = malloc(strlen(buf3)+1);
          if(usr_input.remove_last->newsgroup == NULL)
            return FALSE;
          strcpy(usr_input.remove_last->newsgroup, buf3);
        }
      }
      break;

    case 'L' : /* LIST */
      usr_input.send = TRUE;
      break;

    case 'H' : /* HELP */
      usr_input.help = TRUE;
      break;

    case 'S' : /* SITE */
      if(len == 2) {
        free(usr_input.site);
        usr_input.site = malloc(strlen(buf3)+1);
        if(usr_input.site == NULL)
          return FALSE;
        strcpy(usr_input.site, buf3);
      }
      break;

    case 'N' : /* NEW */
      usr_input.new = TRUE;
      break;

    case 'E' : /* END */
      end_flag = TRUE;
      break;
    }

  }

  return TRUE;

}


/* read in `system's entry in SYSFILE */
boolean scan_sysfile(FILE *sysfile, char *sysname) {
  char *tmp, *next_group;
  boolean flag = TRUE;
  int nextgroup;
  struct node *tmp_node;

  /* find system name in SYSFILE */
  while( flag && fgets(buf1,BUFSIZE,sysfile)!=NULL ) {
    strcpy(buf3, buf1);
    sscanf(buf3, "%s", buf2);
    tmp = strchr(buf2, ':');
    if(tmp != NULL) {
      *tmp = '\0';
      if(stricmp(buf2, sysname) == 0)
        flag = FALSE;
    }
  }

  if(flag)
    return FALSE;
  tmp = strchr(buf1, ':');
  tmp++;
  flag = TRUE;

  do {
    tmp += strspn(tmp, " \t\n\r\v\f"); /* skip white space */
    if(*tmp == '\0') {
      flag = FALSE;
      continue;
    }

    if(*tmp == '\\') {
      if(fgets(buf1,BUFSIZE,sysfile)==NULL)
        flag = FALSE;
      else
        tmp = buf1;
      continue;
    }

    if(*tmp == '#') {
      flag = FALSE;
      continue;
    }

    if(*tmp == ',') {
      tmp++;
      continue;
    }

    nextgroup = strcspn(tmp, " \t\n\r\v\f,");
    strncpy(buf2, tmp, nextgroup);
    buf2[nextgroup]='\0';
    tmp += nextgroup;

    /* add newsgroup */
    if(is_restricted(buf2)) { /* add newsgroup to fixed structure */
      tmp_node = malloc(sizeof(struct node));
      if(tmp_node == NULL)
        return FALSE;
      tmp_node->next = usr_input.fixed;
      usr_input.fixed = tmp_node;
      tmp_node->newsgroup = malloc(strlen(buf2)+1);
      if(tmp_node->newsgroup == NULL)
        return FALSE;
      strcpy(tmp_node->newsgroup, buf2);
    } else { /* add newsgroup to normal structure */
      if(usr_input.old == NULL) {
        usr_input.old = malloc(sizeof(struct node));
        if(usr_input.old == NULL)
          return FALSE;
        usr_input.old_last = usr_input.old;
      } else {
        usr_input.old_last->next = malloc(sizeof(struct node));
        if(usr_input.old_last->next == NULL)
          return FALSE;
        usr_input.old_last = usr_input.old_last->next;
      }
      usr_input.old_last->next = NULL;
      usr_input.old_last->newsgroup = malloc(strlen(buf2)+1);
      if(usr_input.old_last->newsgroup == NULL)
        return FALSE;
      strcpy(usr_input.old_last->newsgroup, buf2);
    }

  } while(flag);

  return TRUE;

}


/* remove ADD and REMOVE instructions which cannot be executed */
boolean cleanup_input(void) {
  struct node *sysptr, *chkptr, *preptr;

  /* verify add's */
  if(!usr_input.new) { /* keep all adds if we erase original feed */
    chkptr = usr_input.add;
    preptr = NULL;
    while(chkptr != NULL) {
      sysptr = usr_input.old;
      while( sysptr!=NULL && stricmp(chkptr->newsgroup,sysptr->newsgroup)!=0 )
        sysptr = sysptr->next;
      if(sysptr!=NULL || !check_newsgroup(chkptr->newsgroup,usr_input.wildcards)) {
        if(preptr == NULL) {
          usr_input.add = chkptr->next;
          if(usr_input.add_last == chkptr)
            usr_input.add_last = NULL;
          free(chkptr);
          chkptr = usr_input.add;
        } else {
          if(chkptr->next == NULL)
            usr_input.add_last = preptr;
          preptr->next = chkptr->next;
          free(chkptr);
          chkptr = preptr->next;
        }
      } else {
        preptr = chkptr;
        if(chkptr != NULL)
          chkptr = chkptr->next;
      }
    }
  }

  /* verify remove's */
  chkptr = usr_input.remove;
  preptr = NULL;
  while(chkptr != NULL) {
    sysptr = usr_input.old;
    while( sysptr!=NULL && stricmp(chkptr->newsgroup,sysptr->newsgroup)!=0 )
      sysptr = sysptr->next;
    if(sysptr==NULL) {
      if(preptr == NULL) {
        usr_input.remove = chkptr->next;
        if(usr_input.remove_last == chkptr)
          usr_input.remove_last = NULL;
        free(chkptr);
        chkptr = usr_input.remove;
      } else {
        if(chkptr->next == NULL)
          usr_input.remove_last = preptr;
        preptr->next = chkptr->next;
        free(chkptr);
        chkptr = preptr->next;
      }
    } else {
      preptr = chkptr;
      if(chkptr != NULL)
        chkptr = chkptr->next;
    }
  }

  return TRUE;

}


/* make changes in sys record */
boolean change_sys(void) {
  struct node *sysptr, *removeptr, *preptr;

  /* check if news feed has to be erased */
  if(usr_input.new)
    usr_input.old = NULL;

  /* add fixed newsgroups */
  if(usr_input.fixed != NULL) {
    preptr = usr_input.fixed;
    while(preptr->next != NULL)
      preptr = preptr->next;
    if(usr_input.old == NULL)
      usr_input.old_last = preptr;
    else
      preptr->next = usr_input.old;
    usr_input.old = usr_input.fixed;
  }

  /* add newsgroups */
  if(usr_input.old == NULL)
    usr_input.old = usr_input.add;
  else
    if(usr_input.old_last == NULL)
      return FALSE;
    else
      usr_input.old_last->next = usr_input.add;
  usr_input.old_last = usr_input.add_last;

  /* remove newsgroups */
  sysptr = usr_input.old;
  preptr = NULL;
  while(sysptr != NULL) {
    removeptr = usr_input.remove;
    while( removeptr!=NULL && stricmp(removeptr->newsgroup,sysptr->newsgroup)!=0 )
      removeptr = removeptr->next;
    if(removeptr!=NULL) {
      if(preptr == NULL) {
        usr_input.old = sysptr->next;
        if(usr_input.old_last == sysptr)
          usr_input.old_last = NULL;
        free(sysptr);
        sysptr = usr_input.old;
      } else {
        if(sysptr->next == NULL)
          usr_input.old_last = preptr;
        preptr->next = sysptr->next;
        free(sysptr);
        sysptr = preptr->next;
      }
    } else {
      preptr = sysptr;
      if(sysptr != NULL)
        sysptr = sysptr->next;
    }
  }

  return TRUE;

}


/* update SYSFILE */
boolean update_sysfile(FILE *sysfile, FILE *newsysfile, char *sysname) {
  char *tmp1, *tmp2;
  boolean flag;
  struct node *next_ptr;

  /* find system name in SYSFILE */
  while( flag && fgets(buf1,BUFSIZE,sysfile)!=NULL ) {
    strcpy(buf3, buf1);
    sscanf(buf3, "%s", buf2);
    tmp1 = strchr(buf2, ':');
    if(tmp1 != NULL) {
      *tmp1 = '\0';
      if(stricmp(buf2, sysname) == 0)
        flag = FALSE;
      else
        fputs(buf1, newsysfile);
    } else
      fputs(buf1, newsysfile);
  }

  /* find end of feed information for `system' */
  flag = TRUE;
  while( flag && fgets(buf1,BUFSIZE,sysfile)!=NULL ) {
    tmp1 = strchr(buf1, '#');
    tmp2 = strchr(buf1, '\\');
    if( tmp2==NULL || tmp1!=NULL && tmp1<tmp2 )
      flag = FALSE;
  }

  /* write system's newsfeedto newsysfile */
  if(usr_input.old == NULL)
    fprintf(newsysfile, "%s:\n", sysname);
  else
    fprintf(newsysfile, "%s:\\\n", sysname);
  next_ptr = usr_input.old;
  while(next_ptr != NULL) {
    if(next_ptr->next == NULL)
      fprintf(newsysfile, " %s\n", next_ptr->newsgroup);
    else
      fprintf(newsysfile, " %s,\\\n", next_ptr->newsgroup);
    next_ptr = next_ptr->next;
  }

  /* make sure there is a blank line before next entry */
  if( fgets(buf1,BUFSIZE,sysfile) != NULL)
    if(buf1[0] != '\n') {
      fprintf(newsysfile, "\n");
      fputs(buf1, newsysfile);
    } else
      fputs(buf1, newsysfile);

  /* copy remainder of sysfile to newsysfile */
  while( fgets(buf1,BUFSIZE,sysfile)!=NULL )
    fputs(buf1, newsysfile);

  return TRUE;

}


/* notify local and remote system about changes */
boolean notify(char *from_address, char *sysname) {
  FILE *tmpfile;
  struct node *next_ptr;

  if((tmpfile=fopen(TMPFILE,"w")) == NULL)
    return FALSE;

  fprintf(tmpfile, "Changes to newsfeed for system: %s\n\n", sysname);

  if(usr_input.new)
    fprintf(tmpfile, "Newsfeed was erased.\n\n");

  if(usr_input.add != NULL)
    fprintf(tmpfile, "Added Newsgroups:\n");
  next_ptr = usr_input.add;
  while(next_ptr != NULL) {
    fprintf(tmpfile, " %s\n", next_ptr->newsgroup);
    next_ptr = next_ptr->next;
  }
  fprintf(tmpfile, "\n");

  if(usr_input.remove != NULL)
    fprintf(tmpfile, "Removed Newsgroups:\n");
  next_ptr = usr_input.remove;
  while(next_ptr != NULL) {
    fprintf(tmpfile, " %s\n", next_ptr->newsgroup);
    next_ptr = next_ptr->next;
  }
  fprintf(tmpfile, "\n");

  if(usr_input.help)
    fprintf(tmpfile, "Help is sent separately.\n\n");

  if(usr_input.send) {
    fprintf(tmpfile, "List of newsgroups currently batched for %s.\n", sysname);
    next_ptr = usr_input.old;
    while(next_ptr != NULL) {
      fprintf(tmpfile, "%s\n", next_ptr->newsgroup);
      next_ptr = next_ptr->next;
    }
  }

  fclose(tmpfile);

  if(LOCALEMAIL == NULL)
    sprintf(buf1, "sendmail <%s -raw -f feed-change -s \"changes to your newsfeed\" -R \"automatic message\" -t %s >NIL:", TMPFILE, from_address);
  else
    sprintf(buf1, "sendmail <%s -raw -b %s -f feed-change -s \"changes to your newsfeed\" -R \"automatic message\" -t %s >NIL:", TMPFILE, LOCALEMAIL, from_address);
  if(system(buf1) != 0)
    return FALSE;
  if(remove(TMPFILE) != 0)
    return FALSE;

  if(usr_input.help) {
    sprintf(buf1, "sendmail <%s -raw -f feed-change -s \"help about feed-change\" -R \"automatic message\" -t %s >NIL:", HELPFILE, from_address);
    if(system(buf1) != 0)
      return FALSE;
  }

  return TRUE;

}


/* read configuration file */
boolean readcf(void) {
  char *cf_filename, *tmp;
  FILE *cf_file;
  int args;
  struct node *tmp_node;
  struct node2 *tmp_node2;

  usr_input.restricted = NULL;

  if((cf_filename=getenv(FC_CONFIG_VARNAME)) == NULL)
    cf_filename=DEFAULT_FC_CONFIG;

  cf_file = fopen(cf_filename, "r");
  if(cf_file == NULL)
    return FALSE;

  while( fgets(buf1,BUFSIZE,cf_file)!=NULL ) {
    strcpy(buf3, buf1);
    if(sscanf(buf3, "%s", buf2) != 1)
      continue;

    if(*buf2 == '#') {
      continue;

    } else if(stricmp(buf2, "LOCAL-RECIPIENT") == 0) {
      free(LOCALEMAIL);
      if(sscanf(buf1, "%*s %s", buf3)!=1)
        return FALSE;
      LOCALEMAIL = malloc(strlen(buf3)+1);
      if(LOCALEMAIL == NULL)
        return FALSE;
      strcpy(LOCALEMAIL, buf3);

    } else if(stricmp(buf2, "SYSFILE") == 0) {
      free(SYSFILE);
      if(sscanf(buf1, "%*s %s", buf3)!=1)
        return FALSE;
      SYSFILE = malloc(strlen(buf3)+1);
      if(SYSFILE == NULL)
        return FALSE;
      strcpy(SYSFILE, buf3);
 
    } else if(stricmp(buf2, "TMPFILE") == 0) {
      free(TMPFILE);
      if(sscanf(buf1, "%*s %s", buf3)!=1)
        return FALSE;
      TMPFILE = malloc(strlen(buf3)+1);
      if(TMPFILE == NULL)
        return FALSE;
      strcpy(TMPFILE, buf3);

    } else if(stricmp(buf2, "HELPFILE") == 0) {
      free(HELPFILE);
      if(sscanf(buf1, "%*s %s", buf3)!=1)
        return FALSE;
      HELPFILE = malloc(strlen(buf3)+1);
      if(HELPFILE == NULL)
        return FALSE;
      strcpy(HELPFILE, buf3);

    } else if(stricmp(buf2, "SITE") == 0) {
      args = sscanf(buf1, "%*s %s %s %s %s", buf2, buf3, buf4, buf5);
      if(args < 3)
        return FALSE;
      tmp_node2 = malloc(sizeof(struct node2));
      if(tmp_node2 == NULL)
        return FALSE;
      tmp_node2->next = usr_names.names;
      tmp_node2->from = malloc(strlen(buf2)+1); /* get address */
      if(tmp_node2->from == NULL)
        return FALSE;
      strcpy(tmp_node2->from, buf2);
      tmp_node2->site = malloc(strlen(buf3)+1); /* get nodename */
      if(tmp_node2->site == NULL)
        return FALSE;
      strcpy(tmp_node2->site, buf3);
      if(toupper(buf4[0]) == 'N') /* get wildcard permission field */
        tmp_node2->wildcards = FALSE;
      else
        tmp_node2->wildcards = TRUE;
      if(args == 4) { /* get password if present */
        tmp_node2->password = malloc(strlen(buf5)+1);
        if(tmp_node2->password == NULL)
          return FALSE;
        strcpy(tmp_node2->password, buf5);
      } else
        tmp_node2->password = NULL;
      usr_names.names = tmp_node2;

    } else if(stricmp(buf2, "RESTRICTED") == 0) {
      args = sscanf(buf1, "%*s %s", buf3);
      if(args != 1)
        return FALSE;
      tmp_node = malloc(sizeof(struct node));
      if(tmp_node == NULL)
        return FALSE;
      tmp_node->next = usr_input.restricted;
      tmp_node->newsgroup = malloc(strlen(buf3)+1);
      if(tmp_node->newsgroup == NULL)
        return FALSE;
      strcpy(tmp_node->newsgroup, buf3);
      usr_input.restricted = tmp_node;
    }

  }

  fclose(cf_file);

  /* default values */
  if(SYSFILE == NULL)
    SYSFILE = "UULIB:Sys";
  if(TMPFILE == NULL)
    TMPFILE = "T:UUCP_fc";

  /* create new and backup sys filenames */
  NEWSYSFILE = malloc(strlen(SYSFILE)+5);
  BAKSYSFILE = malloc(strlen(SYSFILE)+5);
  if(NEWSYSFILE==NULL || BAKSYSFILE==NULL)
    return FALSE;
  strcpy(NEWSYSFILE, SYSFILE);
  tmp = NEWSYSFILE+strlen(SYSFILE);
  *(tmp++) = '.';
  *(tmp++) = 'n';
  *(tmp++) = 'e';
  *(tmp++) = 'w';
  *tmp     = '\0';
  strcpy(BAKSYSFILE, SYSFILE);
  tmp = BAKSYSFILE+strlen(SYSFILE);
  *(tmp++) = '.';
  *(tmp++) = 'b';
  *(tmp++) = 'a';
  *(tmp++) = 'k';
  *tmp     = '\0';

  return TRUE;

}


/* scan data from config file for system */
char *scan_config(char *from_address) {
  struct node2 *tmp;
  boolean flag=TRUE;

  tmp = usr_names.names;

  while(tmp!=NULL && flag) {
    if(stricmp(tmp->from,from_address)==0) {
      if(usr_input.site==NULL ||
         usr_input.site!=NULL && stricmp(usr_input.site,tmp->site)==0) {
        if(tmp->password == NULL) {
          usr_input.wildcards = tmp->wildcards;
          return tmp->site;
        }
        if(stricmp(password,tmp->password)==0) {
          usr_input.wildcards = tmp->wildcards;
          return tmp->site;
        }
      }
    }
    tmp = tmp->next;
  }

  return NULL;

}


/* verify if a newsgroup contains valid characters */
boolean check_newsgroup(char *newsgroup, boolean wildcards) {
  char valid[]=VALID_CHARS;
  char wild[]=WILD_CHARS;

  if( strspn(newsgroup,VALID_CHARS) != strlen(newsgroup))
    return FALSE;

  if( !wildcards && strcspn(newsgroup,WILD_CHARS)!=strlen(newsgroup) )
    return FALSE;

  return TRUE;

}


/* check if a newsgroup is restricted */
boolean is_restricted(char *newsgroup) {
  struct node *tmp;

  tmp = usr_input.restricted;

  while(tmp != NULL) {
    if(stricmp(tmp->newsgroup,newsgroup) == 0)
      return TRUE;
    tmp = tmp->next;
  }

  return FALSE;

}


