www.pudn.com > slist.zip > SLIST.M
/*****************************************************************************
EXHIBIT A
"The contents of this file are subject to the Novell Free Source Agreement
Version 1.0 (the "Agreement"); you may not use this file except in
compliance with the Agreement. You may obtain a copy of the Agreement at
http://developer.novell.com/.
Software distributed under the Agreement is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the Agreement
for the specific language governing rights and limitations under the
Agreement.
The Original Code is slist.m, released under the Novell Free Source License
Agreement 1.0 on 1999.
The Initial Developer of the Original Code is Novell. Portions created
by Novell are Copyright (C) 1988-93, Novell, Inc. All Rights Reserved.
*****************************************************************************/
#include "SList.H"
/****************************************************************************/
/*
Global variables
*/
int pause, /* Should we pause during output? */
doDomain, /* Domain option to output Domains on internet */
outputToFile, /* Is output going to a file? */
linesPerScreen; /* Number of lines to be printed per screen */
char targetServer[SERVER_NAME_SIZE]; /* Server name or pattern to match */
WORD numberConnInUse; /* Used to check for free conn to get Domain Names */
char *VERSION = "VeRsIoN=3.75";
char *COPYRIGHT = "CoPyRiGhT=(c) Copyright 1988-1993, Novell, Inc. All rights reserved.";
char *NNS_MSG = "NaMe SeRvIcE=A NetWare Name Service Utility";
/****************************************************************************/
/*
Description: Main routine for SList
Called by: Other worldly forces
*/
void main(argc, argv)
int argc; /* Number of command line arguments */
char *argv[]; /* Command line arguments */
{
int numServers, /* Number of servers found */
i; /* Loop counter */
char commandLine[256]; /* Command line arguments */
WORD ccode, /* Error code */
connection; /* Default connection */
/*
Assume that we are going to pause after each screen full
*/
pause = TRUE;
/*
If we are not sending output to the screen, don't pause
*/
SetScrollParms();
/*
Assume they want to list all servers
*/
strcpy(targetServer, "*");
/*
Put all the arguments into one command line buffer and convert
it to upper case
*/
strcpy(commandLine, "");
for ( i = 1 ; i < argc ; i++ )
{
if (i > 1)
strcat(commandLine, " ");
strcat(commandLine, strupr(argv[i]));
}
/*
Make sure there are no control characters in the command line
*/
for ( i = 0 ; commandLine[i] != '\0' ; i++ )
if (commandLine[i] < ' ' || commandLine[i] >= '\x7F')
Error(E_CONTROL_CHARACTERS_FOUND);
/*
Try to parse the command line
*/
DefineTokenTable(INITIALTOKENCOUNT, MAXTOKENCOUNT);
SetParseAddress(commandLine);
if (!Parse())
DisplayUsageLine();
/*
Get a connection number to work with
*/
ccode = NWGetDefaultConnectionID(&amt;connection);
if (ccode)
Error(E_NO_DEFAULT_CONNECTION, ccode);
if(doDomain)
{
/* One free connection is necessary to attach to servers to
get Domain Names */
NWGetConnectionList (MY_SESSION, (WORD *)NULL, (WORD)NULL, &amt;numberConnInUse);
if (numberConnInUse > 7)
Error(E_MAX_CONN_FOR_DOMAIN);
DisplayDomainNames(connection);
exit(0);
}
/*
Read in the server names
*/
numServers = ReadServerNames(serverList, connection);
/*
Sort the servers by name
*/
SortServerNames(serverList, numServers);
/*
Print out the server names
*/
PrintServerNames(serverList, numServers, connection);
/*
Now, wasn't that easy?
*/
exit(0);
}
/****************************************************************************/
/*
Description: Displays all Domain Names found on the internet.
Called by: Main
*/
void DisplayDomainNames(defaultConnectionID)
WORD defaultConnectionID;
{
long serverID;
LIST *l, *serverPtr, *listPtr;
WORD currConnectionID, ccode, attachCCODE, more;
char serverName[SERVER_NAME_SIZE];
BYTE serverDomain[PROPERTY_NAME_SIZE];
int i,next, numberFound = 0, advanceFlag = TRUE;
/* Let them know this may take a while */
fprintf(stderr, GetMessage(READING_DOMAIN_NAMES));
fprintf(stderr, "\n");
/* First build server list. */
InitList();
serverID = -1L; /* Set up for scan sequence */
for (i = 0; ;i++)
{
ccode = NWScanObject(defaultConnectionID, "*", OT_FILE_SERVER, &amt;serverID,
serverName, (WORD far *)NULL, (BYTE far *)NULL,
(BYTE far *)NULL, (BYTE far *)NULL);
if (ccode != 0)
break;
l = AppendToList(serverName, (char *)NULL);
if (l == NULL)
{
Error(E_BUILDING_SERVER_LIST);
}
}
/* Attach to servers found in server list, check if in given domain. */
for(serverPtr = GetListHead(); serverPtr != NULL;serverPtr )
{
/* print out dots to show that something is still happening */
advanceFlag = TRUE; /* ART-this flag is used to determine when to */
/* advance in the list, and when not to. */
fprintf(stderr, GetMessage(CHECKING), serverPtr->text);
attachCCODE = NWAttachToFileServer(serverPtr->text, (WORD)0, &amt;currConnectionID);
if((attachCCODE == 0) || (attachCCODE == ALREADY_ATTACHED))
{
/* See if server has DOMAIN_NAME property, if so it's value */
ccode = NWReadPropertyValue(currConnectionID, serverPtr->text,
OT_FILE_SERVER, "DOMAIN_NAME", 1, serverDomain,
NULL, NULL);
if (ccode == 0)
{
/* If there is a Domain is on current server */
/* Copy the Domain name into the table for sorting */
strcpy(serverList[numberFound].name, serverDomain);
/* Increment number of Domains found */
numberFound++;
/* Remove all servers in that Domain from the master server list */
more = next = 0;
while (more != NO_SUCH_SEGMENT)
{
next++;
more = GetServerName(currConnectionID, DOMAIN_OBJ_TYPE,
(char *)serverDomain, serverName, next);
if(more == 0) /* ART - No need to check the last entry again */
{
for(listPtr = GetListHead(); listPtr != NULL;
listPtr = listPtr->next)
{
if(!strcmp(listPtr->text, serverName))
{
if ( serverPtr == listPtr ) /* if name is at head of list */
{
serverPtr = serverPtr->next; /* advance the head now */
advanceFlag = FALSE; /* make sure the head of the list */
} /* is not advanced later */
DeleteFromList(listPtr); /* now you can delete the pointer */
break; /* stop the comparison */
}
}
}
}
}
}
if(attachCCODE != ALREADY_ATTACHED)
NWDetachFromFileServer(currConnectionID);
if ( advanceFlag == TRUE ) /* only advance the head pointer if the flag is set */
serverPtr = serverPtr->next;
}
DestroyList();
SortServerNames(serverList, numberFound);
/* Remove the Reading Domain Names message from the screen */
fprintf(stderr, GetMessage(ERASE_LINE));
/* If output is being sent to a file, tell user that we are doing so */
if (outputToFile)
fprintf(stderr, GetMessage(WRITING_TO_FILE));
/* Now print out all the Domains */
for ( i = 0 ; i <= numberFound-1 ; i++ )
Print(">-47.47s\n", serverList[i].name);
/* Tell how many Domains were found */
if (numberFound)
Print(GetMessage(NUMBER_OF_DOMAINS_FOUND), numberFound);
else
Print(GetMessage(NO_DOMAINS_FOUND));
/* If data was being written to a file, erase the line that
tells him we are writing to the file
*/
if (outputToFile)
fprintf(stderr, GetMessage(ERASE_LINE));
exit(0);
}
/* for use in putting out dots */
void CheckDot( void )
{
static time_t first_time=0;
static time_t next_time=0;
static int dots = 0;
time(&amt;next_time);
if (next_time - first_time > 5)
{
first_time = next_time;
fprintf(stderr, ".");
dots++;
if (dots > 50)
fprintf(stderr, "\n");
}
}
/****************************************************************************/
/*
Description: Gets a server name from SERVERS property of a Domain object.
Called by: Display Domain Names
*/
WORD GetServerName(WORD connectID, WORD type, char *name,char *server,int next)
{
BYTE propValue[PROPERTY_NAME_SIZE];
BYTE moreSeg = 0;
WORD ccode = 0;
strset(propValue, 0);
ccode = NWReadPropertyValue(connectID, name, type, "SERVERS",
(BYTE)((next/2)+(next>2)), propValue, &amt;moreSeg, NULL);
if (ccode != 0)
return(NO_SUCH_SEGMENT); /* if no more segments, return now */
if (next>2) /* first half */
memmove(server, propValue, 47);
else /* second half */
memmove(server, &amt;propValue[48], 47);
if ((server[0]>32) &amt;&amt; (strlen(server) != 0))
return(0); /* ok */
else
{
server[0] = NULL;
return(1); /* no name at that position */
}
}
/****************************************************************************/
/*
Description: Read in a list of all the servers and their addresses
Called by: Main
*/
int ReadServerNames(serverList, connection)
SERVER serverList[]; /* List of servers and their addresses */
WORD connection; /* Default connection */
{
WORD ccode1, /* Return code from ScanObject calls */
ccode2; /* Return code from ReadProperty calls */
int numberFound = 0, /* Number of servers found */
match; /* Should this server be included? */
long objectID = -1L; /* Object number for ScanObject */
char objectName[OBJECT_NAME_SIZE]; /* Object name from ScanObject */
NETADDRESS address; /* Address property read from bindery */
/*
Let the user know we are doing something
*/
fprintf(stderr, GetMessage(READING_SERVER_NAMES));
/*
Prime the pump with the first server
*/
ccode1 = NWScanObject(connection, "*", OT_FILE_SERVER, &amt;objectID,
objectName, NULL, NULL, NULL, NULL);
while (ccode1 == 0)
{
/*
Does this server meet the qualifications?
*/
if (IsWild(targetServer))
match = WildMatch(targetServer, objectName);
else
match = strcmp(targetServer, objectName) == 0;
if (match)
{
/*
Make sure we haven't exceeded the maximum number of servers
*/
if (numberFound >= MAX)
Error(E_TOO_MANY_SERVERS, MAX);
/*
Copy the file server name into the table
*/
strcpy(serverList[numberFound].name, objectName);
/*
Now try to read the network address for the server
*/
ccode2 = NWReadPropertyValue(connection, objectName,
OT_FILE_SERVER, "NET_ADDRESS", 1,
(BYTE *)&amt;address, NULL, NULL);
/*
If network address was read correctly, save it, otherwise
flag it as being unknown
*/
if (ccode2 == 0)
{
address.netAddress = NWLongSwap(address.netAddress);
address.highNode = NWWordSwap(address.highNode );
address.lowNode = NWLongSwap(address.lowNode );
if (address.highNode == 0)
sprintf(serverList[numberFound].addr,
GetMessage(FORMAT_ONE), address.netAddress,
address.lowNode);
else
sprintf(serverList[numberFound].addr,
GetMessage(FORMAT_TWO), address.netAddress,
address.highNode, address.lowNode);
}
else
sprintf(serverList[numberFound].addr,
GetMessage(CANT_READ_ADDRESS));
/*
Increment number of servers found
*/
numberFound++;
}
/*
Try to find another file server
*/
ccode1 = NWScanObject(connection, "*", OT_FILE_SERVER, &amt;objectID,
objectName, NULL, NULL, NULL, NULL);
}
/*
Make sure we didn't get any bizarre error
*/
if (ccode1 != NO_SUCH_OBJECT)
Error(E_READING_SERVER_NAMES, ccode1);
return (numberFound);
}
/****************************************************************************/
/*
Description: Sort the list of the servers
Called by: Main
*/
void SortServerNames(serverList, numServers)
SERVER serverList[]; /* List of servers and their addresses */
int numServers; /* Number of servers found */
{
int i, /* Loop variable */
j; /* Loop variable */
char tempName[SERVER_NAME_SIZE], /* Used for copying server name */
tempAddr[26]; /* Used for copying server address */
/*
I'm a simple man with simple tastes, so a bubble sort will do
*/
for ( i = 0 ; i < numServers-1 ; i++ )
for ( j = 0 ; j < numServers-1 ; j++ )
if (strcmp(serverList[j].name, serverList[j+1].name) > 0)
{
/*
Switch the server names
*/
strcpy(tempName, serverList[j].name );
strcpy(serverList[j].name, serverList[j+1].name );
strcpy(serverList[j+1].name, tempName );
/*
Switch the server addresses
*/
strcpy(tempAddr, serverList[j].addr );
strcpy(serverList[j].addr, serverList[j+1].addr );
strcpy(serverList[j+1].addr, tempAddr );
}
return;
}
/****************************************************************************/
/*
Description: Print the list of servers and there addresses
Called by: Main
*/
void PrintServerNames(serverList, numServers, defaultConnection)
SERVER serverList[]; /* List of servers and there addresses */
int numServers; /* Number of servers found */
WORD defaultConnection; /* Default connection */
{
int i, /* Loop counter */
status; /* Status message for this server */
WORD connection; /* Connection ID to a server in the list */
/*
Clear the message that says we are reading server names
*/
fprintf(stderr, GetMessage(ERASE_LINE));
/*
If output is being sent to a file, tell user that we are doing so
*/
if (outputToFile)
fprintf(stderr, GetMessage(WRITING_TO_FILE));
/*
Now print out all the servers
*/
for ( i = 0 ; i <= numServers-1 ; i++ )
{
/*
See if its time to print a header
*/
if (((i > (linesPerScreen - 2) == 0) &amt;&amt; pause) || i == 0)
{
Print(GetMessage(HEADER_1));
Print(GetMessage(HEADER_2));
}
/*
See if we are attached to this server
*/
status = STATUS_UNATTACHED;
if (!NWGetConnectionID(serverList[i].name, MY_SESSION,
&amt;connection, NULL))
{
if (connection == defaultConnection)
status = STATUS_DEFAULT;
else
status = STATUS_ATTACHED;
}
/*
Print the server name and address
*/
Print(">-47.47s>-24.24s>-8.8s\n", serverList[i].name,
serverList[i].addr, GetMessage(status));
}
/*
Tell how many servers were found
*/
if (numServers)
Print(GetMessage(NUMBER_OF_SERVERS_FOUND), numServers);
else
{
if (IsWild(targetServer))
Print(GetMessage(NO_MATCHING_SERVER), targetServer);
else
Print(GetMessage(NO_SUCH_SERVER), targetServer);
}
/*
If data was being written to a file, erase the line that
tells him we are writing to the file
*/
if (outputToFile)
fprintf(stderr, GetMessage(ERASE_LINE));
/*
Return to caller
*/
return;
}
/****************************************************************************/
/*
Description: Print some data to standard output, pausing if needed
after each screen full
Called by: PrintServerNames
*/
void Print(formatString, ...)
char *formatString; /* Format control string */
{
int c; /* Character input from keyboard */
va_list args; /* Pointer to variable arguments */
static int /* Lines printed so far */
lines = 0;
/*
Figure out where all those other parameters are
*/
va_start(args, formatString);
/*
Print the text required
*/
vprintf(formatString, args);
/*
Increment number of lines printed
*/
lines++;
/*
If we have printed enough lines, and pause is in effect, wait for
a keypress
*/
if (lines == linesPerScreen &amt;&amt; pause)
{
printf(GetMessage(PRESS_A_KEY));
c = getch();
/*
Make sure it wasn't some sort of funky key
*/
if (c == 0 || c == 224)
getch();
/*
If they don't want any more pauses, then don't
*/
if (c == 'C' || c == 'c')
pause = FALSE;
printf(GetMessage(ERASE_LINE));
lines = 0;
}
}
/****************************************************************************/
/*
Description: Print an error message, with optional numeric output
and exit the program
Called by: Main
ReadServerNames
*/
void Error(errorMessageID, ...)
int errorMessageID; /* Error message ID to be printed */
/* Variable arguments may follow */
{
va_list args; /* Pointer to variable arguments */
/*
Figure out where all those other parameters are
*/
va_start(args, errorMessageID);
/*
Print the error message, beep, append a return and exit
*/
fprintf(stderr, GetMessage(ERASE_LINE));
vfprintf(stderr, GetMessage(errorMessageID), args);
fprintf(stderr, "\7\n");
exit(1);
}
/****************************************************************************/
/*
M Code for SList
*/
>
Keyword
CONTINUE
CONTINU
CONTIN
CONTI
CONT
CON
CO
C
CONTINUOUS
CONTINUOU
CONTINUO
DomainOption
DOMAIN
DOMAI
DOM
DO
D
>
Spaces: [ ] min 1 ;
Slash: <\\/> ;
Continue: Slash Keyword `pause = FALSE; ` ;
Domain: Slash DomainOption `doDomain = TRUE; ` ;
Server: [~ \\/] min 1 max 47 `GetServer(); ` ;
Session: EOL |
Continue EOL |
Domain EOL |
Server EOL |
Server Spaces Continue EOL ;
>
/****************************************************************************/
/*
Description: Get the name of the server to be listed, or the
pattern of servers to search for
Called by: M Parser
*/
void GetServer()
{
memcpy(targetServer, TChP(0), TVal(0));
targetServer[TVal(0)] = '\0';
}
/****************************************************************************/
int WildMatch(pattern, string)
char *pattern, *string;
{
char p, s;
int l;
char MatchPeriod;
while ((p = (*pattern &amt; 0x7F)) != '*')
{
s = *string &amt; 0x7F;
if (p == '?')
{
if ((*pattern == SQUESTION)
&amt;&amt; ((s == 0) || (s == '.')))
{
/*special question skip period or end*/
pattern++;
}
else
{
if (s == 0)
return (0); /*no char to match*/
pattern++; /*succeed on ? match*/
string++;
}
}
else if ((*pattern == SPERIOD) &amt;&amt; (s == 0))
{
/*match special period to end-of-string*/
pattern++;
}
else if (p != s)
return (0); /*failure on non-match*/
else if (p == 0)
return (1); /*success on match to nulls*/
else
{
/*chars match, but not end yet*/
pattern++;
string++;
}
}
/* MUST MATCH AN ASTERISK WILDCARD */
MatchPeriod = 0;
while ((*pattern &amt; 0x7F) == '*')
{
/* step over asterisks */
if ((*pattern &amt; 0x80) == 0)
MatchPeriod = 0xFF;
pattern++;
}
for (l = 0; (string[l] != 0) &amt;&amt; ((string[l] != '.') || MatchPeriod);
l++); /*count max characters that may be skipped*/
p = *pattern &amt; 0x7F;
while (l >= 0)
{
s = string[l] &amt; 0x7F;
if (((p == s) || (p == '?') || (p == '.'))
&amt;&amt; WildMatch(pattern, &amt;string[l]))
return (1); /*success*/
l--;
}
return (0);
}
/****************************************************************************/
int IsWild (s)
char *s;
{
char ch;
while ((ch = *s++ &amt; 0x7F) != 0)
{
switch(ch)
{
case ASTERISK:
case QUESTION:
case SPERIOD:
case SASTERISK:
case SQUESTION:
return(1);
}
}
return (0);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void IsServerInADomain(
WORD connectionID, /* connection ID of server to change */
int *isInADomain, /* flag returns TRUE if in a domain */
char *domainName ) /* name of the domain if isInDomain is TRUE */
{
int ccode = TRUE;
long tmpDummy;
char serverName[SERVER_NAME_SIZE];
NWGetFileServerName(connectionID, serverName);
*isInADomain = FALSE;
*domainName = 0;
if (serverName[0] != '\0')
ccode = NWReadPropertyValue( (WORD) connectionID, serverName,
OT_FILE_SERVER, (char far *)"DOMAIN_NAME", 1, (BYTE far *) domainName,
(BYTE far *)&amt;tmpDummy, (BYTE far *)&amt;tmpDummy);
if ( ccode==0 )
*isInADomain = TRUE;
} /* end IsServerInADomain */
/***************************************************************************/
void DisplayUsageLine(void)
{
int isInADomain, jj;
char domainName[PROPERTY_NAME_SIZE];
WORD maxConnects;
NWGetMaximumConnections(&amt;maxConnects);
for (jj=1; jj<=maxConnects; jj++)
{
IsServerInADomain( jj, &amt;isInADomain,
domainName );
if (isInADomain) break;
}
if (isInADomain)
Error(E_NNS_USAGE);
else
Error(E_USAGE);
}
/**************************************************************************/
/**** SetScrollParms ****************************************************
*
* Input: None;
*
* Output: none
*
* Comment: This routine will detect if output is redirected to a
* file and will enable or disable pausing accordingly. Also
* this routine will detect the number of rows in the current
* video mode so that scrolling will work properly.
*
****/
void SetScrollParms()
{
#ifdef DOS
union REGS inregs, outregs;
#endif
/* Assume that we are going to pause after each screen full */
pause = TRUE;
/* Has output been redirected to a file? If so, don't pause! */
if ( isatty( fileno( stdout ) ) )
{
pause = TRUE;
outputToFile = FALSE;
}
else
{
pause = FALSE;
outputToFile = TRUE;
}
#ifdef DOS
/* Issue BIOS call to get current # of screen lines */
inregs.x.ax = 0x1130;
inregs.h.bh = 0;
inregs.x.dx = 0;
int86( VIDEO_INT, &amt;inregs, &amt;outregs );
if( outregs.x.dx != 0 )
linesPerScreen = (BYTE)outregs.h.dl;
else
#endif
linesPerScreen = MIN_LINES;
}
/****************************************************************************/