source:
proiecte/PPPP/gdm/debian/patches/09_gdmsetup.patch
@
141
Last change on this file since 141 was 134, checked in by , 14 years ago | |
---|---|
File size: 133.9 KB |
-
configure.ac
# # Description: Add GDM Setup # Ubuntu: https://bugs.launchpad.net/ubuntu/+source/gdm/+bug/395299 # Upstream: http://bugzilla.gnome.org/show_bug.cgi?id=587750 # diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/configure.ac gdm-2.28.0.new/configure.ac
old new 107 107 AC_SUBST(GCONF_CFLAGS) 108 108 AC_SUBST(GCONF_LIBS) 109 109 110 PKG_CHECK_MODULES(GDMSETUP, 111 dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION 112 gtk+-2.0 >= $GTK_REQUIRED_VERSION 113 gmodule-2.0 114 ) 115 AC_SUBST(GDMSETUP_CFLAGS) 116 AC_SUBST(GDMSETUP_LIBS) 117 110 118 PKG_CHECK_MODULES(SIMPLE_GREETER, 111 119 dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION 112 120 gtk+-2.0 >= $GTK_REQUIRED_VERSION … … 1352 1360 daemon/Makefile 1353 1361 docs/Makefile 1354 1362 gui/Makefile 1363 gui/gdmsetup/Makefile 1355 1364 gui/simple-greeter/Makefile 1356 1365 gui/simple-greeter/libnotificationarea/Makefile 1357 1366 gui/simple-chooser/Makefile 1358 1367 gui/user-switch-applet/Makefile 1359 1368 utils/Makefile 1360 1369 data/gdm.conf 1370 data/gdm.policy 1361 1371 data/Makefile 1362 1372 data/faces/Makefile 1363 1373 data/greeter-autostart/Makefile -
gui/gdmsetup/gdmsetup.c
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/gui/gdmsetup/gdmsetup.c gdm-2.28.0.new/gui/gdmsetup/gdmsetup.c
old new 1 #ifdef HAVE_CONFIG_H 2 #include "config.h" 3 #endif 4 5 #include <string.h> 6 #include <stdlib.h> 7 #include <gtk/gtk.h> 8 #include <gdk/gdkkeysyms.h> 9 #include <dbus/dbus-glib.h> 10 #include <glib/gi18n.h> 11 12 #include "gdm-user-manager.h" 13 14 #define MAX_USERS_IN_COMBO_BOX 20 15 16 /* User interface */ 17 static GtkBuilder *ui; 18 static GtkWidget *dialog, *unlock_button, *option_vbox; 19 static GtkWidget *user_combo, *user_entry, *delay_spin; 20 static GtkWidget *auto_login_radio, *login_delay_box, *login_delay_check; 21 22 /* Timer to delay application of configuration */ 23 static guint apply_timeout = 0; 24 25 /* Flag to show when information is loaded */ 26 static gboolean loaded = FALSE; 27 28 /* Flag to show when information is loaded */ 29 static gboolean locked = TRUE; 30 31 /* True if the user selection method is a combo box, False if an entry */ 32 static gboolean user_list_is_combo = TRUE; 33 34 /* User information */ 35 static GdmUserManager *user_manager; 36 37 /* Proxy to GDM settings */ 38 static DBusGProxy *proxy = NULL; 39 40 41 static gchar * 42 get_value (const gchar *key, gchar *def) 43 { 44 gchar *value; 45 GError *error = NULL; 46 47 if (!dbus_g_proxy_call (proxy, "GetValue", &error, 48 G_TYPE_STRING, key, G_TYPE_INVALID, 49 G_TYPE_STRING, &value, G_TYPE_INVALID)) { 50 g_warning ("Error calling GetValue('%s'): %s", key, error->message); 51 return def; 52 } 53 54 return value; 55 } 56 57 58 static gboolean 59 set_value (const gchar *key, const gchar *value) 60 { 61 GError *error = NULL; 62 63 dbus_g_proxy_call (proxy, "SetValue", &error, 64 G_TYPE_STRING, key, 65 G_TYPE_STRING, value, G_TYPE_INVALID, G_TYPE_INVALID); 66 if (error) { 67 g_warning ("Error calling SetValue('%s', '%s'): %s", key, value, error->message); 68 return FALSE; 69 } 70 71 return TRUE; 72 } 73 74 75 static gboolean 76 get_boolean_value (const gchar *key, gboolean def) 77 { 78 gchar *value; 79 gboolean result; 80 81 value = get_value (key, NULL); 82 if (!value) 83 return def; 84 result = strcmp (value, "true") == 0; 85 g_free (value); 86 return result; 87 } 88 89 90 static gint 91 get_integer_value (const gchar *key, gint def) 92 { 93 gchar *value; 94 gint result; 95 char *end; 96 97 value = get_value (key, NULL); 98 if (!value || value[0] == '\0') 99 result = def; 100 else { 101 result = strtol (value, &end, 10); 102 if (*end != '\0') 103 result = def; 104 } 105 106 if (value) 107 g_free (value); 108 return result; 109 } 110 111 112 static gboolean 113 set_boolean_value (const gchar *key, gboolean value) 114 { 115 return set_value (key, value ? "true" : "false"); 116 } 117 118 119 static gboolean 120 set_integer_value (const gchar *key, gint value) 121 { 122 char value_string[1024]; 123 snprintf(value_string, 1024, "%d", value); 124 return set_value (key, value_string); 125 } 126 127 128 static void 129 update_config () 130 { 131 GtkTreeModel *model; 132 GtkTreeIter iter; 133 gchar *user = NULL; 134 gint delay = 0; 135 gboolean auto_login = FALSE, timed_login = FALSE, error = FALSE; 136 137 if (apply_timeout != 0) { 138 g_source_remove (apply_timeout); 139 apply_timeout = 0; 140 } 141 142 if (user_list_is_combo) { 143 model = gtk_combo_box_get_model (GTK_COMBO_BOX (user_combo)); 144 if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (user_combo), &iter)) 145 gtk_tree_model_get (model, &iter, 1, &user, -1); 146 } 147 else 148 user = g_strdup (gtk_entry_get_text (GTK_ENTRY (user_entry))); 149 150 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (auto_login_radio))) { 151 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (login_delay_check))) 152 timed_login = TRUE; 153 else 154 auto_login = TRUE; 155 } 156 157 delay = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (delay_spin)); 158 159 g_debug ("set user='%s', auto=%s, timed=%s, delay=%d", 160 user, 161 auto_login ? "True" : "False", 162 timed_login ? "True" : "False", delay); 163 164 if (!set_boolean_value ("daemon/TimedLoginEnable", timed_login) || 165 !set_boolean_value ("daemon/AutomaticLoginEnable", auto_login) || 166 !set_value ("daemon/TimedLogin", user) || 167 !set_value ("daemon/AutomaticLogin", user) || 168 !set_integer_value ("daemon/TimedLoginDelay", delay)) 169 error = FALSE; 170 171 if (user) 172 g_free (user); 173 } 174 175 176 G_MODULE_EXPORT 177 void 178 gdm_capplet_response_cb (GtkWidget *widget, gint response_id) 179 { 180 if (response_id != 1) 181 gtk_main_quit (); 182 } 183 184 185 static void 186 unlock_response_cb (DBusGProxy *proxy, 187 DBusGProxyCall *call_id, 188 void *user_data) 189 { 190 gboolean is_unlocked; 191 GError *error = NULL; 192 193 dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_BOOLEAN, &is_unlocked, G_TYPE_INVALID); 194 if (error) { 195 g_warning ("Failed to unlock: %s", error->message); 196 g_error_free (error); 197 return; 198 } 199 200 if (!is_unlocked) 201 return; 202 203 locked = FALSE; 204 gtk_widget_set_sensitive (unlock_button, FALSE); 205 gtk_widget_set_sensitive (option_vbox, loaded && !locked); 206 } 207 208 209 G_MODULE_EXPORT 210 void 211 unlock_button_clicked_cb (GtkWidget *widget) 212 { 213 dbus_g_proxy_begin_call (proxy, "Unlock", unlock_response_cb, NULL, NULL, G_TYPE_INVALID); 214 } 215 216 217 G_MODULE_EXPORT 218 void 219 login_delay_check_toggled_cb (GtkWidget *widget) 220 { 221 gtk_widget_set_sensitive (delay_spin, 222 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (login_delay_check))); 223 224 if (loaded) 225 update_config (); 226 } 227 228 229 static gboolean 230 delayed_apply_cb () 231 { 232 update_config (); 233 return FALSE; 234 } 235 236 237 G_MODULE_EXPORT 238 void 239 apply_config_cb (GtkWidget *widget) 240 { 241 if (loaded) { 242 if (apply_timeout != 0) 243 g_source_remove (apply_timeout); 244 apply_timeout = g_timeout_add (200, (GSourceFunc)delayed_apply_cb, NULL); 245 } 246 } 247 248 249 static void 250 init_login_delay () 251 { 252 gint delay; 253 254 if (get_boolean_value ("daemon/TimedLoginEnable", FALSE)) 255 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (login_delay_check), TRUE); 256 257 delay = get_integer_value ("daemon/TimedLoginDelay", 30); 258 259 g_debug ("init delay=%d", delay); 260 261 gtk_spin_button_set_value (GTK_SPIN_BUTTON (delay_spin), delay); 262 } 263 264 265 G_MODULE_EXPORT 266 void 267 automatic_login_toggle_cb (GtkWidget *automatic_login_toggle) 268 { 269 gboolean automatic_login; 270 271 automatic_login = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (automatic_login_toggle)); 272 gtk_widget_set_sensitive (login_delay_box, automatic_login); 273 gtk_widget_set_sensitive (user_combo, automatic_login); 274 gtk_widget_set_sensitive (user_entry, automatic_login); 275 276 if (loaded) 277 update_config (); 278 } 279 280 281 G_MODULE_EXPORT 282 void 283 default_user_combo_box_changed_cb (void) 284 { 285 if (loaded) { 286 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (auto_login_radio), TRUE); 287 update_config (); 288 } 289 } 290 291 292 static void 293 init_default_user (void) 294 { 295 GtkTreeModel *model; 296 GtkTreeIter iter; 297 gboolean auto_login, timed_login, active; 298 gchar *user = NULL; 299 300 auto_login = get_boolean_value ("daemon/AutomaticLoginEnable", FALSE); 301 timed_login = get_boolean_value ("daemon/TimedLoginEnable", FALSE); 302 303 if (auto_login) 304 user = get_value ("daemon/AutomaticLogin", NULL); 305 if (user == NULL) 306 user = get_value ("daemon/TimedLogin", NULL); 307 308 g_debug ("init user='%s' auto=%s", user, auto_login || timed_login ? "True" : "False"); 309 310 if (auto_login || timed_login) 311 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (auto_login_radio), TRUE); 312 313 if (!user_list_is_combo) { 314 if (user != NULL) 315 gtk_entry_set_text (GTK_ENTRY (user_entry), user); 316 } 317 else { 318 model = gtk_combo_box_get_model (GTK_COMBO_BOX (user_combo)); 319 active = gtk_tree_model_get_iter_first (model, &iter); 320 321 /* If no user then use first available */ 322 if (user == NULL) { 323 if (active) 324 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (user_combo), &iter); 325 } 326 else { 327 while (user != NULL && active) { 328 gchar *u; 329 gboolean matched; 330 331 gtk_tree_model_get (model, &iter, 1, &u, -1); 332 matched = strcmp (user, u) == 0; 333 g_free (u); 334 if (matched) { 335 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (user_combo), &iter); 336 break; 337 } 338 339 active = gtk_tree_model_iter_next (model, &iter); 340 } 341 } 342 } 343 344 g_free (user); 345 } 346 347 348 static void add_user (GdmUser *user) 349 { 350 GtkListStore *model; 351 GtkTreeIter iter; 352 GString *label; 353 354 model = GTK_LIST_STORE (gtk_builder_get_object (ui, "login_user_model")); 355 gtk_list_store_append (model, &iter); 356 label = g_string_new(""); 357 g_string_printf (label, "%s (%s)", gdm_user_get_real_name (user), gdm_user_get_user_name (user)); 358 gtk_list_store_set (model, &iter, 359 0, label->str, 360 1, gdm_user_get_user_name (user), 361 -1); 362 g_string_free (label, TRUE); 363 } 364 365 366 static void 367 users_loaded_cb(GdmUserManager *manager) 368 { 369 GSList *users, *item; 370 371 users = gdm_user_manager_list_users (user_manager); 372 373 if (g_slist_length (users) > MAX_USERS_IN_COMBO_BOX) { 374 user_list_is_combo = FALSE; 375 gtk_widget_hide (user_combo); 376 gtk_widget_show (user_entry); 377 } 378 else { 379 for (item = users; item; item = item->next) 380 add_user ((GdmUser *) item->data); 381 } 382 383 init_default_user (); 384 385 loaded = TRUE; 386 gtk_widget_set_sensitive (option_vbox, loaded && !locked); 387 } 388 389 390 static void 391 user_added_cb (GdmUserManager *manager, GdmUser *user) 392 { 393 if (loaded) 394 add_user (user); 395 } 396 397 398 static void 399 split_text (const gchar *text, const gchar *prefix_label_name, const gchar *suffix_label_name) 400 { 401 gchar **tokens; 402 GtkWidget *prefix_label, *suffix_label; 403 404 prefix_label = GTK_WIDGET (gtk_builder_get_object (ui, prefix_label_name)); 405 suffix_label = GTK_WIDGET (gtk_builder_get_object (ui, suffix_label_name)); 406 407 tokens = g_strsplit (text, "%s", 2); 408 if (tokens[0] != NULL && tokens[1] != NULL) { 409 if (tokens[0][0] != '\0') 410 gtk_label_set_text (GTK_LABEL (prefix_label), g_strstrip (tokens[0])); 411 else 412 gtk_widget_hide (prefix_label); 413 if (tokens[1][0] != '\0') 414 gtk_label_set_text (GTK_LABEL (suffix_label), g_strstrip (tokens[1])); 415 else 416 gtk_widget_hide (suffix_label); 417 } 418 g_strfreev (tokens); 419 } 420 421 422 int main (int argc, char **argv) 423 { 424 GtkCellRenderer *renderer; 425 DBusGConnection *connection; 426 GError *error = NULL; 427 428 bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); 429 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 430 textdomain (GETTEXT_PACKAGE); 431 432 gtk_init (&argc, &argv); 433 434 connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); 435 if (error) { 436 g_warning ("Failed to get system bus: %s", error->message); 437 return 1; 438 } 439 proxy = dbus_g_proxy_new_for_name (connection, 440 "org.gnome.DisplayManager", 441 "/org/gnome/DisplayManager/Settings", 442 "org.gnome.DisplayManager.Settings"); 443 444 ui = gtk_builder_new (); 445 gtk_builder_add_from_file (ui, UIDIR "/gdmsetup.ui", &error); 446 if (error) { 447 g_warning ("Failed to load UI: %s", error->message); 448 return 1; 449 } 450 dialog = GTK_WIDGET (gtk_builder_get_object (ui, "gdm_capplet")); 451 unlock_button = GTK_WIDGET (gtk_builder_get_object (ui, "unlock_button")); 452 option_vbox = GTK_WIDGET (gtk_builder_get_object (ui, "gdm_capplet_vbox")); 453 user_combo = GTK_WIDGET (gtk_builder_get_object (ui, "default_user_combo_box")); 454 user_entry = GTK_WIDGET (gtk_builder_get_object (ui, "default_user_entry")); 455 delay_spin = GTK_WIDGET (gtk_builder_get_object (ui, "login_delay_spin")); 456 auto_login_radio = GTK_WIDGET (gtk_builder_get_object (ui, "automatic_login_radio")); 457 login_delay_box = GTK_WIDGET (gtk_builder_get_object (ui, "login_delay_box")); 458 login_delay_check = GTK_WIDGET (gtk_builder_get_object (ui, "login_delay_check")); 459 gtk_builder_connect_signals (ui, NULL); 460 461 /* Translators: Label for choosing which user to log in as. '%s' is replaced with an input field. */ 462 split_text (_("Log in as %s automatically"), "user_prefix_label", "user_suffix_label"); 463 /* Translators: Label for choosing the login delay. '%s' is replaced with an input field. */ 464 split_text (_("Allow %s seconds for anyone else to log in first"), "delay_prefix_label", "delay_suffix_label"); 465 466 init_login_delay (); 467 468 renderer = gtk_cell_renderer_text_new (); 469 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (user_combo), renderer, TRUE); 470 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (user_combo), renderer, "text", 0); 471 472 user_manager = gdm_user_manager_ref_default (); 473 g_signal_connect (user_manager, "users-loaded", G_CALLBACK (users_loaded_cb), NULL); 474 g_signal_connect (user_manager, "user-added", G_CALLBACK (user_added_cb), NULL); 475 476 gtk_widget_hide (user_entry); 477 478 gtk_widget_set_sensitive (option_vbox, FALSE); 479 gtk_widget_show (dialog); 480 481 gtk_main (); 482 483 return 0; 484 } -
gui/gdmsetup/gdmsetup.desktop.in
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/gui/gdmsetup/gdmsetup.desktop.in gdm-2.28.0.new/gui/gdmsetup/gdmsetup.desktop.in
old new 1 [Desktop Entry] 2 _Name=Login Screen 3 _Comment=Configure login screen behavior 4 Exec=gdmsetup 5 Icon=gdm-setup 6 StartupNotify=true 7 Terminal=false 8 Type=Application 9 Categories=GNOME;GTK;Settings;System; 10 X-GNOME-Bugzilla-Bugzilla=GNOME 11 X-GNOME-Bugzilla-Product=gdm 12 X-GNOME-Bugzilla-Component=general -
gui/gdmsetup/gdmsetup.ui
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/gui/gdmsetup/gdmsetup.ui gdm-2.28.0.new/gui/gdmsetup/gdmsetup.ui
old new 1 <?xml version="1.0"?> 2 <interface> 3 <requires lib="gtk+" version="2.16"/> 4 <!-- interface-naming-policy project-wide --> 5 <object class="GtkListStore" id="login_user_model"> 6 <columns> 7 <!-- column-name label --> 8 <column type="gchararray"/> 9 <!-- column-name user --> 10 <column type="gchararray"/> 11 <!-- column-name icon --> 12 <column type="GdkPixbuf"/> 13 </columns> 14 </object> 15 <object class="GtkDialog" id="gdm_capplet"> 16 <property name="border_width">5</property> 17 <property name="title" translatable="yes" comments="Title of login screen settings dialog">Login Screen Settings</property> 18 <property name="resizable">False</property> 19 <property name="window_position">center</property> 20 <property name="icon_name">gdm-setup</property> 21 <property name="type_hint">normal</property> 22 <property name="has_separator">False</property> 23 <signal name="response" handler="gdm_capplet_response_cb"/> 24 <child internal-child="vbox"> 25 <object class="GtkVBox" id="dialog-vbox1"> 26 <property name="visible">True</property> 27 <property name="orientation">vertical</property> 28 <property name="spacing">12</property> 29 <child> 30 <object class="GtkVBox" id="gdm_capplet_vbox"> 31 <property name="visible">True</property> 32 <property name="orientation">vertical</property> 33 <property name="spacing">18</property> 34 <child> 35 <object class="GtkLabel" id="intro_label"> 36 <property name="visible">True</property> 37 <property name="xalign">0</property> 38 <property name="label" translatable="yes" comments="Description above login option radio buttons">When the computer starts up:</property> 39 </object> 40 <packing> 41 <property name="expand">False</property> 42 <property name="position">0</property> 43 </packing> 44 </child> 45 <child> 46 <object class="GtkVBox" id="vbox3"> 47 <property name="visible">True</property> 48 <property name="orientation">vertical</property> 49 <property name="spacing">12</property> 50 <child> 51 <object class="GtkRadioButton" id="manual_login_radio"> 52 <property name="label" translatable="yes" comments="Radio option to set login screen to prompt for user">_Show the screen for choosing who will log in</property> 53 <property name="visible">True</property> 54 <property name="can_focus">True</property> 55 <property name="receives_default">False</property> 56 <property name="use_underline">True</property> 57 <property name="active">True</property> 58 <property name="draw_indicator">True</property> 59 </object> 60 <packing> 61 <property name="expand">False</property> 62 <property name="position">0</property> 63 </packing> 64 </child> 65 <child> 66 <object class="GtkVBox" id="vbox4"> 67 <property name="visible">True</property> 68 <property name="orientation">vertical</property> 69 <property name="spacing">6</property> 70 <child> 71 <object class="GtkHBox" id="hbox1"> 72 <property name="visible">True</property> 73 <property name="spacing">6</property> 74 <child> 75 <object class="GtkRadioButton" id="automatic_login_radio"> 76 <property name="visible">True</property> 77 <property name="can_focus">True</property> 78 <property name="receives_default">False</property> 79 <property name="draw_indicator">True</property> 80 <property name="group">manual_login_radio</property> 81 <signal name="toggled" handler="automatic_login_toggle_cb"/> 82 <child> 83 <object class="GtkLabel" id="user_prefix_label"> 84 <property name="visible">True</property> 85 <property name="label">_Log in as</property> 86 <property name="use_underline">True</property> 87 </object> 88 </child> 89 </object> 90 <packing> 91 <property name="expand">False</property> 92 <property name="position">0</property> 93 </packing> 94 </child> 95 <child> 96 <object class="GtkComboBox" id="default_user_combo_box"> 97 <property name="visible">True</property> 98 <property name="sensitive">False</property> 99 <property name="model">login_user_model</property> 100 <signal name="changed" handler="default_user_combo_box_changed_cb"/> 101 </object> 102 <packing> 103 <property name="expand">False</property> 104 <property name="position">1</property> 105 </packing> 106 </child> 107 <child> 108 <object class="GtkEntry" id="default_user_entry"> 109 <property name="visible">True</property> 110 <property name="sensitive">False</property> 111 <property name="can_focus">True</property> 112 <property name="invisible_char">•</property> 113 <signal name="changed" handler="apply_config_cb"/> 114 </object> 115 <packing> 116 <property name="position">2</property> 117 </packing> 118 </child> 119 <child> 120 <object class="GtkLabel" id="user_suffix_label"> 121 <property name="visible">True</property> 122 <property name="label">automatically</property> 123 </object> 124 <packing> 125 <property name="expand">False</property> 126 <property name="position">3</property> 127 </packing> 128 </child> 129 </object> 130 <packing> 131 <property name="expand">False</property> 132 <property name="position">0</property> 133 </packing> 134 </child> 135 <child> 136 <object class="GtkAlignment" id="alignment1"> 137 <property name="visible">True</property> 138 <property name="left_padding">16</property> 139 <child> 140 <object class="GtkHBox" id="login_delay_box"> 141 <property name="visible">True</property> 142 <property name="sensitive">False</property> 143 <property name="spacing">6</property> 144 <child> 145 <object class="GtkCheckButton" id="login_delay_check"> 146 <property name="visible">True</property> 147 <property name="can_focus">True</property> 148 <property name="receives_default">False</property> 149 <property name="draw_indicator">True</property> 150 <signal name="toggled" handler="login_delay_check_toggled_cb"/> 151 <child> 152 <object class="GtkLabel" id="delay_prefix_label"> 153 <property name="visible">True</property> 154 <property name="label">_Allow</property> 155 <property name="use_underline">True</property> 156 </object> 157 </child> 158 </object> 159 <packing> 160 <property name="expand">False</property> 161 <property name="position">0</property> 162 </packing> 163 </child> 164 <child> 165 <object class="GtkSpinButton" id="login_delay_spin"> 166 <property name="visible">True</property> 167 <property name="sensitive">False</property> 168 <property name="can_focus">True</property> 169 <property name="invisible_char">•</property> 170 <property name="adjustment">adjustment1</property> 171 <signal name="value_changed" handler="apply_config_cb"/> 172 </object> 173 <packing> 174 <property name="position">1</property> 175 </packing> 176 </child> 177 <child> 178 <object class="GtkLabel" id="delay_suffix_label"> 179 <property name="visible">True</property> 180 <property name="label">seconds for anyone else to log in first</property> 181 </object> 182 <packing> 183 <property name="expand">False</property> 184 <property name="position">2</property> 185 </packing> 186 </child> 187 </object> 188 </child> 189 </object> 190 <packing> 191 <property name="expand">False</property> 192 <property name="position">1</property> 193 </packing> 194 </child> 195 </object> 196 <packing> 197 <property name="expand">False</property> 198 <property name="position">1</property> 199 </packing> 200 </child> 201 </object> 202 <packing> 203 <property name="expand">False</property> 204 <property name="position">1</property> 205 </packing> 206 </child> 207 </object> 208 <packing> 209 <property name="position">1</property> 210 </packing> 211 </child> 212 <child internal-child="action_area"> 213 <object class="GtkHButtonBox" id="dialog-action_area1"> 214 <property name="visible">True</property> 215 <property name="layout_style">end</property> 216 <child> 217 <object class="GtkButton" id="unlock_button"> 218 <property name="label" translatable="yes">_Unlock</property> 219 <property name="visible">True</property> 220 <property name="can_focus">True</property> 221 <property name="receives_default">True</property> 222 <property name="image">image1</property> 223 <property name="use_underline">True</property> 224 <signal name="clicked" handler="unlock_button_clicked_cb"/> 225 </object> 226 <packing> 227 <property name="expand">False</property> 228 <property name="fill">False</property> 229 <property name="position">0</property> 230 </packing> 231 </child> 232 <child> 233 <object class="GtkButton" id="close_button"> 234 <property name="label">gtk-close</property> 235 <property name="visible">True</property> 236 <property name="can_focus">True</property> 237 <property name="receives_default">True</property> 238 <property name="use_stock">True</property> 239 </object> 240 <packing> 241 <property name="expand">False</property> 242 <property name="fill">False</property> 243 <property name="position">1</property> 244 </packing> 245 </child> 246 </object> 247 <packing> 248 <property name="expand">False</property> 249 <property name="pack_type">end</property> 250 <property name="position">0</property> 251 </packing> 252 </child> 253 </object> 254 </child> 255 <action-widgets> 256 <action-widget response="1">unlock_button</action-widget> 257 <action-widget response="-7">close_button</action-widget> 258 </action-widgets> 259 </object> 260 <object class="GtkImage" id="image1"> 261 <property name="visible">True</property> 262 <property name="stock">gtk-dialog-authentication</property> 263 </object> 264 <object class="GtkSizeGroup" id="combo_size_group"/> 265 <object class="GtkSizeGroup" id="radio_size_group"/> 266 <object class="GtkAdjustment" id="adjustment1"> 267 <property name="lower">1</property> 268 <property name="upper">600</property> 269 <property name="step_increment">1</property> 270 </object> 271 </interface> -
gui/gdmsetup/gdm-user.c
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/gui/gdmsetup/gdm-user.c gdm-2.28.0.new/gui/gdmsetup/gdm-user.c
old new 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 2 * 3 * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>. 4 * Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 #include <config.h> 22 23 #include <float.h> 24 #include <string.h> 25 #include <sys/types.h> 26 #include <sys/stat.h> 27 #include <unistd.h> 28 29 #include <glib/gi18n.h> 30 #include <gio/gio.h> 31 #include <gtk/gtk.h> 32 33 #include "gdm-user-manager.h" 34 #include "gdm-user-private.h" 35 36 #define GDM_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_USER, GdmUserClass)) 37 #define GDM_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_USER)) 38 #define GDM_USER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), GDM_TYPE_USER, GdmUserClass)) 39 40 #define GLOBAL_FACEDIR DATADIR "/faces" 41 #define MAX_ICON_SIZE 128 42 #define MAX_FILE_SIZE 65536 43 #define MINIMAL_UID 100 44 #define RELAX_GROUP TRUE 45 #define RELAX_OTHER TRUE 46 47 enum { 48 PROP_0, 49 PROP_MANAGER, 50 PROP_REAL_NAME, 51 PROP_USER_NAME, 52 PROP_UID, 53 PROP_HOME_DIR, 54 PROP_SHELL, 55 PROP_LOGIN_FREQUENCY, 56 }; 57 58 enum { 59 ICON_CHANGED, 60 SESSIONS_CHANGED, 61 LAST_SIGNAL 62 }; 63 64 struct _GdmUser { 65 GObject parent; 66 67 GdmUserManager *manager; 68 69 uid_t uid; 70 char *user_name; 71 char *real_name; 72 char *home_dir; 73 char *shell; 74 GList *sessions; 75 gulong login_frequency; 76 77 GFileMonitor *icon_monitor; 78 }; 79 80 typedef struct _GdmUserClass 81 { 82 GObjectClass parent_class; 83 84 void (* icon_changed) (GdmUser *user); 85 void (* sessions_changed) (GdmUser *user); 86 } GdmUserClass; 87 88 static void gdm_user_finalize (GObject *object); 89 90 static guint signals[LAST_SIGNAL] = { 0 }; 91 92 G_DEFINE_TYPE (GdmUser, gdm_user, G_TYPE_OBJECT) 93 94 static int 95 session_compare (const char *a, 96 const char *b) 97 { 98 if (a == NULL) { 99 return 1; 100 } else if (b == NULL) { 101 return -1; 102 } 103 104 return strcmp (a, b); 105 } 106 107 void 108 _gdm_user_add_session (GdmUser *user, 109 const char *ssid) 110 { 111 GList *li; 112 113 g_return_if_fail (GDM_IS_USER (user)); 114 g_return_if_fail (ssid != NULL); 115 116 li = g_list_find_custom (user->sessions, ssid, (GCompareFunc)session_compare); 117 if (li == NULL) { 118 g_debug ("GdmUser: adding session %s", ssid); 119 user->sessions = g_list_prepend (user->sessions, g_strdup (ssid)); 120 g_signal_emit (user, signals[SESSIONS_CHANGED], 0); 121 } else { 122 g_debug ("GdmUser: session already present: %s", ssid); 123 } 124 } 125 126 void 127 _gdm_user_remove_session (GdmUser *user, 128 const char *ssid) 129 { 130 GList *li; 131 132 g_return_if_fail (GDM_IS_USER (user)); 133 g_return_if_fail (ssid != NULL); 134 135 li = g_list_find_custom (user->sessions, ssid, (GCompareFunc)session_compare); 136 if (li != NULL) { 137 g_debug ("GdmUser: removing session %s", ssid); 138 g_free (li->data); 139 user->sessions = g_list_delete_link (user->sessions, li); 140 g_signal_emit (user, signals[SESSIONS_CHANGED], 0); 141 } else { 142 g_debug ("GdmUser: session not found: %s", ssid); 143 } 144 } 145 146 guint 147 gdm_user_get_num_sessions (GdmUser *user) 148 { 149 return g_list_length (user->sessions); 150 } 151 152 GList * 153 gdm_user_get_sessions (GdmUser *user) 154 { 155 return user->sessions; 156 } 157 158 static void 159 _gdm_user_set_login_frequency (GdmUser *user, 160 gulong login_frequency) 161 { 162 user->login_frequency = login_frequency; 163 g_object_notify (G_OBJECT (user), "login-frequency"); 164 } 165 166 static void 167 gdm_user_set_property (GObject *object, 168 guint param_id, 169 const GValue *value, 170 GParamSpec *pspec) 171 { 172 GdmUser *user; 173 174 user = GDM_USER (object); 175 176 switch (param_id) { 177 case PROP_MANAGER: 178 user->manager = g_value_get_object (value); 179 g_assert (user->manager); 180 break; 181 case PROP_LOGIN_FREQUENCY: 182 _gdm_user_set_login_frequency (user, g_value_get_ulong (value)); 183 break; 184 default: 185 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); 186 break; 187 } 188 } 189 190 static void 191 gdm_user_get_property (GObject *object, 192 guint param_id, 193 GValue *value, 194 GParamSpec *pspec) 195 { 196 GdmUser *user; 197 198 user = GDM_USER (object); 199 200 switch (param_id) { 201 case PROP_MANAGER: 202 g_value_set_object (value, user->manager); 203 break; 204 case PROP_USER_NAME: 205 g_value_set_string (value, user->user_name); 206 break; 207 case PROP_REAL_NAME: 208 g_value_set_string (value, user->real_name); 209 break; 210 case PROP_HOME_DIR: 211 g_value_set_string (value, user->home_dir); 212 break; 213 case PROP_UID: 214 g_value_set_ulong (value, user->uid); 215 break; 216 case PROP_SHELL: 217 g_value_set_string (value, user->shell); 218 break; 219 case PROP_LOGIN_FREQUENCY: 220 g_value_set_ulong (value, user->login_frequency); 221 break; 222 default: 223 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); 224 break; 225 } 226 } 227 228 static void 229 gdm_user_class_init (GdmUserClass *class) 230 { 231 GObjectClass *gobject_class; 232 233 gobject_class = G_OBJECT_CLASS (class); 234 235 gobject_class->set_property = gdm_user_set_property; 236 gobject_class->get_property = gdm_user_get_property; 237 gobject_class->finalize = gdm_user_finalize; 238 239 g_object_class_install_property (gobject_class, 240 PROP_MANAGER, 241 g_param_spec_object ("manager", 242 _("Manager"), 243 _("The user manager object this user is controlled by."), 244 GDM_TYPE_USER_MANAGER, 245 (G_PARAM_READWRITE | 246 G_PARAM_CONSTRUCT_ONLY))); 247 248 g_object_class_install_property (gobject_class, 249 PROP_REAL_NAME, 250 g_param_spec_string ("real-name", 251 "Real Name", 252 "The real name to display for this user.", 253 NULL, 254 G_PARAM_READABLE)); 255 256 g_object_class_install_property (gobject_class, 257 PROP_UID, 258 g_param_spec_ulong ("uid", 259 "User ID", 260 "The UID for this user.", 261 0, G_MAXULONG, 0, 262 G_PARAM_READABLE)); 263 g_object_class_install_property (gobject_class, 264 PROP_USER_NAME, 265 g_param_spec_string ("user-name", 266 "User Name", 267 "The login name for this user.", 268 NULL, 269 G_PARAM_READABLE)); 270 g_object_class_install_property (gobject_class, 271 PROP_HOME_DIR, 272 g_param_spec_string ("home-directory", 273 "Home Directory", 274 "The home directory for this user.", 275 NULL, 276 G_PARAM_READABLE)); 277 g_object_class_install_property (gobject_class, 278 PROP_SHELL, 279 g_param_spec_string ("shell", 280 "Shell", 281 "The shell for this user.", 282 NULL, 283 G_PARAM_READABLE)); 284 g_object_class_install_property (gobject_class, 285 PROP_LOGIN_FREQUENCY, 286 g_param_spec_ulong ("login-frequency", 287 "login frequency", 288 "login frequency", 289 0, 290 G_MAXULONG, 291 0, 292 G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); 293 294 signals [ICON_CHANGED] = 295 g_signal_new ("icon-changed", 296 G_TYPE_FROM_CLASS (class), 297 G_SIGNAL_RUN_LAST, 298 G_STRUCT_OFFSET (GdmUserClass, icon_changed), 299 NULL, NULL, 300 g_cclosure_marshal_VOID__VOID, 301 G_TYPE_NONE, 0); 302 signals [SESSIONS_CHANGED] = 303 g_signal_new ("sessions-changed", 304 G_TYPE_FROM_CLASS (class), 305 G_SIGNAL_RUN_LAST, 306 G_STRUCT_OFFSET (GdmUserClass, sessions_changed), 307 NULL, NULL, 308 g_cclosure_marshal_VOID__VOID, 309 G_TYPE_NONE, 0); 310 } 311 312 313 static void 314 on_icon_monitor_changed (GFileMonitor *monitor, 315 GFile *file, 316 GFile *other_file, 317 GFileMonitorEvent event_type, 318 GdmUser *user) 319 { 320 g_debug ("Icon changed: %d", event_type); 321 322 if (event_type != G_FILE_MONITOR_EVENT_CHANGED && 323 event_type != G_FILE_MONITOR_EVENT_CREATED) { 324 return; 325 } 326 327 _gdm_user_icon_changed (user); 328 } 329 330 static void 331 update_icon_monitor (GdmUser *user) 332 { 333 GFile *file; 334 GError *error; 335 char *path; 336 337 if (user->home_dir == NULL) { 338 return; 339 } 340 341 if (user->icon_monitor != NULL) { 342 g_file_monitor_cancel (user->icon_monitor); 343 user->icon_monitor = NULL; 344 } 345 346 path = g_build_filename (user->home_dir, ".face", NULL); 347 g_debug ("adding monitor for '%s'", path); 348 file = g_file_new_for_path (path); 349 error = NULL; 350 user->icon_monitor = g_file_monitor_file (file, 351 G_FILE_MONITOR_NONE, 352 NULL, 353 &error); 354 if (user->icon_monitor != NULL) { 355 g_signal_connect (user->icon_monitor, 356 "changed", 357 G_CALLBACK (on_icon_monitor_changed), 358 user); 359 } else { 360 g_warning ("Unable to monitor %s: %s", path, error->message); 361 g_error_free (error); 362 } 363 g_object_unref (file); 364 g_free (path); 365 } 366 367 static void 368 gdm_user_init (GdmUser *user) 369 { 370 user->manager = NULL; 371 user->user_name = NULL; 372 user->real_name = NULL; 373 user->sessions = NULL; 374 } 375 376 static void 377 gdm_user_finalize (GObject *object) 378 { 379 GdmUser *user; 380 381 user = GDM_USER (object); 382 383 g_file_monitor_cancel (user->icon_monitor); 384 385 g_free (user->user_name); 386 g_free (user->real_name); 387 388 if (G_OBJECT_CLASS (gdm_user_parent_class)->finalize) 389 (*G_OBJECT_CLASS (gdm_user_parent_class)->finalize) (object); 390 } 391 392 /** 393 * _gdm_user_update: 394 * @user: the user object to update. 395 * @pwent: the user data to use. 396 * 397 * Updates the properties of @user using the data in @pwent. 398 * 399 * Since: 1.0 400 **/ 401 void 402 _gdm_user_update (GdmUser *user, 403 const struct passwd *pwent) 404 { 405 gchar *real_name; 406 407 g_return_if_fail (GDM_IS_USER (user)); 408 g_return_if_fail (pwent != NULL); 409 410 g_object_freeze_notify (G_OBJECT (user)); 411 412 /* Display Name */ 413 if (pwent->pw_gecos && pwent->pw_gecos[0] != '\0') { 414 gchar *first_comma; 415 416 first_comma = strchr (pwent->pw_gecos, ','); 417 if (first_comma) { 418 real_name = g_strndup (pwent->pw_gecos, 419 (first_comma - pwent->pw_gecos)); 420 } else { 421 real_name = g_strdup (pwent->pw_gecos); 422 } 423 424 if (real_name[0] == '\0') { 425 g_free (real_name); 426 real_name = NULL; 427 } 428 } else { 429 real_name = NULL; 430 } 431 432 if ((real_name && !user->real_name) || 433 (!real_name && user->real_name) || 434 (real_name && 435 user->real_name && 436 strcmp (real_name, user->real_name) != 0)) { 437 g_free (user->real_name); 438 user->real_name = real_name; 439 g_object_notify (G_OBJECT (user), "real-name"); 440 } else { 441 g_free (real_name); 442 } 443 444 /* UID */ 445 if (pwent->pw_uid != user->uid) { 446 user->uid = pwent->pw_uid; 447 g_object_notify (G_OBJECT (user), "uid"); 448 } 449 450 /* Username */ 451 if ((pwent->pw_name && !user->user_name) || 452 (!pwent->pw_name && user->user_name) || 453 (pwent->pw_name && 454 user->user_name && 455 strcmp (user->user_name, pwent->pw_name) != 0)) { 456 g_free (user->user_name); 457 user->user_name = g_strdup (pwent->pw_name); 458 g_object_notify (G_OBJECT (user), "user-name"); 459 } 460 461 /* Home Directory */ 462 if ((pwent->pw_dir && !user->home_dir) || 463 (!pwent->pw_dir && user->home_dir) || 464 strcmp (user->home_dir, pwent->pw_dir) != 0) { 465 g_free (user->home_dir); 466 user->home_dir = g_strdup (pwent->pw_dir); 467 g_object_notify (G_OBJECT (user), "home-directory"); 468 g_signal_emit (user, signals[ICON_CHANGED], 0); 469 } 470 471 /* Shell */ 472 if ((pwent->pw_shell && !user->shell) || 473 (!pwent->pw_shell && user->shell) || 474 (pwent->pw_shell && 475 user->shell && 476 strcmp (user->shell, pwent->pw_shell) != 0)) { 477 g_free (user->shell); 478 user->shell = g_strdup (pwent->pw_shell); 479 g_object_notify (G_OBJECT (user), "shell"); 480 } 481 482 update_icon_monitor (user); 483 484 g_object_thaw_notify (G_OBJECT (user)); 485 } 486 487 /** 488 * _gdm_user_icon_changed: 489 * @user: the user to emit the signal for. 490 * 491 * Emits the "icon-changed" signal for @user. 492 * 493 * Since: 1.0 494 **/ 495 void 496 _gdm_user_icon_changed (GdmUser *user) 497 { 498 g_return_if_fail (GDM_IS_USER (user)); 499 500 g_signal_emit (user, signals[ICON_CHANGED], 0); 501 } 502 503 /** 504 * gdm_user_get_uid: 505 * @user: the user object to examine. 506 * 507 * Retrieves the ID of @user. 508 * 509 * Returns: a pointer to an array of characters which must not be modified or 510 * freed, or %NULL. 511 * 512 * Since: 1.0 513 **/ 514 515 uid_t 516 gdm_user_get_uid (GdmUser *user) 517 { 518 g_return_val_if_fail (GDM_IS_USER (user), -1); 519 520 return user->uid; 521 } 522 523 /** 524 * gdm_user_get_real_name: 525 * @user: the user object to examine. 526 * 527 * Retrieves the display name of @user. 528 * 529 * Returns: a pointer to an array of characters which must not be modified or 530 * freed, or %NULL. 531 * 532 * Since: 1.0 533 **/ 534 G_CONST_RETURN gchar * 535 gdm_user_get_real_name (GdmUser *user) 536 { 537 g_return_val_if_fail (GDM_IS_USER (user), NULL); 538 539 return (user->real_name ? user->real_name : user->user_name); 540 } 541 542 /** 543 * gdm_user_get_user_name: 544 * @user: the user object to examine. 545 * 546 * Retrieves the login name of @user. 547 * 548 * Returns: a pointer to an array of characters which must not be modified or 549 * freed, or %NULL. 550 * 551 * Since: 1.0 552 **/ 553 554 G_CONST_RETURN gchar * 555 gdm_user_get_user_name (GdmUser *user) 556 { 557 g_return_val_if_fail (GDM_IS_USER (user), NULL); 558 559 return user->user_name; 560 } 561 562 /** 563 * gdm_user_get_home_directory: 564 * @user: the user object to examine. 565 * 566 * Retrieves the home directory of @user. 567 * 568 * Returns: a pointer to an array of characters which must not be modified or 569 * freed, or %NULL. 570 * 571 * Since: 1.0 572 **/ 573 574 G_CONST_RETURN gchar * 575 gdm_user_get_home_directory (GdmUser *user) 576 { 577 g_return_val_if_fail (GDM_IS_USER (user), NULL); 578 579 return user->home_dir; 580 } 581 582 /** 583 * gdm_user_get_shell: 584 * @user: the user object to examine. 585 * 586 * Retrieves the login shell of @user. 587 * 588 * Returns: a pointer to an array of characters which must not be modified or 589 * freed, or %NULL. 590 * 591 * Since: 1.0 592 **/ 593 594 G_CONST_RETURN gchar * 595 gdm_user_get_shell (GdmUser *user) 596 { 597 g_return_val_if_fail (GDM_IS_USER (user), NULL); 598 599 return user->shell; 600 } 601 602 gulong 603 gdm_user_get_login_frequency (GdmUser *user) 604 { 605 g_return_val_if_fail (GDM_IS_USER (user), 0); 606 607 return user->login_frequency; 608 } 609 610 int 611 gdm_user_collate (GdmUser *user1, 612 GdmUser *user2) 613 { 614 const char *str1; 615 const char *str2; 616 gulong num1; 617 gulong num2; 618 619 g_return_val_if_fail (user1 == NULL || GDM_IS_USER (user1), 0); 620 g_return_val_if_fail (user2 == NULL || GDM_IS_USER (user2), 0); 621 622 if (user1->real_name != NULL) { 623 str1 = user1->real_name; 624 } else { 625 str1 = user1->user_name; 626 } 627 628 if (user2->real_name != NULL) { 629 str2 = user2->real_name; 630 } else { 631 str2 = user2->user_name; 632 } 633 634 num1 = user1->login_frequency; 635 num2 = user2->login_frequency; 636 g_debug ("Login freq 1=%u 2=%u", (guint)num1, (guint)num2); 637 if (num1 > num2) { 638 return -1; 639 } 640 641 if (num1 < num2) { 642 return 1; 643 } 644 645 /* if login frequency is equal try names */ 646 if (str1 == NULL && str2 != NULL) { 647 return -1; 648 } 649 650 if (str1 != NULL && str2 == NULL) { 651 return 1; 652 } 653 654 if (str1 == NULL && str2 == NULL) { 655 return 0; 656 } 657 658 return g_utf8_collate (str1, str2); 659 } 660 661 static gboolean 662 check_user_file (const char *filename, 663 uid_t user, 664 gssize max_file_size, 665 gboolean relax_group, 666 gboolean relax_other) 667 { 668 struct stat fileinfo; 669 670 if (max_file_size < 0) { 671 max_file_size = G_MAXSIZE; 672 } 673 674 /* Exists/Readable? */ 675 if (stat (filename, &fileinfo) < 0) { 676 return FALSE; 677 } 678 679 /* Is a regular file */ 680 if (G_UNLIKELY (!S_ISREG (fileinfo.st_mode))) { 681 return FALSE; 682 } 683 684 /* Owned by user? */ 685 if (G_UNLIKELY (fileinfo.st_uid != user)) { 686 return FALSE; 687 } 688 689 /* Group not writable or relax_group? */ 690 if (G_UNLIKELY ((fileinfo.st_mode & S_IWGRP) == S_IWGRP && !relax_group)) { 691 return FALSE; 692 } 693 694 /* Other not writable or relax_other? */ 695 if (G_UNLIKELY ((fileinfo.st_mode & S_IWOTH) == S_IWOTH && !relax_other)) { 696 return FALSE; 697 } 698 699 /* Size is kosher? */ 700 if (G_UNLIKELY (fileinfo.st_size > max_file_size)) { 701 return FALSE; 702 } 703 704 return TRUE; 705 } 706 707 static char * 708 get_filesystem_type (const char *path) 709 { 710 GFile *file; 711 GFileInfo *file_info; 712 GError *error; 713 char *filesystem_type; 714 715 file = g_file_new_for_path (path); 716 error = NULL; 717 file_info = g_file_query_filesystem_info (file, 718 G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, 719 NULL, 720 &error); 721 if (file_info == NULL) { 722 g_warning ("Unable to query filesystem type for %s: %s", path, error->message); 723 g_error_free (error); 724 g_object_unref (file); 725 return NULL; 726 } 727 728 filesystem_type = g_strdup (g_file_info_get_attribute_string (file_info, 729 G_FILE_ATTRIBUTE_FILESYSTEM_TYPE)); 730 if (filesystem_type == NULL) { 731 g_warning ("GIO returned NULL filesystem type for %s", path); 732 } 733 734 g_object_unref (file); 735 g_object_unref (file_info); 736 737 return filesystem_type; 738 } 739 740 static GdkPixbuf * 741 render_icon_from_home (GdmUser *user, 742 int icon_size) 743 { 744 GdkPixbuf *retval; 745 char *path; 746 gboolean is_local; 747 gboolean is_autofs; 748 gboolean res; 749 char *filesystem_type; 750 751 is_local = FALSE; 752 753 /* special case: look at parent of home to detect autofs 754 this is so we don't try to trigger an automount */ 755 path = g_path_get_dirname (user->home_dir); 756 filesystem_type = get_filesystem_type (path); 757 is_autofs = (filesystem_type != NULL && strcmp (filesystem_type, "autofs") == 0); 758 g_free (filesystem_type); 759 g_free (path); 760 761 if (is_autofs) { 762 return NULL; 763 } 764 765 /* now check that home dir itself is local */ 766 filesystem_type = get_filesystem_type (user->home_dir); 767 is_local = ((filesystem_type != NULL) && 768 (strcmp (filesystem_type, "nfs") != 0) && 769 (strcmp (filesystem_type, "afs") != 0) && 770 (strcmp (filesystem_type, "autofs") != 0) && 771 (strcmp (filesystem_type, "unknown") != 0) && 772 (strcmp (filesystem_type, "ncpfs") != 0)); 773 g_free (filesystem_type); 774 775 /* only look at local home directories so we don't try to 776 read from remote (e.g. NFS) volumes */ 777 if (! is_local) { 778 return NULL; 779 } 780 781 /* First, try "~/.face" */ 782 path = g_build_filename (user->home_dir, ".face", NULL); 783 res = check_user_file (path, 784 user->uid, 785 MAX_FILE_SIZE, 786 RELAX_GROUP, 787 RELAX_OTHER); 788 if (res) { 789 retval = gdk_pixbuf_new_from_file_at_size (path, 790 icon_size, 791 icon_size, 792 NULL); 793 } else { 794 retval = NULL; 795 } 796 g_free (path); 797 798 /* Next, try "~/.face.icon" */ 799 if (retval == NULL) { 800 path = g_build_filename (user->home_dir, 801 ".face.icon", 802 NULL); 803 res = check_user_file (path, 804 user->uid, 805 MAX_FILE_SIZE, 806 RELAX_GROUP, 807 RELAX_OTHER); 808 if (res) { 809 retval = gdk_pixbuf_new_from_file_at_size (path, 810 icon_size, 811 icon_size, 812 NULL); 813 } else { 814 retval = NULL; 815 } 816 817 g_free (path); 818 } 819 820 /* Still nothing, try the user's personal GDM config */ 821 if (retval == NULL) { 822 path = g_build_filename (user->home_dir, 823 ".gnome", 824 "gdm", 825 NULL); 826 res = check_user_file (path, 827 user->uid, 828 MAX_FILE_SIZE, 829 RELAX_GROUP, 830 RELAX_OTHER); 831 if (res) { 832 GKeyFile *keyfile; 833 char *icon_path; 834 835 keyfile = g_key_file_new (); 836 g_key_file_load_from_file (keyfile, 837 path, 838 G_KEY_FILE_NONE, 839 NULL); 840 841 icon_path = g_key_file_get_string (keyfile, 842 "face", 843 "picture", 844 NULL); 845 res = check_user_file (icon_path, 846 user->uid, 847 MAX_FILE_SIZE, 848 RELAX_GROUP, 849 RELAX_OTHER); 850 if (icon_path && res) { 851 retval = gdk_pixbuf_new_from_file_at_size (path, 852 icon_size, 853 icon_size, 854 NULL); 855 } else { 856 retval = NULL; 857 } 858 859 g_free (icon_path); 860 g_key_file_free (keyfile); 861 } else { 862 retval = NULL; 863 } 864 865 g_free (path); 866 } 867 868 return retval; 869 } 870 871 static void 872 curved_rectangle (cairo_t *cr, 873 double x0, 874 double y0, 875 double width, 876 double height, 877 double radius) 878 { 879 double x1; 880 double y1; 881 882 x1 = x0 + width; 883 y1 = y0 + height; 884 885 if (width < FLT_EPSILON || height < FLT_EPSILON) { 886 return; 887 } 888 889 if (width / 2 < radius) { 890 if (height / 2 < radius) { 891 cairo_move_to (cr, x0, (y0 + y1) / 2); 892 cairo_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1) / 2, y0); 893 cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1) / 2); 894 cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0) / 2, y1); 895 cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1) / 2); 896 } else { 897 cairo_move_to (cr, x0, y0 + radius); 898 cairo_curve_to (cr, x0, y0, x0, y0, (x0 + x1) / 2, y0); 899 cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius); 900 cairo_line_to (cr, x1, y1 - radius); 901 cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0) / 2, y1); 902 cairo_curve_to (cr, x0, y1, x0, y1, x0, y1 - radius); 903 } 904 } else { 905 if (height / 2 < radius) { 906 cairo_move_to (cr, x0, (y0 + y1) / 2); 907 cairo_curve_to (cr, x0, y0, x0 , y0, x0 + radius, y0); 908 cairo_line_to (cr, x1 - radius, y0); 909 cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1) / 2); 910 cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1); 911 cairo_line_to (cr, x0 + radius, y1); 912 cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1) / 2); 913 } else { 914 cairo_move_to (cr, x0, y0 + radius); 915 cairo_curve_to (cr, x0 , y0, x0 , y0, x0 + radius, y0); 916 cairo_line_to (cr, x1 - radius, y0); 917 cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius); 918 cairo_line_to (cr, x1, y1 - radius); 919 cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1); 920 cairo_line_to (cr, x0 + radius, y1); 921 cairo_curve_to (cr, x0, y1, x0, y1, x0, y1 - radius); 922 } 923 } 924 925 cairo_close_path (cr); 926 } 927 928 static cairo_surface_t * 929 surface_from_pixbuf (GdkPixbuf *pixbuf) 930 { 931 cairo_surface_t *surface; 932 cairo_t *cr; 933 934 surface = cairo_image_surface_create (gdk_pixbuf_get_has_alpha (pixbuf) ? 935 CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, 936 gdk_pixbuf_get_width (pixbuf), 937 gdk_pixbuf_get_height (pixbuf)); 938 cr = cairo_create (surface); 939 gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); 940 cairo_paint (cr); 941 cairo_destroy (cr); 942 943 return surface; 944 } 945 946 /** 947 * go_cairo_convert_data_to_pixbuf: 948 * @src: a pointer to pixel data in cairo format 949 * @dst: a pointer to pixel data in pixbuf format 950 * @width: image width 951 * @height: image height 952 * @rowstride: data rowstride 953 * 954 * Converts the pixel data stored in @src in CAIRO_FORMAT_ARGB32 cairo format 955 * to GDK_COLORSPACE_RGB pixbuf format and move them 956 * to @dst. If @src == @dst, pixel are converted in place. 957 **/ 958 959 static void 960 go_cairo_convert_data_to_pixbuf (unsigned char *dst, 961 unsigned char const *src, 962 int width, 963 int height, 964 int rowstride) 965 { 966 int i,j; 967 unsigned int t; 968 unsigned char a, b, c; 969 970 g_return_if_fail (dst != NULL); 971 972 #define MULT(d,c,a,t) G_STMT_START { t = (a)? c * 255 / a: 0; d = t;} G_STMT_END 973 974 if (src == dst || src == NULL) { 975 for (i = 0; i < height; i++) { 976 for (j = 0; j < width; j++) { 977 #if G_BYTE_ORDER == G_LITTLE_ENDIAN 978 MULT(a, dst[2], dst[3], t); 979 MULT(b, dst[1], dst[3], t); 980 MULT(c, dst[0], dst[3], t); 981 dst[0] = a; 982 dst[1] = b; 983 dst[2] = c; 984 #else 985 MULT(a, dst[1], dst[0], t); 986 MULT(b, dst[2], dst[0], t); 987 MULT(c, dst[3], dst[0], t); 988 dst[3] = dst[0]; 989 dst[0] = a; 990 dst[1] = b; 991 dst[2] = c; 992 #endif 993 dst += 4; 994 } 995 dst += rowstride - width * 4; 996 } 997 } else { 998 for (i = 0; i < height; i++) { 999 for (j = 0; j < width; j++) { 1000 #if G_BYTE_ORDER == G_LITTLE_ENDIAN 1001 MULT(dst[0], src[2], src[3], t); 1002 MULT(dst[1], src[1], src[3], t); 1003 MULT(dst[2], src[0], src[3], t); 1004 dst[3] = src[3]; 1005 #else 1006 MULT(dst[0], src[1], src[0], t); 1007 MULT(dst[1], src[2], src[0], t); 1008 MULT(dst[2], src[3], src[0], t); 1009 dst[3] = src[0]; 1010 #endif 1011 src += 4; 1012 dst += 4; 1013 } 1014 src += rowstride - width * 4; 1015 dst += rowstride - width * 4; 1016 } 1017 } 1018 #undef MULT 1019 } 1020 1021 static void 1022 cairo_to_pixbuf (guint8 *src_data, 1023 GdkPixbuf *dst_pixbuf) 1024 { 1025 unsigned char *src; 1026 unsigned char *dst; 1027 guint w; 1028 guint h; 1029 guint rowstride; 1030 1031 w = gdk_pixbuf_get_width (dst_pixbuf); 1032 h = gdk_pixbuf_get_height (dst_pixbuf); 1033 rowstride = gdk_pixbuf_get_rowstride (dst_pixbuf); 1034 1035 dst = gdk_pixbuf_get_pixels (dst_pixbuf); 1036 src = src_data; 1037 1038 go_cairo_convert_data_to_pixbuf (dst, src, w, h, rowstride); 1039 } 1040 1041 static GdkPixbuf * 1042 frame_pixbuf (GdkPixbuf *source) 1043 { 1044 GdkPixbuf *dest; 1045 cairo_t *cr; 1046 cairo_surface_t *surface; 1047 guint w; 1048 guint h; 1049 guint rowstride; 1050 int frame_width; 1051 double radius; 1052 guint8 *data; 1053 1054 frame_width = 2; 1055 1056 w = gdk_pixbuf_get_width (source) + frame_width * 2; 1057 h = gdk_pixbuf_get_height (source) + frame_width * 2; 1058 radius = w / 3.0; 1059 1060 dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 1061 TRUE, 1062 8, 1063 w, 1064 h); 1065 rowstride = gdk_pixbuf_get_rowstride (dest); 1066 1067 1068 data = g_new0 (guint8, h * rowstride); 1069 1070 surface = cairo_image_surface_create_for_data (data, 1071 CAIRO_FORMAT_ARGB32, 1072 w, 1073 h, 1074 rowstride); 1075 cr = cairo_create (surface); 1076 cairo_surface_destroy (surface); 1077 1078 /* set up image */ 1079 cairo_rectangle (cr, 0, 0, w, h); 1080 cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); 1081 cairo_fill (cr); 1082 1083 curved_rectangle (cr, frame_width, frame_width, 1084 w - frame_width * 2, h - frame_width * 2, 1085 radius); 1086 cairo_set_source_rgba (cr, 0.5, 0.5, 0.5, 0.3); 1087 cairo_fill_preserve (cr); 1088 1089 surface = surface_from_pixbuf (source); 1090 cairo_set_source_surface (cr, surface, frame_width, frame_width); 1091 cairo_fill (cr); 1092 cairo_surface_destroy (surface); 1093 1094 cairo_to_pixbuf (data, dest); 1095 1096 cairo_destroy (cr); 1097 g_free (data); 1098 1099 return dest; 1100 } 1101 1102 GdkPixbuf * 1103 gdm_user_render_icon (GdmUser *user, 1104 gint icon_size) 1105 { 1106 GdkPixbuf *pixbuf; 1107 GdkPixbuf *framed; 1108 char *path; 1109 char *tmp; 1110 gboolean res; 1111 1112 g_return_val_if_fail (GDM_IS_USER (user), NULL); 1113 g_return_val_if_fail (icon_size > 12, NULL); 1114 1115 path = NULL; 1116 1117 pixbuf = render_icon_from_home (user, icon_size); 1118 if (pixbuf != NULL) { 1119 goto out; 1120 } 1121 1122 /* Try ${GlobalFaceDir}/${username} */ 1123 path = g_build_filename (GLOBAL_FACEDIR, user->user_name, NULL); 1124 res = check_user_file (path, 1125 user->uid, 1126 MAX_FILE_SIZE, 1127 RELAX_GROUP, 1128 RELAX_OTHER); 1129 if (res) { 1130 pixbuf = gdk_pixbuf_new_from_file_at_size (path, 1131 icon_size, 1132 icon_size, 1133 NULL); 1134 } else { 1135 pixbuf = NULL; 1136 } 1137 1138 g_free (path); 1139 if (pixbuf != NULL) { 1140 goto out; 1141 } 1142 1143 /* Finally, ${GlobalFaceDir}/${username}.png */ 1144 tmp = g_strconcat (user->user_name, ".png", NULL); 1145 path = g_build_filename (GLOBAL_FACEDIR, tmp, NULL); 1146 g_free (tmp); 1147 res = check_user_file (path, 1148 user->uid, 1149 MAX_FILE_SIZE, 1150 RELAX_GROUP, 1151 RELAX_OTHER); 1152 if (res) { 1153 pixbuf = gdk_pixbuf_new_from_file_at_size (path, 1154 icon_size, 1155 icon_size, 1156 NULL); 1157 } else { 1158 pixbuf = NULL; 1159 } 1160 g_free (path); 1161 out: 1162 1163 if (pixbuf != NULL) { 1164 framed = frame_pixbuf (pixbuf); 1165 if (framed != NULL) { 1166 g_object_unref (pixbuf); 1167 pixbuf = framed; 1168 } 1169 } 1170 1171 return pixbuf; 1172 } -
gui/gdmsetup/gdm-user.h
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/gui/gdmsetup/gdm-user.h gdm-2.28.0.new/gui/gdmsetup/gdm-user.h
old new 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 2 * 3 * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>. 4 * Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 /* 22 * Facade object for user data, owned by GdmUserManager 23 */ 24 25 #ifndef __GDM_USER__ 26 #define __GDM_USER__ 1 27 28 #include <sys/types.h> 29 #include <gtk/gtk.h> 30 #include <gdk-pixbuf/gdk-pixbuf.h> 31 32 G_BEGIN_DECLS 33 34 #define GDM_TYPE_USER (gdm_user_get_type ()) 35 #define GDM_USER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDM_TYPE_USER, GdmUser)) 36 #define GDM_IS_USER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDM_TYPE_USER)) 37 38 typedef struct _GdmUser GdmUser; 39 40 GType gdm_user_get_type (void) G_GNUC_CONST; 41 42 uid_t gdm_user_get_uid (GdmUser *user); 43 G_CONST_RETURN char *gdm_user_get_user_name (GdmUser *user); 44 G_CONST_RETURN char *gdm_user_get_real_name (GdmUser *user); 45 G_CONST_RETURN char *gdm_user_get_home_directory (GdmUser *user); 46 G_CONST_RETURN char *gdm_user_get_shell (GdmUser *user); 47 guint gdm_user_get_num_sessions (GdmUser *user); 48 GList *gdm_user_get_sessions (GdmUser *user); 49 gulong gdm_user_get_login_frequency (GdmUser *user); 50 51 GdkPixbuf *gdm_user_render_icon (GdmUser *user, 52 gint icon_size); 53 54 gint gdm_user_collate (GdmUser *user1, 55 GdmUser *user2); 56 57 G_END_DECLS 58 59 #endif -
gui/gdmsetup/gdm-user-manager.c
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/gui/gdmsetup/gdm-user-manager.c gdm-2.28.0.new/gui/gdmsetup/gdm-user-manager.c
old new 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 2 * 3 * Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * 19 */ 20 21 #include "config.h" 22 23 #include <stdlib.h> 24 #include <stdio.h> 25 #include <fcntl.h> 26 #include <unistd.h> 27 #include <string.h> 28 #include <signal.h> 29 #include <errno.h> 30 #include <sys/stat.h> 31 #include <sys/types.h> 32 33 #ifdef HAVE_PATHS_H 34 #include <paths.h> 35 #endif /* HAVE_PATHS_H */ 36 37 #include <glib.h> 38 #include <glib/gi18n.h> 39 #include <glib/gstdio.h> 40 #include <glib-object.h> 41 #include <gio/gio.h> 42 43 #include <dbus/dbus.h> 44 #include <dbus/dbus-glib.h> 45 #include <dbus/dbus-glib-lowlevel.h> 46 47 #include "gdm-user-manager.h" 48 #include "gdm-user-private.h" 49 50 #define GDM_USER_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_USER_MANAGER, GdmUserManagerPrivate)) 51 52 #define CK_NAME "org.freedesktop.ConsoleKit" 53 #define CK_PATH "/org/freedesktop/ConsoleKit" 54 #define CK_INTERFACE "org.freedesktop.ConsoleKit" 55 56 #define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager" 57 #define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager" 58 #define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat" 59 #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session" 60 61 /* Prefs Defaults */ 62 #define DEFAULT_ALLOW_ROOT TRUE 63 #define DEFAULT_MAX_ICON_SIZE 128 64 #define DEFAULT_USER_MAX_FILE 65536 65 66 #ifdef __sun 67 #define DEFAULT_MINIMAL_UID 100 68 #else 69 #define DEFAULT_MINIMAL_UID 500 70 #endif 71 72 #ifndef _PATH_SHELLS 73 #define _PATH_SHELLS "/etc/shells" 74 #endif 75 #define PATH_PASSWD "/etc/passwd" 76 77 #define DEFAULT_GLOBAL_FACE_DIR DATADIR "/faces" 78 #define DEFAULT_USER_ICON "stock_person" 79 #define DEFAULT_EXCLUDE { "bin", \ 80 "root", \ 81 "daemon", \ 82 "adm", \ 83 "lp", \ 84 "sync", \ 85 "shutdown", \ 86 "halt", \ 87 "mail", \ 88 "news", \ 89 "uucp", \ 90 "operator", \ 91 "nobody", \ 92 GDM_USERNAME, \ 93 "postgres", \ 94 "pvm", \ 95 "rpm", \ 96 "nfsnobody", \ 97 "pcap", \ 98 NULL } 99 100 struct GdmUserManagerPrivate 101 { 102 GHashTable *users; 103 GHashTable *sessions; 104 GHashTable *exclusions; 105 GHashTable *shells; 106 DBusGConnection *connection; 107 DBusGProxy *seat_proxy; 108 char *seat_id; 109 110 GFileMonitor *passwd_monitor; 111 GFileMonitor *shells_monitor; 112 113 guint reload_id; 114 guint ck_history_id; 115 116 guint8 users_dirty : 1; 117 }; 118 119 enum { 120 LOADING_USERS, 121 USERS_LOADED, 122 USER_ADDED, 123 USER_REMOVED, 124 USER_IS_LOGGED_IN_CHANGED, 125 USER_LOGIN_FREQUENCY_CHANGED, 126 LAST_SIGNAL 127 }; 128 129 static guint signals [LAST_SIGNAL] = { 0, }; 130 131 static void gdm_user_manager_class_init (GdmUserManagerClass *klass); 132 static void gdm_user_manager_init (GdmUserManager *user_manager); 133 static void gdm_user_manager_finalize (GObject *object); 134 135 static gpointer user_manager_object = NULL; 136 137 G_DEFINE_TYPE (GdmUserManager, gdm_user_manager, G_TYPE_OBJECT) 138 139 GQuark 140 gdm_user_manager_error_quark (void) 141 { 142 static GQuark ret = 0; 143 if (ret == 0) { 144 ret = g_quark_from_static_string ("gdm_user_manager_error"); 145 } 146 147 return ret; 148 } 149 150 static gboolean 151 start_new_login_session (GdmUserManager *manager) 152 { 153 GError *error; 154 gboolean res; 155 156 res = g_spawn_command_line_async ("gdmflexiserver -s", &error); 157 if (! res) { 158 g_warning ("Unable to start new login: %s", error->message); 159 g_error_free (error); 160 } 161 162 return res; 163 } 164 165 /* needs to stay in sync with gdm-slave */ 166 static char * 167 _get_primary_user_session_id (GdmUserManager *manager, 168 GdmUser *user) 169 { 170 gboolean res; 171 gboolean can_activate_sessions; 172 GError *error; 173 GList *sessions; 174 GList *l; 175 char *primary_ssid; 176 177 if (manager->priv->seat_id == NULL || manager->priv->seat_id[0] == '\0') { 178 g_debug ("GdmUserManager: display seat id is not set; can't switch sessions"); 179 return NULL; 180 } 181 182 primary_ssid = NULL; 183 sessions = NULL; 184 185 g_debug ("GdmUserManager: checking if seat can activate sessions"); 186 187 error = NULL; 188 res = dbus_g_proxy_call (manager->priv->seat_proxy, 189 "CanActivateSessions", 190 &error, 191 G_TYPE_INVALID, 192 G_TYPE_BOOLEAN, &can_activate_sessions, 193 G_TYPE_INVALID); 194 if (! res) { 195 g_warning ("unable to determine if seat can activate sessions: %s", 196 error->message); 197 g_error_free (error); 198 goto out; 199 } 200 201 if (! can_activate_sessions) { 202 g_debug ("GdmUserManager: seat is unable to activate sessions"); 203 goto out; 204 } 205 206 sessions = gdm_user_get_sessions (user); 207 if (sessions == NULL) { 208 g_warning ("unable to determine sessions for user: %s", 209 gdm_user_get_user_name (user)); 210 goto out; 211 } 212 213 for (l = sessions; l != NULL; l = l->next) { 214 const char *ssid; 215 216 ssid = l->data; 217 218 /* FIXME: better way to choose? */ 219 if (ssid != NULL) { 220 primary_ssid = g_strdup (ssid); 221 break; 222 } 223 } 224 225 out: 226 227 return primary_ssid; 228 } 229 230 static gboolean 231 activate_session_id (GdmUserManager *manager, 232 const char *seat_id, 233 const char *session_id) 234 { 235 DBusError local_error; 236 DBusMessage *message; 237 DBusMessage *reply; 238 gboolean ret; 239 240 ret = FALSE; 241 reply = NULL; 242 243 dbus_error_init (&local_error); 244 message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", 245 seat_id, 246 "org.freedesktop.ConsoleKit.Seat", 247 "ActivateSession"); 248 if (message == NULL) { 249 goto out; 250 } 251 252 if (! dbus_message_append_args (message, 253 DBUS_TYPE_OBJECT_PATH, &session_id, 254 DBUS_TYPE_INVALID)) { 255 goto out; 256 } 257 258 259 dbus_error_init (&local_error); 260 reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (manager->priv->connection), 261 message, 262 -1, 263 &local_error); 264 if (reply == NULL) { 265 if (dbus_error_is_set (&local_error)) { 266 g_warning ("Unable to activate session: %s", local_error.message); 267 dbus_error_free (&local_error); 268 goto out; 269 } 270 } 271 272 ret = TRUE; 273 out: 274 if (message != NULL) { 275 dbus_message_unref (message); 276 } 277 if (reply != NULL) { 278 dbus_message_unref (reply); 279 } 280 281 return ret; 282 } 283 284 static gboolean 285 session_is_login_window (GdmUserManager *manager, 286 const char *session_id) 287 { 288 DBusGProxy *proxy; 289 GError *error; 290 gboolean res; 291 gboolean ret; 292 char *session_type; 293 294 ret = FALSE; 295 296 proxy = dbus_g_proxy_new_for_name (manager->priv->connection, 297 CK_NAME, 298 session_id, 299 CK_SESSION_INTERFACE); 300 if (proxy == NULL) { 301 g_warning ("Failed to connect to the ConsoleKit seat object"); 302 goto out; 303 } 304 305 session_type = NULL; 306 error = NULL; 307 res = dbus_g_proxy_call (proxy, 308 "GetSessionType", 309 &error, 310 G_TYPE_INVALID, 311 G_TYPE_STRING, &session_type, 312 G_TYPE_INVALID); 313 if (! res) { 314 g_debug ("Failed to identify the session type: %s", error->message); 315 g_error_free (error); 316 goto out; 317 } 318 319 if (session_type == NULL || session_type[0] == '\0' || strcmp (session_type, "LoginWindow") != 0) { 320 goto out; 321 } 322 323 ret = TRUE; 324 325 out: 326 if (proxy != NULL) { 327 g_object_unref (proxy); 328 } 329 330 return ret; 331 } 332 333 static char * 334 _get_login_window_session_id (GdmUserManager *manager) 335 { 336 gboolean res; 337 gboolean can_activate_sessions; 338 GError *error; 339 GPtrArray *sessions; 340 char *primary_ssid; 341 int i; 342 343 if (manager->priv->seat_id == NULL || manager->priv->seat_id[0] == '\0') { 344 g_debug ("GdmUserManager: display seat id is not set; can't switch sessions"); 345 return NULL; 346 } 347 348 primary_ssid = NULL; 349 sessions = NULL; 350 351 g_debug ("GdmSlave: checking if seat can activate sessions"); 352 353 error = NULL; 354 res = dbus_g_proxy_call (manager->priv->seat_proxy, 355 "CanActivateSessions", 356 &error, 357 G_TYPE_INVALID, 358 G_TYPE_BOOLEAN, &can_activate_sessions, 359 G_TYPE_INVALID); 360 if (! res) { 361 g_warning ("unable to determine if seat can activate sessions: %s", 362 error->message); 363 g_error_free (error); 364 goto out; 365 } 366 367 if (! can_activate_sessions) { 368 g_debug ("GdmSlave: seat is unable to activate sessions"); 369 goto out; 370 } 371 372 error = NULL; 373 res = dbus_g_proxy_call (manager->priv->seat_proxy, 374 "GetSessions", 375 &error, 376 G_TYPE_INVALID, 377 dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &sessions, 378 G_TYPE_INVALID); 379 if (! res) { 380 g_warning ("unable to determine sessions for user: %s", 381 error->message); 382 g_error_free (error); 383 goto out; 384 } 385 386 for (i = 0; i < sessions->len; i++) { 387 char *ssid; 388 389 ssid = g_ptr_array_index (sessions, i); 390 391 if (session_is_login_window (manager, ssid)) { 392 primary_ssid = g_strdup (ssid); 393 break; 394 } 395 } 396 g_ptr_array_foreach (sessions, (GFunc)g_free, NULL); 397 g_ptr_array_free (sessions, TRUE); 398 399 out: 400 401 return primary_ssid; 402 } 403 404 gboolean 405 gdm_user_manager_goto_login_session (GdmUserManager *manager) 406 { 407 gboolean ret; 408 gboolean res; 409 char *ssid; 410 411 g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), FALSE); 412 413 ret = FALSE; 414 415 /* First look for any existing LoginWindow sessions on the seat. 416 If none are found, create a new one. */ 417 418 ssid = _get_login_window_session_id (manager); 419 if (ssid != NULL) { 420 res = activate_session_id (manager, manager->priv->seat_id, ssid); 421 if (res) { 422 ret = TRUE; 423 } 424 } 425 426 if (! ret) { 427 res = start_new_login_session (manager); 428 if (res) { 429 ret = TRUE; 430 } 431 } 432 433 return ret; 434 } 435 436 gboolean 437 gdm_user_manager_activate_user_session (GdmUserManager *manager, 438 GdmUser *user) 439 { 440 gboolean ret; 441 char *ssid; 442 gboolean res; 443 444 g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), FALSE); 445 g_return_val_if_fail (GDM_IS_USER (user), FALSE); 446 447 ret = FALSE; 448 449 ssid = _get_primary_user_session_id (manager, user); 450 if (ssid == NULL) { 451 goto out; 452 } 453 454 res = activate_session_id (manager, manager->priv->seat_id, ssid); 455 if (! res) { 456 g_debug ("GdmUserManager: unable to activate session: %s", ssid); 457 goto out; 458 } 459 460 ret = TRUE; 461 out: 462 return ret; 463 } 464 465 static void 466 on_user_sessions_changed (GdmUser *user, 467 GdmUserManager *manager) 468 { 469 guint nsessions; 470 471 nsessions = gdm_user_get_num_sessions (user); 472 473 g_debug ("GdmUserManager: sessions changed user=%s num=%d", 474 gdm_user_get_user_name (user), 475 nsessions); 476 477 /* only signal on zero and one */ 478 if (nsessions > 1) { 479 return; 480 } 481 482 g_signal_emit (manager, signals [USER_IS_LOGGED_IN_CHANGED], 0, user); 483 } 484 485 static void 486 on_user_icon_changed (GdmUser *user, 487 GdmUserManager *manager) 488 { 489 g_debug ("GdmUserManager: user icon changed"); 490 } 491 492 static char * 493 get_seat_id_for_session (DBusGConnection *connection, 494 const char *session_id) 495 { 496 DBusGProxy *proxy; 497 GError *error; 498 char *seat_id; 499 gboolean res; 500 501 proxy = NULL; 502 seat_id = NULL; 503 504 proxy = dbus_g_proxy_new_for_name (connection, 505 CK_NAME, 506 session_id, 507 CK_SESSION_INTERFACE); 508 if (proxy == NULL) { 509 g_warning ("Failed to connect to the ConsoleKit session object"); 510 goto out; 511 } 512 513 error = NULL; 514 res = dbus_g_proxy_call (proxy, 515 "GetSeatId", 516 &error, 517 G_TYPE_INVALID, 518 DBUS_TYPE_G_OBJECT_PATH, &seat_id, 519 G_TYPE_INVALID); 520 if (! res) { 521 g_debug ("Failed to identify the current seat: %s", error->message); 522 g_error_free (error); 523 } 524 out: 525 if (proxy != NULL) { 526 g_object_unref (proxy); 527 } 528 529 return seat_id; 530 } 531 532 static char * 533 get_x11_display_for_session (DBusGConnection *connection, 534 const char *session_id) 535 { 536 DBusGProxy *proxy; 537 GError *error; 538 char *x11_display; 539 gboolean res; 540 541 proxy = NULL; 542 x11_display = NULL; 543 544 proxy = dbus_g_proxy_new_for_name (connection, 545 CK_NAME, 546 session_id, 547 CK_SESSION_INTERFACE); 548 if (proxy == NULL) { 549 g_warning ("Failed to connect to the ConsoleKit session object"); 550 goto out; 551 } 552 553 error = NULL; 554 res = dbus_g_proxy_call (proxy, 555 "GetX11Display", 556 &error, 557 G_TYPE_INVALID, 558 G_TYPE_STRING, &x11_display, 559 G_TYPE_INVALID); 560 if (! res) { 561 g_debug ("Failed to identify the x11 display: %s", error->message); 562 g_error_free (error); 563 } 564 out: 565 if (proxy != NULL) { 566 g_object_unref (proxy); 567 } 568 569 return x11_display; 570 } 571 572 static gboolean 573 maybe_add_session_for_user (GdmUserManager *manager, 574 GdmUser *user, 575 const char *ssid) 576 { 577 char *sid; 578 char *x11_display; 579 gboolean ret; 580 581 ret = FALSE; 582 sid = NULL; 583 x11_display = NULL; 584 585 /* skip if on another seat */ 586 sid = get_seat_id_for_session (manager->priv->connection, ssid); 587 if (sid == NULL 588 || manager->priv->seat_id == NULL 589 || strcmp (sid, manager->priv->seat_id) != 0) { 590 g_debug ("GdmUserManager: not adding session on other seat: %s", ssid); 591 goto out; 592 } 593 594 /* skip if doesn't have an x11 display */ 595 x11_display = get_x11_display_for_session (manager->priv->connection, ssid); 596 if (x11_display == NULL || x11_display[0] == '\0') { 597 g_debug ("GdmUserManager: not adding session without a x11 display: %s", ssid); 598 goto out; 599 } 600 601 if (g_hash_table_lookup (manager->priv->exclusions, gdm_user_get_user_name (user))) { 602 g_debug ("GdmUserManager: excluding user '%s'", gdm_user_get_user_name (user)); 603 goto out; 604 } 605 606 g_hash_table_insert (manager->priv->sessions, 607 g_strdup (ssid), 608 g_strdup (gdm_user_get_user_name (user))); 609 610 _gdm_user_add_session (user, ssid); 611 g_debug ("GdmUserManager: added session for user: %s", gdm_user_get_user_name (user)); 612 613 ret = TRUE; 614 615 out: 616 g_free (sid); 617 g_free (x11_display); 618 619 return ret; 620 } 621 622 static void 623 add_sessions_for_user (GdmUserManager *manager, 624 GdmUser *user) 625 { 626 DBusGProxy *proxy; 627 GError *error; 628 gboolean res; 629 guint32 uid; 630 GPtrArray *sessions; 631 int i; 632 633 proxy = dbus_g_proxy_new_for_name (manager->priv->connection, 634 CK_NAME, 635 CK_MANAGER_PATH, 636 CK_MANAGER_INTERFACE); 637 if (proxy == NULL) { 638 g_warning ("Failed to connect to the ConsoleKit manager object"); 639 goto out; 640 } 641 642 uid = gdm_user_get_uid (user); 643 644 g_debug ("Getting list of sessions for user %u", uid); 645 646 error = NULL; 647 res = dbus_g_proxy_call (proxy, 648 "GetSessionsForUnixUser", 649 &error, 650 G_TYPE_UINT, uid, 651 G_TYPE_INVALID, 652 dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), 653 &sessions, 654 G_TYPE_INVALID); 655 if (! res) { 656 g_debug ("Failed to find sessions for user: %s", error->message); 657 g_error_free (error); 658 goto out; 659 } 660 661 g_debug ("Found %d sessions for user %s", sessions->len, gdm_user_get_user_name (user)); 662 663 for (i = 0; i < sessions->len; i++) { 664 char *ssid; 665 666 ssid = g_ptr_array_index (sessions, i); 667 maybe_add_session_for_user (manager, user, ssid); 668 } 669 670 g_ptr_array_foreach (sessions, (GFunc)g_free, NULL); 671 g_ptr_array_free (sessions, TRUE); 672 673 out: 674 if (proxy != NULL) { 675 g_object_unref (proxy); 676 } 677 } 678 679 static GdmUser * 680 create_user (GdmUserManager *manager) 681 { 682 GdmUser *user; 683 684 user = g_object_new (GDM_TYPE_USER, "manager", manager, NULL); 685 g_signal_connect (user, 686 "sessions-changed", 687 G_CALLBACK (on_user_sessions_changed), 688 manager); 689 g_signal_connect (user, 690 "icon-changed", 691 G_CALLBACK (on_user_icon_changed), 692 manager); 693 return user; 694 } 695 696 static void 697 add_user (GdmUserManager *manager, 698 GdmUser *user) 699 { 700 add_sessions_for_user (manager, user); 701 g_hash_table_insert (manager->priv->users, 702 g_strdup (gdm_user_get_user_name (user)), 703 g_object_ref (user)); 704 705 g_signal_emit (manager, signals[USER_ADDED], 0, user); 706 } 707 708 static GdmUser * 709 add_new_user_for_pwent (GdmUserManager *manager, 710 struct passwd *pwent) 711 { 712 GdmUser *user; 713 714 g_debug ("Creating new user"); 715 716 user = create_user (manager); 717 _gdm_user_update (user, pwent); 718 719 add_user (manager, user); 720 721 return user; 722 } 723 724 static char * 725 get_current_seat_id (DBusGConnection *connection) 726 { 727 DBusGProxy *proxy; 728 GError *error; 729 char *session_id; 730 char *seat_id; 731 gboolean res; 732 733 proxy = NULL; 734 session_id = NULL; 735 seat_id = NULL; 736 737 proxy = dbus_g_proxy_new_for_name (connection, 738 CK_NAME, 739 CK_MANAGER_PATH, 740 CK_MANAGER_INTERFACE); 741 if (proxy == NULL) { 742 g_warning ("Failed to connect to the ConsoleKit manager object"); 743 goto out; 744 } 745 746 error = NULL; 747 res = dbus_g_proxy_call (proxy, 748 "GetCurrentSession", 749 &error, 750 G_TYPE_INVALID, 751 DBUS_TYPE_G_OBJECT_PATH, 752 &session_id, 753 G_TYPE_INVALID); 754 if (! res) { 755 g_debug ("Failed to identify the current session: %s", error->message); 756 g_error_free (error); 757 goto out; 758 } 759 760 seat_id = get_seat_id_for_session (connection, session_id); 761 762 out: 763 if (proxy != NULL) { 764 g_object_unref (proxy); 765 } 766 g_free (session_id); 767 768 return seat_id; 769 } 770 771 static gboolean 772 get_uid_from_session_id (GdmUserManager *manager, 773 const char *session_id, 774 uid_t *uidp) 775 { 776 DBusGProxy *proxy; 777 GError *error; 778 guint uid; 779 gboolean res; 780 781 proxy = dbus_g_proxy_new_for_name (manager->priv->connection, 782 CK_NAME, 783 session_id, 784 CK_SESSION_INTERFACE); 785 if (proxy == NULL) { 786 g_warning ("Failed to connect to the ConsoleKit session object"); 787 return FALSE; 788 } 789 790 error = NULL; 791 res = dbus_g_proxy_call (proxy, 792 "GetUnixUser", 793 &error, 794 G_TYPE_INVALID, 795 G_TYPE_UINT, &uid, 796 G_TYPE_INVALID); 797 g_object_unref (proxy); 798 799 if (! res) { 800 g_warning ("Failed to query the session: %s", error->message); 801 g_error_free (error); 802 return FALSE; 803 } 804 805 if (uidp != NULL) { 806 *uidp = (uid_t) uid; 807 } 808 809 return TRUE; 810 } 811 812 static void 813 seat_session_added (DBusGProxy *seat_proxy, 814 const char *session_id, 815 GdmUserManager *manager) 816 { 817 uid_t uid; 818 gboolean res; 819 struct passwd *pwent; 820 GdmUser *user; 821 gboolean is_new; 822 823 g_debug ("Session added: %s", session_id); 824 825 res = get_uid_from_session_id (manager, session_id, &uid); 826 if (! res) { 827 g_warning ("Unable to lookup user for session"); 828 return; 829 } 830 831 errno = 0; 832 pwent = getpwuid (uid); 833 if (pwent == NULL) { 834 g_warning ("Unable to lookup user id %d: %s", (int)uid, g_strerror (errno)); 835 return; 836 } 837 838 /* check exclusions up front */ 839 if (g_hash_table_lookup (manager->priv->exclusions, pwent->pw_name)) { 840 g_debug ("GdmUserManager: excluding user '%s'", pwent->pw_name); 841 return; 842 } 843 844 user = g_hash_table_lookup (manager->priv->users, pwent->pw_name); 845 if (user == NULL) { 846 g_debug ("Creating new user"); 847 848 user = create_user (manager); 849 _gdm_user_update (user, pwent); 850 is_new = TRUE; 851 } else { 852 is_new = FALSE; 853 } 854 855 res = maybe_add_session_for_user (manager, user, session_id); 856 857 /* only add the user if we added a session */ 858 if (is_new) { 859 if (res) { 860 add_user (manager, user); 861 } else { 862 g_object_unref (user); 863 } 864 } 865 } 866 867 static void 868 seat_session_removed (DBusGProxy *seat_proxy, 869 const char *session_id, 870 GdmUserManager *manager) 871 { 872 GdmUser *user; 873 char *username; 874 875 g_debug ("Session removed: %s", session_id); 876 877 /* since the session object may already be gone 878 * we can't query CK directly */ 879 880 username = g_hash_table_lookup (manager->priv->sessions, session_id); 881 if (username == NULL) { 882 return; 883 } 884 885 user = g_hash_table_lookup (manager->priv->users, username); 886 if (user == NULL) { 887 /* nothing to do */ 888 return; 889 } 890 891 g_debug ("GdmUserManager: Session removed for %s", username); 892 _gdm_user_remove_session (user, session_id); 893 } 894 895 static void 896 on_proxy_destroy (DBusGProxy *proxy, 897 GdmUserManager *manager) 898 { 899 g_debug ("GdmUserManager: seat proxy destroyed"); 900 901 manager->priv->seat_proxy = NULL; 902 } 903 904 static void 905 get_seat_proxy (GdmUserManager *manager) 906 { 907 DBusGProxy *proxy; 908 GError *error; 909 910 g_assert (manager->priv->seat_proxy == NULL); 911 912 error = NULL; 913 manager->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); 914 if (manager->priv->connection == NULL) { 915 g_warning ("Failed to connect to the D-Bus daemon: %s", error->message); 916 g_error_free (error); 917 return; 918 } 919 920 manager->priv->seat_id = get_current_seat_id (manager->priv->connection); 921 if (manager->priv->seat_id == NULL) { 922 return; 923 } 924 925 g_debug ("GdmUserManager: Found current seat: %s", manager->priv->seat_id); 926 927 error = NULL; 928 proxy = dbus_g_proxy_new_for_name_owner (manager->priv->connection, 929 CK_NAME, 930 manager->priv->seat_id, 931 CK_SEAT_INTERFACE, 932 &error); 933 934 if (proxy == NULL) { 935 g_warning ("Failed to connect to the ConsoleKit seat object: %s", error->message); 936 g_error_free (error); 937 return; 938 } 939 940 g_signal_connect (proxy, "destroy", G_CALLBACK (on_proxy_destroy), manager); 941 942 dbus_g_proxy_add_signal (proxy, 943 "SessionAdded", 944 DBUS_TYPE_G_OBJECT_PATH, 945 G_TYPE_INVALID); 946 dbus_g_proxy_add_signal (proxy, 947 "SessionRemoved", 948 DBUS_TYPE_G_OBJECT_PATH, 949 G_TYPE_INVALID); 950 dbus_g_proxy_connect_signal (proxy, 951 "SessionAdded", 952 G_CALLBACK (seat_session_added), 953 manager, 954 NULL); 955 dbus_g_proxy_connect_signal (proxy, 956 "SessionRemoved", 957 G_CALLBACK (seat_session_removed), 958 manager, 959 NULL); 960 manager->priv->seat_proxy = proxy; 961 962 } 963 964 /** 965 * gdm_manager_get_user: 966 * @manager: the manager to query. 967 * @username: the login name of the user to get. 968 * 969 * Retrieves a pointer to the #GdmUser object for the login named @username 970 * from @manager. This pointer is not a reference, and should not be released. 971 * 972 * Returns: a pointer to a #GdmUser object. 973 **/ 974 GdmUser * 975 gdm_user_manager_get_user (GdmUserManager *manager, 976 const char *username) 977 { 978 GdmUser *user; 979 980 g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), NULL); 981 g_return_val_if_fail (username != NULL && username[0] != '\0', NULL); 982 983 user = g_hash_table_lookup (manager->priv->users, username); 984 985 if (user == NULL) { 986 struct passwd *pwent; 987 988 pwent = getpwnam (username); 989 990 if (pwent != NULL) { 991 user = add_new_user_for_pwent (manager, pwent); 992 } 993 } 994 995 return user; 996 } 997 998 GdmUser * 999 gdm_user_manager_get_user_by_uid (GdmUserManager *manager, 1000 uid_t uid) 1001 { 1002 GdmUser *user; 1003 struct passwd *pwent; 1004 1005 g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), NULL); 1006 1007 pwent = getpwuid (uid); 1008 if (pwent == NULL) { 1009 g_warning ("GdmUserManager: unable to lookup uid %d", (int)uid); 1010 return NULL; 1011 } 1012 1013 user = g_hash_table_lookup (manager->priv->users, pwent->pw_name); 1014 1015 if (user == NULL) { 1016 user = add_new_user_for_pwent (manager, pwent); 1017 } 1018 1019 return user; 1020 } 1021 1022 static void 1023 listify_hash_values_hfunc (gpointer key, 1024 gpointer value, 1025 gpointer user_data) 1026 { 1027 GSList **list = user_data; 1028 1029 *list = g_slist_prepend (*list, value); 1030 } 1031 1032 GSList * 1033 gdm_user_manager_list_users (GdmUserManager *manager) 1034 { 1035 GSList *retval; 1036 1037 g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), NULL); 1038 1039 retval = NULL; 1040 g_hash_table_foreach (manager->priv->users, listify_hash_values_hfunc, &retval); 1041 1042 return g_slist_sort (retval, (GCompareFunc) gdm_user_collate); 1043 } 1044 1045 static gboolean 1046 parse_value_as_ulong (const char *value, 1047 gulong *ulongval) 1048 { 1049 char *end_of_valid_long; 1050 glong long_value; 1051 gulong ulong_value; 1052 1053 errno = 0; 1054 long_value = strtol (value, &end_of_valid_long, 10); 1055 1056 if (*value == '\0' || *end_of_valid_long != '\0') { 1057 return FALSE; 1058 } 1059 1060 ulong_value = long_value; 1061 if (ulong_value != long_value || errno == ERANGE) { 1062 return FALSE; 1063 } 1064 1065 *ulongval = ulong_value; 1066 1067 return TRUE; 1068 } 1069 1070 static gboolean 1071 parse_ck_history_line (const char *line, 1072 char **user_namep, 1073 gulong *frequencyp) 1074 { 1075 GRegex *re; 1076 GMatchInfo *match_info; 1077 gboolean res; 1078 gboolean ret; 1079 GError *error; 1080 1081 ret = FALSE; 1082 re = NULL; 1083 match_info = NULL; 1084 1085 error = NULL; 1086 re = g_regex_new ("(?P<username>[0-9a-zA-Z]+)[ ]+(?P<frequency>[0-9]+)", 0, 0, &error); 1087 if (re == NULL) { 1088 g_critical ("%s", error->message); 1089 goto out; 1090 } 1091 1092 g_regex_match (re, line, 0, &match_info); 1093 1094 res = g_match_info_matches (match_info); 1095 if (! res) { 1096 g_warning ("Unable to parse history: %s", line); 1097 goto out; 1098 } 1099 1100 if (user_namep != NULL) { 1101 *user_namep = g_match_info_fetch_named (match_info, "username"); 1102 } 1103 1104 if (frequencyp != NULL) { 1105 char *freq; 1106 freq = g_match_info_fetch_named (match_info, "frequency"); 1107 res = parse_value_as_ulong (freq, frequencyp); 1108 g_free (freq); 1109 if (! res) { 1110 goto out; 1111 } 1112 } 1113 1114 ret = TRUE; 1115 1116 out: 1117 if (match_info != NULL) { 1118 g_match_info_free (match_info); 1119 } 1120 if (re != NULL) { 1121 g_regex_unref (re); 1122 } 1123 return ret; 1124 } 1125 1126 static void 1127 process_ck_history_line (GdmUserManager *manager, 1128 const char *line) 1129 { 1130 gboolean res; 1131 char *username; 1132 gulong frequency; 1133 struct passwd *pwent; 1134 GdmUser *user; 1135 1136 frequency = 0; 1137 username = NULL; 1138 res = parse_ck_history_line (line, &username, &frequency); 1139 if (! res) { 1140 return; 1141 } 1142 1143 if (g_hash_table_lookup (manager->priv->exclusions, username)) { 1144 g_debug ("GdmUserManager: excluding user '%s'", username); 1145 g_free (username); 1146 return; 1147 } 1148 1149 /* https://bugzilla.gnome.org/show_bug.cgi?id=587708 */ 1150 /* do not show system users; we cannot use gdm_user_manager_get_user() 1151 * here since this creates/signals users as a side effect */ 1152 pwent = getpwnam (username); 1153 if (pwent == NULL) { 1154 g_warning ("Unable to lookup user name %s: %s", username, g_strerror (errno)); 1155 return; 1156 } 1157 if (pwent->pw_uid < DEFAULT_MINIMAL_UID) { 1158 g_debug ("GdmUserManager: excluding user '%s'", username); 1159 return; 1160 } 1161 1162 user = gdm_user_manager_get_user (manager, username); 1163 if (user == NULL) { 1164 g_debug ("GdmUserManager: unable to lookup user '%s'", username); 1165 g_free (username); 1166 return; 1167 } 1168 1169 g_object_set (user, "login-frequency", frequency, NULL); 1170 g_signal_emit (manager, signals [USER_LOGIN_FREQUENCY_CHANGED], 0, user); 1171 g_free (username); 1172 } 1173 1174 static gboolean 1175 ck_history_watch (GIOChannel *source, 1176 GIOCondition condition, 1177 GdmUserManager *manager) 1178 { 1179 GIOStatus status; 1180 gboolean done = FALSE; 1181 1182 g_return_val_if_fail (manager != NULL, FALSE); 1183 1184 if (condition & G_IO_IN) { 1185 char *str; 1186 GError *error; 1187 1188 error = NULL; 1189 status = g_io_channel_read_line (source, &str, NULL, NULL, &error); 1190 if (error != NULL) { 1191 g_warning ("GdmUserManager: unable to read line: %s", error->message); 1192 g_error_free (error); 1193 } 1194 1195 if (status == G_IO_STATUS_NORMAL) { 1196 g_debug ("GdmUserManager: history output: %s", str); 1197 process_ck_history_line (manager, str); 1198 } else if (status == G_IO_STATUS_EOF) { 1199 done = TRUE; 1200 } 1201 1202 g_free (str); 1203 } else if (condition & G_IO_HUP) { 1204 done = TRUE; 1205 } 1206 1207 if (done) { 1208 g_signal_emit (G_OBJECT (manager), signals[USERS_LOADED], 0); 1209 1210 manager->priv->ck_history_id = 0; 1211 return FALSE; 1212 } 1213 1214 return TRUE; 1215 } 1216 1217 static void 1218 reload_ck_history (GdmUserManager *manager) 1219 { 1220 char *command; 1221 const char *seat_id; 1222 GError *error; 1223 gboolean res; 1224 char **argv; 1225 int standard_out; 1226 GIOChannel *channel; 1227 1228 seat_id = NULL; 1229 if (manager->priv->seat_id != NULL 1230 && g_str_has_prefix (manager->priv->seat_id, "/org/freedesktop/ConsoleKit/")) { 1231 1232 seat_id = manager->priv->seat_id + strlen ("/org/freedesktop/ConsoleKit/"); 1233 } 1234 1235 if (seat_id == NULL) { 1236 g_warning ("Unable to find users: no seat-id found"); 1237 return; 1238 } 1239 1240 command = g_strdup_printf ("ck-history --frequent --seat='%s' --session-type=''", 1241 seat_id); 1242 g_debug ("GdmUserManager: running '%s'", command); 1243 error = NULL; 1244 if (! g_shell_parse_argv (command, NULL, &argv, &error)) { 1245 g_warning ("Could not parse command: %s", error->message); 1246 g_error_free (error); 1247 goto out; 1248 } 1249 1250 error = NULL; 1251 res = g_spawn_async_with_pipes (NULL, 1252 argv, 1253 NULL, 1254 G_SPAWN_SEARCH_PATH, 1255 NULL, 1256 NULL, 1257 NULL, /* pid */ 1258 NULL, 1259 &standard_out, 1260 NULL, 1261 &error); 1262 g_strfreev (argv); 1263 if (! res) { 1264 g_warning ("Unable to run ck-history: %s", error->message); 1265 g_error_free (error); 1266 goto out; 1267 } 1268 1269 channel = g_io_channel_unix_new (standard_out); 1270 g_io_channel_set_close_on_unref (channel, TRUE); 1271 g_io_channel_set_flags (channel, 1272 g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK, 1273 NULL); 1274 manager->priv->ck_history_id = g_io_add_watch (channel, 1275 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, 1276 (GIOFunc)ck_history_watch, 1277 manager); 1278 g_io_channel_unref (channel); 1279 1280 out: 1281 g_free (command); 1282 } 1283 1284 static void 1285 reload_passwd (GdmUserManager *manager) 1286 { 1287 struct passwd *pwent; 1288 GSList *old_users; 1289 GSList *new_users; 1290 GSList *list; 1291 FILE *fp; 1292 1293 old_users = NULL; 1294 new_users = NULL; 1295 1296 errno = 0; 1297 fp = fopen (PATH_PASSWD, "r"); 1298 if (fp == NULL) { 1299 g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno)); 1300 goto out; 1301 } 1302 1303 g_hash_table_foreach (manager->priv->users, listify_hash_values_hfunc, &old_users); 1304 g_slist_foreach (old_users, (GFunc) g_object_ref, NULL); 1305 1306 /* Make sure we keep users who are logged in no matter what. */ 1307 for (list = old_users; list; list = list->next) { 1308 if (gdm_user_get_num_sessions (list->data) > 0) { 1309 g_object_freeze_notify (G_OBJECT (list->data)); 1310 new_users = g_slist_prepend (new_users, g_object_ref (list->data)); 1311 } 1312 } 1313 1314 for (pwent = fgetpwent (fp); pwent != NULL; pwent = fgetpwent (fp)) { 1315 GdmUser *user; 1316 1317 user = NULL; 1318 1319 /* Skip users below MinimalUID... */ 1320 if (pwent->pw_uid < DEFAULT_MINIMAL_UID) { 1321 continue; 1322 } 1323 1324 /* ...And users w/ invalid shells... */ 1325 if (pwent->pw_shell == NULL || 1326 !g_hash_table_lookup (manager->priv->shells, pwent->pw_shell)) { 1327 g_debug ("GdmUserManager: skipping user with bad shell: %s", pwent->pw_name); 1328 continue; 1329 } 1330 1331 /* ...And explicitly excluded users */ 1332 if (g_hash_table_lookup (manager->priv->exclusions, pwent->pw_name)) { 1333 g_debug ("GdmUserManager: explicitly skipping user: %s", pwent->pw_name); 1334 continue; 1335 } 1336 1337 user = g_hash_table_lookup (manager->priv->users, pwent->pw_name); 1338 1339 /* Update users already in the *new* list */ 1340 if (g_slist_find (new_users, user)) { 1341 _gdm_user_update (user, pwent); 1342 continue; 1343 } 1344 1345 if (user == NULL) { 1346 user = create_user (manager); 1347 } else { 1348 g_object_ref (user); 1349 } 1350 1351 /* Freeze & update users not already in the new list */ 1352 g_object_freeze_notify (G_OBJECT (user)); 1353 _gdm_user_update (user, pwent); 1354 1355 new_users = g_slist_prepend (new_users, user); 1356 } 1357 1358 /* Go through and handle added users */ 1359 for (list = new_users; list; list = list->next) { 1360 if (! g_slist_find (old_users, list->data)) { 1361 add_user (manager, list->data); 1362 } 1363 } 1364 1365 /* Go through and handle removed users */ 1366 for (list = old_users; list; list = list->next) { 1367 if (! g_slist_find (new_users, list->data)) { 1368 g_signal_emit (manager, signals[USER_REMOVED], 0, list->data); 1369 g_hash_table_remove (manager->priv->users, 1370 gdm_user_get_user_name (list->data)); 1371 } 1372 } 1373 1374 out: 1375 /* Cleanup */ 1376 1377 fclose (fp); 1378 1379 g_slist_foreach (new_users, (GFunc) g_object_thaw_notify, NULL); 1380 g_slist_foreach (new_users, (GFunc) g_object_unref, NULL); 1381 g_slist_free (new_users); 1382 1383 g_slist_foreach (old_users, (GFunc) g_object_unref, NULL); 1384 g_slist_free (old_users); 1385 } 1386 1387 static void 1388 reload_users (GdmUserManager *manager) 1389 { 1390 reload_ck_history (manager); 1391 reload_passwd (manager); 1392 } 1393 1394 static gboolean 1395 reload_users_timeout (GdmUserManager *manager) 1396 { 1397 reload_users (manager); 1398 manager->priv->reload_id = 0; 1399 1400 return FALSE; 1401 } 1402 1403 static void 1404 queue_reload_users (GdmUserManager *manager) 1405 { 1406 if (manager->priv->reload_id > 0) { 1407 return; 1408 } 1409 1410 g_signal_emit (G_OBJECT (manager), signals[LOADING_USERS], 0); 1411 manager->priv->reload_id = g_idle_add ((GSourceFunc)reload_users_timeout, manager); 1412 } 1413 1414 static void 1415 reload_shells (GdmUserManager *manager) 1416 { 1417 char *shell; 1418 1419 setusershell (); 1420 1421 g_hash_table_remove_all (manager->priv->shells); 1422 for (shell = getusershell (); shell != NULL; shell = getusershell ()) { 1423 /* skip well known not-real shells */ 1424 if (shell == NULL 1425 || strcmp (shell, "/sbin/nologin") == 0 1426 || strcmp (shell, "/bin/false") == 0) { 1427 g_debug ("GdmUserManager: skipping shell %s", shell); 1428 continue; 1429 } 1430 g_hash_table_insert (manager->priv->shells, 1431 g_strdup (shell), 1432 GUINT_TO_POINTER (TRUE)); 1433 } 1434 1435 endusershell (); 1436 } 1437 1438 static void 1439 on_shells_monitor_changed (GFileMonitor *monitor, 1440 GFile *file, 1441 GFile *other_file, 1442 GFileMonitorEvent event_type, 1443 GdmUserManager *manager) 1444 { 1445 if (event_type != G_FILE_MONITOR_EVENT_CHANGED && 1446 event_type != G_FILE_MONITOR_EVENT_CREATED) { 1447 return; 1448 } 1449 1450 reload_shells (manager); 1451 reload_passwd (manager); 1452 } 1453 1454 static void 1455 on_passwd_monitor_changed (GFileMonitor *monitor, 1456 GFile *file, 1457 GFile *other_file, 1458 GFileMonitorEvent event_type, 1459 GdmUserManager *manager) 1460 { 1461 if (event_type != G_FILE_MONITOR_EVENT_CHANGED && 1462 event_type != G_FILE_MONITOR_EVENT_CREATED) { 1463 return; 1464 } 1465 1466 reload_passwd (manager); 1467 } 1468 1469 static void 1470 gdm_user_manager_class_init (GdmUserManagerClass *klass) 1471 { 1472 GObjectClass *object_class = G_OBJECT_CLASS (klass); 1473 1474 object_class->finalize = gdm_user_manager_finalize; 1475 1476 signals [LOADING_USERS] = 1477 g_signal_new ("loading-users", 1478 G_TYPE_FROM_CLASS (klass), 1479 G_SIGNAL_RUN_LAST, 1480 G_STRUCT_OFFSET (GdmUserManagerClass, loading_users), 1481 NULL, NULL, 1482 g_cclosure_marshal_VOID__VOID, 1483 G_TYPE_NONE, 0); 1484 signals [USERS_LOADED] = 1485 g_signal_new ("users-loaded", 1486 G_TYPE_FROM_CLASS (klass), 1487 G_SIGNAL_RUN_LAST, 1488 G_STRUCT_OFFSET (GdmUserManagerClass, users_loaded), 1489 NULL, NULL, 1490 g_cclosure_marshal_VOID__VOID, 1491 G_TYPE_NONE, 0); 1492 signals [USER_ADDED] = 1493 g_signal_new ("user-added", 1494 G_TYPE_FROM_CLASS (klass), 1495 G_SIGNAL_RUN_LAST, 1496 G_STRUCT_OFFSET (GdmUserManagerClass, user_added), 1497 NULL, NULL, 1498 g_cclosure_marshal_VOID__OBJECT, 1499 G_TYPE_NONE, 1, GDM_TYPE_USER); 1500 signals [USER_REMOVED] = 1501 g_signal_new ("user-removed", 1502 G_TYPE_FROM_CLASS (klass), 1503 G_SIGNAL_RUN_LAST, 1504 G_STRUCT_OFFSET (GdmUserManagerClass, user_removed), 1505 NULL, NULL, 1506 g_cclosure_marshal_VOID__OBJECT, 1507 G_TYPE_NONE, 1, GDM_TYPE_USER); 1508 signals [USER_IS_LOGGED_IN_CHANGED] = 1509 g_signal_new ("user-is-logged-in-changed", 1510 G_TYPE_FROM_CLASS (klass), 1511 G_SIGNAL_RUN_LAST, 1512 G_STRUCT_OFFSET (GdmUserManagerClass, user_is_logged_in_changed), 1513 NULL, NULL, 1514 g_cclosure_marshal_VOID__OBJECT, 1515 G_TYPE_NONE, 1, GDM_TYPE_USER); 1516 signals [USER_LOGIN_FREQUENCY_CHANGED] = 1517 g_signal_new ("user-login-frequency-changed", 1518 G_TYPE_FROM_CLASS (klass), 1519 G_SIGNAL_RUN_LAST, 1520 G_STRUCT_OFFSET (GdmUserManagerClass, user_login_frequency_changed), 1521 NULL, NULL, 1522 g_cclosure_marshal_VOID__OBJECT, 1523 G_TYPE_NONE, 1, GDM_TYPE_USER); 1524 1525 g_type_class_add_private (klass, sizeof (GdmUserManagerPrivate)); 1526 } 1527 1528 static void 1529 gdm_user_manager_init (GdmUserManager *manager) 1530 { 1531 int i; 1532 GFile *file; 1533 GError *error; 1534 const char *exclude_default[] = DEFAULT_EXCLUDE; 1535 1536 manager->priv = GDM_USER_MANAGER_GET_PRIVATE (manager); 1537 1538 /* sessions */ 1539 manager->priv->sessions = g_hash_table_new_full (g_str_hash, 1540 g_str_equal, 1541 g_free, 1542 g_free); 1543 1544 /* exclusions */ 1545 manager->priv->exclusions = g_hash_table_new_full (g_str_hash, 1546 g_str_equal, 1547 g_free, 1548 NULL); 1549 for (i = 0; exclude_default[i] != NULL; i++) { 1550 g_hash_table_insert (manager->priv->exclusions, 1551 g_strdup (exclude_default [i]), 1552 GUINT_TO_POINTER (TRUE)); 1553 } 1554 1555 /* /etc/shells */ 1556 manager->priv->shells = g_hash_table_new_full (g_str_hash, 1557 g_str_equal, 1558 g_free, 1559 NULL); 1560 reload_shells (manager); 1561 file = g_file_new_for_path (_PATH_SHELLS); 1562 error = NULL; 1563 manager->priv->shells_monitor = g_file_monitor_file (file, 1564 G_FILE_MONITOR_NONE, 1565 NULL, 1566 &error); 1567 if (manager->priv->shells_monitor != NULL) { 1568 g_signal_connect (manager->priv->shells_monitor, 1569 "changed", 1570 G_CALLBACK (on_shells_monitor_changed), 1571 manager); 1572 } else { 1573 g_warning ("Unable to monitor %s: %s", _PATH_SHELLS, error->message); 1574 g_error_free (error); 1575 } 1576 g_object_unref (file); 1577 1578 /* /etc/passwd */ 1579 manager->priv->users = g_hash_table_new_full (g_str_hash, 1580 g_str_equal, 1581 g_free, 1582 (GDestroyNotify) g_object_run_dispose); 1583 file = g_file_new_for_path (PATH_PASSWD); 1584 manager->priv->passwd_monitor = g_file_monitor_file (file, 1585 G_FILE_MONITOR_NONE, 1586 NULL, 1587 &error); 1588 if (manager->priv->passwd_monitor != NULL) { 1589 g_signal_connect (manager->priv->passwd_monitor, 1590 "changed", 1591 G_CALLBACK (on_passwd_monitor_changed), 1592 manager); 1593 } else { 1594 g_warning ("Unable to monitor %s: %s", PATH_PASSWD, error->message); 1595 g_error_free (error); 1596 } 1597 g_object_unref (file); 1598 1599 1600 get_seat_proxy (manager); 1601 1602 queue_reload_users (manager); 1603 1604 manager->priv->users_dirty = FALSE; 1605 } 1606 1607 static void 1608 gdm_user_manager_finalize (GObject *object) 1609 { 1610 GdmUserManager *manager; 1611 1612 g_return_if_fail (object != NULL); 1613 g_return_if_fail (GDM_IS_USER_MANAGER (object)); 1614 1615 manager = GDM_USER_MANAGER (object); 1616 1617 g_return_if_fail (manager->priv != NULL); 1618 1619 if (manager->priv->seat_proxy != NULL) { 1620 g_object_unref (manager->priv->seat_proxy); 1621 } 1622 1623 if (manager->priv->ck_history_id != 0) { 1624 g_source_remove (manager->priv->ck_history_id); 1625 manager->priv->ck_history_id = 0; 1626 } 1627 1628 if (manager->priv->reload_id > 0) { 1629 g_source_remove (manager->priv->reload_id); 1630 manager->priv->reload_id = 0; 1631 } 1632 1633 g_hash_table_destroy (manager->priv->sessions); 1634 1635 g_file_monitor_cancel (manager->priv->passwd_monitor); 1636 g_hash_table_destroy (manager->priv->users); 1637 1638 g_file_monitor_cancel (manager->priv->shells_monitor); 1639 g_hash_table_destroy (manager->priv->shells); 1640 1641 g_free (manager->priv->seat_id); 1642 1643 G_OBJECT_CLASS (gdm_user_manager_parent_class)->finalize (object); 1644 } 1645 1646 GdmUserManager * 1647 gdm_user_manager_ref_default (void) 1648 { 1649 if (user_manager_object != NULL) { 1650 g_object_ref (user_manager_object); 1651 } else { 1652 user_manager_object = g_object_new (GDM_TYPE_USER_MANAGER, NULL); 1653 g_object_add_weak_pointer (user_manager_object, 1654 (gpointer *) &user_manager_object); 1655 } 1656 1657 return GDM_USER_MANAGER (user_manager_object); 1658 } -
gui/gdmsetup/gdm-user-manager.h
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/gui/gdmsetup/gdm-user-manager.h gdm-2.28.0.new/gui/gdmsetup/gdm-user-manager.h
old new 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 2 * 3 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * 19 */ 20 21 #ifndef __GDM_USER_MANAGER_H 22 #define __GDM_USER_MANAGER_H 23 24 #include <glib-object.h> 25 26 #include "gdm-user.h" 27 28 G_BEGIN_DECLS 29 30 #define GDM_TYPE_USER_MANAGER (gdm_user_manager_get_type ()) 31 #define GDM_USER_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_USER_MANAGER, GdmUserManager)) 32 #define GDM_USER_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_USER_MANAGER, GdmUserManagerClass)) 33 #define GDM_IS_USER_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_USER_MANAGER)) 34 #define GDM_IS_USER_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_USER_MANAGER)) 35 #define GDM_USER_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_USER_MANAGER, GdmUserManagerClass)) 36 37 typedef struct GdmUserManagerPrivate GdmUserManagerPrivate; 38 39 typedef struct 40 { 41 GObject parent; 42 GdmUserManagerPrivate *priv; 43 } GdmUserManager; 44 45 typedef struct 46 { 47 GObjectClass parent_class; 48 49 void (* loading_users) (GdmUserManager *user_manager); 50 void (* users_loaded) (GdmUserManager *user_manager); 51 void (* user_added) (GdmUserManager *user_manager, 52 GdmUser *user); 53 void (* user_removed) (GdmUserManager *user_manager, 54 GdmUser *user); 55 void (* user_is_logged_in_changed) (GdmUserManager *user_manager, 56 GdmUser *user); 57 void (* user_login_frequency_changed) (GdmUserManager *user_manager, 58 GdmUser *user); 59 } GdmUserManagerClass; 60 61 typedef enum 62 { 63 GDM_USER_MANAGER_ERROR_GENERAL, 64 GDM_USER_MANAGER_ERROR_KEY_NOT_FOUND 65 } GdmUserManagerError; 66 67 #define GDM_USER_MANAGER_ERROR gdm_user_manager_error_quark () 68 69 GQuark gdm_user_manager_error_quark (void); 70 GType gdm_user_manager_get_type (void); 71 72 GdmUserManager * gdm_user_manager_ref_default (void); 73 74 GSList * gdm_user_manager_list_users (GdmUserManager *manager); 75 GdmUser * gdm_user_manager_get_user (GdmUserManager *manager, 76 const char *user_name); 77 GdmUser * gdm_user_manager_get_user_by_uid (GdmUserManager *manager, 78 uid_t uid); 79 80 gboolean gdm_user_manager_activate_user_session (GdmUserManager *manager, 81 GdmUser *user); 82 83 gboolean gdm_user_manager_goto_login_session (GdmUserManager *manager); 84 85 G_END_DECLS 86 87 #endif /* __GDM_USER_MANAGER_H */ -
gui/gdmsetup/gdm-user-private.h
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/gui/gdmsetup/gdm-user-private.h gdm-2.28.0.new/gui/gdmsetup/gdm-user-private.h
old new 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 2 * 3 * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20 /* 21 * Private interfaces to the GdmUser object 22 */ 23 24 #ifndef __GDM_USER_PRIVATE__ 25 #define __GDM_USER_PRIVATE__ 1 26 27 #include <pwd.h> 28 29 #include "gdm-user.h" 30 31 G_BEGIN_DECLS 32 33 void _gdm_user_update (GdmUser *user, 34 const struct passwd *pwent); 35 void _gdm_user_add_session (GdmUser *user, 36 const char *session_id); 37 void _gdm_user_remove_session (GdmUser *user, 38 const char *session_id); 39 40 void _gdm_user_icon_changed (GdmUser *user); 41 42 G_END_DECLS 43 44 #endif /* !__GDM_USER_PRIVATE__ */ -
gui/gdmsetup/Makefile.am
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/gui/gdmsetup/Makefile.am gdm-2.28.0.new/gui/gdmsetup/Makefile.am
old new 1 NULL = 2 3 AM_CPPFLAGS = \ 4 -I$(top_srcdir)/common \ 5 -DDATADIR=\""$(datadir)"\" \ 6 -DUIDIR=\""$(uidir)"\" \ 7 -DGNOMELOCALEDIR=\""$(gdmlocaledir)"\" \ 8 $(GDMSETUP_CFLAGS) \ 9 $(NULL) 10 11 bin_PROGRAMS = \ 12 gdmsetup \ 13 $(NULL) 14 15 gdmsetup_SOURCES = \ 16 gdmsetup.c \ 17 gdm-user.c \ 18 gdm-user-manager.c \ 19 $(NULL) 20 21 gdmsetup_LDADD = \ 22 $(GDMSETUP_LIBS) \ 23 $(NULL) 24 25 uidir = $(pkgdatadir) 26 ui_DATA = \ 27 gdmsetup.ui \ 28 $(NULL) 29 30 Utilitiesdir = $(datadir)/applications 31 Utilities_in_files = gdmsetup.desktop.in 32 Utilities_DATA = $(Utilities_in_files:.desktop.in=.desktop) 33 @INTLTOOL_DESKTOP_RULE@ 34 35 EXTRA_DIST = \ 36 $(ui_DATA) \ 37 $(Utilities_in_files) \ 38 $(NULL) -
gui/Makefile.am
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/gui/Makefile.am gdm-2.28.0.new/gui/Makefile.am
old new 1 1 NULL = 2 2 3 3 SUBDIRS = \ 4 gdmsetup \ 4 5 simple-chooser \ 5 6 simple-greeter \ 6 7 user-switch-applet \ -
po/POTFILES.in
diff -Nur -x '*.orig' -x '*~' gdm-2.28.0/po/POTFILES.in gdm-2.28.0.new/po/POTFILES.in
old new 60 60 data/greeter-autostart/metacity.desktop.in 61 61 data/greeter-autostart/orca-screen-reader.desktop.in 62 62 data/greeter-autostart/polkit-gnome-authentication-agent-1.desktop.in 63 gui/gdmsetup/gdmsetup.desktop.in 64 gui/gdmsetup/gdmsetup.c 65 [type: gettext/glade]gui/gdmsetup/gdmsetup.ui 63 66 gui/simple-chooser/gdm-host-chooser-dialog.c 64 67 gui/simple-chooser/gdm-host-chooser-widget.c 65 68 gui/simple-greeter/gdm-cell-renderer-timer.c
Note: See TracBrowser
for help on using the repository browser.