现在的位置: 首页 > 综合 > 正文

GDM-2.20.1自动登录流程分析

2014年02月02日 ⁄ 综合 ⁄ 共 8539字 ⁄ 字号 评论关闭

先观察/daemon/gdm-daemon-config-keys.h中代码:

 

 

/* BEGIN LEGACY KEYS */
#define GDM_KEY_CHOOSER "daemon/Chooser=" LIBEXECDIR "/gdmchooser"
#define GDM_KEY_AUTOMATIC_LOGIN_ENABLE "daemon/AutomaticLoginEnable=false"
#define GDM_KEY_AUTOMATIC_LOGIN "daemon/AutomaticLogin="

 

 

说明是根据这个头文件来定义custom.conf中对应的自动登录配置。

gdm.c开始调用。

 

gdm.c
int main (int argc, char *argv[])

        CODE:
        /* Init XDMCP if applicable */
        if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP) && ! gdm_wait_for_go) {
                gdm_xdmcp_init ();
        }

        create_connections ();

        /* make sure things (currently /tmp/.ICE-unix and /tmp/.X11-unix)
         * are sane */
        gdm_ensure_sanity () ;

        /* Make us a unique global cookie to authenticate */
        gdm_make_global_cookie ();

        /* Start static X servers */
        gdm_start_first_unborn_local (0 /* delay */);     // 登录开始

        /* Accept remote connections */
        if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP) && ! gdm_wait_for_go) {
                g_debug ("Accepting XDMCP connections...");
                gdm_xdmcp_run ();
        }

        /* We always exit via exit (), and sadly we need to g_main_quit ()
         * at times not knowing if it's this main or a recursive one we're
         * quitting.
         */
        while (1)
                {
                        g_main_loop_run (main_loop);
                        g_debug ("main: Exited main loop");
                }

        return EXIT_SUCCESS;    /* Not reached */     // 登录完成!

->
gdm.c
static void gdm_start_first_unborn_local (int delay);

->
display.c
gboolean gdm_display_manage (GdmDisplay *d);

->
display.c 
void gdm_slave_start (GdmDisplay *d); // 通过"/sbin/runlevel"得到运行级别

->
slave.c
static void   gdm_slave_run (GdmDisplay *display);

        CODE:            // 判断是否自动登录,并获得登录账户
                const char *automaticlogin = gdm_daemon_config_get_value_string (GDM_KEY_AUTOMATIC_LOGIN);
                const char *timedlogin     = gdm_daemon_config_get_value_string (GDM_KEY_TIMED_LOGIN);

                if (gdm_daemon_config_get_value_bool (GDM_KEY_AUTOMATIC_LOGIN_ENABLE) &&
                    ! ve_string_empty (automaticlogin)) {
                        g_free (ParsedAutomaticLogin);
                        ParsedAutomaticLogin = gdm_slave_parse_enriched_login (display,
                                                                               automaticlogin);
                    }

                if (gdm_daemon_config_get_value_bool (GDM_KEY_TIMED_LOGIN_ENABLE) &&
                    ! ve_string_empty (timedlogin)) {
                        g_free (ParsedTimedLogin);
                        ParsedTimedLogin = gdm_slave_parse_enriched_login (display,
                                                                           timedlogin);
                    }

        CODE:            // 如果为自动登录直接调用gdm_slave_session_start ()函数
               if ( ! d->handled) {
                /* yay, we now wait for the server to die */
                while (d->servpid > 0) {
                        pause ();
                }
                gdm_slave_quick_exit (DISPLAY_REMANAGE);
        } else if (d->use_chooser) {
                /* this usually doesn't return */
                gdm_slave_chooser ();  /* Run the chooser */
                return;
        } else if (d->type == TYPE_STATIC &&
                   gdm_first_login &&
                   ! ve_string_empty (ParsedAutomaticLogin) &&
                   strcmp (ParsedAutomaticLogin, gdm_root_user ()) != 0) {
                gdm_first_login = FALSE;

                d->logged_in = TRUE;
                gdm_slave_send_num (GDM_SOP_LOGGED_IN, TRUE);
                gdm_slave_send_string (GDM_SOP_LOGIN, ParsedAutomaticLogin);

                if (setup_automatic_session (d, ParsedAutomaticLogin)) {
                        gdm_slave_session_start ();
                }

                gdm_slave_send_num (GDM_SOP_LOGGED_IN, FALSE);
                d->logged_in = FALSE;
                gdm_slave_send_string (GDM_SOP_LOGIN, "");
                logged_in_uid = -1;
                logged_in_gid = -1;

                gdm_debug ("gdm_slave_run: Automatic login done");

                if (remanage_asap) {
                        gdm_slave_quick_exit (DISPLAY_REMANAGE);
                }

                /* return to gdm_slave_start so that the server
                 * can be reinitted and all that kind of fun stuff. */
                return;
        }

->
slave.c
static void  gdm_slave_session_start (void);// 获取用户ID,组ID。

        CODE:                                  // 通过 $HOME/.dmrc 设定用户语言,键盘,以及Session。
        if G_LIKELY (home_dir_ok) {           
                /* Sanity check on ~user/.dmrc */
                usrcfgok = gdm_file_check ("gdm_slave_session_start", pwent->pw_uid,
                                           home_dir, ".dmrc", TRUE, FALSE,
                                           gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE),
                                           gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM));
        } else {
                usrcfgok = FALSE;
        }

        if G_LIKELY (usrcfgok) {
                gdm_daemon_config_get_user_session_lang (&usrsess, &usrlang, home_dir, &savesess);
        } else {
                /* This won't get displayed if the .dmrc file simply doesn't
                 * exist since we pass absentok=TRUE when we call gdm_file_check
                 */
                gdm_errorgui_error_box (d,
                               GTK_MESSAGE_WARNING,
                               _("User's $HOME/.dmrc file is being ignored.  "
                                 "This prevents the default session "
                                 "and language from being saved.  File "
                                 "should be owned by user and have 644 "
                                 "permissions.  User's $HOME directory "
                                 "must be owned by user and not writable "
                                 "by other users."));
                usrsess = g_strdup ("");
                usrlang = g_strdup ("");
        }

        CODE:                                  // 调用登录子函数。
        switch (pid) {

        case -1:
                gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Error forking user session"), "gdm_slave_session_start");

        case 0:
                {
                        const char *lang;
                        gboolean    has_language;

                        has_language = (language != NULL) && (language[0] != '/0');

                        if ((gdm_system_locale != NULL) && (!has_language)) {
                                lang = gdm_system_locale;
                        } else {
                                lang = language;
                        }

                        if G_LIKELY (logfilefd >= 0) {
                                VE_IGNORE_EINTR (close (logpipe[0]));
                        }
                        /* Never returns */
                        session_child_run (pwent,
                                           logpipe[1],
                                           failsafe,
                                           home_dir,
                                           home_dir_ok,
    #ifdef WITH_CONSOLE_KIT
                                           ck_session_cookie,
    #endif
                                           session,
                                           save_session,
                                           lang,
                                           gnome_session,
                                           usrcfgok,
                                           savesess,
                                           savelang);
                        g_assert_not_reached ();
                }

->
slave.c
static void session_child_run (struct passwd *pwent,
                   int logfd,
                   gboolean failsafe,
                   const char *home_dir,
                   gboolean home_dir_ok,
#ifdef WITH_CONSOLE_KIT
                   const char *ck_session_cookie,
#endif
                   const char *session,
                   const char *save_session,
                   const char *language,
                   const char *gnome_session,
                   gboolean usrcfgok,
                   gboolean savesess,
                   gboolean savelang)

        CODE: // session最终设定
        /* Prepare user session */
        g_setenv ("XAUTHORITY", d->userauth, TRUE);
        g_setenv ("DISPLAY", d->name, TRUE);
        if (d->windowpath)
                g_setenv ("WINDOWPATH", d->windowpath, TRUE);
        g_setenv ("LOGNAME", pwent->pw_name, TRUE);
        g_setenv ("USER", pwent->pw_name, TRUE);
        g_setenv ("USERNAME", pwent->pw_name, TRUE);
        g_setenv ("HOME", home_dir, TRUE);
    #ifdef WITH_CONSOLE_KIT
        if (ck_session_cookie != NULL) {
                g_setenv ("XDG_SESSION_COOKIE", ck_session_cookie, TRUE);
        }
    #endif
        g_setenv ("PWD", home_dir, TRUE);
        g_setenv ("GDMSESSION", session, TRUE);
        g_setenv ("DESKTOP_SESSION", session, TRUE);
        g_setenv ("SHELL", pwent->pw_shell, TRUE);

        CODE: // 语言最终设定
        if ( ! ve_string_empty (language)) {
                g_setenv ("LANG", language, TRUE);
                g_setenv ("GDM_LANG", language, TRUE);
        }

        /* just in case there is some weirdness going on */
        VE_IGNORE_EINTR (g_chdir (home_dir));

        if (usrcfgok && home_dir_ok)
                gdm_daemon_config_set_user_session_lang (savesess, savelang, home_dir, save_session, language);

->
登录完成!

【上篇】
【下篇】

抱歉!评论已关闭.