Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtSvc / DtEncap / spc-sm.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * File:         spc-sm.c $XConsortium: spc-sm.c /main/4 1996/04/21 19:10:39 drk $
25  * Language:     C
26  *
27  * (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
28  *
29  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
30  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
31  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
32  * (c) Copyright 1993, 1994 Novell, Inc.                                *
33  */
34
35 #include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
36 #include <signal.h>
37 #include <SPC/spcP.h>
38
39 /*
40  **
41  ** Definitions for blocking signals
42  **
43 */
44
45
46 static int (* spc_state_table[16]) (SPC_Channel_Ptr channel, int connector)= {
47   
48                             /* old_state new_state */
49   
50   NULL,                     /*    00        00     */
51   NULL,                     /*    00        01     */
52   error_fun,                /*    00        10     */
53   NULL,                     /*    00        11     */
54   sigcld_with_reset,        /*    01        00     */
55   NULL,                     /*    01        01     */
56   error_fun,                /*    01        10     */
57   error_fun,                /*    01        11     */
58   connector_eof_with_reset, /*    10        00     */
59   error_fun,                /*    10        01     */
60   NULL,                     /*    10        10     */
61   error_fun,                /*    10        11     */
62   NULL,                     /*    11        00     */
63   connector_eof,            /*    11        01     */
64   NULL,                     /*    11        10     */
65   NULL                      /*    11        11     */
66   };
67
68 /*----------------------------------------------------------------------+*/
69 SPC_Change_State(SPC_Channel_Ptr channel,
70                  int connector, 
71                  int data_line, 
72                  int process_line)
73 /*----------------------------------------------------------------------+*/
74 {
75
76   int iomode=channel->IOMode;
77   int old_state=CHANNEL_STATE(iomode);
78   int new_state, state_index;
79   int (*fun)(SPC_Channel_Ptr, int);
80   int funretval;
81
82   sigset_t newsigmask, oldsigmask;
83
84   sigemptyset(&newsigmask);
85   sigemptyset(&oldsigmask);
86
87   /* Process don't cares */
88   sigaddset(&newsigmask, SIGCHLD);
89   sigprocmask(SIG_BLOCK, &newsigmask, &oldsigmask);
90
91   if(data_line == -1)
92     data_line=DATA_LINE(old_state);
93   if(process_line == -1)
94     process_line = PROC_LINE(old_state);
95
96   /* create new state */
97   
98   new_state=MAKE_STATE(data_line, process_line);
99
100   /* If no state change, return */
101   
102   if(new_state == old_state) {
103     sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
104     return TRUE;
105   }
106
107   /* Lookup & process transition function */
108
109   state_index=MAKE_STATE_INDEX(old_state, new_state);
110   
111   fun=spc_state_table[state_index];
112
113   if(fun == error_fun) {
114     sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
115     return TRUE;
116    }
117   
118   channel->IOMode=MAKE_CHANNEL_STATE(iomode, new_state);
119   if(!fun) {
120     sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
121     return TRUE;
122   }
123
124   funretval=((*fun)(channel, connector));
125
126   sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
127   return funretval;
128
129 }
130
131 /* error_fun is not ever called.  It is just a placeholder for an
132    error condition in the state table */
133
134 /*----------------------------------------------------------------------+*/
135 error_fun(SPC_Channel_Ptr UNUSED_PARM(channel),
136           int             UNUSED_PARM(connector))
137 /*----------------------------------------------------------------------+*/
138 {
139   return(FALSE);
140 }
141
142
143 /*
144  ** 
145  ** This routine is called when an EOF is detected on a specific
146  ** connector within a channel, but the channel still has a subprocess
147  ** associated with it. It will clear the data ready flag on the
148  ** indicated wire.  After that, it will look at all the wires
149  ** associated with the channel and set the channel's data flag to the
150  ** inclusive OR of the individual wire's data flags.
151  **
152 */
153
154 /*----------------------------------------------------------------------+*/
155 connector_eof(SPC_Channel_Ptr channel,
156               int connector)
157 /*----------------------------------------------------------------------+*/
158 {
159   Wire *wire=channel->wires[connector];
160   Wire *tmpwire;
161   int  channelflag=0;
162   int  iomode=channel->IOMode;
163
164   if(!wire)
165     return(FALSE);
166
167   wire->flags &= ~SPCIO_DATA;
168
169   if(IS_SPCIO_STDOUT(iomode)) {
170     tmpwire=channel->wires[STDOUT];
171     channelflag |= IS_SPCIO_DATA(tmpwire->flags);
172   }
173
174   if(IS_SPCIO_STDERR(iomode) && IS_SPCIO_SEPARATE(iomode)) {
175     tmpwire=channel->wires[STDERR];
176     channelflag |= IS_SPCIO_DATA(tmpwire->flags);
177   }
178
179   if(channelflag)
180     channel->IOMode |= SPCIO_DATA;
181   else
182     channel->IOMode &= ~SPCIO_DATA;
183
184   return(TRUE);
185 }
186
187 /*
188  **
189  ** This routine is called when there is no subprocess associated with
190  ** the channel, and an EOF is detected on a connector.  It will first
191  ** call connector_eof on the channel/connector, and if the channel
192  ** does not have its data flag set, it will reset the channel.
193  **
194 */
195
196
197   
198 /*----------------------------------------------------------------------+*/
199 connector_eof_with_reset(SPC_Channel_Ptr channel,
200                          int connector)
201 /*----------------------------------------------------------------------+*/
202 {
203   connector_eof(channel, connector);
204   if(!IS_DATA(channel))
205     XeSPCReset(channel);
206
207   return(TRUE);
208 }
209
210 /*
211  **
212  ** This routine is called when the child associated with the channel
213  ** dies, and there is no data available to be read on the channel.
214  ** It will simply reset then channel.
215  **
216 */
217
218 /*----------------------------------------------------------------------+*/
219 sigcld_with_reset(SPC_Channel_Ptr channel,
220                   int             UNUSED_PARM(connector))
221 /*----------------------------------------------------------------------+*/
222 {
223   mempf0(channel, reset);
224   return(TRUE);
225 }