Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / lib / DtSvc / DtEncap / noio.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 /* $XConsortium: noio.c /main/8 1996/11/21 19:53:13 drk $
24  *
25  * File:         noio.c 
26  * Language:     C
27  *
28  * (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
29  *
30  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
31  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
32  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
33  * (c) Copyright 1993, 1994 Novell, Inc.                                *
34  */
35
36 #include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
37 #include <bms/MemoryMgr.h>
38 #define X_INCLUDE_PWD_H
39 #define XOS_USE_XT_LOCKING
40 #include <X11/Xos_r.h>
41 #include <limits.h>
42
43 #include <SPC/spcP.h>
44 #include "DtSvcLock.h"
45
46 /* Global variables */
47
48 /*
49  * The name of the directory used for authentication and
50  * for temporary logfiles.
51  */
52 XeString SPCD_Authentication_Dir = NULL;
53
54 /*
55  * This array contains the names of the logfiles the SPC daemon
56  * creates.  Before the daemon exits, if any logfiles exist, they 
57  * will be removed.
58  */
59 char **SPC_logfile_list = NULL;
60
61 /*----------------------------------------------------------------------+*/
62 void noio_channel_class_init(object_clasp t)
63 /*----------------------------------------------------------------------+*/
64 {
65   noio_channel_clasp c =(noio_channel_clasp) t;
66   
67   c->new_obj    = alloc_channel_object;
68   
69   c->open       = open_noio_channel_object;
70   c->close      = close_local_channel_object;
71   c->read       = read_noio_channel_object;
72   c->write      = write_noio_channel_object;
73   c->reset      = reset_noio_channel_object;
74   c->pre_fork   = pre_fork_noio_channel_object;
75   c->post_fork  = post_fork_noio_channel_object;
76   c->exec_proc  = exec_proc_local_channel_object;
77   c->signal     = signal_local_channel_object;
78   c->wait_for_termination = local_channel_object_wait_for_termination;
79   c->attach     = attach_noio_channel_object;
80   c->input      = noio_channel_object_input_handler;
81   c->remove_logfile = remove_logfile_local_channel_object;
82
83   /* New B.00 methods */
84
85   c->send_eof   = send_eof_noio_channel_object;
86   c->set_termio = set_termio_noio_channel_object;
87 }
88
89 static struct noio_channel_class noio_channel_class_struct = {
90   (channel_clasp) &channel_class, /* base class pointer */
91   "noio_channel",           /* class name */
92   noio_channel_class_init,  /* class initialize function */
93   sizeof(SPC_Channel),      /* size */
94   0
95   };
96
97 noio_channel_clasp noio_channel_class = &noio_channel_class_struct;
98
99 /*
100  * Forward declarations
101  */
102
103 static int is_dir_usable (
104         char            *dir);
105 static char * get_tmp_dir (
106         void);
107
108
109 /****************************************************************************
110  *
111  * is_dir_usable - given a directory name, return 1 if:
112  *
113  *    #1 the directory exists (determined by stat() succeeding)
114  *
115  *    #2 the directory is readable
116  *
117  *    #3 the directory is writeable
118  *
119  * otherwise, return 0.
120  *
121  * Parameters:
122  *
123  *    char      *dir    - the directory to check
124  *
125  * Return Value:
126  *
127  *    1 if 'dir' is usable and 0 if it is not
128  *
129  ****************************************************************************/
130
131 static int is_dir_usable (
132         char            *dir)
133 {
134    struct stat  stat_buffer;
135
136    if ((stat (dir, &stat_buffer)) != 0) 
137       return (0);
138
139    if ((S_ISDIR(stat_buffer.st_mode)) && (access (dir, W_OK | R_OK) == 0))
140       return (1);
141
142    return (0);
143 }
144
145 /****************************************************************************
146  *
147  * get_tmp_dir - determine the name of a directory to use
148  *    for temporary logfiles.  The first dirctory in the 
149  *    following list that passes the usability test in 
150  *    'is_dir_usable' will be returned:
151  *
152  *       ~/.dt/tmp
153  *
154  *       ~/.dt
155  *
156  *       ~/
157  *
158  * Parameters: NONE
159  *
160  * Return Value:
161  *
162  *    char *    -  the name of the temporary directory to use
163  *                 or NULL if no usable directory is found.
164  *
165  * Notes:  
166  *
167  *    o The caller is responsible for free'ing the returned 
168  *      string (if it is not NULL)
169  *
170  ****************************************************************************/
171
172 static char * get_tmp_dir (
173         void)
174 {
175    char                 *dir;
176    _Xgetpwparams        pwd_buf;
177    struct passwd *      pwd_ret;
178
179    if ((pwd_ret = _XGetpwuid(getuid(), pwd_buf)) == NULL)
180       return (NULL);
181
182    dir = malloc (strlen (pwd_ret->pw_dir) +
183                  strlen (SPCD_ENV_HOME_DIRECTORY) + 8);
184
185    if (!dir)
186       return (NULL);
187
188    (void) sprintf (dir, "%s/%s/tmp", pwd_ret->pw_dir, SPCD_ENV_HOME_DIRECTORY);
189    if (is_dir_usable (dir))
190       return (dir);
191
192    (void) sprintf (dir, "%s/%s", pwd_ret->pw_dir, SPCD_ENV_HOME_DIRECTORY);
193    if (is_dir_usable (dir))
194       return (dir);
195
196    (void) sprintf (dir, "%s", pwd_ret->pw_dir);
197    if (is_dir_usable (dir))
198       return (dir);
199
200    free(dir);
201    return (NULL);
202 }
203
204 /*
205  ***
206  *** Method definitions for noio channel objects
207  ***
208 */
209
210 /*
211  * This routine handles initialization for noio channels
212  */
213
214 /*----------------------------------------------------------------------+*/
215 SPC_Channel_Ptr open_noio_channel_object(SPC_Channel_Ptr channel,
216                                          int iomode,
217                                          XeString hostname)
218 /*----------------------------------------------------------------------+*/
219 {
220   int i=0;
221   SPC_Channel_Ptr result;
222   XeString temp_dir_name = NULL;
223   
224   call_parent_method(channel, open, (channel, iomode, hostname), result);
225
226   if(result==SPC_ERROR)
227     return(SPC_ERROR);
228
229   if(IS_SPCIO_USE_LOGFILE(iomode)) {
230
231     _DtSvcProcessLock();
232     /* Storage from tempnam() freed in remove_logfile_local_channel_object */
233     if (SPCD_Authentication_Dir != NULL)
234       channel->logfile=tempnam(SPCD_Authentication_Dir,"SPC");
235     else {
236       temp_dir_name = get_tmp_dir ();
237       channel->logfile=tempnam(temp_dir_name,"SPC");
238       free(temp_dir_name);
239     }
240
241     /*
242      * Save the name of the logfile so it can removed by the
243      * daemon before it exits.
244      */
245     if (SPC_logfile_list == NULL)
246       /*
247        * Create the first block plus the NULL terminator.
248        */
249       SPC_logfile_list = (char **) malloc (2 * sizeof (char *));
250     else {
251       /*
252        * Need to add this file to the end of the list.
253        */
254       for (i = 0; SPC_logfile_list[i] != NULL; i++);
255       SPC_logfile_list = (char **) realloc (SPC_logfile_list, 
256                                             (i+2) * sizeof (char *));
257     }
258     if (channel->logfile != NULL)
259        SPC_logfile_list[i] = strdup (channel->logfile);
260     else
261        SPC_logfile_list[i] = (char *) NULL;
262     SPC_logfile_list[i+1] = (char *) NULL;
263     _DtSvcProcessUnlock();
264
265     if(!channel->logfile) {
266       SPC_Error(SPC_Out_Of_Memory);
267       return(SPC_ERROR);
268     }
269   }
270   
271   return(channel);
272   
273 }
274
275 /*----------------------------------------------------------------------+*/
276 int read_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
277                              int             UNUSED_PARM(connector), /* STDOUT or STDERR */
278                              XeString        UNUSED_PARM(buffer),
279                              int             UNUSED_PARM(nbytes))
280 /*----------------------------------------------------------------------+*/
281   
282 {
283   SPC_Error(SPC_Bad_Operation);
284   return(SPC_ERROR);
285 }
286
287 /*----------------------------------------------------------------------+*/
288 int write_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
289                               XeString        UNUSED_PARM(buffer),
290                               int             UNUSED_PARM(nbytes))
291 /*----------------------------------------------------------------------+*/
292 {
293   
294   SPC_Error(SPC_Bad_Operation);
295   return(SPC_ERROR);
296 }
297
298 /*----------------------------------------------------------------------+*/
299 int pre_fork_noio_channel_object(SPC_Channel_Ptr channel)
300 /*----------------------------------------------------------------------+*/
301 {
302
303   int result;
304   
305   call_parent_method(channel, pre_fork, (channel), result);
306   
307   if(result==SPC_ERROR)
308     return(SPC_ERROR);
309
310   return(TRUE);
311 }
312
313 /*----------------------------------------------------------------------+*/
314 int post_fork_noio_channel_object(SPC_Channel_Ptr channel,
315                                   int parentp)
316 /*----------------------------------------------------------------------+*/
317 {
318   int result, fd;
319   
320   call_parent_method(channel, post_fork, (channel, parentp), result);
321
322   if(result==SPC_ERROR)
323     return(SPC_ERROR);
324
325   
326   if (parentp) {                /* Master process */
327   }
328   else {                        /* Slave process */
329
330     /* set up STDIN, STDOUT & STDERR to go to /dev/null,
331        or to the appropriate logfile */
332
333     fd=(-1);
334     
335     spc_dup2(fd, STDIN);
336
337     /* Open logfile if necessary */
338     
339     if(IS_SPCIO_USE_LOGFILE(channel->IOMode))
340       if((fd=open(channel->logfile, O_WRONLY | O_CREAT, 0666)) == ERROR) {
341         SPC_Error(SPC_Cannot_Open_Log, channel->logfile);
342         return(SPC_ERROR);
343       }
344     spc_dup2(fd, STDOUT);
345     spc_dup2(fd, STDERR);
346     
347     /* close all other file descriptors */
348     
349     SPC_Close_Unused();
350   }
351   return(TRUE);
352 }
353
354 /*----------------------------------------------------------------------+*/
355 int reset_noio_channel_object(SPC_Channel_Ptr channel)
356 /*----------------------------------------------------------------------+*/
357 {
358   int result;
359   int iomode=channel->IOMode;
360   
361   call_parent_method(channel, reset, (channel), result);
362
363   if(result==SPC_ERROR)
364     return(SPC_ERROR);
365
366   return(TRUE);
367
368 }
369
370 /*----------------------------------------------------------------------+*/
371 int attach_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel), 
372                                int             UNUSED_PARM(foo))
373 /*----------------------------------------------------------------------+*/
374 {
375   /* It is an error to try to attach to a noio channel... */
376   SPC_Error(SPC_Bad_Operation);
377   return(SPC_ERROR);
378 }
379
380 /*----------------------------------------------------------------------+*/
381 void noio_channel_object_input_handler(void  *UNUSED_PARM(client_data),
382                                   int        *UNUSED_PARM(source),
383                                   SPCInputId *UNUSED_PARM(id))
384 /*----------------------------------------------------------------------+*/
385 {
386
387   SPC_Error(SPC_Bad_Operation);
388   return /* (SPC_ERROR) */;
389 }
390
391 int send_eof_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel))
392 {
393   SPC_Error(SPC_Bad_Operation);
394   return(SPC_ERROR);
395 }
396
397 int set_termio_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
398                                    int UNUSED_PARM(connection),
399                                    int UNUSED_PARM(side),
400                                    struct termios * UNUSED_PARM(termio))
401 {
402   SPC_Error(SPC_Bad_Operation);
403   return(SPC_ERROR);
404 }