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

   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. */

/*********************************************************************
   NDSMODOB.C
**********************************************************************

   Description:

   Modifies the surname of the object passed in.  The old
   surname is needed for the value to be deleted, so both old
   name and new name are requested.  The input buffer is
   initialized for a MODIFY_ENTRY operation and two changes are
   placed into the buffer - one to delete the existing value and
   another to assign the new value.  Each change is
   accomplished by NWDSPutChange.  NWDSPutAttrVal is used to
   place the attributes into the buffer.

   Syntax:  ndsmodob <object>

   This example 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).  Also, this example requires the name of a
   valid NDS object to be modified
   (for example, .CN=myname.OU=myunit.O=myorg).
   
*********************************************************************/

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

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

void main(int argc, char *argv[])
{
   NWDSContextHandle    context;
   pBuf_T               pBuf;
   NWDSCCODE            ccode;
   nstr8                strOldName[MAX_DN_CHARS+1];
   nstr8                strNewName[MAX_DN_CHARS+1];
   nstr8                strUserName[NW_MAX_USER_NAME_LEN];
   nstr8                strUserPassword[50];
   LCONV                lConvInfo;

   if(argc < 2)
   {
      printf("\nUsage   :  NDSMODOBJ <object>");
      printf("\nExample :  NDSMODOBJ .cn=myname.ou=myunit.o=myorg");
      exit(1);
   }

   /* Initialize NWCalls and the 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);
   }

   context = NWDSCreateContext( );
   if(context == ERR_CONTEXT_CREATION)
   {
      printf("\nNWDSCreateContext 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).  Modifying an NDS object
       requires SUPERVISOR rights. */
   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 space for the input buffer */
   ccode = NWDSAllocBuf((size_t)DEFAULT_MESSAGE_LEN, &pBuf);
   if(ccode)
   {
      printf("\nNWDSAllocBuf returned %X", ccode);
      FreeContext(context);
   }

   /* Initialize the buffer for a modify operation */
   ccode = NWDSInitBuf(context, DSV_MODIFY_ENTRY, pBuf);
   if(ccode)
   {
      printf("\nNWDSInitBuf returned %X", ccode);
      FreeBuf(pBuf, context);
   }

   /* Store a change record into the buffer with NWDSPutChange.
      Set the changeType arg to REMOVE_VALUE and the attrName
      arg to Surname.  */
   ccode = NWDSPutChange(context, pBuf, DS_REMOVE_VALUE, "Surname");
   if(ccode)
   {
      printf("\nNWDSPutChange returned %X", ccode);
      FreeBuf(pBuf, context);
   }

   /* Prompt for new and old names */
   printf("\nEnter current surname for %s: ", argv[1]);
   gets(strOldName);
   printf("\nEnter new surname: ");
   gets(strNewName);

   /* Use NWDSPutAttrVal to place the existing surname (strOldName)
      into the buffer.  SYN_CI_STRING indicates corresponding data
      type. */
   ccode = NWDSPutAttrVal(context, pBuf, SYN_CI_STRING, strOldName);
   if(ccode)
   {
      printf("\nNWDSPutAttrVal returned %X", ccode);
      FreeBuf(pBuf, context);
   }

   /* Store the second change record into the buffer by calling
      NWDSPutChange. Set the changeType arg to ADD_VALUE and the
      attrName arg remains as Surname.  */
   ccode = NWDSPutChange(context, pBuf, DS_ADD_VALUE, "Surname");
   if(ccode)
   {
      printf("\nNWDSPutChange returned %X", ccode);
      FreeBuf(pBuf, context);
   }

   /* Now use NWDSPutAttrVal to place the new surname (strNewName)
      into the buffer.  SYN_CI_STRING is the corresponding data type.*/
   ccode = NWDSPutAttrVal(context, pBuf, SYN_CI_STRING, strNewName);
   if(ccode)
   {
      printf("\nNWDSPutAttrVal returned %X", ccode);
      FreeBuf(pBuf, context);
   }

   /* Call NWDSModifyObject to perform the set of changes held in the
      input buffer, pBuf.  Set iterationHandle to NULL since no
      more modifications will take place. */
   ccode = NWDSModifyObject(context, argv[1], NULL, 0, pBuf);
   if(ccode)
      printf("\nNWDSModifyObject returned %X\
             Unable to change surname.\n", ccode);
   else
      printf("\nSurname %s has been replaced with %s.",
             strOldName, strNewName);

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

/* Clean up and exit, called on error condition only */
void FreeBuf(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);
} 
