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 //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%% (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%% (c) Copyright 1993, 1994 Novell, Inc.
27 //%% $TOG: mp_c_session.C /main/5 1999/10/14 18:41:24 mgreess $
29 * @(#)mp_c_session.C 1.23 94/10/03
31 * Copyright (c) 1990,1992,1993 by Sun Microsystems, Inc.
33 * Implementation of the _Tt_session class.
35 #include "util/tt_global_env.h"
36 #include "util/tt_host.h"
37 #include "util/tt_enumname.h"
38 #include "mp/mp_global.h"
39 #include "mp/mp_c_message.h"
41 #include "mp/mp_pattern.h"
42 #include "mp/mp_rpc_client.h"
43 #include "mp/mp_rpc_interface.h"
44 #include "mp/mp_c_session.h"
45 #include "mp/mp_desktop.h"
46 #include "mp/mp_xdr_functions.h"
47 #include "util/tt_port.h"
51 #ifdef OPT_UNIX_SOCKET_RPC
52 # include <sys/socket.h>
54 #endif // OPT_UNIX_SOCKET_RPC
56 // Use the parent class (_Tt_session) for construction and destruction.
57 _Tt_c_session::_Tt_c_session () {}
58 _Tt_c_session::~_Tt_c_session () {}
63 // Initializes a session object. This means that we initialize our
64 // desktop connection if this is a desktop session and find the address
65 // of a server session. If none is found or if an address is found but we
66 // are unable to connect to the session then we attempt to auto-start a
71 // TT_ERR_ACCESS Could not init desktop (diagnostic emitted)
72 // TT_ERR_NO_MATCH Advertised address's version is too new
73 // (diagnostic emitted)
74 // TT_ERR_INVALID Authorization error
75 // TT_ERR_NOMP No server running or startable
77 Tt_status _Tt_c_session::
80 _Tt_string start_ttcmd;
85 if (env() == _TT_ENV_X11) {
86 if (_displayname.len() == 0) {
87 _displayname = _tt_global->xdisplayname;
92 status = client_session_init();
96 // We try to ping the session to give it
97 // reasonable time to start up.
98 for (pings = 1; pings <= OPT_PING_TRIES; pings++) {
100 if (status != TT_ERR_NOMP) {
101 // Fatal error or TT_OK
104 sleep(OPT_PING_SLEEP);
107 // Session could not be pinged. If this is an
108 // X11 session, handle the case where there is
109 // an invalid TT_CDE_XATOM_NAME xprop and a valid
110 // TT_XATOM_NAME xprop, because in that case we
111 // were trying to ping the dead TT_CDE_XATOM_NAME
114 if (env() == _TT_ENV_X11) {
115 _Tt_string desktop_addr;
117 if (_desktop->get_prop(TT_CDE_XATOM_NAME,
119 desktop_addr == _address_string) {
121 // Bogus session xprop found -- re-initialize
122 // trying the TT_XATOM_NAME xprop.
124 if (_desktop->get_prop(TT_XATOM_NAME,
126 // Continue the initialization
127 // loop WITHOUT attempting to start
135 // If we\'re here, a session was found but could
136 // not be pinged. Force re-initialization.
137 _address_string = (char *) 0;
141 case TT_ERR_NO_MATCH:
142 // Can't recover from these
144 case TT_WRN_NOTFOUND:
148 // If we haven\'t tried to start one already, do
149 // so. If we have tried but failed, force
150 // client_session_init to re-initialize.
151 if (tried > 0) _address_string = (char *) 0;
153 case TT_AUTHFILE_ACCESS:
154 case TT_AUTHFILE_LOCK:
155 case TT_AUTHFILE_LOCK_TIMEOUT:
156 case TT_AUTHFILE_UNLOCK:
157 case TT_AUTHFILE_MISSING:
158 case TT_AUTHFILE_ENTRY_MISSING:
159 case TT_AUTHFILE_WRITE:
160 return TT_ERR_AUTHORIZATION;
162 _tt_syslog( 0, LOG_ERR,
163 "_Tt_session::client_session_init(): %s",
164 _tt_enumname(status));
165 return TT_ERR_INTERNAL;
168 // Attempt to start a new server
170 if (env() != _TT_ENV_X11) {
171 // can't auto-start anything other than an X
176 int sysStat = startup_ttsession(start_ttcmd);
178 if (WIFEXITED(sysStat)) {
179 exitStat = WEXITSTATUS(sysStat);
180 } else if (WIFSIGNALED(sysStat)) {
181 _tt_syslog( 0, LOG_ERR,
182 "libtt: system(\"%s\"): signal %d",
187 _tt_syslog( 0, LOG_ERR,
188 "libtt: system(\"%s\"): %d",
189 (char *)start_ttcmd, sysStat );
194 // Race condition -- no ttsession was
195 // found in the above code, but by the time
196 // we got around to trying to start one,
197 // another had appeared, so this one exited
201 // another ttsession discovered.
202 // Either way, loop around and connect to it
203 // after nulling _address_string to make sure
204 // we pick the address off the X server again
205 // since the new server will have a new
207 _address_string = (char *)0;
209 // Since the other ttsession was just started,
210 // let it have a chance to initialize
215 // ttsession started.
229 // Starts ttsession by executing either the hardcoded
230 // default command "ttsession -s -d <displayname>"
231 // or the command specified in TTSESSION_CMD or SUN_TTSESSION_CMD.
232 // TTSESSION_CMD and SUN_TTSESSION_CMD provide a way of overriding the
233 // standard options specified when tools auto-start
234 // ttsession. For example, to switch from Classing
235 // Engine format to xdr format for auto-start set
236 // TTSESSION_CMD or SUN_TTSESSION_CMD to "ttsession -X".
237 // The string used is returned in a parameter so c_init can use it in
242 startup_ttsession(_Tt_string &start_ttcmd)
244 // If TTSESSION_CMD or SUN_TTSESSION_CMD is specified, we use system() to run the
245 // command since it might have shell metacharacters (a common
246 // thing to do is TTSESSION_CMD or SUN_TTSESSION_CMD=truss ttsession >/tmp/trace
247 // in order to truss ttsession startup)
249 char* pc_env_value = _tt_get_first_set_env_var(2, "TTSESSION_CMD", "SUN_TTSESSION_CMD");
252 start_ttcmd = pc_env_value;
253 start_ttcmd = start_ttcmd.cat(" -d ");
254 start_ttcmd = start_ttcmd.cat(_displayname);
255 return system((char *)start_ttcmd);
257 // start_ttcmd is not really used but we set it so it can be used
259 start_ttcmd = "ttsession -s -d ";
260 start_ttcmd = start_ttcmd.cat(_displayname);
262 // This is basically a stripped down and specialized system() call...
267 #if defined(__GNUG__)
268 typedef void (*SIG_PF)(int);
270 SIG_PF istat, qstat, cstat;
272 #if defined(_AIX) || defined(OPT_BUG_USL) || defined(OPT_BUG_UXP)
275 if((pid = vfork()) == 0) {
277 (void) execlp("ttsession", "ttsession",
280 (char *)_displayname,
285 istat = signal(SIGINT, SIG_IGN);
286 qstat = signal(SIGQUIT, SIG_IGN);
287 cstat = signal(SIGCLD, SIG_DFL);
289 w = waitpid(pid, &status, 0);
291 (void) signal(SIGINT, istat);
292 (void) signal(SIGQUIT, qstat);
293 (void) signal(SIGCLD, cstat);
295 return((w == -1)? w: status);
300 // Invokes an rpc call on the server session that causes all of the
301 // given procid's patterns to have a session id for the current
302 // session (this allows them to begin matching messages).
304 // See _Tt_s_session::s_join for the server-side of this method.
306 Tt_status _Tt_c_session::
307 c_join(_Tt_procid_ptr &procid)
312 rstatus = call(TT_RPC_JOIN_SESSION,
313 (xdrproc_t)tt_xdr_procid,
317 return((rstatus == TT_OK) ? status : rstatus);
322 // Invokes an rpc call on the server session that causes all of the
323 // given procid's patterns to not have a session id for the current
324 // session (this prevents them from matching messages).
326 // See _Tt_s_session::s_quit for the server-side of this method.
328 Tt_status _Tt_c_session::
329 c_quit(_Tt_procid_ptr &procid)
334 rstatus = call(TT_RPC_QUIT_SESSION,
335 (xdrproc_t)tt_xdr_procid, (char *)&procid,
336 (xdrproc_t)xdr_int, (char *)&status);
337 return((rstatus == TT_OK) ? status : rstatus);