/*
 *	Network Queueing System (NQS)
 *  This version of NQS is Copyright (C) 1992  John Roman
 *
 *  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 1, 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, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/*
*  PROJECT:     Network Queueing System
*  AUTHOR:      John Roman
*
*  Modification history:
*
*       Version Who     When            Description
*       -------+-------+---------------+-------------------------
*       V01.10  JRR                     Initial version.
*       V01.20  JRR     16-Jan-1992	Added support for RS6000.
*       V01.30  JRR     17-Jan-1992	Tweak to above.          
*       V01.4   JRR     28-Feb-1992	Added Cosmic V2 changes. 
*       V01.5   JRR     07-Apr-1992     Added CERN enhancements.
*	V01.6	JRR	17-Jun-1992	Added header.
*	V01.7	JRR	26-Feb-1993	Added Boeing enhancement for Mids.
*	V01.8	JRR			Placeholder
*	V01.9	JRR	28-Feb-1994	Added support for SOLARIS.
*/
/*++ nmapread.c -
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.35.6/npsn_compat/RCS/nmapread.c,v $
 *
 * DESCRIPTION:
 *	Nmapread.c:  Routines to read nmap database
 *
 * STANDARDS VIOLATIONS:
 *
 * REVISION HISTORY: ($Revision: 1.9 $ $Date: 1994/03/30 20:35:42 $ $State: Exp $)
 * $Log: nmapread.c,v $
 * Revision 1.9  1994/03/30  20:35:42  jrroma
 * Version 3.35.6
 *
 * Revision 1.8  93/07/13  21:33:18  jrroma
 * Version 3.34
 * 
 * Revision 1.7  92/12/22  15:52:03  jrroma
 * Version 3.30
 * 
 * Revision 1.6  92/06/18  14:39:21  jrroma
 * Added gnu header
 * 
 * Revision 1.5  92/05/06  10:26:23  jrroma
 * Version 3.20
 * 
 * Revision 1.4  92/02/28  13:28:14  jrroma
 * Added Cosmic V2 changes.
 * 
 * Revision 1.3  92/01/17  16:57:51  jrroma
 * Fix to readdir code.
 * 
 * Revision 1.2  92/01/17  13:00:16  jrroma
 * Added support for RS6000.
 * 
 * Revision 1.1  92/01/17  12:57:07  jrroma
 * Initial revision
 * 
 *
 */

#include "nqs.h"
#include "nmapcommon.h"
#if	vms
#include ssdef
#include syidef
#include descrip
#include rms
#include errno
#include string

typedef struct {
    short len;
    short code;
    int	    addr;
    int	    len_addr;
} ss_list;
#else
#if     BSD43 | ULTRIX | HPUX | SGI | SYS52 | LINUX
#include <sys/dir.h>
#else
#if	IBMRS | DECOSF | SOLARIS
#include <dirent.h>
#else
BAD SYSTEM TYPE
#endif
#endif
#endif

#ifndef __CEXTRACT__
#if __STDC__
static int nmap_scan_map ( int (*func) (), char *p1, char *p2 );
static int nmap_print_mids ( struct nammap *mmap, Mid_t mid, char *pname );
static int nmap_sort_mids ( struct nammap *mmap, Mid_t *mids, int *nummids );

#else /* __STDC__ */

static int nmap_scan_map (/* int (*func) (), char *p1, char *p2 */);
static int nmap_print_mids (/* struct nammap *mmap, Mid_t mid, char *pname */);
static int nmap_sort_mids (/* struct nammap *mmap, Mid_t *mids, int *nummids */);

#endif /* __STDC__ */
#endif /* __CEXTRACT__ */


/*
 *
 *
 *	int nmap_get_uid (from_mid, from_uid, &local_uid)
 *
 *	Map the user-id: from_uid from the machine with mid: from_mid
 *	to the local user-id: local_uid.
 *
 *	Returns:
 *	   0: (NMAP_SUCCESS) if successful.
 *	   1: (NMAP_DEFMAP) if no mapping existed for the specified
 *	      machine and user-id, but a default user-id mapping
 *	      was enabled for the specified machine.
 *	  -1: (NMAP_EUNEXPECT) if an unanticipated error occurred in
 *	      the mapping software.
 *	  -2: (NMAP_ENOPRIV) if the caller did not have sufficient
 *	      privilege to access the mapping database.
 *	  -4: (NMAP_ENOMAP) if no mapping existed for the specified
 *	      machine and user-id.
 */
int nmap_get_uid (from_mid, from_uid, local_uid)
Mid_t from_mid;
uid_t from_uid;
uid_t *local_uid;
{
	struct xidparm parm;
	register int res;
 
	parm.u.u.remote_uid = from_uid;
	res = xidop (from_mid, &parm, GET_UID);
	if (res >= 0) *local_uid = parm.u.u.local_uid;
	nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
	return (res);
}


/*
 *
 *
 *	int nmap_get_gid (from_mid, from_gid, &local_gid)
 *
 *	Map the user-id: from_gid from the machine with mid: from_mid
 *	to the local user-id: local_gid.
 *
 *	Returns:
 *	   0: (NMAP_SUCCESS) if successful.
 *	   1: (NMAP_DEFMAP) if no mapping existed for the specified
 *	      machine and group-id, but a default group-id mapping
 *	      was enabled for the specified machine.
 *	  -1: (NMAP_EUNEXPECT) if an unanticipated error occurred in
 *	      the mapping software.
 *	  -2: (NMAP_ENOPRIV) if the caller did not have sufficient
 *	      privilege to access the mapping database.
 *	  -4: (NMAP_ENOMAP) if no mapping existed for the specified
 *	      machine and group-id.
 */
int nmap_get_gid (from_mid, from_gid, local_gid)
Mid_t from_mid;
gid_t from_gid;
gid_t *local_gid;
{
	struct xidparm parm;
	register int res;
 
	parm.u.g.remote_gid = from_gid;
	res = xidop (from_mid, &parm, GET_GID);
	if (res >= 0) *local_gid = parm.u.g.local_gid;
	nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
	return (res);
}


/*
 *
 *
 *	int nmap_get_mid (&hostent, &mid)
 *
 *	Determine the machine-id (mid) of the system identified by
 *	the specified hostent structure.
 *
 *	NOTE:	If the passed address of the hostent structure is NULL,
 *		then the machine-id the local machine upon which the
 *		calling process is running is determined by this
 *		function call.
 *
 *	Returns:
 *	   0: (NMAP_SUCCESS) if successful.
 *	  -1: (NMAP_EUNEXPECT) if an unanticipated error occurred in
 *	      the mapping software.
 *	  -2: (NMAP_ENOPRIV) if the caller did not have sufficient
 *	      privilege to access the mapping database.
 *	  -4: (NMAP_ENOMAP) if no mapping existed for the specified
 *	      hostent structure.
 */
int nmap_get_mid (hostent, mid)
struct hostent *hostent;
Mid_t *mid;
{

	char hostname [MAX_NAMELENGTH+1];	/* Local host name */
	register int status;
	register int alias;
#if  vms
	ss_list	syilst[2];
	char	*cp;
	char	node_name[16];
	short	node_name_len;
	syilst[0].len = 15;
	syilst[0].code = SYI$_NODENAME;
	syilst[0].addr = &node_name;
	syilst[0].len_addr = &node_name_len;
	syilst[1].len = 0;
	syilst[1].code = 0;
#endif
	if (hostent == (struct hostent *) 0) {
		/*
		 *  No hostent structure was specified.  The caller
		 *  is asking for the machine-id of the local machine.
		 */
#if vms
		sys$getsyi(NULL, NULL, NULL, &syilst, NULL,
				NULL, NULL);
		node_name[node_name_len] = '\0';
		for (cp = &node_name; *cp != '\0'; cp++) {
		    *cp = tolower(*cp);
		}
		status = namop (&node_name, mid, GET_MID);
		return (status);
#endif
		if (gethostname (hostname, MAX_NAMELENGTH) == -1) {
			/*
			 *  We were unable to determine the name of the
			 *  local machine at least using tcp -- for vms
			 *  try getting the nodename and looking for it.
			 */
			return (NMAP_EUNEXPECT);/* We were surprised */
		}
		hostname [MAX_NAMELENGTH]='\0';	/* Null terminate for sure */
		if ((hostent = gethostbyname(hostname))==(struct hostent *)0) {
			return(NMAP_EUNEXPECT);	/* Surprised again! */
		}
	}
	alias = 0;				/* First alias in list */
	status = namop (hostent->h_name, mid, GET_MID);
	if (hostent->h_aliases != (char **)0) {
		while (status == NMAP_ENOMAP && hostent->h_aliases[alias] 
			    != (char *)0){
			/*
			 *  While no mapping, check aliases for a mapping
			 *  until we run out of aliases.
			 */
			status = namop (hostent->h_aliases [alias++], 
					    mid, GET_MID);
		}
	}
	nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
	return (status);	/* Return result */
}


/*
 *
 *
 *	struct hostent *nmap_get_ent (mid):
 *	Return a hostent structure for the specified machine-id.
 *
 *	Returns:
 *		A pointer to a hostent structure for the specified
 *		machine-id if successful; otherwise NULL is returned.
 */
struct hostent *nmap_get_ent (mid)
Mid_t mid;			/* Where to return the machine-id */
{

	char *hostname;		/* Principal name for machine-id */

	if ((hostname = nmap_get_nam (mid)) == (char *) 0) {
		return ((struct hostent *) 0);
	}
	return (gethostbyname (hostname));
}


/*
 *
 *
 *	char *nmap_get_nam (mid)
 *
 *	Return a pointer to the null terminated character string
 *	containing the principal host name for the specified machine-id.
 *	Return NULL for all error conditions (including no mapping for
 *	"mid").
 *
 *	WARNING:  The name is placed in a static data area which is
 *		  overwritten with each call.
 */
char *nmap_get_nam (mid)
Mid_t mid;
{

	static char name [MAX_NAMELENGTH+1];	/* Name space */
	struct nmap_rawblock block;
	register int i;

	if (open_machine (mid, O_RDONLY) != NMAP_SUCCESS) {
		nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
		return ((char *) 0);	/* NMAP_EUNEXPECT or NMAP_ENOPRIV */
	}
	/*
	 *  Seek to beginning of file if not already there.
	 */
	if (LSEEK (machine_file, 0L, 0) == -1) {
		nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
		return ((char *) 0);	/* NMAP_EUNEXPECT */
	}
	/*
	 *  Get the principal name of the machine from the first
	 *  block of the uid/gid mapping file for the target machine.
	 */
	if (READ (machine_file, block.u.bytes, ATOMICBLKSIZ) != ATOMICBLKSIZ) {
		nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
		return ((char *) 0);
	}
	i = 0;
	while (block.u.mhdr.name [i] != '\0' && i < MAX_NAMELENGTH) {
		name [i] = block.u.mhdr.name [i];
		i++;
	}
	name [i] = '\0';	/* Null terminate */
	nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
	return (name);
}
/*
 *
 *
 *	int nmap_list_nam ()
 *
 * List the machine mappings.
 */
int nmap_list_nam ()
{

    static char name [MAX_NAMELENGTH+1];	/* Name space */
    struct nmap_rawblock block;
    register int i;
    int	status;
    Mid_t	mid;
    int	    context = 0;
    int	    counter;
    int	    machine_count;
#if vms
    char    file[256];
    $DESCRIPTOR(file_desc, file);
    $DESCRIPTOR(filespec_desc, "M0*");
    $DESCRIPTOR(default_desc, "NQS_NMAP:*.;");

    counter = machine_count = 0;
    while (TRUE) {
	status = lib$find_file (&filespec_desc, &file_desc, &context, 
		&default_desc,0,0,0);
	if (status != RMS$_NORMAL) {
	    if (status == RMS$_FNF) {
		printf("No machines found.\n");
		return;
	    } 
	    if (status == RMS$_NMF) {
		if (machine_count == 0) {
		    printf ("No machines found.\n");
		    return;
		}
		lib$find_file_end(&context);
		break;
	    }
	    printf("Error finding machine files.\n%s\n", strerror(EVMSERR,
		    status) );
	    return;
	}
	machine_count++;
    }
#else
        char    *map_dir;
	DIR *d;
#if	IBMRS | DECOSF
	struct dirent *dp;
#else
	struct direct *dp;
#endif
	map_dir = getfilnam( "",  MAPDIR);
	d = opendir (map_dir);
	relfilnam (map_dir);
	counter = machine_count = 0;
	while (dp = readdir(d)) {
	    if (dp->d_ino == 0) continue;
	    if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
			continue;
	    if((dp->d_name[0] == 'm') && (dp->d_name[1] == '0') ) 
				machine_count++;
	}
	closedir(d);

#endif
    printf("%4s    %s\n", "Mid", "Principal Name    Aliases");
    for (mid=1; ; mid++) {
	status = open_machine (mid, O_RDONLY);
	if (status != NMAP_SUCCESS) {
	    if (status == NMAP_ENOMID) continue;
	    break;
	}
	/*
	 *  Seek to beginning of file if not already there.
	 */
	if (LSEEK (machine_file, 0L, 0) == -1) break;
	/*
	 *  Get the principal name of the machine from the first
	 *  block of the uid/gid mapping file for the target machine.
	 */
	if (READ (machine_file, block.u.bytes, ATOMICBLKSIZ) != ATOMICBLKSIZ) 
	    break;
	i = 0;
	while (block.u.mhdr.name [i] != '\0' && i < MAX_NAMELENGTH) {
	    name [i] = block.u.mhdr.name [i];
	    i++;
	}
	name [i] = '\0';	/* Null terminate */
	nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
	/* printf("%4d    %10s", mid, name); */
	printf("%4d    ", mid);
	nmap_jrr_mid(mid);
	printf("\n");
	counter++;
	if (counter >= machine_count) return;
    }
    nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
}


/*
 *
 *
 *	int nmap_get_defuid (from_mid, &defuid)
 *
 *
 *	Get the default user-id mapping for the machine with
 *	mid: from_mid to the default user-id: defuid.
 *
 *	Returns:
 *	   0: (NMAP_SUCCESS) if successful.
 *	  -1: (NMAP_EUNEXPECT) if an unanticipated error occurred in
 *	      the mapping software.
 *	  -2: (NMAP_ENOPRIV) if the caller did not have sufficient
 *	      privilege to update the mapping database.
 *	  -4: (NMAP_ENOMAP) if default uid doesn't exist for this mid
 *	  -5: (NMAP_ENOMID) if no such machine as specified by
 *	      the machine-id (mid) exists.
 */
int nmap_get_defuid (from_mid, defuid)
Mid_t from_mid;
uid_t *defuid;
{

	struct nmap_rawblock block;
	int status;

	if ((status = open_machine (from_mid, O_RDONLY)) != NMAP_SUCCESS) {
		nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
		return (status);   /* NMAP_EUNEXPECT, NMAP_ENOMID, or */
				   /* NMAP_ENOPRIV */
	}
	/*
	 *  Seek to beginning of file if not already there.
	 */
	if (LSEEK (machine_file, 0L, 0) == -1) {
		nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
		return (NMAP_EUNEXPECT);
	}
	if (READ (machine_file, block.u.bytes, ATOMICBLKSIZ) != ATOMICBLKSIZ) {
		nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
		return (NMAP_EUNEXPECT);
	}
	if ( block.u.mhdr.defuid_enabled !=  1 )
		return (NMAP_ENOMAP);

	*defuid = block.u.mhdr.defuid;		/* Store default */
	nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
	return (NMAP_SUCCESS);	/* Return success */
}
/*
 *
 *
 *	int nmap_jrr_mid (mid)
 *
 *	Deletes ALL mappings associated with the machine identified by
 *	"mid" (that is, all uid, gid, and name-to-mid, and mid-to-name
 *	mappings for the specified "mid").
 *
 *	Returns:
 *	   0: (NMAP_SUCCESS) if successful.
 *	  -1: (NMAP_EUNEXPECT) if an unanticipated error occurred in
 *	      the mapping software.
 *	  -2: (NMAP_ENOPRIV) if the caller did not have sufficient
 *	      privilege to update the mapping database.
 *	  -5: (NMAP_ENOMID) if no such machine as specified by
 *	      the machine-id (mid) exists.
 */
int nmap_jrr_mid (mid)
Mid_t mid;
{

	char path [MAX_PATHLENGTH+1];
	struct nmap_rawblock hashblock;
	struct nmap_rawblock mapblock;
	register long address;
	unsigned prevoffset;
	unsigned offset;
	register struct nammap *mmap;
	register int i;			/* Index var */
	register int j;			/* Index var */
	int size;			/* Size of entry */
	register int status;		/* Status return from open_name_map() */

	if ((status = open_name_map (O_RDWR)) != NMAP_SUCCESS) {
		nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
		return (status);	/* Return -1: Fatal error */
					/* 	  -2: Insufficient privilege */
	}
	machine_name (mid, path);	/* Get pathname */
	/*
	 *  Path now has the complete pathname of the uid/gid
	 *  mapping file for the specified mid.  Delete the uid/gid
	 *  mappings for the specified machine-id, and the principal
	 *  name for the specified machine.
	 */
	for (i=0; i < HASHNAMBLKS; i++) {
	    if (LSEEK (name_mapfile, (long) i * ATOMICBLKSIZ, 0) == -1) {
		nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
		return (NMAP_EUNEXPECT);
	    }
	    if (READ (name_mapfile, hashblock.u.bytes,
			  ATOMICBLKSIZ) != ATOMICBLKSIZ) {
		nmap_ctl (NMAP_OPNOFD, nfds);
				/* Relinquish file descriptors if necessary */
		return (NMAP_EUNEXPECT);
	    }
	    for (j=0; j < HASHENTSPERBLK; j++) {
		/*
		 * Get address of first block in the hash chain.
		 */
		address = hashblock.u.hash.chain [j];
		while (address != 0L) {
		    if (LSEEK (name_mapfile, address, 0)==-1){
			/*
			 *  Relinquish file descriptors
			 *  as necessary.
			*/
			nmap_ctl (NMAP_OPNOFD, nfds);
			return (NMAP_EUNEXPECT);
		    }
		    if (READ (name_mapfile, mapblock.u.bytes,
			    ATOMICBLKSIZ) != ATOMICBLKSIZ) {
			/*
			 *  Relinquish file descriptors
			 *  as necessary.
			 */
			nmap_ctl (NMAP_OPNOFD, nfds);
			return (NMAP_EUNEXPECT);
		    }
		    /*
		     *  Skip over nextptr for hash chain link and
		     *  examine this block.
		     */
		    offset = ((char *)(&mapblock.u.nhdr.map))
				       - mapblock.u.bytes;
		    prevoffset = offset;
		    do {
			mmap = (struct nammap *)
					       (mapblock.u.bytes + offset);
			if (mmap->namelen != 0 &&
					    mmap->mid == mid) {
			    /*
			     *  
			     *  
			     */
			    printf("%s    ", mmap->name);
			    if (LSEEK (name_mapfile, address, 0)==-1) {
				/*
				 *  Relinquish file
				 *  descriptors as
				 *  necessary.
				 */
				nmap_ctl (NMAP_OPNOFD,nfds);
				return (NMAP_EUNEXPECT);
			    }
		        }
		        /*
		         *  Prepare to access the next entry.
		         */
		        prevoffset = offset;
		        offset += mmap->size;
		    } while (offset < ATOMICBLKSIZ);
		    /*
		     *  No name to specified mid mapping was found
		     *  in this block.  Go inspect the succeeding
		     *  block(s) for such a mapping.
		     */
		    address = mapblock.u.nhdr.nexthash;
	        }
	    }
	}
	nmap_ctl (NMAP_OPNOFD, nfds);
				/* Relinquish file descriptors if necessary */
	return (NMAP_SUCCESS);	/* Success */
}
/*
 *
 *
 *	int nmap_show ()
 *
 *	Display the mids, principal names, and aliases for all of the
 *	machines in the database. Also indicate any potential inconsistencies
 *	in the database (e.g. no mid file, principal name not in machines file).
 *
 *	Returns:
 * 	 0: (NMAP_SUCCESS)	if successful.
 *	 -1: (NMAP_EUNEXPECT)	major error.
 *	 -2: (NMAP_ENOPRIV)	denied access privilege.
 *	 -11: (NMAP_ENOMAPFILE)	The mapping file does not exist.
 *
 */
int nmap_show ()
{
	int nummids = 0;		/* number of mids read from database */
	Mid_t mids[MAX_MIDS+1];		/* list of mids read from database */
	Mid_t testmid;
	char *pname;			/* pointer to principal name */
	char *pname_str;		/* pointer to principal name not */
					/* found string */
	short not_found;		/* principal name not found flag */
	register int status;		/* Status return */
	register int j;			/* index */
	int nmap_scan_map();
	int nmap_sort_mids();
	int nmap_print_mids();

	/*
	 * initialize
	 */
	not_found = 0;
	for (j = 0; j <= MAX_MIDS; j++) mids[j] = 0xffffffff;

	if ((status = open_name_map (O_RDONLY)) != NMAP_SUCCESS) {
		nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
		return (status);	/* Return -1: Fatal error */
					/*	  -2: Insufficient privilege */
	}
	/*
	 * collect all of the currently defined mids in sorted order
	 */
	if ((status = nmap_scan_map (nmap_sort_mids, mids, &nummids))
		!= NMAP_SUCCESS) {
		nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
		return (status);
	}
	if (nummids > MAX_MIDS) {
		printf("********** Encountered more mids in the database than\
 MAX_MIDS\n");
		printf("********** Will process only MAX_MIDS = %d\n\n",
 MAX_MIDS);
		nummids = MAX_MIDS;
	}
	/*
	 *      print header
	 */
	printf (" MID\tPRINCIPAL NAME\tALIASES\n");
	printf (" ---\t--------------\t-------");
	/*
	 *      print all mids, principal names, and aliases
	 */
	for (j = 0; j < nummids; j++) {
		pname_str = "";
		if ((pname = nmap_get_nam (mids[j])) == (char *) 0)
			pname = "????";
		else if (namop (pname, &testmid, GET_MID) != NMAP_SUCCESS ||
			testmid != mids[j]) {
				pname_str = "**";
				not_found = 1;
		}
		printf("\n%4u%4s%-15s\t", mids[j], pname_str, pname);
		/*
		 *   Print aliases
		 */
		if ((status = open_name_map (O_RDONLY)) != NMAP_SUCCESS) {
			nmap_ctl (NMAP_OPNOFD, nfds);
				/* Relinquish file descriptors if necessary */
			return (status);	/* Return -1: Fatal error */
		}
		if ((status = nmap_scan_map (nmap_print_mids, mids[j], pname))
			!= NMAP_SUCCESS) {
			nmap_ctl (NMAP_OPNOFD, nfds);
			/* Relinquish file descriptors if necessary */
			return (status);
		}
	}
	printf ("\n");
	if (not_found)
		printf ("\t** - Principal name not in machines file\n");
	nmap_ctl (NMAP_OPNOFD, nfds);
		/* Relinquish file descriptors if necessary */
	return (NMAP_SUCCESS);
}


/*
 *	int nmap_scan_map ()
 *
 *	Scan the machine database and call the passed function to
 *	process each entry
 *
 */
static
int nmap_scan_map (func, p1, p2)
	int (*func) ();		/* function to be called */
	char *p1, *p2;		/* this is a type violation and should be*/
				/* changed to (void *) when our compiler */
				/* gets around to supporting it */
{
	struct nmap_rawblock block;
	int status;		/* return status of func () */
	long address = HASHNAMBLKS * ATOMICBLKSIZ;
	unsigned prevoffset;
	unsigned offset;
	struct nammap *mmap;

	/*
	 *      Seek to first entry beyond hashblocks
	 */
	if (LSEEK (name_mapfile, address, 0) == -1) return (NMAP_EUNEXPECT);

	while (status = READ (name_mapfile, block.u.bytes, ATOMICBLKSIZ)) {
		if (status == -1) return (NMAP_EUNEXPECT);
		/*
		 *  Skip over nextptr for hash chain link and
		 *  examine this block.
		 */
		offset = ((char *)(&block.u.nhdr.map))
		       - block.u.bytes;
		prevoffset = offset;
		do {
			mmap = (struct nammap *)
			       (block.u.bytes + offset);
			if (mmap->namelen != 0) {
				if ((status = (*func) (mmap, p1, p2)) !=
					NMAP_SUCCESS) return(status);
			}
			/*
			 *  Prepare to access the next entry.
			 */
			prevoffset = offset;
			offset += mmap->size;
		} while (offset < ATOMICBLKSIZ);
	}
	return(NMAP_SUCCESS);
}


/*
 *
 *	int nmap_sort_mids ()
 *
 *	Collect in sorted order each mid in the database
 *
 */
static
int nmap_sort_mids (mmap, mids, nummids)
	struct nammap *mmap;
	Mid_t *mids;
	int *nummids;
{
	register int i;		/* index */
	register int j;		/* index */

	for (j = 0; j <= MAX_MIDS; j++) {
		if (mmap->mid == mids[j]) {
			return (NMAP_SUCCESS);
		}
		if (mmap->mid < mids[j]) {
			if ( ++(*nummids) > MAX_MIDS) return (NMAP_SUCCESS);
			/*
			 * move new mid into position
			 */
			for (i = *nummids; i > j; i--) {
				mids[i] = mids[i-1];
			}
			mids[j] = mmap->mid;
			return (NMAP_SUCCESS);
		}
	}
	return (NMAP_SUCCESS);
}


/*
 *
 *	int nmap_print_mids()
 *
 *	Print principal name and aliases per mid
 *
 */
static
int nmap_print_mids (mmap, mid, pname)
	struct nammap *mmap;
	Mid_t mid;	/* current mid */
	char *pname;	/* pointer to principal name */
{
	char name[MAX_NAMELENGTH + 1];

	strncpy (name, mmap->name, mmap->namelen);
	name[mmap->namelen] = '\0';	/* null terminate for sure */
	if ((mid == mmap->mid) && (strcmp (pname, name) != 0)) {
		printf("%s ", name);
	}
	return(NMAP_SUCCESS);
}
