/*
 * utils.c: miscellaneous utilities
 *
 * Author: John DiMarco, University of Toronto, CDF
 *         jdd@cdf.toronto.edu
 */

#ifndef lint
static char rcsid[] = "$Id: utils.c,v 1.6 1997/04/24 18:43:03 jdd Exp $";
#endif

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef FILENAME_MAX
#include <string.h>
#else
#include <strings.h>
#endif
#include <stdarg.h>
#include "utils.h"

#ifndef u_long
#define u_long unsigned long
#endif /* u_long */

#ifndef u_short
#define u_short unsigned short
#endif /* u_short */

extern char *progname;
extern int d;

/*
 * Error(): behaves like fprintf(stderr, ...) followed by exit(-1), except
 *          that the 'programname: ' preceeds the print, and a newline
 *	    follows it.
 */
/*VARARGS*/
void Error(char *format, ...)
{
	va_list args;

	va_start(args, format);
	(void)fprintf(stderr, "%s: ", progname);
	(void)vfprintf(stderr, format, args);
	(void)fprintf(stderr, "\n");
	va_end(args);
	exit(-1);
}

/*
 * dfprintf(): behaves like fprintf, except the first argument must be a
 *            debugging level. The message will only be printed if "d"
 *            is equal to or greater than the debugging level.
 */
/*VARARGS*/
void dfprintf(int debugLevel, FILE *stream, char *format, ...)
{
	va_list args;
	
	va_start(args, format); 
	if(d >= debugLevel){
		(void)vfprintf(stream, format, args);
	}
	va_end(args);
}
	
/*
 * Warning(): behaves like Error, except returns rather than exits.
 */
/*VARARGS*/
void Warning(char *format, ...)
{
	va_list args;

	va_start(args, format);
	(void)fprintf(stderr, "%s: ", progname);
	(void)vfprintf(stderr, format, args);
	(void)fprintf(stderr, "\n");
	va_end(args);
}

FILE *efopen(file, mode)
char *file, *mode;
{
	FILE *fp;
	if (NULL!=(fp=fopen(file,mode)))
		return(fp);
	Error("can't open file \"%s\" mode \"%s\"", file, mode);
	/*NOTREACHED*/
}

void efclose(f)
FILE *f;
{
	if(EOF==fclose(f))
		Error("can't close file");
	/*NOTREACHED*/
}

/*
 * mylib_malloc(): Checks if it gets a NULL pointer, calls Error if so.
 */
char *mylib_malloc(size, file, line)
unsigned size;
char *file;
int line;
{
	char *result;

	result = malloc(size);
	if(NULL==result){
		Error("Out of memory at line %d in \"%s\".", line, file);
	}
	return(result);
}

/*
 * mylib_realloc(): Checks if it gets a NULL pointer, calls Error if so.
 */
char *mylib_realloc(ptr, size, file, line)
char *ptr, *file;
unsigned size;
int line;
{
	char *result;

	result = realloc(ptr, size);
	if(NULL==result){
		Error("Out of memory at line %d in \"%s\".", line, file);
	}
	return(result);
}

/*
 * mylib_scopy(): Takes a string and creates a new physical copy of it.
 */
char *mylib_scopy(string, file, line)
char *string, *file;
int line;
{
	char *result;

	result = malloc((unsigned)strlen(string)+1);

	if(NULL==result){
		Error("Out of memory at line %d in \"%s\".", line, file);
	}
	(void)strcpy(result, string);
	return(result);
}

/*
 * mylib_srcopy(): Reallocs first string to make room for second, copies it.
 */
char *mylib_srcopy(s1, s2, file, line)
char *s1, *s2, *file;
int line;
{
	s1=mylib_realloc(s1, (unsigned)strlen(s2)+1, file, line);
	(void)strcpy(s1, s2);
	return(s1);
}

/*
 * cat(): Take a list of strings, followed by NULL, return their concatenation
 *        in malloc'ed space.
 */
/*VARARGS*/
char *cat(char *str0, ...)
{
	va_list args;
	unsigned length=1+strlen(str0);
	char *str, *newstr;

	/* get length */
	va_start(args, str0);
	loop{
		str = va_arg(args, char *);
		if(NULL!=str){
			 length+=strlen(str);
		} else {
			break;
		}
	}
	va_end(args);

	newstr=malloc(length);
	if(NULL==newstr) Error("Out of memory in cat()");
	
	newstr[0]=(char)0;
	strcat(newstr, str0);

	/* create string */
	va_start(args, str0);
	loop{
		str = va_arg(args, char *);
		if(NULL!=str) {
			(void)strcat(newstr, str);
		} else {
			break;
		}
	}
	va_end(args);
#ifdef lint
	args=args; /* make lint shut up about "args set but not used" */
#endif
	return(newstr);
}

#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>

/*
 * InAddrToString(): Convert internet address to a.b.c.d numeric string or 
 *                   hostname. If hostresolv, try to find internet address,
 *                   otherwise use numeric form only. 
 */
char *InAddrToString(iaddr, hostresolv)
u_long iaddr;
int hostresolv;
{
	static char iaddrbuff[16];
	struct hostent *h;
	static u_long lastaddr = (u_long)0;
	static int lastfail=0;

	if(INADDR_ANY == iaddr){
		sprintf(iaddrbuff, "*");
	} else {
		if(hostresolv && (!(lastaddr==iaddr) || !lastfail)){
			h=gethostbyaddr((char *)&iaddr, 
				sizeof(iaddr), AF_INET);
			lastaddr=iaddr;
			if(h) {
				lastfail=0;
				return (h->h_name);
			} else {
				lastfail++;
			}
		}
		iaddr=ntohl(iaddr);
		sprintf(iaddrbuff, "%u.%u.%u.%u", (iaddr>>24)&0xff,
		(iaddr>>16)&0xff, (iaddr>>8)&0xff,
		iaddr&0xff);
	}
	return(iaddrbuff);
}

#define PORT_ANY 0

/* 
 * PNumToString(): Convert port numbers to string. Successive calls overwrite.
 *                 "tcp" assumed. Resolve to service name if servresolv.
 */
char *PNumToString(pnum, host, servresolv)
u_short pnum;
u_long host;
int servresolv;
{
	static char pnumbuff[16]; 
	struct servent *sv;

	if(PORT_ANY == pnum){
		sprintf(pnumbuff, "*");
	} else {
		if(servresolv){
			sv=getservbyport(htons((int)pnum), "tcp");
			if(sv){
				return(sv->s_name);
			} 
		}
		sprintf(pnumbuff, "%u", (unsigned int)pnum);
	}
	return(pnumbuff);
}


syntax highlighted by Code2HTML, v. 0.9.1