/*
 * sshchatd_config.c
 *
 * load/save the config information
 *
 * Author: Dario Rodriguez dario@softhome.net
 * This program is licensed under the terms of the GNU GPL v2.1+
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#include <dirent.h>

#include "sshchatd_config.h"

#define USERSBLOCK 128

cconfig *
cconfig_init(void)
{
        cconfig *conf;
        DIR *dir;
        struct dirent *e;
        int pass,count,total;
        int nblocks;
        if((conf=malloc(sizeof(cconfig)))==NULL)
                return(NULL);
        memset(conf,0,sizeof(cconfig));
        mkdir("users",0700);
        if((dir=opendir("users"))==NULL) {
                free(conf),conf=NULL;
                return(NULL);
        }
        for(pass=0,count=0;pass<=1;pass++,rewinddir(dir),total=count,count=0) {
                while((e=readdir(dir))!=NULL) {
                        if(e->d_type!=DT_DIR)
                                continue;
                        if(!(e->d_name[0]>='a' && e->d_name[0]<='z') &&
                           !(e->d_name[0]>='A' && e->d_name[0]<='Z'))
                                continue; /* usernames must start by a letter */
                        if(pass==0) {
                                count++;
                        } else if(count<total) {
                                if((conf->users[conf->numusers]=strdup(e->d_name))==NULL) {
                                        cconfig_free(conf),conf=NULL;
                                        return(NULL); /* insuf. mem. */
                                }
                                conf->numusers++;
                                count++;
                        }
                }
                if(pass==0) {
                        nblocks=((count+USERSBLOCK-1))/USERSBLOCK;
                        if(count>0 && (conf->users=malloc(sizeof(char *)*USERSBLOCK*nblocks))==NULL) {
                                closedir(dir),dir=NULL;
                                cconfig_free(conf),conf=NULL;
                                return(NULL); /* No users or insuf. mem. */
                        }
                        memset(conf->users,0,sizeof(char *)*USERSBLOCK*nblocks);
                        conf->sizeusers=USERSBLOCK*nblocks;
                }
        }
        return(conf);
}

void
cconfig_free(cconfig *conf)
{
        int i;
        if(conf==NULL)
                return;
        if(conf->users!=NULL) {
                for(i=0;i<conf->numusers;i++) {
                        if(conf->users[i]!=NULL)
                                free(conf->users[i]),conf->users[i]=NULL;
                }
                conf->numusers=0;
                conf->sizeusers=0;
                free(conf->users),conf->users=NULL;
        }
        free(conf),conf=NULL;
}