/*-
 * Copyright (c) 1998-2008 DHIS, Dynamic Host Information System
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include "dhid.h"


struct conf_t *base=NULL;
extern int rport;

void off_nl(char *s) {

        while(*s!='\0' && *s!='\r' && *s!='\n') s++;
        *s='\0';
}

void strtolower(char *s) {

        while(*s!='\0') { *s=tolower(*s); s++; }
        return;
}

void free_conf(void) {

        struct conf_t *p;
	struct ser_t *sp;

        if(base!=NULL) {
        p=base->next;
#ifdef QRC
        if(base->atype==AQRC)
        {
        mpz_clear(base->authp);
        mpz_clear(base->authq);
        }
#endif
	sp=base->servers;
	while(sp!=NULL) {
	base->servers=base->servers->next;
	free(sp);
	sp=base->servers;
	}
        free(base);
        while(p!=NULL) {
                base=p;
                p=p->next;
#ifdef QRC
                if(base->atype==AQRC)
                {
                        mpz_clear(base->authp);
                        mpz_clear(base->authq);
                }
#endif
                free(base);
        }
        base=NULL;
        }
}

void read_conf(char *file) {

        FILE *fp;
        char line[1024];
        char str[64];

        free_conf();

        fp=fopen(file,"r");
        if(fp==NULL) { 
                syslog(LOG_ERR,"failed to read %s",file);
                exit(1);
        }

        while(fgets(line,1024,fp)!=NULL) {
        off_nl(line);
        if(!strcmp(line_entry(1,line),"{")) { /* found a record */
        struct conf_t *cp;
#ifdef  QRC
        char keyp[1024],keyq[1024];
        keyp[0]='\0';
        keyq[0]='\0';
#endif
        cp=base;
        if(base==NULL) {
        base=(struct conf_t *)malloc(sizeof(struct conf_t));
        if(base==NULL) {
                syslog(LOG_ERR,"Failed malloc for conf record");
                exit(255);
                } 
                cp=base;
        } else {
                cp=base;
                while(cp->next!=NULL) cp=cp->next;
		cp->next=(struct conf_t *)malloc(sizeof(struct conf_t));
                if(cp->next==NULL) {
                syslog(LOG_ERR,"Failed malloc for conf record");
                exit(255);
                } 
                cp=cp->next;
        }

        /* cp now points to a clear record */

        /* initialising cp */



        cp->id=0;
        cp->pass[0]='\0';
        cp->atype=0;
	cp->servers=NULL;
	cp->cserver=NULL;
        cp->sid=0;
	cp->laddr=0;
        cp->next=NULL;
        cp->refresh=0;
        cp->stage=POLL_STAGE;
        cp->timeout=-1;
        cp->on_cmd[0]='\0';
        cp->on_cmdp[0]='\0';
        cp->off_cmd[0]='\0';
        cp->off_cmdp[0]='\0';

        while(fgets(line,1024,fp)!=NULL) {
        off_nl(line);
        strtolower(line);
        if(!strcmp(line_entry(1,line),"}")) break; /* end of record */


        if(!strcmp(line_entry(1,line),"hostid"))
                cp->id=atoi(line_entry(2,line));

        if(!strcmp(line_entry(1,line),"hostpass")) {
                strcpy(cp->pass,line_entry(2,line));
                cp->atype=APASS;
        }
        if(!strcmp(line_entry(1,line),"isaddr")) {
		char str2[256];
		char str3[256];
                struct ser_t *sp;


                if(cp->servers==NULL) {
                cp->servers=(struct ser_t *)malloc(sizeof(struct ser_t));
                if(cp->servers==NULL) continue;
                sp=cp->servers;
                } else {
                sp=cp->servers;
                while(sp->next!=NULL) sp=sp->next;
                sp->next=(struct ser_t *)malloc(sizeof(struct ser_t));
                if(sp->next==NULL) continue;
                sp=sp->next;
                }
                sp->next=NULL;
		sp->port=DEF_ISPORT;
		sp->addr=0;
		sp->hostname[0]='\0';
	
		strcpy(str2,line_entry(2,line));

		strcpy(str,dot_entry(1,str2));
		strcpy(str3,dot_entry(2,str2));

                if(isdigit(str[0])) sp->addr=inet_addr(str);
		else strcpy(sp->hostname,str);
		if(str3[0]!='\0') sp->port=atoi(str3);
        }
        if(!strcmp(line_entry(1,line),"refresh")) {
                strcpy(str,line_entry(2,line));
                cp->refresh=atoi(str);
		if(cp->refresh<60) cp->refresh=60;
        }
        if(!strcmp(line_entry(1,line),"oncmd")) {
                strcpy(cp->on_cmd,line_entry(2,line));
                strcpy(cp->on_cmdp,line_ptr(3,line));
        }
        if(!strcmp(line_entry(1,line),"offcmd")) {
                strcpy(cp->off_cmd,line_entry(2,line));
                strcpy(cp->off_cmdp,line_ptr(3,line));
        }


        if(!strcmp(line_entry(1,line),"authp")) {
#ifdef  QRC
                strcat(keyp,line_entry(2,line));
                cp->atype=AQRC;
#else
                syslog(LOG_ERR,"QRC authentication not available in this client"
);
                syslog(LOG_ERR,"Please compile QRC support. Exiting ...");
                exit(255);
#endif
        }
       if(!strcmp(line_entry(1,line),"authq")) {
#ifdef  QRC
                strcat(keyq,line_entry(2,line));
                cp->atype=AQRC;
#else
                syslog(LOG_ERR,"QRC authentication not available in this client"
);
                syslog(LOG_ERR,"Please compile QRC support. Exiting ...");
                exit(255);
#endif
        }

        } /* end of record while */

        /* Parameter sanity check */

        if(cp->atype==0) {
                syslog(LOG_ERR,"Failed to read authentication key");
                exit(255);
        }

        if(cp->atype==APASS && cp->pass[0]=='\0') {
                syslog(LOG_ERR,"Failed to read text authentication key");
                exit(255);
        }

#ifdef  QRC
        if(cp->atype==AQRC && (keyp[0]=='\0' || keyq[0]=='\0')) {
                syslog(LOG_ERR,"Failed to read QRC authentication keys");
                exit(255);
        }
#endif

        if(cp->id==0) {
                syslog(LOG_ERR,"Failed to read host id");
                exit(255);
        }

        if(cp->servers==NULL) {
                syslog(LOG_ERR,"Failed to read remote server address");
                exit(255);
        }

#ifdef  QRC
        if(cp->atype==AQRC) {
        mpz_init(cp->authp);
        mpz_init(cp->authq);
        mpz_set_str(cp->authp,keyp,10);
        mpz_set_str(cp->authq,keyq,10);
        }
#endif

        } /* close record */
        } /* close file read while */
        fclose(fp);

        if(base==NULL) {
        syslog(LOG_ERR,"No records configured in dhid.conf ... exiting ...");
        exit(255);
        }
        return;
}


char *line_entry(int idx,char *buff) {

        static char b2[1024],*pb2;
        int i;

        idx--;
        b2[0]='\0';
        pb2=b2;

        while((*buff==' ' || *buff=='\t') && *buff!='\0' && *buff!='\n')
                buff++;
        if(*buff=='\0' || *buff=='\n') return(b2);

        for(i=0;i<idx;i++) {
                while(*buff!=' ' && *buff!='\t' && *buff!='\0' &&
                        *buff!='\n') buff++;
                if(*buff=='\0' || *buff=='\n') return(b2);
                while((*buff==' ' || *buff=='\t') && *buff!='\0' && *buff!='\n')
                        buff++;
                if(*buff=='\0' || *buff=='\n') return(b2);
        }
        while(*buff!=' ' && *buff!='\t' && *buff!='\0' && *buff!='\n') {
                *pb2 = *buff;
                buff++;
                pb2++;
        }
        *pb2 = '\0';
        return(b2);
}

char *dot_entry(int idx,char *buff) {

        static char b2[1024],*pb2;
        int i;

        idx--;
        b2[0]='\0';
        pb2=b2;
        for(i=0;i<idx;i++) {
                while(*buff!=':' && *buff!='\0') buff++;
                if(*buff==':') buff++;
        }
        if(*buff=='\0') return(b2);
        while(*buff!=':' && *buff!='\0') {
                *pb2 = *buff;
                buff++;
                pb2++;
        }
        *pb2 = '\0';
        return(b2);
}
char *line_ptr(int idx,char *buff) {

        int i;
        static char m[1];


        idx--;
        m[0]='\0';

        while((*buff==' ' || *buff=='\t') && *buff!='\0' && *buff!='\n')
                buff++;
        if(*buff=='\0' || *buff=='\n') return(m);

        for(i=0;i<idx;i++) {
                while(*buff!=' ' && *buff!='\t' && *buff!='\0' &&
                        *buff!='\n') buff++;
                if(*buff=='\0' || *buff=='\n') return(m);
                while((*buff==' ' || *buff=='\t') && *buff!='\0' && *buff!='\n')
                        buff++;
                if(*buff=='\0' || *buff=='\n') return(m);
        }
        return(buff);
}


