/* lnstat - Unified linux network statistics
 *
 * Copyright (C) 2004 by Harald Welte <laforge@gnumonks.org>
 *
 * Development of this code was funded by Astaro AG, http://www.astaro.com/
 *
 * Based on original concept and ideas from predecessor rtstat.c:
 *
 * Copyright 2001 by Robert Olsson <robert.olsson@its.uu.se>
 *                                 Uppsala University, Sweden
 *
 * 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 2 of the License, or
 * (at your option) any later version.
 *
 */

/* Maximum number of fields that can be displayed */
#define MAX_FIELDS		64

/* Maximum number of header lines */
#define HDR_LINES 		10

/* default field width if none specified */
#define FIELD_WIDTH_DEFAULT	8
#define FIELD_WIDTH_MAX		20

#define DEFAULT_INTERVAL	2

#define HDR_LINE_LENGTH		(MAX_FIELDS*FIELD_WIDTH_MAX)

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>

#include "lnstat.h"

static struct option opts[] = {
	{ "version", 0, NULL, 'V' },
	{ "count", 1, NULL, 'c' },
	{ "dump", 1, NULL, 'd' },
	{ "file", 1, NULL, 'f' },
	{ "help", 0, NULL, 'h' },
	{ "interval", 1, NULL, 'i' },
	{ "key", 1, NULL, 'k' },
	{ "subject", 1, NULL, 's' },
	{ "width", 1, NULL, 'w' },
};

static int usage(char *name, int exit_code)
{
	fprintf(stderr, "%s Version %s\n", name, LNSTAT_VERSION);
	fprintf(stderr, "Copyright (C) 2004 by Harald Welte "
			"<laforge@gnumonks.org>\n");
	fprintf(stderr, "This program is free software licensed under GNU GPLv2"
			"\nwith ABSOLUTELY NO WARRANTY.\n\n");
	fprintf(stderr, "Parameters:\n");
	fprintf(stderr, "\t-V --version\t\tPrint Version of Program\n");
	fprintf(stderr, "\t-c --count <count>\t"
			"Print <count> number of intervals\n");
	fprintf(stderr, "\t-d --dumpt\t\t"
			"Dump list of available files/keys\n");
	fprintf(stderr, "\t-f --file <file>\tStatistics file to use\n");
	fprintf(stderr, "\t-h --help\t\tThis help message\n");
	fprintf(stderr, "\t-i --interval <intv>\t"
			"Set interval to 'intv' seconds\n");
	fprintf(stderr, "\t-k --keys k,k,k,...\tDisplay only keys specified\n");
	fprintf(stderr, "\t-s --subject [0-2]\t?\n");
	fprintf(stderr, "\t-w --width n,n,n,...\tWidth for each field\n");
	fprintf(stderr, "\n");

	exit(exit_code);
}

struct field_param {
	const char *name;
	struct lnstat_field *lf;
	struct {
		unsigned int width;
	} print;
};

struct field_params {
	unsigned int num;
	struct field_param params[MAX_FIELDS];
};

static void print_line(FILE *of, const struct lnstat_file *lnstat_files,
		       const struct field_params *fp)
{
	int i;

	for (i = 0; i < fp->num; i++) {
		struct lnstat_field *lf = fp->params[i].lf;
		char formatbuf[255];

		snprintf(formatbuf, sizeof(formatbuf)-1, "%%%ulu|",
			 fp->params[i].print.width);
		fprintf(of, formatbuf, lf->result);
	}
	fputc('\n', of);
}

/* find lnstat_field according to user specification */
static int map_field_params(struct lnstat_file *lnstat_files,
			    struct field_params *fps, int interval)
{
	int i, j = 0;
	struct lnstat_file *lf;

	/* no field specification on commandline, need to build default */
	if (!fps->num) {
		for (lf = lnstat_files; lf; lf = lf->next) {
			for (i = 0; i < lf->num_fields; i++) {
				fps->params[j].lf = &lf->fields[i];
				fps->params[j].lf->file->interval.tv_sec =
								interval;
				if (!fps->params[j].print.width)
					fps->params[j].print.width = 
							FIELD_WIDTH_DEFAULT;
				j++;
			}
		}
		fps->num = j;
		return 1;
	}

	for (i = 0; i < fps->num; i++) {
		fps->params[i].lf = lnstat_find_field(lnstat_files,
						      fps->params[i].name);
		if (!fps->params[i].lf) {
			fprintf(stderr, "Field `%s' unknown\n",
				fps->params[i].name);
			return 0;
		}
		fps->params[i].lf->file->interval.tv_sec = interval;
		if (!fps->params[i].print.width)
			fps->params[i].print.width = FIELD_WIDTH_DEFAULT;
	}
	return 1;
}

struct table_hdr {
	int num_lines;
	char *hdr[HDR_LINES];
};

static struct table_hdr *build_hdr_string(struct lnstat_file *lnstat_files,
					  struct field_params *fps,
					  int linewidth)
{
	int h,i;
	static struct table_hdr th;
	int ofs = 0;

	for (i = 0; i < HDR_LINES; i++) {
		th.hdr[i] = malloc(HDR_LINE_LENGTH);
		memset(th.hdr[i], 0, sizeof(th.hdr[i]));
	}

	for (i = 0; i < fps->num; i++) {
		char *cname, *fname = fps->params[i].lf->name;
		char fmt[12];
		unsigned int width = fps->params[i].print.width;

		snprintf(fmt, sizeof(fmt)-1, "%%%u.%us|", width, width);

		snprintf(th.hdr[0]+ofs, width+2, fmt,
			 fps->params[i].lf->file->basename);

		cname = fname;
		for (h = 1; h < HDR_LINES; h++) {
			if (cname - fname >= strlen(fname))
				snprintf(th.hdr[h]+ofs, width+2, fmt, "");
			else {
				th.num_lines = h+1;
				snprintf(th.hdr[h]+ofs, width+2, fmt, cname);
			}
			cname += width;
		}
		ofs += width+1;
	}
	/* fill in spaces */
	for (h = 1; h <= th.num_lines; h++) {
		for (i = 0; i < ofs; i++) {
			if (th.hdr[h][i] == '\0')
				th.hdr[h][i] = ' ';
		}
	}

	return &th;
}

static int print_hdr(FILE *of, struct table_hdr *th)
{
	int i;

	for (i = 0; i < th->num_lines; i++) {
		fputs(th->hdr[i], of);
		fputc('\n', of);
	}
	return 0;
}
		

int main(int argc, char **argv)
{
	struct lnstat_file *lnstat_files;
	const char *basename;
	int c;
	int interval = DEFAULT_INTERVAL;
	int hdr = 2;
	enum {
		MODE_DUMP,
		MODE_NORMAL,
	} mode = MODE_NORMAL;

	unsigned long count = 0;
	static struct field_params fp;
	int num_req_files = 0;
	char *req_files[LNSTAT_MAX_FILES];
	
	/* backwards compatibility mode for old tools */
	basename = strrchr(argv[0], '/');
	if (basename) 
		basename += 1;	  /* name after slash */
	else
		basename = argv[0]; /* no slash */

	if (!strcmp(basename, "rtstat")) {
		/* rtstat compatibility mode */
		req_files[0] = "rt_cache";
		num_req_files = 1;
	} else if (!strcmp(basename, "ctstat")) {
		/* ctstat compatibility mode */
		req_files[0] = "ip_conntrack";
		num_req_files = 1;
	}

	while ((c = getopt_long(argc, argv,"Vc:df:h?i:k:s:w:", 
				opts, NULL)) != -1) {
		int i, len = 0;
		char *tmp, *tok;

		switch (c) {
			case 'c':
				count = strtoul(optarg, NULL, 0);
				break;
			case 'd':
				mode = MODE_DUMP;
				break;
			case 'f':
				req_files[num_req_files++] = strdup(optarg);
				break;
			case '?':
			case 'h':       
				usage(argv[0], 0);
				break;
			case 'i':
				sscanf(optarg, "%u", &interval);
				break;
			case 'k':
				tmp = strdup(optarg);
				if (!tmp)
					break;
				for (tok = strtok(tmp, ",");
				     tok;
				     tok = strtok(NULL, ",")) {
					if (fp.num >= MAX_FIELDS)
						break;
					fp.params[fp.num++].name = tok;
				}
				break;
			case 's':
				sscanf(optarg, "%u", &hdr);
				break;
			case 'w':
				tmp = strdup(optarg);
				if (!tmp)
					break;
				i = 0;
				for (tok = strtok(tmp, ",");
				     tok;
				     tok = strtok(NULL, ",")) {
					len  = strtoul(tok, NULL, 0);
					if (len > FIELD_WIDTH_MAX)
						len = FIELD_WIDTH_MAX;
					fp.params[i].print.width = len;
					i++;
				}
				if (i == 1) {
					for (i = 0; i < MAX_FIELDS; i++)
						fp.params[i].print.width = len;
				}
				break;
			default:
				usage(argv[0], 1);
				break;
		}
	}

	lnstat_files = lnstat_scan_dir(PROC_NET_STAT, num_req_files,
				       (const char **) req_files);

	switch (mode) {
		int i;
		struct table_hdr *header;
	case MODE_DUMP:
		lnstat_dump(stderr, lnstat_files);
		break;
	case MODE_NORMAL:

		if (!map_field_params(lnstat_files, &fp, interval))
			exit(1);
	
		header = build_hdr_string(lnstat_files, &fp, 80);
		if (!header)
			exit(1);

		if (interval < 1 ) 
			interval=1;

		for (i = 0; i < count; i++) {
			if  ((hdr > 1 && (! (i % 20))) || (hdr == 1 && i == 0))
				print_hdr(stdout, header);
			lnstat_update(lnstat_files);
			print_line(stdout, lnstat_files, &fp);
			sleep(interval);
		}
	}

	return 1;
}

