Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / DtSvc / DtEncap / spc-sm.c
1 /*
2  * File:         spc-sm.c $XConsortium: spc-sm.c /main/4 1996/04/21 19:10:39 drk $
3  * Language:     C
4  *
5  * (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
6  *
7  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
8  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
9  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
10  * (c) Copyright 1993, 1994 Novell, Inc.                                *
11  */
12
13 #include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
14 #include <signal.h>
15 #include <SPC/spcP.h>
16
17 /*
18  **
19  ** Definitions for blocking signals
20  **
21 */
22
23
24 static int (* spc_state_table[16]) (SPC_Channel_Ptr channel, int connector)= {
25   
26                             /* old_state new_state */
27   
28   NULL,                     /*    00        00     */
29   NULL,                     /*    00        01     */
30   error_fun,                /*    00        10     */
31   NULL,                     /*    00        11     */
32   sigcld_with_reset,        /*    01        00     */
33   NULL,                     /*    01        01     */
34   error_fun,                /*    01        10     */
35   error_fun,                /*    01        11     */
36   connector_eof_with_reset, /*    10        00     */
37   error_fun,                /*    10        01     */
38   NULL,                     /*    10        10     */
39   error_fun,                /*    10        11     */
40   NULL,                     /*    11        00     */
41   connector_eof,            /*    11        01     */
42   NULL,                     /*    11        10     */
43   NULL                      /*    11        11     */
44   };
45
46 /*----------------------------------------------------------------------+*/
47 SPC_Change_State(SPC_Channel_Ptr channel,
48                  int connector, 
49                  int data_line, 
50                  int process_line)
51 /*----------------------------------------------------------------------+*/
52 {
53
54   int iomode=channel->IOMode;
55   int old_state=CHANNEL_STATE(iomode);
56   int new_state, state_index;
57   int (*fun)(SPC_Channel_Ptr, int);
58   int funretval;
59
60   sigset_t newsigmask, oldsigmask;
61
62   sigemptyset(&newsigmask);
63   sigemptyset(&oldsigmask);
64
65   /* Process don't cares */
66   sigaddset(&newsigmask, SIGCHLD);
67   sigprocmask(SIG_BLOCK, &newsigmask, &oldsigmask);
68
69   if(data_line == -1)
70     data_line=DATA_LINE(old_state);
71   if(process_line == -1)
72     process_line = PROC_LINE(old_state);
73
74   /* create new state */
75   
76   new_state=MAKE_STATE(data_line, process_line);
77
78   /* If no state change, return */
79   
80   if(new_state == old_state) {
81     sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
82     return TRUE;
83   }
84
85   /* Lookup & process transition function */
86
87   state_index=MAKE_STATE_INDEX(old_state, new_state);
88   
89   fun=spc_state_table[state_index];
90
91   if(fun == error_fun) {
92     sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
93     return TRUE;
94    }
95   
96   channel->IOMode=MAKE_CHANNEL_STATE(iomode, new_state);
97   if(!fun) {
98     sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
99     return TRUE;
100   }
101
102   funretval=((*fun)(channel, connector));
103
104   sigprocmask(SIG_SETMASK, &oldsigmask, (sigset_t *)NULL);
105   return funretval;
106
107 }
108
109 /* error_fun is not ever called.  It is just a placeholder for an
110    error condition in the state table */
111
112 /*----------------------------------------------------------------------+*/
113 error_fun(SPC_Channel_Ptr UNUSED_PARM(channel),
114           int             UNUSED_PARM(connector))
115 /*----------------------------------------------------------------------+*/
116 {
117   return(FALSE);
118 }
119
120
121 /*
122  ** 
123  ** This routine is called when an EOF is detected on a specific
124  ** connector within a channel, but the channel still has a subprocess
125  ** associated with it. It will clear the data ready flag on the
126  ** indicated wire.  After that, it will look at all the wires
127  ** associated with the channel and set the channel's data flag to the
128  ** inclusive OR of the individual wire's data flags.
129  **
130 */
131
132 /*----------------------------------------------------------------------+*/
133 connector_eof(SPC_Channel_Ptr channel,
134               int connector)
135 /*----------------------------------------------------------------------+*/
136 {
137   Wire *wire=channel->wires[connector];
138   Wire *tmpwire;
139   int  channelflag=0;
140   int  iomode=channel->IOMode;
141
142   if(!wire)
143     return(FALSE);
144
145   wire->flags &= ~SPCIO_DATA;
146
147   if(IS_SPCIO_STDOUT(iomode)) {
148     tmpwire=channel->wires[STDOUT];
149     channelflag |= IS_SPCIO_DATA(tmpwire->flags);
150   }
151
152   if(IS_SPCIO_STDERR(iomode) && IS_SPCIO_SEPARATE(iomode)) {
153     tmpwire=channel->wires[STDERR];
154     channelflag |= IS_SPCIO_DATA(tmpwire->flags);
155   }
156
157   if(channelflag)
158     channel->IOMode |= SPCIO_DATA;
159   else
160     channel->IOMode &= ~SPCIO_DATA;
161
162   return(TRUE);
163 }
164
165 /*
166  **
167  ** This routine is called when there is no subprocess associated with
168  ** the channel, and an EOF is detected on a connector.  It will first
169  ** call connector_eof on the channel/connector, and if the channel
170  ** does not have its data flag set, it will reset the channel.
171  **
172 */
173
174
175   
176 /*----------------------------------------------------------------------+*/
177 connector_eof_with_reset(SPC_Channel_Ptr channel,
178                          int connector)
179 /*----------------------------------------------------------------------+*/
180 {
181   connector_eof(channel, connector);
182   if(!IS_DATA(channel))
183     XeSPCReset(channel);
184
185   return(TRUE);
186 }
187
188 /*
189  **
190  ** This routine is called when the child associated with the channel
191  ** dies, and there is no data available to be read on the channel.
192  ** It will simply reset then channel.
193  **
194 */
195
196 /*----------------------------------------------------------------------+*/
197 sigcld_with_reset(SPC_Channel_Ptr channel,
198                   int             UNUSED_PARM(connector))
199 /*----------------------------------------------------------------------+*/
200 {
201   mempf0(channel, reset);
202   return(TRUE);
203 }