/*
 * libnqs/misc/machspec.c
 * 
 * DESCRIPTION:
 *
 *	Determine the machine-id of the explicit or implied machine
 *	specification as given in the text parameter.
 *
 *	Original Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	October 11, 1985.
 */

#include <libnqs/license.h>
#include <libnqs/proto.h>
#include <netdb.h>			/* Network database declarations */
#include <libnmap/nmap.h>

/*** machspec
 *
 *
 *	int machspec():
 *
 *	Determine the machine-id of the explicit or implied machine
 *	specification as given in the text parameter.
 *
 *	The form of an explicit machine specification is:
 *
 *		@machine-name	OR
 *		@[integer#]
 *
 *	where the "machine-name" form represents the principal name
 *	or alias assigned to a particular machine, and the "[integer#]"
 *	form is supported so that explicit machine-ids can be specified
 *	in place of a name or alias.
 *
 *	Returns:
 *		0: if successful, in which case the machine-id
 *		   parameter is successfully updated as
 *		   appropriate.
 *
 *	       -1: if an invalid machine-specification syntax
 *		   is encountered.
 *
 *	       -2: if the explicit or implied machine-specification
 *		   is not recognized by the local system (NMAP_ENOMAP).
 *
 *	       -3: if the Network Mapping Procedures (NMAP_)
 *		   deny access to the caller (NMAP_ENOPRIV).
 *
 *	       -4: if some other general NMAP_ error occurs.
 */
int machspec (char *text, Mid_t *machine_id)
{
	Mid_t mid_spec;			/* Machine-id specification */
	struct hostent *ent;		/* Host table entry structure */

  	assert (text 	   != NULL);
  	assert (machine_id != NULL);
  
	while (*text && *text != '@') {
		text++;			/* Look for possible machine- */
	}				/* specification */
	if (*text == '\0') {
		/*
		 *  No machine-specification was given.  The
		 *  local machine is assumed.
		 */
		return (localmid (machine_id));
	}
	/*
	 *  A machine-name specification appears.
	 */
	text++;				/* Step past machine-specification */
					/* introducer character */
	if (*text == '\0') {
		/*
		 *  Missing machine-specification.
		 */
		return (-1);		/* Bad syntax */
	}
	/*
	 *  Determine the machine-id of the destination machine.
	 */
	if (*text == '[') {
		/*
		 *  Could be an explicit machine specification by machine-id.
		 */
		text++;
		mid_spec = 0;
		while (*text >= '0' && *text <= '9') {
			mid_spec *= 10;
			mid_spec += *text - '0';
			text++;
		}
		if (*text == ']') {
			/*
			 *	[ <digit-sequence> ]
			 */
			if (*++text) {		/* Invalid machine-id spec */
				return (-1);	/* Bad syntax */
			}
			*machine_id = mid_spec;
			return (0);		/* Success */
		}
		return (-1);			/* Invalid syntax */
	}
	/*
	 *  The destination host has been specified as a name.
	 */
	if ((ent = gethostbyname (text)) == (struct hostent *) 0) {
		return (-2);			/* This machine is not */
						/* known to us */
	}
	switch (nmap_get_mid (ent, machine_id)) {
	case NMAP_SUCCESS:		/* Successfully got local machine-id */
		return (0);
	case NMAP_ENOMAP:		/* What?  No local mid defined! */
		return (-2);
	case NMAP_ENOPRIV:		/* No privilege */
		return (-3);
	}
	return (-4);			/* General NMAP_ error */
}
