281 lines
6.0 KiB
C
281 lines
6.0 KiB
C
/*
|
||
* unix/dpSock.c --
|
||
*
|
||
* This file implements generic Unix-specific routines for the
|
||
* socket code.
|
||
*
|
||
* 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 "generic/dpInt.h"
|
||
#include "generic/dpPort.h"
|
||
|
||
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* DppCloseSocket --
|
||
*
|
||
* Close the socket passed in.
|
||
*
|
||
* Results:
|
||
* None
|
||
*
|
||
* Side effects:
|
||
* None
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
int
|
||
DppCloseSocket (sock)
|
||
DpSocket sock;
|
||
{
|
||
return close(sock);
|
||
}
|
||
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* DppSetBlock --
|
||
*
|
||
* Put the socket into a blocking or non-blocking state.
|
||
*
|
||
* Results:
|
||
* None
|
||
*
|
||
* Side effects:
|
||
* None
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
int
|
||
DppSetBlock (sock, block)
|
||
DpSocket sock;
|
||
int block;
|
||
{
|
||
int flags;
|
||
flags = fcntl(sock, F_GETFL, 0);
|
||
if (block) {
|
||
/* Set blocking mode */
|
||
fcntl(sock, F_SETFL, flags & ~NBIO_FLAG);
|
||
} else {
|
||
/* Set non-blocking mode */
|
||
fcntl(sock, F_SETFL, flags | NBIO_FLAG);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* -------------------------------------------------------------
|
||
*
|
||
* DppGetErrno --
|
||
*
|
||
* Returns the POSIX error code.
|
||
*
|
||
* Results:
|
||
* The POSIX errorcode.
|
||
*
|
||
* Side Effects:
|
||
* None.
|
||
*
|
||
* -------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
DppGetErrno()
|
||
{
|
||
return Tcl_GetErrno();
|
||
}
|
||
|
||
#ifndef _TCL76
|
||
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* SockBlockMode --
|
||
*
|
||
* Sets the tcp socket to blocking or non-blocking. Just
|
||
* a wrapper around the platform specific function.
|
||
*
|
||
* Results:
|
||
* Zero if the operation was successful, or a nonzero POSIX
|
||
* error code if the operation failed.
|
||
*
|
||
* Side effects:
|
||
* None
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
SockBlockMode (instanceData, mode)
|
||
ClientData instanceData; /* Pointer to tcpState struct */
|
||
int mode; /* TCL_MODE_BLOCKING or TCL_MODE_NONBLOCKING */
|
||
{
|
||
SocketState *statePtr = (SocketState *)instanceData;
|
||
|
||
if (mode == TCL_MODE_BLOCKING) {
|
||
return DppSetBlock(statePtr->sock, 1);
|
||
} else {
|
||
return DppSetBlock(statePtr->sock, 0);
|
||
}
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* SockClose --
|
||
*
|
||
* This function is called by the Tcl channel driver when the
|
||
* caller want to close the socket. It releases the instanceData
|
||
* and closes the scoket. All queued output will have been flushed
|
||
* to the device before this function is called.
|
||
*
|
||
* Results:
|
||
* Zero for success, otherwise a nonzero POSIX error code and,
|
||
* if interp is not NULL, an error message in interp->result
|
||
*
|
||
* Side effects:
|
||
* None
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
SockClose (instanceData, interp)
|
||
ClientData instanceData; /* (in) Pointer to tcpState struct */
|
||
Tcl_Interp *interp; /* (in) For error reporting */
|
||
{
|
||
SocketState *statePtr = (SocketState *)instanceData;
|
||
int result;
|
||
|
||
SDBG(("Closing socket %d\n", statePtr->sock));
|
||
|
||
result = DppCloseSocket(statePtr->sock);
|
||
if ((result != 0) && (interp != NULL)) {
|
||
DppGetErrno();
|
||
Tcl_SetResult(interp, Tcl_PosixError(interp), TCL_STATIC);
|
||
}
|
||
|
||
/*
|
||
* IPM only
|
||
*/
|
||
if (statePtr->flags & SOCKET_IPM) {
|
||
Tcl_DStringFree(&statePtr->groupList);
|
||
}
|
||
|
||
ckfree((char *)statePtr);
|
||
return result;
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* SockWatch --
|
||
*
|
||
* Creates an event callback for this socket or deletes
|
||
* the current callback.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* The callback can do anything.
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
SockWatch (instanceData, mask)
|
||
ClientData instanceData;
|
||
int mask;
|
||
{
|
||
SocketState *infoPtr = (SocketState *) instanceData;
|
||
|
||
if (mask) {
|
||
Tcl_CreateFileHandler(infoPtr->sock, mask,
|
||
(Tcl_FileProc *) Tcl_NotifyChannel,
|
||
(ClientData) infoPtr->channel);
|
||
SDBG(("Creating callback for socket %d\n", infoPtr->sock));
|
||
} else {
|
||
Tcl_DeleteFileHandler(infoPtr->sock);
|
||
SDBG(("Deleting callback for socket %d\n", infoPtr->sock));
|
||
}
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* SockGetFile --
|
||
*
|
||
* Called from Tcl_GetChannelFile to retrieve the handle
|
||
* from inside a socket based channel.
|
||
*
|
||
* Results:
|
||
* TCL_OK
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
SockGetFile(instanceData, direction, handlePtr)
|
||
ClientData instanceData;
|
||
int direction;
|
||
FileHandle *handlePtr;
|
||
{
|
||
SocketState *statePtr = (SocketState *)instanceData;
|
||
|
||
*handlePtr = statePtr->sockFile;
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*--------------------------------------------------------------
|
||
*
|
||
* UdpIpmOutput --
|
||
*
|
||
* This function is called by the Tcl channel driver whenever
|
||
* the user wants to send output to the UDP socket.
|
||
* The function writes toWrite bytes from buf to the socket.
|
||
*
|
||
* Results:
|
||
* A nonnegative integer indicating how many bytes were written
|
||
* to the socket. The return value is normally the same as toWrite,
|
||
* but may be less in some cases such as if the output operation
|
||
* is interrupted by a signal.
|
||
*
|
||
* Side effects:
|
||
* None
|
||
*
|
||
*--------------------------------------------------------------
|
||
*/
|
||
int
|
||
UdpIpmOutput (instanceData, buf, toWrite, errorCodePtr)
|
||
ClientData instanceData; /* (in) Pointer to udpState struct */
|
||
char *buf; /* (in) Buffer to write */
|
||
int toWrite; /* (in) Number of bytes to write */
|
||
int *errorCodePtr; /* (out) POSIX error code (if any) */
|
||
{
|
||
SocketState *statePtr = (SocketState *) instanceData;
|
||
int result;
|
||
|
||
result = sendto(statePtr->sock, buf, toWrite, 0,
|
||
(struct sockaddr *) &statePtr->sockaddr,
|
||
sizeof(statePtr->sockaddr));
|
||
if (result == DP_SOCKET_ERROR) {
|
||
*errorCodePtr = DppGetErrno();
|
||
}
|
||
return result;
|
||
}
|
||
#endif
|