516 lines
13 KiB
C
516 lines
13 KiB
C
/*
|
||
* dpChan.c --
|
||
*
|
||
* Routines for managing install-able channel types.
|
||
*
|
||
* Copyright (c) 1995-1996 Cornell University.
|
||
*
|
||
* See the file "license.terms" for information on usage and redistribution
|
||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||
*
|
||
*/
|
||
|
||
#include <tcl.h>
|
||
#include <stdlib.h>
|
||
#include "generic/dpPort.h"
|
||
#include "generic/dpInt.h"
|
||
|
||
|
||
/*
|
||
* This variable holds the list of channel types.
|
||
*/
|
||
|
||
static Dp_ChannelType * chanTypeList = (Dp_ChannelType *) NULL;
|
||
|
||
/*
|
||
* All the DP built-in channel types.
|
||
*/
|
||
|
||
static Dp_ChannelType builtInTypes[] = {
|
||
{NULL, "ipm", DpOpenIpmChannel},
|
||
{NULL, "tcp", DpOpenTcpChannel},
|
||
#ifndef _WIN32
|
||
{NULL, "email", DpCreateEmailChannel},
|
||
#endif
|
||
{NULL, "identity", DpCreateIdChannel},
|
||
{NULL, "plugfilter", DpCreatePlugFChannel},
|
||
{NULL, "udp", DpOpenUdpChannel},
|
||
{NULL, "serial", DpOpenSerialChannel},
|
||
{NULL, "packoff", DpCreatePOChannel},
|
||
/*
|
||
* This array must end with the following element.
|
||
*/
|
||
{NULL, NULL, NULL}
|
||
};
|
||
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* Dp_RegisterChannelType --
|
||
*
|
||
* Registers a new type of channel that can be used in the DP
|
||
* user-level commands. newTypePtr must points to a Dp_ChannelType
|
||
* structure in *static memory*, the contents of which must not
|
||
* be modified after calling this function.
|
||
*
|
||
* Results:
|
||
* Standard TCL return value. Fails if a channel type with the
|
||
* same name has already been registered.
|
||
*
|
||
* Side effects:
|
||
* On success, newTypePtr is inserted to the head of the list
|
||
* of channel types. Also, the next pointer of newTypePtr is
|
||
* modified.
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
Dp_RegisterChannelType(interp, newTypePtr)
|
||
Tcl_Interp * interp; /* Interpreter to report errors. */
|
||
Dp_ChannelType * newTypePtr;/* The DP channel type record */
|
||
{
|
||
Dp_ChannelType * chanTypePtr;
|
||
|
||
for (chanTypePtr = chanTypeList; chanTypePtr;
|
||
chanTypePtr=chanTypePtr->nextPtr) {
|
||
|
||
if (strcmp(chanTypePtr->name, newTypePtr->name)==0) {
|
||
Tcl_AppendResult(interp, "Channel type \"", newTypePtr->name,
|
||
"\" already exists", NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
|
||
newTypePtr->nextPtr = chanTypeList;
|
||
chanTypeList = newTypePtr;
|
||
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* Dp_GetChannelType --
|
||
*
|
||
* Returns a registered channel type.
|
||
*
|
||
* Results:
|
||
* Standard TCL return value.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
Dp_ChannelType *
|
||
Dp_GetChannelType(interp, name)
|
||
Tcl_Interp * interp; /* Interpreter to report errors. */
|
||
char * name; /* String name of the channel type */
|
||
{
|
||
Dp_ChannelType * chanTypePtr;
|
||
|
||
for (chanTypePtr = chanTypeList; chanTypePtr;
|
||
chanTypePtr=chanTypePtr->nextPtr) {
|
||
|
||
if (strcmp(chanTypePtr->name, name)==0) {
|
||
return chanTypePtr;
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* Dp_ListChannelTypes --
|
||
*
|
||
* Returns a list of valid channel types. The string is
|
||
* dynamically allocated, and must be freed by the caller.
|
||
*
|
||
* Results:
|
||
* Dynamically allocated string with valid channel types.
|
||
*
|
||
* Side effects:
|
||
* Return value must be free'd by caller.
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
char *
|
||
Dp_ListChannelTypes()
|
||
{
|
||
char *str;
|
||
int maxLen, currLen, len;
|
||
Dp_ChannelType *chanTypePtr;
|
||
|
||
maxLen = 1024;
|
||
currLen = 0;
|
||
str = ckalloc (maxLen);
|
||
|
||
for (chanTypePtr = chanTypeList; chanTypePtr != NULL;
|
||
chanTypePtr = chanTypePtr->nextPtr) {
|
||
len = strlen(chanTypePtr->name);
|
||
if ((len + currLen + 2) > maxLen) {
|
||
char *newStr;
|
||
maxLen += max (1024,len+512);
|
||
newStr = ckalloc (maxLen);
|
||
memcpy (newStr, str, currLen);
|
||
ckfree (str);
|
||
str = newStr;
|
||
}
|
||
sprintf (str + currLen, "%s ", chanTypePtr->name);
|
||
currLen += len + 1;
|
||
}
|
||
return str;
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* DpClose --
|
||
*
|
||
* Closes a channel. We just eval "close" in case the
|
||
* close command has been overloaded a la dp_atclose.
|
||
*
|
||
* Results:
|
||
*
|
||
* TCL_OK or TCL_ERROR.
|
||
*
|
||
* Side effects:
|
||
*
|
||
* Closes a channel. It is no longer available in this
|
||
* interpreter.
|
||
*.
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
DpClose(interp, chan)
|
||
Tcl_Interp *interp;
|
||
Tcl_Channel chan;
|
||
{
|
||
char cmd[30];
|
||
|
||
sprintf(cmd, "close %s", Tcl_GetChannelName(chan));
|
||
return Tcl_GlobalEval(interp, cmd);
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* DpInitChannels --
|
||
*
|
||
* Registers all the built-in channels supported by DP.
|
||
*
|
||
* Results:
|
||
* Standard TCL return value.
|
||
*
|
||
* Side effects:
|
||
* Built-in channels are registered in the channel type list.
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
DpInitChannels(interp)
|
||
Tcl_Interp * interp; /* Interpreter to report errors. */
|
||
{
|
||
int i;
|
||
|
||
for (i=0; ; i++) {
|
||
if (builtInTypes[i].name == NULL) {
|
||
break;
|
||
} else {
|
||
if (Dp_RegisterChannelType(interp, &builtInTypes[i]) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
}
|
||
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* DpTranslateOption --
|
||
*
|
||
* This function translates a standard option name (e.g.,
|
||
* "sendBuffer") into a key (e.g., DP_SEND_BUFFER_SIZE)
|
||
*
|
||
* Results:
|
||
* value of option (see dpInt.h for valid keys -- search on
|
||
* DP_SEND_BUFFER_SIZE) if the option was found, -1 if not.
|
||
*
|
||
* Side effects:
|
||
* None
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
int
|
||
DpTranslateOption (name)
|
||
char *name; /* The name to translate */
|
||
{
|
||
char c;
|
||
int len;
|
||
|
||
c = name[0];
|
||
len = strlen(name);
|
||
|
||
if ((c == 'b') && (strncmp(name, "baudrate", len) == 0)) {
|
||
return DP_BAUDRATE;
|
||
} else if ((c == 'c') && (strncmp(name, "charsize", len) == 0)) {
|
||
return DP_CHARSIZE;
|
||
} else if ((c == 'g') && (strncmp(name, "group", len) == 0)) {
|
||
return DP_GROUP;
|
||
} else if ((c == 'h') && (strncmp(name, "host", len) == 0)) {
|
||
return DP_HOST;
|
||
} else if ((c == 'k') && (strncmp(name, "keepAlive", len) == 0)) {
|
||
return DP_KEEP_ALIVE;
|
||
} else if ((c == 'l') && (strncmp(name, "linger", len) == 0)) {
|
||
return DP_LINGER;
|
||
} else if ((c == 'l') && (strncmp(name, "loopback", len) == 0)) {
|
||
return DP_MULTICAST_LOOP;
|
||
} else if ((c == 'm') && (strncmp(name, "myport", len) == 0)) {
|
||
return DP_MYPORT;
|
||
} else if ((c == 'p') && (strncmp(name, "parity", len) == 0)) {
|
||
return DP_PARITY;
|
||
} else if ((c == 'p') && (strncmp(name, "peek", len) == 0)) {
|
||
return DP_PEEK;
|
||
} else if ((c == 'p') && (strncmp(name, "port", len) == 0)) {
|
||
return DP_PORT;
|
||
} else if ((c == 'r') && (strncmp(name, "recvBuffer", len) == 0)) {
|
||
return DP_RECV_BUFFER_SIZE;
|
||
} else if ((c == 'r') && (strncmp(name, "reuseAddr", len) == 0)) {
|
||
return DP_REUSEADDR;
|
||
} else if ((c == 's') && (strncmp(name, "sendBuffer", len) == 0)) {
|
||
return DP_SEND_BUFFER_SIZE;
|
||
} else if ((c == 's') && (strncmp(name, "stopbits", len) == 0)) {
|
||
return DP_STOPBITS;
|
||
} else if ((c == 'm') && (strncmp(name, "myIpAddr", len) == 0)) {
|
||
return DP_MYIPADDR;
|
||
} else if ((c == 'd') && (strncmp(name, "destIpAddr", len) == 0)) {
|
||
return DP_REMOTEIPADDR;
|
||
} else if ((c == 'd') && (strncmp(name, "destport", len) == 0)) {
|
||
return DP_REMOTEPORT;
|
||
} else if ((c == 'a') && (strncmp(name, "address", len) == 0)) {
|
||
return DP_ADDRESS;
|
||
} else if ((c == 'i') && (strncmp(name, "identifier", len) == 0)) {
|
||
return DP_IDENTIFIER;
|
||
} else if ((c == 's') && (strncmp(name, "sequence", len) == 0)) {
|
||
return DP_SEQUENCE;
|
||
} else if ((c == 'c') && (strncmp(name, "channel", len) == 0)) {
|
||
return DP_CHANNEL;
|
||
} else if ((c == 'i') && (strncmp(name, "infilter", len) == 0)) {
|
||
return DP_INFILTER;
|
||
} else if ((c == 'o') && (strncmp(name, "outfilter", len) == 0)) {
|
||
return DP_OUTFILTER;
|
||
} else if ((c == 'i') && (strncmp(name, "inset", len) == 0)) {
|
||
return DP_INSET;
|
||
} else if ((c == 'o') && (strncmp(name, "outset", len) == 0))
|
||
return DP_OUTSET;
|
||
|
||
return -1;
|
||
}
|
||
|
||
|
||
|
||
|
||
/*
|
||
* This variable holds the list of registered plug-in filters.
|
||
*/
|
||
|
||
static Dp_PlugInFilter *plugInList = (Dp_PlugInFilter *) NULL;
|
||
|
||
|
||
/*
|
||
* All the built-in plug-in functions.
|
||
*/
|
||
|
||
static Dp_PlugInFilter builtInPlugs[] = {
|
||
|
||
{NULL, "identity", Identity},
|
||
{NULL, "plug1to2", Plug1to2},
|
||
{NULL, "plug2to1", Plug2to1},
|
||
{NULL, "xor", Xor},
|
||
{NULL, "packon", PackOn},
|
||
{NULL, "uuencode", Uuencode},
|
||
{NULL, "uudecode", Uudecode},
|
||
{NULL, "tclfilter", TclFilter},
|
||
{NULL, "hexout", HexOut},
|
||
{NULL, "hexin", HexIn},
|
||
|
||
/*
|
||
* This array must end with the following element.
|
||
*/
|
||
|
||
{NULL, NULL, NULL}
|
||
};
|
||
|
||
|
||
|
||
/*
|
||
*-----------------------------------------------------------------------------
|
||
*
|
||
* Dp_RegisterPlugInFilter --
|
||
*
|
||
* Registers a new type of filter that can be used in the DP
|
||
* user-level commands. newPlugInPtr must point to a Dp_PlugInFilter
|
||
* structure in *static memory*, the contents of which must not
|
||
* be modified after calling this function.
|
||
*
|
||
* Results:
|
||
*
|
||
* Standard TCL return value. Fails if a filter with the
|
||
* same name has already been registered.
|
||
*
|
||
* Side effects:
|
||
* On success, newPlugInPtr is inserted to the head of the list
|
||
* of filter. Also, the next pointer of newPlugInPtr is
|
||
* modified.
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
Dp_RegisterPlugInFilter (interp, newPlugInPtr)
|
||
Tcl_Interp * interp; /* (in) Interpreter to report errors to. */
|
||
Dp_PlugInFilter * newPlugInPtr; /* (in) Pointer to the filter function. */
|
||
{
|
||
Dp_PlugInFilter *plugInPtr;
|
||
|
||
for (plugInPtr = plugInList; plugInPtr;
|
||
plugInPtr = plugInPtr->nextPtr) {
|
||
|
||
if (strcmp(plugInPtr->name, newPlugInPtr->name)==0) {
|
||
Tcl_AppendResult(interp, "Plug-in filter \"", newPlugInPtr->name,
|
||
"\" already exists", NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
|
||
newPlugInPtr->nextPtr = plugInList;
|
||
plugInList = newPlugInPtr;
|
||
|
||
return TCL_OK;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
*-----------------------------------------------------------------------------
|
||
*
|
||
* Dp_GetFilterPtr --
|
||
*
|
||
* Returns a pointer to the filter function whose name was given.
|
||
*
|
||
* Results:
|
||
*
|
||
* Pointer to the filter function or NULL if the name is not the name of
|
||
* a registered filter function.
|
||
*
|
||
* Side effects:
|
||
*
|
||
* None.
|
||
*
|
||
*-----------------------------------------------------------------------------
|
||
*/
|
||
|
||
Dp_PlugInFilterProc *
|
||
Dp_GetFilterPtr (interp, name)
|
||
Tcl_Interp *interp; /* (in) Interpreter to report errors to. */
|
||
char *name; /* (in) Name of the filter function. */
|
||
{
|
||
Dp_PlugInFilter *plugInPtr;
|
||
|
||
for (plugInPtr = plugInList; plugInPtr;
|
||
plugInPtr = plugInPtr->nextPtr) {
|
||
if (strcmp(plugInPtr->name, name) == 0) {
|
||
return plugInPtr->plugProc;
|
||
}
|
||
}
|
||
|
||
Tcl_AppendResult(interp, "unknown plug-in function \"", name, "\"", NULL);
|
||
return NULL;
|
||
}
|
||
|
||
|
||
/*
|
||
*-----------------------------------------------------------------------------
|
||
*
|
||
* Dp_GetFilterName --
|
||
*
|
||
* Returns the name of the given filter function.
|
||
*
|
||
* Results:
|
||
*
|
||
* A pointer to the name of the filter function or NULL if the function
|
||
* pointer does not appear in the list of registered filter functions.
|
||
*
|
||
* Side effects:
|
||
*
|
||
* None.
|
||
*
|
||
*-----------------------------------------------------------------------------
|
||
*/
|
||
|
||
char *
|
||
Dp_GetFilterName (filter)
|
||
Dp_PlugInFilterProc *filter; /* (in) Pointer to the filter function. */
|
||
{
|
||
Dp_PlugInFilter *plugInPtr;
|
||
|
||
for (plugInPtr = plugInList; plugInPtr;
|
||
plugInPtr = plugInPtr->nextPtr) {
|
||
if (filter, plugInPtr->plugProc) {
|
||
return plugInPtr->name;
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
*-----------------------------------------------------------------------------
|
||
*
|
||
* Dp_DpInitPlugIn --
|
||
*
|
||
* Registers all the built-in channels supported by DP.
|
||
*
|
||
* Results:
|
||
*
|
||
* Standard TCL return value.
|
||
*
|
||
* Side effects:
|
||
*
|
||
* Built-in filter functions are registered in the plug-in filter list.
|
||
*
|
||
*-----------------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
DpInitPlugIn(interp)
|
||
Tcl_Interp * interp; /* (in) Interpreter to report errors to. */
|
||
{
|
||
int i;
|
||
|
||
for (i=0; ; i++) {
|
||
if (builtInPlugs[i].name == NULL) {
|
||
break;
|
||
} else {
|
||
if (Dp_RegisterPlugInFilter(interp, &builtInPlugs[i]) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
}
|
||
|
||
return TCL_OK;
|
||
}
|
||
|
||
|
||
|