/*  
    lsnet is a light weight computer resource/stats monitor.
    Copyright (C) 2009-2010  Sterling Pickens

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "config.h"
#ifdef POSIX_MULTITHREAD_SUPPORT
#include <pthread.h>
#endif
#include <math.h>
#include <time.h>
#include "logdir.h"
#include "cores.h"
#include "processes.h"
#include "cpuinfo.h"
#include "frequency.h"
#include "meminfo.h"
#include "netinfo.h"
#include "errors.h"

extern struct cpu_data cpu;
extern struct net_data net;
extern struct mem_data mem;
extern int using_alt_conf;
extern struct log_data global_strs;
extern char *program_invocation;

void title(void);
void usage(void);


void title() {
        printf("\tlsnet is a product of the linuxsociety team and licensed under GPLv3\n");
        printf("\tThis is version %s dated %s\n", LSNET_VERSION, LSNET_RELEASE_DATE);
        printf("\n");
}

void usage() {
        printf("Usage: lsnet <-c config file> [option]\n");
        printf("Options:\n");
        printf("        -h: display this help menu\n");  
	printf("        -v: display version information\n");
        printf("        -a: run all monitors\n");
	printf("        -s: stop all monitors\n");
        printf("        -1: run cpu monitor only\n");
        printf("        -2: run mem monitor only\n");
        printf("        -3: run net monitor only\n");
        printf("\n");           
}


#ifndef POSIX_MULTITHREAD_SUPPORT
void runall(){
        title();

	int pid = fork();
	if (pid == 0)
		Cpu_ten_min();
     	else 
        	pid = fork();
		if (pid == 0)
			Mem_ten_min();
		else
			pid = fork();
			if (pid == 0)
				Net_ten_min();
			else
				printf( "\n\tMonitor daemons started.\t\n");
}
#else

unsigned int Tid[3] = {0,1,2};

void *runall(void *thread_id){
	//printf("launching thread %u\n", *(unsigned int *)thread_id);
	if(*(unsigned int *)thread_id == 0){
		Cpu_ten_min();
	}else if(*(unsigned int *)thread_id == 1){
		Mem_ten_min();
	}else if(*(unsigned int *)thread_id == 2){
		Net_ten_min();
	}else{
		printf("ERROR: incorrent thread_id passed!\n");
		exit(1);
	}
	pthread_exit;
}

void Manager(){
	int Tcount;
	pthread_t *Threads = (pthread_t *)malloc(sizeof(pthread_t) * 3);
	for(Tcount = 0; Tcount < 3; Tcount++){
		if (pthread_create(&Threads[Tcount], NULL, runall, &Tid[Tcount]) != 0){
			printf("Error: pthread_create failed for thread: %d !\n", Tcount);
			exit(1);
		}
	}
	for(Tcount=0; Tcount<3; Tcount++){
		if (pthread_join(Threads[Tcount], NULL) != 0){
			printf("Error: pthread_join failed for thread: %d !\n", Tcount);
			exit(1);
		}
	}
}
#endif

int main(int argc, char **argv) {
	set_invocation(argv[0]);
	using_alt_conf = 0;
	if(argc == 4){
		if( strcmp(argv[1], "-c") ){
			global_strs.conf_file = (char *)malloc( strlen(argv[2]) + 1);
			(void)strncpy(global_strs.conf_file, (const char *)argv[2], strlen(argv[2]) );
		}else if( strcmp(argv[2], "-c") ){
			global_strs.conf_file = (char *)malloc( strlen(argv[3]) + 1);
			(void)strncpy(global_strs.conf_file, (const char *)argv[3], strlen(argv[3]) );
		}else{
			usage();
			exit(1);
		}
		using_alt_conf = 1;
	}else if(argc != 2){
		usage();
		exit(1);
	}

	//setup all dir strings, folders/files, etc.
	Logdir();

	cpu.frequency = frequency("cpu");
	cpu.polls = floor(60 / cpu.frequency);
	mem.frequency = frequency("mem");
	mem.polls = floor(60 / mem.frequency);
	net.frequency = frequency("net");
	net.polls = floor(60 / net.frequency);
	cpu.cores = coresdetected();
	cpu.mhz = mhzdetected();

	char *commandstr;
        int count4;
        int o;
	int pid;

        while((o=getopt(argc, argv, "hva123s")) != EOF) {
                switch(o) {
                        case 'h':
				title();
                                usage();
                                exit(1);
                                break;
			case 'v':
				printf("Version: %s Released on: %s\n", LSNET_VERSION, LSNET_RELEASE_DATE);
				printf("Compiled on: %s\n", __TIMESTAMP__);
				exit(1);
				break;
                        case 'a':
				clockskew();
				cpulock(); 
				Cpu_allocate();
				memlock(); 
				Mem_allocate();
				netlock();
#ifndef POSIX_MULTITHREAD_SUPPORT
				runall();
#else
				pid = fork();
				if (pid == 0)
					Manager();
				else
					printf( "\n\tMonitor daemons started.\t\n");
#endif

                                exit(1);
                                break;
                        case '1':
                                title();
				clockskew();
				cpulock(); 
				Cpu_allocate();
			        pid = fork();
				if (pid == 0)
                			Cpu_ten_min();
        			else
                                printf("\n\n\tCpu Daemon Started.\n");
                                exit(1);
                                break;
                        case '2':
                                title();
				clockskew();
				memlock();
				Mem_allocate();
				pid = fork();
				if (pid == 0)
					Mem_ten_min();
				else
                                printf("\n\n\tMem Daemon Started.\n");
                                exit(1);
                                break;
                        case '3':
                                title();
				clockskew();
				netlock();
				pid = fork();
				if (pid == 0)
					Net_ten_min();
				else
                                printf("\n\n\tNet Daemon Started.\n");
                                exit(1);
                                break;
			case 's':
				commandstr = malloc(strlen(global_strs.cpu_lock) + strlen(global_strs.mem_lock) + strlen(global_strs.net_lock) + 5);
				strcpy(commandstr, "rm ");
				strcat(commandstr, global_strs.cpu_lock);
				strcat(commandstr, " ");
				strcat(commandstr, global_strs.mem_lock);
				strcat(commandstr, " ");
				strcat(commandstr, global_strs.net_lock);
				system(commandstr);
				system("killall -9 lsnetd");
				free(commandstr);
				printf("\n\n\tDaemons Stopped.\n");
				exit(1);
				break;
                       default:
                                break;   
                        }
        }
        while(optind) {
                title();
                usage();
                printf("\nError: No run options specified!\n\n");
                exit(1);
        }
	return 0;
}
