Files
cdesktop/cde/lib/DtSvc/DtEncap/local.c
2018-05-24 14:25:26 -06:00

251 lines
7.0 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* File: local.c $TOG: local.c /main/5 1999/10/14 15:05:57 mgreess $
* Language: C
*
* (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
*
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
* (c) Copyright 1993, 1994 International Business Machines Corp. *
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
* (c) Copyright 1993, 1994 Novell, Inc. *
*/
#define __need_timeval /* Needed for "struct timeval" from <time.h>. */
#define __need_fd_set
#include <bms/sbport.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <SPC/spcP.h>
#include <SPC/spc-proto.h>
/*
**
** Note that the close routines call the parent method AFTER the
** work done for the child method. This is because the parent method
** will do all the deallocation.
**
*/
/*----------------------------------------------------------------------+*/
int close_local_channel_object(SPC_Channel_Ptr channel)
/*----------------------------------------------------------------------+*/
{
Wire *wirelist;
int result;
for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next){
spc_close(wirelist->fd[READ_SIDE]);
spc_close(wirelist->fd[WRITE_SIDE]);
SPC_XtRemoveInput(&wirelist->read_toolkit_id, SPC_Input);
SPC_XtRemoveInput(&wirelist->except_toolkit_id, SPC_Exception);
}
call_parent_method(channel, close, (channel), result);
if(result==SPC_ERROR)
return(SPC_ERROR);
return(TRUE);
}
/*----------------------------------------------------------------------+*/
int write_local_channel_object(SPC_Channel_Ptr channel,
XeString buffer,
int nbytes)
/*----------------------------------------------------------------------+*/
{
int result;
call_parent_method(channel,
write,
(channel, buffer, nbytes),
result);
if(result==SPC_ERROR)
return(SPC_ERROR);
result = SPC_Write_Chars(channel->file_descs[STDIN], buffer, nbytes);
if(result==ERROR) {
SPC_Error(SPC_Writing);
return(SPC_ERROR);
}
return(result);
}
/* the function exec_proc_local_channel_object is defined in spc-exec.c */
/*----------------------------------------------------------------------+*/
int signal_local_channel_object (SPC_Channel_Ptr channel,
int sig)
/*----------------------------------------------------------------------+*/
{
int result;
call_parent_method(channel, signal, (channel, sig), result);
if(result==SPC_ERROR)
return(SPC_ERROR);
if(sig == SIGKILL || IS_SPCIO_SIGNAL_PGRP(channel->IOMode))
result=kill(-(channel->pid), sig);
else
result=kill(channel->pid, sig);
if(result==ERROR)
return(errno!=ESRCH);
return(TRUE);
}
/*----------------------------------------------------------------------+*/
int local_channel_object_wait_for_termination(SPC_Channel_Ptr channel)
/*----------------------------------------------------------------------+*/
{
int result;
call_parent_method(channel, wait_for_termination, (channel), result);
if(result==SPC_ERROR)
return(SPC_ERROR);
/* Do we need to check for remote channel input here? */
while(IS_ACTIVE(channel)) {
sigset_t mask;
sigemptyset(&mask);
/* the SIGCLD signal handler will take care of us here */
sigsuspend(&mask);
}
return(TRUE);
}
/*----------------------------------------------------------------------+*/
int remove_logfile_local_channel_object(SPC_Channel_Ptr channel)
/*----------------------------------------------------------------------+*/
{
int result;
call_parent_method(channel, remove_logfile, (channel), result);
if(unlink(channel->logfile)==ERROR) {
SPC_Error(SPC_Unlink_Logfile);
return(SPC_ERROR);
}
/* This is malloc'ed memory from open_noio_channel_object() and tempnam() */
XeFree(channel->logfile);
return(TRUE);
}
extern SPC_Channel_Ptr spc_activation_list;
/* All this routine does is to look up the channel, and
call the generic input handler routine */
/*----------------------------------------------------------------------+*/
void local_channel_object_input_handler(void * client_data,
int *source,
SPCInputId * UNUSED_PARM(id))
/*----------------------------------------------------------------------+*/
{
/* WARNING!!! This routine is NOT XPG3 compliant. The timeval struct */
/* is the problem here. */
SPC_Channel_Ptr channel=(SPC_Channel_Ptr) client_data;
int fd=(*source);
int connector;
int len;
fd_set read_fd_vect, except_fd_vect;
SPC_Channel_Ptr tmp, this_ptr;
struct timeval timeout; /* Not part of XPG3 !!! */
/* This ^&@$#% select is here to get around an X toolkit bug */
FD_ZERO(&read_fd_vect);
FD_ZERO(&except_fd_vect);
FD_SET(fd, &read_fd_vect);
FD_SET(fd, &except_fd_vect);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
#if defined(SVR4) || defined(__hpux) || defined(__OpenBSD__) || defined(linux)
select(max_fds, (fd_set*)&read_fd_vect, NULL, (fd_set*)&except_fd_vect, &timeout);
#else
/* UX has select defined with int*, not fd_set* parms */
select(max_fds, (int*)&read_fd_vect, NULL, (int*)&except_fd_vect, &timeout);
#endif
if(! (FD_ISSET(fd, &read_fd_vect) || FD_ISSET(fd, &except_fd_vect))) {
return /* (FALSE) */;
}
/* The following is to get around an apparent Xt bug where sometimes
the client data pointer passed to me is not the one I was expecting.
*/
tmp = spc_activation_list;
this_ptr = NULL;
while(tmp) {
if((fd == Stdin(tmp)) || (fd == Stderr(tmp)))
this_ptr = tmp;
tmp = tmp->next;
}
if(this_ptr == NULL)
this_ptr = channel;
if(this_ptr != channel)
channel = this_ptr;
if((connector=SPC_fd_to_connector(channel, fd)) == ERROR) {
SPC_Error(SPC_Bad_Fd);
return /* (SPC_ERROR) */;
}
len = SPC_Input_Handler(channel, connector);
return /* (len) */;
}
int local_channel_object_send_eof(SPC_Channel_Ptr channel)
{
Wire *wire = channel->wires[STDIN];
spc_close(wire->fd[READ_SIDE]);
spc_close(wire->fd[WRITE_SIDE]);
SPC_XtRemoveInput(&wire->read_toolkit_id, SPC_Input);
SPC_XtRemoveInput(&wire->except_toolkit_id, SPC_Exception);
return(TRUE);
}