2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $XConsortium: noio.c /main/8 1996/11/21 19:53:13 drk $
28 * (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
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. *
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>
44 #include "DtSvcLock.h"
46 /* Global variables */
49 * The name of the directory used for authentication and
50 * for temporary logfiles.
52 XeString SPCD_Authentication_Dir = NULL;
55 * This array contains the names of the logfiles the SPC daemon
56 * creates. Before the daemon exits, if any logfiles exist, they
59 char **SPC_logfile_list = NULL;
61 /*----------------------------------------------------------------------+*/
62 void noio_channel_class_init(object_clasp t)
63 /*----------------------------------------------------------------------+*/
65 noio_channel_clasp c =(noio_channel_clasp) t;
67 c->new_obj = alloc_channel_object;
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;
83 /* New B.00 methods */
85 c->send_eof = send_eof_noio_channel_object;
86 c->set_termio = set_termio_noio_channel_object;
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 */
97 noio_channel_clasp noio_channel_class = &noio_channel_class_struct;
100 * Forward declarations
103 static int is_dir_usable (
105 static char * get_tmp_dir (
109 /****************************************************************************
111 * is_dir_usable - given a directory name, return 1 if:
113 * #1 the directory exists (determined by stat() succeeding)
115 * #2 the directory is readable
117 * #3 the directory is writeable
119 * otherwise, return 0.
123 * char *dir - the directory to check
127 * 1 if 'dir' is usable and 0 if it is not
129 ****************************************************************************/
131 static int is_dir_usable (
134 struct stat stat_buffer;
136 if ((stat (dir, &stat_buffer)) != 0)
139 if ((S_ISDIR(stat_buffer.st_mode)) && (access (dir, W_OK | R_OK) == 0))
145 /****************************************************************************
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:
162 * char * - the name of the temporary directory to use
163 * or NULL if no usable directory is found.
167 * o The caller is responsible for free'ing the returned
168 * string (if it is not NULL)
170 ****************************************************************************/
172 static char * get_tmp_dir (
176 _Xgetpwparams pwd_buf;
177 struct passwd * pwd_ret;
179 if ((pwd_ret = _XGetpwuid(getuid(), pwd_buf)) == NULL)
182 dir = malloc (strlen (pwd_ret->pw_dir) +
183 strlen (SPCD_ENV_HOME_DIRECTORY) + 8);
188 (void) sprintf (dir, "%s/%s/tmp", pwd_ret->pw_dir, SPCD_ENV_HOME_DIRECTORY);
189 if (is_dir_usable (dir))
192 (void) sprintf (dir, "%s/%s", pwd_ret->pw_dir, SPCD_ENV_HOME_DIRECTORY);
193 if (is_dir_usable (dir))
196 (void) sprintf (dir, "%s", pwd_ret->pw_dir);
197 if (is_dir_usable (dir))
205 *** Method definitions for noio channel objects
210 * This routine handles initialization for noio channels
213 /*----------------------------------------------------------------------+*/
214 SPC_Channel_Ptr open_noio_channel_object(SPC_Channel_Ptr channel,
217 /*----------------------------------------------------------------------+*/
220 SPC_Channel_Ptr result;
221 XeString temp_dir_name = NULL;
223 call_parent_method(channel, open, (channel, iomode, hostname), result);
225 if(result==SPC_ERROR)
228 if(IS_SPCIO_USE_LOGFILE(iomode)) {
231 /* Storage from tempnam() freed in remove_logfile_local_channel_object */
232 if (SPCD_Authentication_Dir != NULL)
233 channel->logfile=tempnam(SPCD_Authentication_Dir,"SPC");
235 temp_dir_name = get_tmp_dir ();
236 channel->logfile=tempnam(temp_dir_name,"SPC");
237 if (temp_dir_name != NULL)
242 * Save the name of the logfile so it can removed by the
243 * daemon before it exits.
245 if (SPC_logfile_list == NULL)
247 * Create the first block plus the NULL terminator.
249 SPC_logfile_list = (char **) malloc (2 * sizeof (char *));
252 * Need to add this file to the end of the list.
254 for (i = 0; SPC_logfile_list[i] != NULL; i++);
255 SPC_logfile_list = (char **) realloc (SPC_logfile_list,
256 (i+2) * sizeof (char *));
258 if (channel->logfile != NULL)
259 SPC_logfile_list[i] = strdup (channel->logfile);
261 SPC_logfile_list[i] = (char *) NULL;
262 SPC_logfile_list[i+1] = (char *) NULL;
263 _DtSvcProcessUnlock();
265 if(!channel->logfile) {
266 SPC_Error(SPC_Out_Of_Memory);
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 /*----------------------------------------------------------------------+*/
283 SPC_Error(SPC_Bad_Operation);
287 /*----------------------------------------------------------------------+*/
288 int write_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
289 XeString UNUSED_PARM(buffer),
290 int UNUSED_PARM(nbytes))
291 /*----------------------------------------------------------------------+*/
294 SPC_Error(SPC_Bad_Operation);
298 /*----------------------------------------------------------------------+*/
299 int pre_fork_noio_channel_object(SPC_Channel_Ptr channel)
300 /*----------------------------------------------------------------------+*/
305 call_parent_method(channel, pre_fork, (channel), result);
307 if(result==SPC_ERROR)
313 /*----------------------------------------------------------------------+*/
314 int post_fork_noio_channel_object(SPC_Channel_Ptr channel,
316 /*----------------------------------------------------------------------+*/
320 call_parent_method(channel, post_fork, (channel, parentp), result);
322 if(result==SPC_ERROR)
326 if (parentp) { /* Master process */
328 else { /* Slave process */
330 /* set up STDIN, STDOUT & STDERR to go to /dev/null,
331 or to the appropriate logfile */
337 /* Open logfile if necessary */
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);
344 spc_dup2(fd, STDOUT);
345 spc_dup2(fd, STDERR);
347 /* close all other file descriptors */
354 /*----------------------------------------------------------------------+*/
355 int reset_noio_channel_object(SPC_Channel_Ptr channel)
356 /*----------------------------------------------------------------------+*/
359 int iomode=channel->IOMode;
361 call_parent_method(channel, reset, (channel), result);
363 if(result==SPC_ERROR)
370 /*----------------------------------------------------------------------+*/
371 int attach_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel),
372 int UNUSED_PARM(foo))
373 /*----------------------------------------------------------------------+*/
375 /* It is an error to try to attach to a noio channel... */
376 SPC_Error(SPC_Bad_Operation);
380 /*----------------------------------------------------------------------+*/
381 void noio_channel_object_input_handler(void *UNUSED_PARM(client_data),
382 int *UNUSED_PARM(source),
383 SPCInputId *UNUSED_PARM(id))
384 /*----------------------------------------------------------------------+*/
387 SPC_Error(SPC_Bad_Operation);
388 return /* (SPC_ERROR) */;
391 int send_eof_noio_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel))
393 SPC_Error(SPC_Bad_Operation);
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))
402 SPC_Error(SPC_Bad_Operation);