/*
    Tucnak - VHF contest log
    Copyright (C) 2002-2022  Ladislav Vaiz <ok1zia@nagano.cz>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

*/

#include "header.h"

#include "fifo.h"
#include "language2.h"
#include "main.h"
#include "ntpq.h"
#include "qsodb.h"
#include "tsdl.h"

#ifdef Z_UNIX

struct ntpq *ntpq = NULL;

struct ntpq *init_ntpq(){
	struct ntpq *ntpq;

	progress(VTEXT(T_INIT_NTP));		
	ntpq = g_new0(struct ntpq, 1);
	ntpq->buf = g_string_sized_new(1024);
	ntpq->good = 1;
	ntpq->timer = zselect_timer_new(zsel, 1000, ntpq_timer, ntpq);
	return ntpq;
}

void free_ntpq(struct ntpq *ntpq){
	progress(VTEXT(T_FREE_NTP));		
	if (ntpq->pid) kill(ntpq->pid, SIGTERM);
	if (ntpq->rfd>=0) close(ntpq->rfd);
	if (ntpq->timer) zselect_timer_kill(zsel, ntpq->timer);
	g_string_free(ntpq->buf, TRUE);
	g_free(ntpq);
}

void ntpq_timer(void *arg){
    int fds[2], i;
	struct ntpq *ntpq;
    //char errbuf[1024];
	
    /*dbg("ntpq_timer()\n");*/
	ntpq=(struct ntpq *)arg;
	ntpq->timer=0;
    if (pipe(fds)) zinternal("Can't create thread pipe");
/*	dbg("pipe=%d %d\n", fds[0], fds[1]);*/
	ntpq->rfd=fds[0];
    ntpq->pid=fork();
    if (ntpq->pid<0) {
        dbg("Can't fork for ntpq\n");
        return;
    }
    if (ntpq->pid==0){
        /* child */
        setenv("TERM", "dumb", 1);
        for (i=0;i<1024;i++) {
			if (i==fds[1]) continue;
			close(i);
		}
		open("/dev/null", O_RDONLY);
		if (dup(fds[1]) < 0) exit(-1);
		if (dup(fds[1]) < 0) exit(-1);
        execlp("ntpq", "ntpq", "-pn", NULL);
        char *c = z_strdup_strerror(errno);
        fprintf(stderr, " exec failed errno=%d %s\n", errno, c);
        g_free(c);
        exit(-1);
    }                  
    /* parent */
    ntpq->rfd=fds[0];
	close(fds[1]);
    zselect_set(zsel, ntpq->rfd, ntpq_read_handler, NULL, NULL, ntpq);
}


void ntpq_read_handler(void *arg){
    char s[1030];
    int ret,good;
    gchar *c, *d;
	struct ntpq *ntpq;

	ntpq=(struct ntpq *)arg;

/*	dbg("read...\n");*/
    ret=read(ntpq->rfd, s, 1024);
/*	dbg("read=%d\n", ret);*/
    //err=errno;
	if (ret<0){
/*        dbg("ntpq read error\n");*/
		zselect_set(zsel, ntpq->rfd, NULL, NULL, NULL, NULL);
		close(ntpq->rfd);
		ntpq->timer = zselect_timer_new(zsel, 50001, ntpq_timer, ntpq);
		return;
	}
    if (ret==0){
        good=0;
        for (d=ntpq->buf->str; *d!='\0'; d++){
            if (*d=='*') {
				safe_strncpy(s, d+1, 10);
				c=strchr(s, '.');
				if (!c) break;
				*c='\0';
				if (strcmp(s, "127")==0) break; /* local clock */
                good=1;
                break;
            }
            for (;*d!='\0';d++){
                if (*d!='\n') continue;
                break;
            }
        }
		if (ctest && !ctest->oldcontest && ntpq->oldgood!=good) {
			ntpq->oldgood=good;
			if (!good){
				log_addf(VTEXT(T_NO_NTP));
			}
		}

		ntpq->good=good;
        /*dbg("ntpq->good=%d\n", ntpq->good);*/
        g_string_truncate(ntpq->buf, 0);
		zselect_set(zsel, ntpq->rfd, NULL, NULL, NULL, NULL);
		close(ntpq->rfd);
		if (good)
			ntpq->timer = zselect_timer_new(zsel, 30*60*1000, ntpq_timer, ntpq);
		else
			ntpq->timer = zselect_timer_new(zsel, 2*60*1000, ntpq_timer, ntpq);
		return;
    }
	
    s[ret]='\0';
    /*dbg("ntpq_read_handler('%s');\n", s);*/
    g_string_append(ntpq->buf, s);
}

#endif
