Merge branch 'master' into autotools-conversion
[oweals/cde.git] / cde / programs / dtspcd / spcd_event.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 libraries 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:         spcd_event.c $XConsortium: spcd_event.c /main/4 1996/01/15 13:49:32 rswiston $
25  * Language:     C
26  *
27  * (c) Copyright 1988, 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 #define __need_fd_set
36
37 #include <bms/sbport.h>  /* NOTE: sbport.h must be the first include. */
38 #include <SPC/spcP.h>
39 #include <bms/SbEvent.h> 
40 #include <sys/types.h>   /* for fd_set, FD_SET macros, et. al. */
41 #include <errno.h>
42
43 #ifndef __hpux
44 # define FD_SET_CAST(x) (x)
45 #else
46 # define FD_SET_CAST(x) ((int *)(x))
47 #endif /* __hpux */
48
49 struct {SbInputCallbackProc handler; void* data; }
50   SPCD_input_handlers [FD_SETSIZE],
51   SPCD_except_handlers[FD_SETSIZE];
52
53 int SPCD_max_fd = 1;
54
55 fd_set Sb_Input_Mask, Sb_Except_Mask;
56
57 SbInputId SPCD_AddInput(int fd, SbInputCallbackProc proc, void* data)
58  {SPCD_input_handlers[fd].handler = proc;
59   SPCD_input_handlers[fd].data    = data;
60   FD_SET(fd, &Sb_Input_Mask);
61   if (SPCD_max_fd < fd) SPCD_max_fd = fd;
62   return fd; }
63
64 SbInputId SPCD_AddException(int fd, SbInputCallbackProc proc, void* data)
65  {SPCD_except_handlers[fd].handler = proc;
66   SPCD_except_handlers[fd].data    = data;
67   FD_SET(fd, &Sb_Except_Mask);
68   if (SPCD_max_fd < fd) SPCD_max_fd = fd;
69   return fd; }
70
71 void SPCD_RemoveInput(SbInputId id)
72  {FD_CLR(id, &Sb_Input_Mask);
73  }
74
75 void SPCD_RemoveException(SbInputId id)
76  {FD_CLR(id, &Sb_Except_Mask);
77  }
78
79
80 void SPCD_MainLoopUntil(Boolean *flag)
81 {
82   
83   int fd_vec_size = howmany(SPCD_max_fd, NFDBITS);
84   fd_set input_mask, except_mask;
85   int n, fd;
86   int result;
87
88   do {
89     memcpy(&input_mask, &Sb_Input_Mask, sizeof(fd_set));
90     memcpy(&except_mask, &Sb_Except_Mask, sizeof(fd_set));
91
92     
93     do result=select(SPCD_max_fd + 1, FD_SET_CAST(&input_mask),
94                      FD_SET_CAST(NULL),
95                      FD_SET_CAST(&except_mask), NULL);
96     while(result == -1 && errno==EINTR);
97     
98     if(result < 0) {
99       SPC_Error(SPC_Bad_Select);
100       SPC_Format_Log((XeString)"Exiting server ...");
101       SPC_Close_Log();
102       exit (3);
103     }
104
105     /* Modified loop to break after a single hit on the select.  This */
106     /* is necessary because there is nothing which stops the lower */
107     /* level input handlers from reading the data from a random file */
108     /* descriptor.  If this happens, and the random file descriptor */
109     /* happens to be one on which this loop detected input, the */
110     /* process might hang.  The solution is therefore to go back to */
111     /* the select after every input handler call. */
112     
113     for (fd=0; fd < SPCD_max_fd+1; fd++)
114       {
115         SbInputId id = fd;
116         if(FD_ISSET(fd, &except_mask)) {
117           (*SPCD_except_handlers[fd].handler)(SPCD_except_handlers[fd].data, &fd, &id);
118           break;
119         }
120         if(FD_ISSET(fd, &input_mask)) {
121           (*SPCD_input_handlers[fd].handler)(SPCD_input_handlers[fd].data, &fd, &id);
122           break;
123         }
124       }
125   } while (!*flag);
126 }
127
128 void SPCD_BreakMainLoop(void) 
129
130   /* no need to do anything */ 
131 }
132
133