Files
cdesktop/cde/lib/DtSvc/DtEncap/spc-sm.c
2018-04-28 12:30:20 -06:00

231 lines
6.5 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: spc-sm.c $XConsortium: spc-sm.c /main/4 1996/04/21 19:10:39 drk $
* 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. *
*/
#include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
#include <signal.h>
#include <SPC/spcP.h>
/*
**
** Definitions for blocking signals
**
*/
static int (* spc_state_table[16]) (SPC_Channel_Ptr channel, int connector)= {
/* old_state new_state */
NULL, /* 00 00 */
NULL, /* 00 01 */
error_fun, /* 00 10 */
NULL, /* 00 11 */
sigcld_with_reset, /* 01 00 */
NULL, /* 01 01 */
error_fun, /* 01 10 */
error_fun, /* 01 11 */
connector_eof_with_reset, /* 10 00 */
error_fun, /* 10 01 */
NULL, /* 10 10 */
error_fun, /* 10 11 */
NULL, /* 11 00 */
connector_eof, /* 11 01 */
NULL, /* 11 10 */
NULL /* 11 11 */
};
/*----------------------------------------------------------------------+*/
int
SPC_Change_State(SPC_Channel_Ptr channel,
int connector,
int data_line,
int process_line)
/*----------------------------------------------------------------------+*/
{
int iomode=channel->IOMode;
int old_state=CHANNEL_STATE(iomode);
int new_state, state_index;
int (*fun)(SPC_Channel_Ptr, int);
int funretval;
sigset_t newsigmask, oldsigmask;
sigemptyset(&newsigmask);
sigemptyset(&oldsigmask);
/* Process don't cares */
sigaddset(&newsigmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &newsigmask, &oldsigmask);
if(data_line == -1)
data_line=DATA_LINE(old_state);
if(process_line == -1)
process_line = PROC_LINE(old_state);
/* create new state */
new_state=MAKE_STATE(data_line, process_line);
/* If no state change, return */
if(new_state == old_state) {
sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
return TRUE;
}
/* Lookup & process transition function */
state_index=MAKE_STATE_INDEX(old_state, new_state);
fun=spc_state_table[state_index];
if(fun == error_fun) {
sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
return TRUE;
}
channel->IOMode=MAKE_CHANNEL_STATE(iomode, new_state);
if(!fun) {
sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
return TRUE;
}
funretval=((*fun)(channel, connector));
sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
return funretval;
}
/* error_fun is not ever called. It is just a placeholder for an
error condition in the state table */
/*----------------------------------------------------------------------+*/
int
error_fun(SPC_Channel_Ptr UNUSED_PARM(channel),
int UNUSED_PARM(connector))
/*----------------------------------------------------------------------+*/
{
return(FALSE);
}
/*
**
** This routine is called when an EOF is detected on a specific
** connector within a channel, but the channel still has a subprocess
** associated with it. It will clear the data ready flag on the
** indicated wire. After that, it will look at all the wires
** associated with the channel and set the channel's data flag to the
** inclusive OR of the individual wire's data flags.
**
*/
/*----------------------------------------------------------------------+*/
int
connector_eof(SPC_Channel_Ptr channel,
int connector)
/*----------------------------------------------------------------------+*/
{
Wire *wire=channel->wires[connector];
Wire *tmpwire;
int channelflag=0;
int iomode=channel->IOMode;
if(!wire)
return(FALSE);
wire->flags &= ~SPCIO_DATA;
if(IS_SPCIO_STDOUT(iomode)) {
tmpwire=channel->wires[STDOUT];
channelflag |= IS_SPCIO_DATA(tmpwire->flags);
}
if(IS_SPCIO_STDERR(iomode) && IS_SPCIO_SEPARATE(iomode)) {
tmpwire=channel->wires[STDERR];
channelflag |= IS_SPCIO_DATA(tmpwire->flags);
}
if(channelflag)
channel->IOMode |= SPCIO_DATA;
else
channel->IOMode &= ~SPCIO_DATA;
return(TRUE);
}
/*
**
** This routine is called when there is no subprocess associated with
** the channel, and an EOF is detected on a connector. It will first
** call connector_eof on the channel/connector, and if the channel
** does not have its data flag set, it will reset the channel.
**
*/
/*----------------------------------------------------------------------+*/
int
connector_eof_with_reset(SPC_Channel_Ptr channel,
int connector)
/*----------------------------------------------------------------------+*/
{
connector_eof(channel, connector);
if(!IS_DATA(channel))
XeSPCReset(channel);
return(TRUE);
}
/*
**
** This routine is called when the child associated with the channel
** dies, and there is no data available to be read on the channel.
** It will simply reset then channel.
**
*/
/*----------------------------------------------------------------------+*/
int
sigcld_with_reset(SPC_Channel_Ptr channel,
int UNUSED_PARM(connector))
/*----------------------------------------------------------------------+*/
{
mempf0(channel, reset);
return(TRUE);
}