[134] | 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
---|
| 2 | * |
---|
| 3 | * ck-connector.c : Code for login managers to register with ConsoleKit. |
---|
| 4 | * |
---|
| 5 | * Copyright (c) 2007 David Zeuthen <davidz@redhat.com> |
---|
| 6 | * Copyright (c) 2007 William Jon McCann <mccann@jhu.edu> |
---|
| 7 | * |
---|
| 8 | * Permission is hereby granted, free of charge, to any person |
---|
| 9 | * obtaining a copy of this software and associated documentation |
---|
| 10 | * files (the "Software"), to deal in the Software without |
---|
| 11 | * restriction, including without limitation the rights to use, |
---|
| 12 | * copy, modify, merge, publish, distribute, sublicense, and/or sell |
---|
| 13 | * copies of the Software, and to permit persons to whom the |
---|
| 14 | * Software is furnished to do so, subject to the following |
---|
| 15 | * conditions: |
---|
| 16 | * |
---|
| 17 | * The above copyright notice and this permission notice shall be |
---|
| 18 | * included in all copies or substantial portions of the Software. |
---|
| 19 | * |
---|
| 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
---|
| 21 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
---|
| 22 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
---|
| 23 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
---|
| 24 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
---|
| 25 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
---|
| 26 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
---|
| 27 | * OTHER DEALINGS IN THE SOFTWARE. |
---|
| 28 | */ |
---|
| 29 | |
---|
| 30 | #include <stdio.h> |
---|
| 31 | #include <stdlib.h> |
---|
| 32 | #include <string.h> |
---|
| 33 | #include <unistd.h> |
---|
| 34 | #include <sys/types.h> |
---|
| 35 | #include <dbus/dbus.h> |
---|
| 36 | |
---|
| 37 | #include "ck-connector.h" |
---|
| 38 | |
---|
| 39 | #define N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) |
---|
| 40 | |
---|
| 41 | #if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) |
---|
| 42 | #define _CK_FUNCTION_NAME __func__ |
---|
| 43 | #elif defined(__GNUC__) || defined(_MSC_VER) |
---|
| 44 | #define _CK_FUNCTION_NAME __FUNCTION__ |
---|
| 45 | #else |
---|
| 46 | #define _CK_FUNCTION_NAME "unknown function" |
---|
| 47 | #endif |
---|
| 48 | |
---|
| 49 | #define CK_CONNECTOR_ERROR "org.freedesktop.CkConnector.Error" |
---|
| 50 | |
---|
| 51 | #define _CK_WARNING_FORMAT "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n" |
---|
| 52 | #define _ck_return_if_fail(condition) do { \ |
---|
| 53 | if (!(condition)) { \ |
---|
| 54 | fprintf (stderr, _CK_WARNING_FORMAT, _CK_FUNCTION_NAME, #condition, __FILE__, __LINE__); \ |
---|
| 55 | return; \ |
---|
| 56 | } } while (0) |
---|
| 57 | |
---|
| 58 | #define _ck_return_val_if_fail(condition, val) do { \ |
---|
| 59 | if (!(condition)) { \ |
---|
| 60 | fprintf (stderr, _CK_WARNING_FORMAT, _CK_FUNCTION_NAME, #condition, __FILE__, __LINE__); \ |
---|
| 61 | return val; \ |
---|
| 62 | } } while (0) |
---|
| 63 | |
---|
| 64 | struct _CkConnector |
---|
| 65 | { |
---|
| 66 | int refcount; |
---|
| 67 | char *cookie; |
---|
| 68 | dbus_bool_t session_created; |
---|
| 69 | DBusConnection *connection; |
---|
| 70 | }; |
---|
| 71 | |
---|
| 72 | static struct { |
---|
| 73 | char *name; |
---|
| 74 | int type; |
---|
| 75 | } parameter_lookup[] = { |
---|
| 76 | { "display-device", DBUS_TYPE_STRING }, |
---|
| 77 | { "x11-display-device", DBUS_TYPE_STRING }, |
---|
| 78 | { "x11-display", DBUS_TYPE_STRING }, |
---|
| 79 | { "remote-host-name", DBUS_TYPE_STRING }, |
---|
| 80 | { "session-type", DBUS_TYPE_STRING }, |
---|
| 81 | { "is-local", DBUS_TYPE_BOOLEAN }, |
---|
| 82 | { "unix-user", DBUS_TYPE_INT32 }, |
---|
| 83 | }; |
---|
| 84 | |
---|
| 85 | static int |
---|
| 86 | lookup_parameter_type (const char *name) |
---|
| 87 | { |
---|
| 88 | int i; |
---|
| 89 | int type; |
---|
| 90 | |
---|
| 91 | type = DBUS_TYPE_INVALID; |
---|
| 92 | |
---|
| 93 | for (i = 0; i < N_ELEMENTS (parameter_lookup); i++) { |
---|
| 94 | if (strcmp (name, parameter_lookup[i].name) == 0) { |
---|
| 95 | type = parameter_lookup[i].type; |
---|
| 96 | break; |
---|
| 97 | } |
---|
| 98 | } |
---|
| 99 | |
---|
| 100 | return type; |
---|
| 101 | } |
---|
| 102 | |
---|
| 103 | static dbus_bool_t |
---|
| 104 | add_param_basic (DBusMessageIter *iter_array, |
---|
| 105 | const char *name, |
---|
| 106 | int type, |
---|
| 107 | const void *value) |
---|
| 108 | { |
---|
| 109 | DBusMessageIter iter_struct; |
---|
| 110 | DBusMessageIter iter_variant; |
---|
| 111 | const char *container_type; |
---|
| 112 | |
---|
| 113 | switch (type) { |
---|
| 114 | case DBUS_TYPE_STRING: |
---|
| 115 | container_type = DBUS_TYPE_STRING_AS_STRING; |
---|
| 116 | break; |
---|
| 117 | case DBUS_TYPE_BOOLEAN: |
---|
| 118 | container_type = DBUS_TYPE_BOOLEAN_AS_STRING; |
---|
| 119 | break; |
---|
| 120 | case DBUS_TYPE_INT32: |
---|
| 121 | container_type = DBUS_TYPE_INT32_AS_STRING; |
---|
| 122 | break; |
---|
| 123 | default: |
---|
| 124 | goto oom; |
---|
| 125 | break; |
---|
| 126 | } |
---|
| 127 | |
---|
| 128 | if (! dbus_message_iter_open_container (iter_array, |
---|
| 129 | DBUS_TYPE_STRUCT, |
---|
| 130 | NULL, |
---|
| 131 | &iter_struct)) { |
---|
| 132 | goto oom; |
---|
| 133 | } |
---|
| 134 | |
---|
| 135 | if (! dbus_message_iter_append_basic (&iter_struct, |
---|
| 136 | DBUS_TYPE_STRING, |
---|
| 137 | &name)) { |
---|
| 138 | goto oom; |
---|
| 139 | } |
---|
| 140 | |
---|
| 141 | if (! dbus_message_iter_open_container (&iter_struct, |
---|
| 142 | DBUS_TYPE_VARIANT, |
---|
| 143 | container_type, |
---|
| 144 | &iter_variant)) { |
---|
| 145 | goto oom; |
---|
| 146 | } |
---|
| 147 | |
---|
| 148 | if (! dbus_message_iter_append_basic (&iter_variant, |
---|
| 149 | type, |
---|
| 150 | value)) { |
---|
| 151 | goto oom; |
---|
| 152 | } |
---|
| 153 | |
---|
| 154 | if (! dbus_message_iter_close_container (&iter_struct, |
---|
| 155 | &iter_variant)) { |
---|
| 156 | goto oom; |
---|
| 157 | } |
---|
| 158 | |
---|
| 159 | if (! dbus_message_iter_close_container (iter_array, |
---|
| 160 | &iter_struct)) { |
---|
| 161 | goto oom; |
---|
| 162 | } |
---|
| 163 | |
---|
| 164 | return TRUE; |
---|
| 165 | oom: |
---|
| 166 | return FALSE; |
---|
| 167 | } |
---|
| 168 | |
---|
| 169 | /* Frees all resources allocated and disconnects from the system |
---|
| 170 | * message bus. |
---|
| 171 | */ |
---|
| 172 | static void |
---|
| 173 | _ck_connector_free (CkConnector *connector) |
---|
| 174 | { |
---|
| 175 | if (connector->connection != NULL) { |
---|
| 176 | /* it's a private connection so it's all good */ |
---|
| 177 | dbus_connection_close (connector->connection); |
---|
| 178 | } |
---|
| 179 | |
---|
| 180 | if (connector->cookie != NULL) { |
---|
| 181 | free (connector->cookie); |
---|
| 182 | } |
---|
| 183 | |
---|
| 184 | free (connector); |
---|
| 185 | } |
---|
| 186 | |
---|
| 187 | /** |
---|
| 188 | * Decrements the reference count of a CkConnector, disconnecting |
---|
| 189 | * from the bus and freeing the connector if the count reaches 0. |
---|
| 190 | * |
---|
| 191 | * @param connector the connector |
---|
| 192 | * @see ck_connector_ref |
---|
| 193 | */ |
---|
| 194 | void |
---|
| 195 | ck_connector_unref (CkConnector *connector) |
---|
| 196 | { |
---|
| 197 | _ck_return_if_fail (connector != NULL); |
---|
| 198 | |
---|
| 199 | /* Probably should use some kind of atomic op here */ |
---|
| 200 | connector->refcount -= 1; |
---|
| 201 | if (connector->refcount == 0) { |
---|
| 202 | _ck_connector_free (connector); |
---|
| 203 | } |
---|
| 204 | } |
---|
| 205 | |
---|
| 206 | /** |
---|
| 207 | * Increments the reference count of a CkConnector. |
---|
| 208 | * |
---|
| 209 | * @param connector the connector |
---|
| 210 | * @returns the connector |
---|
| 211 | * @see ck_connector_unref |
---|
| 212 | */ |
---|
| 213 | CkConnector * |
---|
| 214 | ck_connector_ref (CkConnector *connector) |
---|
| 215 | { |
---|
| 216 | _ck_return_val_if_fail (connector != NULL, NULL); |
---|
| 217 | |
---|
| 218 | /* Probably should use some kind of atomic op here */ |
---|
| 219 | connector->refcount += 1; |
---|
| 220 | |
---|
| 221 | return connector; |
---|
| 222 | } |
---|
| 223 | |
---|
| 224 | /** |
---|
| 225 | * Constructs a new Connector to communicate with the ConsoleKit |
---|
| 226 | * daemon. Returns #NULL if memory can't be allocated for the |
---|
| 227 | * object. |
---|
| 228 | * |
---|
| 229 | * @returns a new CkConnector, free with ck_connector_unref() |
---|
| 230 | */ |
---|
| 231 | CkConnector * |
---|
| 232 | ck_connector_new (void) |
---|
| 233 | { |
---|
| 234 | CkConnector *connector; |
---|
| 235 | |
---|
| 236 | connector = calloc (1, sizeof (CkConnector)); |
---|
| 237 | if (connector == NULL) { |
---|
| 238 | goto oom; |
---|
| 239 | } |
---|
| 240 | |
---|
| 241 | connector->refcount = 1; |
---|
| 242 | connector->connection = NULL; |
---|
| 243 | connector->cookie = NULL; |
---|
| 244 | connector->session_created = FALSE; |
---|
| 245 | oom: |
---|
| 246 | return connector; |
---|
| 247 | } |
---|
| 248 | |
---|
| 249 | /** |
---|
| 250 | * Connects to the D-Bus system bus daemon and issues the method call |
---|
| 251 | * OpenSession on the ConsoleKit manager interface. The |
---|
| 252 | * connection to the bus is private. |
---|
| 253 | * |
---|
| 254 | * Returns FALSE on OOM, if the system bus daemon is not running, if |
---|
| 255 | * the ConsoleKit daemon is not running or if the caller doesn't have |
---|
| 256 | * sufficient privileges. |
---|
| 257 | * |
---|
| 258 | * @returns #TRUE if the operation succeeds |
---|
| 259 | */ |
---|
| 260 | dbus_bool_t |
---|
| 261 | ck_connector_open_session (CkConnector *connector, |
---|
| 262 | DBusError *error) |
---|
| 263 | { |
---|
| 264 | DBusError local_error; |
---|
| 265 | DBusMessage *message; |
---|
| 266 | DBusMessage *reply; |
---|
| 267 | dbus_bool_t ret; |
---|
| 268 | char *cookie; |
---|
| 269 | |
---|
| 270 | _ck_return_val_if_fail (connector != NULL, FALSE); |
---|
| 271 | _ck_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), FALSE); |
---|
| 272 | |
---|
| 273 | reply = NULL; |
---|
| 274 | message = NULL; |
---|
| 275 | ret = FALSE; |
---|
| 276 | |
---|
| 277 | dbus_error_init (&local_error); |
---|
| 278 | connector->connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &local_error); |
---|
| 279 | if (connector->connection == NULL) { |
---|
| 280 | if (dbus_error_is_set (&local_error)) { |
---|
| 281 | dbus_set_error (error, |
---|
| 282 | CK_CONNECTOR_ERROR, |
---|
| 283 | "Unable to open session: %s", |
---|
| 284 | local_error.message); |
---|
| 285 | dbus_error_free (&local_error); |
---|
| 286 | } |
---|
| 287 | |
---|
| 288 | goto out; |
---|
| 289 | } |
---|
| 290 | |
---|
| 291 | dbus_connection_set_exit_on_disconnect (connector->connection, FALSE); |
---|
| 292 | |
---|
| 293 | message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", |
---|
| 294 | "/org/freedesktop/ConsoleKit/Manager", |
---|
| 295 | "org.freedesktop.ConsoleKit.Manager", |
---|
| 296 | "OpenSession"); |
---|
| 297 | if (message == NULL) { |
---|
| 298 | goto out; |
---|
| 299 | } |
---|
| 300 | |
---|
| 301 | dbus_error_init (&local_error); |
---|
| 302 | reply = dbus_connection_send_with_reply_and_block (connector->connection, |
---|
| 303 | message, |
---|
| 304 | -1, |
---|
| 305 | &local_error); |
---|
| 306 | if (reply == NULL) { |
---|
| 307 | if (dbus_error_is_set (&local_error)) { |
---|
| 308 | dbus_set_error (error, |
---|
| 309 | CK_CONNECTOR_ERROR, |
---|
| 310 | "Unable to open session: %s", |
---|
| 311 | local_error.message); |
---|
| 312 | dbus_error_free (&local_error); |
---|
| 313 | goto out; |
---|
| 314 | } |
---|
| 315 | } |
---|
| 316 | |
---|
| 317 | dbus_error_init (&local_error); |
---|
| 318 | if (! dbus_message_get_args (reply, |
---|
| 319 | &local_error, |
---|
| 320 | DBUS_TYPE_STRING, &cookie, |
---|
| 321 | DBUS_TYPE_INVALID)) { |
---|
| 322 | if (dbus_error_is_set (&local_error)) { |
---|
| 323 | dbus_set_error (error, |
---|
| 324 | CK_CONNECTOR_ERROR, |
---|
| 325 | "Unable to open session: %s", |
---|
| 326 | local_error.message); |
---|
| 327 | dbus_error_free (&local_error); |
---|
| 328 | goto out; |
---|
| 329 | } |
---|
| 330 | } |
---|
| 331 | |
---|
| 332 | connector->cookie = strdup (cookie); |
---|
| 333 | if (connector->cookie == NULL) { |
---|
| 334 | goto out; |
---|
| 335 | } |
---|
| 336 | |
---|
| 337 | connector->session_created = TRUE; |
---|
| 338 | ret = TRUE; |
---|
| 339 | |
---|
| 340 | out: |
---|
| 341 | if (reply != NULL) { |
---|
| 342 | dbus_message_unref (reply); |
---|
| 343 | } |
---|
| 344 | |
---|
| 345 | if (message != NULL) { |
---|
| 346 | dbus_message_unref (message); |
---|
| 347 | } |
---|
| 348 | |
---|
| 349 | return ret; |
---|
| 350 | } |
---|
| 351 | |
---|
| 352 | static dbus_bool_t |
---|
| 353 | ck_connector_open_session_with_parameters_valist (CkConnector *connector, |
---|
| 354 | DBusError *error, |
---|
| 355 | const char *first_parameter_name, |
---|
| 356 | va_list var_args) |
---|
| 357 | { |
---|
| 358 | DBusError local_error; |
---|
| 359 | DBusMessage *message; |
---|
| 360 | DBusMessage *reply; |
---|
| 361 | DBusMessageIter iter; |
---|
| 362 | DBusMessageIter iter_array; |
---|
| 363 | dbus_bool_t ret; |
---|
| 364 | char *cookie; |
---|
| 365 | const char *name; |
---|
| 366 | |
---|
| 367 | _ck_return_val_if_fail (connector != NULL, FALSE); |
---|
| 368 | |
---|
| 369 | reply = NULL; |
---|
| 370 | message = NULL; |
---|
| 371 | ret = FALSE; |
---|
| 372 | |
---|
| 373 | dbus_error_init (&local_error); |
---|
| 374 | connector->connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &local_error); |
---|
| 375 | if (connector->connection == NULL) { |
---|
| 376 | if (dbus_error_is_set (&local_error)) { |
---|
| 377 | dbus_set_error (error, |
---|
| 378 | CK_CONNECTOR_ERROR, |
---|
| 379 | "Unable to open session: %s", |
---|
| 380 | local_error.message); |
---|
| 381 | dbus_error_free (&local_error); |
---|
| 382 | } |
---|
| 383 | goto out; |
---|
| 384 | } |
---|
| 385 | |
---|
| 386 | dbus_connection_set_exit_on_disconnect (connector->connection, FALSE); |
---|
| 387 | |
---|
| 388 | message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", |
---|
| 389 | "/org/freedesktop/ConsoleKit/Manager", |
---|
| 390 | "org.freedesktop.ConsoleKit.Manager", |
---|
| 391 | "OpenSessionWithParameters"); |
---|
| 392 | if (message == NULL) { |
---|
| 393 | goto out; |
---|
| 394 | } |
---|
| 395 | |
---|
| 396 | dbus_message_iter_init_append (message, &iter); |
---|
| 397 | if (! dbus_message_iter_open_container (&iter, |
---|
| 398 | DBUS_TYPE_ARRAY, |
---|
| 399 | "(sv)", |
---|
| 400 | &iter_array)) { |
---|
| 401 | goto out; |
---|
| 402 | } |
---|
| 403 | |
---|
| 404 | name = first_parameter_name; |
---|
| 405 | while (name != NULL) { |
---|
| 406 | int type; |
---|
| 407 | const void *value; |
---|
| 408 | dbus_bool_t res; |
---|
| 409 | |
---|
| 410 | type = lookup_parameter_type (name); |
---|
| 411 | value = va_arg (var_args, const void *); |
---|
| 412 | |
---|
| 413 | if (type == DBUS_TYPE_INVALID) { |
---|
| 414 | dbus_set_error (error, |
---|
| 415 | CK_CONNECTOR_ERROR, |
---|
| 416 | "Unknown parameter: %s", |
---|
| 417 | name); |
---|
| 418 | goto out; |
---|
| 419 | } |
---|
| 420 | |
---|
| 421 | res = add_param_basic (&iter_array, name, type, value); |
---|
| 422 | if (! res) { |
---|
| 423 | dbus_set_error (error, |
---|
| 424 | CK_CONNECTOR_ERROR, |
---|
| 425 | "Error adding parameter: %s", |
---|
| 426 | name); |
---|
| 427 | goto out; |
---|
| 428 | } |
---|
| 429 | |
---|
| 430 | name = va_arg (var_args, char *); |
---|
| 431 | } |
---|
| 432 | |
---|
| 433 | if (! dbus_message_iter_close_container (&iter, &iter_array)) { |
---|
| 434 | goto out; |
---|
| 435 | } |
---|
| 436 | |
---|
| 437 | dbus_error_init (&local_error); |
---|
| 438 | reply = dbus_connection_send_with_reply_and_block (connector->connection, |
---|
| 439 | message, |
---|
| 440 | -1, |
---|
| 441 | &local_error); |
---|
| 442 | if (reply == NULL) { |
---|
| 443 | if (dbus_error_is_set (&local_error)) { |
---|
| 444 | dbus_set_error (error, |
---|
| 445 | CK_CONNECTOR_ERROR, |
---|
| 446 | "Unable to open session: %s", |
---|
| 447 | local_error.message); |
---|
| 448 | dbus_error_free (&local_error); |
---|
| 449 | goto out; |
---|
| 450 | } |
---|
| 451 | } |
---|
| 452 | |
---|
| 453 | dbus_error_init (&local_error); |
---|
| 454 | if (! dbus_message_get_args (reply, |
---|
| 455 | &local_error, |
---|
| 456 | DBUS_TYPE_STRING, &cookie, |
---|
| 457 | DBUS_TYPE_INVALID)) { |
---|
| 458 | if (dbus_error_is_set (&local_error)) { |
---|
| 459 | dbus_set_error (error, |
---|
| 460 | CK_CONNECTOR_ERROR, |
---|
| 461 | "Unable to open session: %s", |
---|
| 462 | local_error.message); |
---|
| 463 | dbus_error_free (&local_error); |
---|
| 464 | goto out; |
---|
| 465 | } |
---|
| 466 | } |
---|
| 467 | |
---|
| 468 | connector->cookie = strdup (cookie); |
---|
| 469 | if (connector->cookie == NULL) { |
---|
| 470 | goto out; |
---|
| 471 | } |
---|
| 472 | |
---|
| 473 | connector->session_created = TRUE; |
---|
| 474 | ret = TRUE; |
---|
| 475 | |
---|
| 476 | out: |
---|
| 477 | if (reply != NULL) { |
---|
| 478 | dbus_message_unref (reply); |
---|
| 479 | } |
---|
| 480 | |
---|
| 481 | if (message != NULL) { |
---|
| 482 | dbus_message_unref (message); |
---|
| 483 | } |
---|
| 484 | |
---|
| 485 | return ret; |
---|
| 486 | } |
---|
| 487 | |
---|
| 488 | /** |
---|
| 489 | * Opens a new session with parameter from variable argument list. The |
---|
| 490 | * variable argument list should contain the name of each parameter |
---|
| 491 | * followed by the value to append. |
---|
| 492 | * For example: |
---|
| 493 | * |
---|
| 494 | * @code |
---|
| 495 | * |
---|
| 496 | * DBusError error; |
---|
| 497 | * dbus_int32_t v_INT32 = 500; |
---|
| 498 | * const char *v_STRING = "/dev/tty3"; |
---|
| 499 | * |
---|
| 500 | * dbus_error_init (&error); |
---|
| 501 | * ck_connector_open_session_with_parameters (connector, |
---|
| 502 | * &error, |
---|
| 503 | * "unix-user", &v_INT32, |
---|
| 504 | * "display-device", &v_STRING, |
---|
| 505 | * NULL); |
---|
| 506 | * @endcode |
---|
| 507 | * |
---|
| 508 | * @param error error output |
---|
| 509 | * @param first_parameter_name name of the first parameter |
---|
| 510 | * @param ... value of first parameter, list of additional name-value pairs |
---|
| 511 | * @returns #TRUE on success |
---|
| 512 | */ |
---|
| 513 | dbus_bool_t |
---|
| 514 | ck_connector_open_session_with_parameters (CkConnector *connector, |
---|
| 515 | DBusError *error, |
---|
| 516 | const char *first_parameter_name, |
---|
| 517 | ...) |
---|
| 518 | { |
---|
| 519 | va_list var_args; |
---|
| 520 | dbus_bool_t ret; |
---|
| 521 | |
---|
| 522 | _ck_return_val_if_fail (connector != NULL, FALSE); |
---|
| 523 | _ck_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), FALSE); |
---|
| 524 | |
---|
| 525 | va_start (var_args, first_parameter_name); |
---|
| 526 | ret = ck_connector_open_session_with_parameters_valist (connector, |
---|
| 527 | error, |
---|
| 528 | first_parameter_name, |
---|
| 529 | var_args); |
---|
| 530 | va_end (var_args); |
---|
| 531 | |
---|
| 532 | return ret; |
---|
| 533 | } |
---|
| 534 | |
---|
| 535 | /** |
---|
| 536 | * Connects to the D-Bus system bus daemon and issues the method call |
---|
| 537 | * OpenSessionWithParameters on the ConsoleKit manager interface. The |
---|
| 538 | * connection to the bus is private. |
---|
| 539 | * |
---|
| 540 | * The only parameter that is optional is x11_display - it may be set |
---|
| 541 | * to NULL if there is no X11 server associated with the session. |
---|
| 542 | * |
---|
| 543 | * Returns FALSE on OOM, if the system bus daemon is not running, if |
---|
| 544 | * the ConsoleKit daemon is not running or if the caller doesn't have |
---|
| 545 | * sufficient privileges. |
---|
| 546 | * |
---|
| 547 | * @param user UID for the user owning the session |
---|
| 548 | * @param display_device the tty device for the session |
---|
| 549 | * @param x11_display the value of the X11 DISPLAY for the session |
---|
| 550 | * @returns #TRUE if the operation succeeds |
---|
| 551 | */ |
---|
| 552 | dbus_bool_t |
---|
| 553 | ck_connector_open_session_for_user (CkConnector *connector, |
---|
| 554 | uid_t user, |
---|
| 555 | const char *display_device, |
---|
| 556 | const char *x11_display, |
---|
| 557 | DBusError *error) |
---|
| 558 | { |
---|
| 559 | dbus_bool_t ret; |
---|
| 560 | |
---|
| 561 | _ck_return_val_if_fail (connector != NULL, FALSE); |
---|
| 562 | _ck_return_val_if_fail (display_device != NULL, FALSE); |
---|
| 563 | _ck_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), FALSE); |
---|
| 564 | |
---|
| 565 | ret = ck_connector_open_session_with_parameters (connector, |
---|
| 566 | error, |
---|
| 567 | "display-device", &display_device, |
---|
| 568 | "x11-display", &x11_display, |
---|
| 569 | "unix-user", &user, |
---|
| 570 | NULL); |
---|
| 571 | return ret; |
---|
| 572 | } |
---|
| 573 | |
---|
| 574 | /** |
---|
| 575 | * Gets the cookie for the current open session. |
---|
| 576 | * Returns #NULL if no session is open. |
---|
| 577 | * |
---|
| 578 | * @returns a constant string with the cookie. |
---|
| 579 | */ |
---|
| 580 | const char * |
---|
| 581 | ck_connector_get_cookie (CkConnector *connector) |
---|
| 582 | { |
---|
| 583 | _ck_return_val_if_fail (connector != NULL, NULL); |
---|
| 584 | |
---|
| 585 | if (! connector->session_created) { |
---|
| 586 | return NULL; |
---|
| 587 | } else { |
---|
| 588 | return connector->cookie; |
---|
| 589 | } |
---|
| 590 | } |
---|
| 591 | |
---|
| 592 | /** |
---|
| 593 | * Issues the CloseSession method call on the ConsoleKit manager |
---|
| 594 | * interface. |
---|
| 595 | * |
---|
| 596 | * Returns FALSE on OOM, if the system bus daemon is not running, if |
---|
| 597 | * the ConsoleKit daemon is not running, if the caller doesn't have |
---|
| 598 | * sufficient privilege or if a session isn't open. |
---|
| 599 | * |
---|
| 600 | * @returns #TRUE if the operation succeeds |
---|
| 601 | */ |
---|
| 602 | dbus_bool_t |
---|
| 603 | ck_connector_close_session (CkConnector *connector, |
---|
| 604 | DBusError *error) |
---|
| 605 | { |
---|
| 606 | DBusError local_error; |
---|
| 607 | DBusMessage *message; |
---|
| 608 | DBusMessage *reply; |
---|
| 609 | dbus_bool_t ret; |
---|
| 610 | dbus_bool_t session_closed; |
---|
| 611 | |
---|
| 612 | _ck_return_val_if_fail (connector != NULL, FALSE); |
---|
| 613 | _ck_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), FALSE); |
---|
| 614 | |
---|
| 615 | reply = NULL; |
---|
| 616 | message = NULL; |
---|
| 617 | ret = FALSE; |
---|
| 618 | |
---|
| 619 | if (!connector->session_created || connector->cookie == NULL) { |
---|
| 620 | dbus_set_error (error, |
---|
| 621 | CK_CONNECTOR_ERROR, |
---|
| 622 | "Unable to close session: %s", |
---|
| 623 | "no session open"); |
---|
| 624 | goto out; |
---|
| 625 | } |
---|
| 626 | |
---|
| 627 | dbus_error_init (&local_error); |
---|
| 628 | message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", |
---|
| 629 | "/org/freedesktop/ConsoleKit/Manager", |
---|
| 630 | "org.freedesktop.ConsoleKit.Manager", |
---|
| 631 | "CloseSession"); |
---|
| 632 | if (message == NULL) { |
---|
| 633 | goto out; |
---|
| 634 | } |
---|
| 635 | |
---|
| 636 | if (! dbus_message_append_args (message, |
---|
| 637 | DBUS_TYPE_STRING, &(connector->cookie), |
---|
| 638 | DBUS_TYPE_INVALID)) { |
---|
| 639 | goto out; |
---|
| 640 | } |
---|
| 641 | |
---|
| 642 | dbus_error_init (&local_error); |
---|
| 643 | reply = dbus_connection_send_with_reply_and_block (connector->connection, |
---|
| 644 | message, |
---|
| 645 | -1, |
---|
| 646 | &local_error); |
---|
| 647 | if (reply == NULL) { |
---|
| 648 | if (dbus_error_is_set (&local_error)) { |
---|
| 649 | dbus_set_error (error, |
---|
| 650 | CK_CONNECTOR_ERROR, |
---|
| 651 | "Unable to close session: %s", |
---|
| 652 | local_error.message); |
---|
| 653 | dbus_error_free (&local_error); |
---|
| 654 | goto out; |
---|
| 655 | } |
---|
| 656 | } |
---|
| 657 | |
---|
| 658 | dbus_error_init (&local_error); |
---|
| 659 | if (! dbus_message_get_args (reply, |
---|
| 660 | &local_error, |
---|
| 661 | DBUS_TYPE_BOOLEAN, &session_closed, |
---|
| 662 | DBUS_TYPE_INVALID)) { |
---|
| 663 | if (dbus_error_is_set (&local_error)) { |
---|
| 664 | dbus_set_error (error, |
---|
| 665 | CK_CONNECTOR_ERROR, |
---|
| 666 | "Unable to close session: %s", |
---|
| 667 | local_error.message); |
---|
| 668 | dbus_error_free (&local_error); |
---|
| 669 | goto out; |
---|
| 670 | } |
---|
| 671 | } |
---|
| 672 | |
---|
| 673 | if (! session_closed) { |
---|
| 674 | goto out; |
---|
| 675 | } |
---|
| 676 | |
---|
| 677 | connector->session_created = FALSE; |
---|
| 678 | ret = TRUE; |
---|
| 679 | |
---|
| 680 | out: |
---|
| 681 | if (reply != NULL) { |
---|
| 682 | dbus_message_unref (reply); |
---|
| 683 | } |
---|
| 684 | |
---|
| 685 | if (message != NULL) { |
---|
| 686 | dbus_message_unref (message); |
---|
| 687 | } |
---|
| 688 | |
---|
| 689 | return ret; |
---|
| 690 | |
---|
| 691 | } |
---|