88
107
#include "getvt.h"
89
108
#include "errorgui.h"
90
109
#include "cookie.h"
91
#include "gdmconfig.h"
93
/* Some per slave globals */
94
static GdmDisplay *d = 0;
95
static gchar *login = NULL;
96
static gboolean greet = FALSE;
97
static gboolean configurator = FALSE;
98
static gboolean remanage_asap = FALSE;
99
static gboolean got_xfsz_signal = FALSE;
100
static gboolean do_timed_login = FALSE; /* if this is true,
101
login the timed login */
102
static gboolean do_configurator = FALSE; /* if this is true, login as root
103
* and start the configurator */
104
static gboolean do_cancel = FALSE; /* if this is true, go back to
105
username entry & unselect face
106
browser (if present) */
107
static gboolean do_restart_greeter = FALSE; /* if this is true, whack the
108
greeter and try again */
109
static gboolean restart_greeter_now = FALSE; /* restart_greeter_when the
111
static gboolean gdm_wait_for_ack = TRUE; /* wait for ack on all messages to
113
static int in_session_stop = 0;
114
static int in_usr2_signal = 0;
112
#include "gdm-common.h"
114
#include "gdm-daemon-config.h"
116
#include "gdm-socket-protocol.h"
118
#ifdef WITH_CONSOLE_KIT
119
#include "gdmconsolekit.h"
122
#ifndef GDM_BAD_RECORDS_FILE
123
#define GDM_BAD_RECORDS_FILE "/var/log/btmp"
126
#ifndef GDM_NEW_RECORDS_FILE
127
#define GDM_NEW_RECORDS_FILE "/var/log/wtmp"
130
/* Per-slave globals */
132
static GdmDisplay *d = 0;
133
static gchar *login_user = NULL;
134
static gboolean greet = FALSE;
135
static gboolean configurator = FALSE;
136
static gboolean remanage_asap = FALSE;
137
static gboolean got_xfsz_signal = FALSE;
138
static gboolean do_timed_login = FALSE; /* If this is true, login the
140
static gboolean do_configurator = FALSE; /* If this is true, login as
143
static gboolean do_cancel = FALSE; /* If this is true, go back to
144
username entry & unselect
145
face browser (if present) */
146
static gboolean do_restart_greeter = FALSE; /* If this is true, whack the
147
greeter and try again */
148
static gboolean restart_greeter_now = FALSE; /* Restart_greeter_when the
150
static gboolean always_restart_greeter = FALSE; /* Always restart greeter when
151
the user accepts restarts. */
152
static gboolean gdm_wait_for_ack = TRUE; /* Wait for ack on all messages
154
static int in_session_stop = 0;
155
static int in_usr2_signal = 0;
115
156
static gboolean need_to_quit_after_session_stop = FALSE;
116
static int exit_code_to_use = DISPLAY_REMANAGE;
117
static gboolean session_started = FALSE;
118
static gboolean greeter_disabled = FALSE;
119
static gboolean greeter_no_focus = FALSE;
121
static uid_t logged_in_uid = -1;
122
static gid_t logged_in_gid = -1;
124
static gboolean interrupted = FALSE;
125
static gchar *ParsedAutomaticLogin = NULL;
126
static gchar *ParsedTimedLogin = NULL;
128
static int greeter_fd_out = -1;
129
static int greeter_fd_in = -1;
157
static int exit_code_to_use = DISPLAY_REMANAGE;
158
static gboolean session_started = FALSE;
159
static gboolean greeter_disabled = FALSE;
160
static gboolean greeter_no_focus = FALSE;
164
* On Solaris uid_t and gid_t are unsigned ints, so you cannot
165
* set them to -1. These globals are just used for bookkeeping
166
* so using a signed long works.
168
static long logged_in_uid = -1;
169
static long logged_in_gid = -1;
171
static uid_t logged_in_uid = -1;
172
static gid_t logged_in_gid = -1;
175
static int greeter_fd_out = -1;
176
static int greeter_fd_in = -1;
178
static gboolean interrupted = FALSE;
179
static gchar *ParsedAutomaticLogin = NULL;
180
static gchar *ParsedTimedLogin = NULL;
182
static int gdm_in_signal = 0;
183
static int gdm_normal_runlevel = -1;
184
static pid_t extra_process = 0;
185
static int extra_status = 0;
132
188
static gboolean have_suntsol_extension = FALSE;
139
static int slave_waitpid_r = -1;
140
static int slave_waitpid_w = -1;
141
static GSList *slave_waitpids = NULL;
191
static int slave_waitpid_r = -1;
192
static int slave_waitpid_w = -1;
193
static GSList *slave_waitpids = NULL;
143
195
extern gboolean gdm_first_login;
144
extern gboolean gdm_emergency_server;
145
extern pid_t extra_process;
146
extern int extra_status;
147
extern int gdm_in_signal;
148
extern int gdm_normal_runlevel;
150
extern int slave_fifo_pipe_fd; /* the slavepipe (like fifo) connection, this is the write end */
197
/* The slavepipe (like fifo) connection, this is the write end */
198
extern int slave_fifo_pipe_fd;
152
200
/* wait for a GO in the SOP protocol */
153
201
extern gboolean gdm_wait_for_go;
203
extern char *gdm_system_locale;
155
209
/* Local prototypes */
156
static gint gdm_slave_xerror_handler (Display *disp, XErrorEvent *evt);
157
static gint gdm_slave_xioerror_handler (Display *disp);
158
static gint gdm_slave_ignore_xioerror_handler (Display *disp);
159
static void gdm_slave_run (GdmDisplay *display);
160
static void gdm_slave_wait_for_login (void);
161
static void gdm_slave_greeter (void);
162
static void gdm_slave_chooser (void);
163
static void gdm_slave_session_start (void);
164
static void gdm_slave_session_stop (gboolean run_post_session,
210
static gint gdm_slave_xerror_handler (Display *disp, XErrorEvent *evt);
211
static gint gdm_slave_xioerror_handler (Display *disp);
212
static void gdm_slave_run (GdmDisplay *display);
213
static void gdm_slave_wait_for_login (void);
214
static void gdm_slave_greeter (void);
215
static void gdm_slave_chooser (void);
216
static void gdm_slave_session_start (void);
217
static void gdm_slave_session_stop (gboolean run_post_session,
165
218
gboolean no_shutdown_check);
166
static void gdm_slave_alrm_handler (int sig);
167
static void gdm_slave_term_handler (int sig);
168
static void gdm_slave_usr2_handler (int sig);
169
static void gdm_slave_quick_exit (gint status);
170
static void gdm_slave_exit (gint status, const gchar *format, ...) G_GNUC_PRINTF (2, 3);
171
static void gdm_child_exit (gint status, const gchar *format, ...) G_GNUC_PRINTF (2, 3);
172
static gint gdm_slave_exec_script (GdmDisplay *d, const gchar *dir,
219
static void gdm_slave_alrm_handler (int sig);
220
static void gdm_slave_term_handler (int sig);
221
static void gdm_slave_usr2_handler (int sig);
222
static void gdm_slave_quick_exit (gint status);
223
static void gdm_slave_exit (gint status, const gchar *format, ...) G_GNUC_PRINTF (2, 3);
224
static void gdm_child_exit (gint status, const gchar *format, ...) G_GNUC_PRINTF (2, 3);
225
static gint gdm_slave_exec_script (GdmDisplay *d, const gchar *dir,
173
226
const char *login, struct passwd *pwent,
174
227
gboolean pass_stdout);
175
static gchar * gdm_parse_enriched_login (const gchar *s, GdmDisplay *display);
176
static void gdm_slave_handle_usr2_message (void);
177
static void gdm_slave_handle_notify (const char *msg);
178
static void create_temp_auth_file (void);
179
static void set_xnest_parent_stuff (void);
180
static void check_notifies_now (void);
181
static void restart_the_greeter (void);
228
static gchar *gdm_slave_parse_enriched_login (GdmDisplay *d, const gchar *s);
229
static void gdm_slave_handle_usr2_message (void);
230
static void gdm_slave_handle_notify (const char *msg);
231
static void create_temp_auth_file (void);
232
static void set_xnest_parent_stuff (void);
233
static void check_notifies_now (void);
234
static void restart_the_greeter (void);
184
237
static gboolean gdm_can_i_assume_root_role (struct passwd *pwent);
1282
1395
static gboolean do_xfailed_on_xio_error = FALSE;
1285
1398
gdm_slave_run (GdmDisplay *display)
1287
gint openretries = 0;
1289
gint pinginterval = gdm_get_value_int (GDM_KEY_PING_INTERVAL);
1291
/* Reset d since gdm_slave_run is called in a loop */
1296
if (d->sleep_before_run > 0) {
1297
gdm_debug ("gdm_slave_run: Sleeping %d seconds before server start", d->sleep_before_run);
1298
gdm_sleep_no_signal (d->sleep_before_run);
1299
d->sleep_before_run = 0;
1301
check_notifies_now ();
1304
/* set it before we run the server, it may be that we're using
1305
* the XOpenDisplay to find out if a server is ready (as with Xnest) */
1308
/* if this is local display start a server if one doesn't
1310
if (SERVER_IS_LOCAL (d) &&
1312
if G_UNLIKELY ( ! gdm_server_start (d,
1313
TRUE /* try_again_if_busy */,
1314
FALSE /* treat_as_flexi */,
1315
20 /* min_flexi_disp */,
1316
5 /* flexi_retries */)) {
1317
/* We're really not sure what is going on,
1318
* so we throw up our hands and tell the user
1319
* that we've given up. The error is likely something
1321
gdm_text_message_dialog
1322
(C_(N_("Could not start the X\n"
1323
"server (your graphical environment)\n"
1324
"due to some internal error.\n"
1325
"Please contact your system administrator\n"
1326
"or check your syslog to diagnose.\n"
1327
"In the meantime this display will be\n"
1328
"disabled. Please restart GDM when\n"
1329
"the problem is corrected.")));
1330
gdm_slave_quick_exit (DISPLAY_ABORT);
1332
gdm_slave_send_num (GDM_SOP_XPID, d->servpid);
1334
check_notifies_now ();
1337
/* We can use d->handled from now on on this display,
1338
* since the lookup was done in server start */
1340
g_setenv ("DISPLAY", d->name, TRUE);
1341
g_unsetenv ("XAUTHORITY"); /* just in case it's set */
1343
gdm_auth_set_local_auth (d);
1346
/* Now the display name and hostname is final */
1348
char *automaticlogin = gdm_get_value_string (GDM_KEY_AUTOMATIC_LOGIN);
1349
char *timedlogin = gdm_get_value_string (GDM_KEY_TIMED_LOGIN);
1351
if (gdm_get_value_bool (GDM_KEY_AUTOMATIC_LOGIN_ENABLE) &&
1352
! ve_string_empty (automaticlogin)) {
1353
g_free (ParsedAutomaticLogin);
1354
ParsedAutomaticLogin = gdm_parse_enriched_login (automaticlogin,
1358
if (gdm_get_value_bool (GDM_KEY_TIMED_LOGIN_ENABLE) &&
1359
! ve_string_empty (timedlogin)) {
1360
g_free (ParsedTimedLogin);
1361
ParsedTimedLogin = gdm_parse_enriched_login (timedlogin,
1366
/* X error handlers to avoid the default one (i.e. exit (1)) */
1367
do_xfailed_on_xio_error = TRUE;
1368
XSetErrorHandler (gdm_slave_xerror_handler);
1369
XSetIOErrorHandler (gdm_slave_xioerror_handler);
1371
/* We keep our own (windowless) connection (dsp) open to avoid the
1372
* X server resetting due to lack of active connections. */
1374
gdm_debug ("gdm_slave_run: Opening display %s", d->name);
1376
/* if local then the the server should be ready for openning, so
1377
* don't try so long before killing it and trying again */
1378
if (SERVER_IS_LOCAL (d))
1383
while (d->handled &&
1384
openretries < maxtries &&
1386
( ! SERVER_IS_LOCAL (d) || d->servpid > 1)) {
1387
d->dsp = XOpenDisplay (d->name);
1389
if G_UNLIKELY (d->dsp == NULL) {
1390
gdm_debug ("gdm_slave_run: Sleeping %d on a retry", 1+openretries*2);
1391
gdm_sleep_no_signal (1+openretries*2);
1396
/* Really this will only be useful for the first local server,
1397
since that's the only time this can really be on */
1398
while G_UNLIKELY (gdm_wait_for_go) {
1400
/* Wait 1 second. */
1403
select (0, NULL, NULL, NULL, &tv);
1404
/* don't want to use sleep since we're using alarm
1406
check_notifies_now ();
1409
/* Set the busy cursor */
1410
if (d->dsp != NULL) {
1411
Cursor xcursor = XCreateFontCursor (d->dsp, GDK_WATCH);
1412
XDefineCursor (d->dsp,
1413
DefaultRootWindow (d->dsp),
1415
XFreeCursor (d->dsp, xcursor);
1416
XSync (d->dsp, False);
1419
/* Just a race avoiding sleep, probably not necessary though,
1420
* but doesn't hurt anything */
1422
gdm_sleep_no_signal (1);
1424
if (SERVER_IS_LOCAL (d)) {
1425
gdm_slave_send (GDM_SOP_START_NEXT_LOCAL, FALSE);
1428
check_notifies_now ();
1430
/* something may have gone wrong, try xfailed, if local (non-flexi),
1431
* the toplevel loop of death will handle us */
1432
if G_UNLIKELY (d->handled && d->dsp == NULL) {
1433
if (d->type == TYPE_STATIC)
1434
gdm_slave_quick_exit (DISPLAY_XFAILED);
1436
gdm_slave_quick_exit (DISPLAY_ABORT);
1439
/* OK from now on it's really the user whacking us most likely,
1440
* we have already started up well */
1441
do_xfailed_on_xio_error = FALSE;
1443
/* If XDMCP setup pinging */
1444
if ( ! SERVER_IS_LOCAL (d) && pinginterval > 0) {
1445
alarm (pinginterval);
1448
/* checkout xinerama */
1450
gdm_screen_init (d);
1400
gint openretries = 0;
1402
gint pinginterval = gdm_daemon_config_get_value_int (GDM_KEY_PING_INTERVAL);
1404
gdm_reset_locale ();
1406
/* Reset d since gdm_slave_run is called in a loop */
1411
if (d->sleep_before_run > 0) {
1412
gdm_debug ("gdm_slave_run: Sleeping %d seconds before server start", d->sleep_before_run);
1413
gdm_sleep_no_signal (d->sleep_before_run);
1414
d->sleep_before_run = 0;
1416
check_notifies_now ();
1420
* Set it before we run the server, it may be that we're using
1421
* the XOpenDisplay to find out if a server is ready (as with
1426
/* if this is local display start a server if one doesn't
1428
if (SERVER_IS_LOCAL (d) &&
1430
if G_UNLIKELY ( ! gdm_server_start (d,
1431
TRUE /* try_again_if_busy */,
1432
FALSE /* treat_as_flexi */,
1433
20 /* min_flexi_disp */,
1434
5 /* flexi_retries */)) {
1435
/* We're really not sure what is going on,
1436
* so we throw up our hands and tell the user
1437
* that we've given up. The error is likely something
1439
gdm_text_message_dialog
1440
(C_(N_("Could not start the X\n"
1441
"server (your graphical environment)\n"
1442
"due to some internal error.\n"
1443
"Please contact your system administrator\n"
1444
"or check your syslog to diagnose.\n"
1445
"In the meantime this display will be\n"
1446
"disabled. Please restart GDM when\n"
1447
"the problem is corrected.")));
1448
gdm_slave_quick_exit (DISPLAY_ABORT);
1450
gdm_slave_send_num (GDM_SOP_XPID, d->servpid);
1452
check_notifies_now ();
1455
/* We can use d->handled from now on on this display,
1456
* since the lookup was done in server start */
1458
g_setenv ("DISPLAY", d->name, TRUE);
1460
g_setenv ("WINDOWPATH", d->windowpath, TRUE);
1461
g_unsetenv ("XAUTHORITY"); /* just in case it's set */
1463
gdm_auth_set_local_auth (d);
1466
/* Now the display name and hostname is final */
1468
const char *automaticlogin = gdm_daemon_config_get_value_string (GDM_KEY_AUTOMATIC_LOGIN);
1469
const char *timedlogin = gdm_daemon_config_get_value_string (GDM_KEY_TIMED_LOGIN);
1471
if (gdm_daemon_config_get_value_bool (GDM_KEY_AUTOMATIC_LOGIN_ENABLE) &&
1472
! ve_string_empty (automaticlogin)) {
1473
g_free (ParsedAutomaticLogin);
1474
ParsedAutomaticLogin = gdm_slave_parse_enriched_login (display,
1478
if (gdm_daemon_config_get_value_bool (GDM_KEY_TIMED_LOGIN_ENABLE) &&
1479
! ve_string_empty (timedlogin)) {
1480
g_free (ParsedTimedLogin);
1481
ParsedTimedLogin = gdm_slave_parse_enriched_login (display,
1486
/* X error handlers to avoid the default one (i.e. exit (1)) */
1487
do_xfailed_on_xio_error = TRUE;
1488
XSetErrorHandler (gdm_slave_xerror_handler);
1489
XSetIOErrorHandler (gdm_slave_xioerror_handler);
1491
/* We keep our own (windowless) connection (dsp) open to avoid the
1492
* X server resetting due to lack of active connections. */
1494
gdm_debug ("gdm_slave_run: Opening display %s", d->name);
1496
/* if local then the the server should be ready for openning, so
1497
* don't try so long before killing it and trying again */
1498
if (SERVER_IS_LOCAL (d))
1503
while (d->handled &&
1504
openretries < maxtries &&
1506
( ! SERVER_IS_LOCAL (d) || d->servpid > 1)) {
1508
gdm_sigchld_block_push ();
1509
d->dsp = XOpenDisplay (d->name);
1510
gdm_sigchld_block_pop ();
1512
if G_UNLIKELY (d->dsp == NULL) {
1513
gdm_debug ("gdm_slave_run: Sleeping %d on a retry", 1+openretries*2);
1514
gdm_sleep_no_signal (1+openretries*2);
1519
/* Really this will only be useful for the first local server,
1520
since that's the only time this can really be on */
1521
while G_UNLIKELY (gdm_wait_for_go) {
1523
/* Wait 1 second. */
1526
select (0, NULL, NULL, NULL, &tv);
1527
/* don't want to use sleep since we're using alarm
1529
check_notifies_now ();
1532
/* Set the busy cursor */
1533
if (d->dsp != NULL) {
1534
Cursor xcursor = XCreateFontCursor (d->dsp, GDK_WATCH);
1535
XDefineCursor (d->dsp,
1536
DefaultRootWindow (d->dsp),
1538
XFreeCursor (d->dsp, xcursor);
1539
XSync (d->dsp, False);
1542
/* Just a race avoiding sleep, probably not necessary though,
1543
* but doesn't hurt anything */
1545
gdm_sleep_no_signal (1);
1547
if (SERVER_IS_LOCAL (d)) {
1548
gdm_slave_send (GDM_SOP_START_NEXT_LOCAL, FALSE);
1551
check_notifies_now ();
1553
/* something may have gone wrong, try xfailed, if local (non-flexi),
1554
* the toplevel loop of death will handle us */
1555
if G_UNLIKELY (d->handled && d->dsp == NULL) {
1556
if (d->type == TYPE_STATIC)
1557
gdm_slave_quick_exit (DISPLAY_XFAILED);
1559
gdm_slave_quick_exit (DISPLAY_ABORT);
1562
/* OK from now on it's really the user whacking us most likely,
1563
* we have already started up well */
1564
do_xfailed_on_xio_error = FALSE;
1566
/* If XDMCP setup pinging */
1567
if ( ! SERVER_IS_LOCAL (d) && pinginterval > 0) {
1568
alarm (pinginterval);
1571
/* checkout xinerama */
1573
gdm_screen_init (d);
1452
1575
#ifdef HAVE_TSOL
1453
1576
/* Check out Solaris Trusted Xserver extension */
2403
2582
if (extra_arg != NULL) {
2406
for (i = 0; argv[i] != NULL; i++)
2408
new_argv = g_new0 (char *, i+2);
2409
for (i = 0; argv[i] != NULL; i++)
2410
new_argv[i] = argv[i];
2411
new_argv[i++] = (char *)extra_arg;
2412
new_argv[i++] = NULL;
2584
argv = g_renew (char *, argv, argc + 2);
2585
argv[argc] = g_strdup (extra_arg);
2586
argv[argc + 1] = NULL;
2417
2589
VE_IGNORE_EINTR (execv (argv[0], argv));
2421
2594
gdm_slave_greeter (void)
2423
gint pipe1[2], pipe2[2];
2424
struct passwd *pwent;
2431
gdm_debug ("gdm_slave_greeter: Running greeter on %s", d->name);
2433
/* Run the init script. gdmslave suspends until script has terminated */
2434
gdm_slave_exec_script (d, gdm_get_value_string (GDM_KEY_DISPLAY_INIT_DIR),
2435
NULL, NULL, FALSE /* pass_stdout */);
2437
/* Open a pipe for greeter communications */
2438
if G_UNLIKELY (pipe (pipe1) < 0)
2439
gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't init pipe to gdmgreeter"),
2440
"gdm_slave_greeter");
2441
if G_UNLIKELY (pipe (pipe2) < 0) {
2442
VE_IGNORE_EINTR (close (pipe1[0]));
2443
VE_IGNORE_EINTR (close (pipe1[1]));
2444
gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't init pipe to gdmgreeter"),
2445
"gdm_slave_greeter");
2448
/* hackish ain't it */
2449
create_temp_auth_file ();
2451
/* Fork. Parent is gdmslave, child is greeter process. */
2452
gdm_sigchld_block_push ();
2453
gdm_sigterm_block_push ();
2455
pid = d->greetpid = fork ();
2457
gdm_unset_signals ();
2458
gdm_sigterm_block_pop ();
2459
gdm_sigchld_block_pop ();
2466
gdm_unset_signals ();
2469
VE_IGNORE_EINTR (close (pipe1[1]));
2470
VE_IGNORE_EINTR (close (pipe2[0]));
2472
VE_IGNORE_EINTR (dup2 (pipe1[0], STDIN_FILENO));
2473
VE_IGNORE_EINTR (dup2 (pipe2[1], STDOUT_FILENO));
2478
* Leave stderr open to the log
2480
gdm_close_all_descriptors (3 /* from */, -1 /* except */, -1 /* except2 */);
2482
openlog ("gdm", LOG_PID, LOG_DAEMON);
2484
if G_UNLIKELY (setgid (gdm_get_gdmgid ()) < 0)
2485
gdm_child_exit (DISPLAY_ABORT,
2486
_("%s: Couldn't set groupid to %d"),
2487
"gdm_slave_greeter", gdm_get_gdmgid ());
2489
gdmuser = gdm_get_value_string (GDM_KEY_USER);
2490
if G_UNLIKELY (initgroups (gdmuser, gdm_get_gdmgid ()) < 0)
2491
gdm_child_exit (DISPLAY_ABORT,
2492
_("%s: initgroups () failed for %s"),
2493
"gdm_slave_greeter", gdmuser);
2495
if G_UNLIKELY (setuid (gdm_get_gdmuid ()) < 0)
2496
gdm_child_exit (DISPLAY_ABORT,
2497
_("%s: Couldn't set userid to %d"),
2498
"gdm_slave_greeter", gdm_get_gdmuid ());
2502
g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE);
2503
g_setenv ("DISPLAY", d->name, TRUE);
2596
gint pipe1[2], pipe2[2];
2597
struct passwd *pwent;
2599
const char *command;
2600
const char *defaultpath;
2601
const char *gdmuser;
2602
const char *moduleslist;
2603
const char *gdmlang;
2605
gdm_debug ("gdm_slave_greeter: Running greeter on %s", d->name);
2607
/* Run the init script. gdmslave suspends until script has terminated */
2608
gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_DISPLAY_INIT_DIR),
2609
NULL, NULL, FALSE /* pass_stdout */);
2611
/* Open a pipe for greeter communications */
2612
if G_UNLIKELY (pipe (pipe1) < 0)
2613
gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't init pipe to gdmgreeter"),
2614
"gdm_slave_greeter");
2615
if G_UNLIKELY (pipe (pipe2) < 0) {
2616
VE_IGNORE_EINTR (close (pipe1[0]));
2617
VE_IGNORE_EINTR (close (pipe1[1]));
2618
gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't init pipe to gdmgreeter"),
2619
"gdm_slave_greeter");
2505
2622
/* hackish ain't it */
2506
set_xnest_parent_stuff ();
2508
g_setenv ("LOGNAME", gdmuser, TRUE);
2509
g_setenv ("USER", gdmuser, TRUE);
2510
g_setenv ("USERNAME", gdmuser, TRUE);
2511
g_setenv ("GDM_GREETER_PROTOCOL_VERSION",
2512
GDM_GREETER_PROTOCOL_VERSION, TRUE);
2513
g_setenv ("GDM_VERSION", VERSION, TRUE);
2515
pwent = getpwnam (gdmuser);
2516
if G_LIKELY (pwent != NULL) {
2517
/* Note that usually this doesn't exist */
2518
if (pwent->pw_dir != NULL &&
2519
g_file_test (pwent->pw_dir, G_FILE_TEST_EXISTS))
2520
g_setenv ("HOME", pwent->pw_dir, TRUE);
2523
ve_sure_string (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR)),
2525
g_setenv ("SHELL", pwent->pw_shell, TRUE);
2528
ve_sure_string (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR)),
2530
g_setenv ("SHELL", "/bin/sh", TRUE);
2533
defaultpath = gdm_get_value_string (GDM_KEY_PATH);
2534
if (ve_string_empty (g_getenv ("PATH"))) {
2535
g_setenv ("PATH", defaultpath, TRUE);
2536
} else if ( ! ve_string_empty (defaultpath)) {
2537
g_setenv ("PATH", g_strconcat (g_getenv ("PATH"), ":", defaultpath, NULL), TRUE);
2539
g_setenv ("RUNNING_UNDER_GDM", "true", TRUE);
2540
if ( ! ve_string_empty (d->theme_name))
2541
g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
2543
if (gdm_get_value_bool (GDM_KEY_DEBUG_GESTURES)) {
2544
g_setenv ("GDM_DEBUG_GESTURES", "true", TRUE);
2547
/* Note that this is just informative, the slave will not listen to
2548
* the greeter even if it does something it shouldn't on a non-local
2549
* display so it's not a security risk */
2551
g_setenv ("GDM_IS_LOCAL", "yes", TRUE);
2553
g_unsetenv ("GDM_IS_LOCAL");
2556
/* this is again informal only, if the greeter does time out it will
2557
* not actually login a user if it's not enabled for this display */
2558
if (d->timed_login_ok) {
2559
if (ParsedTimedLogin == NULL)
2560
g_setenv ("GDM_TIMED_LOGIN_OK", " ", TRUE);
2562
g_setenv ("GDM_TIMED_LOGIN_OK", ParsedTimedLogin, TRUE);
2564
g_unsetenv ("GDM_TIMED_LOGIN_OK");
2567
if (SERVER_IS_FLEXI (d)) {
2568
g_setenv ("GDM_FLEXI_SERVER", "yes", TRUE);
2570
g_unsetenv ("GDM_FLEXI_SERVER");
2573
if G_UNLIKELY (gdm_emergency_server) {
2576
_("No servers were defined in the "
2577
"configuration file and XDMCP was "
2578
"disabled. This can only be a "
2579
"configuration error. GDM has started "
2580
"a single server for you. You should "
2581
"log in and fix the configuration. "
2582
"Note that automatic and timed logins "
2583
"are disabled now."));
2584
g_unsetenv ("GDM_TIMED_LOGIN_OK");
2587
if G_UNLIKELY (d->failsafe_xserver) {
2590
_("Could not start the regular X "
2591
"server (your graphical environment) "
2592
"and so this is a failsafe X server. "
2593
"You should log in and properly "
2594
"configure the X server."));
2597
if G_UNLIKELY (d->busy_display) {
2598
char *msg = g_strdup_printf
2599
(_("The specified display number was busy, so "
2600
"this server was started on display %s."),
2602
gdm_error_box (d, GTK_MESSAGE_ERROR, msg);
2623
create_temp_auth_file ();
2606
2625
if (d->attached)
2607
command = gdm_get_value_string (GDM_KEY_GREETER);
2626
command = gdm_daemon_config_get_value_string (GDM_KEY_GREETER);
2609
command = gdm_get_value_string (GDM_KEY_REMOTE_GREETER);
2611
if G_UNLIKELY (d->try_different_greeter) {
2612
/* FIXME: we should also really be able to do standalone failsafe
2613
login, but that requires some work and is perhaps an overkill. */
2614
/* This should handle mostly the case where gdmgreeter is crashing
2615
and we'd want to start gdmlogin for the user so that at least
2616
something works instead of a flickering screen */
2619
_("The greeter application appears to be crashing.\n"
2620
"Attempting to use a different one."));
2621
if (strstr (command, "gdmlogin") != NULL) {
2622
/* in case it is gdmlogin that's crashing
2623
try the themed greeter for luck */
2624
command = LIBEXECDIR "/gdmgreeter";
2626
/* in all other cases, try the gdmlogin (standard greeter)
2628
command = LIBEXECDIR "/gdmlogin";
2632
moduleslist = gdm_get_value_string (GDM_KEY_GTK_MODULES_LIST);
2634
if (gdm_get_value_bool (GDM_KEY_ADD_GTK_MODULES) &&
2635
! ve_string_empty (moduleslist) &&
2636
/* don't add modules if we're trying to prevent crashes,
2637
perhaps it's the modules causing the problem in the first place */
2638
! d->try_different_greeter) {
2639
gchar *modules = g_strdup_printf ("--gtk-module=%s", moduleslist);
2640
exec_command (command, modules);
2641
/* Something went wrong */
2642
gdm_error (_("%s: Cannot start greeter with gtk modules: %s. Trying without modules"),
2628
command = gdm_daemon_config_get_value_string (GDM_KEY_REMOTE_GREETER);
2632
* Set access control for audio device so that GDM owned programs can
2633
* play audio and work with accessibility programs that require audio.
2635
system ("/usr/bin/setfacl -m user:gdm:rwx,mask:rwx /dev/audio");
2636
system ("/usr/bin/setfacl -m user:gdm:rwx,mask:rwx /dev/audioctl");
2638
gdm_debug ("Forking greeter process: %s", command);
2640
/* Fork. Parent is gdmslave, child is greeter process. */
2641
gdm_sigchld_block_push ();
2642
gdm_sigterm_block_push ();
2644
pid = d->greetpid = fork ();
2646
gdm_unset_signals ();
2647
gdm_sigterm_block_pop ();
2648
gdm_sigchld_block_pop ();
2655
gdm_unset_signals ();
2658
VE_IGNORE_EINTR (close (pipe1[1]));
2659
VE_IGNORE_EINTR (close (pipe2[0]));
2661
VE_IGNORE_EINTR (dup2 (pipe1[0], STDIN_FILENO));
2662
VE_IGNORE_EINTR (dup2 (pipe2[1], STDOUT_FILENO));
2664
gdm_log_shutdown ();
2666
gdm_close_all_descriptors (2 /* from */, slave_fifo_pipe_fd/* except */, d->slave_notify_fd/* except2 */);
2668
gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */
2672
if G_UNLIKELY (setgid (gdm_daemon_config_get_gdmgid ()) < 0)
2673
gdm_child_exit (DISPLAY_ABORT,
2674
_("%s: Couldn't set groupid to %d"),
2675
"gdm_slave_greeter", gdm_daemon_config_get_gdmgid ());
2677
gdmuser = gdm_daemon_config_get_value_string (GDM_KEY_USER);
2678
if G_UNLIKELY (initgroups (gdmuser, gdm_daemon_config_get_gdmgid ()) < 0)
2679
gdm_child_exit (DISPLAY_ABORT,
2680
_("%s: initgroups () failed for %s"),
2681
"gdm_slave_greeter", gdmuser);
2683
if G_UNLIKELY (setuid (gdm_daemon_config_get_gdmuid ()) < 0)
2684
gdm_child_exit (DISPLAY_ABORT,
2685
_("%s: Couldn't set userid to %d"),
2686
"gdm_slave_greeter", gdm_daemon_config_get_gdmuid ());
2689
gdm_reset_locale ();
2691
g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE);
2692
g_setenv ("DISPLAY", d->name, TRUE);
2694
g_setenv ("WINDOWPATH", d->windowpath, TRUE);
2696
/* hackish ain't it */
2697
set_xnest_parent_stuff ();
2699
g_setenv ("LOGNAME", gdmuser, TRUE);
2700
g_setenv ("USER", gdmuser, TRUE);
2701
g_setenv ("USERNAME", gdmuser, TRUE);
2702
g_setenv ("GDM_GREETER_PROTOCOL_VERSION",
2703
GDM_GREETER_PROTOCOL_VERSION, TRUE);
2704
g_setenv ("GDM_VERSION", VERSION, TRUE);
2706
pwent = getpwnam (gdmuser);
2707
if G_LIKELY (pwent != NULL) {
2708
/* Note that usually this doesn't exist */
2709
if (pwent->pw_dir != NULL &&
2710
g_file_test (pwent->pw_dir, G_FILE_TEST_EXISTS))
2711
g_setenv ("HOME", pwent->pw_dir, TRUE);
2714
ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)),
2716
g_setenv ("SHELL", pwent->pw_shell, TRUE);
2719
ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)),
2721
g_setenv ("SHELL", "/bin/sh", TRUE);
2724
defaultpath = gdm_daemon_config_get_value_string (GDM_KEY_PATH);
2725
if (ve_string_empty (g_getenv ("PATH"))) {
2726
g_setenv ("PATH", defaultpath, TRUE);
2727
} else if ( ! ve_string_empty (defaultpath)) {
2728
gchar *temp_string = g_strconcat (g_getenv ("PATH"),
2729
":", defaultpath, NULL);
2730
g_setenv ("PATH", temp_string, TRUE);
2731
g_free (temp_string);
2733
g_setenv ("RUNNING_UNDER_GDM", "true", TRUE);
2734
if ( ! ve_string_empty (d->theme_name))
2735
g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
2737
if (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG_GESTURES)) {
2738
g_setenv ("GDM_DEBUG_GESTURES", "true", TRUE);
2741
/* Note that this is just informative, the slave will not listen to
2742
* the greeter even if it does something it shouldn't on a non-local
2743
* display so it's not a security risk */
2745
g_setenv ("GDM_IS_LOCAL", "yes", TRUE);
2747
g_unsetenv ("GDM_IS_LOCAL");
2750
/* this is again informal only, if the greeter does time out it will
2751
* not actually login a user if it's not enabled for this display */
2752
if (d->timed_login_ok) {
2753
if (ParsedTimedLogin == NULL)
2754
g_setenv ("GDM_TIMED_LOGIN_OK", " ", TRUE);
2756
g_setenv ("GDM_TIMED_LOGIN_OK", ParsedTimedLogin, TRUE);
2758
g_unsetenv ("GDM_TIMED_LOGIN_OK");
2761
if (SERVER_IS_FLEXI (d)) {
2762
g_setenv ("GDM_FLEXI_SERVER", "yes", TRUE);
2764
g_unsetenv ("GDM_FLEXI_SERVER");
2767
if G_UNLIKELY (d->is_emergency_server) {
2768
gdm_errorgui_error_box (d,
2770
_("No servers were defined in the "
2771
"configuration file and XDMCP was "
2772
"disabled. This can only be a "
2773
"configuration error. GDM has started "
2774
"a single server for you. You should "
2775
"log in and fix the configuration. "
2776
"Note that automatic and timed logins "
2777
"are disabled now."));
2778
g_unsetenv ("GDM_TIMED_LOGIN_OK");
2781
if G_UNLIKELY (d->failsafe_xserver) {
2782
gdm_errorgui_error_box (d,
2784
_("Could not start the regular X "
2785
"server (your graphical environment) "
2786
"and so this is a failsafe X server. "
2787
"You should log in and properly "
2788
"configure the X server."));
2791
if G_UNLIKELY (d->busy_display) {
2792
char *msg = g_strdup_printf
2793
(_("The specified display number was busy, so "
2794
"this server was started on display %s."),
2796
gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, msg);
2800
if G_UNLIKELY (d->try_different_greeter) {
2801
/* FIXME: we should also really be able to do standalone failsafe
2802
login, but that requires some work and is perhaps an overkill. */
2803
/* This should handle mostly the case where gdmgreeter is crashing
2804
and we'd want to start gdmlogin for the user so that at least
2805
something works instead of a flickering screen */
2806
gdm_errorgui_error_box (d,
2808
_("The greeter application appears to be crashing. "
2809
"Attempting to use a different one."));
2810
if (strstr (command, "gdmlogin") != NULL) {
2811
/* in case it is gdmlogin that's crashing
2812
try the themed greeter for luck */
2813
command = LIBEXECDIR "/gdmgreeter";
2815
/* in all other cases, try the gdmlogin (standard greeter)
2817
command = LIBEXECDIR "/gdmlogin";
2821
moduleslist = gdm_daemon_config_get_value_string (GDM_KEY_GTK_MODULES_LIST);
2823
if (gdm_daemon_config_get_value_bool (GDM_KEY_ADD_GTK_MODULES) &&
2824
! ve_string_empty (moduleslist) &&
2825
/* don't add modules if we're trying to prevent crashes,
2826
perhaps it's the modules causing the problem in the first place */
2827
! d->try_different_greeter) {
2828
gchar *modules = g_strdup_printf ("--gtk-module=%s", moduleslist);
2829
exec_command (command, modules);
2830
/* Something went wrong */
2831
gdm_error (_("%s: Cannot start greeter with gtk modules: %s. Trying without modules"),
2832
"gdm_slave_greeter",
2836
exec_command (command, NULL);
2838
gdm_error (_("%s: Cannot start greeter trying default: %s"),
2643
2839
"gdm_slave_greeter",
2840
LIBEXECDIR "/gdmlogin");
2842
g_setenv ("GDM_WHACKED_GREETER_CONFIG", "true", TRUE);
2844
exec_command (LIBEXECDIR "/gdmlogin", NULL);
2846
VE_IGNORE_EINTR (execl (LIBEXECDIR "/gdmlogin", LIBEXECDIR "/gdmlogin", NULL));
2848
gdm_errorgui_error_box (d,
2850
_("Cannot start the greeter application; "
2851
"you will not be able to log in. "
2852
"This display will be disabled. "
2853
"Try logging in by other means and "
2854
"editing the configuration file"));
2856
/* If no greeter we really have to disable the display */
2857
gdm_child_exit (DISPLAY_ABORT, _("%s: Error starting greeter on display %s"), "gdm_slave_greeter", d->name);
2861
gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't fork gdmgreeter process"), "gdm_slave_greeter");
2864
VE_IGNORE_EINTR (close (pipe1[0]));
2865
VE_IGNORE_EINTR (close (pipe2[1]));
2867
whack_greeter_fds ();
2869
greeter_fd_out = pipe1[1];
2870
greeter_fd_in = pipe2[0];
2872
gdm_debug ("gdm_slave_greeter: Greeter on pid %d", (int)pid);
2874
gdm_slave_send_num (GDM_SOP_GREETPID, d->greetpid);
2875
run_pictures (); /* Append pictures to greeter if browsing is on */
2877
if (always_restart_greeter)
2878
gdm_slave_greeter_ctl_no_ret (GDM_ALWAYS_RESTART, "Y");
2880
gdm_slave_greeter_ctl_no_ret (GDM_ALWAYS_RESTART, "N");
2881
gdmlang = g_getenv ("GDM_LANG");
2883
gdm_slave_greeter_ctl_no_ret (GDM_SETLANG, gdmlang);
2886
check_notifies_now ();
2647
exec_command (command, NULL);
2649
gdm_error (_("%s: Cannot start greeter trying default: %s"),
2650
"gdm_slave_greeter",
2651
LIBEXECDIR "/gdmlogin");
2653
g_setenv ("GDM_WHACKED_GREETER_CONFIG", "true", TRUE);
2655
exec_command (LIBEXECDIR "/gdmlogin", NULL);
2657
VE_IGNORE_EINTR (execl (LIBEXECDIR "/gdmlogin", LIBEXECDIR "/gdmlogin", NULL));
2661
_("Cannot start the greeter application; "
2662
"you will not be able to log in. "
2663
"This display will be disabled. "
2664
"Try logging in by other means and "
2665
"editing the configuration file"));
2667
/* If no greeter we really have to disable the display */
2668
gdm_child_exit (DISPLAY_ABORT, _("%s: Error starting greeter on display %s"), "gdm_slave_greeter", d->name);
2672
gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't fork gdmgreeter process"), "gdm_slave_greeter");
2675
VE_IGNORE_EINTR (close (pipe1[0]));
2676
VE_IGNORE_EINTR (close (pipe2[1]));
2678
whack_greeter_fds ();
2680
greeter_fd_out = pipe1[1];
2681
greeter_fd_in = pipe2[0];
2683
gdm_debug ("gdm_slave_greeter: Greeter on pid %d", (int)pid);
2685
gdm_slave_send_num (GDM_SOP_GREETPID, d->greetpid);
2687
run_pictures (); /* Append pictures to greeter if browsing is on */
2689
check_notifies_now ();
2694
2891
/* This should not call anything that could cause a syslog in case we
4083
gdm_slave_parse_enriched_string (GdmDisplay *d, const gchar *s)
4085
GString *str = g_string_new (NULL);
4088
while (s[0] != '\0') {
4090
if (s[0] == '%' && s[1] != 0) {
4097
g_string_append (str, d->hostname);
4101
g_string_append (str, d->name);
4105
g_string_append_c (str, '%');
4112
g_string_append_c (str, *s);
4120
gdm_slave_update_pseudo_device (GdmDisplay *d, const char *device_in)
4126
/* If not a valid device, then do not update */
4127
if (device_in == NULL || strncmp (device_in, "/dev/", 5) != 0) {
4128
gdm_debug ("Warning, invalid device %s", device_in);
4132
/* Parse the string, changing %d to display or %h to hostname, etc. */
4133
str = gdm_slave_parse_enriched_string (d, device_in);
4134
device = g_strdup (str->str);
4135
g_string_free (str, TRUE);
4137
/* If using pseudo-devices, setup symlink if it does not exist */
4138
if (device != NULL &&
4139
gdm_daemon_config_get_value_bool (GDM_KEY_UTMP_PSEUDO_DEVICE)) {
4140
gchar buf[MAXPATHLEN + 1];
4142
memset (buf, 0, sizeof (gchar) * (MAXPATHLEN + 1));
4144
if (stat (device, &st) != 0) {
4145
gdm_debug ("Creating pseudo-device %s", device);
4146
symlink ("/dev/null", device);
4147
} else if (readlink (device, buf, MAXPATHLEN) > 0) {
4148
if (strcmp (buf, "/dev/null") == 0) {
4150
struct utimbuf timebuf;
4152
timebuf.modtime = time ((time_t *) 0);
4153
timebuf.actime = timebuf.modtime;
4155
if ((utime (device, &timebuf)) != 0)
4156
gdm_debug ("Problem updating access time of pseudo-device %s", device);
4158
gdm_debug ("Touching pseudo-device %s",
4161
gdm_debug ("Device %s points to %s", device, buf);
4164
gdm_debug ("Device %s is not a symlink", device);
4171
gdm_slave_get_display_device (GdmDisplay *d)
4173
gchar *device_name = NULL;
4177
device_name = gdm_get_vt_device (d->vtnum);
4180
* Default to the value in the GDM configuration for the
4181
* display number. Allow pseudo devices.
4183
if (device_name == NULL && d->device_name != NULL) {
4184
device_name = gdm_slave_update_pseudo_device (d,
4188
/* If not VT, then use default local value from configuration */
4189
if (device_name == NULL) {
4190
const char *dev_local =
4191
gdm_daemon_config_get_value_string (GDM_KEY_UTMP_LINE_ATTACHED);
4193
if (dev_local != NULL) {
4194
device_name = gdm_slave_update_pseudo_device (d,
4200
* If a remote display, then use default remote value from
4203
const char *dev_remote =
4204
gdm_daemon_config_get_value_string (GDM_KEY_UTMP_LINE_REMOTE);
4205
if (dev_remote != NULL) {
4206
device_name = gdm_slave_update_pseudo_device (d,
4211
gdm_debug ("Display device is %s for display %s", device_name, d->name);
4212
return (device_name);
4216
gdm_slave_write_utmp_wtmp_record (GdmDisplay *d,
4217
GdmSessionRecordType record_type,
4218
const gchar *username,
4221
#if defined(HAVE_UTMPX_H)
4222
struct utmpx record = { 0 };
4223
struct utmpx *u = NULL;
4225
struct utmp record = { 0 };
4227
GTimeVal now = { 0 };
4228
gchar *device_name = NULL;
4231
device_name = gdm_slave_get_display_device (d);
4233
gdm_debug ("Writing %s utmp-wtmp record",
4234
record_type == GDM_SESSION_RECORD_TYPE_LOGIN ? "session" :
4235
record_type == GDM_SESSION_RECORD_TYPE_LOGOUT ? "logout" :
4236
"failed session attempt");
4238
if (record_type != GDM_SESSION_RECORD_TYPE_LOGOUT) {
4240
* It is possible that PAM failed before
4241
* it mapped the user input into a valid username
4242
* so we fallback to try using "(unknown)". We
4243
* don't ever log user input directly, because
4244
* we don't want passwords entered into the
4245
* username entry to accidently get logged.
4247
if (username != NULL) {
4248
#if defined(HAVE_UT_UT_USER)
4249
strncpy (record.ut_user,
4251
sizeof (record.ut_user));
4252
#elif defined(HAVE_UT_UT_NAME)
4253
strncpy (record.ut_name,
4255
sizeof (record.ut_name));
4258
g_assert (record_type == GDM_SESSION_RECORD_TYPE_FAILED_ATTEMPT);
4259
#if defined(HAVE_UT_UT_USER)
4260
strncpy (record.ut_user,
4262
sizeof (record.ut_user));
4263
#elif defined(HAVE_UT_UT_NAME)
4264
strncpy (record.ut_name,
4266
sizeof (record.ut_name));
4270
#if defined(HAVE_UT_UT_USER)
4271
gdm_debug ("utmp-wtmp: Using username %*s",
4272
(int) sizeof (record.ut_user),
4274
#elif defined(HAVE_UT_UT_NAME)
4275
gdm_debug ("utmp-wtmp: Using username %*s",
4276
(int) sizeof (record.ut_name),
4281
#if defined(HAVE_UT_UT_TYPE)
4282
if (record_type == GDM_SESSION_RECORD_TYPE_LOGOUT) {
4283
record.ut_type = DEAD_PROCESS;
4284
gdm_debug ("utmp-wtmp: Using type DEAD_PROCESS");
4286
record.ut_type = USER_PROCESS;
4287
gdm_debug ("utmp-wtmp: Using type USER_PROCESS");
4291
#if defined(HAVE_UT_UT_PID)
4292
record.ut_pid = pid;
4293
gdm_debug ("utmp-wtmp: Using pid %d", (gint)record.ut_pid);
4296
#if defined(HAVE_UT_UT_TV)
4297
g_get_current_time (&now);
4298
record.ut_tv.tv_sec = now.tv_sec;
4299
gdm_debug ("utmp-wtmp: Using time %ld", (glong) record.ut_tv.tv_sec);
4300
#elif defined(HAVE_UT_UT_TIME)
4301
time (&record.ut_time);
4304
#if defined(HAVE_UT_UT_ID)
4305
strncpy (record.ut_id, d->name, sizeof (record.ut_id));
4306
gdm_debug ("utmp-wtmp: Using id %*s",
4307
(int) sizeof (record.ut_id),
4311
if (device_name != NULL) {
4312
g_assert (g_str_has_prefix (device_name, "/dev/"));
4313
strncpy (record.ut_line, device_name + strlen ("/dev/"),
4314
sizeof (record.ut_line));
4315
g_free (device_name);
4319
gdm_debug ("utmp-wtmp: Using line %*s",
4320
(int) sizeof (record.ut_line),
4323
#if defined(HAVE_UT_UT_HOST)
4325
if (! d->attached && g_str_has_prefix (d->name, ":")) {
4326
host = g_strdup_printf ("%s%s",
4330
host = g_strdup (d->name);
4334
strncpy (record.ut_host, host, sizeof (record.ut_host));
4337
gdm_debug ("utmp-wtmp: Using hostname %*s",
4338
(int) sizeof (record.ut_host),
4341
#ifdef HAVE_UT_SYSLEN
4342
record.ut_syslen = MIN (strlen (host), sizeof (record.ut_host));
4347
switch (record_type)
4349
case GDM_SESSION_RECORD_TYPE_LOGIN:
4350
gdm_debug ("Login utmp/wtmp record");
4351
#if defined(HAVE_UPDWTMPX)
4352
updwtmpx (GDM_NEW_RECORDS_FILE, &record);
4353
#elif defined(HAVE_LOGWTMP) && defined(HAVE_UT_UT_HOST) && !defined(HAVE_LOGIN)
4354
#if defined(HAVE_UT_UT_USER)
4355
logwtmp (record.ut_line, record.ut_user, record.ut_host);
4356
#elif defined(HAVE_UT_UT_NAME)
4357
logwtmp (record.ut_line, record.ut_name, record.ut_host);
4361
#if defined(HAVE_GETUTXENT)
4362
/* Update if entry already exists */
4363
while ((u = getutxent ()) != NULL) {
4364
if (u->ut_type == USER_PROCESS &&
4365
(record.ut_line != NULL &&
4366
(strncmp (u->ut_line, record.ut_line,
4367
sizeof (u->ut_line)) == 0 ||
4368
u->ut_pid == record.ut_pid))) {
4370
gdm_debug ("Updating existing utmp record");
4371
pututxline (&record);
4377
/* Add new entry if update did not work */
4378
if (u == (struct utmpx *)NULL) {
4379
gdm_debug ("Adding new utmp record");
4380
pututxline (&record);
4382
#elif defined(HAVE_LOGIN)
4388
case GDM_SESSION_RECORD_TYPE_LOGOUT:
4389
gdm_debug ("Logout utmp/wtmp record");
4391
#if defined(HAVE_UPDWTMPX)
4392
updwtmpx (GDM_NEW_RECORDS_FILE, &record);
4393
#elif defined(HAVE_LOGWTMP)
4394
logwtmp (record.ut_line, "", "");
4397
#if defined(HAVE_GETUTXENT)
4400
while ((u = getutxent ()) != NULL &&
4401
(u = getutxid (&record)) != NULL) {
4403
gdm_debug ("Removing utmp record");
4404
if (u->ut_pid == pid &&
4405
u->ut_type == DEAD_PROCESS) {
4410
u->ut_type = DEAD_PROCESS;
4411
u->ut_tv.tv_sec = record.ut_tv.tv_sec;
4412
u->ut_exit.e_termination = 0;
4413
u->ut_exit.e_exit = 0;
4421
#elif defined(HAVE_LOGOUT)
4422
logout (record.ut_line);
4426
case GDM_SESSION_RECORD_TYPE_FAILED_ATTEMPT:
4427
#if defined(HAVE_UPDWTMPX)
4428
gdm_debug ("Writing failed session attempt record to "
4429
GDM_BAD_RECORDS_FILE);
4430
updwtmpx (GDM_BAD_RECORDS_FILE, &record);
3923
4437
gdm_slave_session_start (void)
3925
struct passwd *pwent;
3926
const char *home_dir = NULL;
3927
char *save_session = NULL, *session = NULL, *language = NULL, *usrsess, *usrlang;
3928
char *gnome_session = NULL;
3930
gboolean savesess = FALSE, savelang = FALSE;
3931
gboolean usrcfgok = FALSE, authok = FALSE;
3932
gboolean home_dir_ok = FALSE;
3933
gboolean failsafe = FALSE;
3934
time_t session_start_time, end_time;
3942
gdm_debug ("gdm_slave_session_start: Attempting session for user '%s'",
3945
pwent = getpwnam (login);
3947
if G_UNLIKELY (pwent == NULL) {
3948
/* This is sort of an "assert", this should NEVER happen */
3950
gdm_slave_whack_greeter ();
3951
gdm_slave_exit (DISPLAY_REMANAGE,
3952
_("%s: User passed auth but getpwnam (%s) failed!"), "gdm_slave_session_start", login);
3955
logged_in_uid = uid = pwent->pw_uid;
3956
logged_in_gid = gid = pwent->pw_gid;
3958
/* Run the PostLogin script */
3959
if G_UNLIKELY (gdm_slave_exec_script (d, gdm_get_value_string (GDM_KEY_POSTLOGIN),
3961
TRUE /* pass_stdout */) != EXIT_SUCCESS &&
3962
/* ignore errors in failsafe modes */
3964
gdm_verify_cleanup (d);
3965
gdm_error (_("%s: Execution of PostLogin script returned > 0. Aborting."), "gdm_slave_session_start");
3966
/* script failed so just try again */
3973
* Set euid, gid to user before testing for user's $HOME since root
3974
* does not always have access to the user's $HOME directory.
3976
if G_UNLIKELY (setegid (pwent->pw_gid) != 0 ||
3977
seteuid (pwent->pw_uid) != 0) {
3978
gdm_error ("Cannot set effective user/group id");
3979
gdm_verify_cleanup (d);
3980
session_started = FALSE;
3984
if G_UNLIKELY (pwent->pw_dir == NULL ||
3985
! g_file_test (pwent->pw_dir, G_FILE_TEST_IS_DIR)) {
3986
char *msg = g_strdup_printf (
3987
_("Your home directory is listed as:\n'%s'\n"
3988
"but it does not appear to exist. "
3989
"Do you want to log in with the / (root) "
3990
"directory as your home directory?\n\n"
3991
"It is unlikely anything will work unless "
3992
"you use a failsafe session."),
3993
ve_sure_string (pwent->pw_dir));
3995
/* Set euid, egid to root:gdm to manage user interaction */
3997
setegid (gdm_get_gdmgid ());
3999
gdm_error (_("%s: Home directory for %s: '%s' does not exist!"),
4000
"gdm_slave_session_start",
4002
ve_sure_string (pwent->pw_dir));
4004
/* Check what the user wants to do */
4005
if ( ! gdm_failsafe_yesno (d, msg)) {
4007
gdm_verify_cleanup (d);
4008
session_started = FALSE;
4014
/* Reset euid, egid back to user */
4015
if G_UNLIKELY (setegid (pwent->pw_gid) != 0 ||
4016
seteuid (pwent->pw_uid) != 0) {
4017
gdm_error ("Cannot set effective user/group id");
4018
gdm_verify_cleanup (d);
4019
session_started = FALSE;
4023
home_dir_ok = FALSE;
4027
home_dir = pwent->pw_dir;
4030
if G_LIKELY (home_dir_ok) {
4031
/* Sanity check on ~user/.dmrc */
4032
usrcfgok = gdm_file_check ("gdm_slave_session_start", pwent->pw_uid,
4033
home_dir, ".dmrc", TRUE, FALSE,
4034
gdm_get_value_int (GDM_KEY_USER_MAX_FILE),
4035
gdm_get_value_int (GDM_KEY_RELAX_PERM));
4040
if G_LIKELY (usrcfgok) {
4041
gdm_get_user_session_lang (&usrsess, &usrlang, home_dir, &savesess);
4043
/* This won't get displayed if the .dmrc file simply doesn't
4044
* exist since we pass absentok=TRUE when we call gdm_file_check
4047
GTK_MESSAGE_WARNING,
4048
_("User's $HOME/.dmrc file is being ignored. "
4049
"This prevents the default session "
4050
"and language from being saved. File "
4051
"should be owned by user and have 644 "
4052
"permissions. User's $HOME directory "
4053
"must be owned by user and not writable "
4054
"by other users."));
4055
usrsess = g_strdup ("");
4056
usrlang = g_strdup ("");
4059
NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
4062
tmp = gdm_ensure_extension (usrsess, ".desktop");
4063
session = gdm_slave_greeter_ctl (GDM_SESS, tmp);
4066
if (session != NULL &&
4067
strcmp (session, GDM_RESPONSE_CANCEL) == 0) {
4068
gdm_debug ("User canceled login");
4069
gdm_verify_cleanup (d);
4070
session_started = FALSE;
4075
language = gdm_slave_greeter_ctl (GDM_LANG, usrlang);
4076
if (language != NULL &&
4077
strcmp (language, GDM_RESPONSE_CANCEL) == 0) {
4078
gdm_debug ("User canceled login");
4079
gdm_verify_cleanup (d);
4080
session_started = FALSE;
4085
session = g_strdup (usrsess);
4086
language = g_strdup (usrlang);
4089
tmp = gdm_strip_extension (session, ".desktop");
4093
if (ve_string_empty (session)) {
4095
session = find_a_session ();
4096
if (session == NULL) {
4097
/* we're running out of options */
4098
session = g_strdup (GDM_SESSION_FAILSAFE_GNOME);
4102
if G_LIKELY (ve_string_empty (language)) {
4110
gdm_debug ("Initial setting: session: '%s' language: '%s'\n",
4111
session, ve_sure_string (language));
4113
/* save this session as the users session */
4114
save_session = g_strdup (session);
4117
char *ret = gdm_slave_greeter_ctl (GDM_SSESS, "");
4118
if ( ! ve_string_empty (ret))
4122
ret = gdm_slave_greeter_ctl (GDM_SLANG, "");
4123
if ( ! ve_string_empty (ret))
4127
gdm_debug ("gdm_slave_session_start: Authentication completed. Whacking greeter");
4129
gdm_slave_whack_greeter ();
4132
if (gdm_get_value_bool (GDM_KEY_KILL_INIT_CLIENTS))
4133
gdm_server_whack_clients (d->dsp);
4135
/* Now that we will set up the user authorization we will
4136
need to run session_stop to whack it */
4137
session_started = TRUE;
4139
/* Setup cookie -- We need this information during cleanup, thus
4140
* cookie handling is done before fork()ing */
4142
if G_UNLIKELY (setegid (pwent->pw_gid) != 0 ||
4143
seteuid (pwent->pw_uid) != 0) {
4144
gdm_error ("Cannot set effective user/group id");
4145
gdm_slave_quick_exit (DISPLAY_REMANAGE);
4148
authok = gdm_auth_user_add (d, pwent->pw_uid,
4149
/* Only pass the home_dir if
4151
home_dir_ok ? home_dir : NULL);
4153
/* FIXME: this should be smarter and only do this on out-of-diskspace
4155
if G_UNLIKELY ( ! authok && home_dir_ok) {
4156
/* try wiping the .xsession-errors file (and perhaps other things)
4157
in an attempt to gain disk space */
4158
if (wipe_xsession_errors (pwent, home_dir, home_dir_ok)) {
4159
gdm_error ("Tried wiping some old user session errors files "
4160
"to make disk space and will try adding user auth "
4163
authok = gdm_auth_user_add (d, pwent->pw_uid,
4164
/* Only pass the home_dir if
4166
home_dir_ok ? home_dir : NULL);
4170
NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
4172
if G_UNLIKELY ( ! authok) {
4173
gdm_debug ("gdm_slave_session_start: Auth not OK");
4177
_("GDM could not write to your authorization "
4178
"file. This could mean that you are out of "
4179
"disk space or that your home directory could "
4180
"not be opened for writing. In any case, it "
4181
"is not possible to log in. Please contact "
4182
"your system administrator"));
4184
gdm_slave_session_stop (FALSE /* run_post_session */,
4185
FALSE /* no_shutdown_check */);
4187
gdm_slave_quick_exit (DISPLAY_REMANAGE);
4190
if G_UNLIKELY (strcmp (session, GDM_SESSION_FAILSAFE_GNOME) == 0 ||
4191
strcmp (session, GDM_SESSION_FAILSAFE_XTERM) == 0 ||
4192
g_ascii_strcasecmp (session, "failsafe") == 0 /* hack */)
4195
if G_LIKELY ( ! failsafe) {
4196
char *exec = gdm_get_session_exec (session, FALSE /* check_try_exec */);
4197
if ( ! ve_string_empty (exec) &&
4198
strcmp (exec, "failsafe") == 0)
4203
/* Write out the Xservers file */
4204
gdm_slave_send_num (GDM_SOP_WRITE_X_SERVERS, 0 /* bogus */);
4206
if G_LIKELY (d->dsp != NULL) {
4209
XSetInputFocus (d->dsp, PointerRoot,
4210
RevertToPointerRoot, CurrentTime);
4212
/* return left pointer */
4213
xcursor = XCreateFontCursor (d->dsp, GDK_LEFT_PTR);
4214
XDefineCursor (d->dsp,
4215
DefaultRootWindow (d->dsp),
4217
XFreeCursor (d->dsp, xcursor);
4218
XSync (d->dsp, False);
4221
/* Init the ~/.xsession-errors stuff */
4222
d->xsession_errors_bytes = 0;
4223
d->xsession_errors_fd = -1;
4224
d->session_output_fd = -1;
4226
logfilefd = open_xsession_errors (pwent,
4230
if G_UNLIKELY (logfilefd < 0 ||
4231
pipe (logpipe) != 0) {
4233
VE_IGNORE_EINTR (close (logfilefd));
4237
/* don't completely rely on this, the user
4238
* could reset time or do other crazy things */
4239
session_start_time = time (NULL);
4241
/* Start user process */
4242
gdm_sigchld_block_push ();
4243
gdm_sigterm_block_push ();
4244
pid = d->sesspid = fork ();
4246
gdm_unset_signals ();
4247
gdm_sigterm_block_pop ();
4248
gdm_sigchld_block_pop ();
4253
gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Error forking user session"), "gdm_slave_session_start");
4256
if G_LIKELY (logfilefd >= 0) {
4257
VE_IGNORE_EINTR (close (logpipe[0]));
4260
session_child_run (pwent,
4272
gdm_assert_not_reached ();
4278
/* this clears internal cache */
4279
gdm_get_session_exec (NULL, FALSE);
4281
if G_LIKELY (logfilefd >= 0) {
4282
d->xsession_errors_fd = logfilefd;
4283
d->session_output_fd = logpipe[0];
4284
/* make the output read fd non-blocking */
4285
fcntl (d->session_output_fd, F_SETFL, O_NONBLOCK);
4286
VE_IGNORE_EINTR (close (logpipe[1]));
4289
/* We must be root for this, and we are, but just to make sure */
4290
NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
4291
/* Reset all the process limits, pam may have set some up for our process and that
4292
is quite evil. But pam is generally evil, so this is to be expected. */
4293
gdm_reset_limits ();
4296
g_free (save_session);
4298
g_free (gnome_session);
4300
gdm_slave_send_num (GDM_SOP_SESSPID, pid);
4302
gdm_sigchld_block_push ();
4303
wp = slave_waitpid_setpid (d->sesspid);
4304
gdm_sigchld_block_pop ();
4310
/* finish reading the session output if any of it is still there */
4311
finish_session_output (TRUE);
4313
/* Now still as root make the system authfile readable by others,
4314
and therefore by the gdm user */
4315
VE_IGNORE_EINTR (g_chmod (GDM_AUTHFILE (d), 0644));
4317
end_time = time (NULL);
4319
gdm_debug ("Session: start_time: %ld end_time: %ld",
4320
(long)session_start_time, (long)end_time);
4322
/* 66 is a very magical number signifying failure in GDM */
4323
if G_UNLIKELY ((d->last_sess_status != 66) &&
4324
(/* sanity */ end_time >= session_start_time) &&
4325
(end_time - 10 <= session_start_time) &&
4326
/* only if the X server still exist! */
4328
gdm_debug ("Session less than 10 seconds!");
4330
/* FIXME: perhaps do some checking to display a better error,
4331
* such as gnome-session missing and such things. */
4332
gdm_error_box_full (d,
4333
GTK_MESSAGE_WARNING,
4334
_("Your session only lasted less than "
4335
"10 seconds. If you have not logged out "
4336
"yourself, this could mean that there is "
4337
"some installation problem or that you may "
4338
"be out of diskspace. Try logging in with "
4339
"one of the failsafe sessions to see if you "
4340
"can fix this problem."),
4341
(d->xsession_errors_filename != NULL) ?
4342
_("View details (~/.xsession-errors file)") :
4344
d->xsession_errors_filename,
4348
gdm_slave_session_stop (pid != 0 /* run_post_session */,
4349
FALSE /* no_shutdown_check */);
4351
gdm_debug ("gdm_slave_session_start: Session ended OK (now all finished)");
4439
struct passwd *pwent;
4440
const char *home_dir = NULL;
4441
char *save_session = NULL, *session = NULL, *language = NULL, *usrsess, *usrlang;
4442
char *gnome_session = NULL;
4443
#ifdef WITH_CONSOLE_KIT
4444
char *ck_session_cookie;
4447
gboolean savesess = FALSE, savelang = FALSE;
4448
gboolean usrcfgok = FALSE, authok = FALSE;
4449
gboolean home_dir_ok = FALSE;
4450
gboolean failsafe = FALSE;
4451
time_t session_start_time, end_time;
4459
gdm_debug ("gdm_slave_session_start: Attempting session for user '%s'",
4462
pwent = getpwnam (login_user);
4464
if G_UNLIKELY (pwent == NULL) {
4465
/* This is sort of an "assert", this should NEVER happen */
4467
gdm_slave_whack_greeter ();
4468
gdm_slave_exit (DISPLAY_REMANAGE,
4469
_("%s: User passed auth but getpwnam (%s) failed!"), "gdm_slave_session_start", login_user);
4472
logged_in_uid = uid = pwent->pw_uid;
4473
logged_in_gid = gid = pwent->pw_gid;
4475
/* Run the PostLogin script */
4476
if G_UNLIKELY (gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_POSTLOGIN),
4478
TRUE /* pass_stdout */) != EXIT_SUCCESS &&
4479
/* ignore errors in failsafe modes */
4481
gdm_verify_cleanup (d);
4482
gdm_error (_("%s: Execution of PostLogin script returned > 0. Aborting."), "gdm_slave_session_start");
4483
/* script failed so just try again */
4488
* Set euid, gid to user before testing for user's $HOME since root
4489
* does not always have access to the user's $HOME directory.
4491
if G_UNLIKELY (setegid (pwent->pw_gid) != 0 ||
4492
seteuid (pwent->pw_uid) != 0) {
4493
gdm_error ("Cannot set effective user/group id");
4494
gdm_verify_cleanup (d);
4495
session_started = FALSE;
4499
if G_UNLIKELY (pwent->pw_dir == NULL ||
4500
! g_file_test (pwent->pw_dir, G_FILE_TEST_IS_DIR)) {
4502
char *msg = g_strdup_printf (
4503
_("Your home directory is listed as: '%s' "
4504
"but it does not appear to exist. "
4505
"Do you want to log in with the / (root) "
4506
"directory as your home directory? "
4507
"It is unlikely anything will work unless "
4508
"you use a failsafe session."),
4509
ve_sure_string (pwent->pw_dir));
4511
/* Set euid, egid to root:gdm to manage user interaction */
4513
setegid (gdm_daemon_config_get_gdmgid ());
4515
gdm_error (_("%s: Home directory for %s: '%s' does not exist!"),
4516
"gdm_slave_session_start",
4518
ve_sure_string (pwent->pw_dir));
4520
/* Check what the user wants to do */
4521
yesno_msg = g_strdup_printf ("yesno_msg=%s", msg);
4522
gdm_slave_send_string (GDM_SOP_SHOW_YESNO_DIALOG, yesno_msg);
4526
if (strcmp (gdm_ack_response, "no") == 0) {
4527
gdm_verify_cleanup (d);
4528
session_started = FALSE;
4531
g_free (gdm_ack_response);
4532
gdm_ack_response = NULL;
4537
g_free (gdm_ack_response);
4538
gdm_ack_response = NULL;
4540
/* Reset euid, egid back to user */
4541
if G_UNLIKELY (setegid (pwent->pw_gid) != 0 ||
4542
seteuid (pwent->pw_uid) != 0) {
4543
gdm_error ("Cannot set effective user/group id");
4544
gdm_verify_cleanup (d);
4545
session_started = FALSE;
4549
home_dir_ok = FALSE;
4553
home_dir = pwent->pw_dir;
4556
if G_LIKELY (home_dir_ok) {
4557
/* Sanity check on ~user/.dmrc */
4558
usrcfgok = gdm_file_check ("gdm_slave_session_start", pwent->pw_uid,
4559
home_dir, ".dmrc", TRUE, FALSE,
4560
gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE),
4561
gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM));
4566
if G_LIKELY (usrcfgok) {
4567
gdm_daemon_config_get_user_session_lang (&usrsess, &usrlang, home_dir, &savesess);
4569
/* This won't get displayed if the .dmrc file simply doesn't
4570
* exist since we pass absentok=TRUE when we call gdm_file_check
4572
gdm_errorgui_error_box (d,
4573
GTK_MESSAGE_WARNING,
4574
_("User's $HOME/.dmrc file is being ignored. "
4575
"This prevents the default session "
4576
"and language from being saved. File "
4577
"should be owned by user and have 644 "
4578
"permissions. User's $HOME directory "
4579
"must be owned by user and not writable "
4580
"by other users."));
4581
usrsess = g_strdup ("");
4582
usrlang = g_strdup ("");
4585
NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
4588
tmp = gdm_ensure_extension (usrsess, ".desktop");
4589
session = gdm_slave_greeter_ctl (GDM_SESS, tmp);
4592
if (session != NULL &&
4593
strcmp (session, GDM_RESPONSE_CANCEL) == 0) {
4594
gdm_debug ("User canceled login");
4595
gdm_verify_cleanup (d);
4596
session_started = FALSE;
4601
language = gdm_slave_greeter_ctl (GDM_LANG, usrlang);
4602
if (language != NULL &&
4603
strcmp (language, GDM_RESPONSE_CANCEL) == 0) {
4604
gdm_debug ("User canceled login");
4605
gdm_verify_cleanup (d);
4606
session_started = FALSE;
4611
session = g_strdup (usrsess);
4612
language = g_strdup (usrlang);
4615
tmp = gdm_strip_extension (session, ".desktop");
4619
if (ve_string_empty (session)) {
4621
session = find_a_session ();
4622
if (session == NULL) {
4623
/* we're running out of options */
4624
session = g_strdup (GDM_SESSION_FAILSAFE_GNOME);
4628
if G_LIKELY (ve_string_empty (language)) {
4635
gdm_debug ("Initial setting: session: '%s' language: '%s'\n",
4636
session, ve_sure_string (language));
4638
/* save this session as the users session */
4639
save_session = g_strdup (session);
4642
char *ret = gdm_slave_greeter_ctl (GDM_SSESS, "");
4643
if ( ! ve_string_empty (ret))
4647
ret = gdm_slave_greeter_ctl (GDM_SLANG, "");
4648
if ( ! ve_string_empty (ret))
4652
gdm_debug ("gdm_slave_session_start: Authentication completed. Whacking greeter");
4654
gdm_slave_whack_greeter ();
4657
if (gdm_daemon_config_get_value_bool (GDM_KEY_KILL_INIT_CLIENTS))
4658
gdm_server_whack_clients (d->dsp);
4661
* If the desktop file specifies that there are special Xserver
4662
* arguments to use, then restart the Xserver with them.
4664
d->xserver_session_args = gdm_daemon_config_get_session_xserver_args (session);
4665
if (d->xserver_session_args) {
4666
gdm_server_stop (d);
4667
gdm_slave_send_num (GDM_SOP_XPID, 0);
4668
gdm_server_start (d, TRUE, FALSE, 20, 5);
4669
gdm_slave_send_num (GDM_SOP_XPID, d->servpid);
4670
g_free (d->xserver_session_args);
4671
d->xserver_session_args = NULL;
4674
/* Now that we will set up the user authorization we will
4675
need to run session_stop to whack it */
4676
session_started = TRUE;
4678
/* Setup cookie -- We need this information during cleanup, thus
4679
* cookie handling is done before fork()ing */
4681
if G_UNLIKELY (setegid (pwent->pw_gid) != 0 ||
4682
seteuid (pwent->pw_uid) != 0) {
4683
gdm_error ("Cannot set effective user/group id");
4684
gdm_slave_quick_exit (DISPLAY_REMANAGE);
4687
authok = gdm_auth_user_add (d, pwent->pw_uid,
4688
/* Only pass the home_dir if
4690
home_dir_ok ? home_dir : NULL);
4692
/* FIXME: this should be smarter and only do this on out-of-diskspace
4694
if G_UNLIKELY ( ! authok && home_dir_ok) {
4695
/* try wiping the .xsession-errors file (and perhaps other things)
4696
in an attempt to gain disk space */
4697
if (wipe_xsession_errors (pwent, home_dir, home_dir_ok)) {
4698
gdm_error ("Tried wiping some old user session errors files "
4699
"to make disk space and will try adding user auth "
4702
authok = gdm_auth_user_add (d, pwent->pw_uid,
4703
/* Only pass the home_dir if
4705
home_dir_ok ? home_dir : NULL);
4709
NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
4711
if G_UNLIKELY ( ! authok) {
4712
gdm_debug ("gdm_slave_session_start: Auth not OK");
4714
gdm_errorgui_error_box (d,
4716
_("GDM could not write to your authorization "
4717
"file. This could mean that you are out of "
4718
"disk space or that your home directory could "
4719
"not be opened for writing. In any case, it "
4720
"is not possible to log in. Please contact "
4721
"your system administrator"));
4723
gdm_slave_session_stop (FALSE /* run_post_session */,
4724
FALSE /* no_shutdown_check */);
4726
gdm_slave_quick_exit (DISPLAY_REMANAGE);
4729
if G_UNLIKELY (strcmp (session, GDM_SESSION_FAILSAFE_GNOME) == 0 ||
4730
strcmp (session, GDM_SESSION_FAILSAFE_XTERM) == 0 ||
4731
g_ascii_strcasecmp (session, "failsafe") == 0 /* hack */)
4734
if G_LIKELY ( ! failsafe) {
4735
char *exec = gdm_daemon_config_get_session_exec (session, FALSE /* check_try_exec */);
4736
if ( ! ve_string_empty (exec) &&
4737
strcmp (exec, "failsafe") == 0)
4742
/* Write out the Xservers file */
4743
gdm_slave_send_num (GDM_SOP_WRITE_X_SERVERS, 0 /* bogus */);
4745
if G_LIKELY (d->dsp != NULL) {
4748
XSetInputFocus (d->dsp, PointerRoot,
4749
RevertToPointerRoot, CurrentTime);
4751
/* return left pointer */
4752
xcursor = XCreateFontCursor (d->dsp, GDK_LEFT_PTR);
4753
XDefineCursor (d->dsp,
4754
DefaultRootWindow (d->dsp),
4756
XFreeCursor (d->dsp, xcursor);
4757
XSync (d->dsp, False);
4760
/* Init the ~/.xsession-errors stuff */
4761
d->xsession_errors_bytes = 0;
4762
d->xsession_errors_fd = -1;
4763
d->session_output_fd = -1;
4765
logfilefd = open_xsession_errors (pwent,
4769
if G_UNLIKELY (logfilefd < 0 ||
4770
pipe (logpipe) != 0) {
4772
VE_IGNORE_EINTR (close (logfilefd));
4776
/* don't completely rely on this, the user
4777
* could reset time or do other crazy things */
4778
session_start_time = time (NULL);
4780
#ifdef WITH_CONSOLE_KIT
4781
ck_session_cookie = open_ck_session (pwent, d, session);
4784
gdm_debug ("Forking user session");
4786
/* Start user process */
4787
gdm_sigchld_block_push ();
4788
gdm_sigterm_block_push ();
4789
pid = d->sesspid = fork ();
4791
gdm_unset_signals ();
4792
gdm_sigterm_block_pop ();
4793
gdm_sigchld_block_pop ();
4798
gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Error forking user session"), "gdm_slave_session_start");
4803
gboolean has_language;
4805
has_language = (language != NULL) && (language[0] != '\0');
4807
if ((gdm_system_locale != NULL) && (!has_language)) {
4808
lang = gdm_system_locale;
4813
if G_LIKELY (logfilefd >= 0) {
4814
VE_IGNORE_EINTR (close (logpipe[0]));
4817
session_child_run (pwent,
4822
#ifdef WITH_CONSOLE_KIT
4832
g_assert_not_reached ();
4836
always_restart_greeter = FALSE;
4837
if (!savelang && language && strcmp (usrlang, language)) {
4838
if (gdm_system_locale != NULL) {
4839
g_setenv ("LANG", gdm_system_locale, TRUE);
4840
setlocale (LC_ALL, "");
4841
g_unsetenv ("GDM_LANG");
4842
/* for "GDM_LANG" */
4843
gdm_clearenv_no_lang ();
4846
gdm_slave_greeter_ctl_no_ret (GDM_SETLANG, DEFAULT_LANGUAGE);
4851
/* this clears internal cache */
4852
gdm_daemon_config_get_session_exec (NULL, FALSE);
4854
if G_LIKELY (logfilefd >= 0) {
4855
d->xsession_errors_fd = logfilefd;
4856
d->session_output_fd = logpipe[0];
4857
/* make the output read fd non-blocking */
4858
fcntl (d->session_output_fd, F_SETFL, O_NONBLOCK);
4859
VE_IGNORE_EINTR (close (logpipe[1]));
4862
/* We must be root for this, and we are, but just to make sure */
4863
NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
4864
/* Reset all the process limits, pam may have set some up for our process and that
4865
is quite evil. But pam is generally evil, so this is to be expected. */
4866
gdm_reset_limits ();
4869
g_free (save_session);
4871
g_free (gnome_session);
4873
gdm_slave_write_utmp_wtmp_record (d,
4874
GDM_SESSION_RECORD_TYPE_LOGIN,
4878
gdm_slave_send_num (GDM_SOP_SESSPID, pid);
4880
gdm_sigchld_block_push ();
4881
wp = slave_waitpid_setpid (d->sesspid);
4882
gdm_sigchld_block_pop ();
4888
/* finish reading the session output if any of it is still there */
4889
finish_session_output (TRUE);
4891
/* Now still as root make the system authfile readable by others,
4892
and therefore by the gdm user */
4893
VE_IGNORE_EINTR (g_chmod (GDM_AUTHFILE (d), 0644));
4895
end_time = time (NULL);
4897
gdm_debug ("Session: start_time: %ld end_time: %ld",
4898
(long)session_start_time, (long)end_time);
4900
/* Sync to get notified in the case the X server died
4902
XSync (d->dsp, False);
4904
/* 66 is a very magical number signifying failure in GDM */
4905
if G_UNLIKELY ((d->last_sess_status != 66) &&
4906
(/* sanity */ end_time >= session_start_time) &&
4907
(end_time - 10 <= session_start_time) &&
4908
/* only if the X server still exist! */
4912
_("Your session only lasted less than "
4913
"10 seconds. If you have not logged out "
4914
"yourself, this could mean that there is "
4915
"some installation problem or that you may "
4916
"be out of diskspace. Try logging in with "
4917
"one of the failsafe sessions to see if you "
4918
"can fix this problem.");
4920
/* FIXME: perhaps do some checking to display a better error,
4921
* such as gnome-session missing and such things. */
4922
gdm_debug ("Session less than 10 seconds!");
4923
msg_string = g_strdup_printf ("type=%d$$error_msg=%s$$details_label=%s$$details_file=%s$$uid=%d$$gid=%d",
4924
GTK_MESSAGE_WARNING,error_msg,
4925
(d->xsession_errors_filename != NULL) ?
4926
_("View details (~/.xsession-errors file)") :
4928
d->xsession_errors_filename,
4931
gdm_slave_send_string (GDM_SOP_SHOW_ERROR_DIALOG, msg_string);
4933
g_free (msg_string);
4937
#ifdef WITH_CONSOLE_KIT
4938
if (ck_session_cookie != NULL) {
4939
close_ck_session (ck_session_cookie);
4940
g_free (ck_session_cookie);
4944
if ((pid != 0) && (d->last_sess_status != -1)) {
4945
gdm_debug ("session '%d' exited with status '%d', recording logout",
4946
pid, d->last_sess_status);
4947
gdm_slave_write_utmp_wtmp_record (d,
4948
GDM_SESSION_RECORD_TYPE_LOGOUT,
4953
gdm_slave_session_stop (pid != 0 /* run_post_session */,
4954
FALSE /* no_shutdown_check */);
4956
gdm_debug ("gdm_slave_session_start: Session ended OK (now all finished)");
4357
4962
gdm_slave_session_stop (gboolean run_post_session,
4358
4963
gboolean no_shutdown_check)
4360
struct passwd *pwent;
4361
char *x_servers_file;
4366
session_started = FALSE;
4368
local_login = login;
4371
/* don't use NEVER_FAILS_ here this can be called from places
4372
kind of exiting and it's ok if this doesn't work (when shouldn't
4377
gdm_slave_send_num (GDM_SOP_SESSPID, 0);
4379
/* Now still as root make the system authfile not readable by others,
4380
and therefore not by the gdm user */
4381
if (GDM_AUTHFILE (d) != NULL) {
4382
VE_IGNORE_EINTR (g_chmod (GDM_AUTHFILE (d), 0640));
4385
gdm_debug ("gdm_slave_session_stop: %s on %s", local_login, d->name);
4387
/* Note we use the info in the structure here since if we get passed
4388
* a 0 that means the process is already dead.
4389
* FIXME: Maybe we should waitpid here, note make sure this will
4390
* not create a hang! */
4391
gdm_sigchld_block_push ();
4393
kill (- (d->sesspid), SIGTERM);
4394
gdm_sigchld_block_pop ();
4397
This is to fix #126071, that is kill processes that may still hold open
4398
fd's in the home directory to allow a clean unmount. However note of course
4399
that this is a race. */
4400
/* FIX HACK: We will get an xioerror out of whack clients if the user crashed
4401
X with ctl-alt-backspace. So, we need to ignore xioerror while we do this.
4402
Otherwise, we end up in a longjmp to quick_exit which will prevent things
4403
like PostSession scripts from processing */
4404
switch (Setjmp (ignore_xioerror_jmp)) {
4406
/* Having just set the jump point, activate the error handler that returns
4407
us to the next case */
4408
XSetIOErrorHandler (gdm_slave_ignore_xioerror_handler);
4411
/* Here means we saw an xioerror and ignored it. */
4412
/* xioerror will cause this to drop back into whack_clients, but I think
4413
that is okay because I haven't seen it do so more than once */
4414
gdm_debug ("gdm_slave_session_stop: back here from xioerror");
4418
gdm_server_whack_clients (d->dsp);
4420
/* Now we should care about xioerror once again??? */
4421
XSetIOErrorHandler (gdm_slave_xioerror_handler);
4423
#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD)
4424
/* let the other processes die perhaps or whatnot */
4428
finish_session_output (run_post_session /* do_read */);
4430
if (local_login == NULL)
4433
pwent = getpwnam (local_login); /* PAM overwrites our pwent */
4435
x_servers_file = gdm_make_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR),
4436
d->name, ".Xservers");
4438
/* if there was a session that ran, run the PostSession script */
4439
if (run_post_session) {
4440
/* Execute post session script */
4441
gdm_debug ("gdm_slave_session_stop: Running post session script");
4442
gdm_slave_exec_script (d, gdm_get_value_string (GDM_KEY_POSTSESSION), local_login, pwent,
4443
FALSE /* pass_stdout */);
4446
VE_IGNORE_EINTR (g_unlink (x_servers_file));
4447
g_free (x_servers_file);
4449
g_free (local_login);
4451
if (pwent != NULL) {
4452
seteuid (0); /* paranoia */
4453
/* Remove display from ~user/.Xauthority */
4454
if G_LIKELY (setegid (pwent->pw_gid) == 0 &&
4455
seteuid (pwent->pw_uid) == 0) {
4456
gdm_auth_user_remove (d, pwent->pw_uid);
4459
/* don't use NEVER_FAILS_ here this can be called from places
4460
kind of exiting and it's ok if this doesn't work (when shouldn't
4469
/* things are going to be killed, so ignore errors */
4470
XSetErrorHandler (ignore_xerror_handler);
4472
gdm_verify_cleanup (d);
4476
if (need_to_quit_after_session_stop) {
4477
gdm_debug ("gdm_slave_session_stop: Final cleanup");
4479
gdm_slave_quick_exit (exit_code_to_use);
4965
struct passwd *pwent;
4966
char *x_servers_file;
4971
session_started = FALSE;
4973
local_login = login_user;
4976
/* don't use NEVER_FAILS_ here this can be called from places
4977
kind of exiting and it's ok if this doesn't work (when shouldn't
4982
gdm_slave_send_num (GDM_SOP_SESSPID, 0);
4984
/* Now still as root make the system authfile not readable by others,
4985
and therefore not by the gdm user */
4986
if (GDM_AUTHFILE (d) != NULL) {
4987
VE_IGNORE_EINTR (g_chmod (GDM_AUTHFILE (d), 0640));
4990
gdm_debug ("gdm_slave_session_stop: %s on %s", local_login, d->name);
4992
/* Note we use the info in the structure here since if we get passed
4993
* a 0 that means the process is already dead.
4994
* FIXME: Maybe we should waitpid here, note make sure this will
4995
* not create a hang! */
4996
gdm_sigchld_block_push ();
4998
kill (- (d->sesspid), SIGTERM);
4999
gdm_sigchld_block_pop ();
5001
finish_session_output (run_post_session /* do_read */);
5003
if (local_login == NULL)
5006
pwent = getpwnam (local_login); /* PAM overwrites our pwent */
5008
x_servers_file = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR),
5009
d->name, ".Xservers");
5011
/* if there was a session that ran, run the PostSession script */
5012
if (run_post_session) {
5013
/* Execute post session script */
5014
gdm_debug ("gdm_slave_session_stop: Running post session script");
5015
gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_POSTSESSION), local_login, pwent,
5016
FALSE /* pass_stdout */);
5019
VE_IGNORE_EINTR (g_unlink (x_servers_file));
5020
g_free (x_servers_file);
5022
g_free (local_login);
5024
if (pwent != NULL) {
5025
seteuid (0); /* paranoia */
5026
/* Remove display from ~user/.Xauthority */
5027
if G_LIKELY (setegid (pwent->pw_gid) == 0 &&
5028
seteuid (pwent->pw_uid) == 0) {
5029
gdm_auth_user_remove (d, pwent->pw_uid);
5032
/* don't use NEVER_FAILS_ here this can be called from places
5033
kind of exiting and it's ok if this doesn't work (when shouldn't
5042
/* things are going to be killed, so ignore errors */
5043
XSetErrorHandler (ignore_xerror_handler);
5045
gdm_verify_cleanup (d);
5049
if (need_to_quit_after_session_stop) {
5050
gdm_debug ("gdm_slave_session_stop: Final cleanup");
5052
gdm_slave_quick_exit (exit_code_to_use);
4482
5055
#ifdef __linux__
4483
/* If on Linux and the runlevel is 0 or 6 and not the runlevel that
4484
we were started in, then we are restarting or halting the machine.
4485
Probably the user selected halt or restart from the logout
4486
menu. In this case we can really just sleep for a few seconds and
4487
basically wait to be killed. I will set the default for 30 seconds
4488
and let people yell at me if this breaks something. It shouldn't.
4489
In fact it should fix things so that the login screen is not brought
4490
up again and then whacked. Waiting is safer then DISPLAY_ABORT,
4491
since if we really do get this wrong, then at the worst case the
4492
user will wait for a few moments. */
4493
if ( ! need_to_quit_after_session_stop &&
4494
! no_shutdown_check &&
4495
g_access ("/sbin/runlevel", X_OK) == 0) {
4498
FILE *fp = popen ("/sbin/runlevel", "r");
4500
fscanf (fp, "%c %d", &ign, &rnl) == 2 &&
4501
(rnl == 0 || rnl == 6) &&
4502
rnl != gdm_normal_runlevel) {
4503
/* this is a stupid loop, but we may be getting signals,
4504
so we don't want to just do sleep (30) */
4505
time_t c = time (NULL);
4506
gdm_info (_("GDM detected a halt or restart "
4509
while (c + 30 >= time (NULL)) {
4511
/* Wait 30 seconds. */
4514
select (0, NULL, NULL, NULL, &tv);
4515
/* don't want to use sleep since we're using alarm
4518
/* hmm, didn't get TERM, weird */
4519
} else if (fp != NULL) {
5056
/* If on Linux and the runlevel is 0 or 6 and not the runlevel that
5057
we were started in, then we are restarting or halting the machine.
5058
Probably the user selected halt or restart from the logout
5059
menu. In this case we can really just sleep for a few seconds and
5060
basically wait to be killed. I will set the default for 30 seconds
5061
and let people yell at me if this breaks something. It shouldn't.
5062
In fact it should fix things so that the login screen is not brought
5063
up again and then whacked. Waiting is safer then DISPLAY_ABORT,
5064
since if we really do get this wrong, then at the worst case the
5065
user will wait for a few moments. */
5066
if ( ! need_to_quit_after_session_stop &&
5067
! no_shutdown_check &&
5068
g_access ("/sbin/runlevel", X_OK) == 0) {
5069
int rnl = get_runlevel ();
5070
if ((rnl == 0 || rnl == 6) && rnl != gdm_normal_runlevel) {
5071
/* this is a stupid loop, but we may be getting signals,
5072
so we don't want to just do sleep (30) */
5073
time_t c = time (NULL);
5074
gdm_info (_("GDM detected a halt or restart "
5076
while (c + 30 >= time (NULL)) {
5078
/* Wait 30 seconds. */
5081
select (0, NULL, NULL, NULL, &tv);
5082
/* don't want to use sleep since we're using alarm
5085
/* hmm, didn't get TERM, weird */
4523
5088
#endif /* __linux__ */
5168
gdm_slave_exec_script (GdmDisplay *d, const gchar *dir, const char *login,
5169
struct passwd *pwent, gboolean pass_stdout)
5780
gdm_slave_exec_script (GdmDisplay *d,
5783
struct passwd *pwent,
5784
gboolean pass_stdout)
5175
char *x_servers_file;
5177
if G_UNLIKELY (!d || ve_string_empty (dir))
5178
return EXIT_SUCCESS;
5180
script = g_build_filename (dir, d->name, NULL);
5181
if (g_access (script, R_OK|X_OK) != 0) {
5185
if (script == NULL &&
5186
! ve_string_empty (d->hostname)) {
5187
script = g_build_filename (dir, d->hostname, NULL);
5188
if (g_access (script, R_OK|X_OK) != 0) {
5193
if (script == NULL &&
5194
SERVER_IS_XDMCP (d)) {
5195
script = g_build_filename (dir, "XDMCP", NULL);
5196
if (g_access (script, R_OK|X_OK) != 0) {
5201
if (script == NULL &&
5202
SERVER_IS_FLEXI (d)) {
5203
script = g_build_filename (dir, "Flexi", NULL);
5204
if (g_access (script, R_OK|X_OK) != 0) {
5209
if (script == NULL) {
5210
script = g_build_filename (dir, "Default", NULL);
5211
if (g_access (script, R_OK|X_OK) != 0) {
5217
if (script == NULL) {
5218
return EXIT_SUCCESS;
5221
create_temp_auth_file ();
5223
pid = gdm_fork_extra ();
5230
VE_IGNORE_EINTR (close (0));
5231
gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */
5233
if ( ! pass_stdout) {
5234
VE_IGNORE_EINTR (close (1));
5235
VE_IGNORE_EINTR (close (2));
5236
/* No error checking here - if it's messed the best response
5237
* is to ignore & try to continue */
5238
gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */
5239
gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */
5242
gdm_close_all_descriptors (3 /* from */, -1 /* except */, -1 /* except2 */);
5244
openlog ("gdm", LOG_PID, LOG_DAEMON);
5246
if (login != NULL) {
5247
g_setenv ("LOGNAME", login, TRUE);
5248
g_setenv ("USER", login, TRUE);
5249
g_setenv ("USERNAME", login, TRUE);
5251
char *gdmuser = gdm_get_value_string (GDM_KEY_USER);
5252
g_setenv ("LOGNAME", gdmuser, TRUE);
5253
g_setenv ("USER", gdmuser, TRUE);
5254
g_setenv ("USERNAME", gdmuser, TRUE);
5256
if (pwent != NULL) {
5257
if (ve_string_empty (pwent->pw_dir)) {
5788
gchar **argv = NULL;
5790
char *x_servers_file;
5795
if G_UNLIKELY (!d || ve_string_empty (dir))
5796
return EXIT_SUCCESS;
5798
script = g_build_filename (dir, d->name, NULL);
5799
if (g_access (script, R_OK|X_OK) != 0) {
5803
if (script == NULL &&
5804
! ve_string_empty (d->hostname)) {
5805
script = g_build_filename (dir, d->hostname, NULL);
5806
if (g_access (script, R_OK|X_OK) != 0) {
5811
if (script == NULL &&
5812
SERVER_IS_XDMCP (d)) {
5813
script = g_build_filename (dir, "XDMCP", NULL);
5814
if (g_access (script, R_OK|X_OK) != 0) {
5819
if (script == NULL &&
5820
SERVER_IS_FLEXI (d)) {
5821
script = g_build_filename (dir, "Flexi", NULL);
5822
if (g_access (script, R_OK|X_OK) != 0) {
5827
if (script == NULL) {
5828
script = g_build_filename (dir, "Default", NULL);
5829
if (g_access (script, R_OK|X_OK) != 0) {
5835
if (script == NULL) {
5836
return EXIT_SUCCESS;
5839
create_temp_auth_file ();
5841
gdm_debug ("Forking extra process: %s", script);
5843
extra_process = pid = gdm_fork_extra ();
5847
gdm_log_shutdown ();
5849
VE_IGNORE_EINTR (close (0));
5850
gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */
5852
if ( ! pass_stdout) {
5853
VE_IGNORE_EINTR (close (1));
5854
VE_IGNORE_EINTR (close (2));
5855
/* No error checking here - if it's messed the best response
5856
* is to ignore & try to continue */
5857
gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */
5858
gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */
5861
gdm_close_all_descriptors (3 /* from */, -1 /* except */, -1 /* except2 */);
5865
if (login != NULL) {
5866
g_setenv ("LOGNAME", login, TRUE);
5867
g_setenv ("USER", login, TRUE);
5868
g_setenv ("USERNAME", login, TRUE);
5870
const char *gdmuser = gdm_daemon_config_get_value_string (GDM_KEY_USER);
5871
g_setenv ("LOGNAME", gdmuser, TRUE);
5872
g_setenv ("USER", gdmuser, TRUE);
5873
g_setenv ("USERNAME", gdmuser, TRUE);
5875
if (pwent != NULL) {
5876
if (ve_string_empty (pwent->pw_dir)) {
5877
g_setenv ("HOME", "/", TRUE);
5878
g_setenv ("PWD", "/", TRUE);
5879
VE_IGNORE_EINTR (g_chdir ("/"));
5881
g_setenv ("HOME", pwent->pw_dir, TRUE);
5882
g_setenv ("PWD", pwent->pw_dir, TRUE);
5883
VE_IGNORE_EINTR (g_chdir (pwent->pw_dir));
5885
VE_IGNORE_EINTR (g_chdir ("/"));
5886
g_setenv ("PWD", "/", TRUE);
5889
g_setenv ("SHELL", pwent->pw_shell, TRUE);
5258
5891
g_setenv ("HOME", "/", TRUE);
5259
5892
g_setenv ("PWD", "/", TRUE);
5260
5893
VE_IGNORE_EINTR (g_chdir ("/"));
5262
g_setenv ("HOME", pwent->pw_dir, TRUE);
5263
g_setenv ("PWD", pwent->pw_dir, TRUE);
5264
VE_IGNORE_EINTR (g_chdir (pwent->pw_dir));
5266
VE_IGNORE_EINTR (g_chdir ("/"));
5267
g_setenv ("PWD", "/", TRUE);
5894
g_setenv ("SHELL", "/bin/sh", TRUE);
5270
g_setenv ("SHELL", pwent->pw_shell, TRUE);
5272
g_setenv ("HOME", "/", TRUE);
5273
g_setenv ("PWD", "/", TRUE);
5274
VE_IGNORE_EINTR (g_chdir ("/"));
5275
g_setenv ("SHELL", "/bin/sh", TRUE);
5278
set_xnest_parent_stuff ();
5280
/* some env for use with the Pre and Post scripts */
5281
x_servers_file = gdm_make_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR),
5282
d->name, ".Xservers");
5283
g_setenv ("X_SERVERS", x_servers_file, TRUE);
5284
g_free (x_servers_file);
5285
if (SERVER_IS_XDMCP (d))
5286
g_setenv ("REMOTE_HOST", d->hostname, TRUE);
5289
if (GDM_AUTHFILE (d) != NULL)
5290
g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE);
5292
g_unsetenv ("XAUTHORITY");
5293
g_setenv ("DISPLAY", d->name, TRUE);
5294
g_setenv ("PATH", gdm_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
5295
g_setenv ("RUNNING_UNDER_GDM", "true", TRUE);
5296
if ( ! ve_string_empty (d->theme_name))
5297
g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
5298
argv = ve_split (script);
5299
VE_IGNORE_EINTR (execv (argv[0], argv));
5300
syslog (LOG_ERR, _("%s: Failed starting: %s"), "gdm_slave_exec_script",
5302
_exit (EXIT_SUCCESS);
5305
gdm_slave_whack_temp_auth_file ();
5307
syslog (LOG_ERR, _("%s: Can't fork script process!"), "gdm_slave_exec_script");
5308
return EXIT_SUCCESS;
5311
gdm_wait_for_extra (&status);
5313
gdm_slave_whack_temp_auth_file ();
5317
if (WIFEXITED (status))
5318
return WEXITSTATUS (status);
5320
return EXIT_SUCCESS;
5897
set_xnest_parent_stuff ();
5899
/* some env for use with the Pre and Post scripts */
5900
x_servers_file = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR),
5901
d->name, ".Xservers");
5902
g_setenv ("X_SERVERS", x_servers_file, TRUE);
5903
g_free (x_servers_file);
5904
if (SERVER_IS_XDMCP (d))
5905
g_setenv ("REMOTE_HOST", d->hostname, TRUE);
5908
if (GDM_AUTHFILE (d) != NULL)
5909
g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE);
5911
g_unsetenv ("XAUTHORITY");
5912
g_setenv ("DISPLAY", d->name, TRUE);
5914
g_setenv ("WINDOWPATH", d->windowpath, TRUE);
5915
g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
5916
g_setenv ("RUNNING_UNDER_GDM", "true", TRUE);
5917
if ( ! ve_string_empty (d->theme_name))
5918
g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
5921
ctrun = g_strdup_printf (
5922
"/bin/sh -c \"/usr/bin/ctrun -l child -i none %s\"",
5924
g_shell_parse_argv (ctrun, NULL, &argv, NULL);
5927
g_shell_parse_argv (script, NULL, &argv, NULL);
5930
VE_IGNORE_EINTR (execv (argv[0], argv));
5932
g_error (_("%s: Failed starting: %s"),
5933
"gdm_slave_exec_script",
5935
_exit (EXIT_SUCCESS);
5938
gdm_slave_whack_temp_auth_file ();
5940
g_error (_("%s: Can't fork script process!"), "gdm_slave_exec_script");
5941
return EXIT_SUCCESS;
5944
gdm_wait_for_extra (extra_process, &status);
5946
gdm_slave_whack_temp_auth_file ();
5950
if (WIFEXITED (status))
5951
return WEXITSTATUS (status);
5953
return EXIT_SUCCESS;
5347
/* The user name for automatic/timed login may be parameterized by
5980
/* The user name for automatic/timed login may be parameterized by
5348
5981
host/display. */
5351
gdm_parse_enriched_login (const gchar *s, GdmDisplay *display)
5984
gdm_slave_parse_enriched_login (GdmDisplay *d, const gchar *s)
5353
gchar cmd, in_buffer[20];
5355
gint pipe1[2], in_buffer_len;
5362
str = g_string_new (NULL);
5364
while (s[0] != '\0') {
5366
if (s[0] == '%' && s[1] != 0) {
5373
g_string_append (str, display->hostname);
5377
g_string_append (str, display->name);
5381
g_string_append_c (str, '%');
5388
g_string_append_c (str, *s);
5987
gchar in_buffer[20];
5988
gint pipe1[2], in_buffer_len;
5989
gchar **argv = NULL;
5995
str = gdm_slave_parse_enriched_string (d, s);
5997
/* Sometimes it is not convenient to use the display or hostname as
5998
user name. A script may be used to generate the automatic/timed
5999
login name based on the display/host by ending the name with the
6002
if (str->len > 0 && str->str[str->len - 1] == '|') {
6003
g_string_truncate (str, str->len - 1);
6004
if G_UNLIKELY (pipe (pipe1) < 0) {
6005
gdm_error (_("%s: Failed creating pipe"),
6006
"gdm_slave_parse_enriched_login");
6008
gdm_debug ("Forking extra process: %s", str->str);
6010
extra_process = pid = gdm_fork_extra ();
6014
/* The child will write the username to stdout based on the DISPLAY
6015
environment variable. */
6017
VE_IGNORE_EINTR (close (pipe1[0]));
6018
if G_LIKELY (pipe1[1] != STDOUT_FILENO) {
6019
VE_IGNORE_EINTR (dup2 (pipe1[1], STDOUT_FILENO));
6022
gdm_log_shutdown ();
6024
gdm_close_all_descriptors (3 /* from */, pipe1[1] /* except */, -1 /* except2 */);
6029
if (GDM_AUTHFILE (d) != NULL)
6030
g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE);
6032
g_unsetenv ("XAUTHORITY");
6033
g_setenv ("DISPLAY", d->name, TRUE);
6035
g_setenv ("WINDOWPATH", d->windowpath, TRUE);
6036
if (SERVER_IS_XDMCP (d))
6037
g_setenv ("REMOTE_HOST", d->hostname, TRUE);
6038
g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
6039
g_setenv ("SHELL", "/bin/sh", TRUE);
6040
g_setenv ("RUNNING_UNDER_GDM", "true", TRUE);
6041
if ( ! ve_string_empty (d->theme_name))
6042
g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
6044
g_shell_parse_argv (str->str, NULL, &argv, NULL);
6046
VE_IGNORE_EINTR (execv (argv[0], argv));
6048
gdm_error (_("%s: Failed executing: %s"),
6049
"gdm_slave_parse_enriched_login",
6051
_exit (EXIT_SUCCESS);
6054
gdm_error (_("%s: Can't fork script process!"),
6055
"gdm_slave_parse_enriched_login");
6056
VE_IGNORE_EINTR (close (pipe1[0]));
6057
VE_IGNORE_EINTR (close (pipe1[1]));
6061
/* The parent reads username from the pipe a chunk at a time */
6062
VE_IGNORE_EINTR (close (pipe1[1]));
6063
g_string_truncate (str, 0);
6065
VE_IGNORE_EINTR (in_buffer_len = read (pipe1[0], in_buffer,
6066
sizeof (in_buffer) - 1));
6067
if (in_buffer_len > 0) {
6068
in_buffer[in_buffer_len] = '\0';
6069
g_string_append (str, in_buffer);
6071
} while (in_buffer_len > 0);
6073
if (str->len > 0 && str->str[str->len - 1] == '\n')
6074
g_string_truncate (str, str->len - 1);
6076
VE_IGNORE_EINTR (close (pipe1[0]));
6078
gdm_wait_for_extra (extra_process, NULL);
5393
/* Sometimes it is not convenient to use the display or hostname as
5394
user name. A script may be used to generate the automatic/timed
5395
login name based on the display/host by ending the name with the
5398
if (str->len > 0 && str->str[str->len - 1] == '|') {
5399
g_string_truncate (str, str->len - 1);
5400
if G_UNLIKELY (pipe (pipe1) < 0) {
5401
gdm_error (_("%s: Failed creating pipe"),
5402
"gdm_parse_enriched_login");
5404
pid = gdm_fork_extra ();
5409
/* The child will write the username to stdout based on the DISPLAY
5410
environment variable. */
5412
VE_IGNORE_EINTR (close (pipe1[0]));
5413
if G_LIKELY (pipe1[1] != STDOUT_FILENO) {
5414
VE_IGNORE_EINTR (dup2 (pipe1[1], STDOUT_FILENO));
5419
gdm_close_all_descriptors (3 /* from */, pipe1[1] /* except */, -1 /* except2 */);
5421
openlog ("gdm", LOG_PID, LOG_DAEMON);
5424
if (GDM_AUTHFILE (display) != NULL)
5425
g_setenv ("XAUTHORITY", GDM_AUTHFILE (display), TRUE);
5427
g_unsetenv ("XAUTHORITY");
5428
g_setenv ("DISPLAY", display->name, TRUE);
5429
if (SERVER_IS_XDMCP (display))
5430
g_setenv ("REMOTE_HOST", display->hostname, TRUE);
5431
g_setenv ("PATH", gdm_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
5432
g_setenv ("SHELL", "/bin/sh", TRUE);
5433
g_setenv ("RUNNING_UNDER_GDM", "true", TRUE);
5434
if ( ! ve_string_empty (d->theme_name))
5435
g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
5437
argv = ve_split (str->str);
5438
VE_IGNORE_EINTR (execv (argv[0], argv));
5439
gdm_error (_("%s: Failed executing: %s"),
5440
"gdm_parse_enriched_login",
5442
_exit (EXIT_SUCCESS);
5445
gdm_error (_("%s: Can't fork script process!"),
5446
"gdm_parse_enriched_login");
5447
VE_IGNORE_EINTR (close (pipe1[0]));
5448
VE_IGNORE_EINTR (close (pipe1[1]));
5452
/* The parent reads username from the pipe a chunk at a time */
5453
VE_IGNORE_EINTR (close (pipe1[1]));
5454
g_string_truncate (str, 0);
5456
VE_IGNORE_EINTR (in_buffer_len = read (pipe1[0], in_buffer,
5457
sizeof (in_buffer) - 1));
5458
if (in_buffer_len > 0) {
5459
in_buffer[in_buffer_len] = '\0';
5460
g_string_append (str, in_buffer);
5462
} while (in_buffer_len > 0);
5464
if (str->len > 0 && str->str[str->len - 1] == '\n')
5465
g_string_truncate (str, str->len - 1);
5467
VE_IGNORE_EINTR (close (pipe1[0]));
5469
gdm_wait_for_extra (NULL);
5474
if (!ve_string_empty(str->str) && gdm_is_user_valid(str->str))
5475
return g_string_free (str, FALSE);
5478
/* "If an empty or otherwise invalid username is returned [by the script]
5479
* automatic login [and timed login] is not performed." -- GDM manual
5481
/* fixme: also turn off automatic login */
5482
gdm_set_value_bool(GDM_KEY_TIMED_LOGIN_ENABLE, FALSE);
5483
d->timed_login_ok = FALSE;
5484
do_timed_login = FALSE;
5485
g_string_free(str, TRUE);
6083
if (!ve_string_empty(str->str) && gdm_is_user_valid(str->str))
6084
return g_string_free (str, FALSE);
6087
/* "If an empty or otherwise invalid username is returned [by the script]
6088
* automatic login [and timed login] is not performed." -- GDM manual
6090
/* fixme: also turn off automatic login */
6091
gdm_daemon_config_set_value_bool(GDM_KEY_TIMED_LOGIN_ENABLE, FALSE);
6092
d->timed_login_ok = FALSE;
6093
do_timed_login = FALSE;
6094
g_string_free (str, TRUE);