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 >
Wrap
C/C++ Source or Header
|
1995-07-18
|
52KB
|
1,797 lines
/****************************************************************************
** File: NDSSHELL.C
**
** Desc: A Shell for Novell Directory Services. Provides "DOS" like
** commands for most of the DS functions.
**
**
** DISCLAIMER
**
** Novell, Inc. makes no representations or warranties with respect to
** any NetWare software, and specifically disclaims any express or
** implied warranties of merchantability, title, or fitness for a
** particular purpose.
**
** Distribution of any NetWare software is forbidden without the
** express written consent of Novell, Inc. Further, Novell reserves
** the right to discontinue distribution of any NetWare software.
**
** Novell is not responsible for lost profits or revenue, loss of use
** of the software, loss of data, costs of re-creating lost data, the
** cost of any substitute equipment or program, or claims by any party
** other than you. Novell strongly recommends a backup be made before
** any software is installed. Technical support for this software
** may be provided at the discretion of Novell.
**
** Programmers:
**
** Ini Who Firm
** --- ----------------- ------------------------------------------------
** CRG Calvin Gaisford Novell Developer Support.
**
** History:
**
** When Who What
** -------- --- ---------------------------------------------------------
** 05-14-95 CRG First code.
** 06-05-95 CRG Added all Comments and cleaned up code.
*/
/***************************************************************************
** Libraries Linked in for .exe
**
** NWCALLS.LIB
** NWLOCALE.LIB
** NWNET.LIB
**
*/
/***************************************************************************
** #defines
*/
#define MAX_COMMANDLINE_LEN 50
#define MAX_COMMAND_LEN 50
/* Tokens used when parsing commands */
#define EXIT_TOK 0x001 /* Exit the shell */
#define DIR_TOK 0x002 /* List Objects in Container */
#define CD_TOK 0x003 /* Change the Context */
#define CLS_TOK 0x004 /* Clear the sreen */
#define LS_TOK 0x005 /* Same as dir_tok for Unix People */
#define NOTHING_TOK 0x006 /* The do nothing token */
#define TYPE_TOK 0x007 /* lists all attributes for an object */
#define MODE_TOK 0x008 /* change the screen mode 25/50 chars */
#define HELP_TOK 0x009 /* list valid commands */
#define VER_TOK 0x00A /* show the version of shell */
#define CLASS_TOK 0x00B /* list objects of specified class */
#define CLASSES_TOK 0x00C /* list all classes currently defined */
#define TREE_TOK 0x00D /* show a tree from current container */
/****************************************************************************
** Include headers, macros, etc.
*/
/*-----------------------------------------------------------------------
** ANSI
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <dos.h>
/*-----------------------------------------------------------------------
** NetWare
*/
#include <nwnet.h>
#include <nwcalls.h>
#include <nwlocale.h>
/*-----------------------------------------------------------------------
** Program Global storage
*/
NWDSContextHandle gContext;
char nContext[MAX_DN_CHARS];
int screenSize = 22;
extern unsigned _stklen=8000;
/***************************************************************************
** Function Prototypes
*/
void mainLoop(void);
int InitDS(void);
int UninitDS(void);
int ProccessCommand(char **commandLine);
int Tokenize(char **commandLine);
int GetToken(char **commandLine, char *command);
int Dir(char **commandLine);
int CD(char **commandLine);
int ChangeContext(char *newContext);
int Banner(void);
int Type(char **commandLine);
void DecodeRights(char *attrName, char *rightsstring, NWDS_PRIVILEGES privs);
int LineOut(int *pause, int *linecount, char *line);
int Mode(char **commandLine);
int Help(void);
int Version(void);
int IsClass(char *className);
int Class(char **commandLine);
int Classes(char **commandLine);
int Exit(char **commandLine);
int DoTree(int *treelevel, int *pause, int *scrcount, int *canceled, long *treeMap);
int Tree(void);
/***************************************************************************
** main
** Only makes three calls. Setup context, loop, cleanup context.
*/
void main(void)
{
if(!InitDS())
mainLoop();
UninitDS();
}
/***************************************************************************
** mainLoop
** Gets all commands from the command line, sets them to lower case and
** sends them off to be processed. Also reads the current mode and sets
** the page length for screen pausing.
*/
void mainLoop(void)
{
char input[MAX_COMMANDLINE_LEN], *commandLine;
struct text_info tInfo;
gettextinfo(&tInfo);
screenSize = (tInfo.screenheight - 3);
clrscr();
do
{
cprintf("\r\n%s>>", nContext);
Banner();
cgets(input);
commandLine = &input[2];
strlwr(commandLine);
}
while(!ProccessCommand(&commandLine));
}
/***************************************************************************
** InitDS
** Create and setup context. These are the standard initializations
** for DS calls
*/
int InitDS(void)
{
NWDSCCODE ccode;
DWORD flags;
LCONV lconvInfo;
ccode=NWCallsInit(NULL,NULL);
if(ccode) /* initialize allowing to call nwcalls functions */
{
printf("FatalError during NWCallsInit %X\n",ccode);
return 1;
}
NWLlocaleconv(&lconvInfo);
ccode = NWInitUnicodeTables(lconvInfo.country_id, lconvInfo.code_page);
if(ccode)
{
printf("NWInitUnicodeTables() returned: %04X\n", ccode);
return 1;
}
gContext=NWDSCreateContext();
if(gContext)
{
printf("FatalError during NWDSCreateContext %X\n",gContext);
return 1;
}
ccode = NWDSGetContext(gContext, DCK_FLAGS, &flags);
if(ccode < 0)
return 1;
flags |= DCV_TYPELESS_NAMES;
/* This will setup the context so that it accepts and returns typeless
names. A typeless name is jross.HR.Novell and not
CN=jross.OU=HR.O=Novell.
*/
ccode = NWDSSetContext(gContext, DCK_FLAGS, &flags);
if(ccode < 0)
return 1;
ccode = NWDSGetContext(gContext, DCK_NAME_CONTEXT, (void *)nContext);
if(ccode < 0)
return 1;
if(strcmp(nContext, "[Root]"))
strupr(nContext);
return 0;
}
/***************************************************************************
** UninitDS
** Release context and unicode tables.
*/
int UninitDS()
{
NWDSCCODE ccode;
ccode=NWDSFreeContext(gContext);
if(ccode)
{
printf("FatalError during NWDSFreeContext %X\n",ccode);
return 1;
}
ccode=NWFreeUnicodeTables();
if(ccode)
{
printf("Error during NWFreeUnicodeTables()\n");
return 1;
}
return(0);
}
/***************************************************************************
** ProcessCommand
** This will take a pointer to the command line, get the command and
** execute the corresponding function with it's command line parameters.
*/
int ProccessCommand(char **commandLine)
{
switch(Tokenize(commandLine))
{
case EXIT_TOK:
return(Exit(commandLine));
case LS_TOK:
case DIR_TOK:
Dir(commandLine);
break;
case CD_TOK:
CD(commandLine);
break;
case CLS_TOK:
clrscr();
break;
case TYPE_TOK:
if(Type(commandLine))
cprintf("\r\nError Typing Object \r\n");
break;
case MODE_TOK:
Mode(commandLine);
break;
case HELP_TOK:
Help();
break;
case VER_TOK:
Version();
break;
case CLASSES_TOK:
Classes(commandLine);
break;
case CLASS_TOK:
Class(commandLine);
break;
case TREE_TOK:
Tree();
break;
case NOTHING_TOK:
break;
default:
cprintf("\r\nCommand not recognized.\r\n");
}
return 0;
}
/***************************************************************************
** Tokenize
** Simply takes a pointer to a string and turns the first group of letters
** (space delimited) and returns a corresponding token. The commandLine
** is pointing to the character just right of the first command.
*/
int Tokenize(char **commandLine)
{
char command[MAX_COMMAND_LEN];
GetToken(commandLine, command);
if(!strcmpi(command, "EXIT"))
return(EXIT_TOK);
if(!strcmp(command, "dir"))
return(DIR_TOK);
if(!strcmp(command, "cd"))
return(CD_TOK);
if(!strcmp(command, "cls"))
return(CLS_TOK);
if(!strcmp(command, "ls"))
return(LS_TOK);
if(!strcmp(command, "type"))
return(TYPE_TOK);
if(!strcmp(command, "mode"))
return(MODE_TOK);
if(!strcmp(command, "?"))
return(HELP_TOK);
if(!strcmp(command, "help"))
return(HELP_TOK);
if(!strcmp(command, "ver"))
return(VER_TOK);
if(!strcmp(command, ""))
return(NOTHING_TOK);
if(!strcmp(command, "classes"))
return(CLASSES_TOK);
if(!strcmp(command, "tree"))
return(TREE_TOK);
if(!IsClass(command))
{
strcat(command, (*commandLine));
strcpy((*commandLine), command);
return(CLASS_TOK);
}
return 0;
}
/***************************************************************************
** GetToken
** Takes the first word (space delimited) and copies it into the string
** passed in and leaves the commandline pointing to the next word. All
** white spaces are skipped on the front of the commandLine.
*/
int GetToken(char **commandLine, char *command)
{
int len;
while(((*commandLine)[0] < 33) && ((*commandLine)[0] != '\x0'))
(*commandLine)++;
for(len=0; ((len < MAX_COMMAND_LEN) && ((*commandLine)[0] > 32)); len++)
{
command[len] = (*commandLine)[0];
(*commandLine)++;
}
command[len] = '\x0';
return(strlen(command));
}
/***************************************************************************
** Exit
** Ends the NDS Shell program and if there is a optional /s on with the
** command, the default context is set to whatever the current context
** is within the NDS Shell.
*/
int Exit(char **commandLine)
{
char option[MAX_COMMAND_LEN];
BYTE newContext[MAX_DN_CHARS];
NWCCODE ccode;
if(GetToken(commandLine, option))
{
if(!strcmp(option, "/s"))
{
strcpy(newContext, ".");
/*
before setting the context, prepend a "." on it so the client
software does not append the context onto the end
*/
strcat(newContext, nContext);
ccode = NWSetDefaultNameContext(MAX_DN_CHARS, newContext);
if(ccode)
cprintf("\r\nError Saving Context: %X\r\n", ccode);
else
{
clrscr();
return 1;
}
}
cprintf("\r\nUnkown Option \"%s\"\r\n", option);
cprintf("\r\n\r\nUsage: exit [/s]\r\n\r\n");
return 0;
}
clrscr();
return 1;
}
/***************************************************************************
** Mode
** This only sets the screen output and has no NetWare API calls.
** Switches the screen from 25 to 50 or 50 to 25 lines.
*/
int Mode(char **commandLine)
{
char option[MAX_COMMAND_LEN];
struct text_info tInfo;
GetToken(commandLine, option);
if(!strcmp(option, "50"))
{
textmode(C4350);
gettextinfo(&tInfo);
screenSize = (tInfo.screenheight - 3);
return 0;
}
if(!strcmp(option, "25"))
{
textmode(C80);
gettextinfo(&tInfo);
screenSize = (tInfo.screenheight - 3);
return 0;
}
cprintf("\r\nUnkown Option \"%s\"\r\n", option);
cprintf("\r\n\r\nUsage: mode [50 | 25]\r\n\r\n");
return 1;
}
/***************************************************************************
** Dir
** If no command line options are included, calls NWDSList and just lists
** all objects in the current container.
** If command line options are passed in and they do not equal /p to pause
** calls NWDSExtSyncList and lists objects fitting the wildcard passed on
** the command line.
*/
int Dir(char **commandLine)
{
NWDS_ITERATION iterHandle = -1L;
NWOBJECT_INFO objectInfo;
NWDS_BUFFER *outBuf;
NWDSCCODE ccode;
NWCOUNT objectCount, attrCount;
char objectName[MAX_DN_CHARS];
int i, wild = 0, pause=0, scrcount;
char option[MAX_COMMAND_LEN];
char object[MAX_DN_CHARS];
char line[DEFAULT_MESSAGE_LEN];
TimeStamp_T timeStamp;
while(GetToken(commandLine, option))
{
if(option[0] == '/')
{
if(!strcmp(option, "/p"))
pause=1;
else
{
cprintf("\r\nUnkown Option \"%s\"\r\n", option);
cprintf("\r\n\r\nUsage: dir [/p] <Object Name(wildcard)>\r\n\r\n", objectName);
return 1;
}
}
else
{
wild = 1;
strcpy(object, option);
}
}
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
if(ccode < 0)
return 1;
cprintf("\r\n\r\nDirectory of \"%s\"\r\n\r\n", nContext);
scrcount=2;
do
{
if(wild)
/* If there was some command line option that did not start with a "/"
it is assumed to be a wild card to list objects. Wildcard can
be a*, *bc, or *abc*.
*/
{
ccode = NWDSExtSyncList( gContext, /* Context Handle */
"", /* Container to start list at */
"", /* Object class to list */
object, /* Object name (wildcards) */
&iterHandle, /* IterationHandle */
&timeStamp, /* Sync Time to search up to */
0, /* Only containers Boolean */
outBuf); /* Buffer to be filled */
if(ccode < 0)
break;
}
else
{
ccode = NWDSList(gContext, /* Context Handle */
"", /* Object Name */
&iterHandle, /* Iteration Handle */
outBuf); /* Buffer to be filled */
if(ccode < 0)
break;
}
ccode = NWDSGetObjectCount(gContext, /* Context Handle */
outBuf, /* Buffer full of info*/
&objectCount); /* var for # of objects */
if(ccode < 0)
break;
for(i=0; i<objectCount; i++)
{
ccode = NWDSGetObjectName(gContext, /* Context Handle */
outBuf, /* Buffer full of info */
objectName, /* var for object name */
&attrCount, /* var for # of attributes */
&objectInfo); /* var for Object Info */
if(ccode < 0)
break;
/*
this section test the baseClass and objectFlags and changes the
color printed on the screen to mark certain objects
*/
if(objectInfo.objectFlags & DS_CONTAINER_ENTRY)
{
textcolor(LIGHTGREEN);
sprintf(line, "%-25s <CON> %-15s", objectName, objectInfo.baseClass);
if(LineOut(&pause, &scrcount, line))
{
textcolor(LIGHTGRAY);
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
return (ccode);
}
textcolor(LIGHTGRAY);
}
else
if(!strcmp(objectInfo.baseClass, "User"))
{
textcolor(YELLOW);
sprintf(line, "%-25s %-15s", objectName, objectInfo.baseClass);
if(LineOut(&pause, &scrcount, line))
{
textcolor(LIGHTGRAY);
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
return (ccode);
}
textcolor(LIGHTGRAY);
}
else
if(!strcmp(objectInfo.baseClass, "NCP Server"))
{
textcolor(LIGHTRED);
sprintf(line, "%-25s %-15s", objectName, objectInfo.baseClass);
if(LineOut(&pause, &scrcount, line))
{
textcolor(LIGHTGRAY);
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
return (ccode);
}
textcolor(LIGHTGRAY);
}
else
if(!strcmp(objectInfo.baseClass, "Volume"))
{
textcolor(LIGHTCYAN);
sprintf(line, "%-25s %-15s", objectName, objectInfo.baseClass);
if(LineOut(&pause, &scrcount, line))
{
textcolor(LIGHTGRAY);
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
return (ccode);
}
textcolor(LIGHTGRAY);
}
else
{
sprintf(line, "%-25s %-15s", objectName, objectInfo.baseClass);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
return (ccode);
}
}
}
}
while(iterHandle != -1);
NWDSFreeBuf(outBuf);
return 0;
}
/***************************************************************************
** CD
** Changes the current context to context passed on command line. If the
** command line has ".." on it, assumed to be parent context.
*/
int CD(char **commandLine)
{
NWDSCCODE ccode;
char option[MAX_COMMAND_LEN];
char newContainer[MAX_DN_CHARS];
char *newoption;
if(!GetToken(commandLine, option))
{
cprintf("\r\n\r\nUsage: cd <RDN | DN>\r\n\r\n");
return 0;
}
if(!strcmp(option, "."))
{
cprintf("\r\n");
return 0;
}
if(!strcmp(option, ".."))
{
ccode = NWDSCanonicalizeName(gContext, ".", newContainer);
if(ccode)
{
cprintf("\r\nProblem Canonicalizing name\r\n");
return 1;
}
cprintf("\r\n");
return(ChangeContext(newContainer));
}
/*
There are some special cases for creating and changing context names
handled here
*/
if(!strcmp(nContext, "[Root]"))
{
if(option[0] == '.')
{
newoption = &(option[1]);
strcpy(newContainer, newoption);
}
else
{
strcpy(newContainer, option);
}
cprintf("\r\n");
return(ChangeContext(newContainer));
}
if(!strcmp(nContext, "\\"))
{
if(option[0] == '.')
{
newoption = &(option[1]);
strcpy(newContainer, newoption);
}
else
{
strcpy(newContainer, option);
}
cprintf("\r\n");
return(ChangeContext(newContainer));
}
if(!strcmp(option, "\\"))
{
strcpy(newContainer, option);
cprintf("\r\n");
return(ChangeContext(newContainer));
}
if(!strcmp(option, "[Root]"))
strcpy(newContainer, "[Root]");
else
{
if(option[0] == '.')
{
newoption = &(option[1]);
strcpy(newContainer, newoption);
}
else
{
strcpy(newContainer, option);
strcat(newContainer, ".");
strcat(newContainer, nContext);
}
}
return(ChangeContext(newContainer));
}
/***************************************************************************
** Class
** Same as DIR but only lists objects on the class specified. In other
** words, if the command was "User" then all User objects are listed.
*/
int Class(char **commandLine)
{
NWDS_ITERATION iterHandle = -1L;
NWOBJECT_INFO objectInfo;
NWDS_BUFFER *outBuf;
NWDSCCODE ccode;
NWCOUNT objectCount, attrCount;
char objectName[MAX_DN_CHARS];
int i, pause=0, scrcount;
char option[MAX_COMMAND_LEN];
char className[MAX_COMMAND_LEN];
char object[MAX_DN_CHARS];
char line[DEFAULT_MESSAGE_LEN];
TimeStamp_T timeStamp;
/*
This first function call was a hack in order to get the class name
since it is supposed to be taken off when tokenizing the original
command.
*/
if(!GetToken(commandLine, className))
return 1;
while(GetToken(commandLine, option))
{
if(!strcmp(option, "/p"))
pause=1;
else
{
cprintf("\r\nUnkown Option \"%s\"\r\n", option);
cprintf("\r\n\r\nUsage: %s [/p] \r\n\r\n", className);
return 1;
}
}
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
if(ccode < 0)
return 1;
cprintf("\r\n\r\nClass \"%s\" List\r\n\r\n", className);
scrcount=2;
do
{
ccode = NWDSExtSyncList( gContext,
"",
className,
"",
&iterHandle,
NULL,
0,
outBuf);
if(ccode < 0)
break;
ccode = NWDSGetObjectCount(gContext, /* Context Handle */
outBuf, /* Buffer full of info*/
&objectCount); /* var for # of objects */
if(ccode < 0)
break;
for(i=0; i<objectCount; i++)
{
ccode = NWDSGetObjectName(gContext, /* Context Handle */
outBuf, /* Buffer full of info */
objectName, /* var for object name */
&attrCount, /* var for # of attributes */
&objectInfo); /* var for Object Info */
if(ccode < 0)
break;
if(objectInfo.objectFlags & DS_CONTAINER_ENTRY)
{
textcolor(LIGHTGREEN);
sprintf(line, "%-25s <CON> %-15s", objectName, objectInfo.baseClass);
if(LineOut(&pause, &scrcount, line))
{
textcolor(LIGHTGRAY);
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
return (ccode);
}
textcolor(LIGHTGRAY);
}
else
if(!strcmp(objectInfo.baseClass, "User"))
{
textcolor(YELLOW);
sprintf(line, "%-25s %-15s", objectName, objectInfo.baseClass);
if(LineOut(&pause, &scrcount, line))
{
textcolor(LIGHTGRAY);
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
return (ccode);
}
textcolor(LIGHTGRAY);
}
else
if(!strcmp(objectInfo.baseClass, "NCP Server"))
{
textcolor(LIGHTRED);
sprintf(line, "%-25s %-15s", objectName, objectInfo.baseClass);
if(LineOut(&pause, &scrcount, line))
{
textcolor(LIGHTGRAY);
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
return (ccode);
}
textcolor(LIGHTGRAY);
}
else
if(!strcmp(objectInfo.baseClass, "Volume"))
{
textcolor(LIGHTCYAN);
sprintf(line, "%-25s %-15s", objectName, objectInfo.baseClass);
if(LineOut(&pause, &scrcount, line))
{
textcolor(LIGHTGRAY);
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
return (ccode);
}
textcolor(LIGHTGRAY);
}
else
{
sprintf(line, "%-25s %-15s", objectName, objectInfo.baseClass);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
return (ccode);
}
}
}
}
while(iterHandle != -1);
NWDSFreeBuf(outBuf);
return 0;
}
/***************************************************************************
** Classes
** Lists all classes currently defined in the schema. This includes any
** classes added to the schema. When classes are displayed, any blank
** characters are replaced with a "_" for command line use.
*/
int Classes(char **commandLine)
{
NWDS_ITERATION iterHandle = -1L;
NWCLASS_INFO classInfo;
NWDS_BUFFER *outBuf;
NWDSCCODE ccode;
NWCOUNT classCount;
char className[MAX_DN_CHARS];
int i, pause=1, scrcount, charcount;
char option[MAX_COMMAND_LEN];
char line[DEFAULT_MESSAGE_LEN];
while(GetToken(commandLine, option))
{
if(!strcmp(option, "/p"))
pause=1;
else
{
cprintf("\r\nUnkown Option \"%s\"\r\n", option);
cprintf("\r\n\r\nUsage: classes [/p] \r\n\r\n");
return 1;
}
}
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
if(ccode < 0)
return 1;
cprintf("\r\n\r\nListing of NDS Classes \r\n\r\n");
scrcount=2;
do
{
ccode = NWDSReadClassDef( gContext, /* context handle */
DS_CLASS_DEF_NAMES, /* type of info to read */
TRUE, /* read all classes */
NULL,
&iterHandle, /* iteration handle */
outBuf); /* Buffer to fill */
if(ccode)
break;
ccode = NWDSGetClassDefCount( gContext, /* Context Handle */
outBuf, /* Buffer full of info*/
&classCount); /* var for # of classes */
if(ccode < 0)
break;
for(i=0; i<classCount; i++)
{
ccode = NWDSGetClassDef( gContext, /* Context Handle */
outBuf, /* Buffer full of info */
className, /* var for class name */
&classInfo); /* var for Class Info */
if(ccode < 0)
break;
for(charcount=strlen(className); charcount >= 0; charcount--)
{
if(className[charcount] == ' ')
className[charcount] = '_';
}
sprintf(line, "%-25s", className);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_READ_CLASS_DEF);
return (ccode);
}
}
}
while(iterHandle != -1L);
NWDSFreeBuf(outBuf);
return 0;
}
/***************************************************************************
** Tree
** Prepares some variables needed to call DoTree.
*/
int Tree(void)
{
int treelevel=0;
int pause=1, scrcount=0, canceled=0;
long treeMap=0;
clrscr();
cprintf("\r\n\r\nNDS Tree\r\n", nContext);
cprintf("%s\r\n", nContext);
scrcount = 2;
return(DoTree(&treelevel, &pause, &scrcount, &canceled, &treeMap));
}
/***************************************************************************
** DoTree
** Builds a tree of all containers from the current container
** on down the tree. This is ugly if you have a very large tree.
** This does not display non-container objects.
*/
int DoTree(int *treelevel, int *pause, int *scrcount, int *canceled, long *treeMap)
{
NWDS_ITERATION iterHandle = -1L;
NWOBJECT_INFO objectInfo;
NWDS_BUFFER *outBuf;
NWDSCCODE ccode;
NWCOUNT objectCount, attrCount;
char objectName[MAX_RDN_CHARS];
int i;
char tmpContext[MAX_DN_CHARS];
char line[160];
int counter;
long tmpMap;
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
if(ccode < 0)
goto _TREEExit2;
do
{
ccode = NWDSExtSyncList( gContext,
"",
"",
"",
&iterHandle,
NULL,
TRUE,
outBuf);
if(ccode < 0)
goto _TREEExit1;
ccode = NWDSGetObjectCount(gContext, /* Context Handle */
outBuf, /* Buffer full of info*/
&objectCount); /* var for # of objects */
if(ccode < 0)
goto _TREEExit1;
for(i=0; i<objectCount; i++)
{
ccode = NWDSGetObjectName(gContext, /* Context Handle */
outBuf, /* Buffer full of info */
objectName, /* var for object name */
&attrCount, /* var for # of attributes */
&objectInfo); /* var for Object Info */
if(ccode < 0)
goto _TREEExit1;
tmpMap = 0x001;
for(counter=0; counter < (*treelevel); counter++)
{
tmpMap <<= counter;
if(!((*treeMap) & tmpMap))
cprintf("\xb3 ");
else
cprintf(" ");
}
if((*canceled))
{
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
goto _TREEExit1;
}
if((iterHandle == -1) && ((i+1) >= objectCount))
{
tmpMap = 0x001;
tmpMap <<= (*treelevel);
(*treeMap) |= tmpMap;
sprintf(line, "\xc0%s", objectName);
}
else
{
tmpMap = 0x001;
tmpMap <<= (*treelevel);
(*treeMap) &= ~tmpMap;
sprintf(line, "\xc3%s", objectName);
}
if(LineOut(pause, scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterHandle, DSV_SEARCH);
(*canceled) = 1;
goto _TREEExit1;
}
if(objectInfo.subordinateCount)
{
strcpy(tmpContext, objectName);
strcat(tmpContext, ".");
strcat(tmpContext, nContext);
ccode = NWDSSetContext(gContext, DCK_NAME_CONTEXT, tmpContext);
if(ccode < 0)
{
cprintf("\r\nProblem Changing Contexts\r\n");
goto _TREEExit1;
}
strcpy(tmpContext, nContext);
ccode = NWDSGetContext(gContext, DCK_NAME_CONTEXT, (void *)nContext);
if(ccode < 0)
{
cprintf("\r\nProblem Setting Contexts\r\n");
goto _TREEExit1;
}
(*treelevel)++;
DoTree(treelevel, pause, scrcount, canceled, treeMap);
(*treelevel)--;
ccode = NWDSSetContext(gContext, DCK_NAME_CONTEXT, tmpContext);
if(ccode < 0)
{
cprintf("\r\nProblem Changing Contexts\r\n");
goto _TREEExit1;
}
strcpy(tmpContext, nContext);
ccode = NWDSGetContext(gContext, DCK_NAME_CONTEXT, (void *)nContext);
if(ccode < 0)
{
cprintf("\r\nProblem Setting Contexts\r\n");
goto _TREEExit1;
}
}
}
}
while(iterHandle != -1);
_TREEExit1:
NWDSFreeBuf(outBuf);
_TREEExit2:
return ccode;
}
/***************************************************************************
** ChangeContext
** Performs the actual changing on the context. Checks first to see if
** the container actually exists and then makes the change.
*/
int ChangeContext(char *newContext)
{
NWDSCCODE ccode;
char objName[MAX_DN_CHARS];
NWOBJECT_INFO objectInfo;
strcpy(objName, ".");
strcat(objName, newContext);
ccode = NWDSReadObjectInfo( gContext,
objName,
NULL,
&objectInfo);
if(ccode < 0)
{
cprintf("\r\nBad Container or Container does not exist!\r\n");
return 1;
}
if(objectInfo.objectFlags & DS_CONTAINER_ENTRY)
{
ccode = NWDSSetContext(gContext, DCK_NAME_CONTEXT, newContext);
if(ccode < 0)
{
cprintf("\r\nProblem Changing Contexts\r\n");
return 1;
}
ccode = NWDSGetContext(gContext, DCK_NAME_CONTEXT, (void *)nContext);
if(ccode < 0)
{
cprintf("\r\nProblem Setting Contexts\r\n");
return 1;
}
}
else
cprintf("\r\nNot a Container!\r\n");
cprintf("\r\n");
if(strcmp(nContext, "[Root]"))
strupr(nContext);
return 0;
}
/***************************************************************************
** Banner
** Prints the banner shown at the top of NDS Shell.
*/
int Banner(void)
{
int x,y;
x=wherex();
y=wherey();
textcolor(WHITE); /*WHITE*/
gotoxy(1,1);
cprintf(" NDS Shell ");
textbackground(4);
cprintf(" Novell Developer Support ");
gotoxy(x,y);
textcolor(LIGHTGRAY); /*GREY*/
textbackground(0); /*Black*/
return 0;
}
/***************************************************************************
** Type
** Prints out an object and all of the attributes with their values that
** are currently defined or that can be read with the current rights.
*/
int Type(char **commandLine)
{
char option[MAX_COMMAND_LEN];
char line[DEFAULT_MESSAGE_LEN];
char tmpline[10];
NWDS_BUFFER *outBuf;
NWDS_ITERATION iterationHandle;
NWDSCCODE ccode;
char objectName[MAX_DN_CHARS];
int i,j;
NWSIZE attrSize;
NWSYNTAX_ID syntax;
NWCOUNT valCount;
NWCOUNT totalAttrs;
char currAttr[MAX_DN_CHARS];
void *attrValue;
char rightsstr[9];
struct date dt;
struct time tm;
WORD n;
int pause=1, scrcount;
if(!GetToken(commandLine, option))
{
cprintf("\r\n\r\nUsage: type <Object Name> [/c]\r\n\r\n", objectName);
return 0;
}
if(!strcmp(option, "."))
{
strcat(objectName, nContext);
}
else
strcpy(objectName, option);
/*
Checking for "/c" becuase by default pause is turned on
*/
if(GetToken(commandLine, option))
{
if(!strcmp(option, "/c"))
pause = 0;
}
strset(rightsstr, '\x0');
iterationHandle=-1L;
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
if(ccode < 0)
{
return(ccode);
}
textcolor(LIGHTGREEN);
cprintf("\r\n\r\nAttributes for \"%s\"\r\n\r\n", objectName);
textcolor(LIGHTGRAY);
scrcount=2;
do
{
ccode = NWDSRead(gContext, /* Context Handle (IN) */
objectName, /* name of object (IN) */
DS_ATTRIBUTE_VALUES, /* a #define (IN) */
TRUE, /* All Attributes (IN) */
NULL, /* Attribute names (IN) */
&iterationHandle, /* iteration Handle (OUT) */
outBuf); /* Output Buffer (OUT) */
if(ccode < 0)
{
NWDSFreeBuf(outBuf);
return(ccode);
}
ccode = NWDSGetAttrCount(gContext, outBuf, &totalAttrs);
if(ccode < 0)
{
NWDSFreeBuf(outBuf);
return(ccode);
}
if((NWCOUNT)0 == totalAttrs)
{
NWDSFreeBuf(outBuf);
return(1);
}
for(i = 0; i < totalAttrs; i++)
{
ccode = NWDSGetAttrName(gContext, outBuf, currAttr, &valCount, &syntax);
if(ccode < 0)
{
NWDSFreeBuf(outBuf);
return(ccode);
}
textcolor(LIGHTGREEN);
sprintf(line, "Attribute: %s", currAttr);
LineOut(&pause, &scrcount, line);
textcolor(LIGHTGRAY);
for(j = 0; j < valCount; j++)
{
/* Note that the attribute value size is computed each time a value
is read. Each attribute may have multiple values and each value
may be a different size */
ccode = NWDSComputeAttrValSize(gContext, outBuf, syntax, &attrSize);
if(ccode < 0)
{
NWDSFreeBuf(outBuf);
return(ccode);
}
if((attrValue = malloc((int)attrSize))==NULL)
{
NWDSFreeBuf(outBuf);
return(ccode);
}
ccode = NWDSGetAttrVal(gContext, outBuf, syntax, attrValue);
if(ccode < 0)
break;
/*
This is a pretty ugly switch statement which handles all of the
syntaxes in NDS. Some syntaxes have the same data types and
therefore are printed out alike. For a list of valid syntaxes,
see the NDS Schema Specification in the NLM area of the online
Documentation
*/
switch(syntax)
{
case SYN_BACK_LINK :
sprintf(line, "%lu",((Back_Link_T *)attrValue)->remoteID);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "%s",((Back_Link_T *)attrValue)->objectName);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_BOOLEAN :
sprintf(line, "%s", ((*((uint8 *)attrValue)) ? "TRUE" : "FALSE"));
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_CI_LIST :
sprintf(line, "%s", ((CI_List_T *)attrValue)->s);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_COUNTER :
sprintf(line, "%lu", *((uint32 *)attrValue));
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_CE_STRING : /* All of these are strings */
case SYN_CI_STRING : /* and therefore are all */
case SYN_NU_STRING : /* printed the same way */
case SYN_PR_STRING :
case SYN_TEL_NUMBER :
case SYN_CLASS_NAME :
case SYN_DIST_NAME :
sprintf(line, "%s",(char *)attrValue);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_EMAIL_ADDRESS :
sprintf(line, "%lu, %s", ((EMail_Address_T *)attrValue)->type, ((EMail_Address_T *)attrValue)->address);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_FAX_NUMBER :
sprintf(line, "%s",((Fax_Number_T *)attrValue)->telephoneNumber);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_HOLD :
sprintf(line, "%s, %lu",((Hold_T *)attrValue)->objectName,((Hold_T *)attrValue)->amount);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_INTEGER :
case SYN_INTERVAL :
sprintf(line, "%lu",*((uint32 *)attrValue));
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_NET_ADDRESS :
sprintf(line, "Address Type:%lu", ((Net_Address_T *)attrValue)->addressType);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "Address Length:%lu", ((Net_Address_T *)attrValue)->addressLength);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
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]);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_OBJECT_ACL :
DecodeRights(((Object_ACL_T *)attrValue)->protectedAttrName, rightsstr, ((Object_ACL_T *)attrValue)->privileges);
sprintf(line,"%-25s %s %s",((Object_ACL_T *)attrValue)->protectedAttrName,rightsstr,((Object_ACL_T *)attrValue)->subjectName);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_OCTET_LIST :
sprintf(line, "Because the syntax SYN_OCTET_LIST is a linked list it is not shown here");
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_OCTET_STRING :
sprintf(line, "Length: 0x%x",((Octet_String_T *)attrValue)->length);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "Data:");
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
strset(line, '\x0');
for(n=0; n<((Octet_String_T *)attrValue)->length; n++)
{
if(!(n%4))
{
strcat(line," ");
}
if(!(n%32))
{
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
strset(line, '\x0');
}
sprintf(tmpline, "%02X",(uint8 *)((Octet_String_T *)attrValue)->data[n]);
strcat(line, tmpline);
}
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_PATH :
sprintf(line, "Name Space Type: %lu",((Path_T *)attrValue)->nameSpaceType);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "%s:%s", ((Path_T *)attrValue)->volumeName,((Path_T *)attrValue)->path);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_PO_ADDRESS :
sprintf(line, "%s",((char **)attrValue)[0]);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "%s",((char **)attrValue)[1]);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "%s",((char **)attrValue)[2]);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "%s",((char **)attrValue)[3]);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "%s",((char **)attrValue)[4]);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "%s",((char **)attrValue)[5]);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_REPLICA_POINTER :
sprintf(line, "serverName: %s", ((Replica_Pointer_T *)attrValue)->serverName);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "replicaType: %lu",((Replica_Pointer_T *)attrValue)->replicaType);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "replicaNumber: %u", ((Replica_Pointer_T *)attrValue)->replicaNumber);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "count: %lu", ((Replica_Pointer_T *)attrValue)->count);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "Replica_Pointer_T.Net_Address_T not shown with this utility");
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_STREAM :
sprintf(line, "Syntax \"SYN_STREAM\" not shown with this utility");
/*
This syntax is not shown because of the difficulty in
displaying it in this type of screen output. I left in
the code here to show how it could be done...
ccode = NWDSOpenStream(gContext, objectName, currAttr, (NWDS_FLAGS)1, &fHandle);
if(!ccode)
_lread(fHandle, (void *)tmpBuffer, DEFAULT_MESSAGE_LEN);
else
{
sprintf(tmpBuffer,"NWDSOpenStream returned: %d",ccode);
}
close(fHandle);
*/
break;
case SYN_TIME :
unixtodos(*((uint32 *)attrValue), &dt, &tm);
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);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_TIMESTAMP :
unixtodos(((NWDS_TimeStamp_T *)attrValue)->wholeSeconds, &dt, &tm);
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);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
sprintf(line, "%lu", ((NWDS_TimeStamp_T *)attrValue)->eventID);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
case SYN_TYPED_NAME :
sprintf(line, "0x%x, 0x%x, 0x%x", ((Typed_Name_T *)attrValue)->objectName, ((Typed_Name_T *)attrValue)->level, ((Typed_Name_T *)attrValue)->interval);
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
default :
sprintf(line, "Unrecognized Sytax");
if(LineOut(&pause, &scrcount, line))
{
ccode = NWDSCloseIteration(gContext, iterationHandle, DSV_READ);
return (ccode);
}
break;
}
free(attrValue);
}
}
}
while(iterationHandle != -1L);
NWDSFreeBuf(outBuf);
return 0;
}
/***************************************************************************
** DecodeRights
** Builds rights string of the format [CRWAS] from NWDS_PRIVILEGES
*/
void DecodeRights(char *attrName, char *rightsstring, NWDS_PRIVILEGES privs)
{
strset(rightsstring, '\x0');
strcat(rightsstring, "[");
if(!strcmp(attrName, "[Entry Rights]"))
{
if(privs & 0x01) /* DS_ENTRY_BROWSE */
strcat(rightsstring, "B");
else
strcat(rightsstring, " ");
if(privs & 0x02) /* DS_ENTRY_ADD */
strcat(rightsstring, "A");
else
strcat(rightsstring, " ");
if(privs & 0x04) /* DS_ENTRY_DELETE */
strcat(rightsstring, "D");
else
strcat(rightsstring, " ");
if(privs & 0x08) /* DS_ENTRY_RENAME */
strcat(rightsstring, "R");
else
strcat(rightsstring, " ");
if(privs & 0x10) /* DS_ENTRY_SUPERVISOR */
strcat(rightsstring, "S");
else
strcat(rightsstring, " ");
}
else
{
if(!strcmp(attrName, "[SMS Rights]"))
{
if(privs & 0x01) /* DS_SMS_SCAN */
strcat(rightsstring, "S");
else
strcat(rightsstring, " ");
if(privs & 0x02) /* DS_SMS_BACKUP */
strcat(rightsstring, "B");
else
strcat(rightsstring, " ");
if(privs & 0x04) /* DS_SMS_RESTORE */
strcat(rightsstring, "R");
else
strcat(rightsstring, " ");
if(privs & 0x08) /* DS_SMS_RENAME */
strcat(rightsstring, "C");
else
strcat(rightsstring, " ");
if(privs & 0x10) /* DS_SMS_DELETE */
strcat(rightsstring, "D");
else
strcat(rightsstring, " ");
if(privs & 0x20) /* DS_SMS_ADMIN */
strcat(rightsstring, "A");
else
strcat(rightsstring, " ");
}
else /* Attribute Rights which applies to all others */
{
if(privs & 0x01) /* DS_ATTR_COMPARE */
strcat(rightsstring, "C");
else
strcat(rightsstring, " ");
if(privs & 0x02) /* DS_ATTR_READ */
strcat(rightsstring, "R");
else
strcat(rightsstring, " ");
if(privs & 0x04) /* DS_ATTR_WRITE */
strcat(rightsstring, "W");
else
strcat(rightsstring, " ");
if(privs & 0x08) /* DS_ATTR_SELF */
strcat(rightsstring, "A");
else
strcat(rightsstring, " ");
if(privs & 0x20) /* DS_ATTR_SUPERVISOR */
strcat(rightsstring, "S");
else
strcat(rightsstring, " ");
}
}
strcat(rightsstring,"]\x0");
}
/***************************************************************************
** LineOut
** Pretty much all output from this application comes through this function
** to control line numbers and pausing the screen.
*/
int LineOut(int *pause, int *linecount, char *line)
{
char input;
cprintf("%s\r\n", line);
(*linecount)++;
if(((*linecount) >= screenSize) && (*pause))
{
textcolor(WHITE);
cprintf("Press any key to continue (C for Continuous ESC to end) . . .");
textcolor(LIGHTGRAY);
while(!kbhit());
input = getch();
if((input == 67) || (input == 99))
(*pause) = 0;
if(input == 27)
return 1;
textcolor(WHITE);
cprintf("\r\n\r\nContinuing...\r\n");
textcolor(LIGHTGRAY);
(*linecount) = 0;
}
return 0;
}
/***************************************************************************
** Help
** Displays all valid commands.
*/
int Help(void)
{
cprintf("\r\nCommands for NDS Shell\r\n\r\n");
cprintf("cd [RDN | DN] (Relative Distinguished Name | Distinguished Name)\r\n");
cprintf("classes [/p] (Lists NDS Classes)\r\n");
cprintf("cls\r\n");
cprintf("dir [/p]\r\n");
cprintf("exit [/s] (Exit NDS Shell /s sets default context)\r\n");
cprintf("help (Help -- This Page)\r\n");
cprintf("mode <25 | 50> (lines per page)\r\n");
cprintf("tree (Displays the tree from current context)\r\n");
cprintf("type <Object Name> [/c] (continuous)\r\n");
cprintf("? (Help -- This Page)\r\n");
cprintf("<class> [/p] (Where class is the NDS Class to be Listed)\r\n");
return 0;
}
/***************************************************************************
** Version
** Displays version information for application.
*/
int Version(void)
{
cprintf("\r\n\r\nNDS Shell Version 4.1\r\n");
cprintf("Written By: Calvin Gaisford\r\n");
cprintf("Novell Developer Support\r\n\r\n");
return 0;
}
/***************************************************************************
** IsClass
** Checks the class passed in to verify if it is a valid class or not.
*/
int IsClass(char *className)
{
NWDS_BUFFER *outBuf, *inBuf;
NWDS_ITERATION iterationHandle = -1L;
NWDSCCODE ccode;
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &outBuf);
if(ccode)
return ccode;
ccode = NWDSAllocBuf(DEFAULT_MESSAGE_LEN, &inBuf);
if(ccode)
goto _Exit2;
ccode = NWDSInitBuf(gContext, DSV_READ_CLASS_DEF, inBuf);
if(ccode)
goto _Exit1;
ccode = NWDSPutClassName(gContext, inBuf, className);
if(ccode)
goto _Exit1;
ccode = NWDSReadClassDef( gContext,
DS_CLASS_DEF_NAMES,
FALSE,
inBuf,
&iterationHandle,
outBuf);
if(ccode)
goto _Exit1;
if(iterationHandle != -1L)
NWDSCloseIteration(gContext, iterationHandle, DSV_READ_CLASS_DEF);
_Exit1:
NWDSFreeBuf(inBuf);
_Exit2:
NWDSFreeBuf(outBuf);
return ccode;
}