Fix dttypes for BSD systems
[oweals/cde.git] / cde / programs / dtsession / SmMain.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 librararies 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 /* $TOG: SmMain.c /main/18 1998/04/20 12:59:26 mgreess $ */
24 /*                                                                      *
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.                                *
29  */
30 /*************************************<+>*************************************
31  *****************************************************************************
32  **
33  **  File:        SmMain.c
34  **
35  **  Project:     HP DT Session Manager (dtsession)
36  **
37  **  Description:
38  **  -----------
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.
42  **
43  **
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  ********************************************************************
50  **
51  **
52  **
53  *****************************************************************************
54  *************************************<+>*************************************/
55
56 #include <stdio.h>
57 #include <locale.h>
58 #ifdef __osf__
59 #include <sys/access.h>
60 #endif
61 #include <X11/Intrinsic.h>
62 #include <X11/StringDefs.h>
63
64 #if defined (USE_X11SSEXT)
65 #include <X11/extensions/scrnsaver.h>
66 #endif /* USE_X11SSEXT */
67
68 #include <Xm/Xm.h>
69 #include <Dt/UserMsg.h>
70 #include <Dt/EnvControlP.h>
71 #include <Dt/DtP.h>
72 #include <Dt/Lock.h>
73 #include "Sm.h"
74 #include "SmError.h"
75 #include "SmGlobals.h"
76 #include "SmCommun.h"
77 #include "SmRestore.h"
78 #include "SmUI.h"
79 #include "SrvPalette.h"
80 #include "SmProtocol.h"
81 #include "SmXSMP.h"
82
83 /*
84  * Internal Functions
85  */
86 static void StopAll(int i);
87 static int RegisterX11ScreenSaver(Display *display, int *ssEventType);
88
89 /*
90  * Internal Defines
91  */
92 #ifdef __hpux
93 #define SECURE_SYS_PATH "/.secure/etc/passwd"
94 #endif
95 #ifdef _AIX
96 #define SECURE_SYS_PATH "/etc/security/passwd"
97 #endif
98 #ifdef SVR4
99 #define SECURE_SYS_PATH "/etc/shadow"
100 #endif
101
102
103 \f
104 /*************************************<->*************************************
105  *
106  *  main (argc, argv)
107  *
108  *
109  *  Description:
110  *  -----------
111  *  Controls the startup and event dispatching of the session manager.
112  *
113  *
114  *  Inputs:
115  *  ------
116  *  argc = command line options
117  *  argv = number of command line options
118  *
119  *
120  *  Outputs:
121  *  -------
122  *
123  *
124  *  Comments:
125  *  --------
126  *
127  *************************************<->***********************************/
128 int
129 main (int argc, char **argv)
130 {
131     int                         n, tmp;
132     Arg                         args[10];
133     XEvent                      next;
134     String                      tmpString;
135     XWindowAttributes           windAtt;
136     XPropertyEvent              *pEvent = (XPropertyEvent *) &next;
137     int                         status;
138     struct stat                 buf;
139     Display                     *srvDisplay;
140     struct sigaction            stopvec;
141     char                        *lang;
142
143 #ifdef __osf__
144
145 # include <sys/sysinfo.h>
146 # include <sys/proc.h>
147
148     unsigned long        op;
149     int                  buffer[2];
150     unsigned long        nbytes = 1;
151     char*                arg = 0;
152     unsigned long        flag = 0;
153
154     int                  ssi_status;
155
156     op = SSI_NVPAIRS;
157
158     buffer[0] = SSIN_UACPROC;
159     buffer[1] =  UAC_NOPRINT;
160 # ifdef DEBUG_UAC
161     buffer[1] |= UAC_SIGBUS;
162 # endif
163
164     ssi_status = setsysinfo ( op, buffer, nbytes, arg, flag );
165 #endif
166
167     setlocale( LC_ALL, "" );
168     XtSetLanguageProc( NULL, NULL, NULL );
169
170     smGD.smState = IN_PROCESS;
171     smGD.programName = strdup (argv[0]);
172
173     /* JET - By default, we always want to leave when SmExit() is called. */
174     smGD.ExitComplete = True;
175
176     /*
177      * We report some errors before we call the DtInitialize procedure.
178      * The Dt initialize procedure sets this name.  If we report
179      * an error via DtSimple error before this is set we see the message
180      * prepended with <unknown program name> in the error log.
181      */
182     DtProgName = SM_RESOURCE_NAME ;
183     
184 #ifdef DEBUG
185     if(argc > 5)
186     {
187         int junk = 1;
188         while(junk)
189         {
190            junk = 1;
191         }
192     }
193 #endif /*  DEBUG */
194     /*
195      * Set our effective gid to the real gid until we need it to be
196      * sys (during contention management)
197      */
198     smGD.runningGID = getgid();
199     smGD.conMgmtGID = getegid();
200
201     /*
202      * Set uid up according to whether this is a secure system
203      * Secure systems need root priviledges to read the /etc/passwd file
204      */
205     smGD.runningUID = getuid();
206
207 #ifdef linux                    /* linux always needs to be setup as secure */
208
209     /*
210      * Save the root priviledge to be restored when trying to unlock
211      */
212     smGD.unLockUID = geteuid();
213     smGD.secureSystem = True;
214     SM_SETEUID(smGD.runningUID);
215     
216 #else
217
218 # ifdef SECURE_SYS_PATH
219     status = stat(SECURE_SYS_PATH, &buf);
220 # else
221     status = -1;
222 # endif
223
224     if(status == -1)
225     {
226         /*
227          * this is not a secure system - remove all suid priviledges
228          */
229         smGD.unLockUID = smGD.runningUID;
230         smGD.secureSystem = False;
231         SM_SETESUID(smGD.runningUID);
232     }
233     else
234     {
235        /*
236         * Save the root priviledge to be restored when trying to unlock
237         */
238         smGD.unLockUID = geteuid();
239         smGD.secureSystem = True;
240         SM_SETEUID(smGD.runningUID);
241     }
242
243 #endif /* linux */
244
245     /*
246      * Initialize LANG if it isn't defined.
247      */
248     if ((lang = getenv ("LANG")) == NULL)
249     {
250         lang = XtMalloc (7);
251         (void) strcpy (lang, "LANG=C");
252         (void) putenv (lang);
253     }
254
255 #ifdef __hpux
256     setresgid(-1, smGD.runningGID, -1);
257 #else  /* _AIX or any other system */
258 #ifndef SVR4
259     setregid(smGD.conMgmtGID, smGD.runningGID);
260 #else
261     setgid(smGD.conMgmtGID);
262     setegid(smGD.runningGID);
263 #endif
264 #endif /* !hpux */
265
266    /*
267     * Set up POSIX sigaction structs
268     */
269
270     /*
271      * Must set SIGPIPE to SIG_IGN so the process does not exit
272      * if a child terminates unexpectedly during an I/O operation
273      * that raises SIGPIPE.  Note that before this process exec's
274      * any subprocesses, SIGPIPE must be set to SIG_DFL.
275      */
276     sigemptyset(&stopvec.sa_mask);
277     stopvec.sa_flags = 0;
278     stopvec.sa_handler = SIG_IGN;
279     (void) sigaction(SIGPIPE, &stopvec, (struct sigaction *) NULL);
280
281     stopvec.sa_handler = StopAll;
282     sigemptyset(&stopvec.sa_mask);
283     stopvec.sa_flags = 0;
284  
285     smGD.childvec.sa_handler = WaitChildDeath;
286     sigemptyset(&smGD.childvec.sa_mask);
287     smGD.childvec.sa_flags = 0;
288
289     smGD.defvec.sa_handler = SIG_DFL;
290     sigemptyset(&smGD.defvec.sa_mask);
291     smGD.defvec.sa_flags = 0;
292
293     smGD.appCon = 0;
294     smGD.display = 0;
295
296     /*
297      * This must be done before XtToolkitInitialize
298      * to set up the local environment
299      */
300     _DtEnvControl(DT_ENV_SET);
301     _DtEnvControl(DT_ENV_SET_BIN);
302
303     /*
304      * Set up NLS error messages first
305      */
306     InitNlsStrings();
307
308     /*
309      * Set the paths of where resources are to be restored from
310      */
311     SetRestorePath(argc, argv);
312
313     /*
314      * The first thing that must happen is that resources must be restored
315      * so that my resources will be correct
316      */
317     if(smGD.compatMode == False)
318     {
319      /*
320       * Load session resources.
321       */
322       RestoreResources(False,
323                        "-load",
324                        "-system",
325                        "-xdefaults",
326                        smGD.resourcePath[0] != '\0' ? "-file" : NULL,
327                        smGD.resourcePath,
328                        NULL);
329     }
330
331     /*
332      * Set up to catch SIGTERM
333      */
334     stopvec.sa_handler = StopAll;
335     sigemptyset(&stopvec.sa_mask);
336     stopvec.sa_flags = 0;
337
338     sigaction(SIGTERM, &stopvec, (struct sigaction *) NULL);
339
340     /*
341      * Now set up a communication with the toolkit
342      *
343      * Create one display connection for dtsession, and one for
344      * the color server. We cannot share a display connection since
345      * motif creates a display object for the color server's display during
346      * color server initialization. Since the color server is not yet 
347      * operational, any dialogs (ie the dtsession logout confirmation
348      * dialogs) created on that display do not get the color server colors. 
349      * The dtsession display object is created after color server
350      * initialization is complete.
351      */
352     if (smGD.appCon == 0) {
353         /*
354          * The following code will have been initialized if the
355          * session creation code posted a dialog.
356          */
357         XtToolkitInitialize();
358         smGD.appCon = XtCreateApplicationContext();
359         smGD.display = XtOpenDisplay(smGD.appCon, NULL, argv[0], 
360                                 SM_RESOURCE_CLASS,
361                                 NULL, 0, &argc, argv);
362     }
363
364     srvDisplay = XtOpenDisplay(smGD.appCon, NULL, argv[0], SM_RESOURCE_CLASS,
365                                  NULL, 0, &argc, argv);
366
367     /*
368      * Initialize XSMP 
369      */
370     if (!InitXSMP (argv[0]))
371         SM_EXIT(-1);
372
373     /* Added the following check to exit in case of error RK 09.08.93 */
374     if(smGD.display == NULL)
375     {
376         PrintError(DtError, GETMESSAGE(4, 1, "Invalid display name - exiting."));
377         SM_EXIT(-1);
378     }
379
380     /*
381      * Lock out other session managers from running - if there is one
382      * running already - exit
383      */
384     if(!_DtGetLock(smGD.display, SM_RUNNING_LOCK))
385     {
386         PrintError(DtError, GETMESSAGE(2, 2, "Another dtsession is currently running - exiting."));
387         SM_EXIT(-1);
388     }
389
390    /*
391     * Restore preferences
392     */
393     if (smGD.resourcePath[0] != '\0')
394     {
395       RestorePreferences(smGD.resourcePath);
396     }
397
398     /*
399      * Start up the color server
400      */
401     InitializeDtcolor(srvDisplay, smGD.sessionType);
402
403     /*
404      * AFTER the colors are set up - create the top level widget
405      * Set up a NULL WM_COMMAND property
406      */
407     n = 0;
408     XtSetArg(args[n], XmNbackground,
409              XBlackPixel(smGD.display, XDefaultScreen(smGD.display))); n++;
410     XtSetArg(args[n], XmNmappedWhenManaged, False); n++;
411     XtSetArg (args[n], XmNwidth, 1); n++;
412     XtSetArg (args[n], XmNheight, 1); n++;
413     smGD.topLevelWid = XtAppCreateShell (SM_RESOURCE_NAME, SM_RESOURCE_CLASS,
414                                          applicationShellWidgetClass,
415                                          smGD.display, args, n);
416     XtRealizeWidget(smGD.topLevelWid);
417
418     /*
419      * Select to get the lock on timeout if the user requests it
420      * and if the server supports it. This must be done before
421      * InitSMGlobals() so smGD.lockOnTimeoutStatus is known.
422      */
423 #if defined (USE_HPSSEXT)
424 #ifdef USE_HP_SPECIFIC_XLIB
425     tmp = XHPSSChangeNotify(smGD.display, &XaSmScreenSaveRet, 3);
426 #else /* USE_HP_SPECIFIC_XLIB */
427     tmp = -1;
428 #endif /* USE_HP_SPECIFIC_XLIB */
429 #elif defined (USE_X11SSEXT)
430     tmp = RegisterX11ScreenSaver(smGD.display, &smGD.ssEventType);
431 #else
432     tmp = -1;
433 #endif
434
435     if(tmp != 0)
436     {
437         smGD.lockOnTimeoutStatus = False;
438         XaSmScreenSaveRet = None;
439 #if defined (USE_X11SSEXT)
440         smGD.ssEventType = None;
441 #endif
442     }
443     else
444     {
445         smGD.lockOnTimeoutStatus = True;
446     }
447
448     InitSMGlobals();
449
450     /*
451      * Put the program into a wait state
452      */
453     ShowWaitState(True);
454
455     InitErrorHandler();
456
457     /*
458      * Restore resources for lang/resolution independence
459      */
460     if((smGD.resourcePath[0] != 0) || (smGD.compatMode == False))
461     {
462         RestoreIndependentResources();
463     }
464
465     /*
466      * Now restore the rest of the clients and the settings
467      */
468     if((smGD.clientPath[0] != 0) && (smGD.compatMode == False))
469     {
470         if(RestoreState() == -1)
471         {
472             StartWM();
473         }
474     }
475     else
476     {
477         if(smGD.compatMode == True)
478         {
479             /*
480              * dtstyle needs the DT_SESSION_STATE  even in
481              * compatibility mode
482              */
483             SetCompatState();
484         }
485         StartWM();
486     }
487
488     /* 
489      * Run the user's startup script if there is one
490      */
491
492     if(smGD.compatMode == False)
493     {
494         StartEtc(False); /* run sessionetc */
495     }
496
497     InitProtocol ();
498
499     /*
500      * If we are in compatibility mode - kill the parent and leave the
501      * child running so that the script exits
502      */
503     if(smGD.compatMode == True)
504     {
505         KillParent();
506     }
507
508     /*
509      * Select for property notify on the top level window - so that
510      * when the style manager changes something - it is known
511      */
512     XGetWindowAttributes(smGD.display, smGD.topLevelWindow, &windAtt);
513     XSelectInput(smGD.display, smGD.topLevelWindow,
514                  windAtt.your_event_mask | PropertyChangeMask);
515
516     ShowWaitState(False);
517
518     /*
519      * Register for events
520      * - PropertyChange (maskable)
521      * - ClientMessage (non-maskable)
522      */
523     XtAddEventHandler(smGD.topLevelWid,
524                       PropertyChangeMask,
525                       True, ProcessEvent, NULL);
526
527     smGD.smState = READY;
528
529 #ifdef __osf__
530     /* If we've just populated a new .dtprofile into the user's home
531      * directory, put up a popup dialog explaining the need to edit it
532      * to allow .login/.profile to work properly
533      */
534
535     arg = getenv("DTNEWPROFILE");
536     if (arg)
537         WarnNewProfile();
538 #endif
539
540     while(1)
541     {
542       XtAppNextEvent(smGD.appCon, &next);
543       if (next.type != 0)
544       {
545 #if defined (USE_X11SSEXT)
546         if (next.type == smGD.ssEventType)
547         {
548          /*
549           * We should simply be calling XtDispatchEvent() but the toolkit
550           * doesn't seem to know how to dispatch a run-time generated
551           * event type.
552           */
553           ProcessEvent(smGD.topLevelWid, NULL, &next, NULL);
554         }
555         else
556         {
557           XtDispatchEvent(&next);
558         }
559 #else
560         XtDispatchEvent(&next);
561 #endif
562       }
563     }
564 }
565
566
567
568 \f
569 /*************************************<->*************************************
570  *
571  *  StopAll
572  *
573  *
574  *  Description:
575  *  -----------
576  *  Signal handler for SIGTERM. Causes dtsession to do a normal shutdown
577  *  procedure without saving any state.
578  *
579  *
580  *  Inputs:
581  *  ------
582  *  shutDown (state flag)
583  *
584  *
585  *  Outputs:
586  *  -------
587  *
588  *
589  *  Comments:
590  *  --------
591  *
592  *  We want to be careful to ignore the TERM signal if we are already
593  *  shutting down when it occurs.
594  *
595  *************************************<->***********************************/
596
597 static void
598 StopAll(int i)
599 {
600     ImmediateExit(-1, 0, True);
601 }
602
603 /*************************************<->*************************************
604  *
605  *  RegisterX11ScreenSaver
606  *
607  *
608  *  Description:
609  *  -----------
610  *  Register with X11 screen saver server extension for screen saver events. 
611  *
612  *  Inputs:
613  *  ------
614  *  display - display from XtOpenDisplay()
615  *  pssEventType - pointer to buffer in which to return ss event type
616  *
617  *  Outputs:
618  *  -------
619  *  pssEventType - (rc=0) screen saver event type, (rc!=0) undefined
620  *
621  *  Returns:
622  *  -------
623  *  0 - successfully registered for screen saver events
624  *  other - failed to register for screen saver events
625  *
626  *  Comments:
627  *  --------
628  *
629  *************************************<->***********************************/
630
631 #if defined (USE_X11SSEXT)
632 static int
633 RegisterX11ScreenSaver(
634   Display *display,
635   int *pssEventType)
636 {
637  /*
638   * Register with X11 screen saver server extension.
639   */
640   int result = -1;
641   int ssErrorBase;
642   int majorVersion;
643   int minorVersion;
644   int screen;
645   Window root;
646   XID xid;
647   XSetWindowAttributes attr;
648   Atom type;
649
650   if (XScreenSaverQueryExtension(display, pssEventType, &ssErrorBase) &&
651       XScreenSaverQueryVersion(display, &majorVersion, &minorVersion) &&
652       majorVersion == 1)
653   {
654    /*
655     * Server supports requested version of X11 screen saver extension.
656     */
657     screen = DefaultScreen(display);
658     root = DefaultRootWindow(display);
659    
660     XGrabServer(display);
661     if (!XScreenSaverGetRegistered(display, screen, &xid, &type))
662     {
663      /* 
664       * No other clients registered with this server so register this one.
665       */
666       XScreenSaverRegister(display, screen, XtWindow(smGD.topLevelWid), XA_WINDOW);
667       result = 0;
668     }
669     XUngrabServer(display);
670
671     if (result == 0)
672     {
673      /* 
674       * Registration successful.
675       */
676       XScreenSaverSelectInput(display, root, 
677                               ScreenSaverNotifyMask|ScreenSaverCycleMask);
678       XScreenSaverSetAttributes(display, root, 0, 0, 1, 1, 0, CopyFromParent,
679                           CopyFromParent, CopyFromParent, CWBackPixel, &attr);
680     }
681   }
682   return(result);   
683 }
684 #endif /* USE_X11SSEXT */
685