blob: d11c988c7de57b6792f4b40d964b4616d99c8192 [file] [log] [blame]
/*
* apchannel.c - simple channel implementation for mod_websh for apache
* nca-073-9
*
* Copyright (c) 1996-2000 by Netcetera AG.
* Copyright (c) 2001 by Apache Software Foundation.
* All rights reserved.
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* @(#) $Id$
*
*/
#include <stdio.h>
#ifdef HAVE_SYS_ERRNO_H
#include <sys/errno.h>
#else
#include <errno.h>
#endif
#include "tcl.h"
#include "httpd.h"
#include "http_config.h"
#include "http_request.h"
#include "http_core.h"
#include "http_protocol.h"
#include "http_main.h"
#include "http_log.h"
#include "util_script.h"
#include "mod_websh.h"
#ifndef APACHE2
#include "http_conf_globals.h"
#endif /* APACHE2 */
#include "request.h"
/* ----------------------------------------------------------------------------
* close apache channel
* ------------------------------------------------------------------------- */
int apchannelCloseProc(ClientData clientData, Tcl_Interp * interp)
{
/* nothing to do */
return 0;
}
/* ----------------------------------------------------------------------------
* input from apache channel
* ------------------------------------------------------------------------- */
int apchannelInputProc(ClientData clientData,
char *buf, int bufSize, int *errorCodePtr)
{
int res = -1;
request_rec *r = NULL;
if ((clientData == NULL) || (buf == NULL))
return res;
r = (request_rec *) clientData;
if (bufSize > 0)
res = ap_get_client_block(r, buf, bufSize);
if (res <= 0)
return -1;
return res;
}
/* ----------------------------------------------------------------------------
* output to apache channel
* ------------------------------------------------------------------------- */
int apchannelOutputProc(ClientData clientData,
TCLCONST char *buf, int toWrite, int *errorCodePtr)
{
int res = -1;
if ((clientData == NULL) || (buf == NULL))
return res;
if (toWrite > 0) {
res = ap_rwrite((void *) buf, toWrite, (request_rec *) clientData);
}
if (res < 0)
return -1;
return res;
}
/* ----------------------------------------------------------------------------
* watch apache channel
* ------------------------------------------------------------------------- */
void apchannelWatchProc(ClientData clientData, int mask)
{
}
/* ----------------------------------------------------------------------------
* getHandle for apache channel
* ------------------------------------------------------------------------- */
int apchannelGetHandleProc(ClientData clientData, int direction,
ClientData * handlePtr)
{
/* "not implemented" */
return EINVAL;
}
/* ----------------------------------------------------------------------------
* apChannelType
* ------------------------------------------------------------------------- */
static Tcl_ChannelType apChannelType = {
"file", /* Type name. */
NULL, /* Set blocking/nonblocking mode. */
apchannelCloseProc, /* Close proc. */
apchannelInputProc, /* Input proc. */
apchannelOutputProc, /* Output proc. */
NULL, /* Seek proc. */
NULL, /* Set option proc. */
NULL, /* Get option proc. */
apchannelWatchProc, /* Initialize notifier. */
apchannelGetHandleProc, /* Get OS handles out of channel. */
};
/* ----------------------------------------------------------------------------
* createApchannel
* ------------------------------------------------------------------------- */
int createApchannel(Tcl_Interp * interp, request_rec * r)
{
Tcl_Channel channel = NULL;
int flag = 0;
if ((interp == NULL) || (r == NULL))
return TCL_ERROR;
flag = TCL_WRITABLE;
if (ap_should_client_block(r)) {
flag = TCL_WRITABLE | TCL_READABLE;
}
channel = Tcl_CreateChannel(&apChannelType, APCHANNEL,
(ClientData) r, flag);
if (channel == NULL)
return TCL_ERROR;
Tcl_RegisterChannel(interp, channel);
return TCL_OK;
}
/* ----------------------------------------------------------------------------
* destroyApchannel
* ------------------------------------------------------------------------- */
int destroyApchannel(Tcl_Interp * interp)
{
Tcl_Channel channel = NULL;
int mode = 0;
if (interp == NULL)
return TCL_ERROR;
channel = Tcl_GetChannel(interp, APCHANNEL, &mode);
mode = 0;
if (channel == NULL) {
mode++;
}
else {
if (Tcl_UnregisterChannel(interp, channel) != TCL_OK)
mode++;
}
if (mode)
return TCL_ERROR;
else
return TCL_OK;
}