/********************************************************************

   Copyright (c) 1996 Novell, Inc.  All Rights Reserved.

   With respect to this file, Novell hereby grants to Developer a
   royalty-free, non-exclusive license to include this sample code
   and derivative binaries in its product. Novell grants to Developer
   worldwide distribution rights to market, distribute or sell this
   sample code file and derivative binaries as a component of
   Developer's product(s).  Novell shall have no obligations to
   Developer or Developer's customers with respect to this code.

   DISCLAIMER:

   Novell disclaims and excludes any and all express, implied, and
   statutory warranties, including, without limitation, warranties
   of good title, warranties against infringement, and the implied
   warranties of merchantability and fitness for a particular purpose.
   Novell does not warrant that the software will satisfy customer's
   requirements or that the licensed works are without defect or error
   or that the operation of the software will be uninterrupted.
   Novell makes no warranties respecting any technical services or
   support tools provided under the agreement, and disclaims all other
   warranties, including the implied warranties of merchantability and
   fitness for a particular purpose. */

/*********************************************************************
   NDSREADA.C
**********************************************************************

   Description:

   Returns the telephone number attribute for a specified object
   taken from the command line.  Call NWDSInitBuf to initialize
   an input buffer for a read operation and NWDSPutAttrName
   to place attribute names into the input buffer.
   Three functions are used to retrieve results:
   NWDSGetAttrCount retrieves the number of attributes,
   NWDSGetAttName retrieves each attr name, the number attr
   values and syntax and NWDSGetAttVal retrieves attribute values

   Syntax:  ndsreada <object name>

   This example requires a valid user object name
   (for example, readobj CN=name.OU=myorgunit.O=myorg).  This example
   also requires that you login as SUPERVISOR (if you haven't
   authenticated to NDS before running the example, the program will
   prompt for user input and perform the authentication).


*********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <nwnet.h>
#include <nwcalls.h>
#include <nwlocale.h>

#define NUM_OF_ATTRS 3   /* obtain three attributes */

/* functions and globals */
void   ReadBuffer(NWDSContextHandle context, pBuf_T pBuf);
void   FreeInBuf(pBuf_T pBuf, NWDSContextHandle context);
void   FreeContext(NWDSContextHandle context);
void   FreeUnicodeTables();
nbool8 bbDoLogout = N_FALSE;

void main(int argc, char *argv[])
{
   NWDSContextHandle   context;
   nint32              lIterationHandle = NO_MORE_ITERATIONS;
   pBuf_T              pInBuf;
   pBuf_T              pOutBuf;
   NWDSCCODE           ccode;
   nstr8               strUserName[NW_MAX_USER_NAME_LEN];
   nstr8               strUserPassword[50];
   nstr8               strObject[MAX_DN_CHARS+1];
   nuint               i;
   LCONV               lConvInfo;
   pnstr8              strAttrName[] = {"Common Name",
                                        "Surname",
                                        "Telephone Number"};

   if(argc != 2)
   {
      printf("\nUsage   :  NDSREADA <object name>");
      printf("\nExample :  NDSREADA .CN=MYNAME.O=MYORG");
      exit(1);
   }

   strcpy(strObject, argv[1]);  /* strObject is object to read */

   /* Initialize NWCalls and unicode tables */

   ccode = NWCallsInit(NULL,NULL);
   if(ccode)
   {
      printf("\nNWCallsInit returned %X", ccode);
      exit(1);
   }

   NWLlocaleconv(&lConvInfo);

   ccode = NWInitUnicodeTables(lConvInfo.country_id,
                               lConvInfo.code_page);
   if(ccode)
   {
      printf("\nNWInitUnicodeTables returned %X", ccode);
      exit(1);
   }

   /* Create an NDS Context */
   ccode = NWDSCreateContextHandle(&context);
   if(ccode)
   {
      printf("\nNWDSCreateContextHandle failed");
      FreeUnicodeTables();
   }

   /*  Must authenticate if not already authenticated to NDS
       (which will always be the case if this example is
       compiled and run as an NLM). */
   if(!NWIsDSAuthenticated())
   {
      printf("\nMust authenticate to NDS");
      printf("\nEnter User Name: ");
      gets(strUserName);
      printf("Enter User Password: ");
      gets(strUserPassword);

      ccode = NWDSLogin(context, 0, strUserName, strUserPassword, 0);
      if(ccode)
      {
         printf("\nNWDSLogin returned %X", ccode);
         FreeContext(context);
      }
      else
      {  /* If example logs in, it will also log out */
         bbDoLogout = N_TRUE;
      }
   }

   /* Allocate and initialize input buffer a directory services
      read operation. */
   ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pInBuf);
   if(ccode)
   {
      printf("\nNWDSAllocBuf returned %X", ccode);
      FreeContext(context);
   }

   ccode = NWDSInitBuf(context, DSV_READ, pInBuf);
   if(ccode)
   {
      printf("\nNWDSInitBuf returned %X", ccode);
      FreeInBuf(pInBuf, context);
   }

   /* Allocate the output buffer to hold returned values */
   ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &pOutBuf);
   if(ccode)
   {
      printf("\nNWDSAllocBuf returned %X", ccode);
      FreeInBuf(pInBuf, context);
   }

   /* To prepare for the read, place the names of the attributes
      into the input buffer */
   for(i = 0; i < NUM_OF_ATTRS; i++)
   {
      ccode = NWDSPutAttrName(context, pInBuf, strAttrName[i]);
      if(ccode)
      {
         printf("\nNWDSPutAttrName returned %X", ccode);
         NWDSFreeBuf(pOutBuf);
         FreeInBuf(pInBuf, context);
      }
   }

   /* Perform the read.  The second arg to NWDSRead specifies that
      attribute values are to be returned. The third attribute, FALSE,
      indicates that only attribute information is desired. */
   ccode = NWDSRead(context, strObject, DS_ATTRIBUTE_VALUES, FALSE,
                    pInBuf, &lIterationHandle, pOutBuf);
   if(ccode)
   {
      printf("\nNWDSRead returned %d. Can't read object\n", ccode);
      NWDSFreeBuf(pOutBuf);
      FreeInBuf(pInBuf, context);
   }

   /* Call ReadBuf to get the data out of the output buffer */
   ReadBuffer(context, pOutBuf);

   /* Clean up, normal termination */
   NWDSFreeBuf(pOutBuf);
   NWDSFreeBuf(pInBuf);
   if(bbDoLogout)
      NWDSLogout(context);
   NWDSFreeContext(context);
   NWFreeUnicodeTables();
}

void ReadBuffer(NWDSContextHandle context, pBuf_T pBuf)
{
   nuint32      luSyntax;
   NWCCODE      ccode;
   nuint32      luAttrCount;
   nuint32      luAttrValCount=1;
   nstr8        strAttrName[MAX_DN_CHARS+1];
   nstr8        strAttrVal[MAX_DN_CHARS+1];
   nuint        i;

   /* Get the number of attributes in pBuf */

   ccode = NWDSGetAttrCount(context, pBuf, &luAttrCount);
   if(ccode)
   {
      printf("\nNWDSGetAttrCount returned %X", ccode);
      return;
   }

   /* Get the name and value for each attribute */
   for(i = 0; i < luAttrCount; i++)
   {
      ccode = NWDSGetAttrName(context, pBuf, strAttrName,
                              &luAttrValCount, &luSyntax);
      if(ccode)
      {
         printf("\nNWDSGetAttrName returned %X", ccode);
         return;
      }
      printf("\nNWDSGetAttrName returned Count =%d, Name =%s\n",
              luAttrValCount, strAttrName);

      ccode = NWDSGetAttrVal(context, pBuf, luSyntax, strAttrVal);
      if(ccode)
      {
         printf("\nNWDSGetAttrVal returned %X", ccode);
         return;
      }
      printf("NWDSGetAttrVal returned : %s ", strAttrVal);
   }
}

/* Clean up Functions, called on error condition only */
void FreeInBuf(pBuf_T pBuf, NWDSContextHandle context)
{
   NWDSFreeBuf(pBuf);
   FreeContext(context);
}

void FreeContext(NWDSContextHandle context)
{
   if(bbDoLogout)
      NWDSLogout(context);
   NWDSFreeContext(context);
   FreeUnicodeTables();
}

void FreeUnicodeTables()
{
   NWFreeUnicodeTables();
   exit(1);
}
