/* IPC config settings handler. This module reads
   the settings in the IPC config file (IPC_CONFIG_FILE).
   The IPC config file is a normal ASCII file that
   can contain two settings. They are:

   	port nnnn
   	host ssss

   'port' specifies the port that the server listens to.
   'host' is the host name of the server. Note that the
   port number must be a valid decimal number and the
   host name must be quoted (single or double quotes,
   but they must match) if it contains a space.
   Rick Smereka, Copyright (C) 1998-2005.

   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.

   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, get a copy via the Internet at
   http://gnu.org/copyleft/gpl.html or write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
   MA 02111-1307 USA

   You can contact the author via email at rsmereka@future-lab.com

   Original version for CodeWarrior V4 under Windows 32bit.
   Dec/98, Rick Smereka

   Ported to HP-UX under GNU C 2.8.1.
   Jan/99, Rick Smereka

   Ported to Red Hat Linux 5.2, Jul/99, Rick Smereka

   Since the introduction of 'socloc' in 2001, this module is now
   obsolete and is not used in any part of the Future Lab GPL software.
   This module is retained in the hope that it may be of some use.
   Jun/2005, Rick Smereka */

#include "stdhead.h"
#include "ipconfig.h"

int ipc_config_read(char *fname, char *nodeid, int *port_number)
{
	/* Read and parse the IPC config file 'fname'. Function
	   returns 'TRUE' upon success, 'FALSE' otherwise.
	   Upon successful completion. 'nodeid' will be
	   loaded with the specified node id and
	   'port_number' will be loaded with the specified
	   port number. Note that both settings might
	   not be present. A null string in 'nodeid'
	   denotes no node id present and a zero
	   'port_number' denotes no port number. */

	FILE *in;
	char *line, *word, *ucase_word;
	int nwords;

   // reasonableness checks

   if (fname == (char *)NULL || !strlen(fname))
      return(IPC_CONFIG_INVALID_PARAMETER);

	if (nodeid == (char *)NULL)
	   return(IPC_CONFIG_INVALID_PARAMETER);

	if (port_number == (int *)NULL)
	   return(IPC_CONFIG_INVALID_PARAMETER);

   nodeid[0] = EOS;
   *port_number = 0;

	// attempt to open config file

	if ((in = fopen(fname, "r")) == (FILE *)NULL)
	   return(IPC_CONFIG_UNABLE_TO_OPEN);

	// alloc line buffer

	if ((line = (char *)malloc(BUFSIZE)) == (char *)NULL)
	   {
	   fclose(in);
	   return(IPC_CONFIG_ALLOC_ERROR);
	   }

	// get first record

	get_rec(in, line);

	while(!feof(in))
	   {
	   // number of command words on line

	   nwords = command_words(line);

	   // must have at least two command words per record

	   if (nwords < 2)
	      {
	      free(line);
	      fclose(in);
	      return(IPC_CONFIG_PARAMETER_MISSING);
	      }

	   /* create word string by dynamically copying and
	      set length to zero */

	   word = initstring(line);
	   word[0] = EOS;

	   // get first command word on line

	   if (!command_word(line, word, 1))
	      {
	      free(word);
	      free(line);
	      fclose(in);
	      return(IPC_CONFIG_INTERNAL_PARSE_ERROR);
	      }

	   // make another copy and convert it to upper case

	   ucase_word = initstring(word);
	   ucase_word[0] = EOS;
	   ucase(word, ucase_word);

	   // is it the 'host' keyword?

	   if (!strcmp(ucase_word, "HOST"))
	      {
	      word[0] = EOS;

	      // get second command word

	      if (!command_word(line, word, 2))
	         {
	         free(word);
	         free(line);
	         free(ucase_word);
	         fclose(in);
	         return(IPC_CONFIG_INTERNAL_PARSE_ERROR);
	         }

	      // copy into 'nodeid'

	      strcpy(nodeid, word);
	      }

	   // is it the 'port' keyword?

	   if (!strcmp(ucase_word, "PORT"))
	      {
	      word[0] = EOS;

	      if (!command_word(line, word, 2))
	         {
	         free(word);
	         free(line);
	         free(ucase_word);
	         fclose(in);
	         return(IPC_CONFIG_INTERNAL_PARSE_ERROR);
	         }

	      // must be a valid decimal number

	      if (!num(word))
	         {
	         free(word);
	         free(line);
	         free(ucase_word);
	         fclose(in);
	         return(IPC_CONFIG_PORT_NOT_NUMERIC);
	         }

	      // set 'port_number'

	      *port_number = atoi(word);
	      }

	   // dealloc temp vars
	   free(word);
	   free(ucase_word);

	   // get next record

	   get_rec(in, line);
	   }

	fclose(in);
	free(line);
   return(IPC_CONFIG_OK);
}

void ipc_config_code_string(int ret, char *mes)
{
   /* Translate an IPC status code to an English string.
      String is returned in 'mes' which must be already
      allocated to suficient length. */
   
   switch(ret)
      {      
      case IPC_CONFIG_OK:
         strcpy(mes, "ok");
         break;
         
      case IPC_CONFIG_INVALID_PARAMETER:
         strcpy(mes, "invalid parameter");
         break;
         
      case IPC_CONFIG_PARAMETER_MISSING:
         strcpy(mes, "parameter missing");
         break;
         
      case IPC_CONFIG_UNABLE_TO_OPEN:
         strcpy(mes, "unable to open config file");
         break;
         
      case IPC_CONFIG_ALLOC_ERROR:
         strcpy(mes, "dynamic memory allocation failure");
         break;
         
      case IPC_CONFIG_INTERNAL_PARSE_ERROR:
         strcpy(mes, "internal parse error");
         break;
         
      case IPC_CONFIG_PORT_NOT_NUMERIC:
         strcpy(mes, "port number not numeric decimal");
         break;
         
      default:
         strcpy(mes, "unknown status code");
      };
}

