#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <string.h>
#include <stubs.h>
#include "ca_defs.h"
/* #define DEBUG */

/**********************************************
 * This file contains the definitions of all	*
 * the functions.										*
	**********************************************/


void stringPack(char *dest, const char *source)
{
#ifdef DEBUG
printf("\nInside stringPack function\n");
#endif 	/* DEBUG */

/*----------------------------------------------------------------------*\

*  Function to rewrite a line of text with only one blankspace between  *
*  each word.
*

\*----------------------------------------------------------------------*/


/*
 * This while loop continues until the NULL character is copied into
 * the destination string.  If a tab character is copied into the 
 * destination string, it is replaced with a blank-space character.
 *
 * Multiple blank-space and/or tab characters are skipped in the source
 * string until any other character is found.
 */

	while (1)
		{
		*dest = *source;

		if (*dest == '\t')
			(*dest = ' ');
	
		/* Exit if have copied the end of the string. */
		if (*dest == '\0')
			return;

/*
 * If the source character was a blank-space or a tab, move to the next 
 * source character.  While the source character is a blank-space or a
 * tab, move to the next character (i.e. ignore these characters).  When
 * any other character is found in the source string, move to the next
 * element of the destination string.
 *
 * Otherwise, simultaneously, move to the next elements of the destination
 * and the source strings.
 */


		
		if ( (*source == ' ') || (*source == '\t') )
			{
			++source;
			while ( (*source == ' ') || (*source == '\t') )
				{
				++source;
				}

			++dest;
			}
		else
			{
			++dest;
			++source;
			}
		}
}


void ca_populateDictionary(dict_t woordenboek[], int size)

/*******************************************************************
 * ca_populateDictionary -- Parses dictionary file, initializes    *
 *									the dictionary structure and writes    *
 *									the file of dictionary symbols, 			*
	*									ca_dictSyms.h									*
	*																						*
	* Parameters																		*
	*		woordenboek -- the dictionary to be populated					*
	*		size -- the total number of variables i.e. the size of the  *
 *	 			  array of dict_t structures.  See D. & D., p.276		*
 *																						*
 * Returns																			*
	*		Nothing ?  (may change this later)									*
 *																						*
 *******************************************************************/

{
const char *blankLine = "\n";
const char *comment = "#";
char line[120];
char input[120];
char test[120];
int lineNo = 0;
int i;
int entry = 0;
FILE *dictPtr, *defnPtr;

gchar **tokens;                         /* Pointer to an array of strings. */
		
/*
	* Try to open the dictionary file for reading.  If it cannot be
 * opened, exit with an error.
 */
if ( (dictPtr = fopen("dictionary.txt", "r")) == NULL)
		{
		fprintf(stderr, "Error: Unable to open 'dictionary.txt'\n");
		die;
		}
		

	/*
	 *Try to open the definitions file for writing.  If it cannot be
  * opened,exit with an error
  */
if ( (defnPtr = fopen("defs.txt", "w")) == NULL)
		{
		fprintf(stderr, "Error: Unable to open 'defs.txt'\n");
		die;
		}
	
		/*
		 * Read the file one line at a time;
		 * if the line begins with a comment, ignore it;
		 * otherwise, split each line into tokens;
		 * print each token.
		 * Assign each token to the appropriate member of
		 * the appropriate element of the dictionary array.
		 */
		
		fgets(input, sizeof(input), dictPtr);
	
		if ( (strncmp(input, comment, 1) != 0) && (strncmp(input, blankLine, 1) != 0) )

			{
			/*
			 * First remove the newline character.
			 * Then replace multiple tab and space
			 * characters with single space characters.
			 */

			/* Remove the newline character, if present. 
			 * Replace the last character of the string
			 * array with with '\0'.
			 */

			input[strlen(input) - 1] = '\0';

			/* Now, remove the multiple space and tab
			 * characters.
			 */

			stringPack(line, input);
			
			g_strchomp(line); /* Remove trailing w-space. */
#ifdef DEBUG
puts(line);
#endif	/*DEBUG */

			tokens = g_strsplit(line, " ", 0);

#ifdef DEBUG						
			for (i = 0; tokens[i] != NULL; i++)
				printf("tokens[%d] = %s\n", i, tokens[i]);
#endif	/* DEBUG */

			/* We no longer need a variable for scope
			 * woordenboek[entry].varScope = atoi(tokens[1]);
			 */

			strcpy(woordenboek[entry].varName, tokens[0]);
			strcpy(woordenboek[entry].varSym, tokens[1]);
			strcpy(woordenboek[entry].varType, tokens[2]);
			woordenboek[entry].varNum = entry;
			
       /*
			 * Write the dictionary symbol and the entry number 
			 * to the definitions file.
        */
			fprintf(defnPtr, "%s\t%d\n", tokens[1], entry);

			++entry;
			g_strfreev( tokens ); 
			}
	/*
	 * Get the 2nd and subsequent line of the file.
	 */

	fgets(input, sizeof(input), dictPtr);

	while(!feof(dictPtr) )
	{
		/*
		 * Process the line if it is not a comment.
		 */

		if ( (strncmp(input, comment, 1) != 0) && (strncmp(input, blankLine, 1) != 0 ) )
		{
			/*
			 * First remove the newline character.
			 * Then replace multiple tab and space
			 * characters with single space characters.
			 */

			/* Remove the newline character, if present. 
			 * Replace the last character of the string
			 * array with with '\0'.
			 */

			input[strlen(input) - 1] = '\0';

			/* Now, remove the multiple space and tab
			 * characters.
			 */

			stringPack(line, input);
			
			g_strchomp(line); /* Remove trailing w/space. */
#ifdef	DEBUG
puts(line);
#endif	/* DEBUG */
			tokens = g_strsplit(line, " ", 0);
			
#ifdef DEBUG
			for (i = 0; tokens[i] != NULL; i++)
				printf("tokens[%d] = %s\n", i, tokens[i]);
#endif	/* DEBUG */

			/*
			 * We no longer need to know the scope of a variable
			 * woordenboek[entry].varScope = atoi(tokens[1]);
        */

			strcpy(woordenboek[entry].varName, tokens[0]);
			strcpy(woordenboek[entry].varSym, tokens[1]);
			strcpy(woordenboek[entry].varType, tokens[2]);
			woordenboek[entry].varNum = entry;
			fprintf(defnPtr, "%s\t%d\n", tokens[1], entry);
			++entry;

			g_strfreev( tokens );
		}
		fgets(input, sizeof(input), dictPtr);
	}		

fclose(dictPtr);
fclose(defnPtr);

}	/* End of ca_populateDictionary() function. */


void opSplitsen (FILE *filePtr, gchar **tokenArray)
{
/*
 * Declaring character constants is safer than using #define.
 * See Oualline's book, p.145.
 *
 */

const char *blankLine = "\n";		/* Declared as a string, not a character. */
const char *comment = "#";			/* Declared as a string. */
char line[99];
char input[99];
int lineNo = 0;
int j;


	fgets(input, sizeof(input), filePtr); /* Get the (first) line from the */
					 /* file to which filePtr points. */
	
#ifdef DEBUG
	printf("\nFIRST INPUT >>> %s\n", input);
#endif	/* DEBUG */

	/* Compare the first character of the input */
	/* to the comment and the newline strings. */

	if ( (strncmp(input, comment, 1) != 0) && (strncmp(input, blankLine, 1) != 0) )
					
				

		{
		/* Remove the newline character, if present. */
		/* Replace the last character */
		/* of the string array with '\0'. */

		input[strlen(input) - 1] = '\0';	
#ifdef DEBUG
printf("First Input >>> %s\n", input);
#endif /* DEBUG */

		strcpy(line, input);
#ifdef DEBUG
printf("First Line after copy >>> %s\n", line);
#endif 	/* DEBUG */

		stringPack(line, input);     
#ifdef DEBUG
printf("Line: %s\n", line);
#endif	/* DEBUG */

		g_strchomp(line);
/*		g_strdelimit(line, " ", ':');
 *		g_strdelimit(line, "\t", '*');
*/

#ifdef DEBUG
		printf("%3d> %s\n", ++lineNo, line);
#endif	/* DEBUG */

		/*
		 * g_strsplit() is a GLib function;
		 * it returns an array of strings.
		 * 
		 * Here, we split on two spaces, "  ".
		 * We set max_tokenArray to be 0.  We want the 
		 * first token to be the name of the variable
		 * and the other tokens to be the value of the variable,
		 * qualifiers, etc.
		 */

		tokenArray = g_strsplit(line, " ", 0);	

#ifdef DEBUG
		for (j = 0; tokenArray[j] != NULL; j++)
			printf("token[%d] = %s\n", j, tokenArray[j]);
#endif	/* DEBUG */

		} /* End of processing the first line, if not commented. */

		/* End of getting the first line. */


	/*Get the 2nd line of the file. */
	fgets(input, sizeof(input), filePtr);

	while(!feof(filePtr) )
		{
			
			/* Process the line if it is not commented. */
			if ( (strncmp(input, comment, 1) != 0) && (strncmp(input, blankLine, 1) != 0 ) )
			{
	   	/* Remove the newline character, if present. */ 
			input[strlen(input) -1] = '\0';
#ifdef DEBUG
printf("Subsequent Input >>> %s\n", input);
#endif	/* DEBUG */

			strcpy(line, input);
#ifdef DEBUG
printf("Subsequent Line after copy >>> %s\n", line);
#endif	/* DEBUG */

			stringPack(line, input);
#ifdef DEBUG
printf("Line: %s\n", line);
#endif	/* DEBUG */

			g_strchomp(line);
/*			g_strdelimit(line, " ", ':');
 *			g_strdelimit(line, "\t", '*');
 */

#ifdef DEBUG
			printf("%3d> %s\n", ++lineNo, line);
#endif	/* DEBUG */

			/*
			 * See the comment above about the maximum 
			 * number of tokens being set to 0.
			 */

			tokenArray = g_strsplit(line, " ", 0);

#ifdef DEBUG
			for (j = 0; tokenArray[j] != NULL; j++)
				{	
				printf("token[%d] = %s\n", j, tokenArray[j]);
				/* Can also use puts(tokenArray[j]) here. */
				}
#endif /* DEBUG */
			} /* Processed uncommented lines. */

		fgets(input, sizeof(input), filePtr);
		} /* Processed the 2nd & subsequent lines of the file. */

} /* End of processing the opened file. */


void ca_readConfig(const char *configFile, values_t confVars[], int size)
/*******************************************************************
 *																						*
 * ca_readConfig -- parses the config file and writes the values   *
 * 						 into memory.												*
 *																						*
 * Parameters																		*
 *		configFile -- the configuration file
	*		confVars[] -- the array of values structures						*
	*		size -- the number of configuration variables					*
 * 																						*
 * Returns																			*
 *		Nothing -- perhaps make this return 0 on successful exit ?	*
 *																						*
 * Note: 	Should we make the name of the config file a global		*
	*			variable ?																*	
 *******************************************************************/
{
FILE *confPtr;			/* Pointer to config file. */
char name[STRLENGTH_M];		/* The name of the config variable */
										/* 80 characters */
char value[STRLENGTH_XXL];			/* The value of the variable */
												/* 640 characters */
int location;			/* Storage Location of the variable's value. */
int type;	 /* Data type of the variable, represented by an integer. */


const char *blankLine = "\n";  /* Declared as a string, not a character. */
const char *comment = "#"; 		/* Declared as a string. */

char source[16];									/* The name of a source. */
char database[STRLENGTH_M]; 		/* The elements of a database. */
												/* 80 characters */
int mode;								/* The mode of operation of the src */
char srcOptions[16];				/* The options of a source. */
char nrtMirror[STRLENGTH_M];			/* The elements of a NRTM */
int updatePort;						/* The update port of the source */

gchar **dbcomps;	/* Pointer to an array of strings that represents */
							/* the components of a db. */

gchar **nrtmcomps; /* Pointer to an array of strings that represents */
							/* the components of a nrtm. */

gchar **optcomps;	/* Pointer to an array of strings that represents */
							/* the components of the options of a source. */

int i;					/* A counting variable. */

ca_database_t *newDbPtr; 	/* A pointer to a new instance of */
										/* ca_database_t.						 */

ca_mirror_t *newMirrPtr;		/* A pointer to a new instance of */
										/* ca_mirror_t.						 */

ca_database_list_t *newSrc;	/* A pointer to a new instance of */
										/* ca_database_list_t.				 */

ca_ripadmin_t	 *newAdminPtr;	/* A pointer to a new instance of */
											/* a ca_ripadmin_t variable. 	*/

/* 
 * Function Prototype for ca_getStorageLocation()
 * We put it here; thus it can only be called from 
 * within ca_readConfig()
 *
 * This function finds the location in the values_t array
 * where we store pointers to the string value and the actual
 * value of the variable.  It returns this location as an 
 * integer.
 *
 */
int ca_getStorageLocation(char [], dict_t [], int);

/*
	* Function Prototype for ca_getType()
	* We put it here so that it can only be called from
	* within ca_readConfig()
 *
 * This function returns the type of the configuration
 * variable.  It returns it as a string.
 *
 */
int ca_getType(char [], dict_t [], int);


#ifdef	DEBUG
printf("\nInside readConfig() function.\n");
printf("Configuration file is: %s\n", configFile);
#endif	/* DEBUG */

/*
	* Open the configuration file for reading .....
 */
if ( (confPtr = fopen(configFile, "r")) == NULL)
		{
		printf("Error: file %s could not be opened.\n", configFile);
		die;
		}

/*
	* Read the first record in the configuration file .....
 * We read the _name_ of the variable using fscanf into a
 * string array.  We read the _value_ of the variable
 * using fgets into an array; thus, we can handle values of
 * variables with qualifiers (e.g. SPLIT after DBLIST) and
 * values with blank characters (e.g. REPLYBANNER).
 */
fscanf(confPtr, "%s", name);
fgets(value, sizeof(value), confPtr);


/* 
	* 		While there are records to be read in the config file.
	*		write the current record into memory,
 *     read the next record in the config file
 */


while (!feof(confPtr) )
	{

/*
	* From the variable name, find the dictionary number.
 * The dictionary number is defined as the place in the 
 * values array in which to store the value of the variable.
 * 
 */

		/*
		 * Process the line only when/if it is not a comment or 
		 * a blankline.
     */
		if ( (strncmp(name, comment, 1) != 0) && (strncmp(name, blankLine, 1) != 0) )
			{
			/*
 		 * If the last character of "value" is '\n',
        * replace it with '\0'.
        */
			if ( value[strlen(value) - 1] == '\n')
				{
				value[strlen(value) - 1] = '\0';
				}

			/*
			 * From the variable name, find the element of the values
			 * array in which to store the value of the variable.
        *
			 */
			location = ca_getStorageLocation(name, dictionary, VARS);

#ifdef DEBUG
			printf("The location is: %d\n", location);
#endif	/* DEBUG */

			/*
			 * See if the string value has already been stored;
			 * if it has, then concatenate the new value to it;
			 * if not, then allocate some memory and copy the
			 * string into it.
			 */

			/*
			 * If this variable already exists, it has a non-zero
        * value and this 'if' statement returns a "true" value.
			 * Otherwise, it returns a "zero" or "false" value.
			 */
			if (confVars[location].strPtr)
				{
				strcat(confVars[location].strPtr, "\n");
				strcat(confVars[location].strPtr, value);
				}
			else
				{
			/*
			 * Store a pointer to the string that contains the value
			 * This is not necessarily the actual value itself.
			 * First, we must allocate some memory.
			 */
			confVars[location].strPtr = (char *)malloc(STRLENGTH_XXL);
			/*
			 * We check the return value of the malloc function .....
        */	
			if (confVars[location].strPtr == NULL)
				{
				fprintf(stderr, "Cannot allocate memory for confVars[location].strPtr\n");
				die;
				}
			strcpy(confVars[location].strPtr, value);
				}

			/*
			 * Now, store a pointer to the _value_ of the variable.  
			 * Do this as follows:
			 * (a) get the _type_ of the variable
			 * (b) store a pointer to the value of the variable in 
			 *     a way that depends on the _type_ of the variable.
        */
#ifdef DEBUG
printf("Variable \"%s\" is data-type \"%d\"\n", name, ca_getType(name, dictionary, VARS) );
#endif /* DEBUG */


type = ca_getType(name, dictionary, VARS);

			/*
			 * Given the _type_ of the variable, store the value of the
  		 * variable in the appropriate way.
			 */		 
			switch(type)	
				{
				case 11:

#ifdef DEBUG
				puts("Data type is Integer");
#endif	/* DEBUG */

				confVars[location].valPtr = malloc(sizeof(int) );
				if (confVars[location].valPtr == NULL)
					{
					fprintf(stderr, "Cannot allocate memory !!!\n");
					die;
					}
				sscanf(value, "%d", (int *) confVars[location].valPtr);
				break;

				case 12:

#ifdef DEBUG
				puts("Data type is String !!! *** !!!");
#endif	/* DEBUG */


				/*
				 * Test if this variable has already been created.
				 * Look for a non-zero i.e. true value.
				 *
				 * First put a '\n' character at the end of the existing 
           * string.
				 * Then, concatenate the additional string.
				 */
				if (confVars[location].valPtr) 
					{
#ifdef DEBUG
					printf("\n%s variable already exists\n", name);
#endif /* DEBUG */
					strcat(confVars[location].valPtr, "\n");
					strcat(confVars[location].valPtr, value);
					}	
				else
					{
					/*
					 * If the variable has not already been created,
					 * then create it.
					 */
#ifdef DEBUG
					printf("\n%s variable does not exist\n", name);
#endif	/* DEBUG */
				
					confVars[location].valPtr = (char *)malloc(STRLENGTH_XXL);
					if (confVars[location].valPtr == NULL)
						{
						fprintf(stderr, "Cannot allocate memory !!!\n");
						die;
						}
					 strcpy(confVars[location].valPtr, value);
					}

				break;

				case 13:
#ifdef DEBUG
				puts("Data type is Dirlist");
#endif	/* DEBUG */
				confVars[location].valPtr = (char *)malloc(STRLENGTH);
				if (confVars[location].valPtr == NULL)
					{
					fprintf(stderr, "Cannot allocate memory !!!\n");
					die;
					}
				 strcpy(confVars[location].valPtr, value);
				break;

				case 14:
#ifdef DEBUG
				puts("Data type is Boolean");
#endif	/* DEBUG */
				confVars[location].valPtr = (char *)malloc(2);
				if (confVars[location].valPtr == NULL)
					{
					fprintf(stderr, "Cannot allocate memory !!!\n");
					die;
					}
				 strcpy(confVars[location].valPtr, value);
				break;

				case 15:
#ifdef DEBUG
				puts("Data type is Source !!!");
#endif	/* DEBUG */

#ifdef DEBUG
puts(name);
puts(value);
#endif	/* DEBUG */
				/*
				 * Split the value into "source" and "database"
           * Use blankspace as the delimiter between the
				 * "source" and "database".
				 */
				sscanf(value, "%s %s %d %s %d %s", source, database, &mode, nrtMirror, &updatePort, srcOptions);
#ifdef DEBUG
puts(source);
puts(database);
printf("%d\n", mode);
puts(nrtMirror);
printf("%d\n", updatePort);
puts(srcOptions);
#endif	/* DEBUG */

				/*
				 * Using the values in "database".
				 * populate a ca_database_t structure.
				 * Give this variable a name.
				 *
				 */

	          	/* First, separate the values in "database", using "," as 
					 * as a delimiting  character.
					 */
				dbcomps = g_strsplit(database, ",", 0);

#ifdef DEBUG                                            
for (i = 0; dbcomps[i] != NULL; i++)
		printf("dbcomps[%d] = %s\n", i, dbcomps[i]);
#endif  /* DEBUG */


					/*
					 * Create a structure for this database.
					 */
				newDbPtr = calloc(1,sizeof(ca_database_t));
				if (newDbPtr == NULL)
					{
					fprintf(stderr, "Cannot allocate memory to new db structure\n");
					die;
					}

				strcpy(newDbPtr->host, dbcomps[0]);
				newDbPtr->port = atoi(dbcomps[1]);
				strcpy(newDbPtr->user, dbcomps[2]);
				strcpy(newDbPtr->password, dbcomps[3]);
				strcpy(newDbPtr->dbName, dbcomps[4]);
				
				g_strfreev(dbcomps);
#ifdef DEBUG
puts("Testing the population of the db structure:");
printf("\n%s::%d::%s::%s::%s\n", newDbPtr->host, newDbPtr->port, newDbPtr->user, newDbPtr->password,  newDbPtr->dbName);
#endif /* DEBUG */
 


				/*
				 * The mode of operation of the source has already been 
				 * set in the sscanf statement above.
				 */

				/*
				 * Using the values in "nrtMirror".
				 * populate a ca_mrrror_t structure.
				 * Give this variable a name.
				 *
				 */

	          	/* First, separate the values in "nrtMirror", using "," as 
					 * as a delimiting  character.
					 */
				nrtmcomps = g_strsplit(nrtMirror, ",", 0);

#ifdef DEBUG                                            
for (i = 0; nrtmcomps[i] != NULL; i++)
		printf("nrtmcomps[%d] = %s\n", i, nrtmcomps[i]);
#endif  /* DEBUG */


					/*
					 * Create a structure for this near-real-time mirror.
					 */
				newMirrPtr = calloc(1,sizeof(ca_mirror_t));
				if (newMirrPtr == NULL)
					{
					fprintf(stderr, "Cannot allocate memory to new nrtm structure\n");
					die;
					}

				strcpy(newMirrPtr->host, nrtmcomps[0]);
				newMirrPtr->port = atoi(nrtmcomps[1]);
				strcpy(newMirrPtr->log, nrtmcomps[2]);
				newMirrPtr->delay = atoi(nrtmcomps[3]);
				newMirrPtr->protocolVer = atoi(nrtmcomps[4]);
#ifdef DEBUG
puts("Testing the population of the nrtm structure:");
printf("\n%s::%d::%s::%d::%d\n", newMirrPtr->host, newMirrPtr->port, newMirrPtr->log, newMirrPtr->delay, newMirrPtr->protocolVer);
#endif /* DEBUG */

                                g_strfreev(nrtmcomps);
				/*
				 * The update port was already set by the sscanf 
				 * statement above.
				 */

				/*
				 * Using the values in "srcOptions"
				 * get the values for the canupd and deflook 
				 * components od the ca_dbSource_t structure.
				 *
				 */

	          	/* First, separate the values in "srcOptions", using "," 
					 * as a delimiting  character.
					 */
				optcomps = g_strsplit(srcOptions, ",", 0);

#ifdef DEBUG                                            
for (i = 0; optcomps[i] != NULL; i++)
		printf("optcomps[%d] = %s\n", i, optcomps[i]);
#endif  /* DEBUG */


				/*
				 * Using the above ca_database_t structure
				 * and the "source" value, 
				 * populate the ca_dbSource_t structure.
				 */
			
					/*
					 * Create a new structure for this source.
					 */
				newSrc = calloc(1,sizeof(ca_dbSource_t));

				if (newSrc == NULL)
					{
					fprintf(stderr, "Cannot allocate memory to new source structure\n");
					die;
					}

				strcpy(newSrc->name, source);
				newSrc->db = *newDbPtr;
				newSrc->opMode = mode;
				newSrc->nrtm = *newMirrPtr;
				newSrc->updPort = updatePort;
				strcpy(newSrc->canupd, optcomps[0]);
				strcpy(newSrc->deflook, optcomps[1]);

				free(newMirrPtr); /* was copied */
				free(newDbPtr); /* was copied */
				g_strfreev(optcomps);

#ifdef DEBUG
puts("Testing the population of the ca_dbSource_t structure:");
printf("Source name: %s\n", newSrc->name);
printf("\nDB == %s::%d::%s::%s::%s\n", (newSrc->db).host, (newSrc->db).port, (newSrc->db).user, (newSrc->db).password, (newSrc->db).dbName);
printf("Mode: %d\n", newSrc->opMode);
printf("NRTM == %s::%d::%s::%d:%d\n", (newSrc->nrtm).host, (newSrc->nrtm).port, (newSrc->nrtm).log, (newSrc->nrtm).delay, (newSrc->nrtm).protocolVer);
printf("UpdPort: %d\n", newSrc->updPort);
printf("Src Options == %s::%s\n", newSrc->canupd, newSrc->deflook);
#endif /* DEBUG */

				/*
				 * Append this ca_src_t structure to the sourceList,
				 * which is a singly-linked list if type GSList.
				 */

sourceList = g_slist_append(sourceList, newSrc);

/*
 * 20000609
	* Experiment:
	* Add the newSrc to the other variable describing the list of sources,
 * mySrcList
 * 
 * mySrcList = g_slist_append(mySrcList, newSrc);
 */

				break;

				case 16:
#ifdef DEBUG
puts("Found the CA_ADMIN stuff !!!");
#endif	/* DEBUG */
				/* The elements of the Admin-DB have already been read in. */
				/* Now, split up the elements and assign them to the */
 			/* components of the Admin-DB structure. */
				/* First, separate the values in "value", using ',' as a */
				/* delimiting character.	*/
				dbcomps = g_strsplit(value, ",", 0);

#ifdef DEBUG				
for (i = 0; dbcomps[i] != NULL; i++)
                printf("dbcomps[%d] = %s\n", i, dbcomps[i]);
#endif  /* DEBUG */

				/*
				 * Now, allocate some memory to the newAdminPtr.
				 */
			   newAdminPtr = calloc(1, sizeof(ca_ripadmin_t) );

				/*
				 * Check that we actually got the memory.
				 */
				if (newAdminPtr ==NULL)
					{	
					fprintf(stderr, "Cannot allocate memory to new admin-db structure\n");
					die;
					}
					
				/*
				 * Now, assign the elements of the dbcomps array to the 
				 * appropriate components of the structure to which 
				 * newAdminPtr points.
				 */
				
				strcpy(newAdminPtr->host, dbcomps[0]);
				newAdminPtr->port = atoi(dbcomps[1]);
				strcpy(newAdminPtr->user, dbcomps[2]);
				strcpy(newAdminPtr->password, dbcomps[3]);
				strcpy(newAdminPtr->tableName, dbcomps[4]);

				g_strfreev(dbcomps);

#ifdef DEBUG
puts("Testing the population of the rip-admin db structure:");
printf("\n%s::%d::%s::%s::%s\n", newAdminPtr->host, newAdminPtr->port, newAdminPtr->user, newAdminPtr->password, newAdminPtr->tableName);
#endif /* DEBUG */

				/*
				 * Now, assign these values into the correct long-term
				 * storage.
				 */


				confVars[location].valPtr = (ca_ripadmin_t *)calloc(1, sizeof(ca_ripadmin_t) );


				/*
				 * Check that we actually got the memory.
				 */
				if (confVars[location].valPtr == NULL)
					{	
					fprintf(stderr, "Cannot allocate memory to new admin-db structure\n");
					die;
					}
				
				memcpy(confVars[location].valPtr, newAdminPtr, sizeof(ca_ripadmin_t));
				/*
				strcpy( ((ca_ripadmin_t *)confVars[location].valPtr)->host, newAdminPtr->host);
				(confVars[location].valPtr)->port = newAdminPtr->port; 
			 	strcpy( (confVars[location].valPtr)->user, newAdminPtr->user);
			 	strcpy( (confVars[location].valPtr)->password, newAdminPtr->password);
			 	strcpy( (confVars[location].valPtr)->tableName, newAdminPtr->tableName);
				*/
			
          free(newAdminPtr);
#ifdef DEBUG
				printf("The ripadmin machine is: %s\n", ((ca_ripadmin_t *)confVars[location].valPtr)->host);
#endif	/* DEBUG */

				break;

				default:
				fprintf(stderr, "Data type not found for variable \"%s\".\n", name);
				die;
				break;
				}
	 		}

fscanf(confPtr, "%s", name);
fgets(value, sizeof(value), confPtr);

	}	/* End of processing the config file. */

}	/* End of readConfig() function */


/*
 * void ca_populateDictionary(dictionary_t woordenboek[], int size, FILE *fiPtr)
 * {
 * int j;
 * char input[99];
 * 
 * for (j=0; (j < size) && !feof(fiPtr); j++)
 * 	j = 0;
 * 	while ((j < size) && !feof(fiPtr) )
 * 	{
 * 	printf("\n%d\n", j);
 * 	
 * 	fgets(input, sizeof(input), filePtr);
 * 
 * 	if ( (strncmp(input, comment, 1) != 0) && (strncmp(input, blankLine, 1) 
 * != 0) )
 * 	{
 * 	fscanf(fiPtr, "%s %s %s %s", woordenboek[j].varName, woordenboek[j].varScope, woordenboek[j].varSym, woordenboek[j].varType);
 * 	}
 * 
 * 	fgets(input, sizeof(input), filePtr);
 * 	printf("%s\n", woordenboek[j].varName);
 * 	}
 * }
 * 
 */


void ca_getDictionary(dict_t woordenboek[], int size)
{
int k;

for (k = 0; k <= size; k++)
	{
	printf("\nj = %d\n", k);
 /*
	 * printf("%s\t%d\t%s\n", woordenboek[k].varName, woordenboek[k].varScope, woordenboek[k].varType);
	 */
	 printf("%s\t%s\t%s\t%d\n", woordenboek[k].varName, woordenboek[k].varSym, woordenboek[k].varType, woordenboek[k].varNum);

	}
}


int ca_get_int(int symbol)
{
int *xPtr;

		/*
		 * First print a message saying that the ca_get_int()
		 * function is being called.
		 */
#ifdef DEBUG
	printf("\nDEBUG: ca_get_int() function is called .....\n");
printf("DEBUG: New value of StringPtr: %s\n", confVars[symbol].strPtr);
#endif 	/* DEBUG */

		/*
		 * Look at the appropriate place in the dictionary;
		 * e.g. C_BINDPORT => the first element, index = 0.
		 *
		 * if the varType is not an integer, exit with an error;
		 *
		 * otherwise, 
		 *		if the varScope is global, look for the value in the
		 *		appropriate place in memory in the global values array;
		 *    otherwise, look for the value in the appropriate place in 
		 * 	memory in the local values array;
		 *
		 *
		 */

		/* Look at the appropriate place in the dictionary. */

#ifdef DEBUG
		printf("\nDEBUG: Variable type: %s\n", dictionary[symbol].varType);
#endif	/* DEBUG */

		/* If the variable type is not an integer, exit with an error. */
		if ( strcmp(dictionary[symbol].varType, "CA_INT") != 0)
			{
			fprintf(stderr, "Error: unexpected variable type.\n");
			die;
			}
		else
			{
			/*
			 * If the variable has global scope, look for it in 
			 * the globals array.  Otherwise, look for it in the
			 * locals array.
			 *
			 */
			

/*
 *				switch(dictionary[symbol].varScope)
 *					{
 *					case 1:
 *					printf("\nThis variable has global scope.\n");
 *					printf("The string is: %s\n", globals[symbol].strPtr);
 *					printf("String2Value: %d\n", atoi(globals[symbol].strPtr));
 *
 *					xPtr = globals[symbol].valPtr;
 *					printf("Value: %d\n", *xPtr);
 *					return(*xPtr);
 *					break;
 *
 *					case 99:
 *					printf("\nThis variable has local scope.\n");
 *					printf("The string is %s\n", locals[symbol].strPtr);
 *					printf("String2Value: %d\n", atoi(locals[symbol].strPtr));
 *					xPtr = locals[symbol].valPtr;
 *					printf("Value: %d\n", *xPtr);
 *					return(*xPtr);
 *					break;
 *
 *					default:
 *					printf("\nAaaargh !!!  This variable has unwelcome scope.\n");			
 *					break;
 *					}
 */

			/*
			 * Lock the value of the variable before reading it.
		 	 */

			mutex_lock(&Lock);

			xPtr = confVars[symbol].valPtr;
			/* 
			 * Unlock the value of the variable after reading it.
			 */
			mutex_unlock(&Lock);
			return(*xPtr);
			}
	
}

char *ca_get_dirlist(int symbol)
{
/*
 * This function returns a pointer to a character array.  Thus,
 * we need to declare such a pointer.
 *
 */

char *xPtr;
#ifdef	DEBUG
	printf("\nca_get_dirlist() function is called .....\n");
#endif	/* DEBUG */


		/*
		 * Look at the appropriate place in the dictionary;
		 * e.g. CA_HELP => the second element, index = 1.
		 *
		 * if the varType is not CA_DIRLIST, exit with an error;
		 *
		 * otherwise, 
		 *		if the varScope is global, look for the value in the
		 *		appropriate place in memory in the global values array;
		 *    otherwise, look for the value in the appropriate place in 
		 * 	memory in the local values array;
		 *
		 *
		 */

		/* Look at the appropriate place in the dictionary. */
		#ifdef DEBUG	
		printf("\nVariable type: %s\n", dictionary[symbol].varType);
		#endif	/* DEBUG */	

		/* If the variable type is not CA_DIRLIST, exit with an error. */
		if ( strcmp(dictionary[symbol].varType, "CA_DIRLIST") != 0)
			{
			fprintf(stderr, "Error: unexpected variable type.\n");
			die;
			}
		else
			{
			/*
			 * If the variable has global scope, look for it in 
			 * the globals array.  Otherwise, look for it in the
			 * locals array.
			 *
			 */

/*
	* This next piece of code (switch statements, etc.) is not
 * needed.  We do not have global or local variables anymore.
 */			

/*
 * 				switch(dictionary[symbol].varScope)
 * 					{
 * 					case 1:
 * 					printf("\nThis variable has global scope.\n");
 * 					printf("The string is: %s\n", globals[symbol].strPtr);
 * 					xPtr = strdup(globals[symbol].valPtr);
 * 					printf("Value: %s\n", xPtr);
 * 					return(xPtr);
 * 					break;
 * 
 * 					case 99:
 * 				
 * 					printf("\nThis variable has local scope.\n");
 * 					printf("The string is %s\n", locals[symbol].strPtr);
 * 					xPtr = locals[symbol].valPtr;
 * 					printf("Value: %s\n", xPtr);
 * 					return(xPtr);
 * 					break;
 * 
 * 					default:
 * 					printf("\nAaaargh !!!  This variable has unwelcome scope.\n");			
 * 					break;
 * 					}
 */
 
				mutex_lock(&Lock);
				xPtr = (strdup(confVars[symbol].valPtr));
				#ifdef DEBUG
				printf("Value: %s\n", xPtr);
				#endif	/* DEBUG */
				mutex_unlock(&Lock);	
				return(xPtr);
			}
	
}


char *ca_get_string(int symbol)
{
/*
 * This function returns a pointer to a character array.  Thus,
 * we need to declare such a pointer.
 *
 */

char *xPtr;
#ifdef	DEBUG
	printf("\nca_get_text() function is called .....\n");
#endif	/* DEBUG */


		/*
		 * Look at the appropriate place in the dictionary;
		 * e.g. CA_REPLYBANNER => the third element, index = 2.
		 *
		 * if the varType is not CA_STRING, exit with an error;
		 *
		 * otherwise, 
		 *		if the varScope is global, look for the value in the
		 *		appropriate place in memory in the global values array;
		 *    otherwise, look for the value in the appropriate place in 
		 * 	memory in the local values array;
		 *
		 *
		 */

		/* Look at the appropriate place in the dictionary. */
		
#ifdef DEBUG
		printf("\nVariable type: %s\n", dictionary[symbol].varType);
#endif	/* DEBUG */
	
		/* If the variable type is not CA_STRING, exit with an error. */
		if ( strcmp(dictionary[symbol].varType, "CA_STRING") != 0)
			{
			fprintf(stderr, "Error: unexpected variable type.\n");
			die;
			}
		else
			{
			/*
			 * If the variable has global scope, look for it in 
			 * the globals array.  Otherwise, look for it in the
			 * locals array.
			 *
			 */

/*
 * We do not need this code any longer.  We do not use
 * global or local variables or the associated arrays,
 * 'globals' and 'locals'.
 *
 *				switch(dictionary[symbol].varScope)
 *					{
 *					case 1:
 *					printf("\nThis variable has global scope.\n");
 *					printf("The string is: %s\n", globals[symbol].strPtr);
 *					xPtr = globals[symbol].valPtr;
 *					printf("Value: %s\n", xPtr);
 *					return(xPtr);
 *					break;
 *
 *					case 99:
 *					printf("\nThis variable has local scope.\n");
 *					printf("The string is %s\n", locals[symbol].strPtr);
 *					xPtr = locals[symbol].valPtr;
 *					printf("Value: %s\n", xPtr);
 *					return(xPtr);
 *					break;
 *
 *					default:
 *					printf("\nAaaargh !!!  This variable has unwelcome scope.\n");			
 *					break;
 *				}
 */
				mutex_lock(&Lock);
				xPtr = (strdup(confVars[symbol].valPtr));
				#ifdef DEBUG
				printf("Value: %s\n", xPtr);
				#endif	/* DEBUG */
				mutex_unlock(&Lock);
				return(xPtr);
			
			}
}


int ca_get_boolean(int symbol)
{
/**********************************************
 * ca_get_boolean()									*
	* 															*
	*															*
	* Parameters											*
	*															*
	*	symbol -- the symbol for the variable		*
 *															*
	*															*
	* Returns												*
	*															*
	*	1 if true, 0 if false.							*
 *															*
 * Remarks												*
	*															*
 *   Is there a better way to implement 		*
	*   Boolean values in C ?							*
 *															*
	*********************************************/

int *xPtr;

/*
 * Print this message if in debug mode.
 *
 */
#ifdef DEBUG
	printf("\nca_get_boolean() function is called .....\n");
printf("DEBUG 5: New value of StringPtr: %s\n", globals[symbol].strPtr);
#endif	/* DEBUG	*/

/**********************************************\
 *															*
	* Here is how this works:							*
 * 															*
 * (a) Check that the type of variable whose 	*
 *     value is being read is CA_BOOLEAN.		*
 *															*
 * (b) Lock the value of the variable before	*
 * 		reading it.										*
 *															*
 * (c) Depending on the scope of the variable	*
 *     look for it in the appropriate array.	*
 *															*
	* (d) Read the value of the variable.			*
 *															*
	* (e) Unlock the value of the variable after *
 *		reading it.										*
	*															*
 *															*
 * Returns												*
	*
	*	an integer value as follows:					*
	*		1 if the db is in testmode (true),							*
	*		0 if the db is not in testmode (false).					*
\*********************************************/


/*
	* Look at the appropriate place in the dictionary; 
	* e.g. CA_BOOLEAN = the fifth element of the dict_t array,
 * => index = 4.
 *
 * If the varType is not Boolean, exit with an error
	* 
 * Otherwise,
	*	if the varScope is global, look for the value in the
	* 	appropriate place in the global values array;
	*
	*	otherwise, look for the value in the appropriate place in the
	*	locals array.
	*
 */

#ifdef DEBUG
/* Look in the appropriate place in the dictionary. */
printf("\nVariable type: %s\n", dictionary[symbol].varType);
#endif	/* DEBUG */

/* If the variable type is not Boolean, exit with an error. */

	if ( strcmp(dictionary[symbol].varType, "CA_BOOLEAN") != 0)
		{
		fprintf(stderr, "Error: Boolean type expected.\n");
		die;
		}

	else
		{
		
		/*
		 * If the variable has global scope, look for it in the globals
		 * array.  Otherwise, look for it in the locals array.
		 *
     */
/* 
 * We do not need this code (switch statements, etc.) anymore.
 */

/*
 *		switch(dictionary[symbol].varScope)
 *			{
 *			case 1:
 *			printf("\nThis variable has global scope.\n");
 *			printf("The string is: %s\n", globals[symbol].strPtr);
 *			printf("String2Value: %d\n", atoi(globals[symbol].strPtr) );
 *			xPtr = globals[symbol].valPtr;
 *			printf("Value: %d\n", *xPtr);
 *			return (*xPtr);
 *			break;
 *
 *			case 99:
 *			printf("\nThis variable has local scope.\n");
 *			printf("The string is %s\n", locals[symbol].strPtr);
 *			printf("String2Value: %d\n", atoi(locals[symbol].strPtr) );
 *			xPtr = locals[symbol].valPtr;
 *			printf("Value: %d\n", *xPtr);
 *			return(*xPtr);
 *			break;
 *
 *			default:
 *			printf("\nError: This variable has unknown scope.\n");
 *			break;
 *
 *			}
 */

		/*
		 * Lock the value of the variable before reading it.
		 *
		 */
		
		mutex_lock(&Lock);
		xPtr = confVars[symbol].valPtr;
		/*
		 * Unlock the value of the variable after reading it.
		 */
		mutex_unlock(&Lock);
		
		return(*xPtr);
	}	
}



void ca_set_int(int symbol)
{
	/*********************************************
	 * ca_set_int()										*
  *  														*
	 * Parameters											*
	 *		symbol -- the symbol for the variable.	*
	 *															*
	 * Returns												*
	 *		1 if successful 0 if not ?					*
	 *															*
	 * Remarks												*
	 * 	Needs a better way to check for valid  *
  *    values from the keyboard.					*
	 *															*
	 *********************************************/

	void *tempPtr;		/* Temp pointer to point to the value pointer
								in the appropriate values array. */
 char newPort[16];
 int invalid;
 int portNr;

 /* Function to change the value in a given values array.
  * This function can only be called from within ca_set_int().
	 */
 int *ca_change_int_value(char []); 
 void testFunction(values_t values[]);

	/*
  * Using the symbol, look at the appropriate place in the
	 * dictionary.
	 */
#ifdef DEBUG
 printf("\nca_set_int() function called .....\n");
	printf("Variable type: %s\n", dictionary[symbol].varType);
#endif	/* DEBUG */


/*
 * Make sure that a reasonable, sensible value of bind-port has
 * been read from the keyboard.
 */

do	{

		/*
		 * First, flush input stream.
     */
		fflush(stdin);

		/*
		 * Prompt for the new value of the bind-port.
		 */
		
		printf("\nNew value of bind-port (non-zero positive integer) >>> ");
		scanf("%s", newPort);
		/*
		 * gets(newPort);                                  
		 */
#ifdef DEBUG
		printf("\nDEBUG: Value of newPort variable: %s\n", newPort);
#endif	/* DEBUG */

		sscanf(newPort, "%d", &portNr);

#ifdef DEBUG
		printf("\nDEBUG: Value of integer variable, portNr: %d\n", portNr);
#endif	/* DEBUG */
		
			if (portNr < 0)
				{
				invalid = 1;
				puts("Only non-zero positive integer values accepted for bind-port");
				}
			else
				{
				invalid = 0;
				}

		} while(invalid);

 /*
	 * Check that the function is attempting to set the correct type
	 * of value.  If not, do not set the value and exit.
	 */

	if (strcmp(dictionary[symbol].varType, "CA_INT") != 0)
		{
		fprintf(stderr, "Error: unexpected variable type.\n");
		die;
		}

	/*
	 * Choose the appropriate values array.  
	 */
	switch(dictionary[symbol].varScope)
		{
		/* If the variable has global scope, 
		 * write it into the globals array.
		 * If it has local scope,
		 * write it into the local array.
		 * If the scope cannot be found, then report an error.
		 */
		case 1:
		globals[symbol].valPtr = ca_change_int_value(newPort);
		globals[symbol].strPtr = newPort;
		
		globals[symbol].strPtr = (char *)calloc(1,sizeof(newPort) );
		
		/* Check the return value of malloc() to make sure that we 
		 * actually got the memory.
		 */
		if (globals[symbol].strPtr == NULL)
			{	
			fprintf(stderr, "Cannot allocate memory for globals[symbol].strPtr.\n");
			die;
			}
#ifdef DEBUG
		printf("DEBUG: New value of StringPtr: %s\n", globals[symbol].strPtr);
#endif	/* DEBUG */

		strcpy(globals[symbol].strPtr, newPort);

#ifdef DEBUG
		printf("DEBUG 2: New value of StringPtr: %s\n", globals[symbol].strPtr);
#endif	/* DEBUG */
		break;

		case 99:
		locals[symbol].valPtr = ca_change_int_value(newPort);
		/*
		 * First allocate some memory and then copy the value of the new 
		 * Port into it.
     */
		locals[symbol].strPtr = (char *)calloc(1,sizeof(newPort) );
		/* 
		 * Now, check that the memory was actually allocated.
		 */
		if (locals[symbol].strPtr == NULL)
			{
			fprintf(stderr, "Cannot allocate memory for locals[symbol].strPtr\n");
			exit(8);
			}
		
		strcpy(locals[symbol].strPtr, newPort);
		/*
		 * locals[symbol].strPtr = newPort;
		 */	
		break;

		default:
		fprintf(stderr, "Error; unknown scope: %d\n", dictionary[symbol].varScope);
		break;
		}

 /*
  * Write the new value of the variable to the correct place in 
  * this array.  (First, set a mutex lock ???).
	 */

 /*
	 * Write the new value of this variable back to the config. file
	 */

ca_writeNewValue(symbol, newPort);

		printf("DEBUG 3: New value of StringPtr: %s\n", globals[symbol].strPtr);

}

int *ca_change_int_value(char value[])
{
void *tempPtr;

/*
 * Check the return value of malloc() in case we did not actually get
 * the memory.
 */
tempPtr = malloc(sizeof(int) );
if (tempPtr == NULL)
		{
		fprintf(stderr, "Cannot allocate memory for tempPtr\n");
		die;
		}

sscanf(value, "%d", (int *) tempPtr);
return(tempPtr);
}



void testFunction(values_t array[])
{
	printf("\nInside the Test function.\n");
	}


void ca_getDatabase(ca_database_t db)
{
printf("\n%s\t%s\t%s\t%s\t%s\n", db.host, db.port, db.user, db.password, db.dbName);
}

void ca_getSource(ca_database_list_t src)
{
printf("\n%s\t%s\t%s\t%s\t%s\t%s\n", src.name, (src.db).host, (src.db).port, (src.db).user, (src.db).password, (src.db).dbName);
}


void ca_getAllSources(GSList *sources)
{
	 
GSList *currentPtr;	/* Pointer to the structure at which we look. */

/*
 * Look at the first member of the linked-list of sources.
 */
currentPtr = sources;

/*
 * Look at each data component of the source list,
 * untill we reach the end of the list.
 */
while(currentPtr != NULL)
	{
 ca_database_list_t *srcPtr = currentPtr->data;
printf("\n%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\n", srcPtr->name, (srcPtr->db).host, (srcPtr->db).port, (srcPtr->db).user, (srcPtr->db).password, (srcPtr->db).dbName);
 currentPtr = currentPtr->next;	
	}
}

void ca_getAsource(char *sourceName, GSList *sources)
/*******************************************************************
 * ca_getAsource -- looks for a source in the linked list				*
 *																						*
 * Parameters																		*
	*	sourceName -- the name of a source for which to look 				*
	*  sources -- the list of sources in which to look						*
 *																						*
 * Returns																			*
 *  nothing, so far.																*
 *																						*
 *******************************************************************/
{
	 
GSList *currentPtr = sources; 

#ifdef DEBUG
printf("\nLooking for source: %s\n", sourceName);
#endif	/* DEBUG */

/*
 * Look at each data component of the source list,
	* compare the name of the source with the sourceName
 * untill we find the source o we reach the end of the list 
 */
{	/* Begin special block 
		 * I got a syntax error when I defined 
		 * "ca_database_list_t *srcPtr = currentPtr->data;"
		 * in the usual way, with all the other local variables.
		 *
     * However, if I define it inside this block, I do not
		 * get any syntax errors.
	    *
 	 */
		

ca_database_list_t *srcPtr = currentPtr->data;
#ifdef DEBUG
printf("FirstSource is: %s\n", srcPtr->name);
#endif	/* DEBUG */
while( (currentPtr != NULL) && ( strcmp(srcPtr->name, sourceName) != 0 ) )
	{
#ifdef DEBUG
 puts("Now printing the current source .....");
 printf("CurrentSource is: %s\n", srcPtr->name);
 printf("%d\n", strcmp(srcPtr->name, sourceName) );
 if ( strcmp(srcPtr->name, sourceName) == 0 ) 
		{
		printf("Found it !!! Source: %s\n", srcPtr->name);
		}
#endif	/* DEBUG */
 currentPtr = currentPtr->next;	
	puts("currentPtr = currentPtr->next");
	if (currentPtr != NULL)
	{
 	srcPtr = currentPtr->data;
 	puts("srcPtr = currentPtr->data");
 }
 #ifdef DEBUG
		puts("At the end of the while loop inside ca_getAsource function .....");
 	printf("The NewSource is: %s\n", srcPtr->name);
 #endif	/* DEBUG */
	}
#ifdef DEBUG
puts("Exited from while loop in ca_getAsource function .....");
#endif /* DEBUG */

if (currentPtr != NULL)
	{
 printf("\nFound the source: %s\n", srcPtr->name); 
/* printf("\n%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", srcPtr->name, (srcPtr->db).host, (srcPtr->db).port, (srcPtr->db).user, (srcPtr->db).password, (srcPtr->db).canupd, (srcPtr->db).deflook, (srcPtr->db).dbName);
*/
 }
else
	{
	printf("\nCould not find source: %s\n", sourceName);
	}
}	/* End special block */

}


ca_dbSource_t *ca_getSourceDetails(char *sourceName, GSList *sources)
/*******************************************************************
 * ca_getSourceDetails															*
 * 	-- A function that compares each 'name' component of every 		*
 *		ca_database_list_t element in the linked-list of sources		*
	*		(the first element of which is a parameter of this function)*
 *		with the name of the source to be found.  If the required	*
	*		source is found, a pointer to the structure representing 	*
 * 		this source is returned.												*
	*																						*
	*	Parameters																		*
	*	--	sourceName - the name of the required source						*
	*	--	sources	- the list of sources in which to look					*
	*																						*
 * 	Returns																			*
	*	-- srcPtr - a pointer to the structure representing the source	*
	*            - or a pointer to NULL, if we cannot find the source *
 *																						*
 *******************************************************************/
{
/* 
	* Define a pointer to the current element in the linked list.
 * Initialise it to the start of the list;
 */
GSList *currentPtr = sources; 	

	/*
		* Define and initialise a pointer that points to the 'data'
	 * component of the GSList struct; i.e. a pointer to a 
	 * variable of type ca_dbSource_t.
	 */
ca_dbSource_t *srcPtr = currentPtr->data;								 
	
	
	/*
		* Look at each data component of list of sources;
		* (each data component is a structure of type ca_dbSource_t
		* i.e. ca_database_list_t).  Compare the 'name' component of
	 * of each ca_dbSource_t structure with the value of sourceName 
	 * untill we get a match or we reach the end of the list.
		*/
	/*
	 * We first check if currentPtr is pointing to NULL;
	 *		if yes, we exit the while loop;
	 * 	if no, we make srcPtr point to the data component
	 *    of the current dbSource structure;
	 *			then, we check if this is the source name that we want;
	 *			if yes, we _break_ from the while loop.
 */
	while (currentPtr != NULL)
		{
	  	srcPtr = currentPtr->data;
 	if (strcmp(srcPtr->name, sourceName) == 0 ) 
			break;
		currentPtr = currentPtr->next;
		}
	
	/*
		* We return a pointer.  If we found the source, this pointer points
	 * to the ca_dbSource_t structure which represents the source.
	 * If we did not find the source, we return a pointer to NULL.
	 */
	if (currentPtr == NULL)
		{	
		srcPtr = NULL;
		return(srcPtr);
		}
 else
		{
		return(srcPtr);
		}
	
}	/* End of ca_getSourceDetails function */
 

ca_SrcHdl_t *ca_get_SourceHandleByPosition(int position)
/*******************************************************************
 * ca_get_SourceHandleByPosition												*
 *	-- retrieves the a handle to a Source									*
 *																						*
 * Parameters																		*
 *	-- the position in the linked list of sources						*
 *																						*
 *																						*
	* Returns																			*
	*	-- a pointer to the source or NULL										*
 *		i.e. a pointer to the data component of the appropriate		*
 *		element in the linked list of sources.								*
 *******************************************************************/
{
ca_dbSource_t * mySource;

mySource = g_slist_nth_data(sourceList, position);
return(mySource);
}

ca_SrcHdl_t *ca_get_SourceHandleByName(char *srcName)
/*******************************************************************
 * ca_get_SourceHandleByName													*
 *	-- retrieves the a handle to a source									*
 *																						*
 * Parameters																		*
 *	-- the name of the required source
 *																						*
 *																						*
	* Returns																			*
	*	-- a pointer to the source or NULL										*
 *		i.e. a pointer to the data component of the appropriate		*
 *		element in the linked list of sources.								*
 *******************************************************************/

{
ca_dbSource_t * mySource;

mySource = ca_getSourceDetails(srcName, sourceList);
return(mySource);
}

char *ca_srchandle2Strelement(ca_SrcHdl_t *ah, int srcAttrib)
/*******************************************************************
	* ca_srchandle2Strelement															*
	*	-- returns a string which represents the attribute of a source *
	*		e.g. returns the name of a source									*
	*		It allocates the required memory;									*
	*		but it returns NULL if the required memory cannot be 			*
	*		allocated.
 *																						*
	* Parameters								 										*
	*	--  source name - the name of the source
	*		 ca_get_SourceHandleByName or ca_get_SourceHandleByPosition *
	*																						*
	*	-- srcAttrib - an integer which represents the required 			*
	*		attribute of the source.  We use #define statments to make	*
	*		a mapping between the attributes and the integers.				*
 *																						*
	* Returns																			*
	* -- a string or NULL															*
 *******************************************************************/
{
char *myStr;
void ca_malloc(char *, int);

if(ah == NULL)
		{
		fprintf(stderr, "ca_srchandle2Strelement(): Cannot dereference NULL pointer\n");
		die;
		}

switch(srcAttrib)
		{
		case 0:
		/* source name */
		myStr = strdup(ah->name);
		break;

		case 1:
		/* canupd */
		myStr =  strdup(ah->canupd);
		break;

		case 2:
		/* deflook */
		/*
		 * ca_malloc(myStr, 2);
		 * strcpy(myStr, (ah->db).deflook);
		 */
		myStr = strdup(ah->deflook);
		break;

		case 3:
		/* machine */
		myStr = strdup((ah->db).host);
		break;

		case 5:
		/* user */
		myStr = strdup((ah->db).user);
		break;

		case 6:
		/* password */
		myStr = strdup((ah->db).password);
		break;

		case 7:
		/* dbName */
		myStr = strdup((ah->db).dbName);
		break;

		case 9:
		/* Near-Real-Time Mirror host */
		myStr = strdup((ah->nrtm).host);
		break;

		case 11:
		/* NRTM Log */
		myStr = strdup((ah->nrtm).log);
		break;

		default:
		puts("Cannot find this source attribute");
		break;
		}

return(myStr);
}

int ca_srchandle2Intelement(ca_SrcHdl_t *ah, int srcAttrib)
/*******************************************************************
	* ca_srchandle2Intelement														*
 * 	-- a function that returns the integer value of the requested	*
 *     attribute of the given source.										*
 *																						*
 * Parameters																		*
	*	--  source name - the name of the source
	*		 ca_get_SourceHandleByName or ca_get_SourceHandleByPosition *
	*																						*
	*	-- srcAttrib - an integer which represents the required 			*
	*		attribute of the source.  We use #define statments to make	*
	*		a mapping between the attributes and the integers.				*
 *																						*
 * Returns																			*
	*  -- an integer.
	*******************************************************************/
{
int myInt;	/* The value of this integer is returned. */

if(ah == NULL)
		{
		fprintf(stderr, "ca_srchandle2Intelement(): Cannot dereference NULL pointer\n");
		die;
		}

	switch(srcAttrib)
		{
		
		case 4:
		/* DB Port */
		myInt = (ah->db).port;
		break;

		case 8:
		/* Mode of Operation of the Source. */
		myInt = ah->opMode;
		break;

		case 10:
		/* Near-Real-Time Mirror port */
		myInt = (ah->nrtm).port;
		break;

		case 12:
		/* NRTM Delay */
		myInt = (ah->nrtm).delay;
		break;

		case 13:
		/* NRTM Protocol Version. */
		myInt = (ah->nrtm).protocolVer;
		break;

		case 14:
		/* Source Update Port */
		myInt = ah->updPort;
		break;

		default:
		fprintf(stderr, "Could not find source-attribute %d\n", srcAttrib);
		die;
    break;  
		}

return (myInt);
}


char *ca_get_adminStrElement(int symbol, int adminAttrib)
/*******************************************************************
	* ca_adminStrElement
	*	-- returns a string which represents the attribute of a admin  *
 *     db
	*		e.g. returns the name of a host machine.						   *
	*		It allocates the required memory;									*
	*		but it returns NULL if the required memory cannot be 			*
	*		allocated.
 *																						*
	* Parameters								 										*
	*  -- symbol - the symbol of the variable
	*																						*
	*	-- adminAttrib - an integer which represents the required 			*
	*		attribute of the Admin db.  We use #define statements to 	*
	*		make a mapping between the attributes and the integers.		*
 *																						*
	* Returns																			*
	* -- a string or NULL															*
 *******************************************************************/
{
char *myStr;
void ca_malloc(char *, int);

/*
	* Make sure that we are calling the correct function.
 */
if ( strcmp(dictionary[symbol].varType, "CA_ADMIN") != 0)
		{
		fprintf(stderr, "Error: unexpected variable type.\n");
		die;
		}
else
		{
 mutex_lock(&Lock);
 switch(adminAttrib)
		{
		case 0:
		/* admin host */
		myStr = strdup( ((ca_ripadmin_t *)confVars[symbol].valPtr)->host);
		break;

		case 2:
		/* User */
		myStr =  strdup( ((ca_ripadmin_t *)confVars[symbol].valPtr)->user);
		break;

		case 3:
		/* password */
		myStr = strdup( ((ca_ripadmin_t *)confVars[symbol].valPtr)->password);
		break;

		case 4:
		/* tableName */
		myStr = strdup( ((ca_ripadmin_t *)confVars[symbol].valPtr)->tableName);
		break;

		default:
		puts("Cannot find this admin attribute");
		die;
		break;
		}
 mutex_unlock(&Lock);

 return(myStr);
 }
}

int ca_get_adminIntElement(int symbol, int adminAttrib)
/*
	* Returns an int element of the admin db structure.
 */
{
int myInt;	/* The value of this integer is returned. */
 
mutex_lock(&Lock);
switch(adminAttrib)
	{
	case 1:
	/* Port number */
	myInt = ((ca_ripadmin_t *)confVars[symbol].valPtr)->port;
	break;

 default:
	puts("Cannot find this admin attribute");
	die;
	break;
	}
mutex_unlock(&Lock);

return(myInt);
}

void ca_malloc(char *someStr, int memSize)
/*******************************************************************
	* ca_malloc																			*
	*	-- a function that allocates memory for a string					*
	*																						*
 * Parameters																		*
	* --someStr	- the string that is to be created							*
	*	 memSize- required amount of memory in bytes							*
	*																						*
	* Returns																			*
	* -- nothing; it assigns the allocated memory to the pointer 		*
 *   that was passed to it.														*
	*																						*
	*******************************************************************/
{
	someStr = malloc(memSize);
	
	/*
	 * Check that we actually did get the memory ....
  */
	if (someStr == NULL)
		{
		fprintf(stderr, "ca_malloc(): cannot allocate memory !!!\n");
		exit(8);
		}
}

void ca_set_boolean(int symbol)
{
/*************************************************************
 *																				*
 * ca_set_boolean()														*
 * 																				*
	*																				*
 * Parameters																*
 *																				*
	* 	symbol -- the symbol for the variable.							*
 *																				*
	*																				*
	* Returns																	*
	*																				*
	* 		nothing																*
 *																				*
	*																				*
 * Remarks																	*
	*																				*
	* 	Must check that a sensible value is given as input.		*
	*																				*
	*																				*
	*************************************************************/


char newTestmodeStr[2];
int newTestmodeVal;	/* The new value of the testmode variable. */
int invalid;				/* Flag to indicate an invalid new value.  */

FILE *testPtr, *tempPtr;			/* The pointer to the files. */
char name[STRLENGTH];				/* The name of the variable. */
char value[STRLENGTH];			/* The value of the variable. */

/*
 * Function to change the value in a given values array.
 * This function can only be called from within ca_set_boolean().
 */
int *ca_change_int_value(char []);


/*
	* Using the symbol, look at the appropriate place in the 
 * dictionary.
	*/
#ifdef DEBUG
printf("\nca_set_int() function called .....\n");
printf("Variable type: %s\n", dictionary[symbol].varType);
#endif		/* DEBUG */

/*
 * Check that the function is attempting to set the correct type of 
 * value.  If not, do not set the value, but exit instead.
 */

if (strcmp(dictionary[symbol].varType, "CA_BOOLEAN") != 0)
		{
		fprintf(stderr, "Error: CA_BOOLEAN data type expected.\n");
		die;
		}

/*
 * First, flush the input stream.
 */
fflush(stdin);


/*
 * Make sure that a reasonable, sensible value of bind-port has
 * been read from the keyboard.
 */

do	{
			/*
			 * Prompt for the new value of the testmode.
			 */

			printf("\nNew value of testmode (0 or 1) >>> ");
			scanf("%s", newTestmodeStr);

			/*
			 * We scanf() the value as a string, but we want it to be an
			 * integer.  Thus, we use sscanf() to scanf the value from the
    	 * string-variable and store it as an integer in an integer
			 * variable.
			 */ 
			sscanf(newTestmodeStr, "%d", &newTestmodeVal);

			/*
        * We only change the testmode when the user is absolutely sure
			 * that they want to change.  Thus, we only accept two possible
			 * values for testmode.
			 */

			if ( (newTestmodeVal < 0) || (newTestmodeVal > 1) )
				{
				invalid = 1;
				puts("Only '0' or '1' accepted as value for testmode.");
				}
			else
				{
				invalid = 0;
				}	
		} while(invalid);
	

/*
	* Lock the value of the variable before changing it.
 */

mutex_lock(&Lock);


/*
 * Choose the appropriate values array.
 */

switch(dictionary[symbol].varScope)
		{
		/*
		 * If the variable has global scope, 
		 * write it into the globals array.
		 * If it has local scope, 
		 * write it into the local array.
		 * If the scope cannot be found, then report an error.
     */
		case 1:
		globals[symbol].valPtr = ca_change_int_value(newTestmodeStr);
		globals[symbol].strPtr = newTestmodeStr;
		break;

		case 99:
		locals[symbol].valPtr = ca_change_int_value(newTestmodeStr);
		locals[symbol].strPtr = newTestmodeStr;
		break;

		default:
		fprintf(stderr, "Error: unknown scope: %d\n", dictionary[symbol].varScope);
		break;
		}

/*
	* Write the new value of this variable back to the config file.
 *
 * To be implemented.
 */

/*
 * Find the actual name of the variable from the dictionary
 * structure (use the variable symbol as an index into the
 * array of dictionary structures.
 */
 
	printf("Name of variable to be changed: %s\n", dictionary[symbol].varName);
	printf("Type of variable to be changed: %s\n", dictionary[symbol].varType);

/*
	* Open the test config file for reading .....
 */
if ( (testPtr = fopen(testFile, "r")) == NULL)
	{
	printf("File \"%s\" could not be opened.\n", testFile);
	die;
	}

/*
	* Open the temporary file for writing .....
 */
if ((tempPtr = fopen(tempFile, "w")) == NULL)
	{
	printf("File \"%s\" could not be opened.\n", tempFile);
 die;
 }

/*
 * Read the first record in the test config file.
 */
 
 fscanf(testPtr, "%s", name);
 fgets(value, sizeof(value), testPtr);
 
 /*
  * If the last character of "value" is '\n',
  * replace it with '\0'.
  */
	if (value[strlen(value) - 1] == '\n')
		{
		printf("The value string is %s", value);
		printf("Replacing last character of \"%s\" with the NULL character\n", name);
		value[strlen(value) - 1] = '\0';
		printf("The new value string is %s", value);
		}


/*
	* While there are records to be read in the test config file:
	* 		Write the current record into the temporary file.
 * 		Read the next record in the config file.
 * Repeat untill the EOF has been reached.
 */
	
while(!feof(testPtr) )
	{
 fprintf(tempPtr, "%s %s\n", name, value);
 fscanf(testPtr, "%s", name);
	fgets(value, sizeof(value), testPtr);

 /*
  * If the last character of "value" is '\n',
  * replace it with '\0'.
  */
	if (value[strlen(value) - 1] == '\n')
		{
		printf("The last character of the value string is %c", value[strlen(value) - 1]);
		printf("The value string is %s", value);
		printf("Replacing last character of \"%s\" with the NULL character\n",name);
		value[strlen(value) - 1] = '\0';
		printf("The new value string is %s", value);
		}

 
 /*
  * if we read the variable that we want to change,
  * stop reading this file and print only the name
  * of this variable to the temporary file.
  */

	/*
	 * If we read the variable that we want to change,
  * replace the value of this variable in the config
  * file with the value supplied from the keyboard.
  *
  */
	if ( strcmp(name, dictionary[symbol].varName) == 0)
		{
		strcpy(value, newTestmodeStr);
		printf("The replacement string is %s", value);
		}
	/*
	 * Flush the pointer to the test config file.
	 */
	fflush(testPtr);

	}				
 /* 
	 * Here ends the loop that writes the config file, with the
  * new variable, to the temporary file.
	 */

/*
 *
 * While !(the record to be updated)
	*	BEGIN
	*  Write the record to the temporary file
 *  Read the next record in the config file
 *	END
 *
 * Write the new value to the temporary file
 * Read the next record in the config file
 * COMMENT: this is the record to be updated.
 * COMMENT: discard this record.
 * 
 * Read the next record in the config file
	*
 * While !(EOF)
	*	BEGIN
	*  write the record to the temporary file
 *  read the next record in the config file
 *  END
 *
 * Close Config file
 * Close Temporary file
 *
 * Open Temporary file for reading
 * Open Config file for writing
 *
 * Read the next record of the Temporary file
 *
 * While (!EOF of Temporary file)
	*	BEGIN
	*  write the record into the Config file
	*  read the next record of the Temporary file
 *  END
 * 
	*	Close Temporary file
 *  Close Config file
 *
 */

fclose(testPtr);
fclose(tempPtr);

/*
	* Now, flush the file pointers
 */
	fflush(testPtr);
	fflush(tempPtr);

/*
 * Open the temporary file for reading.
	* Open the config file for writing.
 * Write the contents of the temporary file
 * into the config file.
 */

/*
	* Open the temporary file for reading .....
 */
if ((tempPtr = fopen(tempFile, "r")) == NULL)
	{
	printf("File \"%s\" could not be opened for reading.\n", tempFile);
 die;
 }

/*
	* Open the config file for writing .....
 */
if ((testPtr = fopen(testFile, "w")) == NULL)
	{
	printf("File \"%s\" could not be opened for writing.\n", testFile);
 die;
 }

/*
 * Read the first record in the temporary file.
 */
 
 fscanf(tempPtr, "%s", name);
 fgets(value, sizeof(value), tempPtr);
	printf("\nFIRST LINE: %s %s", name, value);
 
 
/*
	* While there are records to be read in the temporary file:
	* 		Write the current record into the test config file.
 * 		Read the next record in the temporary file.
 * Repeat untill the EOF has been reached.
 */
	
while(!feof(tempPtr) )
	{
 fprintf(testPtr, "%s %s", name, value);
 fscanf(tempPtr, "%s", name);
	fgets(value, sizeof(value), tempPtr);
 }

fclose(testPtr);
fclose(tempPtr);

/*
	* Unlock the value of the variable after setting it and writing the
 * new value back to the configuration (and the dictionary) file.
	*
 */
	mutex_unlock(&Lock);

}


void ca_set_dirlist(int symbol)
{
/****************************************************************
	* ca_set_dirlist()															*
 *																					*
 * Parameters																  	*
	*		symbol -- the symbol of the variable.							*
 *																					*
 * Returns																		*
	*		1 if successful, 0 if not successful.							*
	*																					*
	* Remarks																		*
 *		Writing the new value back to the config file has yet to *
	*		be implemented.														*
 *																					*
	****************************************************************/

 char newDir[80];
 /*
  * Declare a pointer to a values_t variable.
	 * Later, we shall assign this pointer to the first element
  * of either the globals or the locals array, as appropriate.
  */
 values_t *hereValues;

	/*
	 * Using the symbol, look in the appropriate place in the dictionary.
	 */
#ifdef DEBUG
	printf("\nca_set_dirlist() function called ..... \n");
 printf("Variable type: %s\n", dictionary[symbol].varType);
#endif

	/*
	 * First, flush the input stream.
	 */
	fflush(stdin);

	/* 
	 * Prompt for the new value of the directory.
	 */
	printf("\nNew value of %s [80 characters, maximum] >>> ", dictionary[symbol].varName);
 scanf("%s", newDir);
	
/*
 * Make sure that a reasonable, sensible value of the directory 
 * value has been read from the keyboard.
 *
 * How do we implement this ???
 *
 */


 /*
  * Make sure that the function is attempting to set the correct type
  * of value.  If not, do not set the value - and exit.
  */

if (strcmp(dictionary[symbol].varType, "CA_DIRLIST") != 0)
		{
		fprintf(stderr, "Error: unexpected variable type.\n");
		exit(51);
		}	

	/*
  * Choose the appropriate values array.
	 * Assign a temporary pointer to this array.
	 */

	switch(dictionary[symbol].varScope)
		{
		/* If the variable has global scope,
		 * write it into the globals array.
		 * If it has local scope, 
		 * write it into the locals array.
 	 * If the scope cannot be found, report an error.
		 */
		case 1:
		hereValues = globals;
		break;

		case 99:
		hereValues = locals;
		break;

		default:
		fprintf(stderr, "Error: Unknown scope: %d\n", dictionary[symbol].varScope);
		break;
		}


	/*
  * Check for the presence of the mutex lock:
	 *		if present,
	 * 		wait until it is available;
	 *		else
  *			get the lock and proceed with the change of value.
	 */
	
	/*
  * Write the new value of the variable to the correct place
	 * in the [appropriate] values array.
	 *
  * Note that there is a check to see if malloc() actually worked .....
	 */

		hereValues[symbol].valPtr = (char *)malloc(80);
		if (hereValues[symbol].valPtr == NULL)
			{
			fprintf(stderr, "Cannot alllocate memory for hereValuesvlPtr\n");
			die;
			}
		strcpy(hereValues[symbol].valPtr,newDir); 


		hereValues[symbol].strPtr = (char *)malloc(sizeof(newDir) );
		if (hereValues[symbol].strPtr == NULL)
			{
			fprintf(stderr, "Cannot alllocate memory for hereValuestPtr\n");
			die;
			}
		strcpy(hereValues[symbol].strPtr, newDir);

	/*
	 * Free the temporary pointer, hereValues.
  *
  */
	free(hereValues);
	hereValues = NULL;
		
	/*
	 * Release the mutex lock.
	 */

	/*
	 * Write the new value of this variable back to the config file.
	 */

}


void ca_set_string(int symbol)
{

/****************************************************************
	* ca_set_string()															*
 *																					*
 * Parameters																  	*
	*		symbol -- the symbol of the variable.							*
 *																					*
 * Returns																		*
	*		1 if successful, 0 if not successful ?							*
	*																					*
	* Remarks																		*
 *		Writing the new value back to the config file has yet to *
	*		be implemented.														*
 *																					*
	****************************************************************/

 char newString[80];	/* May need to make this bigger. */

 /*
  * Declare a pointer to a values_t variable.
	 * Later, we shall assign this pointer to the first element
  * of either the globals or the locals array, as appropriate.
  */
 values_t *hereValues;

	/*
	 * Using the symbol, look in the appropriate place in the dictionary.
	 */
#ifdef DEBUG
	printf("\nca_set_string() function called ..... \n");
 printf("Variable type: %s\n", dictionary[symbol].varType);
#endif

	/*
	 * First, flush the input stream.
	 */
	fflush(stdin);

	/* 
	 * Prompt for the new value of the string.
	 */
	printf("\nNew value of %s [80 characters, maximum] >>> ", dictionary[symbol].varName);
gets(newString);
	
/*
 * Make sure that a reasonable, sensible value of the string
 * value has been read from the keyboard.
 *
 * How do we implement this ???
 *
 */


 /*
  * Make sure that the function is attempting to set the correct type
  * of value.  If not, do not set the value - and exit.
  */

if (strcmp(dictionary[symbol].varType, "CA_STRING") != 0)
		{
		fprintf(stderr, "Error: unexpected variable type.\n");
		exit(51);
		}	

	/*
  * Choose the appropriate values array.
	 * Assign a temporary pointer to this array.
	 */

	switch(dictionary[symbol].varScope)
		{
		/* If the variable has global scope,
		 * write it into the globals array.
		 * If it has local scope, 
		 * write it into the locals array.
 	 * If the scope cannot be found, report an error.
		 */
		case 1:
		hereValues = globals;
		break;

		case 99:
		hereValues = locals;
		break;

		default:
		fprintf(stderr, "Error: Unknown scope: %d\n", dictionary[symbol].varScope);
		break;
		}


	/*
  * Check for the presence of the mutex lock:
	 *		if present,
	 * 		wait until it is available;
	 *		else
  *			get the lock and proceed with the change of value.
	 */
	mutex_lock(&Lock);
	
	/*
  * Write the new value of the variable to the correct place
	 * in the [appropriate] values array.
  * Note the check to the return value of malloc() to see if the
	 * memory was actually obtained.
	 */

		hereValues[symbol].valPtr = (char *)malloc(80);
		if (hereValues[symbol].valPtr == NULL)
			{
			fprintf(stderr, "Cannot allocate memory for hereValues[symbol].valPtr\n");
			die;
			}
		strcpy(hereValues[symbol].valPtr, newString); 


		hereValues[symbol].strPtr = (char *)malloc(sizeof(newString) );
		if (hereValues[symbol].strPtr == NULL)
			{
			fprintf(stderr, "Cannot allocate memory for hereValues[symbol].strPtr\n");
			die;
			}
		strcpy(hereValues[symbol].strPtr, newString);

	/*
	 * Free the temporary pointer, hereValues.
	 *
  */
	free(hereValues);
 hereValues = NULL;

	/*
	 * Release the mutex lock.
	 */
	mutex_unlock(&Lock);

	/*
	 * Write the new value of this variable back to the config file.
	 * Implement this later ?
	 */

}


int ca_writeNewValue(int dictSymbol, char *newValue)
{

FILE *confPtr;						/* Pointer to config file */
FILE *tempPtr;						/* The pointer to temp file. */
char name[STRLENGTH];				/* The name of the variable. */
char value[STRLENGTH];			/* The value of the variable. */


/*
 * Find the actual name of the variable from the dictionary
 * structure (use the variable symbol as an index into the
 * array of dictionary structures.
 */
#ifdef DEBUG 
	printf("Name of variable to be changed: %s\n", dictionary[dictSymbol].varName);
	printf("Type of variable to be changed: %s\n", dictionary[dictSymbol].varType);
#endif	/* DEBUG */

/*
	* Open the test config file for reading .....
 */
if ( (confPtr = fopen(testFile, "r")) == NULL)
	{
	printf("File \"%s\" could not be opened.\n", testFile);
	die;
	}

/*
	* Open the temporary file for writing .....
 */
if ((tempPtr = fopen(tempFile, "w")) == NULL)
	{
	printf("File \"%s\" could not be opened.\n", tempFile);
 die;
 }

/*
 * Read the first record in the test config file.
 */
 
 fscanf(confPtr, "%s", name);
 fgets(value, sizeof(value), confPtr);
 
 /*
  * If the last character of "value" is '\n',
  * replace it with '\0'.
  */
	if (value[strlen(value) - 1] == '\n')
		{
#ifdef DEBUG
		printf("The value string is %s", value);
		printf("Replacing last character of \"%s\" with the NULL character\n", name);
#endif	/* DEBUG */

		value[strlen(value) - 1] = '\0';

#ifdef DEBUG
		printf("The new value string is %s", value);
#endif	/* DEBUG */
		}

	/*
	 * If we read the variable that we want to change,
  * replace the value of this variable in the config
  * file with the value supplied from the keyboard.
  *
  */
	if ( strcmp(name, dictionary[dictSymbol].varName) == 0)
		{
		strcpy(value, newValue);

#ifdef DEBUG
		printf("The replacement string is %s", value);
#endif	/* DEBUG */
}

/*
	* While there are records to be read in the test config file:
	* 		Write the current record into the temporary file.
 * 		Read the next record in the config file.
 * Repeat untill the EOF has been reached.
 */
	
while(!feof(confPtr) )
	{
 fprintf(tempPtr, "%s %s\n", name, value);
 fscanf(confPtr, "%s", name);
	fgets(value, sizeof(value), confPtr);

 /*
  * If the last character of "value" is '\n',
  * replace it with '\0'.
  */
	if (value[strlen(value) - 1] == '\n')
		{
#ifdef DEBUG
		printf("The last character of the value string is %c", value[strlen(value) - 1]);
		printf("The value string is %s", value);
		printf("Replacing last character of \"%s\" with the NULL character\n",name);
#endif	/* DEBUG */

		value[strlen(value) - 1] = '\0';
#ifdef DEBUG
		printf("The new value string is %s", value);
#endif	/* DEBUG */
		}


	/*
	 * If we read the variable that we want to change,
  * replace the value of this variable in the config
  * file with the value supplied from the keyboard.
  *
  */
	if ( strcmp(name, dictionary[dictSymbol].varName) == 0)
		{
		strcpy(value, newValue);

#ifdef DEBUG
		printf("The replacement string is %s", value);
#endif	/* DEBUG */
		}

	/*
	 * Flush the pointer to the test config file.
	 */
	fflush(confPtr);

	}				
 /* 
	 * Here ends the loop that writes the config file, with the
  * new variable, to the temporary file.
	 */

/*
 *
 * While !(the record to be updated)
	*	BEGIN
	*  Write the record to the temporary file
 *  Read the next record in the config file
 *	END
 *
 * Write the new value to the temporary file
 * Read the next record in the config file
 * COMMENT: this is the record to be updated.
 * COMMENT: discard this record.
 * 
 * Read the next record in the config file
	*
 * While !(EOF)
	*	BEGIN
	*  write the record to the temporary file
 *  read the next record in the config file
 *  END
 *
 * Close Config file
 * Close Temporary file
 *
 * Open Temporary file for reading
 * Open Config file for writing
 *
 * Read the next record of the Temporary file
 *
 * While (!EOF of Temporary file)
	*	BEGIN
	*  write the record into the Config file
	*  read the next record of the Temporary file
 *  END
 * 
	*	Close Temporary file
 *  Close Config file
 *
 */

fclose(confPtr);
fclose(tempPtr);

/*
	* Now, flush the file pointers
 */
	fflush(confPtr);
	fflush(tempPtr);

/*
 * Open the temporary file for reading.
	* Open the config file for writing.
 * Write the contents of the temporary file
 * into the config file.
 */

/*
	* Open the temporary file for reading .....
 */
if ((tempPtr = fopen(tempFile, "r")) == NULL)
	{
	printf("File \"%s\" could not be opened for reading.\n", tempFile);
 die;
 }

/*
	* Open the config file for writing .....
 */
if ((confPtr = fopen(testFile, "w")) == NULL)
	{
	printf("File \"%s\" could not be opened for writing.\n", testFile);
 die;
 }

/*
 * Read the first record in the temporary file.
 */
 
 fscanf(tempPtr, "%s", name);
 fgets(value, sizeof(value), tempPtr);
#ifdef DEBUG
	printf("\nFIRST LINE: %s %s", name, value);
#endif /* DEBUG */
 
/*
	* While there are records to be read in the temporary file:
	* 		Write the current record into the test config file.
 * 		Read the next record in the temporary file.
 * Repeat untill the EOF has been reached.
 */
	
while(!feof(tempPtr) )
	{
 fprintf(confPtr, "%s %s", name, value);
 fscanf(tempPtr, "%s", name);
	fgets(value, sizeof(value), tempPtr);
 }

fclose(confPtr);
fclose(tempPtr);
unlink(tempFile);

return(0);
}


int ca_getStorageLocation(char *confVar, dict_t woordenboek[], int size)
/*************************************************************
 * ca_getStorageLocation()												*
	*	- takes the name of a config variable and searches the  	*
 *    dictionary structure for the storage location for this *
 * 	  variable.																*
 *																				*
 * Parameters																*
	*	confVar -- the string variable that contains the name    *
 *        	  of the variable.										*	
 *  woordenboek -- the dictionary structure to be searched	*
	*	size			-- the size of the dictionary structure to	*
 *                 searched.											*
 *																				*
 * Returns																	*
	*	the location (integer) in the values array.					*
 *																				*
	*************************************************************/
{
int i, 
where,
found = 0	;		/* Whether or not the symbol has been found. */


#ifdef DEBUG
printf("The variable name in ca_getStorageLocation is: %s\n", confVar);
#endif /* DEBUG */

/*
 * Compares each name in the dictionary with the one for which
 * we are looking.
 */
i = 0;
while (!found && i <= size)
	{
	if (strcmp(woordenboek[i].varName, confVar) == 0)
		{
		found = 1;
		}
	else
		{
		++i;
		}
	}

/*
	* Returns the storage location for the given variable name
 * or else returns NOT_FOUND
 */
if (found)
		{
		/*	mySymbol = atoi(woordenboek[i].varSym);	*/
#ifdef DEBUG
    printf("Symbol is %s\n", woordenboek[i].varSym);
		printf("Storage Location is: %d\n", woordenboek[i].varNum);
#endif	/* DEBUG */
	   where = woordenboek[i].varNum; 
		}
else
		{
		fprintf(stderr, "Error: cannot find storage location for variable %s\n", confVar);	
		where = NOT_FOUND;
		}
	return (where);

}


void ca_getConfig(values_t confVars[], int size)
/*************************************************************
 * ca_getConfig -- prints the strings representing the 		*
 * 					   values of the configuration variables		*
 *																				*
 * Parameters																*
	*		confVars -- the values_t array which stores the 		*
	*						values of the configuration variables.	   *
	*		size -- the number of configuration variables,			*
	*		        the number of elements in the confVars array  *
 *																				*
 *																				*
 *************************************************************/
{
int i = 0; 	/* A counting variable. */

puts("A dump of the strings of the values of the Config Vars:");
puts("Number\t\tString");
puts("----------");

while (i < size)
	{
	printf("%d\t\t%s\n", i, confVars[i].strPtr);
 ++i;
	}

}


int ca_getType(char *confVar, dict_t woordenboek[], int size)
/****************************************************************
	* ca_getType -- returns the data type of the variable.			*
 *																					*
 * Parameters																	*
 *		confVar -- the name of the configuration variable.			*
	*		woordenboek -- the array of dict_t structures.				*
	*		size -- the number of configuration variables.				*
 *																					*
 * Returns																		*
 *		an integer representing the data type of the variable		*
 *																					*
 ****************************************************************/
{
int i = 0,		/* Counter variable. */
		found = 0;	/* Set this == 1 when we find the variable.  */
int myType;	/* Integer representing the type of the config variable. */

/*
 * Compare each name in the dictionary with the one for which we
 * are looking.
 */
 
myType = 0;

#ifdef DEBUG
printf("ca_getType function called for variable: %s\n", confVar);
#endif	/* DEBUG */

while (!found && i <= size)
		{
		if (strcmp(woordenboek[i].varName, confVar) == 0)
			{
			found = 1;
#ifdef DEBUG	
printf("ca_getType function: %s, %s matched.\n", woordenboek[i].varName, confVar);
#endif	/* DEBUG */
			}
		else
			{
			++i;
			}
		}			

/*
	* Return the type of the config variable or
	* else return "NOT FOUND".
 */
if (found)
		{
			if(strcmp(woordenboek[i].varType, "CA_INT") == 0)
				{
#ifdef DEBUG
printf("ca_getType function: %s variable of type %s is Integer type\n", woordenboek[i].varName, woordenboek[i].varType);

printf("ca_getType function: %s, %s\n", woordenboek[i].varName, woordenboek[i].varType);
#endif /* DEBUG */
				myType = 11;
#ifdef DEBUG
				printf("For type CA_INT, myType is %d\n", myType);
printf("ca_getType function: %s, %s, %d\n", woordenboek[i].varName, woordenboek[i].varType, myType);
#endif /* DEBUG */
				}
			else
				{
					if(strcmp(woordenboek[i].varType, "CA_STRING") == 0)
						{
#ifdef DEBUG
printf("ca_getType function: %s variable of type %s is String type\n", woordenboek[i].varName, woordenboek[i].varType);
printf("ca_getType function: %s, %s\n", woordenboek[i].varName, woordenboek[i].varType);
#endif /* DEBUG */
						myType = 12;
#ifdef DEBUG
printf("ca_getType function: %s, %s, %d\n", woordenboek[i].varName, woordenboek[i].varType, myType);
#endif /* DEBUG */
						}
					else
						{
						if (strcmp(woordenboek[i].varType, "CA_DIRLIST") == 0 )
							{
#ifdef DEBUG
printf("ca_getType function: %s, %s\n", woordenboek[i].varName, woordenboek[i].varType);
#endif /* DEBUG */
							myType = 13;
#ifdef DEBUG
printf("ca_getType function: %s, %s, %d\n", woordenboek[i].varName, woordenboek[i].varType, myType);
#endif /* DEBUG */
							}
						else
							{
							if (strcmp(woordenboek[i].varType, "CA_BOOLEAN") == 0)
								{
#ifdef DEBUG
printf("ca_getType function: %s, %s\n", woordenboek[i].varName, woordenboek[i].varType);
#endif /* DEBUG */
								myType = 14;
#ifdef DEBUG
printf("ca_getType function: %s, %s, %d\n", woordenboek[i].varName, woordenboek[i].varType, myType);
#endif /* DEBUG */
								}
							else
								{
								if (strcmp(woordenboek[i].varType, "CA_SOURCETYPE") == 0)
									{	
#ifdef DEBUG
printf("ca_getType function: %s, %s\n", woordenboek[i].varName, woordenboek[i].varType);
#endif /* DEBUG */
									myType = 15;
#ifdef DEBUG
printf("ca_getType function: %s, %s, %d\n", woordenboek[i].varName, woordenboek[i].varType, myType);
#endif /* DEBUG */
									}
								else
									{
									if (strcmp(woordenboek[i].varType, "CA_ADMIN") == 0)
										{	
#ifdef DEBUG
printf("ca_getType function: %s, %s\n", woordenboek[i].varName, woordenboek[i].varType);
#endif /* DEBUG */
									myType = 16;
#ifdef DEBUG
printf("ca_getType function: %s, %s, %d\n", woordenboek[i].varName, woordenboek[i].varType, myType);
#endif /* DEBUG */
										
										}
									}
								}
							}
						}
				}
		}
	else
		{
		myType = NOT_FOUND;
		}
	return(myType);
 }
