/* * tclXchannelfd.c -- * * OS system dependent interface for unix systems. The idea behind these * functions is to provide interfaces to various functions that vary on the * various platforms. These functions either implement the call in a manner * approriate to the platform or return an error indicating the functionality * is not available on that platform. This results in code with minimal * number of #ifdefs. *----------------------------------------------------------------------------- * Copyright 2017 Shannon Noe * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies. Karl Lehenbauer and * Mark Diekhans make no representations about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. *----------------------------------------------------------------------------- */ #include "tclExtdInt.h" /*----------------------------------------------------------------------------- * ChannelToFd -- * * Convert a channel to a file descriptor. * * Parameters: * o channel - Channel to get file number for. * o direction - TCL_READABLE or TCL_WRITABLE, or zero. If zero, then * return the first of the read and write numbers. * o type - The type of the file. not set if an error occurs. * * Returns: * The unix file descriptor of the channel. *----------------------------------------------------------------------------- */ static int ChannelToFd (Tcl_Channel channel, int direction) { ClientData handle; int fd = -1; if (direction == 0) { if (Tcl_GetChannelHandle (channel, TCL_READABLE, &handle) != TCL_OK && Tcl_GetChannelHandle (channel, TCL_WRITABLE, &handle) != TCL_OK) { return -1; } } else { if (Tcl_GetChannelHandle (channel, direction, &handle) != TCL_OK) { return -1; } } memcpy(&fd, &handle, sizeof(fd)); return fd; } static int TclX_ChannelFdObjCmd (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj*CONST objv[]) { const char *channelName; Tcl_Channel channel; int fd; if (objc < 2) return TclX_WrongArgs (interp, objv [0], "arg ?arg...?"); channelName = Tcl_GetStringFromObj (objv [1], NULL); if (channelName) { channel = Tcl_GetChannel (interp, channelName, NULL); if (channel) { fd = ChannelToFd(channel, 0); if (fd != -1) { Tcl_SetObjResult (interp, Tcl_NewIntObj(fd)); return TCL_OK; } } } Tcl_SetResult(interp, "failed to get file descriptor from channel", TCL_STATIC); return TCL_ERROR; } /*----------------------------------------------------------------------------- * TclX_ChannelFdInit -- * Initialize the channelfd command. *----------------------------------------------------------------------------- */ void TclX_ChannelFdInit (Tcl_Interp *interp) { Tcl_CreateObjCommand (interp, "channelfd", TclX_ChannelFdObjCmd, (ClientData) NULL, (Tcl_CmdDeleteProc*) NULL); } /* vim: set ts=4 sw=4 sts=4 et : */