459 lines
11 KiB
Diff
459 lines
11 KiB
Diff
diff --git a/desktop.c b/desktop.c
|
|
index c591fa7..88784f5 100644
|
|
--- a/desktop.c
|
|
+++ b/desktop.c
|
|
@@ -17,8 +17,10 @@
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
+#include <sys/wait.h>
|
|
#include <dirent.h>
|
|
#include <time.h>
|
|
+#include <errno.h>
|
|
#include <glib.h>
|
|
#include <limits.h>
|
|
#include <pwd.h>
|
|
@@ -395,12 +397,31 @@ void do_autostart(void)
|
|
ptrs[++count] = strtok(NULL, " \t");
|
|
|
|
usleep(delay);
|
|
- lprintf("Starting %s with prio %d at %d", entry->exec, entry->prio, delay);
|
|
+ lprintf("Starting session '%s' %s with prio %d at %d",
|
|
+ session, entry->exec, entry->prio, delay);
|
|
execvp(ptrs[0], ptrs);
|
|
exit(ret);
|
|
}
|
|
}
|
|
|
|
+void wait_for_session_exit(void)
|
|
+{
|
|
+ lprintf("wait_for_session_exit");
|
|
+ for (;;) {
|
|
+ errno = 0;
|
|
+ if (waitpid (session_pid, NULL, 0) < 0) {
|
|
+ if (errno == EINTR) {
|
|
+ continue;
|
|
+ } else if (errno == ECHILD)
|
|
+ break; /* child already reaped */
|
|
+ else
|
|
+ lprintf("waidpid error '%s'", strerror (errno));
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ lprintf("session exited");
|
|
+}
|
|
|
|
void start_desktop_session(void)
|
|
{
|
|
diff --git a/lib.c b/lib.c
|
|
index 4788fef..b530bfd 100644
|
|
--- a/lib.c
|
|
+++ b/lib.c
|
|
@@ -24,8 +24,6 @@
|
|
#include "uxlaunch.h"
|
|
|
|
|
|
-#define LOGFILE "/var/log/uxlaunch.log"
|
|
-
|
|
extern char **environ;
|
|
|
|
static int first_time = 1;
|
|
@@ -36,10 +34,14 @@ struct timeval start;
|
|
static FILE *log;
|
|
|
|
|
|
-void open_log(void)
|
|
+void open_log(const char *logfile)
|
|
{
|
|
/* truncate log */
|
|
log = fopen(LOGFILE, "w");
|
|
+ if (!logfile)
|
|
+ log = stdout;
|
|
+ else
|
|
+ log = fopen(logfile, "w");
|
|
if (!log)
|
|
logfile_enabled = 0;
|
|
}
|
|
diff --git a/misc.c b/misc.c
|
|
index 9dae4fc..3a3f1b6 100644
|
|
--- a/misc.c
|
|
+++ b/misc.c
|
|
@@ -103,6 +103,17 @@ void start_gconf(void)
|
|
lprintf("failed to start gconftool-2: %d", ret);
|
|
}
|
|
|
|
+/*
|
|
+ * Stop gconfd to save gconf keys before shutdown
|
|
+ */
|
|
+void stop_gconf(void)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = system("gconftool-2 --shutdown");
|
|
+ if (ret)
|
|
+ lprintf("failed to shut down gconf %d", ret);
|
|
+}
|
|
|
|
void init_screensaver(int lock_now)
|
|
{
|
|
diff --git a/options.c b/options.c
|
|
index 11d550a..5a16d87 100644
|
|
--- a/options.c
|
|
+++ b/options.c
|
|
@@ -29,6 +29,7 @@ char session[256] = "/usr/bin/mutter --sm-disable";
|
|
char username[256] = "meego";
|
|
|
|
int verbose = 0;
|
|
+int x_session_only = 0;
|
|
|
|
static struct option opts[] = {
|
|
{ "user", 1, NULL, 'u' },
|
|
@@ -46,6 +47,7 @@ void usage(const char *name)
|
|
printf(" -u, --user Start session as specific username\n");
|
|
printf(" -t, --tty Start session on alternative tty number\n");
|
|
printf(" -s, --session Start a non-default session\n");
|
|
+ printf(" -x, --xsession Start X apps inside an existing X session\n");
|
|
printf(" -v, --verbose Display lots of output to the console\n");
|
|
printf(" -h, --help Display this help message\n");
|
|
}
|
|
@@ -132,7 +134,7 @@ void get_options(int argc, char **argv)
|
|
|
|
/* parse cmdline - overrides */
|
|
while (1) {
|
|
- c = getopt_long(argc, argv, "u:t:s:hv", opts, &i);
|
|
+ c = getopt_long(argc, argv, "u:t:s:hvx", opts, &i);
|
|
if (c == -1)
|
|
break;
|
|
|
|
@@ -153,6 +155,11 @@ void get_options(int argc, char **argv)
|
|
case 'v':
|
|
verbose = 1;
|
|
break;
|
|
+ case 'x':
|
|
+ x_session_only = 1;
|
|
+ if (getenv ("USER"))
|
|
+ strncpy (username, getenv ("USER"), 256);
|
|
+ break;
|
|
default:
|
|
break;
|
|
}
|
|
@@ -170,12 +177,14 @@ void get_options(int argc, char **argv)
|
|
}
|
|
}
|
|
|
|
- lprintf("uxlaunch v%s started.", VERSION);
|
|
+ open_log(!x_session_only ? LOGFILE : NULL);
|
|
+
|
|
+ lprintf("uxlaunch v%s started%s.", VERSION, x_session_only ? " for x session only" : "" );
|
|
lprintf("user \"%s\", tty #%d, session \"%s\"", username, tty, session);
|
|
|
|
pass = getpwnam(username);
|
|
- if (!pass)
|
|
+ if (!pass) {
|
|
+ lprintf("Error: can't find user \"%s\"", username);
|
|
exit(EXIT_FAILURE);
|
|
-
|
|
-
|
|
+ }
|
|
}
|
|
diff --git a/pam.c b/pam.c
|
|
index f6ecf69..e5cf5c3 100644
|
|
--- a/pam.c
|
|
+++ b/pam.c
|
|
@@ -5,6 +5,7 @@
|
|
* Authors:
|
|
* Auke Kok <auke@linux.intel.com>
|
|
* Arjan van de Ven <arjan@linux.intel.com>
|
|
+ * Michael Meeks <michael.meeks@novell.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
@@ -25,6 +26,48 @@ pam_handle_t *ph;
|
|
struct pam_conv pc;
|
|
|
|
/*
|
|
+ * Sometimes PAM likes to chat with you, before it is assured
|
|
+ * enough to let you log-in: fun.
|
|
+ */
|
|
+static int
|
|
+pam_conversation_fn (int msg_count,
|
|
+ const struct pam_message **messages,
|
|
+ struct pam_response **responses,
|
|
+ void *user_data)
|
|
+{
|
|
+ int i;
|
|
+ (void)user_data;
|
|
+
|
|
+ lprintf ("pam conversation with %d messages", msg_count);
|
|
+ if (responses)
|
|
+ *responses = NULL;
|
|
+
|
|
+ if (msg_count < 1) /* ping */
|
|
+ return PAM_SUCCESS;
|
|
+
|
|
+ /* otherwise find any helpful data we can to print, and bail */
|
|
+ if (!responses || !messages) {
|
|
+ lprintf ("pam conversation with no message, or response");
|
|
+ return PAM_CONV_ERR;
|
|
+ }
|
|
+ *responses = calloc (msg_count, sizeof (struct pam_response));
|
|
+ for (i = 0; i < msg_count; i++) {
|
|
+ const struct pam_message *msg = messages[i];
|
|
+
|
|
+ if (msg->msg_style == PAM_TEXT_INFO)
|
|
+ lprintf ("pam chats to us: '%s'", msg->msg);
|
|
+ else if (msg->msg_style == PAM_ERROR_MSG)
|
|
+ lprintf ("Error: pam error msg '%s'", msg->msg);
|
|
+ else
|
|
+ lprintf ("pam message %d style %d: '%s'",
|
|
+ i, msg->msg_style, msg->msg);
|
|
+ (*responses)[i].resp = NULL;
|
|
+ (*responses)[i].resp_retcode = PAM_SUCCESS;
|
|
+ }
|
|
+ return PAM_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
* Creating a PAM session. We need a pam "login" session so that the dbus
|
|
* "at_console" logic will work correctly, as well as various /dev file
|
|
* permissions.
|
|
@@ -40,6 +83,9 @@ void setup_pam_session(void)
|
|
|
|
snprintf(x, 256, "tty%d", tty);
|
|
|
|
+ pc.conv = pam_conversation_fn;
|
|
+ pc.appdata_ptr = NULL;
|
|
+
|
|
err = pam_start("login", pass->pw_name, &pc, &ph);
|
|
|
|
err = pam_set_item(ph, PAM_TTY, &x);
|
|
diff --git a/user.c b/user.c
|
|
index 111201a..91d38c0 100644
|
|
--- a/user.c
|
|
+++ b/user.c
|
|
@@ -52,13 +52,6 @@ static void do_env(void)
|
|
setenv("PATH", buf, 1);
|
|
snprintf(user_xauth_path, PATH_MAX, "%s/.Xauthority", pass->pw_dir);
|
|
setenv("XAUTHORITY", user_xauth_path, 1);
|
|
- snprintf(buf, PATH_MAX, "%s/.cache", pass->pw_dir);
|
|
- mkdir(buf, 0700);
|
|
- setenv("XDG_CACHE_HOME", buf, 0);
|
|
- snprintf(buf, PATH_MAX, "%s/.config", pass->pw_dir);
|
|
- setenv("XDG_CONFIG_HOME", buf, 0);
|
|
- setenv("OOO_FORCE_DESKTOP","gnome", 0);
|
|
- setenv("LIBC_FATAL_STDERR_", "1", 0);
|
|
|
|
file = popen("/bin/bash -l -c export", "r");
|
|
if (!file)
|
|
@@ -200,12 +193,34 @@ void switch_to_user(void)
|
|
|
|
static char *scim_languages[] = { "zh_", "ja_", "ko_", "lo_", "th_" };
|
|
|
|
+void setup_user_environment (void)
|
|
+{
|
|
+ unsigned int i;
|
|
+ char buf[PATH_MAX];
|
|
+ const char *lang = getenv ("LANG");
|
|
+
|
|
+ for (i = 0; lang && i < sizeof(scim_languages) / sizeof(scim_languages[0]); i++) {
|
|
+ if (strstr (lang, scim_languages[i])) {
|
|
+ setenv("GTK_IM_MODULE", "scim-bridge", 0);
|
|
+ setenv("CLUTTER_IM_MODULE","scim-bridge", 0);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* setup misc. user directories and variables */
|
|
+ snprintf(buf, PATH_MAX, "%s/.cache", pass->pw_dir);
|
|
+ mkdir(buf, 0700);
|
|
+ setenv("XDG_CACHE_HOME", buf, 0);
|
|
+ snprintf(buf, PATH_MAX, "%s/.config", pass->pw_dir);
|
|
+ setenv("XDG_CONFIG_HOME", buf, 0);
|
|
+ setenv("OOO_FORCE_DESKTOP","gnome", 0);
|
|
+ setenv("LIBC_FATAL_STDERR_", "1", 0);
|
|
+}
|
|
+
|
|
void set_i18n(void)
|
|
{
|
|
FILE *f;
|
|
lprintf("entering set_i18n");
|
|
|
|
-
|
|
/*
|
|
* /etc/sysconfig/i18n contains shell code that sets
|
|
* various i18n options in environment, typically:
|
|
@@ -235,16 +250,8 @@ void set_i18n(void)
|
|
|
|
/* grab the stuff we need, avoiding comments
|
|
* and other user stuff we don't care for now */
|
|
- if (!strcmp(key, "LANG")) {
|
|
- unsigned int i;
|
|
+ if (!strcmp(key, "LANG"))
|
|
setenv(key, val, 1);
|
|
- for (i = 0; i < sizeof(scim_languages) / sizeof(scim_languages[0]); i++) {
|
|
- if (strstr(val, scim_languages[i])) {
|
|
- setenv("GTK_IM_MODULE", "scim-bridge", 0);
|
|
- setenv("CLUTTER_IM_MODULE","scim-bridge", 0);
|
|
- }
|
|
- }
|
|
- }
|
|
if (!strcmp(key, "SYSFONT"))
|
|
setenv(key, val, 1);
|
|
}
|
|
diff --git a/uxlaunch.c b/uxlaunch.c
|
|
index 2c680ab..dd06326 100644
|
|
--- a/uxlaunch.c
|
|
+++ b/uxlaunch.c
|
|
@@ -20,13 +20,44 @@
|
|
|
|
#include "uxlaunch.h"
|
|
|
|
-
|
|
-int main(int argc, char **argv)
|
|
+/*
|
|
+ * Launch apps that form the user's X session
|
|
+ */
|
|
+static void
|
|
+launch_user_session(void)
|
|
{
|
|
char xhost_cmd[80];
|
|
|
|
- open_log();
|
|
+ setup_user_environment();
|
|
+
|
|
+ start_ssh_agent();
|
|
+
|
|
+ setup_consolekit_session();
|
|
+
|
|
+ /* dbus needs the CK env var */
|
|
+ start_dbus_session_bus();
|
|
+
|
|
+ /* gconf needs dbus */
|
|
+ start_gconf();
|
|
+
|
|
+ maybe_start_screensaver();
|
|
+
|
|
+ start_desktop_session();
|
|
+
|
|
+ /* finally, set local username to be allowed at any time,
|
|
+ * which is not depenedent on hostname changes */
|
|
+ snprintf(xhost_cmd, 80, "/usr/bin/xhost +SI:localuser:%s",
|
|
+ pass->pw_name);
|
|
+ if (system(xhost_cmd) != 0)
|
|
+ lprintf("%s failed", xhost_cmd);
|
|
+
|
|
+ get_session_type();
|
|
+ autostart_desktop_files();
|
|
+ do_autostart();
|
|
+}
|
|
|
|
+int main(int argc, char **argv)
|
|
+{
|
|
/*
|
|
* General objective:
|
|
* Do the things that need root privs first,
|
|
@@ -53,6 +84,13 @@ int main(int argc, char **argv)
|
|
|
|
get_options(argc, argv);
|
|
|
|
+ if (x_session_only) {
|
|
+ launch_user_session();
|
|
+ wait_for_session_exit();
|
|
+ stop_gconf();
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
setup_xauth();
|
|
|
|
setup_efs();
|
|
@@ -81,33 +119,9 @@ int main(int argc, char **argv)
|
|
* so can happen while X is talking to the
|
|
* hardware
|
|
*/
|
|
-
|
|
wait_for_X_signal();
|
|
|
|
- start_ssh_agent();
|
|
-
|
|
- setup_consolekit_session();
|
|
-
|
|
- /* dbus needs the CK env var */
|
|
- start_dbus_session_bus();
|
|
-
|
|
- /* gconf needs dbus */
|
|
- start_gconf();
|
|
-
|
|
- maybe_start_screensaver();
|
|
-
|
|
- start_desktop_session();
|
|
-
|
|
- /* finally, set local username to be allowed at any time,
|
|
- * which is not depenedent on hostname changes */
|
|
- snprintf(xhost_cmd, 80, "/usr/bin/xhost +SI:localuser:%s",
|
|
- pass->pw_name);
|
|
- if (system(xhost_cmd) != 0)
|
|
- lprintf("%s failed", xhost_cmd);
|
|
-
|
|
- get_session_type();
|
|
- autostart_desktop_files();
|
|
- do_autostart();
|
|
+ launch_user_session();
|
|
|
|
/*
|
|
* we do this now to make sure dbus etc are not spawning
|
|
@@ -124,6 +138,8 @@ int main(int argc, char **argv)
|
|
*/
|
|
wait_for_X_exit();
|
|
|
|
+ stop_gconf();
|
|
+
|
|
set_text_mode();
|
|
|
|
// close_consolekit_session();
|
|
diff --git a/uxlaunch.h b/uxlaunch.h
|
|
index 58d24e2..97d7160 100644
|
|
--- a/uxlaunch.h
|
|
+++ b/uxlaunch.h
|
|
@@ -24,12 +24,14 @@ extern int session_pid;
|
|
extern int xpid;
|
|
|
|
extern int verbose;
|
|
+extern int x_session_only;
|
|
|
|
extern void get_options(int argc, char **argv);
|
|
extern void set_i18n(void);
|
|
extern void setup_pam_session(void);
|
|
extern void close_pam_session(void);
|
|
extern void switch_to_user(void);
|
|
+extern void setup_user_environment (void);
|
|
extern void set_tty(void);
|
|
extern void setup_xauth(void);
|
|
extern void start_X_server(void);
|
|
@@ -40,12 +42,14 @@ extern void setup_consolekit_session(void);
|
|
extern void start_ssh_agent(void);
|
|
extern void stop_ssh_agent(void);
|
|
extern void start_gconf(void);
|
|
+extern void stop_gconf(void);
|
|
extern void init_screensaver(int);
|
|
extern void maybe_start_screensaver(void);
|
|
extern void get_session_type(void);
|
|
extern void autostart_desktop_files(void);
|
|
extern void do_autostart(void);
|
|
extern void start_desktop_session(void);
|
|
+extern void wait_for_session_exit(void);
|
|
extern void start_bash(void);
|
|
extern void wait_for_X_exit(void);
|
|
extern void set_text_mode(void);
|
|
@@ -54,7 +58,9 @@ extern void oom_adj(int, int);
|
|
extern void start_oom_task(void);
|
|
extern void stop_oom_task(void);
|
|
|
|
-extern void open_log(void);
|
|
+#define LOGFILE "/var/log/uxlaunch.log"
|
|
+
|
|
+extern void open_log(const char *);
|
|
extern void lprintf(const char *, ...);
|
|
extern void log_environment(void);
|
|
|
|
|
|
|