/*
  users_file routines for gtic
*/

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

#include "config.h"

list_t *users;

struct flag_tab user_flag_tab[]={
{USER_HOLD,		"hold"},
{USER_AUTOCREATE,	"autocreate"},
{USER_PAUSE,		"pause"},
{USER_AUTO_RW,		"auto_rw"},
{USER_AUTO_RO,		"auto_ro"},
{USER_NO_TICS,		"no_tics"},
{0,			NULL}
};

void readusers(void)
{
  FILE *fp; char buff1[BUFSIZE],buff2[BUFSIZE];
  user_t *cur; char *p,*p2;
  int linecnt=0;
  fp=fopen(users_file,"r");
  if(fp==NULL)
  {
    e_printf("unable to open users_file %s: ",users_file);
    perror("");
    abort2();
  }
  users=list_init();
  while(fgets(buff1,sizeof(buff1)-1,fp))
  {
    linecnt++;
    if(buff1[0]=='\r'||buff1[0]==0||buff1[0]=='\n'||buff1[0]=='#') continue;
    cur=xmalloc(sizeof(user_t));
    strcpy(buff2,buff1);
    p=strtok(buff2,DELIM);
    if(!p)
    {
      e_printf("%s - %d line, token #1 (address) absent",users_file,linecnt);
      abort2();
    }
		if (ftntonode(&(cur->addr),p,NULL))
		{
			e_printf("%s - %d line, \"%s\" is not a FTN addr",
				users_file,linecnt,p);
			abort2();
		}
/*printf("DEBUG: (users.c) %s\n",p);
*/
    p=strtok(NULL,DELIM);
    if(!p)
    {
      e_printf("%s - %d line, token #2 (password) absent",users_file,linecnt);
      abort2();
    }
/*printf("DEBUG: (users.c) %s\n",p);
*/
		cur->passwd=xstrcpy(p);

    p=strtok(NULL,DELIM);
    if(!p)
    {
      e_printf("%s - %d line, token #3 (group) absent",users_file,linecnt);
      abort2();
    }

    cur->groups=list_init();
    strcpy(buff1,p); /* [1] */

    /*
      strtok have internal variables and can't works with more than one
      strings. Parse buff1 later.
    */
    
    p=strtok(NULL,DELIM); /* last token [2] */

    /* parse [1] */
    p2=strtok(buff1,",");
    while(p2)
    {
      list_add(cur->groups,p2,NULL);
      p2=strtok(NULL,",");
    }

    /* parse [2] */
    cur->flags=0;
    if(p)
    {
      cur->flags=parse_list_with_flag_tab(users_file,linecnt,p,
	(struct flag_tab *)user_flag_tab,",");
    }
    nodetoftn(buff1,&(cur->addr)); /* address of user as key in userlist */
/*printf("DEBUG: readusers - %d line=%s, %s, %04X\n",linecnt,buff1,
cur->passwd,cur->flags);
*/
		list_add(users,buff1,cur);
  }

  fclose(fp);
}

void writeusers(void)
{
  int i,j; char new_path[PATH_MAX];
  FILE *fp; struct stat stat_buff;
  user_t *u; int no_comma;
  int stat_fail=FALSE;
  
  ass(users!=NULL);

  /* get uid,gid,mode for old users_file */
  if(stat(users_file,&stat_buff))
  {
    l_printf("Warning: unable to stat %s",users_file);
    stat_fail=TRUE;
  }
  
  /* make a backup copy of users_file */
  strcpy(new_path,users_file);
    strcat(new_path,".bak");
  if(rename(users_file,new_path))
    l_printf("Warning: unable to move %s to %s",users_file,new_path);

  /* try to create new users_file, restore backup if fail */
  fp=fopen(users_file,"w");
  if(fp==NULL)
  {
    e_printf("unable to create users_file %s, trying to restore backup",
    	users_file);
    if(rename(new_path,users_file))
      e_printf("unable to restore users file (%s to %s)",new_path,users_file);
    return;
  }

  /* restore permissions and uid/gid */
  fchmod(fileno(fp),stat_fail?0600:stat_buff.st_mode);
  if(stat_fail==FALSE)
    fchown(fileno(fp),stat_buff.st_uid,stat_buff.st_gid);


  /* write users list */
  for(i=0;i<list_head_max(users);i++)
  {
    u=list_get_entry(users,i);
    ass(u!=NULL);

    ass(u->passwd!=NULL);
    ass(u->groups!=NULL);

    fprintf(fp,"%s ",nodetoftn(NULL,&(u->addr)));
    fprintf(fp,"%s ",u->passwd);

    no_comma=TRUE;
    for(j=0;j<list_head_max(u->groups);j++)
    {
      if(no_comma==FALSE) fprintf(fp,",");
      no_comma=FALSE;
      fprintf(fp,"%s",(char *)list_get_key(u->groups,j));
    }

    fprintf(fp," ");
    write_flag_tab_to_FILE(fp,u->flags,(struct flag_tab*)&user_flag_tab);

    fprintf(fp,"\n");
  }
  ass(fclose(fp)==0);
}


syntax highlighted by Code2HTML, v. 0.9.1