/*
**  Copyright 2000-2004 University of Illinois Board of Trustees
**  Copyright 2000-2004 Mark D. Roth
**  All rights reserved.
**
**  init.c - nph code to initialize a new server connection
**
**  Mark D. Roth <roth@feep.net>
*/

#include <nph.h>

#include <errno.h>
#include <pwd.h>
#include <sys/param.h>
#include <netdb.h>

#ifdef STDC_HEADERS
# include <string.h>
# include <stdlib.h>
#endif

#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif


/* verify that a field exists on the server */
int
check_field(PH *newph, char *field)
{
	struct ph_fieldinfo *fieldinfo = NULL;

	if (ph_get_fieldinfo(newph, field, &fieldinfo) == PH_ERR_DATAERR)
	{
		nph_printf(1, "unknown field \"%s\"\n", field);
		return -1;
	}
	return 0;
}


/* verify that a list of fields exists on the server */
int
check_fields(PH *newph, char *string)
{
	char buf[NPH_BUF_SIZE];
	char *wordp, *nextp;

	strlcpy(buf, string, sizeof(buf));
	nextp = buf;
	while ((wordp = strsep(&nextp, " ")) != NULL)
	{
		if (*wordp == '\0')
			continue;

		if (check_field(newph, wordp) == -1)
			return -1;
	}

	return 0;
}


/* connect to PH server and initialize options */
int
server_init(PH **newph, char *server)
{
	int i, debug, ph_open_flags = PH_OPEN_DONTID;
	char *fields = NULL;
	char buf[NPH_BUF_SIZE];

	/* set flags */
	if (strchr(server, '/') != NULL)
		ph_open_flags |= PH_OPEN_LOCAL;
	else if (geteuid() == 0)
	{
		get_option("usereservedport", &i);
		if (i)
			ph_open_flags |= PH_OPEN_PRIVPORT;
	}
	get_option("debug", &debug);

	/* open connection */
	if (ph_open(newph, server, ph_open_flags,
		    (debug ? send_debug : NULL),
		    (debug ? recv_debug : NULL),
		    NULL) == -1)
	{
		nph_printf(1, "ph_open(): %s\n", strerror(errno));
		return -1;
	}
	nph_printf(1, "connected to PH server %s\n", server);

	/* send id */
	snprintf(buf, sizeof(buf), "nph-%s", PACKAGE_VERSION);
	if (ph_id(*newph, buf) == -1)
	{
		nph_printf(1, "ph_id(): %s\n", strerror(errno));
		return -1;
	}

	/* validate field list */
	get_option("returnfields", &fields);
	if (fields != NULL
	    && check_fields(*newph, fields))
	{
		nph_printf(1, "unsetting invalid \"returnfields\" option\n");
		set_option("returnfields", "");
	}

	return 0;
}


/* read the system-wide ph_server file */
char *
read_server_file(void)
{
	FILE *f;
	char buf[MAXHOSTNAMELEN + 5];

	f = fopen(SERVER_FILE, "r");
	if (f == NULL)
	{
		nph_printf(1, "cannot open server file %s: %s\n",
			   SERVER_FILE, strerror(errno));
		exit(1);
	}

	if (fgets(buf, sizeof(buf), f) == NULL)
	{
		nph_printf(1, "fgets(): %s\n", strerror(errno));
		fclose(f);
		exit(1);
	}

	fclose(f);

	/* strip newline */
	if (buf[strlen(buf) - 1] == '\n')
		buf[strlen(buf) - 1] = '\0';

	return strdup(buf);
}


/* change servers */
int
nph_connect(int cmdc, char **cmdv)
{
	PH *newph;

	if (cmdv[1] == NULL
	    || cmdv[2] != NULL)
	{
		print_help(cmdv[0]);
		return -1;
	}

	if (server_init(&newph, cmdv[1]) != 0)
		return -1;

	/* close old connection */
	if (ph != NULL)
	{
		nph_printf(1, "disconnecting from server %s\n", ph_server);
		if (ph_close(ph, 0) == -1)
			nph_printf(1, "warning: ph_close(): %s\n",
				   strerror(errno));
	}

	/* save new handle */
	ph = newph;
	ph_server = strdup(cmdv[1]);
	got_servers = 0;

	return 0;
}


/* read an nphrc file */
int
read_nphrc(char *filename)
{
	struct passwd *pw;
	char nphrc[MAXPATHLEN];
	char *cp;
	int i;

	if (filename != NULL)
		return read_command_file(filename);

	cp = getenv("HOME");
	if (cp == NULL)
	{
		pw = getpwuid(getuid());
		if (pw == NULL)
		{
			perror("nph: cannot determine user's home directory: "
			       "getpwuid()");
			return -1;
		}
		cp = pw->pw_dir;
	}

	snprintf(nphrc, sizeof(nphrc), "%s/.nphrc.%s", cp, ph_server);
	i = read_command_file(nphrc);

	if (i == 1)
	{
		snprintf(nphrc, MAXPATHLEN, "%s/.nphrc", cp);
		i = read_command_file(nphrc);
	}

	if (i == 1)
	{
		snprintf(nphrc, MAXPATHLEN, "%s", SYSTEM_NPHRC);
		i = read_command_file(nphrc);
	}

	return i;
}


/* read commands from a file and execute them */
int
read_command_file(char *filename)
{
	char buf[NPH_BUF_SIZE];
	FILE *f;
	int line = 0;
	char *p;

	/* open file */
	f = fopen(filename, "r");
	if (f == NULL)
	{
		if (errno == ENOENT)
			return 1;
		nph_printf(1, "cannot open %s: %s\n", filename,
			   strerror(errno));
		return -1;
	}
	nph_printf(1, "reading file %s...\n", filename);

	/* parse each line of the config file */
	while (fgets(buf, sizeof(buf), f) != NULL)
	{
		line++;

		/* strip off newlines */
		if (buf[strlen(buf) - 1] == '\n')
			buf[strlen(buf) - 1] = '\0';

		/* strip off comments */
		if ((p = strchr(buf, '#')) != NULL)
			*p = '\0';

		/* handle blank lines */
		if (buf[0] == '\0')
			continue;

		/* run command */
		nph_command(buf);
	}

	fclose(f);
	return 0;
}


/* read commands from a file */
int
nph_source(int cmdc, char **cmdv)
{
	int i;

	if (cmdv[1] == NULL
	    || cmdv[2] != NULL)
	{
		print_help(cmdv[0]);
		return -1;
	}

	i = read_command_file(cmdv[1]);
	if (i == 1)
		nph_printf(1, "cannot open %s: no such file or directory\n",
			   cmdv[1]);
	return i;
}




syntax highlighted by Code2HTML, v. 0.9.1