2 * This file is part of uxlaunch
4 * (C) Copyright 2009 Intel Corporation
6 * Auke Kok <auke@linux.intel.com>
7 * Arjan van de Ven <arjan@linux.intel.com>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; version 2
16 #include <sys/types.h>
22 #include <sys/types.h>
26 #include <sys/types.h>
31 #include <X11/Xauth.h>
36 char user_xauth_path[PATH_MAX];
38 static void do_env(void)
45 /* start with a clean environ */
48 setenv("USER", pass->pw_name, 1);
49 setenv("LOGNAME", pass->pw_name, 1);
50 setenv("HOME", pass->pw_dir, 1);
51 setenv("SHELL", pass->pw_shell, 1);
52 snprintf(buf, PATH_MAX, "/var/spool/mail/%s", pass->pw_name);
53 setenv("MAIL", buf, 1);
54 setenv("DISPLAY", displayname, 1);
55 snprintf(buf, PATH_MAX, "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:%s/bin", pass->pw_dir);
56 setenv("PATH", buf, 1);
57 snprintf(user_xauth_path, PATH_MAX, "%s/.Xauthority", pass->pw_dir);
58 setenv("XAUTHORITY", user_xauth_path, 1);
60 file = popen("/bin/bash -l -c export", "r");
66 memset(buf, 0, sizeof(buf));
67 if (fgets(buf, sizeof(buf) - 1, file) == NULL)
69 c = strchr(buf, '\n');
76 if (strstr(buf, "PWD"))
78 // if (strstr(buf, "DISPLAY"))
90 dprintf("Setting %s to %s\n", &buf[11], c);
91 setenv(&buf[11], c, 1);
100 #define BACKLIGHT_CLASS "/sys/class/backlight"
101 #define BACKLIGHT_FILE "brightness"
103 static void set_backlight_driver_perms(const char *backlight_dir_path)
105 char backlight_file_path[PATH_MAX];
110 snprintf(backlight_file_path, sizeof(backlight_file_path),
111 "%s/%s", backlight_dir_path, BACKLIGHT_FILE);
113 ret = chown(backlight_dir_path, pass->pw_uid, pass->pw_gid);
115 lprintf("Failed to set \"%s\" ownership", backlight_dir_path);
117 ret = chown(backlight_file_path, pass->pw_uid, pass->pw_gid);
119 lprintf("Failed to set \"%s\" ownership", backlight_file_path);
124 static void set_backlight_perms(const char *backlight_class)
127 struct dirent *entry;
128 char backlight_dir_path[PATH_MAX];
132 dir = opendir(backlight_class);
134 while (NULL != (entry = readdir (dir))) {
135 if (entry->d_name && entry->d_name[0] != '.' &&
136 entry->d_type == DT_LNK) {
138 snprintf(backlight_dir_path,
139 sizeof (backlight_dir_path),
140 "%s/%s", backlight_class,
142 set_backlight_driver_perms(backlight_dir_path);
147 lprintf ("Failed to opendir(\"%s\")", backlight_class);
154 * Change from root (as we started) to the target user.
157 * 2) env variables: HOME, MAIL, LOGNAME, USER, SHELL, DISPLAY and PATH
158 * 3) chdir(/home/foo);
160 void switch_to_user(void)
168 initgroups(pass->pw_name, pass->pw_gid);
170 /* make sure that the user owns /dev/ttyX */
171 ret = chown(displaydev, pass->pw_uid, pass->pw_gid);
173 lprintf("Failed to fix /dev/tty permission");
175 /* make sure the user owns the X backlight devices */
176 set_backlight_perms (BACKLIGHT_CLASS);
178 if (!((setgid(pass->pw_gid) == 0) && (setuid(pass->pw_uid) == 0))) {
179 lprintf("Fatal: Unable to setgid()/setuid()\n");
183 if (access(pass->pw_dir, R_OK || W_OK || X_OK) != 0) {
184 lprintf("Fatal: \"%s\" has incompatible permissions", pass->pw_dir);
188 if (setpgid(0, getpgid(getppid())) == -1)
189 lprintf("Unable to setpgid()");
191 lprintf("Unable to setsid()");
197 ret = chdir(pass->pw_dir);
199 fp = fopen(user_xauth_path, "w");
201 if (XauWriteAuth(fp, &x_auth) != 1)
202 lprintf("Unable to write .Xauthority");
206 /* redirect further IO to .xsession-errors */
207 snprintf(fn, PATH_MAX, "%s/.xsession-errors", pass->pw_dir);
211 /* xserver.c already truncates this file, so append */
212 fp = freopen(fn, "a", stdout);
213 fp = freopen(fn, "a", stderr);
215 lprintf("Unable to open \"%s\n\" for writing", fn);
221 static char *scim_languages[] = { "zh_", "ja_", "ko_", "lo_", "th_" };
223 void setup_user_environment (void)
227 const char *lang = getenv ("LANG");
231 for (i = 0; lang && i < sizeof(scim_languages) / sizeof(scim_languages[0]); i++) {
232 if (strstr(lang, scim_languages[i])) {
233 setenv("GTK_IM_MODULE", "scim-bridge", 0);
234 setenv("CLUTTER_IM_MODULE","scim-bridge", 0);
238 /* setup misc. user directories and variables */
239 snprintf(buf, PATH_MAX, "%s/.cache", pass->pw_dir);
241 setenv("XDG_CACHE_HOME", buf, 0);
242 snprintf(buf, PATH_MAX, "%s/.config", pass->pw_dir);
243 setenv("XDG_CONFIG_HOME", buf, 0);
244 setenv("OOO_FORCE_DESKTOP","gnome", 0);
245 setenv("LIBC_FATAL_STDERR_", "1", 0);
261 * /etc/sysconfig/i18n contains shell code that sets
262 * various i18n options in environment, typically:
265 snprintf(path, PATH_MAX, "%s/.config/i18n", pass->pw_dir);
266 f = fopen(path, "r");
269 dprintf("Unable to open ~/.config/i18n, trying /etc/sysconfig/i18n");
270 f = fopen("/etc/sysconfig/i18n", "r");
277 while (fgets(buf, 256, f) != NULL) {
280 c = strchr(buf, '\n');
281 if (c) *c = 0; /* remove trailing \n */
283 continue; /* skip comments */
285 key = strtok(buf, "=");
288 val = strtok(NULL, "=\""); /* note \" */
292 /* grab the stuff we need, avoiding comments
293 * and other user stuff we don't care for now */
294 if (!strcmp(key, "LANG"))
296 if (!strcmp(key, "SYSFONT"))