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 /* $TOG: SmMain.c /main/18 1998/04/20 12:59:26 mgreess $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
26 * (c) Copyright 1993, 1994 International Business Machines Corp. *
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
28 * (c) Copyright 1993, 1994 Novell, Inc. *
30 /*************************************<+>*************************************
31 *****************************************************************************
35 ** Project: HP DT Session Manager (dtsession)
39 ** This is the controlling program for the session manager. It
40 ** calls routines to start the BMS, initialize globals and handlers,
41 ** and restore the correct session.
44 *******************************************************************
45 ** (c) Copyright Hewlett-Packard Company, 1990. All rights are
46 ** reserved. Copying or other reproduction of this program
47 ** except for archival purposes is prohibited without prior
48 ** written consent of Hewlett-Packard Company.
49 ********************************************************************
53 *****************************************************************************
54 *************************************<+>*************************************/
58 #include <X11/Intrinsic.h>
59 #include <X11/StringDefs.h>
61 #if defined (USE_X11SSEXT)
62 #include <X11/extensions/scrnsaver.h>
63 #endif /* USE_X11SSEXT */
66 #include <Dt/UserMsg.h>
67 #include <Dt/EnvControlP.h>
71 #include <DtXinerama.h> /* JET - Xinerama support */
75 #include "SmGlobals.h"
77 #include "SmRestore.h"
79 #include "SrvPalette.h"
80 #include "SmProtocol.h"
86 static void StopAll(int i);
87 static int RegisterX11ScreenSaver(Display *display, int *ssEventType);
93 #define SECURE_SYS_PATH "/.secure/etc/passwd"
96 #define SECURE_SYS_PATH "/etc/security/passwd"
99 #define SECURE_SYS_PATH "/etc/shadow"
102 #define SECURE_SYS_PATH "/etc/master.passwd"
107 /*************************************<->*************************************
114 * Controls the startup and event dispatching of the session manager.
119 * argc = command line options
120 * argv = number of command line options
130 *************************************<->***********************************/
132 main (int argc, char **argv)
138 XWindowAttributes windAtt;
139 XPropertyEvent *pEvent = (XPropertyEvent *) &next;
143 struct sigaction stopvec;
146 setlocale( LC_ALL, "" );
147 XtSetLanguageProc( NULL, NULL, NULL );
149 smGD.smState = IN_PROCESS;
150 smGD.programName = strdup (argv[0]);
152 /* JET - By default, we always want to leave when SmExit() is called. */
153 smGD.ExitComplete = True;
156 * We report some errors before we call the DtInitialize procedure.
157 * The Dt initialize procedure sets this name. If we report
158 * an error via DtSimple error before this is set we see the message
159 * prepended with <unknown program name> in the error log.
161 DtProgName = SM_RESOURCE_NAME ;
174 * Set our effective gid to the real gid until we need it to be
175 * sys (during contention management)
177 smGD.runningGID = getgid();
178 smGD.conMgmtGID = getegid();
181 * Set uid up according to whether this is a secure system
182 * Secure systems need root privileges to read the /etc/passwd file
184 smGD.runningUID = getuid();
186 #ifdef linux /* linux always needs to be setup as secure */
189 * Save the root privilege to be restored when trying to unlock
191 smGD.unLockUID = geteuid();
192 smGD.secureSystem = True;
193 SM_SETEUID(smGD.runningUID);
197 # ifdef SECURE_SYS_PATH
198 status = stat(SECURE_SYS_PATH, &buf);
206 * this is not a secure system - remove all suid privileges
208 smGD.unLockUID = smGD.runningUID;
209 smGD.secureSystem = False;
210 SM_SETESUID(smGD.runningUID);
215 * Save the root privilege to be restored when trying to unlock
217 smGD.unLockUID = geteuid();
218 smGD.secureSystem = True;
219 SM_SETEUID(smGD.runningUID);
225 * Initialize LANG if it isn't defined.
227 if ((lang = getenv ("LANG")) == NULL)
230 (void) strcpy (lang, "LANG=C");
231 (void) putenv (lang);
235 setresgid(-1, smGD.runningGID, -1);
236 #else /* _AIX or any other system */
238 setregid(smGD.conMgmtGID, smGD.runningGID);
240 setgid(smGD.conMgmtGID);
241 setegid(smGD.runningGID);
246 * Set up POSIX sigaction structs
250 * Must set SIGPIPE to SIG_IGN so the process does not exit
251 * if a child terminates unexpectedly during an I/O operation
252 * that raises SIGPIPE. Note that before this process exec's
253 * any subprocesses, SIGPIPE must be set to SIG_DFL.
255 sigemptyset(&stopvec.sa_mask);
256 stopvec.sa_flags = 0;
257 stopvec.sa_handler = SIG_IGN;
258 (void) sigaction(SIGPIPE, &stopvec, (struct sigaction *) NULL);
260 stopvec.sa_handler = StopAll;
261 sigemptyset(&stopvec.sa_mask);
262 stopvec.sa_flags = 0;
264 smGD.childvec.sa_handler = WaitChildDeath;
265 sigemptyset(&smGD.childvec.sa_mask);
266 smGD.childvec.sa_flags = 0;
268 smGD.defvec.sa_handler = SIG_DFL;
269 sigemptyset(&smGD.defvec.sa_mask);
270 smGD.defvec.sa_flags = 0;
276 * This must be done before XtToolkitInitialize
277 * to set up the local environment
279 _DtEnvControl(DT_ENV_SET);
280 _DtEnvControl(DT_ENV_SET_BIN);
283 * Set up NLS error messages first
288 * Set the paths of where resources are to be restored from
290 SetRestorePath(argc, argv);
293 * The first thing that must happen is that resources must be restored
294 * so that my resources will be correct
296 if(smGD.compatMode == False)
299 * Load session resources.
301 RestoreResources(False,
305 smGD.resourcePath[0] != '\0' ? "-file" : NULL,
311 * Set up to catch SIGTERM
313 stopvec.sa_handler = StopAll;
314 sigemptyset(&stopvec.sa_mask);
315 stopvec.sa_flags = 0;
317 sigaction(SIGTERM, &stopvec, (struct sigaction *) NULL);
320 * Now set up a communication with the toolkit
322 * Create one display connection for dtsession, and one for
323 * the color server. We cannot share a display connection since
324 * motif creates a display object for the color server's display during
325 * color server initialization. Since the color server is not yet
326 * operational, any dialogs (ie the dtsession logout confirmation
327 * dialogs) created on that display do not get the color server colors.
328 * The dtsession display object is created after color server
329 * initialization is complete.
331 if (smGD.appCon == 0) {
333 * The following code will have been initialized if the
334 * session creation code posted a dialog.
336 XtToolkitInitialize();
337 smGD.appCon = XtCreateApplicationContext();
338 smGD.display = XtOpenDisplay(smGD.appCon, NULL, argv[0],
340 NULL, 0, &argc, argv);
343 srvDisplay = XtOpenDisplay(smGD.appCon, NULL, argv[0], SM_RESOURCE_CLASS,
344 NULL, 0, &argc, argv);
349 if (!InitXSMP (argv[0]))
352 /* Added the following check to exit in case of error RK 09.08.93 */
353 if(smGD.display == NULL)
355 PrintError(DtError, GETMESSAGE(4, 1, "Invalid display name - exiting."));
360 * Lock out other session managers from running - if there is one
361 * running already - exit
363 if(!_DtGetLock(smGD.display, SM_RUNNING_LOCK))
365 PrintError(DtError, GETMESSAGE(2, 2, "Another dtsession is currently running - exiting."));
369 /* JET - initialize for Xinerama, if present 4/12/2001 */
371 smGD.DtXineramaInfo = _DtXineramaInit(smGD.display);
374 if (smGD.DtXineramaInfo == NULL)
375 { /* No xinerama, how... sad. */
376 fprintf(stderr, "### JET SmMain: Xinerama NOT available.\n");
380 fprintf(stderr, "### JET SmMain: Xinerama available, scrns = %d\n",
381 dpyinfo.DtXineramaInfo->numscreens);
389 * Restore preferences
391 if (smGD.resourcePath[0] != '\0')
393 RestorePreferences(smGD.resourcePath);
397 * Start up the color server
399 InitializeDtcolor(srvDisplay, smGD.sessionType);
402 * AFTER the colors are set up - create the top level widget
403 * Set up a NULL WM_COMMAND property
406 XtSetArg(args[n], XmNbackground,
407 XBlackPixel(smGD.display, XDefaultScreen(smGD.display))); n++;
408 XtSetArg(args[n], XmNmappedWhenManaged, False); n++;
409 XtSetArg (args[n], XmNwidth, 1); n++;
410 XtSetArg (args[n], XmNheight, 1); n++;
411 smGD.topLevelWid = XtAppCreateShell (SM_RESOURCE_NAME, SM_RESOURCE_CLASS,
412 applicationShellWidgetClass,
413 smGD.display, args, n);
414 XtRealizeWidget(smGD.topLevelWid);
417 * Select to get the lock on timeout if the user requests it
418 * and if the server supports it. This must be done before
419 * InitSMGlobals() so smGD.lockOnTimeoutStatus is known.
421 #if defined (USE_HPSSEXT)
422 #ifdef USE_HP_SPECIFIC_XLIB
423 tmp = XHPSSChangeNotify(smGD.display, &XaSmScreenSaveRet, 3);
424 #else /* USE_HP_SPECIFIC_XLIB */
426 #endif /* USE_HP_SPECIFIC_XLIB */
427 #elif defined (USE_X11SSEXT)
428 tmp = RegisterX11ScreenSaver(smGD.display, &smGD.ssEventType);
435 smGD.lockOnTimeoutStatus = False;
436 XaSmScreenSaveRet = None;
437 #if defined (USE_X11SSEXT)
438 smGD.ssEventType = None;
443 smGD.lockOnTimeoutStatus = True;
449 * Put the program into a wait state
456 * Restore resources for lang/resolution independence
458 if((smGD.resourcePath[0] != 0) || (smGD.compatMode == False))
460 RestoreIndependentResources();
464 * Now restore the rest of the clients and the settings
466 if((smGD.clientPath[0] != 0) && (smGD.compatMode == False))
468 if(RestoreState() == -1)
475 if(smGD.compatMode == True)
478 * dtstyle needs the DT_SESSION_STATE even in
487 * Run the user's startup script if there is one
490 if(smGD.compatMode == False)
492 StartEtc(False); /* run sessionetc */
498 * If we are in compatibility mode - kill the parent and leave the
499 * child running so that the script exits
501 if(smGD.compatMode == True)
507 * Select for property notify on the top level window - so that
508 * when the style manager changes something - it is known
510 XGetWindowAttributes(smGD.display, smGD.topLevelWindow, &windAtt);
511 XSelectInput(smGD.display, smGD.topLevelWindow,
512 windAtt.your_event_mask | PropertyChangeMask);
514 ShowWaitState(False);
517 * Register for events
518 * - PropertyChange (maskable)
519 * - ClientMessage (non-maskable)
521 XtAddEventHandler(smGD.topLevelWid,
523 True, ProcessEvent, NULL);
525 smGD.smState = READY;
529 XtAppNextEvent(smGD.appCon, &next);
532 #if defined (USE_X11SSEXT)
533 if (next.type == smGD.ssEventType)
536 * We should simply be calling XtDispatchEvent() but the toolkit
537 * doesn't seem to know how to dispatch a run-time generated
540 ProcessEvent(smGD.topLevelWid, NULL, &next, NULL);
544 XtDispatchEvent(&next);
547 XtDispatchEvent(&next);
556 /*************************************<->*************************************
563 * Signal handler for SIGTERM. Causes dtsession to do a normal shutdown
564 * procedure without saving any state.
569 * shutDown (state flag)
579 * We want to be careful to ignore the TERM signal if we are already
580 * shutting down when it occurs.
582 *************************************<->***********************************/
587 ImmediateExit(-1, 0, True);
590 /*************************************<->*************************************
592 * RegisterX11ScreenSaver
597 * Register with X11 screen saver server extension for screen saver events.
601 * display - display from XtOpenDisplay()
602 * pssEventType - pointer to buffer in which to return ss event type
606 * pssEventType - (rc=0) screen saver event type, (rc!=0) undefined
610 * 0 - successfully registered for screen saver events
611 * other - failed to register for screen saver events
616 *************************************<->***********************************/
618 #if defined (USE_X11SSEXT)
620 RegisterX11ScreenSaver(
625 * Register with X11 screen saver server extension.
636 if (XScreenSaverQueryExtension(display, pssEventType, &ssErrorBase) &&
637 XScreenSaverQueryVersion(display, &majorVersion, &minorVersion) &&
641 * Server supports requested version of X11 screen saver extension.
643 screen = DefaultScreen(display);
644 root = DefaultRootWindow(display);
646 XGrabServer(display);
647 if (!XScreenSaverGetRegistered(display, screen, &xid, &type))
650 * No other clients registered with this server so register this one.
652 XScreenSaverRegister(display, screen, XtWindow(smGD.topLevelWid), XA_WINDOW);
655 XUngrabServer(display);
659 XSetWindowAttributes attr;
662 * Registration successful.
664 XScreenSaverSelectInput(display, root,
665 ScreenSaverNotifyMask|ScreenSaverCycleMask);
667 /* Even though OverrideRedirect is the default attribute in this
668 * check, lets make sure it's set, and make sure only the
669 * CWOverrideRedirect attr is being looked at. The rest is
670 * just random garbage anyway, since it's allocated from the stack.
672 attr.override_redirect = True;
673 XScreenSaverSetAttributes(display, root, 0, 0, 1, 1, 0, CopyFromParent,
674 CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr);
679 #endif /* USE_X11SSEXT */