/*1* tclFHandle.c --2*3* This file contains functions for manipulating Tcl file handles.4*5* Copyright (c) 1995 Sun Microsystems, Inc.6*7* See the file "license.terms" for information on usage and redistribution8* of this file, and for a DISCLAIMER OF ALL WARRANTIES.9*10* SCCS: @(#) tclFHandle.c 1.8 96/06/27 15:31:3411*/1213#include "tcl.h"14#include "tclInt.h"15#include "tclPort.h"1617/*18* The FileHashKey structure is used to associate the OS file handle and type19* with the corresponding notifier data in a FileHandle.20*/2122typedef struct FileHashKey {23int type; /* File handle type. */24ClientData osHandle; /* Platform specific OS file handle. */25} FileHashKey;2627typedef struct FileHandle {28FileHashKey key; /* Hash key for a given file. */29ClientData data; /* Platform specific notifier data. */30Tcl_FileFreeProc *proc; /* Callback to invoke when file is freed. */31} FileHandle;3233/*34* Static variables used in this file:35*/3637static Tcl_HashTable fileTable; /* Hash table containing file handles. */38static int initialized = 0; /* 1 if this module has been initialized. */3940/*41* Static procedures used in this file:42*/4344static void FileExitProc _ANSI_ARGS_((ClientData clientData));4546/*47*----------------------------------------------------------------------48*49* Tcl_GetFile --50*51* This function retrieves the file handle associated with a52* platform specific file handle of the given type. It creates53* a new file handle if needed.54*55* Results:56* Returns the file handle associated with the file descriptor.57*58* Side effects:59* Initializes the file handle table if necessary.60*61*----------------------------------------------------------------------62*/6364Tcl_File65Tcl_GetFile(osHandle, type)66ClientData osHandle; /* Platform specific file handle. */67int type; /* Type of file handle. */68{69FileHashKey key;70Tcl_HashEntry *entryPtr;71int new;7273if (!initialized) {74Tcl_InitHashTable(&fileTable, sizeof(FileHashKey)/sizeof(int));75Tcl_CreateExitHandler(FileExitProc, 0);76initialized = 1;77}78key.osHandle = osHandle;79key.type = type;80entryPtr = Tcl_CreateHashEntry(&fileTable, (char *) &key, &new);81if (new) {82FileHandle *newHandlePtr;83newHandlePtr = (FileHandle *) ckalloc(sizeof(FileHandle));84newHandlePtr->key = key;85newHandlePtr->data = NULL;86newHandlePtr->proc = NULL;87Tcl_SetHashValue(entryPtr, newHandlePtr);88}8990return (Tcl_File) Tcl_GetHashValue(entryPtr);91}9293/*94*----------------------------------------------------------------------95*96* Tcl_FreeFile --97*98* Deallocates an entry in the file handle table.99*100* Results:101* None.102*103* Side effects:104* None.105*106*----------------------------------------------------------------------107*/108109void110Tcl_FreeFile(handle)111Tcl_File handle;112{113Tcl_HashEntry *entryPtr;114FileHandle *handlePtr = (FileHandle *) handle;115116/*117* Invoke free procedure, then delete the handle.118*/119120if (handlePtr->proc) {121(*handlePtr->proc)(handlePtr->data);122}123124/*125* Tcl_File structures may be freed as a result of running the126* channel table exit handler. The file table is freed by the file127* table exit handler, which may run before the channel table exit128* handler. The file table exit handler sets the "initialized"129* variable back to zero, so that the Tcl_FreeFile (when invoked130* from the channel table exit handler) can notice that the file131* table has already been destroyed. Otherwise, accessing a132* deleted hash table would cause a panic.133*/134135if (initialized) {136entryPtr = Tcl_FindHashEntry(&fileTable, (char *) &handlePtr->key);137if (entryPtr) {138Tcl_DeleteHashEntry(entryPtr);139}140}141ckfree((char *) handlePtr);142}143144/*145*----------------------------------------------------------------------146*147* Tcl_GetFileInfo --148*149* This function retrieves the platform specific file data and150* type from the file handle.151*152* Results:153* If typePtr is not NULL, sets *typePtr to the type of the file.154* Returns the platform specific file data.155*156* Side effects:157* None.158*159*----------------------------------------------------------------------160*/161162ClientData163Tcl_GetFileInfo(handle, typePtr)164Tcl_File handle;165int *typePtr;166{167FileHandle *handlePtr = (FileHandle *) handle;168169if (!handlePtr)170return 0;171if (typePtr) {172*typePtr = handlePtr->key.type;173}174return handlePtr->key.osHandle;175}176177/*178*----------------------------------------------------------------------179*180* Tcl_SetNotifierData --181*182* This function is used by the notifier to associate platform183* specific notifier information and a deletion procedure with184* a file handle.185*186* Results:187* None.188*189* Side effects:190* Updates the data and delProc slots in the file handle.191*192*----------------------------------------------------------------------193*/194195void196Tcl_SetNotifierData(handle, proc, data)197Tcl_File handle;198Tcl_FileFreeProc *proc;199ClientData data;200{201FileHandle *handlePtr = (FileHandle *) handle;202handlePtr->proc = proc;203handlePtr->data = data;204}205206/*207*----------------------------------------------------------------------208*209* Tcl_GetNotifierData --210*211* This function is used by the notifier to retrieve the platform212* specific notifier information associated with a file handle.213*214* Results:215* Returns the data stored in a file handle by a previous call to216* Tcl_SetNotifierData, and places a pointer to the free proc217* in the location referred to by procPtr.218*219* Side effects:220* None.221*222*----------------------------------------------------------------------223*/224225ClientData226Tcl_GetNotifierData(handle, procPtr)227Tcl_File handle;228Tcl_FileFreeProc **procPtr;229{230FileHandle *handlePtr = (FileHandle *) handle;231if (procPtr != NULL) {232*procPtr = handlePtr->proc;233}234return handlePtr->data;235}236237/*238*----------------------------------------------------------------------239*240* FileExitProc --241*242* This function an exit handler that frees any memory allocated243* for the file handle table.244*245* Results:246* None.247*248* Side effects:249* Cleans up the file handle table.250*251*----------------------------------------------------------------------252*/253254static void255FileExitProc(clientData)256ClientData clientData; /* Not used. */257{258Tcl_DeleteHashTable(&fileTable);259initialized = 0;260}261262263