home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / ndshel.exe / NDSSHELL.C < prev    next >
C/C++ Source or Header  |  1995-07-18  |  52KB  |  1,797 lines

  1. /****************************************************************************
  2. **    File:    NDSSHELL.C
  3. **
  4. **    Desc: A Shell for Novell Directory Services.  Provides "DOS" like
  5. **                commands for most of the DS functions.
  6. **
  7. **
  8. **        DISCLAIMER
  9. **
  10. **    Novell, Inc. makes no representations or warranties with respect to
  11. **    any NetWare software, and specifically disclaims any express or
  12. **    implied warranties of merchantability, title, or fitness for a
  13. **    particular purpose.
  14. **
  15. **    Distribution of any NetWare software is forbidden without the
  16. **    express written consent of Novell, Inc.  Further, Novell reserves
  17. **    the right to discontinue distribution of any NetWare software.
  18. **
  19. **    Novell is not responsible for lost profits or revenue, loss of use
  20. **    of the software, loss of data, costs of re-creating lost data, the
  21. **    cost of any substitute equipment or program, or claims by any party
  22. **    other than you.  Novell strongly recommends a backup be made before
  23. **    any software is installed.   Technical support for this software
  24. **    may be provided at the discretion of Novell.
  25. **
  26. **    Programmers:
  27. **
  28. **        Ini    Who                                Firm
  29. **        --- ----------------- ------------------------------------------------
  30. **        CRG    Calvin Gaisford        Novell Developer Support.
  31. **
  32. **    History:
  33. **
  34. **        When         Who What
  35. **        -------- --- ---------------------------------------------------------
  36. **        05-14-95 CRG First code.
  37. **        06-05-95 CRG Added all Comments and cleaned up code.
  38. */
  39.  
  40.  
  41. /***************************************************************************
  42. **  Libraries Linked in for .exe
  43. **
  44. **  NWCALLS.LIB
  45. **  NWLOCALE.LIB
  46. **  NWNET.LIB
  47. **
  48. */
  49.  
  50.  
  51. /***************************************************************************
  52. **  #defines
  53. */
  54. #define MAX_COMMANDLINE_LEN    50
  55. #define MAX_COMMAND_LEN    50
  56.  
  57. /* Tokens used when parsing commands */
  58. #define EXIT_TOK        0x001        /* Exit the shell */
  59. #define DIR_TOK            0x002        /* List Objects in Container */
  60. #define CD_TOK            0x003        /* Change the Context */
  61. #define CLS_TOK            0x004        /* Clear the sreen */
  62. #define LS_TOK            0x005        /* Same as dir_tok for Unix People */
  63. #define NOTHING_TOK    0x006        /* The do nothing token */
  64. #define TYPE_TOK        0x007        /* lists all attributes for an object */
  65. #define MODE_TOK        0x008        /* change the screen mode 25/50 chars */
  66. #define HELP_TOK        0x009        /* list valid commands */
  67. #define VER_TOK            0x00A        /* show the version of shell */
  68. #define CLASS_TOK        0x00B        /* list objects of specified class */
  69. #define CLASSES_TOK 0x00C        /* list all classes currently defined */
  70. #define TREE_TOK        0x00D        /* show a tree from current container */
  71.  
  72.  
  73. /****************************************************************************
  74. **    Include headers, macros, etc.
  75. */
  76.  
  77.     /*-----------------------------------------------------------------------
  78.     **    ANSI
  79.     */
  80.     #include <stdio.h>
  81.     #include <stdlib.h>
  82.     #include <conio.h>
  83.     #include <string.h>
  84.     #include <dos.h>
  85.  
  86.     /*-----------------------------------------------------------------------
  87.     **    NetWare
  88.     */
  89.     #include <nwnet.h>
  90.     #include <nwcalls.h>
  91.     #include <nwlocale.h>
  92.  
  93.     /*-----------------------------------------------------------------------
  94.     **    Program Global storage
  95.     */
  96.     NWDSContextHandle gContext;
  97.     char                            nContext[MAX_DN_CHARS];
  98.     int                                screenSize = 22;
  99.  
  100.     extern unsigned _stklen=8000;
  101.  
  102.  
  103. /***************************************************************************
  104. **    Function Prototypes
  105. */
  106. void mainLoop(void);
  107. int  InitDS(void);
  108. int  UninitDS(void);
  109. int  ProccessCommand(char **commandLine);
  110. int  Tokenize(char **commandLine);
  111. int  GetToken(char **commandLine, char *command);
  112. int  Dir(char **commandLine);
  113. int  CD(char **commandLine);
  114. int  ChangeContext(char *newContext);
  115. int  Banner(void);
  116. int  Type(char **commandLine);
  117. void DecodeRights(char *attrName, char *rightsstring, NWDS_PRIVILEGES    privs);
  118. int  LineOut(int *pause, int    *linecount, char *line);
  119. int  Mode(char **commandLine);
  120. int  Help(void);
  121. int  Version(void);
  122. int  IsClass(char *className);
  123. int  Class(char **commandLine);
  124. int  Classes(char **commandLine);
  125. int  Exit(char **commandLine);
  126. int  DoTree(int *treelevel, int *pause, int *scrcount, int *canceled, long *treeMap);
  127. int  Tree(void);
  128.  
  129.  
  130.  
  131. /***************************************************************************
  132. **    main
  133. **    Only makes three calls.  Setup context, loop, cleanup context.
  134. */
  135. void main(void)
  136. {
  137.     if(!InitDS())
  138.         mainLoop();
  139.     UninitDS();
  140. }
  141.  
  142.  
  143.  
  144. /***************************************************************************
  145. **    mainLoop
  146. **  Gets all commands from the command line, sets them to lower case and
  147. **    sends them off to be processed.  Also reads the current mode and sets
  148. **    the page length for screen pausing.
  149. */
  150. void mainLoop(void)
  151. {
  152.     char    input[MAX_COMMANDLINE_LEN], *commandLine;
  153.     struct text_info    tInfo;
  154.  
  155.     gettextinfo(&tInfo);
  156.     screenSize = (tInfo.screenheight - 3);
  157.     clrscr();
  158.     do
  159.     {
  160.         cprintf("\r\n%s>>", nContext);
  161.         Banner();
  162.         cgets(input);
  163.         commandLine = &input[2];
  164.         strlwr(commandLine);
  165.     }
  166.     while(!ProccessCommand(&commandLine));
  167. }
  168.  
  169.  
  170.  
  171. /***************************************************************************
  172. **    InitDS
  173. **    Create and setup context.  These are the standard initializations
  174. **    for DS calls
  175. */
  176. int InitDS(void)
  177. {
  178.     NWDSCCODE      ccode;
  179.     DWORD              flags;
  180.     LCONV            lconvInfo;
  181.  
  182.     ccode=NWCallsInit(NULL,NULL);
  183.     if(ccode)          /* initialize allowing to call nwcalls functions */
  184.     {
  185.         printf("FatalError during NWCallsInit %X\n",ccode);
  186.         return 1;
  187.     }
  188.     NWLlocaleconv(&lconvInfo);
  189.     ccode = NWInitUnicodeTables(lconvInfo.country_id, lconvInfo.code_page);
  190.     if(ccode)
  191.     {
  192.         printf("NWInitUnicodeTables() returned: %04X\n", ccode);
  193.         return 1;
  194.     }
  195.     gContext=NWDSCreateContext();
  196.     if(gContext)
  197.     {
  198.         printf("FatalError during NWDSCreateContext %X\n",gContext);
  199.         return 1;
  200.     }
  201.     ccode = NWDSGetContext(gContext, DCK_FLAGS, &flags);
  202.     if(ccode < 0)
  203.         return 1;
  204.  
  205.     flags |= DCV_TYPELESS_NAMES;
  206.  
  207.     /*     This will setup the context so that it accepts and returns typeless
  208.             names.  A typeless name is jross.HR.Novell and not
  209.             CN=jross.OU=HR.O=Novell.
  210.     */
  211.  
  212.     ccode = NWDSSetContext(gContext, DCK_FLAGS, &flags);
  213.     if(ccode < 0)
  214.         return 1;
  215.     ccode = NWDSGetContext(gContext, DCK_NAME_CONTEXT, (void *)nContext);
  216.     if(ccode < 0)
  217.         return 1;
  218.     if(strcmp(nContext, "[Root]"))
  219.         strupr(nContext);
  220.     return 0;
  221. }
  222.  
  223.  
  224.  
  225. /***************************************************************************
  226. **    UninitDS
  227. **    Release context and unicode tables.
  228. */
  229. int UninitDS()
  230. {
  231.     NWDSCCODE ccode;
  232.  
  233.     ccode=NWDSFreeContext(gContext);
  234.     if(ccode)
  235.     {
  236.         printf("FatalError during NWDSFreeContext %X\n",ccode);
  237.         return 1;
  238.     }
  239.     ccode=NWFreeUnicodeTables();
  240.     if(ccode)
  241.     {
  242.         printf("Error during NWFreeUnicodeTables()\n");
  243.         return 1;
  244.     }
  245.     return(0);
  246. }
  247.  
  248.  
  249.  
  250. /***************************************************************************
  251. **    ProcessCommand
  252. **    This will take a pointer to the command line, get the command and
  253. **    execute the corresponding function with it's command line parameters.
  254. */
  255. int ProccessCommand(char **commandLine)
  256. {
  257.     switch(Tokenize(commandLine))
  258.     {
  259.         case EXIT_TOK:
  260.             return(Exit(commandLine));
  261.         case LS_TOK:
  262.         case DIR_TOK:
  263.             Dir(commandLine);
  264.             break;
  265.         case CD_TOK:
  266.             CD(commandLine);
  267.             break;
  268.         case CLS_TOK:
  269.             clrscr();
  270.             break;
  271.         case TYPE_TOK:
  272.             if(Type(commandLine))
  273.                 cprintf("\r\nError Typing Object \r\n");
  274.             break;
  275.         case MODE_TOK:
  276.             Mode(commandLine);
  277.             break;
  278.         case HELP_TOK:
  279.             Help();
  280.             break;
  281.         case VER_TOK:
  282.             Version();
  283.             break;
  284.         case CLASSES_TOK:
  285.             Classes(commandLine);
  286.             break;
  287.         case CLASS_TOK:
  288.             Class(commandLine);
  289.             break;
  290.         case TREE_TOK:
  291.             Tree();
  292.             break;
  293.         case NOTHING_TOK:
  294.             break;
  295.         default:
  296.             cprintf("\r\nCommand not recognized.\r\n");
  297.     }
  298.     return 0;
  299. }
  300.  
  301.  
  302.  
  303. /***************************************************************************
  304. **    Tokenize
  305. **    Simply takes a pointer to a string and turns the first group of letters
  306. **    (space delimited) and returns a corresponding token.  The commandLine
  307. **    is pointing to the character just right of the first command.
  308. */
  309. int Tokenize(char **commandLine)
  310. {
  311.     char    command[MAX_COMMAND_LEN];
  312.  
  313.     GetToken(commandLine, command);
  314.     if(!strcmpi(command, "EXIT"))
  315.         return(EXIT_TOK);
  316.     if(!strcmp(command, "dir"))
  317.         return(DIR_TOK);
  318.     if(!strcmp(command, "cd"))
  319.         return(CD_TOK);
  320.     if(!strcmp(command, "cls"))
  321.         return(CLS_TOK);
  322.     if(!strcmp(command, "ls"))
  323.         return(LS_TOK);
  324.     if(!strcmp(command, "type"))
  325.         return(TYPE_TOK);
  326.     if(!strcmp(command, "mode"))
  327.         return(MODE_TOK);
  328.     if(!strcmp(command, "?"))
  329.         return(HELP_TOK);
  330.     if(!strcmp(command, "help"))
  331.         return(HELP_TOK);
  332.     if(!strcmp(command, "ver"))
  333.         return(VER_TOK);
  334.     if(!strcmp(command, ""))
  335.         return(NOTHING_TOK);
  336.     if(!strcmp(command, "classes"))
  337.         return(CLASSES_TOK);
  338.     if(!strcmp(command, "tree"))
  339.         return(TREE_TOK);
  340.     if(!IsClass(command))
  341.     {
  342.         strcat(command, (*commandLine));
  343.         strcpy((*commandLine), command);
  344.         return(CLASS_TOK);
  345.     }
  346.     return 0;
  347. }
  348.  
  349.  
  350.  
  351. /***************************************************************************
  352. **    GetToken
  353. **    Takes the first word (space delimited) and copies it into the string
  354. **    passed in and leaves the commandline pointing to the next word.  All
  355. **    white spaces are skipped on the front of the commandLine.
  356. */
  357. int GetToken(char **commandLine, char *command)
  358. {
  359.     int        len;
  360.  
  361.     while(((*commandLine)[0] < 33) && ((*commandLine)[0] != '\x0'))
  362.         (*commandLine)++;
  363.     for(len=0; ((len < MAX_COMMAND_LEN) && ((*commandLine)[0] > 32)); len++)
  364.     {
  365.         command[len] = (*commandLine)[0];
  366.         (*commandLine)++;
  367.     }
  368.     command[len] = '\x0';
  369.     return(strlen(command));
  370. }
  371.  
  372.  
  373.  
  374. /***************************************************************************
  375. **    Exit
  376. **  Ends the NDS Shell program and if there is a optional /s on with the
  377. **    command, the default context is set to whatever the current context
  378. **    is within the NDS Shell.
  379. */
  380. int Exit(char **commandLine)
  381. {
  382.     char     option[MAX_COMMAND_LEN];
  383.     BYTE     newContext[MAX_DN_CHARS];
  384.     NWCCODE    ccode;
  385.  
  386.     if(GetToken(commandLine, option))
  387.     {
  388.         if(!strcmp(option, "/s"))
  389.         {
  390.             strcpy(newContext, ".");
  391.             /*
  392.                     before setting the context, prepend a "." on it so the client
  393.                     software does not append the context onto the end
  394.             */
  395.             strcat(newContext, nContext);
  396.             ccode = NWSetDefaultNameContext(MAX_DN_CHARS, newContext);
  397.             if(ccode)
  398.                 cprintf("\r\nError Saving Context: %X\r\n", ccode);
  399.             else
  400.             {
  401.                 clrscr();
  402.                 return 1;
  403.             }
  404.         }
  405.         cprintf("\r\nUnkown Option \"%s\"\r\n", option);
  406.         cprintf("\r\n\r\nUsage: exit [/s]\r\n\r\n");
  407.         return 0;
  408.     }
  409.     clrscr();
  410.     return 1;
  411. }
  412.  
  413.  
  414.  
  415. /***************************************************************************
  416. **    Mode
  417. **    This only sets the screen output and has no NetWare API calls.
  418. **    Switches the screen from 25 to 50 or 50 to 25 lines.
  419. */
  420. int Mode(char **commandLine)
  421. {
  422.     char                                    option[MAX_COMMAND_LEN];
  423.     struct text_info    tInfo;
  424.  
  425.     GetToken(commandLine, option);
  426.     if(!strcmp(option, "50"))
  427.     {
  428.         textmode(C4350);
  429.         gettextinfo(&tInfo);
  430.         screenSize = (tInfo.screenheight - 3);
  431.         return 0;
  432.     }
  433.     if(!strcmp(option, "25"))
  434.     {
  435.         textmode(C80);
  436.         gettextinfo(&tInfo);
  437.         screenSize = (tInfo.screenheight - 3);
  438.         return 0;
  439.     }
  440.     cprintf("\r\nUnkown Option \"%s\"\r\n", option);
  441.     cprintf("\r\n\r\nUsage: mode [50 | 25]\r\n\r\n");
  442.     return 1;
  443. }
  444.  
  445.  
  446.  
  447. /***************************************************************************
  448. **    Dir
  449. **  If no command line options are included, calls NWDSList and just lists
  450. **    all objects in the current container.
  451. **    If command line options are passed in and they do not equal /p to pause
  452. **    calls NWDSExtSyncList and lists objects fitting the wildcard passed on
  453. **    the command line.
  454. */
  455. int Dir(char **commandLine)
  456. {
  457.     NWDS_ITERATION                iterHandle = -1L;
  458.     NWOBJECT_INFO                    objectInfo;
  459.     NWDS_BUFFER                        *outBuf;
  460.     NWDSCCODE                            ccode;
  461.     NWCOUNT                                objectCount, attrCount;
  462.     char                                    objectName[MAX_DN_CHARS];
  463.     int                                        i, wild = 0, pause=0, scrcount;
  464.     char                                    option[MAX_COMMAND_LEN];
  465.     char                                    object[MAX_DN_CHARS];
  466.     char                                    line[DEFAULT_MESSAGE_LEN];
  467.     TimeStamp_T                        timeStamp;
  468.  
  469.  
  470.     while(GetToken(commandLine, option))
  471.     {
  472.         if(option[0] == '/')
  473.         {
  474.             if(!strcmp(option, "/p"))
  475.                 pause=1;
  476.             else
  477.             {
  478.                 cprintf("\r\nUnkown Option \"%s\"\r\n", option);
  479.                 cprintf("\r\n\r\nUsage: dir [/p] <Object Name(wildcard)>\r\n\r\n", objectName);
  480.                 return 1;
  481.             }
  482.         }
  483.         else
  484.         {
  485.             wild = 1;
  486.             strcpy(object, option);
  487.         }
  488.     }
  489.     ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
  490.     if(ccode < 0)
  491.         return 1;
  492.     cprintf("\r\n\r\nDirectory of \"%s\"\r\n\r\n", nContext);
  493.     scrcount=2;
  494.     do
  495.     {
  496.         if(wild)
  497.         /*  If there was some command line option that did not start with a "/"
  498.                 it is assumed to be a wild card to list objects.  Wildcard can
  499.                 be a*, *bc, or *abc*.
  500.         */
  501.         {
  502.             ccode = NWDSExtSyncList(    gContext,          /* Context Handle */
  503.                                                                 "",                      /* Container to start list at */
  504.                                                                 "",                      /* Object class to list */
  505.                                                                 object,       /* Object name (wildcards) */
  506.                                                                 &iterHandle,    /* IterationHandle */
  507.                                                                 &timeStamp,        /* Sync Time to search up to */
  508.                                                                 0,                        /* Only containers Boolean */
  509.                                                                 outBuf);            /* Buffer to be filled */
  510.             if(ccode < 0)
  511.                 break;
  512.         }
  513.         else
  514.         {
  515.             ccode = NWDSList(gContext,            /* Context Handle */
  516.                                                 "",                        /* Object Name */
  517.                                                 &iterHandle,    /* Iteration Handle */
  518.                                                 outBuf);         /* Buffer to be filled */
  519.             if(ccode < 0)
  520.                 break;
  521.         }
  522.         ccode = NWDSGetObjectCount(gContext,                /* Context Handle */
  523.                                                                 outBuf,                    /* Buffer full of info*/
  524.                                                                 &objectCount);    /* var for # of objects */
  525.         if(ccode < 0)
  526.             break;
  527.         for(i=0; i<objectCount; i++)
  528.         {
  529.             ccode = NWDSGetObjectName(gContext,            /* Context Handle */
  530.                                                                 outBuf,                /* Buffer full of info */
  531.                                                                 objectName,     /* var for object name */
  532.                                                                 &attrCount,     /* var for # of attributes */
  533.                                                                 &objectInfo); /* var for Object Info */
  534.             if(ccode < 0)
  535.                 break;
  536.  
  537.             /*
  538.                 this section test the baseClass and objectFlags and changes the
  539.                 color printed on the screen to mark certain objects
  540.             */
  541.  
  542.             if(objectInfo.objectFlags & DS_CONTAINER_ENTRY)
  543.             {
  544.                 textcolor(LIGHTGREEN);
  545.                 sprintf(line, "%-25s <CON> %-15s", objectName, objectInfo.baseClass);
  546.                 if(LineOut(&pause, &scrcount, line))
  547.                 {
  548.                     textcolor(LIGHTGRAY);
  549.                     ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  550.                     return (ccode);
  551.                 }
  552.                 textcolor(LIGHTGRAY);
  553.             }
  554.             else
  555.                 if(!strcmp(objectInfo.baseClass, "User"))
  556.                 {
  557.                     textcolor(YELLOW);
  558.                     sprintf(line, "%-25s       %-15s", objectName, objectInfo.baseClass);
  559.                     if(LineOut(&pause, &scrcount, line))
  560.                     {
  561.                         textcolor(LIGHTGRAY);
  562.                         ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  563.                         return (ccode);
  564.                     }
  565.                     textcolor(LIGHTGRAY);
  566.                 }
  567.                 else
  568.                     if(!strcmp(objectInfo.baseClass, "NCP Server"))
  569.                     {
  570.                         textcolor(LIGHTRED);
  571.                         sprintf(line, "%-25s       %-15s", objectName, objectInfo.baseClass);
  572.                         if(LineOut(&pause, &scrcount, line))
  573.                         {
  574.                             textcolor(LIGHTGRAY);
  575.                             ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  576.                             return (ccode);
  577.                         }
  578.                         textcolor(LIGHTGRAY);
  579.                     }
  580.                     else
  581.                         if(!strcmp(objectInfo.baseClass, "Volume"))
  582.                         {
  583.                             textcolor(LIGHTCYAN);
  584.                             sprintf(line, "%-25s       %-15s", objectName, objectInfo.baseClass);
  585.                             if(LineOut(&pause, &scrcount, line))
  586.                             {
  587.                                 textcolor(LIGHTGRAY);
  588.                                 ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  589.                                 return (ccode);
  590.                             }
  591.                             textcolor(LIGHTGRAY);
  592.                         }
  593.                         else
  594.                         {
  595.                             sprintf(line, "%-25s       %-15s", objectName, objectInfo.baseClass);
  596.                             if(LineOut(&pause, &scrcount, line))
  597.                             {
  598.                                 ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  599.                                 return (ccode);
  600.                             }
  601.                         }
  602.         }
  603.     }
  604.     while(iterHandle != -1);
  605.  
  606.     NWDSFreeBuf(outBuf);
  607.     return 0;
  608. }
  609.  
  610.  
  611.  
  612. /***************************************************************************
  613. **    CD
  614. **    Changes the current context to context passed on command line.  If the
  615. **    command line has ".." on it, assumed to be parent context.
  616. */
  617. int CD(char **commandLine)
  618. {
  619.     NWDSCCODE            ccode;
  620.     char                    option[MAX_COMMAND_LEN];
  621.     char          newContainer[MAX_DN_CHARS];
  622.   char                    *newoption;
  623.  
  624.     if(!GetToken(commandLine, option))
  625.     {
  626.         cprintf("\r\n\r\nUsage: cd <RDN | DN>\r\n\r\n");
  627.         return 0;
  628.     }
  629.     if(!strcmp(option, "."))
  630.     {
  631.         cprintf("\r\n");
  632.         return 0;
  633.     }
  634.     if(!strcmp(option, ".."))
  635.     {
  636.         ccode = NWDSCanonicalizeName(gContext, ".", newContainer);
  637.         if(ccode)
  638.         {
  639.             cprintf("\r\nProblem Canonicalizing name\r\n");
  640.             return 1;
  641.         }
  642.         cprintf("\r\n");
  643.         return(ChangeContext(newContainer));
  644.     }
  645.  
  646.     /*
  647.         There are some special cases for creating and changing context names
  648.         handled here
  649.     */
  650.  
  651.     if(!strcmp(nContext, "[Root]"))
  652.     {
  653.         if(option[0] == '.')
  654.         {
  655.             newoption = &(option[1]);
  656.             strcpy(newContainer, newoption);
  657.         }
  658.         else
  659.         {
  660.             strcpy(newContainer, option);
  661.         }
  662.         cprintf("\r\n");
  663.         return(ChangeContext(newContainer));
  664.     }
  665.  
  666.     if(!strcmp(nContext, "\\"))
  667.     {
  668.         if(option[0] == '.')
  669.         {
  670.             newoption = &(option[1]);
  671.             strcpy(newContainer, newoption);
  672.         }
  673.         else
  674.         {
  675.             strcpy(newContainer, option);
  676.         }
  677.         cprintf("\r\n");
  678.         return(ChangeContext(newContainer));
  679.     }
  680.  
  681.     if(!strcmp(option, "\\"))
  682.     {
  683.         strcpy(newContainer, option);
  684.         cprintf("\r\n");
  685.         return(ChangeContext(newContainer));
  686.     }
  687.  
  688.     if(!strcmp(option, "[Root]"))
  689.         strcpy(newContainer, "[Root]");
  690.     else
  691.     {
  692.         if(option[0] == '.')
  693.         {
  694.             newoption = &(option[1]);
  695.             strcpy(newContainer, newoption);
  696.         }
  697.         else
  698.         {
  699.             strcpy(newContainer, option);
  700.             strcat(newContainer, ".");
  701.             strcat(newContainer, nContext);
  702.         }
  703.     }
  704.     return(ChangeContext(newContainer));
  705. }
  706.  
  707.  
  708.  
  709. /***************************************************************************
  710. **    Class
  711. **    Same as DIR but only lists objects on the class specified.  In other
  712. **    words, if the command was "User" then all User objects are listed.
  713. */
  714. int Class(char **commandLine)
  715. {
  716.     NWDS_ITERATION                iterHandle = -1L;
  717.     NWOBJECT_INFO                    objectInfo;
  718.     NWDS_BUFFER                        *outBuf;
  719.     NWDSCCODE                            ccode;
  720.     NWCOUNT                                objectCount, attrCount;
  721.     char                                    objectName[MAX_DN_CHARS];
  722.     int                                        i, pause=0, scrcount;
  723.     char                                    option[MAX_COMMAND_LEN];
  724.     char                                    className[MAX_COMMAND_LEN];
  725.     char                                    object[MAX_DN_CHARS];
  726.     char                                    line[DEFAULT_MESSAGE_LEN];
  727.     TimeStamp_T                        timeStamp;
  728.  
  729.  
  730.     /*
  731.         This first function call was a hack in order to get the class name
  732.         since it is supposed to be taken off when tokenizing the original
  733.         command.
  734.     */
  735.     if(!GetToken(commandLine, className))
  736.         return 1;
  737.     while(GetToken(commandLine, option))
  738.     {
  739.         if(!strcmp(option, "/p"))
  740.             pause=1;
  741.         else
  742.         {
  743.             cprintf("\r\nUnkown Option \"%s\"\r\n", option);
  744.             cprintf("\r\n\r\nUsage: %s [/p] \r\n\r\n", className);
  745.             return 1;
  746.         }
  747.     }
  748.     ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
  749.     if(ccode < 0)
  750.         return 1;
  751.     cprintf("\r\n\r\nClass \"%s\" List\r\n\r\n", className);
  752.     scrcount=2;
  753.     do
  754.     {
  755.         ccode = NWDSExtSyncList(    gContext,
  756.                                                             "",
  757.                                                             className,
  758.                                                             "",
  759.                                                             &iterHandle,
  760.                                                             NULL,
  761.                                                             0,
  762.                                                             outBuf);
  763.         if(ccode < 0)
  764.             break;
  765.  
  766.         ccode = NWDSGetObjectCount(gContext,                /* Context Handle */
  767.                                                                 outBuf,                    /* Buffer full of info*/
  768.                                                                 &objectCount);    /* var for # of objects */
  769.         if(ccode < 0)
  770.             break;
  771.         for(i=0; i<objectCount; i++)
  772.         {
  773.             ccode = NWDSGetObjectName(gContext,            /* Context Handle */
  774.                                                                 outBuf,                /* Buffer full of info */
  775.                                                                 objectName,     /* var for object name */
  776.                                                                 &attrCount,     /* var for # of attributes */
  777.                                                                 &objectInfo); /* var for Object Info */
  778.             if(ccode < 0)
  779.                 break;
  780.  
  781.             if(objectInfo.objectFlags & DS_CONTAINER_ENTRY)
  782.             {
  783.                 textcolor(LIGHTGREEN);
  784.                 sprintf(line, "%-25s <CON> %-15s", objectName, objectInfo.baseClass);
  785.                 if(LineOut(&pause, &scrcount, line))
  786.                 {
  787.                     textcolor(LIGHTGRAY);
  788.                     ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  789.                     return (ccode);
  790.                 }
  791.                 textcolor(LIGHTGRAY);
  792.             }
  793.             else
  794.                 if(!strcmp(objectInfo.baseClass, "User"))
  795.                 {
  796.                     textcolor(YELLOW);
  797.                     sprintf(line, "%-25s       %-15s", objectName, objectInfo.baseClass);
  798.                     if(LineOut(&pause, &scrcount, line))
  799.                     {
  800.                         textcolor(LIGHTGRAY);
  801.                         ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  802.                         return (ccode);
  803.                     }
  804.                     textcolor(LIGHTGRAY);
  805.                 }
  806.                 else
  807.                     if(!strcmp(objectInfo.baseClass, "NCP Server"))
  808.                     {
  809.                         textcolor(LIGHTRED);
  810.                         sprintf(line, "%-25s       %-15s", objectName, objectInfo.baseClass);
  811.                         if(LineOut(&pause, &scrcount, line))
  812.                         {
  813.                             textcolor(LIGHTGRAY);
  814.                             ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  815.                             return (ccode);
  816.                         }
  817.                         textcolor(LIGHTGRAY);
  818.                     }
  819.                     else
  820.                         if(!strcmp(objectInfo.baseClass, "Volume"))
  821.                         {
  822.                             textcolor(LIGHTCYAN);
  823.                             sprintf(line, "%-25s       %-15s", objectName, objectInfo.baseClass);
  824.                             if(LineOut(&pause, &scrcount, line))
  825.                             {
  826.                                 textcolor(LIGHTGRAY);
  827.                                 ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  828.                                 return (ccode);
  829.                             }
  830.                             textcolor(LIGHTGRAY);
  831.                         }
  832.                         else
  833.                         {
  834.                             sprintf(line, "%-25s       %-15s", objectName, objectInfo.baseClass);
  835.                             if(LineOut(&pause, &scrcount, line))
  836.                             {
  837.                                 ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  838.                                 return (ccode);
  839.                             }
  840.                         }
  841.         }
  842.     }
  843.     while(iterHandle != -1);
  844.  
  845.     NWDSFreeBuf(outBuf);
  846.     return 0;
  847. }
  848.  
  849.  
  850.  
  851. /***************************************************************************
  852. **    Classes
  853. **    Lists all classes currently defined in the schema.  This includes any
  854. **  classes added to the schema.  When classes are displayed, any blank
  855. **    characters are replaced with a "_" for command line use.
  856. */
  857. int Classes(char **commandLine)
  858. {
  859.     NWDS_ITERATION                iterHandle = -1L;
  860.     NWCLASS_INFO                    classInfo;
  861.     NWDS_BUFFER                        *outBuf;
  862.     NWDSCCODE                            ccode;
  863.     NWCOUNT                                classCount;
  864.     char                                    className[MAX_DN_CHARS];
  865.     int                                        i, pause=1, scrcount, charcount;
  866.     char                                    option[MAX_COMMAND_LEN];
  867.     char                                    line[DEFAULT_MESSAGE_LEN];
  868.  
  869.     while(GetToken(commandLine, option))
  870.     {
  871.         if(!strcmp(option, "/p"))
  872.             pause=1;
  873.         else
  874.         {
  875.             cprintf("\r\nUnkown Option \"%s\"\r\n", option);
  876.             cprintf("\r\n\r\nUsage: classes [/p] \r\n\r\n");
  877.             return 1;
  878.         }
  879.     }
  880.     ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
  881.     if(ccode < 0)
  882.         return 1;
  883.     cprintf("\r\n\r\nListing of NDS Classes \r\n\r\n");
  884.     scrcount=2;
  885.     do
  886.     {
  887.         ccode = NWDSReadClassDef(    gContext,                        /* context handle */
  888.                                                             DS_CLASS_DEF_NAMES, /* type of info to read */
  889.                                                             TRUE,                                /* read all classes */
  890.                                                             NULL,
  891.                                                             &iterHandle,                /* iteration handle */
  892.                                                             outBuf);                        /* Buffer to fill */
  893.         if(ccode)
  894.             break;
  895.  
  896.         ccode = NWDSGetClassDefCount(    gContext,                /* Context Handle */
  897.                                                                     outBuf,                    /* Buffer full of info*/
  898.                                                                     &classCount);      /* var for # of classes */
  899.         if(ccode < 0)
  900.             break;
  901.         for(i=0; i<classCount; i++)
  902.         {
  903.             ccode = NWDSGetClassDef(    gContext,            /* Context Handle */
  904.                                                                 outBuf,                /* Buffer full of info */
  905.                                                                 className,       /* var for class name */
  906.                                                                 &classInfo);  /* var for Class Info */
  907.             if(ccode < 0)
  908.                 break;
  909.  
  910.             for(charcount=strlen(className); charcount >= 0; charcount--)
  911.             {
  912.                 if(className[charcount] == ' ')
  913.                     className[charcount] = '_';
  914.             }
  915.  
  916.             sprintf(line, "%-25s", className);
  917.             if(LineOut(&pause, &scrcount, line))
  918.             {
  919.                 ccode = NWDSCloseIteration(gContext, iterHandle, DSV_READ_CLASS_DEF);
  920.                 return (ccode);
  921.             }
  922.         }
  923.     }
  924.     while(iterHandle != -1L);
  925.  
  926.     NWDSFreeBuf(outBuf);
  927.     return 0;
  928. }
  929.  
  930.  
  931.  
  932. /***************************************************************************
  933. **    Tree
  934. **    Prepares some variables needed to call DoTree.
  935. */
  936. int Tree(void)
  937. {
  938.     int treelevel=0;
  939.     int    pause=1, scrcount=0, canceled=0;
  940.     long    treeMap=0;
  941.  
  942.     clrscr();
  943.     cprintf("\r\n\r\nNDS Tree\r\n", nContext);
  944.     cprintf("%s\r\n", nContext);
  945.     scrcount = 2;
  946.     return(DoTree(&treelevel, &pause, &scrcount, &canceled, &treeMap));
  947. }
  948.  
  949.  
  950.  
  951. /***************************************************************************
  952. **    DoTree
  953. **    Builds a tree of all containers from the current container
  954. **    on down the tree.  This is ugly if you have a very large tree.
  955. **  This does not display non-container objects.
  956. */
  957. int DoTree(int *treelevel, int *pause, int *scrcount, int *canceled, long *treeMap)
  958. {
  959.     NWDS_ITERATION                iterHandle = -1L;
  960.     NWOBJECT_INFO                    objectInfo;
  961.     NWDS_BUFFER                        *outBuf;
  962.     NWDSCCODE                            ccode;
  963.     NWCOUNT                                objectCount, attrCount;
  964.     char                                    objectName[MAX_RDN_CHARS];
  965.     int                                        i;
  966.     char                                    tmpContext[MAX_DN_CHARS];
  967.     char                                    line[160];
  968.     int                                        counter;
  969.     long                                    tmpMap;
  970.  
  971.     ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
  972.     if(ccode < 0)
  973.         goto _TREEExit2;
  974.     do
  975.     {
  976.         ccode = NWDSExtSyncList(    gContext,
  977.                                                             "",
  978.                                                             "",
  979.                                                             "",
  980.                                                             &iterHandle,
  981.                                                             NULL,
  982.                                                             TRUE,
  983.                                                             outBuf);
  984.         if(ccode < 0)
  985.             goto _TREEExit1;
  986.  
  987.         ccode = NWDSGetObjectCount(gContext,                /* Context Handle */
  988.                                                                 outBuf,                    /* Buffer full of info*/
  989.                                                                 &objectCount);    /* var for # of objects */
  990.         if(ccode < 0)
  991.             goto _TREEExit1;
  992.         for(i=0; i<objectCount; i++)
  993.         {
  994.             ccode = NWDSGetObjectName(gContext,            /* Context Handle */
  995.                                                                 outBuf,                /* Buffer full of info */
  996.                                                                 objectName,     /* var for object name */
  997.                                                                 &attrCount,     /* var for # of attributes */
  998.                                                                 &objectInfo); /* var for Object Info */
  999.             if(ccode < 0)
  1000.                 goto _TREEExit1;
  1001.  
  1002.             tmpMap = 0x001;
  1003.             for(counter=0; counter < (*treelevel); counter++)
  1004.             {
  1005.                 tmpMap <<= counter;
  1006.                 if(!((*treeMap) & tmpMap))
  1007.                     cprintf("\xb3  ");
  1008.                 else
  1009.                     cprintf("   ");
  1010.             }
  1011.             if((*canceled))
  1012.             {
  1013.                 ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  1014.                 goto _TREEExit1;
  1015.             }
  1016.             if((iterHandle == -1) && ((i+1) >= objectCount))
  1017.             {
  1018.                 tmpMap = 0x001;
  1019.                 tmpMap <<= (*treelevel);
  1020.                 (*treeMap) |= tmpMap;
  1021.                 sprintf(line, "\xc0%s", objectName);
  1022.             }
  1023.             else
  1024.             {
  1025.                 tmpMap = 0x001;
  1026.                 tmpMap <<= (*treelevel);
  1027.                 (*treeMap) &= ~tmpMap;
  1028.                 sprintf(line, "\xc3%s", objectName);
  1029.             }
  1030.             if(LineOut(pause, scrcount, line))
  1031.             {
  1032.                 ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
  1033.                 (*canceled) = 1;
  1034.                 goto _TREEExit1;
  1035.             }
  1036.             if(objectInfo.subordinateCount)
  1037.             {
  1038.                 strcpy(tmpContext, objectName);
  1039.                 strcat(tmpContext, ".");
  1040.                 strcat(tmpContext, nContext);
  1041.                 ccode = NWDSSetContext(gContext, DCK_NAME_CONTEXT, tmpContext);
  1042.                 if(ccode < 0)
  1043.                 {
  1044.                     cprintf("\r\nProblem Changing Contexts\r\n");
  1045.                     goto _TREEExit1;
  1046.                 }
  1047.                 strcpy(tmpContext, nContext);
  1048.                 ccode = NWDSGetContext(gContext, DCK_NAME_CONTEXT, (void *)nContext);
  1049.                 if(ccode < 0)
  1050.                 {
  1051.                     cprintf("\r\nProblem Setting Contexts\r\n");
  1052.                     goto _TREEExit1;
  1053.                 }
  1054.                 (*treelevel)++;
  1055.                 DoTree(treelevel, pause, scrcount, canceled, treeMap);
  1056.                 (*treelevel)--;
  1057.                 ccode = NWDSSetContext(gContext, DCK_NAME_CONTEXT, tmpContext);
  1058.                 if(ccode < 0)
  1059.                 {
  1060.                     cprintf("\r\nProblem Changing Contexts\r\n");
  1061.                     goto _TREEExit1;
  1062.                 }
  1063.                 strcpy(tmpContext, nContext);
  1064.                 ccode = NWDSGetContext(gContext, DCK_NAME_CONTEXT, (void *)nContext);
  1065.                 if(ccode < 0)
  1066.                 {
  1067.                     cprintf("\r\nProblem Setting Contexts\r\n");
  1068.                     goto _TREEExit1;
  1069.                 }
  1070.             }
  1071.         }
  1072.     }
  1073.     while(iterHandle != -1);
  1074.  
  1075.     _TREEExit1:
  1076.     NWDSFreeBuf(outBuf);
  1077.     _TREEExit2:
  1078.     return ccode;
  1079. }
  1080.  
  1081.  
  1082.  
  1083. /***************************************************************************
  1084. **    ChangeContext
  1085. **    Performs the actual changing on the context.  Checks first to see if
  1086. **    the container actually exists and then makes the change.
  1087. */
  1088. int ChangeContext(char *newContext)
  1089. {
  1090.     NWDSCCODE                            ccode;
  1091.     char                                    objName[MAX_DN_CHARS];
  1092.     NWOBJECT_INFO                    objectInfo;
  1093.  
  1094.     strcpy(objName, ".");
  1095.     strcat(objName, newContext);
  1096.  
  1097.     ccode = NWDSReadObjectInfo(    gContext,
  1098.                                                             objName,
  1099.                                                             NULL,
  1100.                                                             &objectInfo);
  1101.     if(ccode < 0)
  1102.     {
  1103.         cprintf("\r\nBad Container or Container does not exist!\r\n");
  1104.         return 1;
  1105.     }
  1106.     if(objectInfo.objectFlags & DS_CONTAINER_ENTRY)
  1107.     {
  1108.         ccode = NWDSSetContext(gContext, DCK_NAME_CONTEXT, newContext);
  1109.         if(ccode < 0)
  1110.         {
  1111.             cprintf("\r\nProblem Changing Contexts\r\n");
  1112.             return 1;
  1113.         }
  1114.         ccode = NWDSGetContext(gContext, DCK_NAME_CONTEXT, (void *)nContext);
  1115.         if(ccode < 0)
  1116.         {
  1117.             cprintf("\r\nProblem Setting Contexts\r\n");
  1118.             return 1;
  1119.         }
  1120.     }
  1121.     else
  1122.         cprintf("\r\nNot a Container!\r\n");
  1123.     cprintf("\r\n");
  1124.     if(strcmp(nContext, "[Root]"))
  1125.         strupr(nContext);
  1126.     return 0;
  1127. }
  1128.  
  1129.  
  1130.  
  1131. /***************************************************************************
  1132. **    Banner
  1133. **    Prints the banner shown at the top of NDS Shell.
  1134. */
  1135. int Banner(void)
  1136. {
  1137.     int        x,y;
  1138.  
  1139.     x=wherex();
  1140.     y=wherey();
  1141.     textcolor(WHITE);     /*WHITE*/
  1142.     gotoxy(1,1);
  1143.     cprintf(" NDS Shell ");
  1144.     textbackground(4);
  1145.     cprintf(" Novell Developer Support                                            ");
  1146.     gotoxy(x,y);
  1147.     textcolor(LIGHTGRAY);             /*GREY*/
  1148.     textbackground(0); /*Black*/
  1149.     return 0;
  1150. }
  1151.  
  1152.  
  1153.  
  1154. /***************************************************************************
  1155. **    Type
  1156. **    Prints out an object and all of the attributes with their values that
  1157. **    are currently defined or that can be read with the current rights.
  1158. */
  1159. int Type(char **commandLine)
  1160. {
  1161.     char                            option[MAX_COMMAND_LEN];
  1162.     char                            line[DEFAULT_MESSAGE_LEN];
  1163.     char                            tmpline[10];
  1164.     NWDS_BUFFER                *outBuf;
  1165.     NWDS_ITERATION        iterationHandle;
  1166.     NWDSCCODE                    ccode;
  1167.     char                            objectName[MAX_DN_CHARS];
  1168.     int                                i,j;
  1169.     NWSIZE                        attrSize;
  1170.     NWSYNTAX_ID                syntax;
  1171.     NWCOUNT                        valCount;
  1172.     NWCOUNT                        totalAttrs;
  1173.     char                            currAttr[MAX_DN_CHARS];
  1174.     void                            *attrValue;
  1175.     char                            rightsstr[9];
  1176.     struct date                dt;
  1177.     struct time                tm;
  1178.     WORD                            n;
  1179.     int                                pause=1, scrcount;
  1180.  
  1181.  
  1182.     if(!GetToken(commandLine, option))
  1183.     {
  1184.         cprintf("\r\n\r\nUsage: type <Object Name> [/c]\r\n\r\n", objectName);
  1185.         return 0;
  1186.     }
  1187.     if(!strcmp(option, "."))
  1188.     {
  1189.         strcat(objectName, nContext);
  1190.     }
  1191.     else
  1192.         strcpy(objectName, option);
  1193.  
  1194.     /*
  1195.         Checking for "/c" becuase by default pause is turned on
  1196.     */
  1197.  
  1198.     if(GetToken(commandLine, option))
  1199.     {
  1200.         if(!strcmp(option, "/c"))
  1201.             pause = 0;
  1202.     }
  1203.  
  1204.     strset(rightsstr, '\x0');
  1205.     iterationHandle=-1L;
  1206.  
  1207.     ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
  1208.     if(ccode < 0)
  1209.     {
  1210.             return(ccode);
  1211.     }
  1212.  
  1213.     textcolor(LIGHTGREEN);
  1214.     cprintf("\r\n\r\nAttributes for \"%s\"\r\n\r\n", objectName);
  1215.     textcolor(LIGHTGRAY);
  1216.     scrcount=2;
  1217.     do
  1218.     {
  1219.         ccode = NWDSRead(gContext,                /* Context Handle  (IN)        */
  1220.                                 objectName,                        /* name of object  (IN)        */
  1221.                                 DS_ATTRIBUTE_VALUES,    /* a #define         (IN)            */
  1222.                                 TRUE,                                    /* All Attributes (IN)            */
  1223.                                 NULL,                                    /* Attribute names (IN)     */
  1224.                                 &iterationHandle,            /* iteration Handle (OUT) */
  1225.                                 outBuf);              /* Output Buffer (OUT)         */
  1226.         if(ccode < 0)
  1227.         {
  1228.                 NWDSFreeBuf(outBuf);
  1229.                 return(ccode);
  1230.         }
  1231.         ccode = NWDSGetAttrCount(gContext, outBuf, &totalAttrs);
  1232.         if(ccode < 0)
  1233.         {
  1234.                 NWDSFreeBuf(outBuf);
  1235.                 return(ccode);
  1236.         }
  1237.         if((NWCOUNT)0 == totalAttrs)
  1238.         {
  1239.                 NWDSFreeBuf(outBuf);
  1240.                 return(1);
  1241.         }
  1242.         for(i = 0; i < totalAttrs; i++)
  1243.         {
  1244.             ccode = NWDSGetAttrName(gContext, outBuf, currAttr, &valCount, &syntax);
  1245.             if(ccode < 0)
  1246.             {
  1247.                     NWDSFreeBuf(outBuf);
  1248.                     return(ccode);
  1249.             }
  1250.             textcolor(LIGHTGREEN);
  1251.             sprintf(line, "Attribute: %s", currAttr);
  1252.             LineOut(&pause, &scrcount, line);
  1253.             textcolor(LIGHTGRAY);
  1254.             for(j = 0; j < valCount; j++)
  1255.             {
  1256.  
  1257.                 /*  Note that the attribute value size is computed each time a value
  1258.                         is read.  Each attribute may have multiple values and each value
  1259.                         may be a different size */
  1260.  
  1261.                 ccode = NWDSComputeAttrValSize(gContext, outBuf, syntax, &attrSize);
  1262.                 if(ccode < 0)
  1263.                 {
  1264.                         NWDSFreeBuf(outBuf);
  1265.                         return(ccode);
  1266.                 }
  1267.                 if((attrValue = malloc((int)attrSize))==NULL)
  1268.                 {
  1269.                     NWDSFreeBuf(outBuf);
  1270.                     return(ccode);
  1271.                 }
  1272.                 ccode = NWDSGetAttrVal(gContext, outBuf, syntax, attrValue);
  1273.                 if(ccode < 0)
  1274.                     break;
  1275.  
  1276.                 /*
  1277.                     This is a pretty ugly switch statement which handles all of the
  1278.                     syntaxes in NDS.  Some syntaxes have the same data types and
  1279.                     therefore are printed out alike.  For a list of valid syntaxes,
  1280.                     see the NDS Schema Specification in the NLM area of the online
  1281.                     Documentation
  1282.                 */
  1283.  
  1284.                 switch(syntax)
  1285.                 {
  1286.                     case SYN_BACK_LINK    :
  1287.                                         sprintf(line, "%lu",((Back_Link_T *)attrValue)->remoteID);
  1288.                                         if(LineOut(&pause, &scrcount, line))
  1289.                                         {
  1290.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1291.                                             return (ccode);
  1292.                                         }
  1293.                                         sprintf(line, "%s",((Back_Link_T *)attrValue)->objectName);
  1294.                                         if(LineOut(&pause, &scrcount, line))
  1295.                                         {
  1296.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1297.                                             return (ccode);
  1298.                                         }
  1299.                                         break;
  1300.                     case SYN_BOOLEAN        :
  1301.                                         sprintf(line, "%s", ((*((uint8 *)attrValue)) ? "TRUE" : "FALSE"));
  1302.                                         if(LineOut(&pause, &scrcount, line))
  1303.                                         {
  1304.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1305.                                             return (ccode);
  1306.                                         }
  1307.                                         break;
  1308.                     case SYN_CI_LIST        :
  1309.                                         sprintf(line, "%s", ((CI_List_T *)attrValue)->s);
  1310.                                         if(LineOut(&pause, &scrcount, line))
  1311.                                         {
  1312.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1313.                                             return (ccode);
  1314.                                         }
  1315.                                         break;
  1316.                     case SYN_COUNTER        :
  1317.                                         sprintf(line, "%lu", *((uint32 *)attrValue));
  1318.                                         if(LineOut(&pause, &scrcount, line))
  1319.                                         {
  1320.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1321.                                             return (ccode);
  1322.                                         }
  1323.                                         break;
  1324.                     case SYN_CE_STRING     :                                /* All of these are strings */
  1325.                     case SYN_CI_STRING    :                                /* and therefore are all    */
  1326.                     case SYN_NU_STRING    :               /* printed the same way     */
  1327.                     case SYN_PR_STRING    :
  1328.                     case SYN_TEL_NUMBER    :
  1329.                     case SYN_CLASS_NAME    :
  1330.                     case SYN_DIST_NAME    :
  1331.                                         sprintf(line, "%s",(char *)attrValue);
  1332.                                         if(LineOut(&pause, &scrcount, line))
  1333.                                         {
  1334.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1335.                                             return (ccode);
  1336.                                         }
  1337.                                         break;
  1338.                     case SYN_EMAIL_ADDRESS :
  1339.                                         sprintf(line, "%lu, %s", ((EMail_Address_T *)attrValue)->type, ((EMail_Address_T *)attrValue)->address);
  1340.                                         if(LineOut(&pause, &scrcount, line))
  1341.                                         {
  1342.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1343.                                             return (ccode);
  1344.                                         }
  1345.                                         break;
  1346.                     case SYN_FAX_NUMBER    :
  1347.                                         sprintf(line, "%s",((Fax_Number_T *)attrValue)->telephoneNumber);
  1348.                                         if(LineOut(&pause, &scrcount, line))
  1349.                                         {
  1350.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1351.                                             return (ccode);
  1352.                                         }
  1353.                                         break;
  1354.                     case SYN_HOLD        :
  1355.                                         sprintf(line, "%s, %lu",((Hold_T *)attrValue)->objectName,((Hold_T *)attrValue)->amount);
  1356.                                         if(LineOut(&pause, &scrcount, line))
  1357.                                         {
  1358.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1359.                                             return (ccode);
  1360.                                         }
  1361.                                         break;
  1362.                     case SYN_INTEGER    :
  1363.                     case SYN_INTERVAL    :
  1364.                                         sprintf(line, "%lu",*((uint32 *)attrValue));
  1365.                                         if(LineOut(&pause, &scrcount, line))
  1366.                                         {
  1367.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1368.                                             return (ccode);
  1369.                                         }
  1370.                                         break;
  1371.                     case SYN_NET_ADDRESS    :
  1372.                                         sprintf(line, "Address Type:%lu", ((Net_Address_T *)attrValue)->addressType);
  1373.                                         if(LineOut(&pause, &scrcount, line))
  1374.                                         {
  1375.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1376.                                             return (ccode);
  1377.                                         }
  1378.                                         sprintf(line, "Address Length:%lu", ((Net_Address_T *)attrValue)->addressLength);
  1379.                                         if(LineOut(&pause, &scrcount, line))
  1380.                                         {
  1381.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1382.                                             return (ccode);
  1383.                                         }
  1384.                                         sprintf(line, "Address:%02X%02X%02X%02X:%02X%02X%02X%02X%02X%02X",((Net_Address_T *)attrValue)->address[0],((Net_Address_T *)attrValue)->address[1],((Net_Address_T *)attrValue)->address[2],((Net_Address_T *)attrValue)->address[3],((Net_Address_T *)attrValue)->address[4],((Net_Address_T *)attrValue)->address[5],((Net_Address_T *)attrValue)->address[6],((Net_Address_T *)attrValue)->address[7],((Net_Address_T *)attrValue)->address[8],((Net_Address_T *)attrValue)->address[9]);
  1385.                                         if(LineOut(&pause, &scrcount, line))
  1386.                                         {
  1387.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1388.                                             return (ccode);
  1389.                                         }
  1390.                                         break;
  1391.                     case SYN_OBJECT_ACL    :
  1392.                                         DecodeRights(((Object_ACL_T *)attrValue)->protectedAttrName, rightsstr, ((Object_ACL_T *)attrValue)->privileges);
  1393.                                         sprintf(line,"%-25s %s %s",((Object_ACL_T *)attrValue)->protectedAttrName,rightsstr,((Object_ACL_T *)attrValue)->subjectName);
  1394.                                         if(LineOut(&pause, &scrcount, line))
  1395.                                         {
  1396.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1397.                                             return (ccode);
  1398.                                         }
  1399.                                         break;
  1400.                     case SYN_OCTET_LIST :
  1401.                                         sprintf(line, "Because the syntax SYN_OCTET_LIST is a linked list it is not shown here");
  1402.                                         if(LineOut(&pause, &scrcount, line))
  1403.                                         {
  1404.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1405.                                             return (ccode);
  1406.                                         }
  1407.                                         break;
  1408.                     case SYN_OCTET_STRING :
  1409.                                         sprintf(line, "Length: 0x%x",((Octet_String_T *)attrValue)->length);
  1410.                                         if(LineOut(&pause, &scrcount, line))
  1411.                                         {
  1412.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1413.                                             return (ccode);
  1414.                                         }
  1415.                                         sprintf(line, "Data:");
  1416.                                         if(LineOut(&pause, &scrcount, line))
  1417.                                         {
  1418.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1419.                                             return (ccode);
  1420.                                         }
  1421.                                         strset(line, '\x0');
  1422.                                         for(n=0; n<((Octet_String_T *)attrValue)->length; n++)
  1423.                                         {
  1424.                                             if(!(n%4))
  1425.                                             {
  1426.                                                 strcat(line," ");
  1427.                                             }
  1428.                                             if(!(n%32))
  1429.                                             {
  1430.                                                 if(LineOut(&pause, &scrcount, line))
  1431.                                                 {
  1432.                                                     ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1433.                                                     return (ccode);
  1434.                                                 }
  1435.                                                 strset(line, '\x0');
  1436.                                             }
  1437.                                             sprintf(tmpline, "%02X",(uint8 *)((Octet_String_T *)attrValue)->data[n]);
  1438.                                             strcat(line, tmpline);
  1439.                                         }
  1440.                                         if(LineOut(&pause, &scrcount, line))
  1441.                                         {
  1442.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1443.                                             return (ccode);
  1444.                                         }
  1445.                                         break;
  1446.                     case SYN_PATH    :
  1447.                                         sprintf(line, "Name Space Type: %lu",((Path_T *)attrValue)->nameSpaceType);
  1448.                                         if(LineOut(&pause, &scrcount, line))
  1449.                                         {
  1450.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1451.                                             return (ccode);
  1452.                                         }
  1453.                                         sprintf(line, "%s:%s", ((Path_T *)attrValue)->volumeName,((Path_T *)attrValue)->path);
  1454.                                         if(LineOut(&pause, &scrcount, line))
  1455.                                         {
  1456.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1457.                                             return (ccode);
  1458.                                         }
  1459.                                         break;
  1460.                     case SYN_PO_ADDRESS :
  1461.                                         sprintf(line, "%s",((char **)attrValue)[0]);
  1462.                                         if(LineOut(&pause, &scrcount, line))
  1463.                                         {
  1464.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1465.                                             return (ccode);
  1466.                                         }
  1467.                                         sprintf(line, "%s",((char **)attrValue)[1]);
  1468.                                         if(LineOut(&pause, &scrcount, line))
  1469.                                         {
  1470.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1471.                                             return (ccode);
  1472.                                         }
  1473.                                         sprintf(line, "%s",((char **)attrValue)[2]);
  1474.                                         if(LineOut(&pause, &scrcount, line))
  1475.                                         {
  1476.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1477.                                             return (ccode);
  1478.                                         }
  1479.                                         sprintf(line, "%s",((char **)attrValue)[3]);
  1480.                                         if(LineOut(&pause, &scrcount, line))
  1481.                                         {
  1482.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1483.                                             return (ccode);
  1484.                                         }
  1485.                                         sprintf(line, "%s",((char **)attrValue)[4]);
  1486.                                         if(LineOut(&pause, &scrcount, line))
  1487.                                         {
  1488.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1489.                                             return (ccode);
  1490.                                         }
  1491.                                         sprintf(line, "%s",((char **)attrValue)[5]);
  1492.                                         if(LineOut(&pause, &scrcount, line))
  1493.                                         {
  1494.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1495.                                             return (ccode);
  1496.                                         }
  1497.                                         break;
  1498.                     case SYN_REPLICA_POINTER    :
  1499.                                         sprintf(line, "serverName: %s", ((Replica_Pointer_T *)attrValue)->serverName);
  1500.                                         if(LineOut(&pause, &scrcount, line))
  1501.                                         {
  1502.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1503.                                             return (ccode);
  1504.                                         }
  1505.                                         sprintf(line, "replicaType: %lu",((Replica_Pointer_T *)attrValue)->replicaType);
  1506.                                         if(LineOut(&pause, &scrcount, line))
  1507.                                         {
  1508.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1509.                                             return (ccode);
  1510.                                         }
  1511.                                         sprintf(line, "replicaNumber: %u", ((Replica_Pointer_T *)attrValue)->replicaNumber);
  1512.                                         if(LineOut(&pause, &scrcount, line))
  1513.                                         {
  1514.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1515.                                             return (ccode);
  1516.                                         }
  1517.                                         sprintf(line, "count: %lu", ((Replica_Pointer_T *)attrValue)->count);
  1518.                                         if(LineOut(&pause, &scrcount, line))
  1519.                                         {
  1520.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1521.                                             return (ccode);
  1522.                                         }
  1523.                                         sprintf(line, "Replica_Pointer_T.Net_Address_T not shown with this utility");
  1524.                                         if(LineOut(&pause, &scrcount, line))
  1525.                                         {
  1526.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1527.                                             return (ccode);
  1528.                                         }
  1529.                                         break;
  1530.                     case SYN_STREAM :
  1531.                                         sprintf(line, "Syntax \"SYN_STREAM\" not shown with this utility");
  1532. /*
  1533.                                         This syntax is not shown because of the difficulty in
  1534.                                         displaying it in this type of screen output.  I left in
  1535.                                         the code here to show how it could be done...
  1536.  
  1537.                                         ccode = NWDSOpenStream(gContext, objectName, currAttr, (NWDS_FLAGS)1, &fHandle);
  1538.                                         if(!ccode)
  1539.                                             _lread(fHandle, (void *)tmpBuffer, DEFAULT_MESSAGE_LEN);
  1540.                                         else
  1541.                                         {
  1542.                                             sprintf(tmpBuffer,"NWDSOpenStream returned: %d",ccode);
  1543.                                         }
  1544.                                         close(fHandle);
  1545. */
  1546.                                         break;
  1547.                     case SYN_TIME :
  1548.                                         unixtodos(*((uint32 *)attrValue), &dt, &tm);
  1549.                                         sprintf(line, "%d-%d-%d  %d:%d:%d", dt.da_mon, dt.da_day, dt.da_year, tm.ti_hour, tm.ti_min, tm.ti_sec);
  1550.                                         if(LineOut(&pause, &scrcount, line))
  1551.                                         {
  1552.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1553.                                             return (ccode);
  1554.                                         }
  1555.                                         break;
  1556.                     case SYN_TIMESTAMP :
  1557.                                         unixtodos(((NWDS_TimeStamp_T *)attrValue)->wholeSeconds, &dt, &tm);
  1558.                                         sprintf(line, "%d-%d-%d  %d:%d:%d", dt.da_mon, dt.da_day, dt.da_year, tm.ti_hour, tm.ti_min, tm.ti_sec);
  1559.                                         if(LineOut(&pause, &scrcount, line))
  1560.                                         {
  1561.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1562.                                             return (ccode);
  1563.                                         }
  1564.                                         sprintf(line, "%lu", ((NWDS_TimeStamp_T *)attrValue)->eventID);
  1565.                                         if(LineOut(&pause, &scrcount, line))
  1566.                                         {
  1567.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1568.                                             return (ccode);
  1569.                                         }
  1570.                                         break;
  1571.                     case SYN_TYPED_NAME :
  1572.                                         sprintf(line, "0x%x, 0x%x, 0x%x", ((Typed_Name_T *)attrValue)->objectName, ((Typed_Name_T *)attrValue)->level, ((Typed_Name_T *)attrValue)->interval);
  1573.                                         if(LineOut(&pause, &scrcount, line))
  1574.                                         {
  1575.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1576.                                             return (ccode);
  1577.                                         }
  1578.                                         break;
  1579.                     default                :
  1580.                                         sprintf(line, "Unrecognized Sytax");
  1581.                                         if(LineOut(&pause, &scrcount, line))
  1582.                                         {
  1583.                                             ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
  1584.                                             return (ccode);
  1585.                                         }
  1586.                                         break;
  1587.                 }
  1588.                 free(attrValue);
  1589.             }
  1590.         }
  1591.     }
  1592.     while(iterationHandle != -1L);
  1593.     NWDSFreeBuf(outBuf);
  1594.     return 0;
  1595. }
  1596.  
  1597.  
  1598.  
  1599. /***************************************************************************
  1600. **    DecodeRights
  1601. **    Builds rights string of the format [CRWAS] from NWDS_PRIVILEGES
  1602. */
  1603. void DecodeRights(char *attrName, char *rightsstring, NWDS_PRIVILEGES    privs)
  1604. {
  1605.  
  1606.     strset(rightsstring, '\x0');
  1607.     strcat(rightsstring, "[");
  1608.     if(!strcmp(attrName, "[Entry Rights]"))
  1609.     {
  1610.         if(privs & 0x01)                            /* DS_ENTRY_BROWSE */
  1611.             strcat(rightsstring, "B");
  1612.         else
  1613.             strcat(rightsstring, " ");
  1614.         if(privs & 0x02)                      /* DS_ENTRY_ADD */
  1615.             strcat(rightsstring, "A");
  1616.         else
  1617.             strcat(rightsstring, " ");
  1618.         if(privs & 0x04)                      /* DS_ENTRY_DELETE */
  1619.             strcat(rightsstring, "D");
  1620.         else
  1621.             strcat(rightsstring, " ");
  1622.         if(privs & 0x08)                      /* DS_ENTRY_RENAME */
  1623.             strcat(rightsstring, "R");
  1624.         else
  1625.             strcat(rightsstring, " ");
  1626.         if(privs & 0x10)                      /* DS_ENTRY_SUPERVISOR */
  1627.             strcat(rightsstring, "S");
  1628.         else
  1629.             strcat(rightsstring, " ");
  1630.     }
  1631.     else
  1632.     {
  1633.         if(!strcmp(attrName, "[SMS Rights]"))
  1634.         {
  1635.             if(privs & 0x01)                        /* DS_SMS_SCAN */
  1636.                 strcat(rightsstring, "S");
  1637.             else
  1638.                 strcat(rightsstring, " ");
  1639.             if(privs & 0x02)                        /* DS_SMS_BACKUP */
  1640.                 strcat(rightsstring, "B");
  1641.             else
  1642.                 strcat(rightsstring, " ");
  1643.             if(privs & 0x04)                        /* DS_SMS_RESTORE */
  1644.                 strcat(rightsstring, "R");
  1645.             else
  1646.                 strcat(rightsstring, " ");
  1647.             if(privs & 0x08)                        /* DS_SMS_RENAME */
  1648.                 strcat(rightsstring, "C");
  1649.             else
  1650.                 strcat(rightsstring, " ");
  1651.             if(privs & 0x10)                        /* DS_SMS_DELETE */
  1652.                 strcat(rightsstring, "D");
  1653.             else
  1654.                 strcat(rightsstring, " ");
  1655.             if(privs & 0x20)                        /* DS_SMS_ADMIN */
  1656.                 strcat(rightsstring, "A");
  1657.             else
  1658.                 strcat(rightsstring, " ");
  1659.         }
  1660.         else     /* Attribute Rights which applies to all others */
  1661.         {
  1662.             if(privs & 0x01)                        /* DS_ATTR_COMPARE */
  1663.                 strcat(rightsstring, "C");
  1664.             else
  1665.                 strcat(rightsstring, " ");
  1666.             if(privs & 0x02)                        /* DS_ATTR_READ */
  1667.                 strcat(rightsstring, "R");
  1668.             else
  1669.                 strcat(rightsstring, " ");
  1670.             if(privs & 0x04)                        /* DS_ATTR_WRITE */
  1671.                 strcat(rightsstring, "W");
  1672.             else
  1673.                 strcat(rightsstring, " ");
  1674.             if(privs & 0x08)                        /* DS_ATTR_SELF */
  1675.                 strcat(rightsstring, "A");
  1676.             else
  1677.                 strcat(rightsstring, " ");
  1678.             if(privs & 0x20)                        /* DS_ATTR_SUPERVISOR */
  1679.                 strcat(rightsstring, "S");
  1680.             else
  1681.                 strcat(rightsstring, " ");
  1682.         }
  1683.     }
  1684.     strcat(rightsstring,"]\x0");
  1685. }
  1686.  
  1687.  
  1688.  
  1689. /***************************************************************************
  1690. **    LineOut
  1691. **    Pretty much all output from this application comes through this function
  1692. **    to control line numbers and pausing the screen.
  1693. */
  1694. int LineOut(int *pause, int    *linecount, char *line)
  1695. {
  1696.     char input;
  1697.  
  1698.     cprintf("%s\r\n", line);
  1699.     (*linecount)++;
  1700.     if(((*linecount) >= screenSize) && (*pause))
  1701.     {
  1702.         textcolor(WHITE);
  1703.         cprintf("Press any key to continue (C for Continuous ESC to end) . . .");
  1704.         textcolor(LIGHTGRAY);
  1705.         while(!kbhit());
  1706.         input = getch();
  1707.         if((input == 67) || (input == 99))
  1708.             (*pause) = 0;
  1709.         if(input == 27)
  1710.             return 1;
  1711.         textcolor(WHITE);
  1712.         cprintf("\r\n\r\nContinuing...\r\n");
  1713.         textcolor(LIGHTGRAY);
  1714.         (*linecount) = 0;
  1715.     }
  1716.     return 0;
  1717. }
  1718.  
  1719.  
  1720.  
  1721. /***************************************************************************
  1722. **    Help
  1723. **    Displays all valid commands.
  1724. */
  1725. int Help(void)
  1726. {
  1727.     cprintf("\r\nCommands for NDS Shell\r\n\r\n");
  1728.     cprintf("cd      [RDN | DN] (Relative Distinguished Name | Distinguished Name)\r\n");
  1729.     cprintf("classes [/p] (Lists NDS Classes)\r\n");
  1730.     cprintf("cls\r\n");
  1731.     cprintf("dir     [/p]\r\n");
  1732.     cprintf("exit    [/s] (Exit NDS Shell  /s sets default context)\r\n");
  1733.     cprintf("help    (Help -- This Page)\r\n");
  1734.     cprintf("mode    <25 | 50> (lines per page)\r\n");
  1735.     cprintf("tree    (Displays the tree from current context)\r\n");
  1736.     cprintf("type    <Object Name> [/c] (continuous)\r\n");
  1737.     cprintf("?       (Help -- This Page)\r\n");
  1738.     cprintf("<class> [/p] (Where class is the NDS Class to be Listed)\r\n");
  1739.     return 0;
  1740. }
  1741.  
  1742.  
  1743.  
  1744. /***************************************************************************
  1745. **    Version
  1746. **    Displays version information for application.
  1747. */
  1748. int Version(void)
  1749. {
  1750.     cprintf("\r\n\r\nNDS Shell Version 4.1\r\n");
  1751.     cprintf("Written By: Calvin Gaisford\r\n");
  1752.     cprintf("Novell Developer Support\r\n\r\n");
  1753.     return 0;
  1754. }
  1755.  
  1756.  
  1757.  
  1758. /***************************************************************************
  1759. **    IsClass
  1760. **    Checks the class passed in to verify if it is a valid class or not.
  1761. */
  1762. int IsClass(char *className)
  1763. {
  1764.     NWDS_BUFFER                *outBuf, *inBuf;
  1765.     NWDS_ITERATION        iterationHandle = -1L;
  1766.     NWDSCCODE                    ccode;
  1767.  
  1768.     ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
  1769.     if(ccode)
  1770.         return ccode;
  1771.     ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &inBuf);
  1772.     if(ccode)
  1773.         goto _Exit2;
  1774.     ccode = NWDSInitBuf(gContext, DSV_READ_CLASS_DEF, inBuf);
  1775.     if(ccode)
  1776.         goto _Exit1;
  1777.     ccode = NWDSPutClassName(gContext, inBuf, className);
  1778.     if(ccode)
  1779.         goto _Exit1;
  1780.     ccode = NWDSReadClassDef(    gContext,
  1781.                                                         DS_CLASS_DEF_NAMES,
  1782.                                                         FALSE,
  1783.                                                         inBuf,
  1784.                                                         &iterationHandle,
  1785.                                                         outBuf);
  1786.     if(ccode)
  1787.         goto _Exit1;
  1788.     if(iterationHandle != -1L)
  1789.         NWDSCloseIteration(gContext, iterationHandle, DSV_READ_CLASS_DEF);
  1790.  
  1791.     _Exit1:
  1792.         NWDSFreeBuf(inBuf);
  1793.     _Exit2:
  1794.         NWDSFreeBuf(outBuf);
  1795.     return ccode;
  1796. }
  1797.