/*
 *  nwbpvalues.c
 *
 *  List the contents of a SET property of a bindery object on a NetWare server
 *
 *  Copyright (C) 1996 by Volker Lendecke
 *
 */

#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>

static char *progname;

static void
print_property(char *prop_name, __u8 *val, int segments);

static void
usage(void)
{
	fprintf(stderr, "usage: %s [options]\n", progname);
}

static void
help(void)
{
        printf("\n");
        printf("usage: %s [options]\n", progname);
        printf("\n"
	       "-h             Print this help text\n"
	       "-S server      Server name to be used\n"
               "-U username    Username sent to server\n"
               "-P password    Use this password\n"
               "-n             Do not use any password\n"
               "-C             Don't convert password to uppercase\n"
	       "\n"
	       "-o object_name Name of object\n"
	       "-t type        Object type (decimal value)\n"
	       "-p property    Name of property to be listed\n"
	       "-v             Verbose object listing\n"
	       "\n");
}

int
main(int argc, char *argv[])
{
	struct ncp_conn *conn;
	char *object_name = NULL;
	int object_type = -1;
	char *property_name = NULL;
	__u8 property_value[255*128];
	int segno;
	int verbose = 0;
	struct nw_property segment;
	struct ncp_property_info info;
	long err;

	int result = 1;
	
	int opt;

	progname = argv[0];

	if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
	{
		com_err(argv[0], err, "in ncp_initialize");
		goto finished;
	}

	while ((opt = getopt(argc, argv, "ho:t:p:v")) != EOF)
	{
		switch(opt) {
		case 'o':
			object_name = optarg;
			str_upper(object_name);
			break;
		case 't':
			object_type = atoi(optarg);
			break;
		case 'p':
			property_name = optarg;
			if (strlen(property_name) > 15)
			{
				fprintf(stderr, "%s: Property Name too long\n",
					argv[0]);
				exit(1);
			}
			str_upper(property_name);
			break;
		case 'v':
			verbose = 1;
			break;
		case 'h':
			help();
			goto finished;
		default:
			usage();
			goto finished;
		}
	}

	if (object_type < 0)
	{
		fprintf(stderr, "%s: You must specify an object type\n",
			argv[0]);
		goto finished;
	}

	if (object_name == NULL)
	{
		fprintf(stderr, "%s: You must specify an object name\n",
			argv[0]);
		goto finished;
	}

	if (property_name == NULL)
	{
		fprintf(stderr, "%s: You must specify a property name\n",
			argv[0]);
		goto finished;
	}

	if (ncp_scan_property(conn, object_type, object_name,
			      0xffffffff, property_name, &info) != 0)
	{
		fprintf(stderr, "%s: Could not find property\n", argv[0]);
		goto finished;
	}

	segno = 1;
	while (ncp_read_property_value(conn, object_type, object_name,
				       segno, property_name, &segment) == 0)
	{
		memcpy(&(property_value[(segno-1)*128]), segment.value, 128);
		if ((segment.more_flag == 0) || (segno == 255))
		{
			break;
		}
	}
		

	if ((info.property_flags & 2) == 0)
	{
		print_property(property_name, property_value, segno);
	}
	else
	{
		int objects = 32 * segno;
		__u32 *value = (__u32 *)property_value;
		int i;

		for (i = 0; i < objects; i++)
		{
			struct ncp_bindery_object o;

			if ((*value == 0) || (*value == 0xffffffff))
			{
				break;
			}
			if (ncp_get_bindery_object_name(conn, ntohl(*value),
							&o) == 0)
			{
				if (verbose != 0)
				{
					printf("%s %08X %04X\n",
					       o.object_name,
					       (unsigned int) o.object_id,
					       (unsigned int) o.object_type);
				}
				else
				{
					printf("%s\n", o.object_name);
				}
			}
			value += 1;
		}
	}
	result = 0;
			
 finished:
	ncp_close(conn);
	return result;
}

static void
print_unknown(__u8 *val)
{
	int j = (128/16);
	while (1)
	{
		int i;
		for ( i = 0 ; i < 16 ; i++ )
		{
			printf ( "%02X " , val[i] );
		}
		printf ( "   [" );
		for ( i = 0 ; i < 16 ; i++ )
		{
			printf ( "%c" , isprint(val[i]) ? val[i] : '.');
		}
		j -= 1;
		if ( j == 0 )
		{
			printf ( "]\n" );
			return;
		}
		printf ( "]+\n" ) ;
		val += 16;
	}
}

static void
print_string(__u8 *val)
{
	puts(val);
}

static struct {
    char    *pname ;
    void    (*func)(__u8 *) ;
}   formats[] = {
    { "DESCRIPTION"     , print_string } ,
    { "SURNAME"         , print_string } ,
    { "OBJECT_CLASS"    , print_string } ,
    { "DESCRIPTION"     , print_string } ,
    { "IDENTIFICATION"  , print_string } ,
    { "Q_DIRECTORY"     , print_string } ,
    { NULL		, NULL }
};

static void
print_property(char *prop_name, __u8 *val, int segments)
{
	int i;
	void (*f)(__u8 *);

	for (i = 0; formats[i].pname != NULL; i++)
	{
		if (strcasecmp(prop_name, formats[i].pname) == 0)
		{
			break;
		}
	}
	f = formats[i].func;

	if (f != NULL)
	{
		f(val);
		return;
	}

	for (i = 0; i < segments; i++)
	{
		printf("Segment: %03d\n", i+1);
		print_unknown(&(val[i*128]));
		printf("\n");
	}
}
	
