/*

$Id: util.c,v 1.2 2003/02/10 14:46:34 peloy Exp $

*/

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <time.h>
#include <string.h>

#include "tcp-md5.h"

extern int tflag;
extern int thiszone;

/*
 * Copy arg vector into a new buffer, concatenating arguments with spaces.
 */
char *
copy_argv(register char **argv)
{
	register char **p;
	register u_int len = 0;
	char *buf;
	char *src, *dst;

	p = argv;
	if (*p == 0)
		return 0;

	while (*p)
		len += strlen(*p++) + 1;

	buf = (char *)malloc(len);
	if (buf == NULL)
		error("copy_argv: malloc");

	p = argv;
	dst = buf;
	while ((src = *p++) != NULL) {
		while ((*dst++ = *src++) != '\0')
			;
		dst[-1] = ' ';
	}
	dst[-1] = '\0';

	return buf;
}

/*
 * Returns the difference between gmt and local time in seconds.
 * Use gmtime() and localtime() to keep things simple. (Stolen
 * verbatim from tcpdump.)
 */
int32_t
gmt2local(time_t t)
{
	register int dt, dir;
	register struct tm *gmt, *loc;
	struct tm sgmt;

	if (t == 0)
		t = time(NULL);
	gmt = &sgmt;
	*gmt = *gmtime(&t);
	loc = localtime(&t);
	dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
	    (loc->tm_min - gmt->tm_min) * 60;

	/*
	 * If the year or julian day is different, we span 00:00 GMT
	 * and must add or subtract a day. Check the year first to
	 * avoid problems when the julian day wraps.
	 */
	dir = loc->tm_year - gmt->tm_year;
	if (dir == 0)
		dir = loc->tm_yday - gmt->tm_yday;
	dt += dir * 24 * 60 * 60;

	return (dt);
}

/*
 * Print the timestamp (stolen verbatim from tcpdump)
 */
void
Ts_print(register const struct timeval *tvp)
{
	register int s;
	struct tm *tm;
	time_t Time;
	static unsigned b_sec;
	static unsigned b_usec;

	switch(tflag) {
	case 1: /* Default */
		s = (tvp->tv_sec + thiszone) % 86400;
		(void)printf("%02d:%02d:%02d.%06u ",
			     s / 3600, (s % 3600) / 60, s % 60,
			     (unsigned)tvp->tv_usec);
		break;
	case -1: /* Unix timeval style */
		(void)printf("%u.%06u ",
			     (unsigned)tvp->tv_sec,
			     (unsigned)tvp->tv_usec);
		break;
	case -2:
		if (b_sec == 0) {
			printf("000000 ");
		} else {
			int d_usec = tvp->tv_usec - b_usec;
			int d_sec = tvp->tv_sec - b_sec;
			
			while (d_usec < 0) {
				d_usec += 1000000;
				d_sec--;
			}
			if (d_sec)
				printf("%d. ", d_sec);
			printf("%06d ", d_usec);
		}
		b_sec = tvp->tv_sec;
		b_usec = tvp->tv_usec;
		break;
	case -3: /* Default + Date*/
		s = (tvp->tv_sec + thiszone) % 86400;
		Time = (tvp->tv_sec + thiszone) - s;
		tm  = gmtime (&Time);
		(void)printf("%02d/%02d/%04d %02d:%02d:%02d.%06u ",
			     tm->tm_mon+1, tm->tm_mday,
			     tm->tm_year+1900,
			     s / 3600, (s % 3600) / 60,
			     s % 60, (unsigned)tvp->tv_usec);
		break;
	}
}

void dump(const unsigned char *data, unsigned len)
{
	unsigned i, j;

	for (i = 0; i <= len/16; i++) {
		printf("%08x  ", i*16);

		for (j = 0; j < 16; j++) {
			if (i*16 + j < len)
				printf("%02x", data[i*16 + j]);
			else
				printf("  ");

			if (j & 1)
				printf(" ");
		}

		for (j = 0; j < 16; j++)
			if (i*16 + j < len)
				printf("%c", isprint(data[i*16 + j]) ? data[i*16 + j] : '.');

		printf("\n");
	}

	printf("\n");
}

/* VARARGS */
void
error(const char *fmt, ...)
{
	va_list ap;

	(void)fprintf(stderr, "%s: ", program_name);
	va_start(ap, fmt);
	(void)vfprintf(stderr, fmt, ap);
	va_end(ap);
	if (*fmt) {
		fmt += strlen(fmt);
		if (fmt[-1] != '\n')
			(void)fputc('\n', stderr);
	}
	exit(1);
	/* NOTREACHED */
}

