diff options
Diffstat (limited to 'kdm/backend/session.c')
-rw-r--r-- | kdm/backend/session.c | 813 |
1 files changed, 0 insertions, 813 deletions
diff --git a/kdm/backend/session.c b/kdm/backend/session.c deleted file mode 100644 index 9a12ce312..000000000 --- a/kdm/backend/session.c +++ /dev/null @@ -1,813 +0,0 @@ -/* - -Copyright 1988, 1998 The Open Group -Copyright 2000-2004 Oswald Buddenhagen <ossi@kde.org> - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from the copyright holder. - -*/ - -/* - * xdm - display manager daemon - * Author: Keith Packard, MIT X Consortium - * - * subdaemon event loop, etc. - */ - -#include "dm.h" -#include "dm_error.h" - -#include <X11/Xlib.h> -#include <X11/Xatom.h> -#include <X11/cursorfont.h> - -#include <stdio.h> -#include <ctype.h> -#include <signal.h> - -#ifdef WITH_CONSOLE_KIT -#include "consolekit.h" -#endif - -struct display *td; -const char *td_setup = "auto"; - -static void DeleteXloginResources( void ); -static void LoadXloginResources( void ); -static void SetupDisplay( const char *arg ); - - -static Jmp_buf pingTime; - -/* ARGSUSED */ -static void -catchAlrm( int n ATTR_UNUSED ) -{ - Longjmp( pingTime, 1 ); -} - -static Jmp_buf tenaciousClient; - -/* ARGSUSED */ -static void -waitAbort( int n ATTR_UNUSED ) -{ - Longjmp( tenaciousClient, 1 ); -} - -static void -AbortClient( int pid ) -{ - int sig = SIGTERM; - volatile int i; - int retId; - - for (i = 0; i < 4; i++) { - if (kill( -pid, sig ) == -1) { - switch (errno) { - case EPERM: - LogError( "Can't kill client\n" ); - case EINVAL: - case ESRCH: - return; - } - } - if (!Setjmp( tenaciousClient )) { - (void)Signal( SIGALRM, waitAbort ); - (void)alarm( (unsigned)10 ); - retId = wait( (waitType *)0 ); - (void)alarm( (unsigned)0 ); - (void)Signal( SIGALRM, SIG_DFL ); - if (retId == pid) - break; - } else - (void)Signal( SIGALRM, SIG_DFL ); - sig = SIGKILL; - } -} - - -static char * -conv_auto( int what, const char *prompt ATTR_UNUSED ) -{ - switch (what) { - case GCONV_USER: - return curuser; - case GCONV_PASS: - case GCONV_PASS_ND: - return curpass; - default: - LogError( "Unknown authentication data type requested for autologin.\n" ); - return 0; - } -} - -static void -DoAutoLogon( void ) -{ - ReStr( &curuser, td->autoUser ); - ReStr( &curpass, td->autoPass ); - ReStr( &curtype, "classic" ); - cursource = PWSRC_AUTOLOGIN; -} - -static int -AutoLogon( Time_t tdiff ) -{ - Debug( "autoLogon, tdiff = %d, rLogin = %d, goodexit = %d, nuser = %s\n", - tdiff, td->hstent->rLogin, td->hstent->goodExit, td->hstent->nuser ); - if (td->hstent->rLogin == 2 || - (td->hstent->rLogin == 1 && - tdiff <= 0 && !td->hstent->goodExit && !td->hstent->lock)) - { - curuser = td->hstent->nuser; - td->hstent->nuser = 0; - curpass = td->hstent->npass; - td->hstent->npass = 0; - newdmrc = td->hstent->nargs; - td->hstent->nargs = 0; - ReStr( &curtype, "classic" ); - cursource = (td->hstent->rLogin == 1) ? PWSRC_RELOGIN : PWSRC_MANUAL; - return 1; - } else if (*td->autoUser && !td->autoDelay && - ((tdiff > 0 && ((td->displayType & d_lifetime) == dTransient || - !td->hstent->lastExit)) || - td->autoAgain)) - { - unsigned int lmask; - Window dummy1, dummy2; - int dummy3, dummy4, dummy5, dummy6; - XQueryPointer( dpy, DefaultRootWindow( dpy ), - &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, &dummy6, - &lmask ); - if (lmask & ShiftMask) - return 0; - DoAutoLogon(); - return 1; - } - return 0; -} - - -static const struct { - int vcode, echo, ndelay; -} grqs[] = { - { V_GET_TEXT, TRUE, FALSE }, - { V_GET_TEXT, FALSE, FALSE }, - { V_GET_TEXT, TRUE, FALSE }, - { V_GET_TEXT, FALSE, FALSE }, - { V_GET_TEXT, FALSE, TRUE }, - { V_GET_BINARY, 0, 0 } -}; - -char * -conv_interact( int what, const char *prompt ) -{ - char *ret; - int tag; - - GSendInt( grqs[what].vcode ); - if (what == GCONV_BINARY) { - unsigned const char *up = (unsigned const char *)prompt; - int len = up[3] | (up[2] << 8) | (up[1] << 16) | (up[0] << 24); - GSendArr( len, prompt ); - GSendInt( FALSE ); /* ndelay */ - return GRecvArr( &len ); - } else { - GSendStr( prompt ); - GSendInt( grqs[what].echo ); - GSendInt( grqs[what].ndelay ); - ret = GRecvStr(); - if (ret) { - tag = GRecvInt(); - switch (what) { - case GCONV_USER: - /* assert(tag & V_IS_USER); */ - if (curuser) - free( curuser ); - curuser = ret; - break; - case GCONV_PASS: - case GCONV_PASS_ND: - /* assert(tag & V_IS_PASSWORD); */ - if (curpass) - free( curpass ); - curpass = ret; - break; - default: - if (tag & V_IS_USER) - ReStr( &curuser, ret ); - else if (tag & V_IS_PASSWORD) - ReStr( &curpass, ret ); - else if (tag & V_IS_NEWPASSWORD) - ReStr( &newpass, ret ); - else if (tag & V_IS_OLDPASSWORD) - ReStr( &ret, curpass ); - } - } - return ret; - } -} - -static int greeter; -GProc grtproc; -GTalk grttalk; - -GTalk mstrtalk; /* make static; see dm.c */ - -int -CtrlGreeterWait( int wreply ) -{ - int i, cmd, type, rootok; - char *name, *pass, **avptr; -#ifdef XDMCP - ARRAY8Ptr aptr; -#endif - - if (Setjmp( mstrtalk.errjmp )) { - CloseGreeter( TRUE ); - SessionExit( EX_UNMANAGE_DPY ); - } - - while (GRecvCmd( &cmd )) { - switch (cmd) - { - case G_Ready: - Debug( "G_Ready\n" ); - return 0; - case G_GetCfg: - /*Debug ("G_GetCfg\n");*/ - type = GRecvInt(); - /*Debug (" index %#x\n", type);*/ - if (type == C_isLocal) - i = (td->displayType & d_location) == dLocal; - else if (type == C_hasConsole) -#ifdef HAVE_VTS - i = *consoleTTYs != 0; -#else - i = td->console != 0; -#endif - else if (type == C_isAuthorized) - i = td->authorizations != 0; - else - goto normal; - GSendInt( GE_Ok ); - /*Debug (" -> bool %d\n", i);*/ - GSendInt( i ); - break; - normal: - if (!(avptr = FindCfgEnt( td, type ))) { - /*Debug (" -> not found\n");*/ - GSendInt( GE_NoEnt ); - break; - } - switch (type & C_TYPE_MASK) { - default: - /*Debug (" -> unknown type\n");*/ - GSendInt( GE_BadType ); - break; - case C_TYPE_INT: - case C_TYPE_STR: - case C_TYPE_ARGV: -#ifdef XDMCP - case C_TYPE_ARR: -#endif - GSendInt( GE_Ok ); - switch (type & C_TYPE_MASK) { - case C_TYPE_INT: - /*Debug (" -> int %#x (%d)\n", *(int *)avptr, *(int *)avptr);*/ - GSendInt( *(long *)avptr ); - break; - case C_TYPE_STR: - /*Debug (" -> string %\"s\n", *avptr);*/ - GSendStr( *avptr ); - break; - case C_TYPE_ARGV: - /*Debug (" -> sending argv %\"[{s\n", *(char ***)avptr);*/ - GSendArgv( *(char ***)avptr ); - break; -#ifdef XDMCP - case C_TYPE_ARR: - aptr = *(ARRAY8Ptr *)avptr; - /*Debug (" -> sending array %02[*:hhx\n", - aptr->length, aptr->data);*/ - GSendArr( aptr->length, (char *)aptr->data ); - break; -#endif - } - break; - } - break; - case G_ReadDmrc: - Debug( "G_ReadDmrc\n" ); - name = GRecvStr(); - Debug( " user %\"s\n", name ); - if (StrCmp( dmrcuser, name )) { - if (curdmrc) { free( curdmrc ); curdmrc = 0; } - if (dmrcuser) - free( dmrcuser ); - dmrcuser = name; - i = ReadDmrc(); - Debug( " -> status %d\n", i ); - GSendInt( i ); - Debug( " => %\"s\n", curdmrc ); - } else { - if (name) - free( name ); - Debug( " -> status " stringify( GE_Ok ) "\n" ); - GSendInt( GE_Ok ); - Debug( " => keeping old\n" ); - } - break; - case G_GetDmrc: - Debug( "G_GetDmrc\n" ); - name = GRecvStr(); - Debug( " key %\"s\n", name ); - pass = iniEntry( curdmrc, "Desktop", name, 0 ); - Debug( " -> %\"s\n", pass ); - GSendStr( pass ); - if (pass) - free( pass ); - free( name ); - break; -/* case G_ResetDmrc: - Debug ("G_ResetDmrc\n"); - if (newdmrc) { free (newdmrc); newdmrc = 0; } - break; */ - case G_PutDmrc: - Debug( "G_PutDmrc\n" ); - name = GRecvStr(); - Debug( " key %\"s\n", name ); - pass = GRecvStr(); - Debug( " value %\"s\n", pass ); - newdmrc = iniEntry( newdmrc, "Desktop", name, pass ); - free( pass ); - free( name ); - break; - case G_VerifyRootOK: - Debug( "G_VerifyRootOK\n" ); - rootok = TRUE; - goto doverify; - case G_Verify: - Debug( "G_Verify\n" ); - rootok = FALSE; - doverify: - if (curuser) { free( curuser ); curuser = 0; } - if (curpass) { free( curpass ); curpass = 0; } - if (curtype) free( curtype ); - curtype = GRecvStr(); - Debug( " type %\"s\n", curtype ); - cursource = PWSRC_MANUAL; - if (Verify( conv_interact, rootok )) { - Debug( " -> return success\n" ); - GSendInt( V_OK ); - } else - Debug( " -> failure returned\n" ); - break; - case G_AutoLogin: - Debug( "G_AutoLogin\n" ); - DoAutoLogon(); - if (Verify( conv_auto, FALSE )) { - Debug( " -> return success\n" ); - GSendInt( V_OK ); - } else - Debug( " -> failure returned\n" ); - break; - case G_SetupDpy: - Debug( "G_SetupDpy\n" ); - SetupDisplay( 0 ); - td_setup = 0; - GSendInt( 0 ); - break; - default: - return cmd; - } - if (!wreply) - return -1; - } - Debug( "lost connection to greeter\n" ); - return -2; -} - -void -OpenGreeter() -{ - char *name, **env; - static Time_t lastStart; - int cmd; - Cursor xcursor; - - GSet( &grttalk ); - if (greeter) - return; - if (time( 0 ) < lastStart + 10) /* XXX should use some readiness indicator instead */ - SessionExit( EX_UNMANAGE_DPY ); - greeter = 1; - ASPrintf( &name, "greeter for display %s", td->name ); - Debug( "starting %s\n", name ); - - /* Hourglass cursor */ - if ((xcursor = XCreateFontCursor( dpy, XC_watch ))) { - XDefineCursor( dpy, DefaultRootWindow( dpy ), xcursor ); - XFreeCursor( dpy, xcursor ); - } - XFlush( dpy ); - - /* Load system default Resources (if any) */ - LoadXloginResources(); - - grttalk.pipe = &grtproc.pipe; - env = systemEnv( (char *)0 ); - if (GOpen( &grtproc, (char **)0, "_greet", env, name, &td->gpipe )) - SessionExit( EX_UNMANAGE_DPY ); - freeStrArr( env ); - if ((cmd = CtrlGreeterWait( TRUE ))) { - if (cmd != -2) - LogError( "Received unknown or unexpected command %d from greeter\n", cmd ); - CloseGreeter( TRUE ); - SessionExit( EX_UNMANAGE_DPY ); - } - Debug( "%s ready\n", name ); - time( &lastStart ); -} - -int -CloseGreeter( int force ) -{ - int ret; - - if (!greeter) - return EX_NORMAL; - greeter = 0; - ret = GClose (&grtproc, 0, force); - Debug( "greeter for %s stopped\n", td->name ); - if (WaitCode( ret ) > EX_NORMAL && WaitCode( ret ) <= EX_MAX) { - Debug( "greeter-initiated session exit, code %d\n", WaitCode( ret ) ); - SessionExit( WaitCode( ret ) ); - } - return ret; -} - -void -PrepErrorGreet() -{ - if (!greeter) { - OpenGreeter(); - GSendInt( G_ErrorGreet ); - GSendStr( curuser ); - } -} - -static Jmp_buf idleTOJmp; - -/* ARGSUSED */ -static void -IdleTOJmp( int n ATTR_UNUSED ) -{ - Longjmp( idleTOJmp, 1 ); -} - - -static Jmp_buf abortSession; - -/* ARGSUSED */ -static void -catchTerm( int n ATTR_UNUSED ) -{ - Signal( SIGTERM, SIG_IGN ); - Longjmp( abortSession, EX_AL_RESERVER_DPY ); -} - -/* - * We need our own error handlers because we can't be sure what exit code Xlib - * will use, and our Xlib does exit(1) which matches EX_REMANAGE_DPY, which - * can cause a race condition leaving the display wedged. We need to use - * EX_RESERVER_DPY for IO errors, to ensure that the manager waits for the - * server to terminate. For other X errors, we should give up. - */ - -/*ARGSUSED*/ -static int -IOErrorHandler( Display *dspl ATTR_UNUSED ) -{ - LogError( "Fatal X server IO error: %m\n" ); - /* The only X interaction during the session are pings, and those - have an own IOErrorHandler -> not EX_AL_RESERVER_DPY */ - Longjmp( abortSession, EX_RESERVER_DPY ); - /*NOTREACHED*/ - return 0; -} - -/*ARGSUSED*/ -static int -ErrorHandler( Display *dspl ATTR_UNUSED, XErrorEvent *event ) -{ - LogError( "X error\n" ); - if (event->error_code == BadImplementation) - Longjmp( abortSession, EX_UNMANAGE_DPY ); - return 0; -} - -void -ManageSession( struct display *d ) -{ - int ex, cmd; - volatile int clientPid = 0; - volatile Time_t tdiff = 0; -#ifdef WITH_CONSOLE_KIT - char *ck_session_cookie; -#endif - - - td = d; - Debug( "ManageSession %s\n", d->name ); - if ((ex = Setjmp( abortSession ))) { - CloseGreeter( TRUE ); - if (clientPid) - AbortClient( clientPid ); - SessionExit( ex ); - /* NOTREACHED */ - } - (void)XSetIOErrorHandler( IOErrorHandler ); - (void)XSetErrorHandler( ErrorHandler ); - (void)Signal( SIGTERM, catchTerm ); - - (void)Signal( SIGHUP, SIG_IGN ); - - if (Setjmp( grttalk.errjmp )) - Longjmp( abortSession, EX_RESERVER_DPY ); /* EX_RETRY_ONCE */ - -#ifdef XDMCP - if (d->useChooser) - DoChoose(); - /* NOTREACHED */ -#endif - - if (d->hstent->sdRec.how) { - OpenGreeter(); - GSendInt( G_ConfShutdown ); - GSendInt( d->hstent->sdRec.how ); - GSendInt( d->hstent->sdRec.uid ); - GSendStr( d->hstent->sdRec.osname ); - if ((cmd = CtrlGreeterWait( TRUE )) != G_Ready) { - LogError( "Received unknown command %d from greeter\n", cmd ); - CloseGreeter( TRUE ); - } - goto regreet; - } - - tdiff = time( 0 ) - td->hstent->lastExit - td->openDelay; - if (AutoLogon( tdiff )) { - if (!Verify( conv_auto, FALSE )) - goto gcont; - if (greeter) - GSendInt( V_OK ); - } else { - regreet: - OpenGreeter(); - if (Setjmp( idleTOJmp )) { - CloseGreeter( TRUE ); - SessionExit( EX_NORMAL ); - } - Signal( SIGALRM, IdleTOJmp ); - alarm( td->idleTimeout ); -#ifdef XDMCP - if (((d->displayType & d_location) == dLocal) && - d->loginMode >= LOGIN_DEFAULT_REMOTE) - goto choose; -#endif - for (;;) { - Debug( "ManageSession, greeting, tdiff = %d\n", tdiff ); - GSendInt( (*td->autoUser && td->autoDelay && - (tdiff > 0 || td->autoAgain)) ? - G_GreetTimed : G_Greet ); - gcont: - cmd = CtrlGreeterWait( TRUE ); -#ifdef XDMCP - recmd: - if (cmd == G_DChoose) { - choose: - cmd = DoChoose(); - goto recmd; - } - if (cmd == G_DGreet) - continue; -#endif - alarm( 0 ); - if (cmd == G_Ready) - break; - if (cmd == -2) - CloseGreeter( FALSE ); - else { - LogError( "Received unknown command %d from greeter\n", cmd ); - CloseGreeter( TRUE ); - } - goto regreet; - } - } - - if (CloseGreeter( FALSE ) != EX_NORMAL) - goto regreet; - - DeleteXloginResources(); - - if (td_setup) - SetupDisplay( td_setup ); - -#ifdef WITH_CONSOLE_KIT - ck_session_cookie = open_ck_session (getpwnam(curuser), d); - if (!(clientPid = StartClient(ck_session_cookie))) { -#else - if (!(clientPid = StartClient())) { -#endif - LogError( "Client start failed\n" ); - SessionExit( EX_NORMAL ); /* XXX maybe EX_REMANAGE_DPY? -- enable in dm.c! */ - } - Debug( "client Started\n" ); - - /* - * Wait for session to end, - */ - for (;;) { - if (!Setjmp( pingTime )) { - (void)Signal( SIGALRM, catchAlrm ); - (void)alarm( d->pingInterval * 60 ); /* may be 0 */ - (void)Wait4( clientPid ); - (void)alarm( 0 ); - break; - } else { - (void)alarm( 0 ); - if (!PingServer( d )) - catchTerm( SIGTERM ); - } - } - -#ifdef WITH_CONSOLE_KIT - if (ck_session_cookie != NULL) { - close_ck_session (ck_session_cookie); - free (ck_session_cookie); - } -#endif - - /* - * Sometimes the Xsession somehow manages to exit before - * a server crash is noticed - so we sleep a bit and wait - * for being killed. - */ - if (!PingServer( d )) { - Debug( "X server dead upon session exit.\n" ); - if ((d->displayType & d_location) == dLocal) - sleep( 10 ); - SessionExit( EX_AL_RESERVER_DPY ); - } - SessionExit( EX_NORMAL ); /* XXX maybe EX_REMANAGE_DPY? -- enable in dm.c! */ -} - -static int xResLoaded; - -void -LoadXloginResources() -{ - char **args; - char **env; - - if (!xResLoaded && td->resources[0] && access( td->resources, 4 ) == 0) { - env = systemEnv( (char *)0 ); - if ((args = parseArgs( (char **)0, td->xrdb )) && - (args = addStrArr( args, td->resources, -1 ))) - { - Debug( "loading resource file: %s\n", td->resources ); - (void)runAndWait( args, env ); - freeStrArr( args ); - } - freeStrArr( env ); - xResLoaded = TRUE; - } -} - -void -SetupDisplay( const char *arg ) -{ - char **env; - - env = systemEnv( (char *)0 ); - (void)source( env, td->setup, arg ); - freeStrArr( env ); -} - -void -DeleteXloginResources() -{ - int i; - Atom prop; - - if (!xResLoaded) - return; - xResLoaded = FALSE; - prop = XInternAtom( dpy, "SCREEN_RESOURCES", True ); - XDeleteProperty( dpy, RootWindow( dpy, 0 ), XA_RESOURCE_MANAGER ); - if (prop) - for (i = ScreenCount(dpy); --i >= 0; ) - XDeleteProperty( dpy, RootWindow( dpy, i ), prop ); - XSync( dpy, 0 ); -} - - -int -source( char **env, const char *file, const char *arg ) -{ - char **args; - int ret; - - if (file && file[0]) { - Debug( "source %s\n", file ); - if (!(args = parseArgs( (char **)0, file ))) - return waitCompose( 0,0,3 ); - if (arg && !(args = addStrArr( args, arg, -1 ))) - return waitCompose( 0,0,3 ); - ret = runAndWait( args, env ); - freeStrArr( args ); - return ret; - } - return 0; -} - -char ** -inheritEnv( char **env, const char **what ) -{ - char *value; - - for (; *what; ++what) - if ((value = getenv( *what ))) - env = setEnv( env, *what, value ); - return env; -} - -char ** -baseEnv( const char *user ) -{ - char **env; - - env = 0; - -#ifdef _AIX - /* we need the tags SYSENVIRON: and USRENVIRON: in the call to setpenv() */ - env = setEnv( env, "SYSENVIRON:", 0 ); -#endif - - if (user) { - env = setEnv( env, "USER", user ); -#ifdef _AIX - env = setEnv( env, "LOGIN", user ); -#endif - env = setEnv( env, "LOGNAME", user ); - } - -#ifdef _AIX - env = setEnv( env, "USRENVIRON:", 0 ); -#endif - - env = inheritEnv( env, (const char **)exportList ); - - env = setEnv( env, "DISPLAY", - memcmp( td->name, "localhost:", 10 ) ? - td->name : td->name + 9 ); - - if (td->ctrl.path) - env = setEnv( env, "DM_CONTROL", fifoDir ); - - return env; -} - -char ** -systemEnv( const char *user ) -{ - char **env; - - env = baseEnv( user ); - if (td->authFile) - env = setEnv( env, "XAUTHORITY", td->authFile ); - env = setEnv( env, "PATH", td->systemPath ); - env = setEnv( env, "SHELL", td->systemShell ); - return env; -} |