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 libraries 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;
84 if (env() == _TT_ENV_X11) {
85 if (_displayname.len() == 0) {
86 _displayname = _tt_global->xdisplayname;
91 status = client_session_init();
95 // We try to ping the session to give it
96 // reasonable time to start up.
97 for (pings = 1; pings <= OPT_PING_TRIES; pings++) {
99 if (status != TT_ERR_NOMP) {
100 // Fatal error or TT_OK
103 sleep(OPT_PING_SLEEP);
106 // Session could not be pinged. If this is an
107 // X11 session, handle the case where there is
108 // an invalid TT_CDE_XATOM_NAME xprop and a valid
109 // TT_XATOM_NAME xprop, because in that case we
110 // were trying to ping the dead TT_CDE_XATOM_NAME
113 if (env() == _TT_ENV_X11) {
114 _Tt_string desktop_addr;
116 if (_desktop->get_prop(TT_CDE_XATOM_NAME,
118 desktop_addr == _address_string) {
120 // Bogus session xprop found -- re-initialize
121 // trying the TT_XATOM_NAME xprop.
123 if (_desktop->get_prop(TT_XATOM_NAME,
125 // Continue the initialization
126 // loop WITHOUT attempting to start
134 // If we\'re here, a session was found but could
135 // not be pinged. Force re-initialization.
136 _address_string = (char *) 0;
140 case TT_ERR_NO_MATCH:
141 // Can't recover from these
143 case TT_WRN_NOTFOUND:
147 // If we haven\'t tried to start one already, do
148 // so. If we have tried but failed, force
149 // client_session_init to re-initialize.
150 if (tried > 0) _address_string = (char *) 0;
152 case TT_AUTHFILE_ACCESS:
153 case TT_AUTHFILE_LOCK:
154 case TT_AUTHFILE_LOCK_TIMEOUT:
155 case TT_AUTHFILE_UNLOCK:
156 case TT_AUTHFILE_MISSING:
157 case TT_AUTHFILE_ENTRY_MISSING:
158 case TT_AUTHFILE_WRITE:
159 return TT_ERR_AUTHORIZATION;
161 _tt_syslog( 0, LOG_ERR,
162 "_Tt_session::client_session_init(): %s",
163 _tt_enumname(status));
164 return TT_ERR_INTERNAL;
167 // Attempt to start a new server
169 if (env() != _TT_ENV_X11) {
170 // can't auto-start anything other than an X
175 int sysStat = startup_ttsession(start_ttcmd);
177 if (WIFEXITED(sysStat)) {
178 exitStat = WEXITSTATUS(sysStat);
179 } else if (WIFSIGNALED(sysStat)) {
180 _tt_syslog( 0, LOG_ERR,
181 "libtt: system(\"%s\"): signal %d",
186 _tt_syslog( 0, LOG_ERR,
187 "libtt: system(\"%s\"): %d",
188 (char *)start_ttcmd, sysStat );
193 // Race condition -- no ttsession was
194 // found in the above code, but by the time
195 // we got around to trying to start one,
196 // another had appeared, so this one exited
200 // another ttsession discovered.
201 // Either way, loop around and connect to it
202 // after nulling _address_string to make sure
203 // we pick the address off the X server again
204 // since the new server will have a new
206 _address_string = (char *)0;
208 // Since the other ttsession was just started,
209 // let it have a chance to initialize
214 // ttsession started.
228 // Starts ttsession by executing either the hardcoded
229 // default command "ttsession -s -d <displayname>"
230 // or the command specified in TTSESSION_CMD or SUN_TTSESSION_CMD.
231 // TTSESSION_CMD and SUN_TTSESSION_CMD provide a way of overriding the
232 // standard options specified when tools auto-start
233 // ttsession. For example, to switch from Classing
234 // Engine format to xdr format for auto-start set
235 // TTSESSION_CMD or SUN_TTSESSION_CMD to "ttsession -X".
236 // The string used is returned in a parameter so c_init can use it in
241 startup_ttsession(_Tt_string &start_ttcmd)
243 // If TTSESSION_CMD or SUN_TTSESSION_CMD is specified, we use system() to run the
244 // command since it might have shell metacharacters (a common
245 // thing to do is TTSESSION_CMD or SUN_TTSESSION_CMD=truss ttsession >/tmp/trace
246 // in order to truss ttsession startup)
248 char* pc_env_value = _tt_get_first_set_env_var(2, "TTSESSION_CMD", "SUN_TTSESSION_CMD");
251 start_ttcmd = pc_env_value;
252 start_ttcmd = start_ttcmd.cat(" -d ");
253 start_ttcmd = start_ttcmd.cat(_displayname);
254 return system((char *)start_ttcmd);
256 // start_ttcmd is not really used but we set it so it can be used
258 start_ttcmd = "ttsession -s -d ";
259 start_ttcmd = start_ttcmd.cat(_displayname);
261 // This is basically a stripped down and specialized system() call...
266 #if defined(__GNUG__)
267 typedef void (*SIG_PF)(int);
269 SIG_PF istat, qstat, cstat;
274 if((pid = vfork()) == 0) {
276 (void) execlp("ttsession", "ttsession",
279 (char *)_displayname,
284 istat = signal(SIGINT, SIG_IGN);
285 qstat = signal(SIGQUIT, SIG_IGN);
286 cstat = signal(SIGCHLD, SIG_DFL);
288 w = waitpid(pid, &status, 0);
290 (void) signal(SIGINT, istat);
291 (void) signal(SIGQUIT, qstat);
292 (void) signal(SIGCHLD, cstat);
294 return((w == -1)? w: status);
299 // Invokes an rpc call on the server session that causes all of the
300 // given procid's patterns to have a session id for the current
301 // session (this allows them to begin matching messages).
303 // See _Tt_s_session::s_join for the server-side of this method.
305 Tt_status _Tt_c_session::
306 c_join(_Tt_procid_ptr &procid)
311 rstatus = call(TT_RPC_JOIN_SESSION,
312 (xdrproc_t)tt_xdr_procid,
316 return((rstatus == TT_OK) ? status : rstatus);
321 // Invokes an rpc call on the server session that causes all of the
322 // given procid's patterns to not have a session id for the current
323 // session (this prevents them from matching messages).
325 // See _Tt_s_session::s_quit for the server-side of this method.
327 Tt_status _Tt_c_session::
328 c_quit(_Tt_procid_ptr &procid)
333 rstatus = call(TT_RPC_QUIT_SESSION,
334 (xdrproc_t)tt_xdr_procid, (char *)&procid,
335 (xdrproc_t)xdr_int, (char *)&status);
336 return((rstatus == TT_OK) ? status : rstatus);