Please review the function TnmInitPath() in the attached file.
I've replaced the old TnmInitPath code to find the executable
name, with code to use Tcl_GetNameOfExecutable. Along with
some (heavily commented) string mangling code to look for the
other corresponding exectuable. I'm sure there's some nice
clean "Tcl" way to do this, but I don't know what it is. :-/
Hopefully this code will be independant of whatever Tcl
distribution is installed (Sun, ActiveState, TclPro, whatever).
This could be moved into a generic section of Tnm, such as
InitVars?
Pete
/*
* tnmWinInit.c --
*
* This file contains the Windows specific entry point.
*
* Copyright (c) 1996-1997 University of Twente.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tnmInt.h"
#include "tnmPort.h"
#include <arpa/nameser.h>
#include <resolv.h>
#if defined(__WIN32__)
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# undef WIN32_LEAN_AND_MEAN
/*
* VC++ has an alternate entry point called DllMain, so we need to rename
* our entry point.
*/
# if defined(_MSC_VER)
# define EXPORT(a,b) __declspec(dllexport) a b
# define DllEntryPoint DllMain
# else
# if defined(__BORLANDC__)
# define EXPORT(a,b) a _export b
# else
# define EXPORT(a,b) a b
# endif
# endif
#else
# define EXPORT(a,b) a b
#endif
/*
* Forward declarations for procedures defined later in this file:
*/
static void
FixPath _ANSI_ARGS_((char *path));
static char*
GetRegValue _ANSI_ARGS_((char *path, char *attribute));
EXTERN EXPORT(int,Tnm_Init) _ANSI_ARGS_((Tcl_Interp *interp));
EXTERN EXPORT(int,Tnm_SafeInit) _ANSI_ARGS_((Tcl_Interp *interp));
/*
*----------------------------------------------------------------------
*
* DllEntryPoint --
*
* This wrapper function is used by Windows to invoke the
* initialization code for the DLL. If we are compiling
* with Visual C++, this routine will be renamed to DllMain.
* routine.
*
* Results:
* Returns TRUE;
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
#ifdef __WIN32__
BOOL APIENTRY
DllEntryPoint(hInst, reason, reserved)
HINSTANCE hInst; /* Library instance handle. */
DWORD reason; /* Reason this function is being called. */
LPVOID reserved; /* Not used. */
{
return TRUE;
}
#endif
/*
*----------------------------------------------------------------------
*
* FixPath --
*
* This procedure converts a Windows path into the Tcl
* representation by converting "\\" to "/".
*
* Results:
* None.
*
* Side effects:
* The path is modified.
*
*----------------------------------------------------------------------
*/
static void
FixPath(path)
char *path;
{
if (path) {
for (; *path; path++) {
if (*path == '\\') {
*path = '/';
}
}
}
}
/*
*----------------------------------------------------------------------
*
* GetRegValue --
*
* This procedure retrieves a value from the Windows registry.
*
* Results:
* A pointer to the string containing the value or NULL if the
* value can't be obtained. The string points to static memory
* and is overwritten by every call to this procedure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static char *
GetRegValue(path, attribute)
char *path;
char *attribute;
{
int code;
HKEY key;
DWORD size;
static char *value = NULL;
if (value) {
ckfree(value);
value = NULL;
}
code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &key);
if (code != ERROR_SUCCESS) {
return NULL;
}
code = RegQueryValueEx(key, attribute, NULL, NULL, NULL, &size);
if (code != ERROR_SUCCESS) {
return NULL;
}
value = ckalloc(size);
code = RegQueryValueEx(key, attribute, NULL, NULL, value, &size);
if (code != ERROR_SUCCESS) {
ckfree(value);
value = NULL;
}
return value;
}
/*
*----------------------------------------------------------------------
*
* TnmInitPath --
*
* This procedure is called to determine the installation path
* of the Tnm extension on this system. It uses the Windows
* registry to retrieve the the toplevel Tnm directory name.
*
* Results:
* None.
*
* Side effects:
* Initializes the global Tcl variable tnm(library).
*
*----------------------------------------------------------------------
*/
void
TnmInitPath(interp)
Tcl_Interp *interp;
{
char buf[20]; /* scratch space */
char *p, *path, *tclVersion, *tkVersion, *otherExec;
char **pathv;
int pathc;
Tcl_DString ds;
path = GetRegValue("Software\\Scotty\\Tnm\\" TNM_VERSION, "Library");
if (! path) {
path = getenv("TNM_LIBRARY");
if (! path) {
path = TNMLIB;
}
}
FixPath(path);
Tcl_SetVar2(interp, "tnm", "library", path, TCL_GLOBAL_ONLY);
/*
* Also initialize the tkined(library) variable which is used
* by tnmIned.c to locate Tkined specific files. This should
* be removed once Tkined gets integrated into Tnm.
*/
path = GetRegValue("Software\\Scotty\\Tkined\\" TKI_VERSION, "Library");
if (! path) {
path = getenv("TKINED_LIBRARY");
if (! path) {
path = TKINEDLIB;
}
}
FixPath(path);
Tcl_SetVar2(interp, "tkined", "library", path, TCL_GLOBAL_ONLY);
/*
* Locate tclsh and wish so that we can start additional
* scripts with the correct path name.
*/
/* first, get the tcl/tk version information */
Tcl_DStringInit(&ds);
tclVersion = Tcl_GetVar(interp, "tcl_version", TCL_GLOBAL_ONLY);
tkVersion = Tcl_GetVar(interp, "tk_version", TCL_GLOBAL_ONLY);
/* use Tcl_GetNameOfExecutable() to get full path of current executable */
Tcl_SplitPath( Tcl_GetNameOfExecutable(), &pathc, &pathv );
Tcl_JoinPath( pathc, pathv, &ds );
/* this could be tclsh or wish */
if ( strncmp( pathv[pathc-1], "tclsh", 5 ) == 0 ) {
Tcl_SetVar2(interp, "tnm", "tclsh", Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY);
otherExec = "wish";
}
else if ( strncmp( pathv[pathc-1], "wish", 4 ) == 0 ) {
Tcl_SetVar2(interp, "tnm", "wish", Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY);
otherExec = "tclsh";
}
else /* unknown executable - should probably print out some kind of error msg?? */
return;
/* we're done using current DString value */
Tcl_DStringFree(&ds);
/* now, we need to find the corresponding other executable */
/* build up the name wish<ver>.exe */
memset( buf, 0, sizeof(buf) );
strcat( buf, otherExec );
path = buf + strlen(buf);
for (p = tclVersion; *p && path < (buf+sizeof(buf)); p++) {
if (isdigit(*p)) *path++ = *p;
}
*path = '\0'; /* null terminate */
strcat( buf, ".exe" );
/* replace last entry in pathv with the name of wish */
/* this is not a memory leak since pathv memory is
* contiguously allocated and so it'll all be freed when
* we free pathv below */
pathv[pathc-1] = buf;
/* now reconstruct the path and see if we have our wish */
Tcl_JoinPath( pathc, pathv, &ds );
if (access(Tcl_DStringValue(&ds), R_OK | X_OK) == 0) {
Tcl_SetVar2(interp, "tnm", otherExec,
Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY);
}
Tcl_DStringFree(&ds);
Tcl_Free( (char *)pathv );
}
/*
*----------------------------------------------------------------------
*
* TnmInitDns --
*
* This procedure is called to initialize the DNS resolver and to
* save the domain name in the global tnm(domain) Tcl variable.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
TnmInitDns(interp)
Tcl_Interp *interp;
{
char domain[MAXDNAME], *p;
char *nameServer = NULL, *domainName = NULL;
int i;
char *paths[] = {
"System\\CurrentControlSet\\Services\\TcpIP\\Parameters",
"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
"System\\CurrentControlSet\\Services\\VxD\\MSTCP",
NULL
};
res_init();
_res.options |= RES_RECURSE | RES_DNSRCH | RES_DEFNAMES | RES_AAONLY;
/*
* Get the list of name servers from the Windows registry and set
* the list of default DNS servers. Note, this should be done
* automatically by the resolver but it is obviously not on
* Windows machines.
*/
for (i = 0; paths[i] && ! nameServer; i++) {
nameServer = GetRegValue(paths[i], "NameServer");
if (nameServer) {
int n = 0;
char *s = strtok(nameServer, ", ");
while (s && n < MAXNS) {
TnmSetIPAddress((Tcl_Interp *) NULL, s, &_res.nsaddr_list[n]);
s = strtok(NULL, ", ");
n++;
}
_res.nscount = n;
}
}
if (! nameServer) {
TnmSetIPAddress((Tcl_Interp *) NULL,
"127.0.0.1", &_res.nsaddr_list[0]);
_res.nscount = 1;
}
/* Get the domain name form the Windows registry and set the
* default domain name for the resolver, if not done
* automatically. */
for (i = 0; paths[i] && ! domainName; i++) {
domainName = GetRegValue(paths[i], "Domain");
}
if (! _res.defdname[0] && domainName && strlen(domainName) < MAXDNAME) {
strcpy(_res.defdname, domainName);
}
/*
* Remove the any trailing dots or white spaces and save the
* result in tnm(domain).
*/
strcpy(domain, _res.defdname);
p = domain + strlen(domain) - 1;
while ((*p == '.' || isspace(*p)) && p > domain) {
*p-- = '\0';
}
Tcl_SetVar2(interp, "tnm", "domain", domain, TCL_GLOBAL_ONLY);
}
/*
*----------------------------------------------------------------------
*
* Tnm_Init --
*
* This procedure is the Windows entry point for trusted Tcl
* interpreters.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Tcl variables are created.
*
*----------------------------------------------------------------------
*/
EXPORT(int,Tnm_Init)(interp)
Tcl_Interp *interp;
{
return TnmInit(interp, 0);
}
/*
*----------------------------------------------------------------------
*
* Tnm_SafeInit --
*
* This procedure is the Windows entry point for safe Tcl
* interpreters.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Tcl variables are created.
*
*----------------------------------------------------------------------
*/
EXPORT(int,Tnm_SafeInit)(interp)
Tcl_Interp *interp;
{
return TnmInit(interp, 1);
}
-- !! This message is brought to you via the `tkined & scotty' mailing list. !! Please do not reply to this message to unsubscribe. To subscribe or !! unsubscribe, send a mail message to <tkined-request@ibr.cs.tu-bs.de>. !! See http://wwwsnmp.cs.utwente.nl/~schoenw/scotty/ for more information.
This archive was generated by hypermail 2b29 : Thu Jan 03 2002 - 14:56:28 MET